diff --git a/applications/PoP/roomtest/pop_kid.c b/applications/PoP/roomtest/pop_kid.c index 01700e8..8d05048 100644 --- a/applications/PoP/roomtest/pop_kid.c +++ b/applications/PoP/roomtest/pop_kid.c @@ -90,7 +90,21 @@ void pop_kid_free(void) extern void _gfx_w0_isr(void); #define KD_DATA_OFF 0x100u -#define KD_FRAMES(i) ((const uint8_t *)(KD_DATA_OFF + KID_BIN_FRAMES_OFF) + (uint16_t)(i) * 5u) +/* Адрес кадра i в замапленной странице. Считаем В uint16_t и кастуем ОДИН + * раз: запись `(const uint8_t *)CONST + (uint16_t)i * 5u` SDCC 4.5 собирает + * НЕВЕРНО — умножение делает в 16 битах (add hl,hl / add hl,bc), а потом + * берёт только МЛАДШИЙ байт результата и подставляет старший байт константы + * (`ld c,l` / `inc b`). Для кадров i >= 52 (i*5 >= 256) адрес уезжает на + * −256*k, и cur_frame наполняется чужой строкой таблицы: у бега/шага/подъёма + * пропадал бит FRAME_NEEDS_FLOOR, и Kid проваливался сквозь пол. + * Артефакт: .sprinter-cc-roomtest/pop_kid.asm, функция load_frame. */ +static const uint8_t *kd_frame_ptr(uint8_t i) +{ + uint16_t off = (uint16_t)i; + off += (uint16_t)(off << 2); /* i*5 = i + i*4, без умножения */ + off += (uint16_t)(KD_DATA_OFF + KID_BIN_FRAMES_OFF); + return (const uint8_t *)off; +} #define KD_SEQ(cs) (*((const uint8_t *)(KD_DATA_OFF + KID_BIN_SEQTBL_OFF) + \ (uint16_t)((cs) - SEQTBL_BASE))) /* Байт seqtbl по адресу оригинала (база SEQTBL_BASE); ТОЛЬКО под замапленной @@ -142,7 +156,7 @@ void pop_kid_data_free(void) * cur_frame. Звать ТОЛЬКО когда страница данных замаплена в W0. */ static void load_frame(void) { - const uint8_t *f = KD_FRAMES(Kid.frame); + const uint8_t *f = kd_frame_ptr(Kid.frame); cur_frame.image = f[0]; cur_frame.dx = (int8_t)f[1]; cur_frame.dy = (int8_t)f[2];