/* * pop_geom.h — общая геометрия PoP и PRNG оригинала. * * Сюда сведено то, что раньше дублировалось по модулям (x_bump/y_land в * pop_kid и pop_map, y_to_row в pop_bg и pop_map, 32-битный LCG в pop_bg и * pop_trob). Кроме экономии это ФУНДАМЕНТ bank-safe API: модуль живёт в * W1/W2 и не трогает графику, поэтому его может звать и главный цикл, и * резидент W3, и будущий __banked-код стражей (docs/layout_plan_v2.md §4). */ #ifndef POP_GEOM_H #define POP_GEOM_H #include #define FIRST_ONSCREEN_COLUMN 5 /* индекс col 0 комнаты в x_bump */ #define TILE_SIZEX 14 /* ширина тайла в координатах персонажа */ #define TILE_SIZEY 63 /* высота ряда */ /* x_bump (data.h): левая граница колонки в координатах персонажа; колонка * комнаты col = x_bump[col + FIRST_ONSCREEN_COLUMN]. y_land: пол ряда * (индекс row+1; [0] — ряд «над комнатой»). */ extern const int16_t pop_x_bump[20]; extern const int16_t pop_y_land[5]; /* y_to_row_mod4 (seg006): ряд по координате y с оборотом mod 4 (−1 = полоса * над комнатой, 3 = под комнатой). */ int8_t pop_y_to_row(int16_t y); /* prandom (порт seg009:321). Сид ВНЕШНИЙ: у стен (раскладка кладки) и у * анимаций тайлов (фаза факелов) свои последовательности, смешивать их * нельзя. * * ДВА генератора, выбор через POP_PRANDOM_EXACT (см. pop_geom.c): * 0 (по умолчанию) — xorshift16 + шаг Вейля. Быстрый: ни одного * умножения. Последовательность ОТЛИЧАЕТСЯ от SDLPoP, то есть другая * раскладка кладки и другие броски в боёвке — статистически * эквивалентные, но не те же самые; * 1 — LCG оригинала (s*214013+2531011) бит-в-бит. Для сверки картинки * с эталоном. Дороже: даже посчитанный 16-битными половинами (без * __mullong, который один стоил 8 430 тактов — замер в MAME) он * обходится в ~7 000 тактов на вызов. * * Состояние — две 16-битные половины, а не unsigned long: иначе SDCC на * умножении зовёт __mullong. */ typedef struct { uint16_t lo, hi; } pop_rnd_t; #ifndef POP_PRANDOM_EXACT #define POP_PRANDOM_EXACT 0 #endif uint16_t pop_prandom(pop_rnd_t *seed, uint16_t maxv); /* Сид из 16-битного числа (старшая половина = 0). */ #define pop_prandom_set(s, v) do { (s).lo = (uint16_t)(v); (s).hi = 0; } while (0) #endif