Compare commits

..
4 Commits
Author SHA1 Message Date
alexandClaude Sonnet 5 168d6a71bd Fix esp32 wait-timing race, rename wc_api.lib, keyboard: Enter-to-advance
esp32.c: two-phase esp_wait_busy() so a stale non-BUSY status right after
esp_cmd() isn't mistaken for completion (fixed a real TRACK_PLAY/0x88 race
on heavier XM files); added single-phase esp_wait_not_busy() for
esp_send_dma()'s per-chunk wait, which never actually sets BUSY and was
timing out on every chunk under the two-phase version.

vgm_wc_api.lib renamed to wc_api.lib (build.bat updated to match).

Keyboard: tried replacing wc_key_esc/pgup/pgdn/space with a raw PS/2-FIFO
reader (matching how VGMPLAY.WMF's own player reads keys) so Enter could
also advance to the next file. Reverted after two confirmed hardware
regressions (esp32 transfers failing with ESP_ERR_INV_XM, and the keyboard
going unresponsive once WC's own PS/2 scanning was disabled to stop it
competing with the raw reads) - VGMPLAY's approach relies on a full custom
interrupt handler xmplay has no equivalent need for. Back to the simple
wc_key_*() wrappers, plus wc_key_enter() so Enter now advances too, and
wc_key_wait_release() (called after wc_gedpl()) to debounce the Enter/F3
that launched the plugin itself.

Also: About window now centers dynamically for all three WC text modes
(90x36/80x25/80x30) instead of a fixed position, and matches the main
window's color scheme.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-07 12:40:36 +03:00
alexandClaude Sonnet 5 ecf52d60c8 docs: README + ВНИМАНИЕ - конфликт со стандартным ftview по .XM/.XMZ
Стандартный ftview сам регистрируется на .XM/.XMZ - те же расширения,
что и xmplay. Таблица "расширение -> плагин" в WC статическая, так что
при совместной установке они конфликтуют. Нужно использовать
переработанную версию ftview (расширения убраны):
https://git.alexkorochinskiy.ru/alex/ftview.git

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-07 12:33:12 +03:00
alex a279a0eed3 Update sources, rebuild artifacts, add .gitignore 2026-08-31 21:26:25 +03:00
alexandClaude Sonnet 5 ee64fb85a9 Fix esp32 detection, add colored caption, live stats, single-loop playback
- Fix state_esp init bug: crt0.s never runs GSINIT and hex2bin fills
  unbacked memory with 0xFF (not 0), so a plain zero-init global always
  read 0xFF on load; give it a real 0xFF sentinel initializer instead.
- Vendor demyanenko-d/VGMPLAY.WMF's wc_api library (SDCC 4.6.0 +
  --sdcccall 1) instead of hand-rolled PRSRW/PRIAT wrappers, which
  corrupted esp32 file loading in three different shapes; colored "File:"
  caption now works.
- Trim shared-file footprint: vendor only the esp32.c functions actually
  used, drop unused sdklib.h/sdk.lib linkage.
- Re-enable periodic live stats (Pattern/Row/BPM/Time/progress bar).
- Limit playback to one loop via TRACK_SET_PARAMS/MAX_LOOP_COUNT, and
  auto-advance to the next file when a track finishes on its own
  (detected via a PLAYING->STOPPED ESP_REG_TRACK_STATUS transition).
- Pin the Z80 clock to 14MHz for the whole plugin lifetime so esp32 SPI
  wait-loop timeouts (raw iteration counts, not real time) don't depend
  on whatever turbo setting was active before the plugin started.
- Pad TRACK_INIT's timeout well past the firmware's 5s song-length
  measurement cap (XM_MEASURE_MAX_US).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-30 21:40:24 +03:00
