/* * gfx_putchar256 — символ шрифтом 8×8 в (x,y), mode 0x81 (байт на * пиксель). На ряд глифа (8 пикселей) пишем 8 байт: FG где бит 1, * BG где 0. Рендер ряда сам делает DI / W3 save+restore — вызывать * можно из любого контекста без скобок. */ #include "_gfx.h" /* Скретч рендера ряда — только этого модуля. */ static uint8_t txt_y; static uint8_t txt_row; /* битовый паттерн текущего ряда глифа */ static uint8_t txt_fg; static uint8_t txt_bg; static uint16_t txt_addr; /* VRAM-адрес ряда */ static void render_row_256(void) __naked { __asm di in a, (#0xE2) push af ld a, #0x50 out (#0xE2), a ld a, (_txt_y) out (#0x89), a ld hl, (_txt_addr) ld a, (_txt_fg) ld d, a ld a, (_txt_bg) ld e, a ld a, (_txt_row) ld b, #8 ; 8 пикселей в ряду rr256_loop: rla ; CY = старший бит, A <<= 1 jr nc, rr256_bg ld (hl), d ; FG jr rr256_next rr256_bg: ld (hl), e ; BG rr256_next: inc hl djnz rr256_loop pop af out (#0xE2), a ei ret __endasm; } void gfx_putchar256(int x, int y, char c, uint8_t fg, uint8_t bg) { _gfx_font_ensure(); if ((unsigned)x >= GFX_WIDTH || (unsigned)y >= GFX_HEIGHT) return; txt_fg = fg; txt_bg = bg; uint8_t cc = (uint8_t)c; uint16_t base = (uint16_t)(_gfx_addr_base + (unsigned)x); for (int r = 0; r < 8; r++) { int yy = y + r; if ((unsigned)yy >= GFX_HEIGHT) break; txt_y = (uint8_t)yy; txt_addr = base; /* Interleaved-раскладка: ряд r глифа cc — font[r*256 + cc]. */ txt_row = _gfx_font_ptr[r * 256 + cc]; render_row_256(); } }