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,120 @@
/*
* p1_screen.c — визуальная проверка экранной EMM-страницы и WINREST.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <conio.h>
#include <sprinter_mem.h>
#include "p1_platform.h"
#define P1_SCREEN_W 80u
#define P1_SCREEN_H 32u
#define P1_ROW_BYTES 160u
#define P1_MARKER_OFF 0x2000u
static uint8_t row_buf[P1_ROW_BYTES];
static uint8_t marker_buf[2u * 20u * 2u];
static void row_clear(uint8_t attr)
{
uint8_t x;
for (x = 0; x < P1_SCREEN_W; x++) {
row_buf[(uint16_t)x * 2u] = ' ';
row_buf[(uint16_t)x * 2u + 1u] = attr;
}
}
static void row_text(uint8_t x, const char *text, uint8_t attr)
{
while (*text && x < P1_SCREEN_W) {
row_buf[(uint16_t)x * 2u] = (uint8_t)*text++;
row_buf[(uint16_t)x * 2u + 1u] = attr;
x++;
}
}
static void marker_build(void)
{
static const char top[] = "PARTIAL WINREST OK ";
static const char bot[] = "offset = 0x2000 ";
uint8_t x;
for (x = 0; x < 20; x++) {
marker_buf[(uint16_t)x * 2u] = (uint8_t)top[x];
marker_buf[(uint16_t)x * 2u + 1u] =
COLOR(COLOR_WHITE, COLOR_RED);
marker_buf[40u + (uint16_t)x * 2u] = (uint8_t)bot[x];
marker_buf[40u + (uint16_t)x * 2u + 1u] =
COLOR(COLOR_YELLOW, COLOR_RED);
}
}
int p1_test_screen(void)
{
uint8_t block;
uint8_t page;
uint8_t y;
p1_heading("WINREST: preparing EMM screen");
errno = 0;
block = mem_alloc_pages(1);
if (block == 0) {
printf("mem_alloc_pages failed: errno=%d\n", errno);
return -1;
}
page = mem_get_page(block, 0);
if (page == 0) {
printf("mem_get_page failed: errno=%d\n", errno);
mem_free_block(block);
return -1;
}
for (y = 0; y < P1_SCREEN_H; y++) {
/* Только яркие foreground 9..15 на синем: граница не должна
* исчезать из-за комбинации blue-on-blue вроде прежнего 0x11. */
uint8_t attr = COLOR((uint8_t)(COLOR_LIGHTBLUE + (y % 7u)),
COLOR_BLUE);
row_clear(attr);
row_buf[0] = (y == 0 || y == 31) ? '+' : '|';
row_buf[158] = (y == 0 || y == 31) ? '+' : '|';
if (y == 0 || y == 31) {
uint8_t x;
for (x = 1; x < 79; x++) row_buf[(uint16_t)x * 2u] = '-';
}
if (y == 2) row_text(4, "FULL 80x32 WINREST FROM EMM PAGE",
COLOR(COLOR_WHITE, COLOR_BLUE));
if (y == 4) row_text(4, "Rows have different foreground colours.",
COLOR(COLOR_YELLOW, COLOR_BLUE));
if (y == 6) row_text(4, "Expected: complete border, no shifted cells.",
COLOR(COLOR_YELLOW, COLOR_BLUE));
if (y == 28) row_text(4, "Press a key for partial-offset test.",
COLOR(COLOR_WHITE, COLOR_BLUE));
bank_write(page, (uint16_t)y * P1_ROW_BYTES,
row_buf, P1_ROW_BYTES);
}
marker_build();
bank_write(page, P1_MARKER_OFF, marker_buf, sizeof(marker_buf));
p1_winrest(0, 0, P1_SCREEN_H, P1_SCREEN_W, page, 0);
(void)getkey();
/* Две строки по 20 ячеек поверх середины полного экрана. */
p1_winrest(14, 30, 2, 20, page, P1_MARKER_OFF);
(void)getkey();
mem_free_block(block);
p1_heading("WINREST test finished");
cputs("Visual checks:\r\n");
cputs(" 1. Full 80x32 frame had no shifts or holes.\r\n");
cputs(" 2. Red/yellow 20x2 marker appeared at row 14, col 30.\r\n");
cputs(" 3. Marker text started at offset 0x2000.\r\n");
cputs("\r\nReturn PASS only records that both calls completed.\r\n");
return 0;
}