/* * 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(); }