Габариты спрайтов в байтах: uint16_t -> uint8_t в слоте отрисовки
Замечание пользователя: спрайты наших атласов не крупнее 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 <noreply@anthropic.com>
This commit is contained in:
@@ -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));
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user