pop_blit_b: границы экрана двумя беззнаковыми сравнениями вместо четырёх знаковых

Проверка «спрайт целиком на экране» стояла как
  pb_x >= 0 && pb_top >= 0 && pb_x + pb_w <= 320 && pb_top + pb_h <= 256
— четыре знаковых 16-битных сравнения, а знаковое у SDCC z80 разворачивается
в пару sbc плюс jp PO / xor 0x80 / jp P (видно в листинге).

Беззнаковая форма делает то же двумя: отрицательная координата в
беззнаковом виде становится очень большой и проваливает условие так же,
как проверка >= 0, а верхняя граница переносится в правую часть вместе со
сложением.  Границы неотрицательны по построению: pb_w и pb_h не больше
255, значит 320-pb_w >= 65 и 256-pb_h >= 1.

Работа кадра 438 978 -> 438 600.  Немного, но идиома стандартная и код
не усложняется.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-19 17:52:43 +03:00
parent b3e754a66b
commit 892f005ca5
+12 -2
View File
@@ -622,8 +622,18 @@ void pop_blit_b(atlas_t *a, uint8_t idx, int x, int ybottom)
return;
}
/* pb_w<256 && pb_h<256 больше не проверяем — гарантировано типом. */
if (pb_x >= 0 && pb_top >= 0 &&
pb_x + (int)pb_w <= 320 && pb_top + (int)pb_h <= 256) {
/* «Целиком на экране?» — ДВУМЯ беззнаковыми сравнениями вместо
* четырёх знаковых. Отрицательная координата в беззнаковом виде
* становится очень большой и проваливает то же условие, что
* проверка `>= 0`, а верхняя граница переносится в правую часть,
* так что сложение уходит вместе с ней. Знаковое сравнение у
* SDCC z80 стоит дорого: пара `sbc` плюс `jp PO / xor 0x80 / jp P`
* на каждое (видно в листинге).
*
* Границы правой части неотрицательны по построению: pb_w и pb_h
* не больше 255, значит 320-pb_w >= 65 и 256-pb_h >= 1. */
if ((unsigned int)pb_x <= (unsigned int)(320 - (int)pb_w) &&
(unsigned int)pb_top <= (unsigned int)(256 - (int)pb_h)) {
if (pop_upside) gfx_blit_noclip_vflip(pb_x, pb_top, pb_img);
else gfx_blit_noclip(pb_x, pb_top, pb_img);
} else {