Volkov: добавить Sprinter Commander

Реализовать двухпанельный Commander от платформенного PoC до этапов P6-P20: EMM-каталог, сортировку и выбор, операции с файлами и деревьями, транзакционное копирование, метаданные, политику конфликтов и предварительную проверку свободного места.

Добавить проектную документацию, HDD/MAME-сценарии и проверенные артефакты. Расширить libc операцией bank_write_page, исправлением режима O_RDONLY и связанными регрессионными проверками.
This commit is contained in:
2026-09-10 10:45:30 +03:00
parent 05bcd8197e
commit 8e389c03f8
870 changed files with 21310 additions and 25 deletions
@@ -0,0 +1,143 @@
/*
* 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;
}