scr_x: таблица готовых значений на весь диапазон, включая отрицательные
Первая версия крыла только 0..255 байтовой таблицей x/7 по тождеству
8x/7 == x + x/7. Это было мимо: obj_x = 2*fwd - 116 уходит в минус, как
только fwd < 58 (левее x_bump[5]) — то есть у ЛЕВОЙ КРОМКИ комнаты, и там
мы продолжали звать __divsint.
Границы взяты из данных, а не на глаз: kid_data.bin даёт dx кадров Кида
-5..+10, стража -2..+10; при Char.x типа uint8_t и render_dx из
{-140,0,+140} полный диапазон obj_x = -416..695. SCRX[1152] кроет
-448..703 — деление стало недостижимым, оставлено страховкой.
Хранится ГОТОВОЕ значение (int16_t), а не x/7: байтовая таблица вдвое
меньше, но со знаковыми значениями требует расширения знака плюс
16-битного сложения — те же такты, что лишний add hl,hl при 2-байтном
индексе. Кодоген проверен: индекс полный 16-битный (грабли
sdcc_z80_const_ptr_index_bug обойдены отдельной uint16_t-переменной),
~130 тактов номинала против ~1 000 у __divsint.
Банк 4: 7 336 -> 9 394 из 16 384 (свободно 6 990). Таблица сверена
питоном обратно из .c (1 152 записи), правило генерации «усечение к нулю»
закреплено тестом geom_mul8div7_trunc_to_zero на целевом компиляторе.
tests-host: [geom] 1961 -> 1992, все 5 наборов прошли.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -72,16 +72,21 @@ TC_TEST(geom_y_to_row_matches_formula)
|
||||
}
|
||||
}
|
||||
|
||||
/* calc_screen_x_coord (seg008:2602) считается в pop_cdraw.c таблицей DIV7 по
|
||||
* тождеству 8x/7 == x + x/7 (7x делится нацело, поэтому усечение обеих частей
|
||||
* совпадает). Само тождество и проверяем — оно и есть неочевидная часть;
|
||||
* таблица DIV7 сгенерирована как x/7 и живёт в банке 4, сюда не линкуется. */
|
||||
TC_TEST(geom_mul8div7_identity)
|
||||
/* calc_screen_x_coord (seg008:2602) считается в pop_cdraw.c ГОТОВОЙ таблицей
|
||||
* SCRX (банк 4, сюда не линкуется). Таблица сгенерирована питоном по правилу
|
||||
* «усечение К НУЛЮ»: значение = знак(x) * (|x|*8 / 7). Проверяем ИМЕННО это
|
||||
* правило на целевом компиляторе: если бы __divsint у SDCC округлял иначе
|
||||
* (к минус бесконечности), вся отрицательная половина таблицы уехала бы на
|
||||
* пиксель, а поймалось бы это только глазами на левой кромке комнаты. */
|
||||
TC_TEST(geom_mul8div7_trunc_to_zero)
|
||||
{
|
||||
int16_t x;
|
||||
/* obj_x = 2*fwd − 116; со сдвигом шва (∓140) уходит в −406..684. */
|
||||
for (x = -420; x <= 700; x++)
|
||||
TC_EQ((int16_t)(x * 8 / 7), (int16_t)(x + x / 7));
|
||||
/* Полный диапазон obj_x по данным кадров: −416..695 (см. шапку scr_x). */
|
||||
for (x = -448; x <= 703; x++) {
|
||||
int16_t want = (int16_t)(((x < 0) ? -x : x) * 8 / 7);
|
||||
if (x < 0) want = (int16_t)-want;
|
||||
TC_EQ((int16_t)(x * 8 / 7), want);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---- PRNG: сверка asm-LCG с эталонной формулой ---------------------- */
|
||||
@@ -166,7 +171,7 @@ int main(void)
|
||||
TC_RUN(geom_yland_rows);
|
||||
TC_RUN(geom_y_to_row);
|
||||
TC_RUN(geom_y_to_row_matches_formula);
|
||||
TC_RUN(geom_mul8div7_identity);
|
||||
TC_RUN(geom_mul8div7_trunc_to_zero);
|
||||
#if POP_PRANDOM_EXACT
|
||||
TC_RUN(geom_lcg_matches_reference);
|
||||
TC_RUN(geom_lcg_seed_zero);
|
||||
|
||||
Reference in New Issue
Block a user