From 79bcabde949da3cb4ef39f93c3a5dfeace631748 Mon Sep 17 00:00:00 2001 From: Alexander Petrov Date: Wed, 19 Aug 2026 18:00:19 +0300 Subject: [PATCH] =?UTF-8?q?=D0=93=D0=B0=D0=B1=D0=B0=D1=80=D0=B8=D1=82?= =?UTF-8?q?=D1=8B=20=D1=81=D0=BF=D1=80=D0=B0=D0=B9=D1=82=D0=BE=D0=B2=20?= =?UTF-8?q?=D0=B2=20=D0=B1=D0=B0=D0=B9=D1=82=D0=B0=D1=85:=20uint16=5Ft=20-?= =?UTF-8?q?>=20uint8=5Ft=20=D0=B2=20=D1=81=D0=BB=D0=BE=D1=82=D0=B5=20?= =?UTF-8?q?=D0=BE=D1=82=D1=80=D0=B8=D1=81=D0=BE=D0=B2=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Замечание пользователя: спрайты наших атласов не крупнее 64x64, а w/h почти везде были uint16_t. Это уже записано в памяти проекта (pop_sprite_size_limits: весь игровой кадр PoP <= 56x63; больше 255 только восемь полноэкранных подложек титров, а они через слот персонажа не проходят). Переведены в uint8_t: w/h, ow/oh, fpw/fph, cw/ch в pop_cdraw_t, параметры cd_overlay_add и cd_clip_add, локали w/h/vis_w в pop_char_draw и cd_splash, и чтение габарита из шапки ленты (было двухбайтным сложением со сдвигом). Эффект: лёгкая позиция 438 600 -> 438 324 (там персонажи не рисуются, поэтому почти ничего), тяжёлая — циан 181 404 -> 180 270. Плюс 24 байта _DATA на двух слотах. Скромно, но код от этого не запутаннее, а честнее: тип теперь отражает реальный диапазон. Проверено в MAME — бой идёт, хвостов и обрезков нет. Co-Authored-By: Claude Opus 5 --- applications/PoP/roomtest/pop_cdraw.c | 56 ++++++++++++++++----------- applications/PoP/roomtest/pop_cdraw.h | 8 ++-- 2 files changed, 38 insertions(+), 26 deletions(-) diff --git a/applications/PoP/roomtest/pop_cdraw.c b/applications/PoP/roomtest/pop_cdraw.c index b3c0c66..d77d6ad 100644 --- a/applications/PoP/roomtest/pop_cdraw.c +++ b/applications/PoP/roomtest/pop_cdraw.c @@ -258,7 +258,7 @@ static int scr_x(int x) * страницы. Оба мелкие и в одном кадре встречаются редко — их объединение * дешевле третьего heal-слота. */ static void cd_overlay_add(pop_cdraw_t *s, uint8_t dp, int x, int y, - uint16_t w, uint16_t h) + uint8_t w, uint8_t h) { if (!s->ovalid[dp]) { s->ox[dp] = x; s->oy[dp] = y; s->ow[dp] = w; s->oh[dp] = h; @@ -273,14 +273,14 @@ static void cd_overlay_add(pop_cdraw_t *s, uint8_t dp, int x, int y, if (x + (int)w > x1) x1 = x + (int)w; if (y + (int)h > y1) y1 = y + (int)h; s->ox[dp] = x0; s->oy[dp] = y0; - s->ow[dp] = (uint16_t)(x1 - x0); s->oh[dp] = (uint16_t)(y1 - y0); + s->ow[dp] = (uint8_t)(x1 - x0); s->oh[dp] = (uint8_t)(y1 - y0); } } /* Добавить прямоугольник в окно fore-клипа слота (объединение «спрайт + * накладные»): по нему fore-проход возвращает куски тайлов и по нему же * расширяет перебор колонок/рядов. */ -static void cd_clip_add(pop_cdraw_t *s, int x, int y, uint16_t w, uint16_t h) +static void cd_clip_add(pop_cdraw_t *s, int x, int y, uint8_t w, uint8_t h) { if (!s->cw) { s->cx = x; s->cy = y; s->cw = w; s->ch = h; @@ -292,8 +292,8 @@ static void cd_clip_add(pop_cdraw_t *s, int x, int y, uint16_t w, uint16_t h) if (y < s->cy) s->cy = y; if (x + (int)w > x1) x1 = x + (int)w; if (y + (int)h > y1) y1 = y + (int)h; - s->cw = (uint16_t)(x1 - s->cx); - s->ch = (uint16_t)(y1 - s->cy); + s->cw = (uint8_t)(x1 - s->cx); + s->ch = (uint8_t)(y1 - s->cy); } } @@ -469,7 +469,7 @@ static void cd_splash(pop_cdraw_t *s, uint8_t who, const atlas_t *pages, const atlas_t *ap; uint8_t aidx; const uint8_t *img; - uint16_t w, h; + uint8_t w, h; int qx = fp_x, qy = obj_y; int fw = (Char.direction < 0) ? -5 : 5; /* obj_dx_forward(5) */ @@ -491,8 +491,12 @@ static void cd_splash(pop_cdraw_t *s, uint8_t who, const atlas_t *pages, qx = scr_x(qx + fw); /* calc_screen_x_coord */ img = (const uint8_t *)atlas_image(ap, aidx); gfx_w0_map(ap->page); - w = (uint16_t)(img[0] | ((uint16_t)img[1] << 8)); - h = (uint16_t)(img[2] | ((uint16_t)img[3] << 8)); + /* Габарит БАЙТАМИ: спрайты персонажей и накладных не крупнее 64x64 + * (memory pop_sprite_size_limits — весь игровой кадр PoP <= 56x63), + * а 16-битные w/h заставляли SDCC держать их в стековом кадре и + * считать каждое сравнение парой загрузок. */ + w = img[0]; + h = img[2]; if (w && h) { int top = qy - (int)h + 1; uint8_t flip = (uint8_t)(Char.direction >= 0); @@ -503,15 +507,15 @@ static void cd_splash(pop_cdraw_t *s, uint8_t who, const atlas_t *pages, if (top + rows > 192) rows = 192 - top; if (rows <= 0) return; gfx_set_bank(GFX_BANK_SPRITE); - if (pop_onscreen_cols(qx, top + POP_YOFF, w, (uint16_t)rows)) + if (pop_onscreen_cols(qx, top + POP_YOFF, w, (uint8_t)rows)) gfx_blit_cols_part_noclip(qx, top + POP_YOFF, img, flip, (uint8_t)skip, (uint8_t)rows); else gfx_blit_cols_part(qx, top + POP_YOFF, img, flip, skip, rows); gfx_set_bank(GFX_BANK_NORMAL); dp = gfx_get_draw_page() & 1; - cd_overlay_add(s, dp, qx, top, w, (uint16_t)rows); - cd_clip_add(s, qx, top, w, (uint16_t)rows); + cd_overlay_add(s, dp, qx, top, w, (uint8_t)rows); + cd_clip_add(s, qx, top, w, (uint8_t)rows); } } @@ -523,7 +527,7 @@ void pop_char_draw(uint8_t who) __banked const atlas_t *pages; const uint8_t *img; uint8_t npages, page, idx, dp, flip, hurt, lskip; - uint16_t w, h, vis_w; + uint8_t w, h, vis_w; int obj_x, obj_y, fp_x, fwd, top, bx, skip, rows, ct, cr; int bcut; /* срез СНИЗУ (clip_char в перевёрнутом виде) */ @@ -625,8 +629,12 @@ void pop_char_draw(uint8_t who) __banked } gfx_w0_map(vpg); } - w = (uint16_t)(img[0] | ((uint16_t)img[1] << 8)); - h = (uint16_t)(img[2] | ((uint16_t)img[3] << 8)); + /* Габарит БАЙТАМИ: спрайты персонажей и накладных не крупнее 64x64 + * (memory pop_sprite_size_limits — весь игровой кадр PoP <= 56x63), + * а 16-битные w/h заставляли SDCC держать их в стековом кадре и + * считать каждое сравнение парой загрузок. */ + w = img[0]; + h = img[2]; dp = gfx_get_draw_page() & 1; if (w && h) { /* Спрайты нарисованы ЛИЦОМ ВЛЕВО (как в оригинале); seg008:864 — @@ -683,7 +691,7 @@ void pop_char_draw(uint8_t who) __banked if (cr) { int avail = cr - bx; if (avail <= 0) vis_w = 0; /* весь спрайт за косяком */ - else if (avail < (int)w) vis_w = (uint16_t)avail; + else if (avail < (int)w) vis_w = (uint8_t)avail; } /* КЛИП ТЕНИ СЛЕВА (seg008:1699): на уровне зеркала она может * показываться ТОЛЬКО СПРАВА от него — @@ -712,7 +720,7 @@ void pop_char_draw(uint8_t who) __banked if (lskip) /* тень у зеркала: срез слева */ gfx_blit_cols_part_wx(bx, top + POP_YOFF, img, flip, skip, rows, lskip, (uint8_t)(vis_w - lskip)); - else if (vis_w == w && pop_onscreen_cols(bx, top + POP_YOFF, w, (uint16_t)rows)) + else if (vis_w == w && pop_onscreen_cols(bx, top + POP_YOFF, w, (uint8_t)rows)) gfx_blit_cols_part_noclip(bx, top + POP_YOFF, img, flip, (uint8_t)skip, (uint8_t)rows); else @@ -723,9 +731,9 @@ void pop_char_draw(uint8_t who) __banked /* heal чистит ТОЛЬКО нарисованное: иначе стирается кромка пола над * срезом (мусор/дыра в кладке на второй странице дабл-буфера). */ s->x[dp] = bx + lskip; s->y[dp] = top; - s->w[dp] = (uint16_t)(vis_w - lskip); s->h[dp] = (uint16_t)rows; + s->w[dp] = (uint8_t)(vis_w - lskip); s->h[dp] = (uint8_t)rows; s->valid[dp] = (uint8_t)(rows != 0); - if (rows) cd_clip_add(s, bx, top, vis_w, (uint16_t)rows); + if (rows) cd_clip_add(s, bx, top, vis_w, (uint8_t)rows); s->fpw = w; s->fph = h; /* габарит КАДРА (не обрезанный): */ /* по нему считается футпринт */ } @@ -806,7 +814,7 @@ void pop_mirror_draw(int clip_top) __banked const kframe *fr = &kid_frame; const uint8_t *img; uint8_t page, idx, flip; - uint16_t w, h, vis_w; + uint8_t w, h, vis_w; int fwd, obj_x, obj_y, fp_x, bx, top, skip = 0, rows, cl; uint8_t lskip = 0; @@ -824,8 +832,12 @@ void pop_mirror_draw(int clip_top) __banked img = (const uint8_t *)atlas_image(&kidp[page], idx); gfx_w0_map(kidp[page].page); - w = (uint16_t)(img[0] | ((uint16_t)img[1] << 8)); - h = (uint16_t)(img[2] | ((uint16_t)img[3] << 8)); + /* Габарит БАЙТАМИ: спрайты персонажей и накладных не крупнее 64x64 + * (memory pop_sprite_size_limits — весь игровой кадр PoP <= 56x63), + * а 16-битные w/h заставляли SDCC держать их в стековом кадре и + * считать каждое сравнение парой загрузок. */ + w = img[0]; + h = img[2]; if (!w || !h) { gfx_w0_unmap(); return; } flip = (uint8_t)(Char.direction >= 0); bx = flip ? obj_x - (int)w : obj_x; @@ -946,7 +958,7 @@ void pop_hp_draw(void) __banked if (g_ok && Guard.charid != 0 && Guard.charid != CHARID_4_SKELETON && Guard.charid != CHARID_24_MOUSE && gd) { const uint8_t *img = (const uint8_t *)atlas_image(&gp[0], 0); - uint16_t w, h; + uint8_t w, h; gfx_w0_map(gp[0].page); w = (uint16_t)(img[0] | ((uint16_t)img[1] << 8)); h = (uint16_t)(img[2] | ((uint16_t)img[3] << 8)); diff --git a/applications/PoP/roomtest/pop_cdraw.h b/applications/PoP/roomtest/pop_cdraw.h index 25f233e..f05fb15 100644 --- a/applications/PoP/roomtest/pop_cdraw.h +++ b/applications/PoP/roomtest/pop_cdraw.h @@ -51,21 +51,21 @@ typedef struct { * видео-ОЗУ и своя ОЗУ-копия, поэтому heal обязан стирать спрайт именно * той страницы, в которую сейчас рисуем */ int x[2], y[2]; - uint16_t w[2], h[2]; + uint8_t w[2], h[2]; /* габарит: спрайты игры не крупнее 64x64 */ uint8_t valid[2]; /* НАКЛАДНЫЕ спрайты (клинок + брызги урона) — свой прямоугольник, не * объединение с персонажем: объединение сильно больше суммы двух * (клинок уходит вперёд-вверх), а heal стоит ровно по площади */ int ox[2], oy[2]; - uint16_t ow[2], oh[2]; + uint8_t ow[2], oh[2]; uint8_t ovalid[2]; /* габарит кадра для fore-прохода: fpx — ЛОГИЧЕСКАЯ X (до ×8/7), * fpy — низ спрайта; fpw == 0 — в этом кадре рисовать было нечего */ int fpx, fpy; - uint16_t fpw, fph; + uint8_t fpw, fph; /* окно fore-клипа слота (объединение «спрайт + накладные»), КОМНАТНЫЙ y */ int cx, cy; - uint16_t cw, ch; + uint8_t cw, ch; /* straddle: рендерное смещение по ЛОГИЧЕСКОЙ X, когда комната персонажа * не совпадает с отрисованной (порт xpos_in_drawn_room) */ int render_dx;