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,11 @@
# Матрица влияния W3/EMM на длинный F_FIRST/F_NEXT.
PROJ_ROOT := $(abspath $(CURDIR)/../../../..)
EXAMPLE := p3map
MEMORY := big
ALLOCS ?= 3000
EXTRA_FLAGS := --safe --max-allocs $(ALLOCS) --bank 1=bank1_enum.c
include $(PROJ_ROOT)/app.mk
$(EXE): Makefile bank1_enum.c
@@ -0,0 +1,90 @@
/*
* bank1_enum.c — отделяет влияние адреса ffblk от переключений W3.
*
* Весь перебор исполняется при подключённом BANK1, а диагностический DTA
* занимает последние 256 байт W1. Это историческая матрица, доказавшая,
* что ни адрес DTA, ни чтение/запись W3 не снимают предел DSS. mode=0 не
* трогает W3, mode=1 читает байт EMM, mode=2 пишет 24 байта EMM.
*/
#include <stdint.h>
#include <errno.h>
#include <dir.h>
#include <sprinter_mem.h>
#define FIND_ATTRS (FA_RDONLY | FA_HIDDEN | FA_SYSTEM | FA_DIREC | FA_ARCH)
__at (0x7F00) static ffblk_t find_buf;
/* Копии wrapper находятся в том же W1, что и цикл. Так проверяется не
* только адрес ffblk, но и адрес самой инструкции RST/возврата из DSS. */
static int p3_ffirst_local(const char *pattern, ffblk_t *buf,
uint8_t attrib) __naked
{
(void)pattern; (void)buf; (void)attrib;
__asm
ld iy, #2
add iy, sp
ld a, 0 (iy)
push ix
ld bc, #0x0119
rst #0x10
pop ix
pop hl
inc sp
jr c, p3_ffirst_fail$
ld de, #0
jp (hl)
p3_ffirst_fail$:
call __errno_set
ld de, #-1
jp (hl)
__endasm;
}
static int p3_fnext_local(ffblk_t *buf) __naked
{
(void)buf;
__asm
push ix
ex de, hl
ld c, #0x1A
rst #0x10
pop ix
jr c, p3_fnext_fail$
ld de, #0
ret
p3_fnext_fail$:
call __errno_set
ld de, #-1
ret
__endasm;
}
uint16_t p3_enum_mode(uint8_t mode, uint8_t page, int *end_errno) __banked
{
uint16_t count = 0u;
uint8_t payload[24];
uint16_t offset;
errno = 0;
if ((mode >= 3u ?
p3_ffirst_local("*.*", &find_buf, FIND_ATTRS) :
ffirst("*.*", &find_buf, FIND_ATTRS)) == 0) {
for (;;) {
count++;
if (mode == 1u) {
payload[0] = bank_load_byte(page, 0u);
} else if (mode == 2u || mode == 4u) {
offset = (uint16_t)(((count - 1u) % 640u) * 24u);
bank_write(page, offset, payload, 24u);
}
errno = 0;
if ((mode >= 3u ? p3_fnext_local(&find_buf) :
fnext(&find_buf)) != 0) break;
if (count == 2000u) break;
}
}
*end_errno = errno;
return count;
}
@@ -0,0 +1,56 @@
/* p3map.c — экранный отчёт матрицы длинного перебора каталога. */
#include <stdio.h>
#include <stdint.h>
#include <errno.h>
#include <unistd.h>
#include <conio.h>
#include <sprinter_mem.h>
uint16_t p3_enum_mode(uint8_t mode, uint8_t page, int *end_errno) __banked;
int main(void)
{
uint8_t block;
uint8_t page;
uint8_t mode;
uint16_t count;
int end_errno;
(void)settextmode(TEXT_MODE_80x32);
clrscr_attr(0x17u);
gotoxy(0u, 0u);
textattr(0x1Fu);
cputs("P3 F_NEXT / W3 matrix\r\n\r\n");
textattr(0x17u);
block = mem_alloc_pages(1u);
page = block ? mem_get_page(block, 0u) : 0u;
printf("EMM: block=%u page=%02X errno=%d\n",
(unsigned)block, (unsigned)page, errno);
if (!block || !page) goto done;
for (mode = 0u; mode != 5u; mode++) {
errno = 0;
if (chdir("\\BIGDIR") != 0) {
printf("mode %u: chdir error=%d\n", (unsigned)mode, errno);
break;
}
count = p3_enum_mode(mode, page, &end_errno);
printf("mode %u: count=%u end_errno=%d\n",
(unsigned)mode, (unsigned)count, end_errno);
errno = 0;
if (chdir("\\") != 0) {
printf("root after mode %u: error=%d\n",
(unsigned)mode, errno);
break;
}
}
mem_free_block(block);
done:
textattr(0x1Eu);
cputs("\r\nProbe stopped; MAME test will take a snapshot.");
for (;;) (void)getkey();
}