Files
Sprinter-SDCC/libbgi/bgi256/_bgi_hspan_raw.c
T
snark13 9b1ce71130 libbgi: упростить safe-контроль span'ов + отсекать len==0
_bgi_vspan_raw: safe-версия (без GFX_NOCHECK) больше НЕ клиппит диапазон
y+len и не обрабатывает y<0 — проверяется только валидность x/y (как в
_bgi_hspan_raw).  Сознательный компромисс: safe ловит грубый выход за
экран по координате, но не частичный отрезок; y+len<=256 — обязанность
вызывающего.

Оба span'а: в safe добавлена проверка len==0 → return (иначе B=0 по
конвенции акселератора рисует «256»).  В fast (GFX_NOCHECK) проверка
вырезается — поведение прежнее (256 точек), задокументировано в шапках.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-10 15:16:53 +03:00

87 lines
4.2 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.
/*
* _bgi_hspan_raw — горизонтальная линия len пикселей от (x,y), mode 0x81,
* через Fill-burst'ы акселератора (до 256 байт за выстрел).
*
* Это «сырой» leaf-примитив: максимально тонкий, БЕЗ клиппинга. Всю
* защиту берёт на себя вызывающий (см. ОГРАНИЧЕНИЯ). Проверенный путь:
* _bgi_fill_span (клиппит сам) и _bgi_lineseg (ортогональ) → сюда.
*
* ---- ОГРАНИЧЕНИЯ ВЫЗОВА (ответственность вызывающего) --------------
* - W3-скобка: вызывать ТОЛЬКО между _bgi_begin/_bgi_end (W3 замаплен
* на видеобанк; DI/EI вокруг каждого выстрела ставит сам сегмент).
* - Клиппинга НЕТ. Требуется 0 <= x и x+len <= 320 (иначе burst
* вылезет за строку и затрёт соседнюю видеопамять). Отрицательный x
* и x+len>320 НЕ обрезаются — координаты обязаны быть уже валидны.
* - Диапазон len: 1..320. len==0: safe-версия (с проверками) тихо
* вернётся; fast (GFX_NOCHECK) из-за конвенции акселератора (B=0 =
* «256») отрисует 256 точек. len<0 / len>320 — UB.
* - Встроенная проверка (если НЕ задан GFX_NOCHECK) отсекает лишь
* грубый выход за экран по одной координате: (unsigned)y>=256 и
* (unsigned)x>=320 → тихий возврат. Это НЕ клиппинг диапазона —
* частичного отрезка/правого края не режет.
*
* ---- ABI ----------------------------------------------------------
* __sdcccall(1): x→HL, y→DE(E=y), len→стек(4/5(ix)), color→стек(6(ix)),
* __naked → callee-pops 3 байта аргументов (len + color) вручную.
* Значения уходят в _gfx_hfill256_segment через регистры (HL=addr,
* C=color, B=len, E=y) — без глобального скретча; сегмент клоббер только
* A/F, поэтому HL/E переживают выстрел (см. _gfx_hfill256.c).
*
* ---- Логика двух burst'ов (len 257..320) --------------------------
* Сначала 256 точек на addr (B=0), затем inc h (addr+256) и хвост
* (len-256) точек. Усечение len до младшего байта само даёт (len-256)
* для 257..320; при len==256 младший байт 0 → одиночный burst «256».
*/
#include "../_bgi.h"
void _bgi_hspan_raw(int x, int y, int len, uint8_t color) __naked
{
__asm
.globl __gfx_addr_base
.globl __gfx_hfill256_segment
push ix
ld ix, #0
add ix, sp
#ifndef GFX_NOCHECK
ld a, d
or a, a
jr NZ, hs_ret ; (unsigned)y >= 256
ld a, l
sub a, #0x40
ld a, h
sbc a, #0x01
jr NC, hs_ret ; (unsigned)x >= 320
ld a, 4 (ix)
or a, 5 (ix)
jr Z, hs_ret ; len == 0 (иначе B=0 «256»)
#endif
ld c, l
ld b, h ; BC = x
ld hl, (__gfx_addr_base)
add hl, bc ; HL = base + x
ld a, 6 (ix)
ld c, a ; C = color
ld a, 5 (ix)
or a, a
jr Z, hs_single ; len < 256
ld a, 4 (ix)
or a, a
jr Z, hs_single ; len == 256 (B=0)
;; 257..320: два burst-a
ld b, #0 ; 256
call __gfx_hfill256_segment
inc h ; addr + 256
hs_single:
ld a, 4 (ix)
ld b, a ; B = len (0 если ==256)
call __gfx_hfill256_segment
hs_ret:
pop ix
pop hl
pop af
inc sp
jp (hl)
__endasm;
}