25 changed files with 6107 additions and 3706 deletions
+22
View File
@@ -0,0 +1,22 @@
# Build output (SDCC/Z80 toolchain — regenerated by build.bat)
obj/
bin/
build/
# SDCC-generated files if they ever end up outside obj/
*.rel
*.lst
*.map
*.noi
*.sym
*.lk
*.ihx
*.adb
*.cdb
*.omf
# Editor/OS cruft
.vscode/
*.swp
Thumbs.db
.DS_Store
+76
View File
@@ -0,0 +1,76 @@
# XM Player
Плагин для Wild Commander (ZX Evolution / TS-Conf), проигрывающий XM, XMZ
(запакованный gzip'ом XM) и S3M модули через ESP32-сопроцессор платы. Z80
только передаёт файл на ESP32 и отображает окно со статусом; сам разбор
модуля и синтез звука выполняет прошивка ESP32.
> ⚠️ **Несовместим со стандартным ftview.** Оригинальный (стандартный)
> плагин `ftview` сам регистрируется на расширения `.XM` и `.XMZ` — ровно
> те же, что и у этого плагина. У Wild Commander таблица "расширение →
> плагин" статическая, зашита в заголовок при сборке, и если файл поставить
> вместе со стандартным `ftview`, они будут конфликтовать за одни и те же
> расширения. Используйте переработанную версию `ftview` (расширения `.XM`
> и `.XMZ` из неё убраны, воспроизведение вынесено в этот плагин) —
> она лежит отдельным репозиторием: https://git.alexkorochinskiy.ru/alex/ftview.git
## Требования
- ZX Evolution / TS-Conf с прошитым ESP32-сопроцессором
- Wild Commander (заголовок плагина версии 10+, есть в текущих сборках)
- переработанная версия `ftview` (см. предупреждение выше), а не стандартная
## Возможности
- Проигрывание `.XM`, `.XMZ`, `.S3M`
- Окно с живым статусом: имя файла, статус загрузки/воспроизведения,
паттерн, строка, BPM, прошедшее/общее время, прогресс-бар
- Ошибки выводятся прямо в строке статуса (с кодом ошибки ESP32, например
`Playback error (0x90)`), без отдельного всплывающего окна
- Автоматический переход к следующему файлу по окончании трека
- Параметр `stoponerror` в ini — остановка на ошибке вместо автоперехода,
удобно, чтобы найти, какой именно файл в подборке вызывает проблему
## Управление
| Клавиша | Действие |
|--------------|----------------------------------------------|
| PgDn, Enter | Следующий файл |
| PgUp | Предыдущий файл |
| Esc | Остановить воспроизведение и выйти |
| Space | Выйти, не останавливая текущее воспроизведение |
## Установка
Скопировать `xmplay.wmf` в каталог плагинов Wild Commander. Плагин сам
регистрируется на расширения `.XM`, `.XMZ` и `.S3M`.
Чтобы при ошибке воспроизведения плагин останавливался, а не переходил
сразу к следующему файлу, добавить в `wc.ini`:
```
XMPLAY.WMF -stoponerror=1
```
(`0` или отсутствие параметра — поведение по умолчанию: автопереход при ошибке.)
## Сборка
Нужен [SDCC](http://sdcc.sourceforge.net/) версии 4.6.0 (зафиксирована в
`build.bat`) и `hex2bin` — оба есть в тулчейне SDK ZX Evolution.
```
build.bat
```
Результат — `xmplay.wmf` в корне проекта.
## Благодарности
Собран на основе `wc_api.lib` из `demyanenko-d/VGMPLAY.WMF` — используется
для доступа к API Wild Commander (окна, вывод текста, клавиатура, ini-параметры).
## Статус
Проверено на реальном железе: воспроизведение, живая статистика,
прогресс-бар, обработка ошибок и управление с клавиатуры.
BIN
View File
Binary file not shown.
+2 -2
View File
@@ -2,7 +2,7 @@ REM NOTE: xmplay pins its OWN SDCC version here, independent of the rest of
REM ft812sdk (which stays on 4.0.0 for ABI reasons - see project memory on
REM the earlier shared-lib ABI mismatch incident). 4.6.0 is needed here
REM specifically for --sdcccall 1, required to link demyanenko-d/
REM VGMPLAY.WMF's wc_api library (vgm_wc_api.lib) - our own hand-rolled
REM VGMPLAY.WMF's wc_api library (wc_api.lib) - our own hand-rolled
REM PRSRW+PRIAT implementations corrupted esp32 file loading in three
REM different shapes and were abandoned in favor of their tested code.
set SDCC=E:\SDCC\4.6.0
@@ -14,7 +14,7 @@ del /q /s obj >nul
sdasz80 -o obj/crt0.rel src/crt0.s
if errorlevel 1 pause & exit
sdcc -Isrc -I../lib/sdk -I../../../esp32/src/main -mz80 --sdcccall 1 --std-sdcc11 --opt-code-speed --no-std-crt0 obj/crt0.rel --code-loc 0x8003 --data-loc 0xA800 src/main.c vgm_wc_api.lib -o obj/out.hex
sdcc -Isrc -I../lib/sdk -I../../../esp32/src/main -mz80 --sdcccall 1 --std-sdcc11 --opt-code-speed --no-std-crt0 obj/crt0.rel --code-loc 0x8003 --data-loc 0xA800 src/main.c wc_api.lib -o obj/out.hex
if errorlevel 1 pause & exit
if exist obj/out.hex hex2bin obj/out.hex >nul
+21 -26
View File
@@ -74,7 +74,7 @@ _hdr:
.db #0x4d ; 77 'M'
.db #0x44 ; 68 'D'
.db #0x4c ; 76 'L'
.db #0x07 ; 7
.db #0x0a ; 10
.db 0x00
.db #0x01 ; 1
.db #0x00 ; 0
@@ -204,12 +204,7 @@ _hdr:
.db 0x00
.db 0x00
.byte #0xff, #0xff, #0xff, #0xff ; 4294967295
.ascii "XM Player"
.db 0x00
.db 0x00
.db 0x00
.db 0x00
.db 0x00
.ascii "XM Player v0.1"
.db 0x00
.db 0x00
.db 0x00
@@ -291,25 +286,25 @@ _hdr:
.db 0x00
.db 0x00
.db 0x00
.db 0x00
.db 0x00
.db 0x00
.db 0x00
.db 0x00
.db 0x00
.db 0x00
.db 0x00
.db 0x00
.db 0x00
.db 0x00
.db 0x00
.db 0x00
.db 0x00
.db 0x00
.db 0x00
.db 0x00
.db 0x00
.db 0x00
.db #0x12 ; 18
.db #0x01 ; 1
.db #0x73 ; 115 's'
.db #0x74 ; 116 't'
.db #0x6f ; 111 'o'
.db #0x70 ; 112 'p'
.db #0x6f ; 111 'o'
.db #0x6e ; 110 'n'
.db #0x65 ; 101 'e'
.db #0x72 ; 114 'r'
.db #0x72 ; 114 'r'
.db #0x6f ; 111 'o'
.db #0x72 ; 114 'r'
.db #0x02 ; 2
.db #0x30 ; 48 '0'
.db #0x00 ; 0
.db #0x31 ; 49 '1'
.db #0x00 ; 0
.db #0x00 ; 0
.db 0x00
.db 0x00
.db 0x00
BIN
View File
Binary file not shown.
+3 -3
View File
@@ -1,12 +1,12 @@
:200200000000000000000000000000000000000057696C64436F6D6D616E6465724D444CDB
:2002200007000100001D000000000000000000000000000000000000000000000000000099
:200220000A000100001D000000000000000000000000000000000000000000000000000096
:20024000584D20584D5A53334D000000000000000000000000000000000000000000000007
:2002600000000000000000000000000000000000000000000000000000000000000000007E
:2002800000000000000000000000000000000000000000000000000000000000000000005E
:2002A00000FFFFFFFF584D20506C6179657200000000000000000000000000000000000010
:2002A00000FFFFFFFF584D20506C617965722076302E3100000000000000000000000000EB
:2002C00000000000000300000000000000000000000000000000000000000000000000001B
:2002E0000000000000000000000000000000000000000000000000000000000000000000FE
:200300000000000000000000000000000000000000000000000000000000000000000000DD
:2003000000000000120173746F706F6E6572726F720230003100000000000000000000009A
:200320000000000000000000000000000000000000000000000000000000000000000000BD
:2003400000000000000000000000000000000000000000000000000000000000000000009D
:2003600000000000000000000000000000000000000000000000000000000000000000007D
+338 -343
View File
@@ -74,7 +74,7 @@
0000001D 4D 74 .db #0x4d ; 77 'M'
0000001E 44 75 .db #0x44 ; 68 'D'
0000001F 4C 76 .db #0x4c ; 76 'L'
00000020 07 77 .db #0x07 ; 7
00000020 0A 77 .db #0x0a ; 10
00000021 00 78 .db 0x00
00000022 01 79 .db #0x01 ; 1
00000023 00 80 .db #0x00 ; 0
@@ -204,345 +204,340 @@
0000009F 00 204 .db 0x00
000000A0 00 205 .db 0x00
000000A1 FF FF FF FF 206 .byte #0xff, #0xff, #0xff, #0xff ; 4294967295
000000A5 58 4D 20 50 6C 61 79 207 .ascii "XM Player"
65 72
000000AE 00 208 .db 0x00
000000AF 00 209 .db 0x00
000000B0 00 210 .db 0x00
000000B1 00 211 .db 0x00
000000B2 00 212 .db 0x00
000000B3 00 213 .db 0x00
000000B4 00 214 .db 0x00
000000B5 00 215 .db 0x00
000000B6 00 216 .db 0x00
000000B7 00 217 .db 0x00
000000B8 00 218 .db 0x00
000000B9 00 219 .db 0x00
000000BA 00 220 .db 0x00
000000BB 00 221 .db 0x00
000000BC 00 222 .db 0x00
000000BD 00 223 .db 0x00
000000BE 00 224 .db 0x00
000000BF 00 225 .db 0x00
000000C0 00 226 .db 0x00
000000C1 00 227 .db 0x00
000000C2 00 228 .db 0x00
000000C3 00 229 .db 0x00
000000C4 00 230 .db 0x00
000000C5 03 231 .db #0x03 ; 3
000000C6 00 232 .db 0x00
000000C7 00 233 .db 0x00
000000C8 00 234 .db 0x00
000000C9 00 235 .db 0x00
000000CA 00 236 .db 0x00
000000CB 00 237 .db 0x00
000000CC 00 238 .db 0x00
000000CD 00 239 .db 0x00
000000CE 00 240 .db 0x00
000000CF 00 241 .db 0x00
000000D0 00 242 .db 0x00
000000D1 00 243 .db 0x00
000000D2 00 244 .db 0x00
000000D3 00 245 .db 0x00
000000D4 00 246 .db 0x00
000000D5 00 247 .db 0x00
000000D6 00 248 .db 0x00
000000D7 00 249 .db 0x00
000000D8 00 250 .db 0x00
000000D9 00 251 .db 0x00
000000DA 00 252 .db 0x00
000000DB 00 253 .db 0x00
000000DC 00 254 .db 0x00
000000DD 00 255 .db 0x00
000000DE 00 256 .db 0x00
000000DF 00 257 .db 0x00
000000E0 00 258 .db 0x00
000000E1 00 259 .db 0x00
000000E2 00 260 .db 0x00
000000E3 00 261 .db 0x00
000000E4 00 262 .db 0x00
000000E5 00 263 .db 0x00
000000E6 00 264 .db 0x00
000000E7 00 265 .db 0x00
000000E8 00 266 .db 0x00
000000E9 00 267 .db 0x00
000000EA 00 268 .db 0x00
000000EB 00 269 .db 0x00
000000EC 00 270 .db 0x00
000000ED 00 271 .db 0x00
000000EE 00 272 .db 0x00
000000EF 00 273 .db 0x00
000000F0 00 274 .db 0x00
000000F1 00 275 .db 0x00
000000F2 00 276 .db 0x00
000000F3 00 277 .db 0x00
000000F4 00 278 .db 0x00
000000F5 00 279 .db 0x00
000000F6 00 280 .db 0x00
000000F7 00 281 .db 0x00
000000F8 00 282 .db 0x00
000000F9 00 283 .db 0x00
000000FA 00 284 .db 0x00
000000FB 00 285 .db 0x00
000000FC 00 286 .db 0x00
000000FD 00 287 .db 0x00
000000FE 00 288 .db 0x00
000000FF 00 289 .db 0x00
00000100 00 290 .db 0x00
00000101 00 291 .db 0x00
00000102 00 292 .db 0x00
00000103 00 293 .db 0x00
00000104 00 294 .db 0x00
00000105 00 295 .db 0x00
00000106 00 296 .db 0x00
00000107 00 297 .db 0x00
00000108 00 298 .db 0x00
00000109 00 299 .db 0x00
0000010A 00 300 .db 0x00
0000010B 00 301 .db 0x00
0000010C 00 302 .db 0x00
0000010D 00 303 .db 0x00
0000010E 00 304 .db 0x00
0000010F 00 305 .db 0x00
00000110 00 306 .db 0x00
00000111 00 307 .db 0x00
00000112 00 308 .db 0x00
00000113 00 309 .db 0x00
00000114 00 310 .db 0x00
00000115 00 311 .db 0x00
00000116 00 312 .db 0x00
00000117 00 313 .db 0x00
00000118 00 314 .db 0x00
00000119 00 315 .db 0x00
0000011A 00 316 .db 0x00
0000011B 00 317 .db 0x00
0000011C 00 318 .db 0x00
0000011D 00 319 .db 0x00
0000011E 00 320 .db 0x00
0000011F 00 321 .db 0x00
00000120 00 322 .db 0x00
00000121 00 323 .db 0x00
00000122 00 324 .db 0x00
00000123 00 325 .db 0x00
00000124 00 326 .db 0x00
00000125 00 327 .db 0x00
00000126 00 328 .db 0x00
00000127 00 329 .db 0x00
00000128 00 330 .db 0x00
00000129 00 331 .db 0x00
0000012A 00 332 .db 0x00
0000012B 00 333 .db 0x00
0000012C 00 334 .db 0x00
0000012D 00 335 .db 0x00
0000012E 00 336 .db 0x00
0000012F 00 337 .db 0x00
00000130 00 338 .db 0x00
00000131 00 339 .db 0x00
00000132 00 340 .db 0x00
00000133 00 341 .db 0x00
00000134 00 342 .db 0x00
00000135 00 343 .db 0x00
00000136 00 344 .db 0x00
00000137 00 345 .db 0x00
00000138 00 346 .db 0x00
00000139 00 347 .db 0x00
0000013A 00 348 .db 0x00
0000013B 00 349 .db 0x00
0000013C 00 350 .db 0x00
0000013D 00 351 .db 0x00
0000013E 00 352 .db 0x00
0000013F 00 353 .db 0x00
00000140 00 354 .db 0x00
00000141 00 355 .db 0x00
00000142 00 356 .db 0x00
00000143 00 357 .db 0x00
00000144 00 358 .db 0x00
00000145 00 359 .db 0x00
00000146 00 360 .db 0x00
00000147 00 361 .db 0x00
00000148 00 362 .db 0x00
00000149 00 363 .db 0x00
0000014A 00 364 .db 0x00
0000014B 00 365 .db 0x00
0000014C 00 366 .db 0x00
0000014D 00 367 .db 0x00
0000014E 00 368 .db 0x00
0000014F 00 369 .db 0x00
00000150 00 370 .db 0x00
00000151 00 371 .db 0x00
00000152 00 372 .db 0x00
00000153 00 373 .db 0x00
00000154 00 374 .db 0x00
00000155 00 375 .db 0x00
00000156 00 376 .db 0x00
00000157 00 377 .db 0x00
00000158 00 378 .db 0x00
00000159 00 379 .db 0x00
0000015A 00 380 .db 0x00
0000015B 00 381 .db 0x00
0000015C 00 382 .db 0x00
0000015D 00 383 .db 0x00
0000015E 00 384 .db 0x00
0000015F 00 385 .db 0x00
00000160 00 386 .db 0x00
00000161 00 387 .db 0x00
00000162 00 388 .db 0x00
00000163 00 389 .db 0x00
00000164 00 390 .db 0x00
00000165 00 391 .db 0x00
00000166 00 392 .db 0x00
00000167 00 393 .db 0x00
00000168 00 394 .db 0x00
00000169 00 395 .db 0x00
0000016A 00 396 .db 0x00
0000016B 00 397 .db 0x00
0000016C 00 398 .db 0x00
0000016D 00 399 .db 0x00
0000016E 00 400 .db 0x00
0000016F 00 401 .db 0x00
00000170 00 402 .db 0x00
00000171 00 403 .db 0x00
00000172 00 404 .db 0x00
00000173 00 405 .db 0x00
00000174 00 406 .db 0x00
00000175 00 407 .db 0x00
00000176 00 408 .db 0x00
00000177 00 409 .db 0x00
00000178 00 410 .db 0x00
00000179 00 411 .db 0x00
0000017A 00 412 .db 0x00
0000017B 00 413 .db 0x00
0000017C 00 414 .db 0x00
0000017D 00 415 .db 0x00
0000017E 00 416 .db 0x00
0000017F 00 417 .db 0x00
00000180 00 418 .db 0x00
00000181 00 419 .db 0x00
00000182 00 420 .db 0x00
00000183 00 421 .db 0x00
00000184 00 422 .db 0x00
00000185 00 423 .db 0x00
00000186 00 424 .db 0x00
00000187 00 425 .db 0x00
00000188 00 426 .db 0x00
00000189 00 427 .db 0x00
0000018A 00 428 .db 0x00
0000018B 00 429 .db 0x00
0000018C 00 430 .db 0x00
0000018D 00 431 .db 0x00
0000018E 00 432 .db 0x00
0000018F 00 433 .db 0x00
00000190 00 434 .db 0x00
00000191 00 435 .db 0x00
00000192 00 436 .db 0x00
00000193 00 437 .db 0x00
00000194 00 438 .db 0x00
00000195 00 439 .db 0x00
00000196 00 440 .db 0x00
00000197 00 441 .db 0x00
00000198 00 442 .db 0x00
00000199 00 443 .db 0x00
0000019A 00 444 .db 0x00
0000019B 00 445 .db 0x00
0000019C 00 446 .db 0x00
0000019D 00 447 .db 0x00
0000019E 00 448 .db 0x00
0000019F 00 449 .db 0x00
000001A0 00 450 .db 0x00
000001A1 00 451 .db 0x00
000001A2 00 452 .db 0x00
000001A3 00 453 .db 0x00
000001A4 00 454 .db 0x00
000001A5 00 455 .db 0x00
000001A6 00 456 .db 0x00
000001A7 00 457 .db 0x00
000001A8 00 458 .db 0x00
000001A9 00 459 .db 0x00
000001AA 00 460 .db 0x00
000001AB 00 461 .db 0x00
000001AC 00 462 .db 0x00
000001AD 00 463 .db 0x00
000001AE 00 464 .db 0x00
000001AF 00 465 .db 0x00
000001B0 00 466 .db 0x00
000001B1 00 467 .db 0x00
000001B2 00 468 .db 0x00
000001B3 00 469 .db 0x00
000001B4 00 470 .db 0x00
000001B5 00 471 .db 0x00
000001B6 00 472 .db 0x00
000001B7 00 473 .db 0x00
000001B8 00 474 .db 0x00
000001B9 00 475 .db 0x00
000001BA 00 476 .db 0x00
000001BB 00 477 .db 0x00
000001BC 00 478 .db 0x00
000001BD 00 479 .db 0x00
000001BE 00 480 .db 0x00
000001BF 00 481 .db 0x00
000001C0 00 482 .db 0x00
000001C1 00 483 .db 0x00
000001C2 00 484 .db 0x00
000001C3 00 485 .db 0x00
000001C4 00 486 .db 0x00
000001C5 00 487 .db 0x00
000001C6 00 488 .db 0x00
000001C7 00 489 .db 0x00
000001C8 00 490 .db 0x00
000001C9 00 491 .db 0x00
000001CA 00 492 .db 0x00
000001CB 00 493 .db 0x00
000001CC 00 494 .db 0x00
000001CD 00 495 .db 0x00
000001CE 00 496 .db 0x00
000001CF 00 497 .db 0x00
000001D0 00 498 .db 0x00
000001D1 00 499 .db 0x00
000001D2 00 500 .db 0x00
000001D3 00 501 .db 0x00
000001D4 00 502 .db 0x00
000001D5 00 503 .db 0x00
000001D6 00 504 .db 0x00
000001D7 00 505 .db 0x00
000001D8 00 506 .db 0x00
000001D9 00 507 .db 0x00
000001DA 00 508 .db 0x00
000001DB 00 509 .db 0x00
000001DC 00 510 .db 0x00
000001DD 00 511 .db 0x00
000001DE 00 512 .db 0x00
000001DF 00 513 .db 0x00
000001E0 00 514 .db 0x00
000001E1 00 515 .db 0x00
000001E2 00 516 .db 0x00
000001E3 00 517 .db 0x00
000001E4 00 518 .db 0x00
000001E5 00 519 .db 0x00
000001E6 00 520 .db 0x00
000001E7 00 521 .db 0x00
000001E8 00 522 .db 0x00
000001E9 00 523 .db 0x00
000001EA 00 524 .db 0x00
000001EB 00 525 .db 0x00
000001EC 00 526 .db 0x00
000001ED 00 527 .db 0x00
000001EE 00 528 .db 0x00
000001EF 00 529 .db 0x00
000001F0 00 530 .db 0x00
000001F1 00 531 .db 0x00
000001F2 00 532 .db 0x00
000001F3 00 533 .db 0x00
000001F4 00 534 .db 0x00
000001F5 00 535 .db 0x00
000001F6 00 536 .db 0x00
000001F7 00 537 .db 0x00
000001F8 00 538 .db 0x00
000001F9 00 539 .db 0x00
000001FA 00 540 .db 0x00
000001FB 00 541 .db 0x00
000001FC 00 542 .db 0x00
000001FD 00 543 .db 0x00
000001FE 00 544 .db 0x00
000001FF 00 545 .db 0x00
546 .area _INITIALIZER
547 .area _CABS (ABS)
000000A5 58 4D 20 50 6C 61 79 207 .ascii "XM Player v0.1"
65 72 20 76 30 2E 31
000000B3 00 208 .db 0x00
000000B4 00 209 .db 0x00
000000B5 00 210 .db 0x00
000000B6 00 211 .db 0x00
000000B7 00 212 .db 0x00
000000B8 00 213 .db 0x00
000000B9 00 214 .db 0x00
000000BA 00 215 .db 0x00
000000BB 00 216 .db 0x00
000000BC 00 217 .db 0x00
000000BD 00 218 .db 0x00
000000BE 00 219 .db 0x00
000000BF 00 220 .db 0x00
000000C0 00 221 .db 0x00
000000C1 00 222 .db 0x00
000000C2 00 223 .db 0x00
000000C3 00 224 .db 0x00
000000C4 00 225 .db 0x00
000000C5 03 226 .db #0x03 ; 3
000000C6 00 227 .db 0x00
000000C7 00 228 .db 0x00
000000C8 00 229 .db 0x00
000000C9 00 230 .db 0x00
000000CA 00 231 .db 0x00
000000CB 00 232 .db 0x00
000000CC 00 233 .db 0x00
000000CD 00 234 .db 0x00
000000CE 00 235 .db 0x00
000000CF 00 236 .db 0x00
000000D0 00 237 .db 0x00
000000D1 00 238 .db 0x00
000000D2 00 239 .db 0x00
000000D3 00 240 .db 0x00
000000D4 00 241 .db 0x00
000000D5 00 242 .db 0x00
000000D6 00 243 .db 0x00
000000D7 00 244 .db 0x00
000000D8 00 245 .db 0x00
000000D9 00 246 .db 0x00
000000DA 00 247 .db 0x00
000000DB 00 248 .db 0x00
000000DC 00 249 .db 0x00
000000DD 00 250 .db 0x00
000000DE 00 251 .db 0x00
000000DF 00 252 .db 0x00
000000E0 00 253 .db 0x00
000000E1 00 254 .db 0x00
000000E2 00 255 .db 0x00
000000E3 00 256 .db 0x00
000000E4 00 257 .db 0x00
000000E5 00 258 .db 0x00
000000E6 00 259 .db 0x00
000000E7 00 260 .db 0x00
000000E8 00 261 .db 0x00
000000E9 00 262 .db 0x00
000000EA 00 263 .db 0x00
000000EB 00 264 .db 0x00
000000EC 00 265 .db 0x00
000000ED 00 266 .db 0x00
000000EE 00 267 .db 0x00
000000EF 00 268 .db 0x00
000000F0 00 269 .db 0x00
000000F1 00 270 .db 0x00
000000F2 00 271 .db 0x00
000000F3 00 272 .db 0x00
000000F4 00 273 .db 0x00
000000F5 00 274 .db 0x00
000000F6 00 275 .db 0x00
000000F7 00 276 .db 0x00
000000F8 00 277 .db 0x00
000000F9 00 278 .db 0x00
000000FA 00 279 .db 0x00
000000FB 00 280 .db 0x00
000000FC 00 281 .db 0x00
000000FD 00 282 .db 0x00
000000FE 00 283 .db 0x00
000000FF 00 284 .db 0x00
00000100 00 285 .db 0x00
00000101 00 286 .db 0x00
00000102 00 287 .db 0x00
00000103 00 288 .db 0x00
00000104 12 289 .db #0x12 ; 18
00000105 01 290 .db #0x01 ; 1
00000106 73 291 .db #0x73 ; 115 's'
00000107 74 292 .db #0x74 ; 116 't'
00000108 6F 293 .db #0x6f ; 111 'o'
00000109 70 294 .db #0x70 ; 112 'p'
0000010A 6F 295 .db #0x6f ; 111 'o'
0000010B 6E 296 .db #0x6e ; 110 'n'
0000010C 65 297 .db #0x65 ; 101 'e'
0000010D 72 298 .db #0x72 ; 114 'r'
0000010E 72 299 .db #0x72 ; 114 'r'
0000010F 6F 300 .db #0x6f ; 111 'o'
00000110 72 301 .db #0x72 ; 114 'r'
00000111 02 302 .db #0x02 ; 2
00000112 30 303 .db #0x30 ; 48 '0'
00000113 00 304 .db #0x00 ; 0
00000114 31 305 .db #0x31 ; 49 '1'
00000115 00 306 .db #0x00 ; 0
00000116 00 307 .db #0x00 ; 0
00000117 00 308 .db 0x00
00000118 00 309 .db 0x00
00000119 00 310 .db 0x00
0000011A 00 311 .db 0x00
0000011B 00 312 .db 0x00
0000011C 00 313 .db 0x00
0000011D 00 314 .db 0x00
0000011E 00 315 .db 0x00
0000011F 00 316 .db 0x00
00000120 00 317 .db 0x00
00000121 00 318 .db 0x00
00000122 00 319 .db 0x00
00000123 00 320 .db 0x00
00000124 00 321 .db 0x00
00000125 00 322 .db 0x00
00000126 00 323 .db 0x00
00000127 00 324 .db 0x00
00000128 00 325 .db 0x00
00000129 00 326 .db 0x00
0000012A 00 327 .db 0x00
0000012B 00 328 .db 0x00
0000012C 00 329 .db 0x00
0000012D 00 330 .db 0x00
0000012E 00 331 .db 0x00
0000012F 00 332 .db 0x00
00000130 00 333 .db 0x00
00000131 00 334 .db 0x00
00000132 00 335 .db 0x00
00000133 00 336 .db 0x00
00000134 00 337 .db 0x00
00000135 00 338 .db 0x00
00000136 00 339 .db 0x00
00000137 00 340 .db 0x00
00000138 00 341 .db 0x00
00000139 00 342 .db 0x00
0000013A 00 343 .db 0x00
0000013B 00 344 .db 0x00
0000013C 00 345 .db 0x00
0000013D 00 346 .db 0x00
0000013E 00 347 .db 0x00
0000013F 00 348 .db 0x00
00000140 00 349 .db 0x00
00000141 00 350 .db 0x00
00000142 00 351 .db 0x00
00000143 00 352 .db 0x00
00000144 00 353 .db 0x00
00000145 00 354 .db 0x00
00000146 00 355 .db 0x00
00000147 00 356 .db 0x00
00000148 00 357 .db 0x00
00000149 00 358 .db 0x00
0000014A 00 359 .db 0x00
0000014B 00 360 .db 0x00
0000014C 00 361 .db 0x00
0000014D 00 362 .db 0x00
0000014E 00 363 .db 0x00
0000014F 00 364 .db 0x00
00000150 00 365 .db 0x00
00000151 00 366 .db 0x00
00000152 00 367 .db 0x00
00000153 00 368 .db 0x00
00000154 00 369 .db 0x00
00000155 00 370 .db 0x00
00000156 00 371 .db 0x00
00000157 00 372 .db 0x00
00000158 00 373 .db 0x00
00000159 00 374 .db 0x00
0000015A 00 375 .db 0x00
0000015B 00 376 .db 0x00
0000015C 00 377 .db 0x00
0000015D 00 378 .db 0x00
0000015E 00 379 .db 0x00
0000015F 00 380 .db 0x00
00000160 00 381 .db 0x00
00000161 00 382 .db 0x00
00000162 00 383 .db 0x00
00000163 00 384 .db 0x00
00000164 00 385 .db 0x00
00000165 00 386 .db 0x00
00000166 00 387 .db 0x00
00000167 00 388 .db 0x00
00000168 00 389 .db 0x00
00000169 00 390 .db 0x00
0000016A 00 391 .db 0x00
0000016B 00 392 .db 0x00
0000016C 00 393 .db 0x00
0000016D 00 394 .db 0x00
0000016E 00 395 .db 0x00
0000016F 00 396 .db 0x00
00000170 00 397 .db 0x00
00000171 00 398 .db 0x00
00000172 00 399 .db 0x00
00000173 00 400 .db 0x00
00000174 00 401 .db 0x00
00000175 00 402 .db 0x00
00000176 00 403 .db 0x00
00000177 00 404 .db 0x00
00000178 00 405 .db 0x00
00000179 00 406 .db 0x00
0000017A 00 407 .db 0x00
0000017B 00 408 .db 0x00
0000017C 00 409 .db 0x00
0000017D 00 410 .db 0x00
0000017E 00 411 .db 0x00
0000017F 00 412 .db 0x00
00000180 00 413 .db 0x00
00000181 00 414 .db 0x00
00000182 00 415 .db 0x00
00000183 00 416 .db 0x00
00000184 00 417 .db 0x00
00000185 00 418 .db 0x00
00000186 00 419 .db 0x00
00000187 00 420 .db 0x00
00000188 00 421 .db 0x00
00000189 00 422 .db 0x00
0000018A 00 423 .db 0x00
0000018B 00 424 .db 0x00
0000018C 00 425 .db 0x00
0000018D 00 426 .db 0x00
0000018E 00 427 .db 0x00
0000018F 00 428 .db 0x00
00000190 00 429 .db 0x00
00000191 00 430 .db 0x00
00000192 00 431 .db 0x00
00000193 00 432 .db 0x00
00000194 00 433 .db 0x00
00000195 00 434 .db 0x00
00000196 00 435 .db 0x00
00000197 00 436 .db 0x00
00000198 00 437 .db 0x00
00000199 00 438 .db 0x00
0000019A 00 439 .db 0x00
0000019B 00 440 .db 0x00
0000019C 00 441 .db 0x00
0000019D 00 442 .db 0x00
0000019E 00 443 .db 0x00
0000019F 00 444 .db 0x00
000001A0 00 445 .db 0x00
000001A1 00 446 .db 0x00
000001A2 00 447 .db 0x00
000001A3 00 448 .db 0x00
000001A4 00 449 .db 0x00
000001A5 00 450 .db 0x00
000001A6 00 451 .db 0x00
000001A7 00 452 .db 0x00
000001A8 00 453 .db 0x00
000001A9 00 454 .db 0x00
000001AA 00 455 .db 0x00
000001AB 00 456 .db 0x00
000001AC 00 457 .db 0x00
000001AD 00 458 .db 0x00
000001AE 00 459 .db 0x00
000001AF 00 460 .db 0x00
000001B0 00 461 .db 0x00
000001B1 00 462 .db 0x00
000001B2 00 463 .db 0x00
000001B3 00 464 .db 0x00
000001B4 00 465 .db 0x00
000001B5 00 466 .db 0x00
000001B6 00 467 .db 0x00
000001B7 00 468 .db 0x00
000001B8 00 469 .db 0x00
000001B9 00 470 .db 0x00
000001BA 00 471 .db 0x00
000001BB 00 472 .db 0x00
000001BC 00 473 .db 0x00
000001BD 00 474 .db 0x00
000001BE 00 475 .db 0x00
000001BF 00 476 .db 0x00
000001C0 00 477 .db 0x00
000001C1 00 478 .db 0x00
000001C2 00 479 .db 0x00
000001C3 00 480 .db 0x00
000001C4 00 481 .db 0x00
000001C5 00 482 .db 0x00
000001C6 00 483 .db 0x00
000001C7 00 484 .db 0x00
000001C8 00 485 .db 0x00
000001C9 00 486 .db 0x00
000001CA 00 487 .db 0x00
000001CB 00 488 .db 0x00
000001CC 00 489 .db 0x00
000001CD 00 490 .db 0x00
000001CE 00 491 .db 0x00
000001CF 00 492 .db 0x00
000001D0 00 493 .db 0x00
000001D1 00 494 .db 0x00
000001D2 00 495 .db 0x00
000001D3 00 496 .db 0x00
000001D4 00 497 .db 0x00
000001D5 00 498 .db 0x00
000001D6 00 499 .db 0x00
000001D7 00 500 .db 0x00
000001D8 00 501 .db 0x00
000001D9 00 502 .db 0x00
000001DA 00 503 .db 0x00
000001DB 00 504 .db 0x00
000001DC 00 505 .db 0x00
000001DD 00 506 .db 0x00
000001DE 00 507 .db 0x00
000001DF 00 508 .db 0x00
000001E0 00 509 .db 0x00
000001E1 00 510 .db 0x00
000001E2 00 511 .db 0x00
000001E3 00 512 .db 0x00
000001E4 00 513 .db 0x00
000001E5 00 514 .db 0x00
000001E6 00 515 .db 0x00
000001E7 00 516 .db 0x00
000001E8 00 517 .db 0x00
000001E9 00 518 .db 0x00
000001EA 00 519 .db 0x00
000001EB 00 520 .db 0x00
000001EC 00 521 .db 0x00
000001ED 00 522 .db 0x00
000001EE 00 523 .db 0x00
000001EF 00 524 .db 0x00
000001F0 00 525 .db 0x00
000001F1 00 526 .db 0x00
000001F2 00 527 .db 0x00
000001F3 00 528 .db 0x00
000001F4 00 529 .db 0x00
000001F5 00 530 .db 0x00
000001F6 00 531 .db 0x00
000001F7 00 532 .db 0x00
000001F8 00 533 .db 0x00
000001F9 00 534 .db 0x00
000001FA 00 535 .db 0x00
000001FB 00 536 .db 0x00
000001FC 00 537 .db 0x00
000001FD 00 538 .db 0x00
000001FE 00 539 .db 0x00
000001FF 00 540 .db 0x00
541 .area _INITIALIZER
542 .area _CABS (ABS)
+5 -5
View File
@@ -18,7 +18,7 @@ T 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
R 00 00 00 00
T 0C 00 00 00 00 00 00 00 57 69 6C 64 43 6F 6D 6D
R 00 00 00 00
T 18 00 00 00 61 6E 64 65 72 4D 44 4C 07 00 01 00
T 18 00 00 00 61 6E 64 65 72 4D 44 4C 0A 00 01 00
R 00 00 00 00
T 24 00 00 00 00 1D 00 00 00 00 00 00 00 00 00 00
R 00 00 00 00
@@ -42,7 +42,7 @@ T 90 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
R 00 00 00 00
T 9C 00 00 00 00 00 00 00 00 FF FF FF FF 58 4D 20
R 00 00 00 00
T A8 00 00 00 50 6C 61 79 65 72 00 00 00 00 00 00
T A8 00 00 00 50 6C 61 79 65 72 20 76 30 2E 31 00
R 00 00 00 00
T B4 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
R 00 00 00 00
@@ -56,11 +56,11 @@ T E4 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
R 00 00 00 00
T F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
R 00 00 00 00
T FC 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
T FC 00 00 00 00 00 00 00 00 00 00 00 12 01 73 74
R 00 00 00 00
T 08 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00
T 08 01 00 00 6F 70 6F 6E 65 72 72 6F 72 02 30 00
R 00 00 00 00
T 14 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00
T 14 01 00 00 31 00 00 00 00 00 00 00 00 00 00 00
R 00 00 00 00
T 20 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00
R 00 00 00 00
+1224 -523
View File
File diff suppressed because it is too large Load Diff
BIN
View File
Binary file not shown.
+127 -90
View File
@@ -1,4 +1,4 @@
:20800300ED7B01B8C94F3E13D3773E01D357AFD357DB5779D357AFD3573E03D377C94F3EB8
:20800300ED7B00B8C94F3E13D3773E01D357AFD357DB5779D357AFD3573E03D377C94F3EB9
:2080230013D3773E02D35779D357DB57DB57DB574F3E03D37779C9DDE5DD210000DD39F556
:20804300F54F3E13D3773E02D35779D357DB57DB57DB574FDB575759DB57DD77FCAFDD77E5
:20806300FDDD77FEDD77FFDD7EFCDD77FEAFDD77FFDD77FCDD77FDDD6EFEDB57DD77FCAF95
@@ -7,93 +7,130 @@
:2080C300B72807DB571213C3C1803E03D377E133E9474D3E13D3773E01D35778D357DB5768
:2080E30079D3573E03D377C94F3E13D3773E01D35779D357DB57FD210200FD39FD7E00D3BA
:2081030057FD7E01D357FD7E02D357FD7E03D3573E03D377E1F1F1E93E13D3773E07D357CF
:20812300DB573E03D377C97D01AF1AED797C01AF1BED79FD210200FD39FD7E0001AF1CEDD2
:2081430079FD7E01FD4E02FD23CB39CB1F3D01AF26ED79FD7E023D01AF28ED793E13D377C0
:208163003E03D357DB57DB573E8201AF27ED793E27DBAF0738F93E03D377CD1B811160EABA
:20818300210000CDD881E1F1F133E93E13D3773E08D357DB573E03D377C9DDE5DD21000065
:2081A300DD394FDD5E04DD5605DD6E06DD66077BC6FF5F7ACEFF577DCEFF6F7CCEFF67B5EA
:2081C300B2B3280EE5C5D53E01CD2180D1C1E19120DDDDE1C97BC6FF5F7ACEFF577DCEFFC6
:2081E3006F7CCEFF67B5B2B3C8E5D53E01CD2180D1E1FE0228DFC9E5D53E03CDEB80FD2141
:208203000200FD39FD6E003E02CDD4803EE0CD088011204E210000CDD8813E0BCD21805F08
:208223001600E133E9AFCD0880CD8E81CD1B813E01C90100180A20052F00000000008F824F
:2082430099829A820100FFFF20052F00000000008F829982B0820100FFFF20052F000000E0
:2082630000008F829982D0828100190A280B4F0000000000EE82998203830100160A2405FC
:208283004F0000000000118399821A830E204572726F72212000000E0C014E6F20455350E7
:2082A300333220646574656374656421000E0C014F7574206F66206D656D6F727920286624
:2082C300696C6520746F6F2062696729000E0C01506C61796261636B206572726F722028A0
:2082E3006261642066696C653F29000E20584D2F584D5A2F53334D20506C6179657220007C
:208303000E0C01506C6179696E672E2E2E000E2041626F757420000E0C01584D20506C619B
:208323007965722076312E3000DDE5DD210000DD3921ECFF39F93EA2CD0880111027210013
:2083430000CDD8813EE4CD0880111027210000CDD8813A07B83D280A3A07B8D6022808C3C2
:208363006F833E08C371833E0CC371833E05F533ED5B03B82A05B8CDFA812131B8733E01B1
:20838300CD21803209B83A09B83D2804AFC33C85210C0039EB2103B8010400EDB0AFDD7710
:2083A300FCDD77FDDD77FEDD77FFDD7EFBDDB6FADDB6F9DDB6F8CAC984DD7EF9D610DD7E22
:2083C300FADE00DD7EFBDE00301121000039EB210C0039010400EDB0C3ED83DD36EC00DDF1
:2083E30036ED10AFDD77EEDD77EF21050039EB21000039010400EDB0DD7EF1C6FFDD7EF26F
:20840300CE01473E00CE005F3E00CE005748435ACB3BCB18CB19DD71F779F5332101A8CD46
:208423000D8A210000E5DD6EF1DD66F2E53E03CDEB80DD6EFEDD66FFE5DD6EFCDD66FDE5F1
:208443003E07CDEB803EE1CD0880210000E521D007E53E03CD9D81F1F1DD7EF7DD77F5DDBF
:2084630036F6003A0260DD77F7DD6EF52600E5210002E5DD7EF7F5332101A8CD2A81DD5E9C
:20848300F1DD56F2DD6EFCDD66FD19DD75FCDD74FDDD7EFEDD8EF3DD77FE3003DD34FFDD5E
:2084A3007EF8DD96F1DD77F8DD7EF9DD9EF2DD77F9DD7EFADD9EF3DD77FADD7EFBDD9EF4AF
:2084C300DD77FBC3AD833A07B83D203D3A31B86F3E0BCDD4802E053E02CDD4802A05B8E568
:2084E3002A03B8E53E03CDEB803EF2CD0880111027210000CDD8813E01CD21803209B83A48
:2085030009B83D2804AFC33C853EA0CD0880111027210000CDD8813E01CD21803209B83A5F
:2085230009B83D2804AFC33C853EA1CD0880111027210000CDD8813E01DDF9DDE1C976CD39
:20854300DB8AB728F9C94F790DB7C876C34A85217D82CD648ACD4185217D82CDC28AAFC39D
:208563000380213582CD648ACD4185213582CDC28AAFC30380214782CD648A3E32CD4985B9
:20858300214782CDC28A3E02C30380215982CD648A3E32CD4985215982CDC28A3E02C30372
:2085A30080ED4B0AB81E006B260009563E0C836F3EB8CE00677AB7280A7BD6203005721C32
:2085C300C3AA853600C93E45F533210500E5210101E511F385216B82CD7B8A210CB8CDCFFF
:2085E3008AD5210107E5110CB8216B82CD2E8AC946696C653A00DDE5DD210000DD39EB015E
:208603002586DD7E0407070707E60F6F2600097E1213DD7E04E60F6F2600097E12DDE1E1DA
:2086230033E93031323334353637383941424344454600DDE5DD210000DD39F54D44E1D567
:20864300C5116400DD6EFEDD66FFCDDE89EB110A00CD298AC17BC63002696023E5C5110AB3
:2086630000DD6EFEDD66FFCDDE89EB110A00CD298AC1E17BC630770303C5110A00DD6EFEF9
:20868300DD66FFCD298AC17BC63002DDF9DDE1C9DDE5DD210000DD39E5210000E52E3CE574
:2086A300DD5E04DD5605DD6E06DD6607CDC3B8F1F1010000C50E64C5CD3CB8F1F14BC521AA
:2086C3000000E52E3CE5DD5E04DD5605DD6E06DD6607CD3CB8F1F1C151D52E0A7ACDD989E6
:2086E3007B2E0ACD228A7BD1C630E1E577C1C503C5D52E0A7ACD228A7BD1C1C63002E1E5B3
:208703002323363AC1C5030303C5D52E0A7BCDD9897B2E0ACD228A7BD1C1C63002DD7EFE0B
:20872300C6044FDD7EFFCE0047C52E0A7BCD228A7BC1C63002DDF9DDE1E1F1F1E92109001F
:20874300E5210301E5119687216B82CD2E8A210700E521030CE511A087216B82CD2E8A2158
:208763000600E5210315E511A887216B82CD2E8A210500E5210501E511AF87216B82CD2EB3
:208783008A210300E521050CE511B587216B82CD2E8AC95061747465726E3A2300202052B6
:2087A3006F773A2300202042504D3A0054696D653A00202F2000DDE5DD210000DD3921F8F3
:2087C300FF39F93A31B86F3E0BCDD4803EA8CD088011D007210000CDD8813E2BCD2180DD4B
:2087E30077FA3E2CCD2180DD77FB3E02F53321010039EB3E31CDA8803E2DCD3A80DD73FC8E
:20880300DD72FDDD75FEDD74FF3A30B8FD212DB8FDB602FDB601FDB600200C3E36CD3A8001
:20882300ED532DB8222FB8DD7EFAF5332132B8CDF985210200E521030AE51132B8216B8210
:20884300CD2E8ADD7EFBF5332132B8CDF985210200E5210313E51132B8216B82CD2E8AD139
:20886300D52134B8CD3686210300E521031BE51134B8216B82CD2E8A210000E52144ACE5D1
:20888300DD5EFCDD56FDDD6EFEDD66FFCDC3B8F1E3D52137B8CD9386210500E5210507E5DF
:2088A3001137B8216B82CD2E8A210000E52144ACE5ED5B2DB82A2FB8CDC3B8F1E3D521379F
:2088C300B8CD9386210500E521050FE51137B8216B82CD2E8ADDF9DDE1C9CDA4853A00A80A
:2088E300B7200DCD2882B73E0120023E023200A83A00A83DC26585322DB8322EB8322FB8D5
:208903003230B8CD2C83B7200B3A09B8D699CA7885C38E85216B82CD648ACDC985CD40875D
:20892300CDB98776CD718AB728273EA2CD0880111027210000CDD8813EE4CD088011102760
:20894300210000CDD881216B82CDC28A3E02CD0380CDE58AB728273EA2CD08801110272136
:208963000000CDD8813EE4CD0880111027210000CDD881216B82CDC28A3E04CD0380CDDB67
:208983008AB7289F3EA2CD0880111027210000CDD8813EE4CD0880111027210000CDD88102
:2089A300216B82CDC28AAFCD0380C32689ED7301B83208B8ED430AB8083207B82203B8ED5C
:1689C3005305B83A08B8B7CADD883A08B8D603CA5285AFC3038045
:03800000C3B08981
:2089D9005D6F2600547BE680B220110610ED6A17933001833FED6A10F65FEBC906097D6C02
:2089F9002600CB1DED6AED523001193F1710F5CB10505FC9DDE5DD210000DD39DD46043E87
:208A190030CD0660DDE1E133E95D6FCDDB89EBC9CDDE89EBC9DDE5E5D5DD210000DD39DD19
:208A3900460BDD4E0ADD5608DD5E09DD6E00DD6601D9DD6E02DD6603E5DDE1D93E03CD068D
:188A590060D1E1DDE1E133333333E9DDE5E5DDE13E01CD0660DDE1C941
:20B83C00DDE5DD210000DD39010000DD7E07073838DDCB0426DDCB0516DDCB0616DDCB0734
:20B85C00167BDD96047ADD9E057DDD9E067CDD9E073012DDCB073EDDCB061EDDCB051EDD2B
:20B87C00CB041E1804044818C27BDD96047ADD9E057DDD9E067CDD9E0738147BDD96045FF8
:20B89C007ADD9E05577DDD9E066F7CDD9E0767DDCB073EDDCB061EDDCB051EDDCB041E79A2
:20B8BC000DB720C5DDE1C9DDE5DD210000DD39F5F5AFDD77FCDD77FDDD77FEDD77FF062061
:20B8DC007C07E6014FCB23CB12ED6ADDCBFC26DDCBFD16DDCBFE16DDCBFF16CB412804DD5E
:20B8FC00CBFCC6DD7EFCDD9604DD7EFDDD9E05DD7EFEDD9E06DD7EFFDD9E073826DD7EFC8E
:20B91C00DD9604DD77FCDD7EFDDD9E05DD77FDDD7EFEDD9E06DD77FEDD7EFFDD9E07DD77BF
:0AB93C00FFCBC3109BDDF9DDE1C96C
:208A7100DDE53E1ACD0660DDE1C9DDE5E5D5DD210000DD39DD460BDD4E0ADD5608DD5E099F
:208A9100DD6E00DD6601D9DD6E02DD6603DD7E0CF5E5DDE1D93E03CD0660F108D9E5DDE109
:208AB100D93E04CD0660D1E1DDE1E13333333333E9DDE5E5DDE13E02CD0660DDE1C9AF47C9
:1E8AD1004FEDB121FFFFED42EBC9DDE53E17CD0660DDE1C9DDE53E19CD0660DDE1C9F4
:20812300DB573E03D377C9DDE5DD210000DD39F5F5DD75FEDD74FF2109607EDD77FC237E5D
:20814300DD77FD2A09607DDD96FC4F7CDD9EFD4779DD96FE78DD9EFF300E3E01CD2180FEFD
:208163000228E03E01C36C81AFDDF9DDE1C97D01AF1AED797C01AF1BED79FD210200FD3947
:20818300FD7E0001AF1CED79FD7E01FD4E02FD23CB39CB1F3D01AF26ED79FD7E023D01AF75
:2081A30028ED793E13D3773E03D357DB57DB573E8201AF27ED793E27DBAF0738F93E03D38C
:2081C30077CD1B81216400CD2A81E1F1F133E93E13D3773E08D357DB573E03D377C9DDE58D
:2081E300DD210000DD3921FBFF39F9DD77FFDD73FDDD72FE2109607EDD77FB237EDD77FCE6
:208203002A09607DDD96FB4F7CDD9EFC4779DD96FD78DD9EFE300F3E01CD2180DD96FF20FC
:20822300DF3E01C32A82AFDDF9DDE1C9EBED4B0960C5D53E01CD2180D1C1FE02280D2A09D5
:2082430060BFED42AFED5238E8AFC92A0960BFED42AFED523010C5D53E01CD2180D1C1FEC1
:208263000228E83E01C9AFC9E5D53E03CDEB80FD210200FD39FD6E003E02CDD4803EE0CD29
:208283000880216400CD2F823E0BCD21805F1600E133E9AFCD0880CDD281CD1B813E01C992
:2082A3008100190A280C700000000000C782E182E1820100160A2407700000000000E28244
:2082C300E182EB820E20584D2F584D5A2F53334D20506C617965722076302E312000000EE8
:2082E3002041626F757420000D0E584D20506C617965722076302E310D0E627920416C65A6
:2083030078204B6F726F6368696E736B697900DDE5DD210000DD3921ECFF39F93EA2CD08FC
:2083230080216400CD2F823EE4CD0880216400CD2F823A06B83D280A3A06B8D6022808C313
:208343004F833E08C351833E0CC351833E05F533ED5B02B82A04B8CD6B822130B8733E01C2
:20836300CD21803208B83A08B83D2804AFC33985210C0039EB2102B8010400EDB0AFDD7736
:20838300FCDD77FDDD77FEDD77FFDD7EFBDDB6FADDB6F9DDB6F8CAA284DD7EF9D610DD7E69
:2083A300FADE00DD7EFBDE00301121000039EB210C0039010400EDB0C3CD83DD36EC00DD31
:2083C30036ED10AFDD77EEDD77EF21050039EB21000039010400EDB0DD7EF1C6FFDD7EF28F
:2083E300CE01473E00CE005F3E00CE005748435ACB3BCB18CB19DD71F779F5332100A8CD68
:20840300008E210000E5DD6EF1DD66F2E53E03CDEB80DD6EFEDD66FFE5DD6EFCDD66FDE51A
:208423003E07CDEB803EE1CD08801164003E03CDE181DD7EF7DD77F5DD36F6003A0260DD46
:2084430077F7DD6EF52600E5210002E5DD7EF7F5332100A8CD7181DD5EF1DD56F2DD6EFCBE
:20846300DD66FD19DD75FCDD74FDDD7EFEDD8EF3DD77FE3003DD34FFDD7EF8DD96F1DD77AD
:20848300F8DD7EF9DD9EF2DD77F9DD7EFADD9EF3DD77FADD7EFBDD9EF4DD77FBC38D833AA1
:2084A30006B83D203A3A30B86F3E0BCDD4802E053E02CDD4802A04B8E52A02B8E53E03CD33
:2084C300EB803EF2CD088021FA00CD2F823E01CD21803208B83A08B83D2804AFC339853EA0
:2084E300A0CD088021F401CD2F823E01CD21803208B83A08B83D2804AFC339853A30B86F2D
:208503003E0BCDD4802E013E3ACDD4803EA6CD0880216400CD2F823EA1CD0880216400CD64
:208523002F823E01CD21803208B83A08B83D2804AFC339853E01DDF9DDE1C976CD208FB710
:2085430028F9C94F790DB7C876C347853A0E60D62438033E5AC93E50C9DDE5DD210000DDA3
:2085630039F5DD77FFDD75FE7DDD96FF301BDD7EFFDD5EFE934F9F475950CB7828035950D2
:20858300137BCB2ACB1FC38D85AFDDF9DDE1C91144B821B582011200EDB02148B86EE5CD34
:2085A3004F85E1CD5C853246B82149B86E3A0E60CD5C853247B82144B8CD578ECD3E85218E
:2085C30044B8CD078FAFC303803BFD210000FD39FD77003EA2CD0880216400CD2F823EE4E7
:2085E300CD0880216400CD2F822132B8CD078F210000397E33C3038033C92132B8CD078FF7
:20860300AFC3038076CD878EB72006CD648EB728053E02CDCC85CD2A8FB728053E04CDCCE7
:2086230085CD208FB728DDAFCDCC85C307863AB2B8F533214986CDDA87CD3E852132B8CD0B
:20864300078FAFC303804E6F20455350333220666F756E64003E01CD6E8EFE023E01C8AF68
:20866300C93A08B8F533218886CDDA87CD5886B72803CD07863E32CD46852132B8CD078F52
:208683003E02C3038046696C6520746F6F206C61726765003A08B8F53321BB86CDDA87CDB5
:2086A3005886B72803CD07863E32CD46852132B8CD078F3E02C30380506C61796261636B7A
:2086C300206572726F7200ED4B09B81E006B260009563E0B836F3EB8CE00677AB7280A7B02
:2086E300D6203005721CC3D0863600C9210500E5210201E5113B872132B8CD218E210BB854
:20870300CD148F3E71F533D5210207E5110BB82132B8CDB68E210700E5210301E51141874B
:208723002132B8CD218E212400E5210A02E51149872132B8CD218EC946696C653A005374C1
:20874300617475733A00506755702F5067446E3A547261636B204573633A53746F7020534E
:20876300706163653A4C6561766500DDE5DD210000DD39F51E007B854F3E008C470A4FB7DD
:20878300281F7BD618301A3E5683DD77FE3EB8CE00DD77FFE5DD6EFEDD66FF71E11CC37942
:2087A300877BD618300C2156B81600191C3620C3A4872132B8DD7E04F533111800D5110328
:2087C30009D51156B8CDB68EDDF9DDE1E133E93E71F533CD6E87C9DDE5DD210000DD393B84
:2087E300EB0E0069260019463E6E816F3EB8CE0067793CDD77FF78B7280C79D61130077056
:20880300DD4EFFC3E687DD4EFF3620690C2600116EB8193628690C2600116EB81936306978
:208823000C2600116EB8193678690C2600116EB819DD7E0407070707E60FC6815F3E00CEF8
:2088430088571A77690C2600116EB819DD7E04E60FC6815F3E00CE88571A77690C26001198
:208863006EB8193629692600116EB81936003E72F533216EB8CD6E8733DDE1E133E9303112
:20888300323334353637383941424344454600DDE5DD210000DD39EB01BE88DD7E0407071F
:2088A3000707E60F6F2600097E1213DD7E04E60F6F2600097E12DDE1E133E930313233343A
:2088C300353637383941424344454600DDE5DD210000DD39F54D44E1D5C5116400DD6EFE58
:2088E300DD66FFCDC78DEB110A00CD1C8EC17BC63002696023E5C5110A00DD6EFEDD66FF25
:20890300CDC78DEB110A00CD1C8EC1E17BC630770303C5110A00DD6EFEDD66FFCD1C8EC183
:208923007BC63002DDF9DDE1C9DDE5DD210000DD39E5210000E52E3CE5DD5E04DD5605DD00
:208943006E06DD6607CD3AB9F1F1010000C50E64C5CDB3B8F1F14BC5210000E52E3CE5DD5B
:208963005E04DD5605DD6E06DD6607CDB3B8F1F1C151D52E0A7ACDC28D7B2E0ACD158E7B52
:20898300D1C630E1E577C1C503C5D52E0A7ACD158E7BD1C1C63002E1E52323363AC1C50381
:2089A3000303C5D52E0A7BCDC28D7B2E0ACD158E7BD1C1C63002DD7EFEC6044FDD7EFFCE83
:2089C3000047C52E0A7BCD158E7BC1C63002DDF9DDE1E1F1F1E9210900E5210401E511784E
:2089E3008A2132B8CD218E210700E521040CE511828A2132B8CD218E210600E5210415E571
:208A0300118A8A2132B8CD218E210500E5210601E511918A2132B8CD218E210300E52106AC
:208A23000CE511978A2132B8CD218E1190B80E006926001936200C79D62038F4212000E557
:208A4300210804E52132B8CD218E210804E52132B8CD918E7AE63F57CBFBED53B0B80E00FF
:208A63002AB0B85D7CC6C0576926001936070C79D62038ECC95061747465726E3A23002003
:208A830020526F773A2300202042504D3A0054696D653A00202F2000DDE5DD210000DD39B7
:208AA3004B42EBDD7E07DDB606DDB605DDB604283069603E0529CB13CB123D20F8DD4E0643
:208AC300DD4607C5DD4E04DD4605C5EBCD3AB9F1F14B423E20BB3E009A3009012000C3E779
:208AE3008A0100001100002AB0B87CC6C067197B917A9830053E40C3FF8A3E0777136B620A
:208B03007DD6207CDE0038DFDDE1E1F1F1E9DDE5DD210000DD3921F8FF39F93A30B86F3E15
:208B23000BCDD4803EA8CD0880213200CD2F823E28CD2180DD77FF3A31B8D621201DDD7E21
:208B4300FFD62020163EE4CD0880216400CD2F822132B8CD078F3E02CD0380DD7EFF3231B2
:208B6300B83E2BCD2180DD77FA3E2CCD2180DD77FB3E02F53321010039EB3E31CDA8803E9E
:208B83002DCD3A80DD73FCDD72FDDD75FEDD74FF3A2FB8FD212CB8FDB602FDB601FDB600A7
:208BA300200C3E36CD3A80ED532CB8222EB8DD7EFAF5332186B8CD92883E71F533210200A2
:208BC300E521040AE51186B82132B8CDB68EDD7EFBF5332186B8CD92883E71F53321020070
:208BE300E5210413E51186B82132B8CDB68ED1D52188B8CDCF883E71F533210300E52104D5
:208C03001BE51188B82132B8CDB68E210000E52144ACE5DD5EFCDD56FDDD6EFEDD66FFCD29
:208C23003AB9F1E3D5218BB8CD2C893E71F533210500E5210607E5118BB82132B8CDB68E4A
:208C4300210000E52144ACE5ED5B2CB82A2EB8CD3AB9F1E3D5218BB8CD2C893E71F5332192
:208C63000500E521060FE5118BB82132B8CDB68E2A2EB8E52A2CB8E5DD5EFCDD56FDDD6EE2
:208C8300FEDD66FFCD9B8ADDF9DDE1C9DDE5DD210000DD393BCDCA861132B821A3820112C0
:208CA30000EDB02136B86EE5CD4F85E1CD5C853234B82137B86E3A0E60CD5C853235B8CDA4
:208CC3007D8ECDFD8E2132B8CD578ECDEF8621798DCDD2873AB2B83C200DCD9682B73E01FA
:208CE30020023E0232B2B83AB2B83D2806CD3186C3758DAF322CB8322DB8322EB8322FB80E
:208D0300CD1283B720133A08B8D6992006CD6486C3758DCD9786C3758D21918DCDD287CD18
:208D2300D9892131B83621CD118BDD36FF0076DD34FFDD7EFFD60A3807DD36FF00CD118B78
:208D4300CD878EB72006CD648EB728053E02CDCC85CD2A8FB728053E04CDCC85CD208FB753
:208D63002804AFCDCC85CDF68DB728C2CDFD85C3318D33DDE1C94C6F6164696E672C207002
:208D83006C6561736520776169742E2E2E00506C6179696E6700ED7300B83207B8ED430951
:1F8DA300B8083206B82202B8ED5304B83A07B8B7CA8F8C3A07B8D603CA9285AFC30380EC
:01B9BD00FF8A
:03800000C3998D94
:208DC2005D6F2600547BE680B220110610ED6A17933001833FED6A10F65FEBC906097D6C15
:208DE2002600CB1DED6AED523001193F1710F5CB10505FC9DDE53E10CD0660DDE1C9DDE549
:208E0200DD210000DD39DD46043E30CD0660DDE1E133E95D6FCDC48DEBC9CDC78DEBC9DD69
:208E2200E5E5D5DD210000DD39DD460BDD4E0ADD5608DD5E09DD6E00DD6601D9DD6E02DD09
:208E42006603E5DDE1D93E03CD0660D1E1DDE1E133333333E9DDE5E5DDE13E01CD0660DDFD
:1B8E6200E1C9DDE53E16CD0660DDE1C908DDE53E53CD066020023EFFDDE1C907
:20B8B300DDE5DD210000DD39010000DD7E07073838DDCB0426DDCB0516DDCB0616DDCB07BD
:20B8D300167BDD96047ADD9E057DDD9E067CDD9E073012DDCB073EDDCB061EDDCB051EDDB4
:20B8F300CB041E1804044818C27BDD96047ADD9E057DDD9E067CDD9E0738147BDD96045F81
:20B913007ADD9E05577DDD9E066F7CDD9E0767DDCB073EDDCB061EDDCB051EDDCB041E792A
:07B933000DB720C5DDE1C9DD
:0A8E7D00DDE53E0FCD0660DDE1C922
:20B93A00DDE5DD210000DD39F5F5AFDD77FCDD77FDDD77FEDD77FF06207C07E6014FCB236B
:20B95A00CB12ED6ADDCBFC26DDCBFD16DDCBFE16DDCBFF16CB412804DDCBFCC6DD7EFCDDC5
:20B97A009604DD7EFDDD9E05DD7EFEDD9E06DD7EFFDD9E073826DD7EFCDD9604DD77FCDD2C
:20B99A007EFDDD9E05DD77FDDD7EFEDD9E06DD77FEDD7EFFDD9E07DD77FFCBC3109BDDF9D7
:03B9BA00DDE1C903
:208E8700DDE53E1ACD0660DDE1C9DDE5E5DD210000DD39DD5606DD5E07DD6E00DD6601E54D
:208EA700DDE13E05CD0660EBE1DDE1E13333E9DDE5E5D5DD210000DD39DD460BDD4E0ADDED
:208EC7005608DD5E09DD6E00DD6601D9DD6E02DD6603DD7E0CF5E5DDE1D93E03CD0660F1B1
:208EE70008D9E5DDE1D93E04CD0660D1E1DDE1E13333333333E9DDE53E2ECD0660DDE1C978
:208F0700DDE5E5DDE13E02CD0660DDE1C9AF474FEDB121FFFFED42EBC9DDE53E17CD0660BC
:0D8F2700DDE1C9DDE53E19CD0660DDE1C9E3
:00000001FF
+1 -1
View File
@@ -3,7 +3,7 @@
-b _CODE = 0x8003
-b _DATA = 0xa800
-k E:\SDCC\4.6.0\bin\..\lib\z80
-l vgm_wc_api.lib
-l wc_api.lib
-l z80
obj/out.rel
obj/crt0.rel
+2521 -1814
View File
File diff suppressed because it is too large Load Diff
+133 -81
View File
@@ -16,33 +16,33 @@ Area Addr Size Decimal Bytes (A
00000000 l__GSINIT
00000000 l__HEADER
00000000 l__HEAP
00000000 l__INITIALIZED
00000000 l__INITIALIZER
00000000 s__CABS
00000000 s__DABS
00000000 s__HEADER
00000000 s__HEADER0
00000001 l__INITIALIZED
00000001 l__INITIALIZER
00000003 l__HEADER0
0000010A l__HOME
00000AEC l__CODE
0000103C l__DATA
00000F31 l__CODE
000010B2 l__DATA
00008003 s__CODE
0000A800 s__DATA
0000B83C s__HOME
0000B83C s__INITIALIZED
0000B946 s__BSEG
0000B946 s__BSS
0000B946 s__GSFINAL
0000B946 s__GSINIT
0000B946 s__HEAP
0000B946 s__INITIALIZER
0000B8B2 s__INITIALIZED
0000B8B3 s__HOME
0000B9BD s__GSFINAL
0000B9BD s__GSINIT
0000B9BD s__INITIALIZER
0000B9BE s__BSEG
0000B9BE s__BSS
0000B9BE s__HEAP
ASxxxx Linker V05.50.4-SDLD, page 2.
Hexadecimal [32-Bits]
Area Addr Size Decimal Bytes (Attributes)
-------------------------------- ---- ---- ------- ----- ------------
_CODE 00008003 00000AEC = 2796. bytes (REL,CON)
_CODE 00008003 00000F31 = 3889. bytes (REL,CON)
Value Global Global Defined In Module
----- -------------------------------- ------------------------
@@ -54,92 +54,138 @@ _CODE 00008003 00000AEC = 2796. bytes (R
000080D4 _esp_wr_reg8 main
000080EB _esp_wr_reg32 main
0000811B _esp_wr_end main
0000812A _esp_send_dma main
0000818E _esp_rd_end main
0000819D _esp_wait_status main
000081D8 _esp_wait_busy main
000081FA _esp_create_obj main
00008228 _esp_init main
00008235 _err_no_esp main
00008247 _err_out_of_mem main
00008259 _err_playback main
0000826B _win_xm main
0000827D _win_about main
0000832C _play_xm main
00008541 _wait_esc_key main
00008549 _wait_frames main
00008552 _about main
00008565 _error_esp main
00008578 _error_oom main
0000858E _error_playback main
000085A4 _copy_file_name main
000085C9 _xm_draw_static_labels main
000085F9 _put_hex2 main
00008636 _put_dec3 main
00008693 _put_time main
00008740 _xm_draw_stats_labels main
000087B9 _xm_update_info main
000088DD _main_start main
000089B0 _main main
000089D9 __divuchar divunsigned
000089DB __divu8 divunsigned
000089DE __divu16 divunsigned
000089DE __divuint divunsigned
00008A0D _wc_load512 wc_load512
00008A22 __moduchar modunsigned
00008A29 __moduint modunsigned
00008A2E _wc_prsrw wc_prsrw
00008A64 _wc_prwow wc_prwow
00008A71 _wc_key_pgdn wc_key_pgdn
00008A7B _wc_prsrw_attr wc_prsrw_attr
00008AC2 _wc_rresb wc_rresb
00008ACF _strlen strlen
00008ADB _wc_key_esc wc_key_esc
00008AE5 _wc_key_pgup wc_key_pgup
0000812A _esp_wait_not_busy main
00008171 _esp_send_dma main
000081D2 _esp_rd_end main
000081E1 _esp_wait_status main
0000822F _esp_wait_busy main
0000826B _esp_create_obj main
00008296 _esp_init main
000082A3 _win_xm_tpl main
000082B5 _win_about_tpl main
00008312 _play_xm main
0000853E _wait_esc_key main
00008546 _wait_frames main
0000854F _wc_screen_width main
0000855C _wc_center main
00008592 _about main
000085CC _unload_and_exit main
000085FD _leave_playing_and_exit main
00008607 _wait_for_manual_exit main
00008631 _error_esp main
00008658 _stop_on_error main
00008664 _error_oom main
00008697 _error_playback main
000086CA _copy_file_name main
000086EF _xm_draw_static_labels main
0000876E _xm_set_status_attr main
000087D2 _xm_set_status main
000087DA _xm_set_status_code main
00008892 _put_hex2 main
000088CF _put_dec3 main
0000892C _put_time main
000089D9 _xm_draw_stats_labels main
00008A9B _draw_progress_bar main
00008B11 _xm_update_info main
00008C8F _main_start main
00008D99 _main main
00008DC2 __divuchar divunsigned
00008DC4 __divu8 divunsigned
00008DC7 __divu16 divunsigned
00008DC7 __divuint divunsigned
00008DF6 _wc_key_space wc_key_space
00008E00 _wc_load512 wc_load512
00008E15 __moduchar modunsigned
ASxxxx Linker V05.50.4-SDLD, page 3.
Hexadecimal [32-Bits]
Area Addr Size Decimal Bytes (Attributes)
-------------------------------- ---- ---- ------- ----- ------------
_DATA 0000A800 0000103C = 4156. bytes (REL,CON)
_CODE 00008003 00000F31 = 3889. bytes (REL,CON)
Value Global Global Defined In Module
----- -------------------------------- ------------------------
0000A800 _state_esp main
0000A801 _fs_buf main
0000B801 _ret_sp main
0000B803 _filesize main
0000B807 _file_ext main
0000B808 _call_type main
0000B809 _last_esp_status main
0000B80A _p_file_name main
0000B80C _file_name main
0000B82D _total_samples main
0000B831 _xm_handle main
00008E1C __moduint modunsigned
00008E21 _wc_prsrw wc_prsrw
00008E57 _wc_prwow wc_prwow
00008E64 _wc_key_enter wc_key_enter
00008E6E _wc_prm_pl wc_prm_pl
00008E7D _wc_gedpl wc_gedpl
00008E87 _wc_key_pgdn wc_key_pgdn
00008E91 _wc_gadrw wc_gadrw
00008EB6 _wc_prsrw_attr wc_prsrw_attr
00008EFD _wc_key_wait_release wc_key_wait_release
00008F07 _wc_rresb wc_rresb
00008F14 _strlen strlen
00008F20 _wc_key_esc wc_key_esc
00008F2A _wc_key_pgup wc_key_pgup
ASxxxx Linker V05.50.4-SDLD, page 4.
Hexadecimal [32-Bits]
Area Addr Size Decimal Bytes (Attributes)
-------------------------------- ---- ---- ------- ----- ------------
_HOME 0000B83C 0000010A = 266. bytes (REL,CON)
_DATA 0000A800 000010B2 = 4274. bytes (REL,CON)
Value Global Global Defined In Module
----- -------------------------------- ------------------------
0000B83C __modulong _modulong
0000B8C3 __divulong _divulong
0000A800 _fs_buf main
0000B800 _ret_sp main
0000B802 _filesize main
0000B806 _file_ext main
0000B807 _call_type main
0000B808 _last_esp_status main
0000B809 _p_file_name main
0000B80B _file_name main
0000B82C _total_samples main
0000B830 _xm_handle main
0000B831 _last_track_status main
0000B832 _win_xm main
0000B844 _win_about main
0000B8B0 _bar_attr_ofs main
ASxxxx Linker V05.50.4-SDLD, page 5.
Hexadecimal [32-Bits]
Area Addr Size Decimal Bytes (Attributes)
-------------------------------- ---- ---- ------- ----- ------------
_INITIALIZED 0000B8B2 00000001 = 1. bytes (REL,CON)
Value Global Global Defined In Module
----- -------------------------------- ------------------------
0000B8B2 _state_esp main
ASxxxx Linker V05.50.4-SDLD, page 6.
Hexadecimal [32-Bits]
Area Addr Size Decimal Bytes (Attributes)
-------------------------------- ---- ---- ------- ----- ------------
_HOME 0000B8B3 0000010A = 266. bytes (REL,CON)
Value Global Global Defined In Module
----- -------------------------------- ------------------------
0000B8B3 __modulong _modulong
0000B93A __divulong _divulong
ASxxxx Linker V05.50.4-SDLD, page 7.
Hexadecimal [32-Bits]
Area Addr Size Decimal Bytes (Attributes)
-------------------------------- ---- ---- ------- ----- ------------
_INITIALIZER 0000B9BD 00000001 = 1. bytes (REL,CON)
Value Global Global Defined In Module
----- -------------------------------- ------------------------
ASxxxx Linker V05.50.4-SDLD, page 8.
Hexadecimal [32-Bits]
Area Addr Size Decimal Bytes (Attributes)
-------------------------------- ---- ---- ------- ----- ------------
_HEADER0 00000000 00000003 = 3. bytes (ABS,CON)
Value Global Global Defined In Module
----- -------------------------------- ------------------------
ASxxxx Linker V05.50.4-SDLD, page 6.
ASxxxx Linker V05.50.4-SDLD, page 9.
Files Linked [ module(s) ]
@@ -150,20 +196,26 @@ obj/crt0.rel [ crt0 ]
Libraries Linked [ object file ]
E:\SDCC\4.6.0\bin\..\lib\z80/z80.lib [ divunsigned.rel ]
vgm_wc_api.lib [ wc_load512.rel ]
wc_api.lib [ wc_key_space.rel ]
wc_api.lib [ wc_load512.rel ]
E:\SDCC\4.6.0\bin\..\lib\z80/z80.lib [ modunsigned.rel ]
vgm_wc_api.lib [ wc_prsrw.rel ]
vgm_wc_api.lib [ wc_prwow.rel ]
wc_api.lib [ wc_prsrw.rel ]
wc_api.lib [ wc_prwow.rel ]
wc_api.lib [ wc_key_enter.rel ]
wc_api.lib [ wc_prm_pl.rel ]
E:\SDCC\4.6.0\bin\..\lib\z80/z80.lib [ _modulong.rel ]
wc_api.lib [ wc_gedpl.rel ]
E:\SDCC\4.6.0\bin\..\lib\z80/z80.lib [ _divulong.rel ]
vgm_wc_api.lib [ wc_key_pgdn.rel ]
vgm_wc_api.lib [ wc_prsrw_attr.rel ]
vgm_wc_api.lib [ wc_rresb.rel ]
wc_api.lib [ wc_key_pgdn.rel ]
wc_api.lib [ wc_gadrw.rel ]
wc_api.lib [ wc_prsrw_attr.rel ]
wc_api.lib [ wc_key_wait_release.rel ]
wc_api.lib [ wc_rresb.rel ]
E:\SDCC\4.6.0\bin\..\lib\z80/z80.lib [ strlen.rel ]
vgm_wc_api.lib [ wc_key_esc.rel ]
vgm_wc_api.lib [ wc_key_pgup.rel ]
wc_api.lib [ wc_key_esc.rel ]
wc_api.lib [ wc_key_pgup.rel ]
ASxxxx Linker V05.50.4-SDLD, page 7.
ASxxxx Linker V05.50.4-SDLD, page 10.
User Base Address Definitions
+85 -67
View File
@@ -7,26 +7,26 @@ DEF l__GSFINAL 0x0
DEF l__GSINIT 0x0
DEF l__HEADER 0x0
DEF l__HEAP 0x0
DEF l__INITIALIZED 0x0
DEF l__INITIALIZER 0x0
DEF s__CABS 0x0
DEF s__DABS 0x0
DEF s__HEADER 0x0
DEF s__HEADER0 0x0
DEF l__INITIALIZED 0x1
DEF l__INITIALIZER 0x1
DEF l__HEADER0 0x3
DEF l__HOME 0x10A
DEF l__CODE 0xAEC
DEF l__DATA 0x103C
DEF l__CODE 0xF31
DEF l__DATA 0x10B2
DEF s__CODE 0x8003
DEF s__DATA 0xA800
DEF s__HOME 0xB83C
DEF s__INITIALIZED 0xB83C
DEF s__BSEG 0xB946
DEF s__BSS 0xB946
DEF s__GSFINAL 0xB946
DEF s__GSINIT 0xB946
DEF s__HEAP 0xB946
DEF s__INITIALIZER 0xB946
DEF s__INITIALIZED 0xB8B2
DEF s__HOME 0xB8B3
DEF s__GSFINAL 0xB9BD
DEF s__GSINIT 0xB9BD
DEF s__INITIALIZER 0xB9BD
DEF s__BSEG 0xB9BE
DEF s__BSS 0xB9BE
DEF s__HEAP 0xB9BE
DEF _wc_exit 0x8003
DEF _esp_cmd 0x8008
DEF _esp_rd_reg8 0x8021
@@ -35,59 +35,77 @@ DEF _esp_rd_regs 0x80A8
DEF _esp_wr_reg8 0x80D4
DEF _esp_wr_reg32 0x80EB
DEF _esp_wr_end 0x811B
DEF _esp_send_dma 0x812A
DEF _esp_rd_end 0x818E
DEF _esp_wait_status 0x819D
DEF _esp_wait_busy 0x81D8
DEF _esp_create_obj 0x81FA
DEF _esp_init 0x8228
DEF _err_no_esp 0x8235
DEF _err_out_of_mem 0x8247
DEF _err_playback 0x8259
DEF _win_xm 0x826B
DEF _win_about 0x827D
DEF _play_xm 0x832C
DEF _wait_esc_key 0x8541
DEF _wait_frames 0x8549
DEF _about 0x8552
DEF _error_esp 0x8565
DEF _error_oom 0x8578
DEF _error_playback 0x858E
DEF _copy_file_name 0x85A4
DEF _xm_draw_static_labels 0x85C9
DEF _put_hex2 0x85F9
DEF _put_dec3 0x8636
DEF _put_time 0x8693
DEF _xm_draw_stats_labels 0x8740
DEF _xm_update_info 0x87B9
DEF _main_start 0x88DD
DEF _main 0x89B0
DEF __divuchar 0x89D9
DEF __divu8 0x89DB
DEF __divu16 0x89DE
DEF __divuint 0x89DE
DEF _wc_load512 0x8A0D
DEF __moduchar 0x8A22
DEF __moduint 0x8A29
DEF _wc_prsrw 0x8A2E
DEF _wc_prwow 0x8A64
DEF _wc_key_pgdn 0x8A71
DEF _wc_prsrw_attr 0x8A7B
DEF _wc_rresb 0x8AC2
DEF _strlen 0x8ACF
DEF _wc_key_esc 0x8ADB
DEF _wc_key_pgup 0x8AE5
DEF _state_esp 0xA800
DEF _fs_buf 0xA801
DEF _ret_sp 0xB801
DEF _filesize 0xB803
DEF _file_ext 0xB807
DEF _call_type 0xB808
DEF _last_esp_status 0xB809
DEF _p_file_name 0xB80A
DEF _file_name 0xB80C
DEF _total_samples 0xB82D
DEF _xm_handle 0xB831
DEF __modulong 0xB83C
DEF __divulong 0xB8C3
DEF _esp_wait_not_busy 0x812A
DEF _esp_send_dma 0x8171
DEF _esp_rd_end 0x81D2
DEF _esp_wait_status 0x81E1
DEF _esp_wait_busy 0x822F
DEF _esp_create_obj 0x826B
DEF _esp_init 0x8296
DEF _win_xm_tpl 0x82A3
DEF _win_about_tpl 0x82B5
DEF _play_xm 0x8312
DEF _wait_esc_key 0x853E
DEF _wait_frames 0x8546
DEF _wc_screen_width 0x854F
DEF _wc_center 0x855C
DEF _about 0x8592
DEF _unload_and_exit 0x85CC
DEF _leave_playing_and_exit 0x85FD
DEF _wait_for_manual_exit 0x8607
DEF _error_esp 0x8631
DEF _stop_on_error 0x8658
DEF _error_oom 0x8664
DEF _error_playback 0x8697
DEF _copy_file_name 0x86CA
DEF _xm_draw_static_labels 0x86EF
DEF _xm_set_status_attr 0x876E
DEF _xm_set_status 0x87D2
DEF _xm_set_status_code 0x87DA
DEF _put_hex2 0x8892
DEF _put_dec3 0x88CF
DEF _put_time 0x892C
DEF _xm_draw_stats_labels 0x89D9
DEF _draw_progress_bar 0x8A9B
DEF _xm_update_info 0x8B11
DEF _main_start 0x8C8F
DEF _main 0x8D99
DEF __divuchar 0x8DC2
DEF __divu8 0x8DC4
DEF __divu16 0x8DC7
DEF __divuint 0x8DC7
DEF _wc_key_space 0x8DF6
DEF _wc_load512 0x8E00
DEF __moduchar 0x8E15
DEF __moduint 0x8E1C
DEF _wc_prsrw 0x8E21
DEF _wc_prwow 0x8E57
DEF _wc_key_enter 0x8E64
DEF _wc_prm_pl 0x8E6E
DEF _wc_gedpl 0x8E7D
DEF _wc_key_pgdn 0x8E87
DEF _wc_gadrw 0x8E91
DEF _wc_prsrw_attr 0x8EB6
DEF _wc_key_wait_release 0x8EFD
DEF _wc_rresb 0x8F07
DEF _strlen 0x8F14
DEF _wc_key_esc 0x8F20
DEF _wc_key_pgup 0x8F2A
DEF _fs_buf 0xA800
DEF _ret_sp 0xB800
DEF _filesize 0xB802
DEF _file_ext 0xB806
DEF _call_type 0xB807
DEF _last_esp_status 0xB808
DEF _p_file_name 0xB809
DEF _file_name 0xB80B
DEF _total_samples 0xB82C
DEF _xm_handle 0xB830
DEF _last_track_status 0xB831
DEF _win_xm 0xB832
DEF _win_about 0xB844
DEF _bar_attr_ofs 0xB8B0
DEF _state_esp 0xB8B2
DEF __modulong 0xB8B3
DEF __divulong 0xB93A
LOAD obj/out.ihx
+904 -528
View File
File diff suppressed because it is too large Load Diff
+87 -61
View File
@@ -63,104 +63,130 @@ Hexadecimal [32-Bits]
Symbol Table
0 ___str_11 00000793 R
0 ___str_12 0000079D R
0 ___str_13 000007A5 R
0 ___str_14 000007AC R
0 ___str_15 000007B2 R
0 ___str_9 000005F0 R
0 ___str_12 00000A75 R
0 ___str_13 00000A7F R
0 ___str_14 00000A87 R
0 ___str_15 00000A8E R
0 ___str_16 00000A94 R
0 ___str_17 00000D76 R
0 ___str_18 00000D8E R
0 ___str_4 00000646 R
0 ___str_5 00000685 R
0 ___str_6 000006B8 R
0 ___str_7 00000738 R
0 ___str_8 0000073E R
0 ___str_9 00000746 R
__divuchar ******** GX
__divuint ******** GX
__divulong ******** GX
__moduchar ******** GX
__moduint ******** GX
__modulong ******** GX
0 __str_0 0000028C R
0 __str_1 00000296 R
0 __str_2 00000297 R
0 __str_3 000002AD R
0 __str_4 000002CD R
0 __str_5 000002EB R
0 __str_6 00000300 R
0 __str_7 0000030E R
0 __str_8 00000317 R
0 _about 0000054F GR
1 _call_type 00001008 GR
0 _copy_file_name 000005A1 GR
1 _decbuf 00001034 R
0 _err_no_esp 00000232 GR
0 _err_out_of_mem 00000244 GR
0 _err_playback 00000256 GR
0 _error_esp 00000562 GR
0 _error_oom 00000575 GR
0 _error_playback 0000058B GR
0 __str_0 000002C4 R
0 __str_1 000002DE R
0 __str_2 000002DF R
0 __str_3 000002E8 R
7 __xinit__state_esp 00000000 R
0 _about 0000058F GR
1 _bar_attr_ofs 000010B0 GR
1 _barbuf 00001090 R
1 _call_type 00001007 GR
0 _copy_file_name 000006C7 GR
1 _decbuf 00001088 R
0 _draw_progress_bar 00000A98 GR
0 _error_esp 0000062E GR
0 _error_oom 00000661 GR
0 _error_playback 00000694 GR
0 _esp_cmd 00000005 GR
0 _esp_create_obj 000001F7 GR
0 _esp_init 00000225 GR
0 _esp_rd_end 0000018B GR
0 _esp_create_obj 00000268 GR
0 _esp_init 00000293 GR
0 _esp_rd_end 000001CF GR
0 _esp_rd_reg32 00000037 GR
0 _esp_rd_reg8 0000001E GR
0 _esp_rd_regs 000000A5 GR
0 _esp_send_dma 00000127 GR
0 _esp_wait_busy 000001D5 GR
0 _esp_wait_status 0000019A GR
0 _esp_send_dma 0000016E GR
0 _esp_wait_busy 0000022C GR
0 _esp_wait_not_busy 00000127 GR
0 _esp_wait_status 000001DE GR
0 _esp_wr_end 00000118 GR
0 _esp_wr_reg32 000000E8 GR
0 _esp_wr_reg8 000000D1 GR
1 _file_ext 00001007 GR
1 _file_name 0000100C GR
1 _filesize 00001003 GR
1 _fs_buf 00000001 GR
1 _hexbuf 00001032 R
1 _last_esp_status 00001009 GR
0 _main 000009AD GR
0 _main_start 000008DA GR
1 _p_file_name 0000100A GR
0 _play_xm 00000329 GR
0 _put_dec3 00000633 GR
1 _file_ext 00001006 GR
1 _file_name 0000100B GR
1 _filesize 00001002 GR
1 _fs_buf 00000000 GR
1 _hexbuf 00001086 R
1 _last_esp_status 00001008 GR
1 _last_track_status 00001031 GR
ASxxxx Assembler V05.50.4+NoICE+SDCCmods-WIP-R14 (Zilog Z80 / Hitachi HD64180 / ZX-Next / eZ80 / R800) Page 3
Hexadecimal [32-Bits]
Symbol Table
0 _put_hex2 000005F6 GR
0 _put_hex2_hexch_10000_105 00000622 R
0 _put_time 00000690 GR
1 _ret_sp 00001001 GR
1 _state_esp 00000000 GR
0 _leave_playing_and_exit 000005FA GR
0 _main 00000D96 GR
0 _main_start 00000C8C GR
1 _p_file_name 00001009 GR
0 _play_xm 0000030F GR
0 _put_dec3 000008CC GR
0 _put_hex2 0000088F GR
0 _put_hex2_hexch_10000_144 000008BB R
0 _put_time 00000929 GR
1 _ret_sp 00001000 GR
2 _state_esp 00000000 GR
1 _status_buf 00001056 R
1 _status_code_buf 0000106E R
0 _stop_on_error 00000655 GR
_strlen ******** GX
1 _timebuf 00001037 R
1 _total_samples 0000102D GR
0 _wait_esc_key 0000053E GR
0 _wait_frames 00000546 GR
1 _timebuf 0000108B R
1 _total_samples 0000102C GR
0 _unload_and_exit 000005C9 GR
0 _wait_esc_key 0000053B GR
0 _wait_for_manual_exit 00000604 GR
0 _wait_frames 00000543 GR
0 _wc_center 00000559 GR
0 _wc_exit 00000000 GR
_wc_gadrw ******** GX
_wc_gedpl ******** GX
_wc_key_enter ******** GX
_wc_key_esc ******** GX
_wc_key_pgdn ******** GX
_wc_key_pgup ******** GX
_wc_key_space ******** GX
_wc_key_wait_release ******** GX
_wc_load512 ******** GX
_wc_prm_pl ******** GX
_wc_prsrw ******** GX
_wc_prsrw_attr ******** GX
_wc_prwow ******** GX
_wc_rresb ******** GX
0 _win_about 0000027A GR
0 _win_xm 00000268 GR
0 _xm_draw_static_labels 000005C6 GR
0 _xm_draw_stats_labels 0000073D GR
1 _xm_handle 00001031 GR
0 _xm_update_info 000007B6 GR
0 _wc_screen_width 0000054C GR
1 _win_about 00001044 GR
0 _win_about_tpl 000002B2 GR
1 _win_xm 00001032 GR
0 _win_xm_tpl 000002A0 GR
0 _xm_draw_static_labels 000006EC GR
0 _xm_draw_stats_labels 000009D6 GR
1 _xm_handle 00001030 GR
0 _xm_set_status 000007CF GR
0 _xm_set_status_attr 0000076B GR
0 _xm_set_status_code 000007D7 GR
0 _xm_set_status_code_hexch_10000_141 0000087E R
0 _xm_update_info 00000B0E GR
ASxxxx Assembler V05.50.4+NoICE+SDCCmods-WIP-R14 (Zilog Z80 / Hitachi HD64180 / ZX-Next / eZ80 / R800) Page 4
Hexadecimal [32-Bits]
Area Table
0 _CODE size 9D6 flags 0
1 _DATA size 103C flags 0
2 _INITIALIZED size 0 flags 0
0 _CODE size DBF flags 0
1 _DATA size 10B2 flags 0
2 _INITIALIZED size 1 flags 0
3 _DABS size 0 flags 8
4 _HOME size 0 flags 0
5 _GSINIT size 0 flags 0
6 _GSFINAL size 0 flags 0
7 _INITIALIZER size 0 flags 0
7 _INITIALIZER size 1 flags 0
8 _CABS size 0 flags 8
+80 -10
View File
@@ -13,7 +13,7 @@
#define SPI_ESP_CS_ON 0x13
#define SPI_ESP_CS_OFF 0x03
u32 esp_wait_busy(u32 timeout);
u8 esp_wait_busy(u16 max_frames);
void esp_cmd(u8 cmd)
{
@@ -99,6 +99,31 @@ void esp_wr_end()
SPI_CTRL = SPI_ESP_CS_OFF;
}
// Plain single-phase "not busy" wait - for the one call site (esp_send_dma()
// below) where BUSY is genuinely never set for the awaited transition.
// Confirmed by reading the firmware (spi_slave.cpp's DREQ_DATA handler,
// reached via esp_wr_end() -> the low-level SPI W_END transaction, NOT
// esp_cmd()/the command() ISR dispatcher): it does the memcpy and jumps
// straight from DATA_M2S to READY, no BUSY in between. esp_wait_busy()'s
// two-phase "see BUSY first" logic is correct for actual commands (anything
// issued via esp_cmd(), which always sets BUSY before dispatching to
// xm_task/helper_task - see esp_wait_busy() below) but hangs here for its
// full timeout on every single chunk waiting for a BUSY that never appears -
// confirmed on hardware as "plays, but loading takes forever" after
// esp_wait_busy() was made two-phase project-wide.
u8 esp_wait_not_busy(u16 max_frames)
{
u16 start = *(u16*)_TMN;
while ((u16)(*(u16*)_TMN - start) < max_frames)
{
if (esp_rd_reg8(ESP_REG_STATUS) != ESP_ST_BUSY)
return 1;
}
return 0;
}
void esp_send_dma(u16 a, u8 p, u16 l, u16 n)
{
@@ -117,7 +142,7 @@ void esp_send_dma(u16 a, u8 p, u16 l, u16 n)
SPI_CTRL = SPI_ESP_CS_OFF;
esp_wr_end();
esp_wait_busy(60000);
esp_wait_not_busy(100); // 2s - esp32 consuming one DMA'd chunk should be near-instant
}
void esp_rd_end()
@@ -128,18 +153,63 @@ void esp_rd_end()
SPI_CTRL = SPI_ESP_CS_OFF;
}
u32 esp_wait_status(u8 status, u32 timeout)
// Both wait against WC's own frame timer (_TMN, 0x6009 - a 16-bit counter
// incremented at 50Hz by WC's interrupt) instead of a raw SPI-poll
// iteration count. An iteration count isn't real time - it depends on the
// current Z80 clock, which xmplay doesn't control (WC's turbo setting
// could be anything when the plugin starts) - and an uncalibrated guess
// already caused one real bug (TRACK_INIT timing out early on heavier
// files, see main.c's esp_wait_ready() history/comment). Returns 1 if the
// awaited condition was seen within max_frames, 0 on timeout.
u8 esp_wait_status(u8 status, u16 max_frames)
{
while (--timeout) if (esp_rd_reg8(ESP_REG_STATUS) == status) break;
u16 start = *(u16*)_TMN;
return timeout;
while ((u16)(*(u16*)_TMN - start) < max_frames)
{
if (esp_rd_reg8(ESP_REG_STATUS) == status)
return 1;
}
u32 esp_wait_busy(u32 timeout)
{
while (--timeout) if (esp_rd_reg8(ESP_REG_STATUS) != ESP_ST_BUSY) break;
return 0;
}
return timeout;
// A bare "status != BUSY" poll right after issuing a command can't tell
// "already finished" apart from "hasn't started yet": esp_cmd() doesn't
// touch ESP_REG_STATUS, so until the esp32's command() ISR gets around to
// setting BUSY for THIS command, the register still holds whatever the
// PREVIOUS command left there (typically READY) - and that stale READY
// satisfies "!= BUSY" just as well as a real completion does. Confirmed on
// real hardware via firmware-side timestamps (tbfire.xm, ESP_ERR_INV_XM_HANDLE
// on TRACK_PLAY): the esp32 recorded PLAY being rejected 1ms *before*
// TRACK_INIT even started processing - proving esp_wait_busy() had already
// returned "done" on TRACK_INIT's leftover-READY-from-WRITE_OBJECT, not on
// its actual completion. Fixed by requiring a genuine BUSY sighting first,
// so a "not busy" seen afterward is guaranteed to be THIS command's own
// completion. Every esp_wait_busy() call site in this plugin waits on an
// esp32 command that's handled by a background task (xm_task/helper_task),
// never resolved synchronously inside the ISR, so BUSY is always genuinely
// observable for at least one poll - this doesn't risk a regression on a
// command that completes "too fast to see".
u8 esp_wait_busy(u16 max_frames)
{
u16 start = *(u16*)_TMN;
// Phase 1: wait for the esp32 to actually start processing this command.
while (esp_rd_reg8(ESP_REG_STATUS) != ESP_ST_BUSY)
{
if ((u16)(*(u16*)_TMN - start) >= max_frames)
return 0;
}
// Phase 2: wait for it to finish (status becomes anything other than BUSY).
while ((u16)(*(u16*)_TMN - start) < max_frames)
{
if (esp_rd_reg8(ESP_REG_STATUS) != ESP_ST_BUSY)
return 1;
}
return 0;
}
int esp_create_obj(u32 size, u8 type)
@@ -147,7 +217,7 @@ int esp_create_obj(u32 size, u8 type)
esp_wr_reg32(ESP_REG_DATA_SIZE, size);
esp_wr_reg8(ESP_REG_OBJ_TYPE, type);
esp_cmd(ESP_CMD_MAKE_OBJECT);
esp_wait_busy(20000);
esp_wait_busy(100); // 2s - object allocation should be near-instant
// +++ check error
return esp_rd_reg8(ESP_REG_OBJ_HANDLE);
+412 -142
View File
@@ -12,12 +12,20 @@
// This used to be `const u8 state_esp = 0;`, written to via `*(u8*)&state_esp`
// as a code-size trick (skip GSINIT zero-init - a const's value is already
// known at compile time). That's undefined behavior (modifying a const
// object), and SDCC 4.6.0's more aggressive optimizer actually exploits it:
// it folds `state_esp != 1` to a compile-time-constant `true` (since the
// const's initializer is 0), permanently ignoring the "write" - which is
// exactly why esp32 detection always failed after the 4.0.0->4.6.0 bump.
// Plain (non-const) global; BSS zero-init already makes it start at 0.
u8 state_esp;
// object), and SDCC 4.6.0's more aggressive optimizer exploited it (folded
// `state_esp != 1` to a compile-time-constant `true`), so it was replaced
// with a plain global on the assumption that BSS zero-init makes it start
// at 0. That assumption was WRONG for this project: crt0.s never calls
// GSINIT (just `jp _main`), and hex2bin fills any address with no real hex
// record with 0xFF, not 0 - confirmed by reading obj/out.bin directly at
// state_esp's address (0xA800), which held 0xFF. So a truly-uninitialized
// global here always reads 0xFF on load, `!state_esp` is always false,
// esp_init() never runs, and error_esp() fires unconditionally - this is
// what actually broke esp32 detection, not (only) the const-UB optimizer
// fold. Fix: give it a real (non-zero) initializer so SDCC places it in the
// _DATA area with actual bytes in the loaded blob (like the original const
// did), and check against the real fill/sentinel value instead of 0.
u8 state_esp = 0xFF;
#define FS_BUF_SIZE 0x1000
u8 fs_buf[FS_BUF_SIZE]; // at 0xAE00 (_PAGE2 to get page)
@@ -36,6 +44,12 @@ char file_name[33];
u32 total_samples;
u8 xm_handle;
// Set right after a successful play_xm() (track is genuinely PLAYING at that
// point); compared against TRACK_GET_INFO's ESP_REG_TRACK_STATUS on every
// poll so a PLAYING->STOPPED transition (loop limit reached, track stopped
// itself) can be told apart from a track that was simply never started.
u8 last_track_status;
// --- Extensions ---------------------------
// file_ext is the matched entry's index into wc_h.c's ext[] table, so this
// enum must stay in the same order as that array (XM, XMZ, S3M).
@@ -47,85 +61,87 @@ enum
};
// --- Windows ------------------------------
const WC_TX_WINDOW err_no_esp =
{
/* window with header and text */ WC_WIND_HDR_TXT,
/* cursor color mask */ 0,
/* X,Y (position) */ 24, 10,
/* W,H (size) */ 32, 5,
/* paper/ink (window color) */ 0x2F,
/* -reserved- */ 0,
/* window restore buffer address */ 0,
/* separators */ 0, 0,
/* header text */ "\x0E" " Error! ",
/* footer text */ "",
/* window text */ "\x0E\x0C\x01" "No ESP32 detected!",
};
const WC_TX_WINDOW err_out_of_mem =
{
/* window with header and text */ WC_WIND_HDR_TXT,
/* cursor color mask */ 0,
/* X,Y (position) */ 255, 255,
/* W,H (size) */ 32, 5,
/* paper/ink (window color) */ 0x2F,
/* -reserved- */ 0,
/* window restore buffer address */ 0,
/* separators */ 0, 0,
/* header text */ "\x0E" " Error! ",
/* footer text */ "",
/* window text */ "\x0E\x0C\x01" "Out of memory (file too big)",
};
const WC_TX_WINDOW err_playback =
{
/* window with header and text */ WC_WIND_HDR_TXT,
/* cursor color mask */ 0,
/* X,Y (position) */ 255, 255,
/* W,H (size) */ 32, 5,
/* paper/ink (window color) */ 0x2F,
/* -reserved- */ 0,
/* window restore buffer address */ 0,
/* separators */ 0, 0,
/* header text */ "\x0E" " Error! ",
/* footer text */ "",
/* window text */ "\x0E\x0C\x01" "Playback error (bad file?)",
};
// STEP 1 of the gradual reintroduction: bigger, fixed position (not
// auto-center) - no wc_prsrw() calls yet, still just static wnd_txt like
// before. This exact size/position was already confirmed stable on its own
// earlier (before wc_prsrw/live-info were layered on top).
const WC_TX_WINDOW win_xm =
// win_xm_tpl is the compile-time template (const -> lands in CODE, so its
// bytes are genuinely baked into the loaded blob - unlike a non-const
// initialized global here, which would NOT be: this project's crt0.s never
// calls GSINIT, so _INITIALIZED-area bytes are simply absent from out.bin
// and read back as hex2bin's 0xFF fill regardless of the initializer given
// (confirmed by inspecting obj/out.bin - state_esp's own "give it a real
// initializer" fix above only works because 0xFF was picked to coincide
// with that fill value, not because the initializer is actually emitted).
// win_xm (below) is the mutable, actually-used instance: memcpy'd from this
// template at the point of use (see main_start()), then y_pos is patched to
// the real HEI-based center (HEI = screen height, 25/30/36 rows, see
// wc_api.h - WC's own 255,255 "auto-center" sentinel doesn't work on this
// WC build, see win_about's history below).
const WC_TX_WINDOW win_xm_tpl =
{
/* window with header and text + shadow (0x80) */ WC_WIND_HDR_TXT | 0x80,
/* cursor color mask */ 0,
/* X,Y (position) */ 25, 10,
/* W,H (size) */ 40, 11,
/* paper/ink (window color) */ 0x4F,
/* X,Y (position) */ 25, 10, // both placeholders, overwritten at runtime - see main_start()
/* W,H (size) */ 40, 12,
/* paper/ink (window color) */ 0x70, // white paper, black ink/border - matches VGMPLAY.WMF's CLR_WIN = WC_COLOR(WC_WHITE, WC_BLACK)
/* -reserved- */ 0,
/* window restore buffer address */ 0,
/* separators */ 0, 0,
/* header text */ "\x0E" " XM/XMZ/S3M Player ",
/* header text */ "\x0E" " XM/XMZ/S3M Player v0.1 ",
/* footer text */ "",
/* window text */ "\x0E\x0C\x01" "Playing..."
/* window text */ "" // replaced by the dynamic "Status:" line, see xm_set_status()
};
const WC_TX_WINDOW win_about =
// The actually-used, mutable instance - populated via memcpy from win_xm_tpl
// (see main_start()). Left without an initializer here on purpose: it would
// be silently ignored by this project's crt0.s anyway (see comment above),
// and an explicit memcpy at point of use is clearer than relying on that.
WC_TX_WINDOW win_xm;
// win_about_tpl/win_about follow the exact same const-template + memcpy'd-
// instance split as win_xm_tpl/win_xm above, for the same reason.
const WC_TX_WINDOW win_about_tpl =
{
/* window with header and text */ WC_WIND_HDR_TXT,
/* cursor color mask */ 0,
/* X,Y (position) */ 22, 10,
/* W,H (size) */ 36, 5,
/* paper/ink (window color) */ 0x4F,
/* X,Y (position) */ 22, 10, // both placeholders, overwritten at runtime - see about(). Screen
// width is NOT always 80: WC has three text modes - 90x36, 80x25,
// 80x30 (user-confirmed) - so width depends on HEI same as height
// does. (255,255 "auto-center" made the window not appear at all
// on this WC build, see project memory - not retried here.)
/* W,H (size) */ 36, 7, // +1 row for the 2nd centered line, +1 more for the blank line
// before the player name below
/* paper/ink (window color) */ 0x70, // matches win_xm_tpl's own color (white paper, black ink) - was
// 0x4F before, per explicit request to make About look the same
/* -reserved- */ 0,
/* window restore buffer address */ 0,
/* separators */ 0, 0,
/* header text */ "\x0E" " About ",
/* footer text */ "",
/* window text */ "\x0E\x0C\x01" "XM Player v1.0"
/* window text */ "\x0D" "\x0E" "XM Player v0.1" "\x0D" "\x0E" "by Alex Korochinskiy"
// Leading \x0D adds one blank row before the player name (purely cosmetic,
// per request) - see win_about_tpl's height above, bumped to make room.
// Root cause (read straight from WC's own firmware source - WCIF.ASM's
// TXTPR/CNTR/STSCN, not guessed): \x0E centers by scanning FORWARD through
// the text to measure the line's length (STSCN). That scan skips right
// over \x0C,YY (down-shift) without treating it as a line end - only a
// real \x0D or the string's own 0x00 terminate the scan. So with \x0C,01
// between the two lines (as this used to be), line 1's scan ran straight
// through the shift and hit line 2's OWN \x0E before reaching any real
// terminator - STSCN treats hitting a second \x0E mid-scan as a measurement
// failure and CNTR silently skips centering for it. Line 2 always worked
// because nothing follows it but the string's NUL. Using a real \x0D here
// gives line 1's scan a proper stopping point, fixing it - and \x0D moves
// to the next row exactly like \x0C,01 did (both land on Y+1 here), so this
// doesn't change vertical position at all.
};
WC_TX_WINDOW win_about; // mutable instance - see win_xm's comment above
void xm_set_status(const char *msg); // defined below, used by error_*() before that point
void xm_set_status_code(const char *msg, u8 code); // ditto
bool esp_init()
{
esp_cmd(ESP_CMD_NOP);
@@ -142,9 +158,9 @@ bool esp_init()
bool play_xm()
{
esp_cmd(ESP_CMD_TRACK_STOP);
esp_wait_busy(10000);
esp_wait_busy(100); // 2s - both should be near-instant
esp_cmd(ESP_CMD_KILL_OBJECTS);
esp_wait_busy(10000);
esp_wait_busy(100);
u8 obj_type;
switch (file_ext)
@@ -172,7 +188,7 @@ bool play_xm()
esp_wr_reg32(ESP_REG_DATA_SIZE, s);
esp_wr_reg32(ESP_REG_DATA_OFFSET, offs);
esp_cmd(ESP_CMD_WRITE_OBJECT);
esp_wait_status(ESP_ST_DATA_M2S, 2000);
esp_wait_status(ESP_ST_DATA_M2S, 100); // 2s - near-instant state transition
esp_send_dma((u16)fs_buf, *(u8*)_PAGE2, 512, sec);
offs += s;
@@ -188,7 +204,7 @@ bool play_xm()
esp_wr_reg8(ESP_REG_OBJ_TYPE, OBJ_TYPE_XM);
esp_wr_reg32(ESP_REG_DATA_SIZE, filesize);
esp_cmd(ESP_CMD_UNZIP);
esp_wait_busy(10000);
esp_wait_busy(250); // 5s - decompression time scales with file size
last_esp_status = esp_rd_reg8(ESP_REG_STATUS);
if (last_esp_status != ESP_ST_READY)
@@ -196,14 +212,31 @@ bool play_xm()
}
esp_cmd(ESP_CMD_TRACK_INIT);
esp_wait_busy(10000);
// 500 frames = 10s, comfortably past the firmware's 5s song-length
// measurement cap (XM_MEASURE_MAX_US in tracker.cpp) - see esp_wait_busy()
// in esp32.c for why this needs to be real-time-based, not an iteration
// count (an uncalibrated guess here previously caused ESP_ERR_INV_XM_HANDLE
// failures on heavier files that legitimately needed close to the full 5s).
esp_wait_busy(500);
last_esp_status = esp_rd_reg8(ESP_REG_STATUS);
if (last_esp_status != ESP_ST_READY)
return false;
// Play just one loop instead of looping forever. TRACK_INIT resets the
// limit back to 0 (infinite), so this must be (re)issued after every
// TRACK_INIT/TRACK_RESET, not just once.
esp_wr_reg8(ESP_REG_OBJ_HANDLE, xm_handle);
esp_wr_reg8(ESP_REG_TRACK_MAX_LOOP_COUNT, 1);
esp_cmd(ESP_CMD_TRACK_SET_PARAMS);
esp_wait_busy(100); // 2s - both should be near-instant
esp_cmd(ESP_CMD_TRACK_PLAY);
esp_wait_busy(10000);
esp_wait_busy(100);
last_esp_status = esp_rd_reg8(ESP_REG_STATUS);
if (last_esp_status != ESP_ST_READY)
return false;
return true;
}
@@ -232,35 +265,128 @@ void wait_frames(u8 n)
}
}
// Screen width isn't fixed at 80 either - WC has three text modes: 90x36,
// 80x25, 80x30 (user-confirmed), so width tracks HEI the same way height
// does (there's no separate documented width system variable to read).
// Matches demyanenko-d/VGMPLAY.WMF's own centering code (src_sdcc/main.c,
// "scr_w = (scr_h >= 36) ? 90 : 80") - same three modes, same mapping.
u8 wc_screen_width()
{
return (*(u8*)_HEI >= 36) ? 90 : 80;
}
// Clamps to 0 instead of underflowing (u8 wraparound) if the window is ever
// bigger than the screen - matches VGMPLAY.WMF's own centering code, same
// guard.
u8 wc_center(u8 screen_size, u8 win_size)
{
return (screen_size > win_size) ? (screen_size - win_size) / 2 : 0;
}
void about()
{
memcpy(&win_about, &win_about_tpl, sizeof(win_about));
win_about.x_pos = wc_center(wc_screen_width(), win_about.x_size);
win_about.y_pos = wc_center(*(u8*)_HEI, win_about.y_size);
wc_prwow(&win_about);
wait_esc_key();
wc_rresb(&win_about);
wc_exit(WC_EXIT);
}
// Shared by the main playback key-poll loop and wait_for_manual_exit() -
// stops the track, kills the esp32 objects, closes the window and hands
// control back to WC with the given signal.
void unload_and_exit(WC_EXIT_SIGNAL sig)
{
esp_cmd(ESP_CMD_TRACK_STOP);
esp_wait_busy(100); // 2s - both should be near-instant
esp_cmd(ESP_CMD_KILL_OBJECTS);
esp_wait_busy(100);
wc_rresb(&win_xm);
wc_exit(sig);
}
// Space - just leave, no esp32 commands at all: the track keeps playing on
// its own after the plugin exits, only our window/UI goes away.
void leave_playing_and_exit()
{
wc_rresb(&win_xm);
wc_exit(WC_EXIT);
}
// Used after an error when stoponerror=1: keeps responding to the same
// navigation keys as normal playback, but issues no esp32 commands and
// touches nothing on screen on its own - only acts once the user actually
// presses PgDn/PgUp/Esc, so the error stays visible for as long as needed.
void wait_for_manual_exit()
{
while (1)
{
__asm
halt
__endasm;
if (wc_key_pgdn() || wc_key_enter())
unload_and_exit(WC_NEXT_FILE);
if (wc_key_pgup())
unload_and_exit(WC_PREV_FILE);
if (wc_key_esc())
unload_and_exit(WC_EXIT);
}
}
// Errors used to open their own separate popup window; now they're just
// another Status value on the already-open win_xm, per user request - one
// less window type to keep track of, and errors show up in the same place
// as everything else instead of a separate modal-looking box.
void error_esp()
{
wc_prwow(&err_no_esp);
// esp_init() currently always returns true (no real detection logic yet,
// see its "+++ detect" comment), so state_esp is the only thing that can
// land here - shown anyway for when real detection is added.
xm_set_status_code("No ESP32 found", state_esp);
wait_esc_key();
wc_rresb(&err_no_esp);
wc_rresb(&win_xm);
wc_exit(WC_EXIT);
}
// wc_prm_pl(1) reads the "stoponerror" INI parameter declared in wc_h.c -
// the FIRST (and only) declared parameter, and per WC's own PRM_PL doc
// ("i:A' - номер параметра (от 1 до 8)") that's queried 1-based, not
// 0-based as a third-party reference wrongly suggested (which is why this
// never actually triggered - always asking for a nonexistent parameter 0).
// Option 2 ("1") means stop instead of moving on to the next file; option 1
// ("0", the default) keeps the old auto-advance behavior. 0xFF (param
// missing from an old/malformed header) is treated the same as the default.
u8 stop_on_error()
{
return wc_prm_pl(1) == 2;
}
void error_oom()
{
wc_prwow(&err_out_of_mem);
xm_set_status_code("File too large", last_esp_status);
if (stop_on_error())
wait_for_manual_exit();
wait_frames(50); // show the error for ~1 second (50Hz), then auto-advance
wc_rresb(&err_out_of_mem);
wc_rresb(&win_xm);
wc_exit(WC_NEXT_FILE);
}
void error_playback()
{
wc_prwow(&err_playback);
xm_set_status_code("Playback error", last_esp_status);
if (stop_on_error())
wait_for_manual_exit();
wait_frames(50); // show the error for ~1 second (50Hz), then auto-advance
wc_rresb(&err_playback);
wc_rresb(&win_xm);
wc_exit(WC_NEXT_FILE);
}
@@ -285,21 +411,106 @@ void copy_file_name()
// Coloring (PRIAT) via demyanenko-d/VGMPLAY.WMF's wc_prsrw_attr() - our own
// three hand-rolled attempts all corrupted esp32 file loading; retesting
// with their library now that build.bat pins SDCC 4.6.0 + --sdcccall 1.
#define ROW_FILE 1
#define ATTR_CAPTION 0x45 // cyan ink - "File:" caption
#define ROW_FILE 2 // row 1 left blank - a gap below the header, was too cramped right against it
// Attribute byte for wc_prsrw_attr() is (paper<<4)|ink, 0=black..7=white
// (confirmed on hardware via the old cyan "File:" caption, 0x45 = paper 4
// green/ink 5 cyan). White paper (7) throughout to match win_xm's own base
// color (0x70). Static captions ("File:", "Status:", "Pattern:", etc.) just
// use plain wc_prsrw() and inherit the window's own black ink - no override
// needed. ATTR_VALUE (blue) is for anything we actually write/update
// (filename, status text, live stats, progress bar); ATTR_ERROR (red)
// overrides that specifically for error text (see xm_set_status_code()).
#define ATTR_VALUE 0x71 // blue on white
#define ATTR_ERROR 0x72 // red on white
// Status: replaces the window's old baked-in "Playing..." text with a
// dynamic field - shows "Loading..." while play_xm() streams the file to
// the esp32 (can take a noticeable while for a big file - without this the
// window opens with just "File:" and nothing else visibly changes until
// playback starts, which reads as a hung interface), then whatever state/
// error is worth surfacing from there on (checked against ESP_REG_STATUS/
// ESP_REG_TRACK_STATUS as those checks get added).
#define ROW_STATUS 3
#define STATUS_VALUE_X 9
#define STATUS_VALUE_WIDTH 24
static char status_buf[STATUS_VALUE_WIDTH];
#define ROW_HINT 10 // one blank row after it, before the bottom border
#define HINT_TEXT "PgUp/PgDn:Track Esc:Stop Space:Leave"
void xm_draw_static_labels()
{
wc_prsrw_attr(&win_xm, "File:", ROW_FILE, 1, 5, ATTR_CAPTION);
wc_prsrw(&win_xm, file_name, ROW_FILE, 7, strlen(file_name));
wc_prsrw(&win_xm, "File:", ROW_FILE, 1, 5);
wc_prsrw_attr(&win_xm, file_name, ROW_FILE, 7, strlen(file_name), ATTR_VALUE);
wc_prsrw(&win_xm, "Status:", ROW_STATUS, 1, 7);
// Centered: 38 usable columns (1..38) minus 36-char HINT_TEXT leaves a
// 1-column margin each side, so it starts at column 2.
wc_prsrw(&win_xm, HINT_TEXT, ROW_HINT, 2, sizeof(HINT_TEXT) - 1);
}
// msg must be in #8000-#BFFF (a string literal or a global/static buffer,
// same constraint as every other wc_prsrw() text pointer here) - pads with
// spaces to STATUS_VALUE_WIDTH so a shorter message never leaves stray
// characters from a longer previous one.
void xm_set_status_attr(const char *msg, u8 attr)
{
u8 i = 0;
while (msg[i] && i < STATUS_VALUE_WIDTH)
{
status_buf[i] = msg[i];
i++;
}
while (i < STATUS_VALUE_WIDTH)
status_buf[i++] = ' ';
wc_prsrw_attr(&win_xm, status_buf, ROW_STATUS, STATUS_VALUE_X, STATUS_VALUE_WIDTH, attr);
}
void xm_set_status(const char *msg)
{
xm_set_status_attr(msg, ATTR_VALUE);
}
// Same as xm_set_status(), but appends " (0xXX)" with the raw esp status/
// error code - for on-screen diagnostics, so a failure doesn't need a
// hardware debugger to tell exactly which ESP_ST_*/ESP_ERR_* value it was.
static char status_code_buf[24];
void xm_set_status_code(const char *msg, u8 code)
{
static const char hexch[] = "0123456789ABCDEF";
u8 i = 0;
while (msg[i] && i < sizeof(status_code_buf) - 7)
{
status_code_buf[i] = msg[i];
i++;
}
status_code_buf[i++] = ' ';
status_code_buf[i++] = '(';
status_code_buf[i++] = '0';
status_code_buf[i++] = 'x';
status_code_buf[i++] = hexch[(code >> 4) & 0xF];
status_code_buf[i++] = hexch[code & 0xF];
status_code_buf[i++] = ')';
status_code_buf[i] = 0;
xm_set_status_attr(status_code_buf, ATTR_ERROR);
}
// --- Live status display (STEP 3, no coloring - plain wc_prsrw only) -----
#define ROW_STATS 3
#define ROW_TIME 5
#define ROW_BAR 6
#define BAR_X 1
#define BAR_WIDTH 34
#define ROW_STATS 4
#define ROW_TIME 6
#define ROW_BAR 8 // blank rows between each of these for spacing
// Window content is 40 wide with a 1-char border each side (38 usable
// columns, x=1..38) - BAR_X=4/BAR_WIDTH=32 gives a 3-column margin on
// both sides (4-1=3 before, 38-(4+32-1)=3 after). Adjust if the actual
// border turns out different on hardware.
#define BAR_X 4
#define BAR_WIDTH 32
void put_hex2(char *dst, u8 val)
{
@@ -327,19 +538,9 @@ void put_time(char *dst, u32 sec)
dst[4] = '0' + s % 10;
}
void xm_draw_stats_labels()
{
wc_prsrw(&win_xm, "Pattern:#", ROW_STATS, 1, 9);
wc_prsrw(&win_xm, " Row:#", ROW_STATS, 12, 7);
wc_prsrw(&win_xm, " BPM:", ROW_STATS, 21, 6);
wc_prsrw(&win_xm, "Time:", ROW_TIME, 1, 5);
wc_prsrw(&win_xm, " / ", ROW_TIME, 12, 3);
}
// wc_prsrw()'s text pointer MUST be in #8000-#BFFF (our own code/data
// window) - but this plugin runs on WC's OWN stack, which lives in a
// DIFFERENT window (#4000-#7FFF, per plugins/READ_ME.TXT: "стек... в Win 1
// DIFFERENT window (#4000-#7FFF, per plugins/READ_ME.TXT: "стек... в Win 1
// #4000-#7FFF"). Local (stack-allocated) char buffers passed to wc_prsrw()
// are therefore in the WRONG memory window entirely - this is almost
// certainly why xm_draw_static_labels() (string literal + a global array,
@@ -349,16 +550,81 @@ void xm_draw_stats_labels()
static char hexbuf[2];
static char decbuf[3];
static char timebuf[5];
static char barbuf[BAR_WIDTH];
// Attribute plane offset for a character cell = (char_addr & 0x3FFF) | 0x0080
// (same convention VGMPLAY.WMF's own progress bar uses on this same TS-Conf
// text hardware) - both planes sit in the #C000-#FFFF window that PRWOW/
// PRSRW/GADRW etc. all leave mapped in on exit. Computed once in
// xm_draw_stats_labels() (window position is fixed for the plugin's
// lifetime) - draw_progress_bar() only ever writes attribute bytes there,
// recoloring the background to grow a solid bar instead of drawing "="/"-"
// characters.
u16 bar_attr_ofs;
#define ATTR_BAR_FILLED 0x40 // green paper, black ink - filled portion (matches VGMPLAY.WMF's WC_COLOR(WC_GREEN, WC_BLACK))
#define ATTR_BAR_EMPTY 0x07 // black paper, white ink - unfilled portion
void xm_draw_stats_labels()
{
u8 i;
wc_prsrw(&win_xm, "Pattern:#", ROW_STATS, 1, 9);
wc_prsrw(&win_xm, " Row:#", ROW_STATS, 12, 7);
wc_prsrw(&win_xm, " BPM:", ROW_STATS, 21, 6);
wc_prsrw(&win_xm, "Time:", ROW_TIME, 1, 5);
wc_prsrw(&win_xm, " / ", ROW_TIME, 12, 3);
for (i = 0; i < BAR_WIDTH; i++)
barbuf[i] = ' ';
wc_prsrw(&win_xm, barbuf, ROW_BAR, BAR_X, BAR_WIDTH);
bar_attr_ofs = (wc_gadrw(&win_xm, ROW_BAR, BAR_X) & 0x3FFF) | 0x0080;
for (i = 0; i < BAR_WIDTH; i++)
*(volatile u8*)(0xC000 + bar_attr_ofs + i) = ATTR_BAR_EMPTY;
}
void draw_progress_bar(u32 samples, u32 total)
{
u16 filled, i;
if (total)
{
filled = (u16)(((u32)samples * BAR_WIDTH) / total);
if (filled > BAR_WIDTH)
filled = BAR_WIDTH;
}
else
filled = 0; // total length unknown (measurement timed out) - show empty
for (i = 0; i < BAR_WIDTH; i++)
*(volatile u8*)(0xC000 + bar_attr_ofs + i) = (i < filled) ? ATTR_BAR_FILLED : ATTR_BAR_EMPTY;
}
void xm_update_info()
{
u8 pattern, row;
u8 pattern, row, status;
u16 bpm;
u32 samples;
esp_wr_reg8(ESP_REG_OBJ_HANDLE, xm_handle);
esp_cmd(ESP_CMD_TRACK_GET_INFO);
esp_wait_busy(2000);
esp_wait_busy(50); // 1s - a plain info read should be near-instant
// TRACK_GET_INFO already writes ESP_REG_TRACK_STATUS (same register
// TRACK_GET_STATE reports), so no separate command is needed to catch the
// PLAYING->STOPPED transition once the loop-count limit is reached.
status = esp_rd_reg8(ESP_REG_TRACK_STATUS);
if (last_track_status == TRACK_OBJ_ST_PLAYING && status == TRACK_OBJ_ST_STOPPED)
{
esp_cmd(ESP_CMD_KILL_OBJECTS);
esp_wait_busy(100);
wc_rresb(&win_xm);
wc_exit(WC_NEXT_FILE);
}
last_track_status = status;
pattern = esp_rd_reg8(ESP_REG_TRACK_PATTERN);
row = esp_rd_reg8(ESP_REG_TRACK_ROW);
@@ -369,22 +635,22 @@ void xm_update_info()
total_samples = esp_rd_reg32(ESP_REG_TRACK_TOTAL_SAMPLES);
put_hex2(hexbuf, pattern);
wc_prsrw(&win_xm, hexbuf, ROW_STATS, 10, 2);
wc_prsrw_attr(&win_xm, hexbuf, ROW_STATS, 10, 2, ATTR_VALUE);
put_hex2(hexbuf, row);
wc_prsrw(&win_xm, hexbuf, ROW_STATS, 19, 2);
wc_prsrw_attr(&win_xm, hexbuf, ROW_STATS, 19, 2, ATTR_VALUE);
put_dec3(decbuf, bpm);
wc_prsrw(&win_xm, decbuf, ROW_STATS, 27, 3);
wc_prsrw_attr(&win_xm, decbuf, ROW_STATS, 27, 3, ATTR_VALUE);
put_time(timebuf, samples / 44100UL);
wc_prsrw(&win_xm, timebuf, ROW_TIME, 7, 5);
wc_prsrw_attr(&win_xm, timebuf, ROW_TIME, 7, 5, ATTR_VALUE);
put_time(timebuf, total_samples / 44100UL);
wc_prsrw(&win_xm, timebuf, ROW_TIME, 15, 5);
wc_prsrw_attr(&win_xm, timebuf, ROW_TIME, 15, 5, ATTR_VALUE);
draw_progress_bar(samples, total_samples);
// Progress bar skipped for now per user request - reintroduce as its own
// separate step once Pattern/Row/BPM/Time are confirmed stable.
}
void main_start()
@@ -393,7 +659,34 @@ void main_start()
copy_file_name();
if (!state_esp)
// Open the window before anything esp32-related runs, including the
// detection check - errors go into "Status:" on this same window (see
// error_esp() etc.) rather than a separate popup, and a big file's
// transfer in play_xm() can take a noticeable while, so nothing on
// screen during either would read as a hung interface. This used to be
// deferred until after play_xm() succeeded, because opening a window
// before esp32 activity used to corrupt the transfer - that was tied to
// our old hand-rolled PRSRW/PRIAT wrappers, not to window timing itself,
// and no longer applies now that we're on the real wc_api library
// (see project memory).
memcpy(&win_xm, &win_xm_tpl, sizeof(win_xm));
win_xm.x_pos = wc_center(wc_screen_width(), win_xm.x_size);
win_xm.y_pos = wc_center(*(u8*)_HEI, win_xm.y_size);
// GEDPL must run before ANY other WC API call - plugins/READ_ME.TXT is
// explicit that the screen can be in an arbitrary state on entry ("!при
// запуске плагина надо вызывать GEDPL... т.к. при входе в плагин может
// быть любой экран!"), so wc_key_wait_release() (see wc_api.c's comment -
// debounces the Enter/F3 that launched this plugin, so the main loop's
// wc_key_enter() check below doesn't immediately treat it as a fresh
// keypress) goes right after it, not before.
wc_gedpl();
wc_key_wait_release();
wc_prwow(&win_xm);
xm_draw_static_labels();
xm_set_status("Loading, please wait...");
if (state_esp == 0xFF)
state_esp = esp_init() ? 1 : 2;
if (state_esp != 1)
@@ -413,61 +706,38 @@ void main_start()
return;
}
// Draw the status window only AFTER play_xm() has already finished the
// file transfer and issued TRACK_INIT/TRACK_PLAY - drawing a window
// beforehand previously corrupted the esp32 transfer (see project memory).
wc_prwow(&win_xm);
xm_draw_static_labels();
xm_set_status("Playing");
xm_draw_stats_labels();
xm_update_info(); // single call for now - periodic re-calling is a separate step, once this is confirmed stable
last_track_status = TRACK_OBJ_ST_PLAYING;
xm_update_info();
frame_ctr = 0;
// poll keys
while (1)
{
__asm
halt
__endasm;
// DEBUG: periodic xm_update_info() disabled - isolating whether repeated
// wc_prsrw() calls over time (not just one initial call) is what causes
// the screen to fill with garbage after a while.
// if (++frame_ctr >= 10) // ~5 updates/sec at 50Hz
// {
// frame_ctr = 0;
// xm_update_info();
// }
if (wc_key_pgdn()) // PgDn - unload and go to next file
if (++frame_ctr >= 10) // ~5 updates/sec at 50Hz
{
esp_cmd(ESP_CMD_TRACK_STOP);
esp_wait_busy(10000);
esp_cmd(ESP_CMD_KILL_OBJECTS);
esp_wait_busy(10000);
wc_rresb(&win_xm);
wc_exit(WC_NEXT_FILE);
frame_ctr = 0;
xm_update_info();
}
if (wc_key_pgdn() || wc_key_enter()) // PgDn or Enter - unload and go to next file
unload_and_exit(WC_NEXT_FILE);
if (wc_key_pgup()) // PgUp - unload and go to previous file
{
esp_cmd(ESP_CMD_TRACK_STOP);
esp_wait_busy(10000);
esp_cmd(ESP_CMD_KILL_OBJECTS);
esp_wait_busy(10000);
wc_rresb(&win_xm);
wc_exit(WC_PREV_FILE);
}
unload_and_exit(WC_PREV_FILE);
if (wc_key_esc()) // Esc - unload and exit
{
esp_cmd(ESP_CMD_TRACK_STOP);
esp_wait_busy(10000);
esp_cmd(ESP_CMD_KILL_OBJECTS);
esp_wait_busy(10000);
wc_rresb(&win_xm);
wc_exit(WC_EXIT);
}
unload_and_exit(WC_EXIT);
if (wc_key_space()) // Space - leave the track playing, just exit
leave_playing_and_exit();
}
}
+43 -6
View File
@@ -1,31 +1,68 @@
// This project now builds under SDCC 4.6.0 + `--sdcccall 1` (SDCC's
// register calling convention) - see build.bat for why this is pinned
// PER-PROJECT, independent of the rest of ft812sdk (which stays on 4.0.0).
// This lets us link directly against demyanenko-d/VGMPLAY.WMF's real,
// hardware-tested wc_api library (vgm_wc_api.lib, assembled verbatim from
// hardware-tested wc_api library (wc_api.lib, assembled verbatim from
// their src_sdcc/lib/wc_api/*.s with the SAME SDCC 4.6.0's sdasz80) instead
// of our own hand-rolled __naked wrappers - our attempts at PRSRW+PRIAT (in
// three different shapes: globals-based single function, two separate
// naked functions, and a stack-based hand-port of their EXX logic) all
// corrupted esp32 file loading in ways never fully root-caused.
//
// Keyboard handling went through a raw-PS/2-FIFO rewrite (keys.c, since
// reverted) attempting to match how VGMPLAY.WMF's own player reads keys.
// That approach caused two confirmed hardware regressions - esp32 file
// transfers failing (ESP_ERR_INV_XM, 0x90, right after upload) and, once
// wc_int_pl() was worked around, the keyboard not responding at all (WC's
// own interrupt-driven PS/2 scan competes with raw FIFO reads for the same
// hardware) - so it's back to these simple WC-#6006-API wrappers
// (wc_key_esc/pgup/pgdn/space, plus wc_key_enter for PgDn's alternate).
// Their key-check constants (wc_key_esc=0x17, wc_key_pgup=0x19,
// wc_key_pgdn=0x1A) were confirmed to exactly match our own _ESC/_PGU/_PGD
// constants in wc_api.h before relying on them - same underlying WC #6006
// API, just a different project's wrapper names.
// wc_key_pgdn=0x1A, wc_key_enter=0x16) were confirmed to exactly match our
// own _ESC/_PGU/_PGD/_ENKE constants in wc_api.h - same underlying WC
// #6006 API, just a different project's wrapper names.
//
// Everything below is just extern declarations for symbols the linker
// pulls out of vgm_wc_api.lib (added to build.bat) - no bodies here.
// pulls out of wc_api.lib (added to build.bat) - no bodies here.
void wc_prwow(void *win);
void wc_rresb(void *win);
u8 wc_load512(u16 dest, u8 blocks);
u8 wc_key_esc(void);
u8 wc_key_pgup(void);
u8 wc_key_pgdn(void);
u8 wc_key_space(void);
u8 wc_key_enter(void);
// Waits for all keys to be reported released from WC's own point of view -
// called once at the top of main_start(), after wc_gedpl(). Needed because
// the plugin is launched BY an Enter keypress (or F3): without this, the
// very first wc_key_enter() check in the main loop can still see that same
// launch keypress as "down" and immediately treat it as a fresh Enter,
// jumping to the next file right after loading with no real keypress -
// confirmed on hardware, reproduces the same way whether Enter is read via
// this library's wc_key_enter() or via the raw-PS/2 rewrite that preceded
// it (see the file header comment) - a real human-timing race (the user
// hasn't necessarily released Enter yet by the time the file's done
// loading), not a bug tied to either keyboard-reading mechanism
// specifically.
void wc_key_wait_release(void);
void wc_gedpl(void);
void wc_prsrw(void *win, const u8 *text, u8 y, u8 x, u16 len);
void wc_prsrw_attr(void *win, const u8 *text, u8 y, u8 x, u16 len, u8 attr);
// y/x are 1-based; returns the character cell's address (relative to the
// #C000 window GADRW/PRWOW/PRSRW etc. all leave mapped in on exit) - see
// main.c's bar_attr_ofs for how the attribute-plane byte is derived from it.
u16 wc_gadrw(void *win, u8 y, u8 x);
// param_num is 1-based (matching WC's own PRM_PL doc, "i:A' - номер
// параметра (от 1 до 8)" - NOT 0-based as a third-party reference wrongly
// suggested, see main.c's stop_on_error()); returns the 1-based selected
// option index ("от 1 до 10"), or 0xFF if the plugin header doesn't declare
// that parameter at all.
u8 wc_prm_pl(u8 param_num);
// wc_exit is ours, not theirs - it unwinds our own crt0.s's saved SP
// (_ret_sp) to return control to WC, so there's no equivalent in their
// library to borrow. Adjusted for sdcccall(1): a single u8 argument now
+2
View File
@@ -17,6 +17,8 @@
#define _WCAPI 0x6006 // точка доступа к функциям
#define _TMN 0x6009 // синхра. переменная-таймер, инкрементится по инту
#define _HEI 0x600E // screen height in text rows: 25, 30 or 36 (see plugins/READ_ME.TXT)
//---------------------------------------
// API functions
#define _MNGC_PL 0x00 // включение страницы на 0xC000 (из выделенного блока)
+19 -3
View File
@@ -2,11 +2,18 @@
#include <defs.h>
#include <wc_h.h>
// STOPONERROR_PARAM: index passed to wc_prm_pl() to read this back (0-based,
// so this is the 1st and only declared parameter). Its declared options are
// "0" (default, at 1-based option index 1 - keep the old auto-advance
// behavior) and "1" (option index 2 - stop instead of moving to the next
// file after an error). See main.c's error_oom()/error_playback().
#define STOPONERROR_PARAM 0
static const WC_HDR hdr =
{
/* +00 -reserved- */ "",
/* +16 Magic string */ {'W', 'i', 'l', 'd', 'C', 'o', 'm', 'm', 'a', 'n', 'd', 'e', 'r', 'M', 'D', 'L'},
/* +32 Format version */ 7,
/* +32 Format version */ 10, // WC_PLUGIN_VERSION - v1.09+ needed for the INI param list below (PRM_PL)
/* +33 -reserved- */ "",
/* +34 Number of pages */ 1,
/* +35 Page at 0x8000 */ 0,
@@ -21,6 +28,15 @@ static const WC_HDR hdr =
/* */ },
/* +160 0x00 */ "",
/* +161 Max file size */ 0xFFFFFFFF,
/* +165 Plugin name */ "XM Player",
/* +197 Starting condition */ SC_MENU // also run by extension
/* +165 Plugin name */ "XM Player v0.1",
/* +197 Starting condition */ SC_MENU, // also run by extension
/* +198 -reserved- */ "",
/* +260 INI parameters */ {
/* record length (incl. this byte): 1+1+11+1+4 = 18 */ 18,
/* default option (1-based) */ 1,
/* parameter name, no terminator, no CAPS */ 's','t','o','p','o','n','e','r','r','o','r',
/* option count */ 2,
/* "0",0, "1",0 */ '0', 0, '1', 0,
/* end of parameter list */ 0
/* */ }
};
+2 -1
View File
@@ -32,5 +32,6 @@ typedef struct
u32 file_max_size; /* +161 Max file size */
char name[32]; /* +165 Plugin name */
SCOND cond; /* +197 Starting condition */
u8 res4[314]; /* +198 -reserved- */
u8 res4[62]; /* +198 -reserved- */
u8 ini_params[252]; /* +260 INI parameter list (WC v1.09+, PRM_PL) */
} WC_HDR;
View File