libbgi: gfx_pal_sync + палитра ↔ файл (gfx_pal_fsave/fload); все PASS

- gfx_pal_sync(): палитра страницы 1 := палитре 0 (все 256 записей,
  чанками по 64 через общий буфер _gfx_pal_buf в W2) — обязательный
  шаг дабл-буфера (грабли examples/space: без него флип на страницу 1
  чёрный).  examples/space переведён на хелпер.
- gfx_pal_fsave(pal, path): 256 записей × 4 Б (B,G,R,0 — родной формат
  BIOS $A4) = 1024 Б.
- gfx_pal_fload(pal, path): принимает и усечённый файл (64 Б = палитра
  16 цветов) — грузит сколько есть, остальные слоты не трогает;
  возвращает число записей.

tests/palfile (MAME dev, все PASS): fsave; fload восстанавливает
испорченные слоты (n=256); усечённый файл на 2 записи чинит только их
(n=2, слот 2 не тронут); sync чинит испорченный слот палитры 1.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-13 16:51:49 +03:00
parent 8792594c5a
commit 6dea6955c2
10 changed files with 224 additions and 8 deletions
+9
View File
@@ -0,0 +1,9 @@
/*
* _gfx_pal_buf — общий строковый буфер палитровых хелперов
* (gfx_pal_sync / gfx_pal_fload / gfx_pal_fsave): 64 записи × 4 байта.
* Статик в W2 — BIOS $A4 требует буфер в #4000-#BFFF. Отдельный
* data-модуль: линкуется только с самими хелперами (DCE).
*/
#include "../_bgi.h"
uint8_t _gfx_pal_buf[_GFX_PAL_CHUNK * 4];
+40
View File
@@ -0,0 +1,40 @@
/*
* gfx_pal_fload — загрузить палитру pal_num (0..3) из файла формата
* gfx_pal_fsave (записи по 4 байта: B, G, R, 0). Файл может быть
* УСЕЧЁН: грузится столько полных записей, сколько есть (палитра
* 16-цветной картинки — файл 64 байта), остальные слоты не трогаются.
* Возврат: число загруженных записей (0..256) или -1 + errno.
*
* NB: заливает только палитру pal_num — для дабл-буфера после загрузки
* в 0 звать gfx_pal_sync().
*/
#include <fcntl.h>
#include <unistd.h>
#include "../_bgi.h"
int gfx_pal_fload(uint8_t pal_num, const char *path)
{
int fd, n, total = 0;
uint8_t start = 0;
fd = open(path, O_RDONLY);
if (fd < 0)
return -1;
while (total < 256) {
uint8_t entries;
n = read(fd, _gfx_pal_buf, _GFX_PAL_CHUNK * 4);
if (n < 0) { close(fd); return -1; }
entries = (uint8_t)(n / 4);
if (!entries)
break;
gfx_pal_load(pal_num, start, entries, _gfx_pal_buf);
start += entries;
total += entries;
if (n < (int)(_GFX_PAL_CHUNK * 4))
break; /* конец файла */
}
close(fd);
return total;
}
+30
View File
@@ -0,0 +1,30 @@
/*
* gfx_pal_fsave — сохранить палитру pal_num (0..3) в файл: 256 записей
* по 4 байта (B, G, R, 0 — родной формат BIOS $A4), итого 1024 байта.
* Пишется чанками по 64 записи через общий буфер. 0 — OK; -1 + errno.
*/
#include <fcntl.h>
#include <unistd.h>
#include "../_bgi.h"
int gfx_pal_fsave(uint8_t pal_num, const char *path)
{
uint8_t k, start = 0;
int fd, rc = 0;
fd = creat(path, 0);
if (fd < 0)
return -1;
for (k = 0; k < 4; k++) {
gfx_pal_get(pal_num, start, _GFX_PAL_CHUNK, _gfx_pal_buf);
if (write(fd, _gfx_pal_buf, _GFX_PAL_CHUNK * 4)
!= _GFX_PAL_CHUNK * 4) {
rc = -1;
break;
}
start += _GFX_PAL_CHUNK;
}
close(fd);
return rc;
}
+20
View File
@@ -0,0 +1,20 @@
/*
* gfx_pal_sync — палитра страницы 1 := палитре страницы 0 (все 256
* записей, чанками по 64 через общий буфер). Обязательный шаг
* seamless-дабл-буфера: у каждой графической страницы СВОЯ палитра, и
* без синхронизации флип на страницу 1 показывает сцену чёрной
* (грабли examples/space 2026-07-13). Звать после initgraph и после
* любых правок палитры 0 (gfx_pal_set/load/reset).
*/
#include "../_bgi.h"
void gfx_pal_sync(void)
{
uint8_t k, start = 0;
for (k = 0; k < 4; k++) {
gfx_pal_get(0, start, _GFX_PAL_CHUNK, _gfx_pal_buf);
gfx_pal_load(1, start, _GFX_PAL_CHUNK, _gfx_pal_buf);
start += _GFX_PAL_CHUNK;
}
}