Files
Sprinter-SDCC/libbgi/common/putimage.c
T
snark13 a823e7ee9c libbgi: блочные AND/OR/XOR акселератора (блит строками и колонками)
Акселератор умеет не только копировать блок, но и совмещать его с
приёмником: опкод `and/or/xor (hl)` между триггерами чтения и записи
переводит внутренний автомат из «буфер := память» в «буфер <op>= память».
Операция ортогональна направлению (гориз. LD L,L / верт. LD A,A), значит
одинаково работает и для row-major картинок, и для column-major спрайтов
персонажей с бесплатным флипом.

Полный набор, по образцу существующего копирующего:
- ядра bgi256/_bgi_blit_rows_op_raw.c и _bgi_blit_cols_op_raw.c;
- строками: gfx_blit_op / gfx_blit_part_op (через _gfx_blit_full_op);
- колонками: gfx_blit_cols_op / gfx_blit_cols_part_wx_op (skip/rows/
  skipw/maxw и flip — как у копирующего близнеца);
- putimage(XOR/OR/AND_PUT) переведён на accel, попиксельным остался
  только NOT_PUT — закрыт пункт 2d-1 docs/TODO.md.

Одна функция на три операции: опкод патчится SMC, как размер блока и
страйд, — ветвления в цикле нет.  Колоночный путь дороже строкового на
один OUT Port_Y: вертикальный op-burst шагает Port_Y, и перед записью
его надо вернуть на верх колонки (STOP обязателен — иначе fetch операнда
OUT перезапустит burst, memory/accel_operand_fetch_retrigger).

Две оговорки (в шапках модулей):
- операция ЧИТАЕТ ОЗУ-копию экрана, а не видео-ОЗУ, поэтому при банках
  0x54/0x5C совмещается с чистым фоном, а не с нарисованным поверх;
- аппаратная прозрачность #FF совместима с AND (нейтраль) и OR (#FF|bg =
  #FF, запись подавляется), но НЕ с XOR: там источник обязан хранить
  прозрачный пиксель как 0x00.

Проверка: tests/accop (новый) — 8/8 PASS в MAME, побайтно, источник с
разными значениями по строкам И колонкам + рамка вокруг; tests/bgi_img
получил две байтовые самопроверки (COPY==источник, XOR дважды == фон),
обе PASS.  make size-check: роста нет (эталон принят заново — kbdpoll
+63 Б приехал из прошлой сессии, воспроизводится и без этих правок).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 15:03:47 +03:00

59 lines
2.8 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* putimage — вывести образ bitmap левым-верхним углом в (left,top)
* операцией op. Заголовок буфера: uint16 width, uint16 height.
*
* COPY_PUT — через accel-ядро gfx_blit_part (block-copy строками, до
* 256 байт за burst; Фаза A спрайтового дизайна) — С КЛИППИНГОМ по
* экрану (superset поведения Turbo C, где выход за экран — UB) и
* с учётом текущего банка (gfx_set_bank: 0x58 даёт аппаратную
* прозрачность 0xFF, 0x54/0x5C — временный вывод).
*
* XOR/OR/AND_PUT — тоже через акселератор (gfx_blit_part_op, 2026-08-11;
* закрыт пункт 2d-1 docs/TODO.md): акселератор умеет блочные AND/OR/XOR
* между своим буфером и памятью приёмника, попиксельного цикла CPU больше
* нет. Клиппинг у них теперь ТОТ ЖЕ, что у COPY_PUT (раньше на этом пути
* клипа не было вовсе). Оговорки — в шапке common/_gfx_blit_full_op.c:
* операция читает ОЗУ-копию экрана (при банках 0x54/0x5C это чистый фон),
* а прозрачность #FF совместима с AND/OR, но не с XOR.
*
* NOT_PUT — по-прежнему по-пиксельно (пишем ~src): это не операция с
* приёмником, а инверсия источника, у акселератора такого режима нет.
* Клиппинга на этом пути НЕТ (per-pixel bounds-check только в safe).
*
* Буфер bitmap обязан лежать вне W3 (< 0xC000) — на время операции W3
* замаплен на видеобанк.
*/
#include "../_bgi.h"
void putimage(int left, int top, const void *bitmap, int op)
{
const uint8_t *p = (const uint8_t *)bitmap;
int w, h, x, y;
uint8_t gop;
w = p[0] | (p[1] << 8);
h = p[2] | (p[3] << 8);
if (w <= 0 || h <= 0) return;
switch (op) {
case COPY_PUT:
gfx_blit_part(left, top, bitmap, 0, 0, w, h);
return;
case XOR_PUT: gop = GFX_OP_XOR; break;
case OR_PUT: gop = GFX_OP_OR; break;
case AND_PUT: gop = GFX_OP_AND; break;
default: gop = 0; break; /* NOT_PUT — попиксельно ниже */
}
if (gop) {
gfx_blit_part_op(left, top, bitmap, 0, 0, w, h, gop);
return;
}
p += 4;
_bgi_begin();
for (y = 0; y < h; y++)
for (x = 0; x < w; x++)
_bgi_plot_raw(left + x, top + y, (uint8_t)~(*p++));
_bgi_end();
}