8e389c03f8
Реализовать двухпанельный Commander от платформенного PoC до этапов P6-P20: EMM-каталог, сортировку и выбор, операции с файлами и деревьями, транзакционное копирование, метаданные, политику конфликтов и предварительную проверку свободного места. Добавить проектную документацию, HDD/MAME-сценарии и проверенные артефакты. Расширить libc операцией bank_write_page, исправлением режима O_RDONLY и связанными регрессионными проверками.
144 lines
3.5 KiB
C
144 lines
3.5 KiB
C
/*
|
||
* p1_sys.c — отсутствующие в libc сырые ESTEX wrappers для проб P1.
|
||
*
|
||
* ABI SDCC __sdcccall(1): int возвращается в DE, uint8_t — в A. Каждый RST
|
||
* сохраняет IX, потому что IX callee-saved. Ошибка ESTEX (CF=1, код в A)
|
||
* проходит через общий libc-хелпер __errno_set.
|
||
*/
|
||
|
||
#include <stdint.h>
|
||
#include "p1_platform.h"
|
||
|
||
uint8_t p1_exec_exit_code;
|
||
|
||
/* ESTEX DSKINFO $03:
|
||
* A=disk (0xFF=current)
|
||
* out: A=sectors/cluster, HL=total clusters,
|
||
* DE=free clusters, BC=bytes/sector.
|
||
*/
|
||
int p1_disk_info(uint8_t disk, P1DiskInfo *out) __naked
|
||
{
|
||
(void)disk;
|
||
(void)out;
|
||
__asm
|
||
;; A = disk, DE = out.
|
||
push ix
|
||
push de
|
||
ld c, #0x03
|
||
rst #0x10
|
||
jr c, _p1_di_error
|
||
|
||
;; Забрать out в IX, пока все выходные регистры DSS ещё целы.
|
||
pop ix
|
||
ld 0 (ix), a
|
||
ld 1 (ix), l
|
||
ld 2 (ix), h
|
||
ld 3 (ix), e
|
||
ld 4 (ix), d
|
||
ld 5 (ix), c
|
||
ld 6 (ix), b
|
||
pop ix
|
||
ld de, #0
|
||
ret
|
||
|
||
_p1_di_error:
|
||
pop de ; снять сохранённый out
|
||
pop ix
|
||
call __errno_set
|
||
ld de, #-1
|
||
ret
|
||
__endasm;
|
||
}
|
||
|
||
/* ESTEX EXEC $40. path_mode: 0 — короткое имя/PATH, 1 — передан путь.
|
||
* На успехе код дочерней программы сохраняется в p1_exec_exit_code.
|
||
*/
|
||
int p1_exec(uint8_t path_mode, const char *path) __naked
|
||
{
|
||
(void)path_mode;
|
||
(void)path;
|
||
__asm
|
||
;; A = path_mode, DE = path. Такой порядок не оставляет 8-битный
|
||
;; второй аргумент на стеке в ABI SDCC.
|
||
push ix
|
||
ld b, a
|
||
ex de, hl
|
||
ld c, #0x40
|
||
rst #0x10
|
||
pop ix
|
||
jr c, _p1_exec_error
|
||
ld (_p1_exec_exit_code), a
|
||
ld de, #0
|
||
ret
|
||
|
||
_p1_exec_error:
|
||
call __errno_set
|
||
ld de, #-1
|
||
ret
|
||
__endasm;
|
||
}
|
||
|
||
/* ESTEX WAIT $42 возвращает код последней завершившейся программы в A. */
|
||
uint8_t p1_wait_code(void) __naked
|
||
{
|
||
__asm
|
||
push ix
|
||
ld c, #0x42
|
||
rst #0x10
|
||
pop ix
|
||
ret
|
||
__endasm;
|
||
}
|
||
|
||
/* ESTEX WINREST $5A:
|
||
* D=row, E=col, H=height, L=width, B=physical page,
|
||
* IX=0xC000+offset.
|
||
*
|
||
* Раскладка аргументов подтверждена существующим tests/winrest и mdview2:
|
||
* A=row, L=col, стек +2 height, +3 width, +4 page, +5..6 offset.
|
||
*/
|
||
void p1_winrest(uint8_t row, uint8_t col, uint8_t height, uint8_t width,
|
||
uint8_t page, uint16_t offset) __naked
|
||
{
|
||
(void)row;
|
||
(void)col;
|
||
(void)height;
|
||
(void)width;
|
||
(void)page;
|
||
(void)offset;
|
||
__asm
|
||
ld iy, #2
|
||
add iy, sp
|
||
ld d, a
|
||
ld e, l
|
||
|
||
push ix
|
||
ld l, 3 (iy)
|
||
ld h, 4 (iy)
|
||
ld bc, #0xC000
|
||
add hl, bc
|
||
push hl
|
||
pop ix
|
||
|
||
ld h, 0 (iy)
|
||
ld a, 1 (iy)
|
||
ld l, a
|
||
ld a, 2 (iy)
|
||
ld b, a
|
||
ld c, #0x5A
|
||
di
|
||
rst #0x10
|
||
ei
|
||
pop ix
|
||
|
||
;; Снять 5 стековых байтов height,width,page,offset.
|
||
pop hl
|
||
inc sp
|
||
inc sp
|
||
inc sp
|
||
inc sp
|
||
inc sp
|
||
jp (hl)
|
||
__endasm;
|
||
}
|