Add OPL4 playback and analyzer support

This commit is contained in:
2026-09-15 14:59:29 +03:00
commit 1686838e03
553 changed files with 50524 additions and 0 deletions
+203
View File
@@ -0,0 +1,203 @@
/**
* @file keys.c
* @brief PS/2 клавиатура через TSConfig CMOS FIFO (порты #EFF7/#DFF7/#BFF7)
* @see inc/keys.h
*
* Аппаратный PS/2 FIFO буфер в FPGA TSConfig, регистр CMOS #F0.
*
* ps2_poll() за один вызов полностью сливает FIFO (tight loop).
* Если среди прочитанных байтов есть make-код нашей клавиши — возвращает
* последний найденный KEY_*. Стая байтов никогда не копится.
*
* Единственный бит состояния — skip flag (после F0 нужно пропустить 1 байт).
* E0 (extended prefix) не требует skip: сам E0 не совпадает с нашими кодами,
* а release extended (E0 F0 SC) корректно обрабатывается через F0→skip.
*
* Опрос ~1 раз в TV-кадр (rate-limited по isr_tick_ctr).
* ps2_poll полностью на asm.
*/
#include "../inc/types.h"
#include "../inc/keys.h"
#include "../inc/isr.h" /* isr_tick_ctr (volatile uint8_t) */
#include "../inc/variant_cfg.h" /* ISR_TICKS_PER_FRAME */
/* Единственная FSM-переменная: skip flag (0 или 1). */
static uint8_t ps2_state; /* 0 = normal, 1 = skip next byte */
static uint8_t ps2_last_tick;
/* ── ps2_init: активация PS/2 FIFO + одноразовый слив ────────────── */
void ps2_init(void)
{
__asm
; Разрешить PS/2 порты (бит 7 #EFF7)
ld bc, #0xEFF7
ld a, #0x80
out (c), a
; Выбрать CMOS reg #F0, записать 2 (активация), re-select #F0
ld bc, #0xDFF7
ld a, #0xF0
out (c), a
ld bc, #0xBFF7
ld a, #0x02
out (c), a
ld bc, #0xDFF7
ld a, #0xF0
out (c), a
; Слив FIFO (tight loop, макс 256 итераций)
ld bc, #0xBFF7
ld e, #0
_pi_drain:
in a, (c)
or a, a
jr z, _pi_done ; 0x00 = пусто
inc a
jr z, _pi_ovf ; 0xFF = overflow
dec e
jr nz, _pi_drain
jr _pi_done
_pi_ovf:
ld bc, #0xDFF7
ld a, #0x0C
out (c), a
ld bc, #0xBFF7
ld a, #0x01
out (c), a
ld bc, #0xDFF7
ld a, #0xF0
out (c), a
_pi_done:
__endasm;
ps2_state = 0;
ps2_last_tick = isr_tick_ctr;
}
/* ── ps2_deinit: слив FIFO перед выходом ──────────────────────────── */
void ps2_deinit(void)
{
__asm
ld bc, #0xDFF7
ld a, #0xF0
out (c), a
ld bc, #0xBFF7
ld e, #0
_pd_loop:
in a, (c)
or a, a
jr z, _pd_done ; 0x00 = пусто
inc a
jr z, _pd_ovf ; 0xFF = overflow
dec e
jr nz, _pd_loop
jr _pd_done
_pd_ovf:
ld bc, #0xDFF7
ld a, #0x0C
out (c), a
ld bc, #0xBFF7
ld a, #0x01
out (c), a
ld bc, #0xDFF7
ld a, #0xF0
out (c), a
_pd_done:
__endasm;
}
/* ── ps2_poll: tight-drain FIFO, rate-limited, полностью asm ──────── */
uint8_t ps2_poll(void) __naked
{
__asm
;; ── Rate limit: ~1 TV-кадр ────────────────────────
ld a, (_isr_tick_ctr)
ld hl, #_ps2_last_tick
ld e, a
sub a, (hl)
cp a, #ISR_TICKS_PER_FRAME
jp c, _pp_none
ld (hl), e
;; ── Подготовка: выбрать FIFO, init регистров ──────
ld bc, #0xDFF7
ld a, #0xF0
out (c), a
ld bc, #0xBFF7 ; BC = порт FIFO на весь цикл
ld a, (_ps2_state)
ld d, a ; D = skip flag (от пред. вызова)
ld e, #0 ; E = результат (KEY_NONE)
;; ── Цикл: читаем FIFO до пустого ─────────────────
_pp_loop:
in a, (c) ; BC = #BFF7
or a, a
jr z, _pp_done ; 0x00 = пусто → выход
inc a
jr z, _pp_ovf ; 0xFF = overflow
dec a ; восстановить байт
bit 0, d
jr nz, _pp_clr_skip ; skip-флаг → пропустить байт
cp a, #0xF0
jr z, _pp_set_skip ; F0 → пропустить след. байт
;; ── Трансляция scan code → KEY_* ──────────────────
cp a, #0x76 ; ESC
jr z, _pp_k_esc
cp a, #0x29 ; SPACE
jr z, _pp_k_next
cp a, #0x4D ; P
jr z, _pp_k_prev
cp a, #0x16 ; 1
jr z, _pp_k_saa1
cp a, #0x1E ; 2
jr z, _pp_k_saa2
jr _pp_loop ; неизвестная → продолжаем слив
_pp_k_esc: ld e, #KEY_ESC
jr _pp_loop
_pp_k_next: ld e, #KEY_NEXT
jr _pp_loop
_pp_k_prev: ld e, #KEY_PREV
jr _pp_loop
_pp_k_saa1: ld e, #KEY_SAA1
jr _pp_loop
_pp_k_saa2: ld e, #KEY_SAA2
jr _pp_loop
_pp_set_skip:
ld d, #1
jr _pp_loop
_pp_clr_skip:
ld d, #0
jr _pp_loop
;; ── Overflow: сброс FIFO ─────────────────────────
_pp_ovf:
ld bc, #0xDFF7
ld a, #0x0C
out (c), a
ld bc, #0xBFF7
ld a, #0x01
out (c), a
ld bc, #0xDFF7
ld a, #0xF0
out (c), a
ld d, #0 ; сбросить skip
;; fall-through
;; ── Готово: сохранить skip, вернуть KEY ───────────
_pp_done:
ld a, d
ld (_ps2_state), a ; skip flag для след. вызова
ld a, e ; A = KEY_* (sdcccall(1))
ret
_pp_none:
xor a, a ; KEY_NONE = 0
ret
__endasm;
}
+2017
View File
File diff suppressed because it is too large Load Diff
+38
View File
@@ -0,0 +1,38 @@
@echo off
REM ===========================================================================
REM build_lib.bat — Сборка статической библиотеки wc_api.lib
REM
REM Каждая функция WC API — отдельный .rel модуль.
REM Линковщик SDCC подтягивает из .lib только модули с нужными символами.
REM ===========================================================================
setlocal
cd /d "%~dp0"
set ASFLAGS=-plosff
set BUILDDIR=..\..\build\wc_api
set LIBFILE=..\..\build\wc_api.lib
REM --- Папка для .rel файлов ---
if not exist "%BUILDDIR%" mkdir "%BUILDDIR%"
REM --- Сборка всех .s → .rel ---
for %%f in (*.s) do (
sdasz80 %ASFLAGS% "%BUILDDIR%\%%~nf.rel" "%%f" >nul
if errorlevel 1 ( echo FAIL %%f && exit /b 1 )
)
REM --- Удалить старую библиотеку ---
if exist "%LIBFILE%" del "%LIBFILE%"
REM --- Создать .lib архив (Windows cmd не раскрывает *.rel для sdar) ---
setlocal enabledelayedexpansion
set RELFILES=
for %%f in ("%BUILDDIR%\*.rel") do set RELFILES=!RELFILES! "%%f"
sdar -rc "%LIBFILE%" %RELFILES% >nul
if errorlevel 1 ( echo FAIL sdar && exit /b 1 )
endlocal
echo wc_api.lib OK
exit /b 0
+11
View File
@@ -0,0 +1,11 @@
.module wc_adir
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_adir
_wc_adir::
ex af, af'
push ix
ld a, #0x38
call WC_ENTRY
pop ix
ret
+13
View File
@@ -0,0 +1,13 @@
.module wc_chtosep
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_chtosep
_wc_chtosep::
push ix
ld b, d
ld c, e ; BC = bufend (from DE)
ex de, hl ; DE = buf (from HL)
ld a, #0x34
call WC_ENTRY
pop ix
ret
+12
View File
@@ -0,0 +1,12 @@
.module wc_curser
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_curser
_wc_curser::
push ix
push hl
pop ix
ld a, #0x07
call WC_ENTRY
pop ix
ret
+12
View File
@@ -0,0 +1,12 @@
.module wc_cursor
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_cursor
_wc_cursor::
push ix
push hl
pop ix
ld a, #0x06
call WC_ENTRY
pop ix
ret
+10
View File
@@ -0,0 +1,10 @@
.module wc_delfl
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_delfl
_wc_delfl::
push ix
ld a, #0x4B
call WC_ENTRY
pop ix
ret
+11
View File
@@ -0,0 +1,11 @@
.module wc_dmapl
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_dmapl
_wc_dmapl::
ex af, af'
push ix
ld a, #0x0D
call WC_ENTRY
pop ix
ret
+15
View File
@@ -0,0 +1,15 @@
.module wc_fentry
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_fentry
_wc_fentry::
push ix
; HL = name (sdcccall(1); WC нужен HL — уже на месте!)
ld a, #0x3B
call WC_ENTRY
ld a, #0
jr z, _wc_fentry_end
inc a
_wc_fentry_end:
pop ix
ret
+22
View File
@@ -0,0 +1,22 @@
.module wc_findnext
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_findnext
_wc_findnext::
push ix
ld ix, #0
add ix, sp
ld a, 4(ix) ; A = flags (from stack)
ex af, af' ; A' = flags
ex de, hl ; DE = entry_buf (SDCC HL → WC DE)
ld a, #0x3A
call WC_ENTRY
ld a, #0
jr z, _wc_findnext_end
inc a
_wc_findnext_end:
pop ix
; callee cleans 1 byte (flags)
pop hl
inc sp
jp (hl)
+25
View File
@@ -0,0 +1,25 @@
.module wc_gadrw
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_gadrw
_wc_gadrw::
push ix
push hl ; save win (HL = 1st arg)
ld ix, #0
add ix, sp
ld d, 6(ix) ; D = y
ld e, 7(ix) ; E = x
ld l, 0(ix)
ld h, 1(ix) ; HL = win
push hl
pop ix ; IX = win
ld a, #0x05
call WC_ENTRY ; HL = result addr
ex de, hl ; DE = result (sdcccall(1) uint16)
pop hl ; remove saved win (use HL, keep DE)
pop ix ; restore caller IX
; callee cleans 2 bytes (y+x); preserve DE = return value
pop hl ; HL = return address
inc sp
inc sp ; discard y(1)+x(1)
jp (hl) ; return, DE = result
+10
View File
@@ -0,0 +1,10 @@
.module wc_gdir
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_gdir
_wc_gdir::
push ix
ld a, #0x3F
call WC_ENTRY
pop ix
ret
+10
View File
@@ -0,0 +1,10 @@
.module wc_gedpl
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_gedpl
_wc_gedpl::
push ix
ld a, #0x0F
call WC_ENTRY
pop ix
ret
+10
View File
@@ -0,0 +1,10 @@
.module wc_gfile
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_gfile
_wc_gfile::
push ix
ld a, #0x3E
call WC_ENTRY
pop ix
ret
+10
View File
@@ -0,0 +1,10 @@
.module wc_gipagpl
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_gipagpl
_wc_gipagpl::
push ix
ld a, #0x32
call WC_ENTRY
pop ix
ret
+11
View File
@@ -0,0 +1,11 @@
.module wc_gvmod
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_gvmod
_wc_gvmod::
ex af, af'
push ix
ld a, #0x42
call WC_ENTRY
pop ix
ret
+11
View File
@@ -0,0 +1,11 @@
.module wc_gvsgp
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_gvsgp
_wc_gvsgp::
push ix
ld c, a
ld a, #0x47
call WC_ENTRY
pop ix
ret
+17
View File
@@ -0,0 +1,17 @@
.module wc_gvtl
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_gvtl
_wc_gvtl::
push ix
ld ix, #0
add ix, sp
ld c, 4(ix) ; C = page
ld b, a ; B = plane
ld a, #0x46
call WC_ENTRY
pop ix
; callee cleans 1 byte (page)
pop hl
inc sp
jp (hl)
+11
View File
@@ -0,0 +1,11 @@
.module wc_gvtm
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_gvtm
_wc_gvtm::
push ix
ld c, a
ld a, #0x45
call WC_ENTRY
pop ix
ret
+10
View File
@@ -0,0 +1,10 @@
.module wc_gxoff
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_gxoff
_wc_gxoff::
push ix
ld a, #0x44
call WC_ENTRY
pop ix
ret
+10
View File
@@ -0,0 +1,10 @@
.module wc_gyoff
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_gyoff
_wc_gyoff::
push ix
ld a, #0x43
call WC_ENTRY
pop ix
ret
+11
View File
@@ -0,0 +1,11 @@
.module wc_int_pl
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_int_pl
_wc_int_pl::
ex af, af'
push ix
ld a, #0x56
call WC_ENTRY
pop ix
ret
+13
View File
@@ -0,0 +1,13 @@
.module wc_int_pl_handler
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_int_pl_handler
_wc_int_pl_handler::
push ix
; HL = handler_addr (sdcccall(1); WC тоже нужен HL)
ld a, #0xFF
ex af, af' ; A' = 0xFF
ld a, #0x56
call WC_ENTRY
pop ix
ret
+19
View File
@@ -0,0 +1,19 @@
.module wc_istr
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_istr
_wc_istr::
push ix
ld ix, #0
add ix, sp
ld a, 4(ix) ; A = mode (from stack)
ex af, af' ; A' = mode
push hl
pop ix ; IX = win (HL = 1st arg)
ld a, #0x09
call WC_ENTRY
pop ix
; callee cleans 1 byte (mode)
pop hl
inc sp
jp (hl)
+11
View File
@@ -0,0 +1,11 @@
.module wc_kbscn
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_kbscn
_wc_kbscn::
ex af, af' ; A' = mode
push ix
ld a, #0x2A
call WC_ENTRY
pop ix
ret
+10
View File
@@ -0,0 +1,10 @@
.module wc_key_alt
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_key_alt
_wc_key_alt::
push ix
ld a, #0x27
call WC_ENTRY
pop ix
ret
+10
View File
@@ -0,0 +1,10 @@
.module wc_key_any
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_key_any
_wc_key_any::
push ix
ld a, #0x2D
call WC_ENTRY
pop ix
ret
+10
View File
@@ -0,0 +1,10 @@
.module wc_key_bspc
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_key_bspc
_wc_key_bspc::
push ix
ld a, #0x18
call WC_ENTRY
pop ix
ret
+10
View File
@@ -0,0 +1,10 @@
.module wc_key_caps
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_key_caps
_wc_key_caps::
push ix
ld a, #0x2C
call WC_ENTRY
pop ix
ret
+10
View File
@@ -0,0 +1,10 @@
.module wc_key_ctrl
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_key_ctrl
_wc_key_ctrl::
push ix
ld a, #0x29
call WC_ENTRY
pop ix
ret
+10
View File
@@ -0,0 +1,10 @@
.module wc_key_del
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_key_del
_wc_key_del::
push ix
ld a, #0x2B
call WC_ENTRY
pop ix
ret
+10
View File
@@ -0,0 +1,10 @@
.module wc_key_down
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_key_down
_wc_key_down::
push ix
ld a, #0x12
call WC_ENTRY
pop ix
ret
+10
View File
@@ -0,0 +1,10 @@
.module wc_key_end
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_key_end
_wc_key_end::
push ix
ld a, #0x1C
call WC_ENTRY
pop ix
ret
+10
View File
@@ -0,0 +1,10 @@
.module wc_key_enter
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_key_enter
_wc_key_enter::
push ix
ld a, #0x16
call WC_ENTRY
pop ix
ret
+10
View File
@@ -0,0 +1,10 @@
.module wc_key_esc
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_key_esc
_wc_key_esc::
push ix
ld a, #0x17
call WC_ENTRY
pop ix
ret
+10
View File
@@ -0,0 +1,10 @@
.module wc_key_f1
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_key_f1
_wc_key_f1::
push ix
ld a, #0x1D
call WC_ENTRY
pop ix
ret
+10
View File
@@ -0,0 +1,10 @@
.module wc_key_f10
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_key_f10
_wc_key_f10::
push ix
ld a, #0x26
call WC_ENTRY
pop ix
ret
+10
View File
@@ -0,0 +1,10 @@
.module wc_key_f2
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_key_f2
_wc_key_f2::
push ix
ld a, #0x1E
call WC_ENTRY
pop ix
ret
+10
View File
@@ -0,0 +1,10 @@
.module wc_key_f3
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_key_f3
_wc_key_f3::
push ix
ld a, #0x1F
call WC_ENTRY
pop ix
ret
+10
View File
@@ -0,0 +1,10 @@
.module wc_key_f4
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_key_f4
_wc_key_f4::
push ix
ld a, #0x20
call WC_ENTRY
pop ix
ret
+10
View File
@@ -0,0 +1,10 @@
.module wc_key_f5
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_key_f5
_wc_key_f5::
push ix
ld a, #0x21
call WC_ENTRY
pop ix
ret
+10
View File
@@ -0,0 +1,10 @@
.module wc_key_f6
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_key_f6
_wc_key_f6::
push ix
ld a, #0x22
call WC_ENTRY
pop ix
ret
+10
View File
@@ -0,0 +1,10 @@
.module wc_key_f7
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_key_f7
_wc_key_f7::
push ix
ld a, #0x23
call WC_ENTRY
pop ix
ret
+10
View File
@@ -0,0 +1,10 @@
.module wc_key_f8
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_key_f8
_wc_key_f8::
push ix
ld a, #0x24
call WC_ENTRY
pop ix
ret
+10
View File
@@ -0,0 +1,10 @@
.module wc_key_f9
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_key_f9
_wc_key_f9::
push ix
ld a, #0x25
call WC_ENTRY
pop ix
ret
+10
View File
@@ -0,0 +1,10 @@
.module wc_key_home
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_key_home
_wc_key_home::
push ix
ld a, #0x1B
call WC_ENTRY
pop ix
ret
+10
View File
@@ -0,0 +1,10 @@
.module wc_key_ins
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_key_ins
_wc_key_ins::
push ix
ld a, #0x55
call WC_ENTRY
pop ix
ret
+10
View File
@@ -0,0 +1,10 @@
.module wc_key_left
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_key_left
_wc_key_left::
push ix
ld a, #0x13
call WC_ENTRY
pop ix
ret
+10
View File
@@ -0,0 +1,10 @@
.module wc_key_pgdn
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_key_pgdn
_wc_key_pgdn::
push ix
ld a, #0x1A
call WC_ENTRY
pop ix
ret
+10
View File
@@ -0,0 +1,10 @@
.module wc_key_pgup
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_key_pgup
_wc_key_pgup::
push ix
ld a, #0x19
call WC_ENTRY
pop ix
ret
+10
View File
@@ -0,0 +1,10 @@
.module wc_key_right
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_key_right
_wc_key_right::
push ix
ld a, #0x14
call WC_ENTRY
pop ix
ret
+10
View File
@@ -0,0 +1,10 @@
.module wc_key_shift
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_key_shift
_wc_key_shift::
push ix
ld a, #0x28
call WC_ENTRY
pop ix
ret
+10
View File
@@ -0,0 +1,10 @@
.module wc_key_space
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_key_space
_wc_key_space::
push ix
ld a, #0x10
call WC_ENTRY
pop ix
ret
+10
View File
@@ -0,0 +1,10 @@
.module wc_key_tab
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_key_tab
_wc_key_tab::
push ix
ld a, #0x15
call WC_ENTRY
pop ix
ret
+10
View File
@@ -0,0 +1,10 @@
.module wc_key_up
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_key_up
_wc_key_up::
push ix
ld a, #0x11
call WC_ENTRY
pop ix
ret
+10
View File
@@ -0,0 +1,10 @@
.module wc_key_wait_any
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_key_wait_any
_wc_key_wait_any::
push ix
ld a, #0x2F
call WC_ENTRY
pop ix
ret
+10
View File
@@ -0,0 +1,10 @@
.module wc_key_wait_release
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_key_wait_release
_wc_key_wait_release::
push ix
ld a, #0x2E
call WC_ENTRY
pop ix
ret
+16
View File
@@ -0,0 +1,16 @@
.module wc_load256
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_load256
_wc_load256::
push ix
ld ix, #0
add ix, sp
ld b, 4(ix) ; B = blocks (1 byte on stack)
; HL = dest (already in HL)
ld a, #0x3C
call WC_ENTRY
pop ix
pop hl ; HL = return address
inc sp ; discard 1-byte 'blocks' arg
jp (hl) ; return (callee cleans stack arg)
+16
View File
@@ -0,0 +1,16 @@
.module wc_load512
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_load512
_wc_load512::
push ix
ld ix, #0
add ix, sp
ld b, 4(ix) ; B = blocks (1 byte on stack)
; HL = dest (sdcccall(1) first uint16 → HL)
ld a, #0x30
call WC_ENTRY
pop ix
pop hl ; HL = return address
inc sp ; discard 1-byte 'blocks' arg
jp (hl) ; return (callee cleans stack arg)
+11
View File
@@ -0,0 +1,11 @@
.module wc_loadnone
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_loadnone
_wc_loadnone::
push ix
ld b, a
ld a, #0x3D
call WC_ENTRY
pop ix
ret
+34
View File
@@ -0,0 +1,34 @@
.module wc_mezz
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_mezz
_wc_mezz::
push ix
push hl ; save win (HL = 1st arg)
ld ix, #0
add ix, sp
ld a, 6(ix) ; A = msg_num
ld l, 7(ix)
ld h, 8(ix) ; HL = str
ld d, 9(ix) ; D = y
ld e, 10(ix) ; E = x
exx
ex af, af' ; A' = msg_num
ld l, 0(ix)
ld h, 1(ix) ; HL = win
push hl
pop ix ; IX = win
exx ; HL=str, D=y, E=x
ld a, #0x0C
call WC_ENTRY
ld a, d ; return: next row
pop hl ; remove saved win
pop ix
; callee cleans 5 bytes
pop hl ; HL = return address
inc sp
inc sp
inc sp
inc sp
inc sp
jp (hl)
+10
View File
@@ -0,0 +1,10 @@
.module wc_mkdir
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_mkdir
_wc_mkdir::
push ix
ld a, #0x49
call WC_ENTRY
pop ix
ret
+10
View File
@@ -0,0 +1,10 @@
.module wc_mkfile
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_mkfile
_wc_mkfile::
push ix
ld a, #0x48
call WC_ENTRY
pop ix
ret
+11
View File
@@ -0,0 +1,11 @@
.module wc_mng0_pl
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_mng0_pl
_wc_mng0_pl::
ex af, af'
push ix
ld a, #0x4E
call WC_ENTRY
pop ix
ret
+11
View File
@@ -0,0 +1,11 @@
.module wc_mng0vpl
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_mng0vpl
_wc_mng0vpl::
ex af, af'
push ix
ld a, #0x50
call WC_ENTRY
pop ix
ret
+11
View File
@@ -0,0 +1,11 @@
.module wc_mng8_pl
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_mng8_pl
_wc_mng8_pl::
ex af, af'
push ix
ld a, #0x4F
call WC_ENTRY
pop ix
ret
+11
View File
@@ -0,0 +1,11 @@
.module wc_mng8vpl
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_mng8vpl
_wc_mng8vpl::
ex af, af'
push ix
ld a, #0x51
call WC_ENTRY
pop ix
ret
+11
View File
@@ -0,0 +1,11 @@
.module wc_mngc_pl
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_mngc_pl
_wc_mngc_pl::
ex af, af'
push ix
ld a, #0x00
call WC_ENTRY
pop ix
ret
+11
View File
@@ -0,0 +1,11 @@
.module wc_mngcvpl
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_mngcvpl
_wc_mngcvpl::
ex af, af'
push ix
ld a, #0x41
call WC_ENTRY
pop ix
ret
+11
View File
@@ -0,0 +1,11 @@
.module wc_mngv_pl
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_mngv_pl
_wc_mngv_pl::
ex af, af'
push ix
ld a, #0x40
call WC_ENTRY
pop ix
ret
+18
View File
@@ -0,0 +1,18 @@
.module wc_nork
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_nork
_wc_nork::
push ix
ld ix, #0
add ix, sp
ld a, 4(ix) ; A = val (from stack)
ex af, af' ; A' = val
; HL = addr (1st arg, already in HL)
ld a, #0x0A
call WC_ENTRY
pop ix
; callee cleans 1 byte (val)
pop hl
inc sp
jp (hl)
+15
View File
@@ -0,0 +1,15 @@
.module wc_prm_pl
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_prm_pl
_wc_prm_pl::
ex af, af'
push ix
ld a, #0x53
call WC_ENTRY
; Z=нет параметра → вернуть 0xFF, иначе A=номер опции
jr nz, _wc_prm_pl_end
ld a, #0xFF
_wc_prm_pl_end:
pop ix
ret
+34
View File
@@ -0,0 +1,34 @@
.module wc_prsrw
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_prsrw
_wc_prsrw::
push ix
push hl ; save win (HL = 1st arg)
push de ; save str (DE = 2nd arg)
ld ix, #0
add ix, sp
ld b, 11(ix) ; B = len_hi
ld c, 10(ix) ; C = len_lo
ld d, 8(ix) ; D = y
ld e, 9(ix) ; E = x
ld l, 0(ix)
ld h, 1(ix) ; HL = str
exx
ld l, 2(ix)
ld h, 3(ix) ; HL = win
push hl
pop ix ; IX = win
exx ; BC=len, DE=y|x, HL=str
ld a, #0x03
call WC_ENTRY
pop de ; remove saved str
pop hl ; remove saved win
pop ix ; restore caller IX
; callee cleans: y(1)+x(1)+len(2) = 4 bytes
pop hl ; HL = return address
inc sp
inc sp
inc sp
inc sp
jp (hl)
+50
View File
@@ -0,0 +1,50 @@
.module wc_prsrw_attr
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_prsrw_attr
_wc_prsrw_attr::
push ix
push hl ; save win (HL = 1st arg)
push de ; save str (DE = 2nd arg)
ld ix, #0
add ix, sp
; ── вызов #03 (prsrw) ──────────────────────────────────
ld b, 11(ix) ; B = len_hi
ld c, 10(ix) ; C = len_lo
ld d, 8(ix) ; D = y
ld e, 9(ix) ; E = x
ld l, 0(ix)
ld h, 1(ix) ; HL = str
exx
ld l, 2(ix)
ld h, 3(ix) ; HL = win
ld a, 12(ix) ; A = attr (IX всё ещё → фрейм)
push af ; сохраняем attr на стеке
push hl
pop ix ; IX = win
exx ; BC=len, DE=y|x, HL=str; HL'=win
ld a, #0x03
call WC_ENTRY
; ── вызов #04 (priat) ──────────────────────────────────
pop af ; A = attr
ex af, af' ; A' = attr
exx ; HL = win (из HL'), BC=len, DE=y|x
push hl
pop ix ; IX = win
exx ; restore BC=len, DE=y|x
ld a, #0x04
call WC_ENTRY
pop de ; remove saved str
pop hl ; remove saved win
pop ix ; restore caller IX
; callee cleans 5 bytes: y(1)+x(1)+len(2)+attr(1)
pop hl ; HL = return address
inc sp
inc sp
inc sp
inc sp
inc sp
jp (hl)
+12
View File
@@ -0,0 +1,12 @@
.module wc_prwow
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_prwow
_wc_prwow::
push ix
push hl
pop ix
ld a, #0x01
call WC_ENTRY
pop ix
ret
+10
View File
@@ -0,0 +1,10 @@
.module wc_rename
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_rename
_wc_rename::
push ix
ld a, #0x4A
call WC_ENTRY
pop ix
ret
+8
View File
@@ -0,0 +1,8 @@
.module wc_resident_call
.area _CODE
.globl _wc_resident_call
_wc_resident_call::
ex de, hl ; HL = addr (from DE = 2nd arg)
; A = page (1st arg, already in A)
call 0x6028 ; resident call — returns here
ret
+7
View File
@@ -0,0 +1,7 @@
.module wc_resident_jump
.area _CODE
.globl _wc_resident_jump
_wc_resident_jump::
ex de, hl ; HL = addr (from DE = 2nd arg)
; A = page (1st arg, already in A)
jp 0x6020 ; resident jump — never returns!
+12
View File
@@ -0,0 +1,12 @@
.module wc_rresb
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_rresb
_wc_rresb::
push ix
push hl
pop ix
ld a, #0x02
call WC_ENTRY
pop ix
ret
+16
View File
@@ -0,0 +1,16 @@
.module wc_save512
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_save512
_wc_save512::
push ix
ld ix, #0
add ix, sp
ld b, 4(ix)
; HL = src (DON'T ex de, hl!)
ld a, #0x31
call WC_ENTRY
pop ix
pop hl
inc sp
jp (hl)
+33
View File
@@ -0,0 +1,33 @@
.module wc_scrlwow
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_scrlwow
_wc_scrlwow::
push ix
push hl ; save win (HL = 1st arg)
ld ix, #0
add ix, sp
ld a, 10(ix) ; A = flags
ld b, 8(ix) ; B = h
ld c, 9(ix) ; C = w
ld d, 6(ix) ; D = y
ld e, 7(ix) ; E = x
exx
ex af, af' ; A' = flags
ld l, 0(ix)
ld h, 1(ix)
push hl
pop ix ; IX = win
exx ; BC=h/w, DE=y/x
ld a, #0x54
call WC_ENTRY
pop hl ; remove saved win
pop ix
; callee cleans 5 bytes
pop hl
inc sp
inc sp
inc sp
inc sp
inc sp
jp (hl)
+11
View File
@@ -0,0 +1,11 @@
.module wc_stream
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_stream
_wc_stream::
push ix
ld d, a
ld a, #0x39
call WC_ENTRY
pop ix
ret
+38
View File
@@ -0,0 +1,38 @@
.module wc_strset
.area _CODE
.globl _wc_strset
_wc_strset::
push ix
ld ix, #0
add ix, sp
ld a, 4(ix) ; c (из-за push ix)
pop ix
; записываем первый байт
ld (hl), a
ld b, d
ld c, e
; len == 1 → всё
dec bc
ld a, b
or c
jr z, _wc_strset_done
; DE = HL + 1
push hl
pop de
inc de
; BC = len - 1 уже
ldir
_wc_strset_done:
; очистка стека
pop bc
inc sp
push bc
ret
+11
View File
@@ -0,0 +1,11 @@
.module wc_tentry
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_tentry
_wc_tentry::
push ix
ex de, hl ; DE = addr (SDCC HL → WC DE)
ld a, #0x33
call WC_ENTRY
pop ix
ret
+30
View File
@@ -0,0 +1,30 @@
.module wc_tmrkdfl
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_tmrkdfl
_wc_tmrkdfl::
push ix
push hl ; save panel (HL = 1st arg)
push de ; save filenum (DE = 2nd arg)
ld ix, #0
add ix, sp
ld e, 8(ix)
ld d, 9(ix) ; DE = namebuf (from stack)
ld l, 0(ix)
ld h, 1(ix) ; HL = filenum (from saved DE)
exx
ld l, 2(ix)
ld h, 3(ix) ; HL = panel (from saved HL)
push hl
pop ix ; IX = panel
exx ; HL=filenum, DE=namebuf
ld a, #0x36
call WC_ENTRY
pop de ; remove saved filenum
pop hl ; remove saved panel
pop ix
; callee cleans 2 bytes (namebuf)
pop hl
inc sp
inc sp
jp (hl)
+12
View File
@@ -0,0 +1,12 @@
.module wc_turbopl
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_turbopl
_wc_turbopl::
push ix
ld c, l ; C = param (2-й аргумент)
ld b, a ; B = mode (1-й аргумент)
ld a, #0x0E
call WC_ENTRY
pop ix
ret
+30
View File
@@ -0,0 +1,30 @@
.module wc_txtpr
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_txtpr
_wc_txtpr::
push ix ; (1) save caller IX
push hl ; (2) save win ptr (HL = 1st arg)
push de ; (3) save str ptr (DE = 2nd arg)
ld ix, #0
add ix, sp
ld d, 9(ix) ; D = y
ld e, 8(ix) ; E = x
ld l, 0(ix)
ld h, 1(ix) ; HL = str ptr
exx ; shadow: HL'=str, D'=y, E'=x
ld l, 2(ix)
ld h, 3(ix) ; HL = win ptr
push hl
pop ix ; IX = win ptr
exx ; restore HL=str, D=y, E=x
ld a, #0x0B
call WC_ENTRY
ld a, d ; A = return: next Y
pop de ; (3) restore DE
pop hl ; (2) restore HL
pop ix ; (1) restore IX
pop hl ; HL = return address
inc sp ; } discard caller's push bc (2 bytes: y, x)
inc sp ; }
jp (hl) ; return (callee cleans stack args)
+15
View File
@@ -0,0 +1,15 @@
.module wc_yn
.area _CODE
WC_ENTRY = 0x6006
.globl _wc_yn
_wc_yn::
ex af, af'
push ix
ld a, #0x08
call WC_ENTRY
ld a, #0
jr nz, _wc_yn_end
inc a
_wc_yn_end:
pop ix
ret