PoP roomtest: pop_bg и pop_map в банки; --dataseg BANKn стал опцией
Резидента --w3 больше нет: отрисовка (pop_bg + pop_gdraw) уехала в БАНК 2, физика/коллизия (pop_map) — в БАНК 3. Куча W1/W2 1294 -> 6750 Б. Что это разблокировало. Резидент был тупиком: из банка он недостижим ни прямо, ни транзитивно, поэтому pop_map (самый крупный модуль, 5.8 КБ) в банк было не увести — он зовёт mob-отрисовку. Проверено, что банк->банк РАБОТАЕТ: ___sdcc_bcall_ehl читает страницу окна портом 0xE2 и кладёт её на СТЕК своего кадра (runtime/bank.s), поэтому вложенность корректна по построению. Подтверждено в MAME цепочкой W1 -> банк1 -> банк2 -> банк1: nested=124 after=8, ровно ожидаемое. Значит развязка mob'а (самое рисковое место, loose-полы) НЕ понадобилась — pop_map зовёт pop_bg трамплином. Правила вызовов проверены на сгенерированном asm и записаны в memory sdcc_banked_call_rules: трамплин выбирает ОБЪЯВЛЕНИЕ (__banked), а не раскладка — даже внутри одного .c между __banked функциями он есть. Внутрибанковые функции оставлены непомеченными и зовутся напрямую, в т.ч. через границу файла (pop_gdraw -> pop_fore_over_char). sprinter-cc: --dataseg BANKn БОЛЬШЕ НЕ ставится по умолчанию. Раньше вся писучая память банкового модуля уезжала в страницу банка и снаружи не читалась (проверено на .map: глобал лёг по 0x0001C000) — грабли на каждом переносе. Теперь данные банков по умолчанию в общем _DATA (W1/W2, замаплен всегда), а прежнее поведение — по явному --bank-data. Замеры (комната 3, Kid + страж; кадр Sprinter в турбо = 430 000 тактов): до переноса 338 508 (0.79 кадра) + pop_bg в банк 2 347 100 (+2.5 %) + pop_map в банк 3 371 100 (+9.6 % к исходному, 0.86 кадра) Плата — трамплины (~654 такта на вызов, ~30 вызовов за кадр). При пейсинге в 3 кадра это 29 % логического кадра, но запас до ОДНОГО кадра всего ~59 000 тактов — под звук его надо возвращать (следующий шаг: батчить кроссбанковые вызовы, начиная с pop_redraw_needed). Профилирование бордюром включено по умолчанию (make PROF=0 выключает) и переведено на реально работающие биты: бит 0 (красный) у бордюра Sprinter ИГНОРИРУЕТСЯ, поэтому различимых состояний четыре и значения обязаны быть чётными — 0 чёрный (ждём vsync), 2 синий (логика), 4 зелёный (фон), 6 циан (спрайты). Раньше нечётные номера сливались и полосы не читались. Проверено в MAME: комнаты 1/3 рисуются как прежде, бег и коллизия работают, в комнате 12 плиты проваливаются со щебнем — то есть цепочка loose банк3 -> банк2 живая. Полосы бордюра в комнате 3: логика 73 строки, фон 64, спрайты 128, свободно 23. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -28,6 +28,7 @@
|
||||
* есть то, что понадобится стражам, чиста от графики. Разделение mob на
|
||||
* логику и отрисовку — задел следующей фазы. */
|
||||
#include "pop_bg.h"
|
||||
#include "pop_state.h"
|
||||
#include "pop_trob.h" /* room_modif + trob-список (пики/ворота) */
|
||||
|
||||
/* ---- Тайлы / действия / seq id (подмножество PoP) ------------------ */
|
||||
@@ -149,13 +150,13 @@ uint8_t pop_ceil_fell; /* 0 = нет; иначе col+1 провал
|
||||
|
||||
uint8_t pop_debris_at; /* 0 = нет; иначе tilepos+1 нового щебня в ЭТОЙ комнате */
|
||||
|
||||
void pop_map_set_above(uint8_t *above_row2_fg) { g_above = above_row2_fg; }
|
||||
void pop_map_set_above(uint8_t *above_row2_fg) __banked { g_above = above_row2_fg; }
|
||||
|
||||
void pop_map_set(uint8_t *fg) { g_fg = fg; }
|
||||
void pop_map_set(uint8_t *fg) __banked { g_fg = fg; }
|
||||
|
||||
void pop_map_set_room(uint8_t room) { g_room = room; }
|
||||
void pop_map_set_room(uint8_t room) __banked { g_room = room; }
|
||||
|
||||
void pop_kid_hp_reset(void) { hitp_curr = 3; pop_kid_dead = 0; }
|
||||
void pop_kid_hp_reset(void) __banked { hitp_curr = 3; pop_kid_dead = 0; }
|
||||
|
||||
/* take_hp (seg006:06BD, только Kid): count>=hitp → смерть (return 1). */
|
||||
static uint8_t take_hp(uint8_t count)
|
||||
@@ -166,7 +167,7 @@ static uint8_t take_hp(uint8_t count)
|
||||
}
|
||||
|
||||
void pop_map_set_edges(uint8_t left, uint8_t right, uint8_t up, uint8_t down,
|
||||
const uint8_t *lcol_fg, const uint8_t *rcol_fg)
|
||||
const uint8_t *lcol_fg, const uint8_t *rcol_fg) __banked
|
||||
{
|
||||
g_link_l = left; g_link_r = right; g_link_u = up; g_link_d = down;
|
||||
if (lcol_fg) { uint8_t i; for (i = 0; i < 6; i++) g_lcol[i] = lcol_fg[i]; }
|
||||
@@ -587,7 +588,7 @@ static int edge_classify(int d)
|
||||
return d;
|
||||
}
|
||||
|
||||
int pop_edge_distance(void)
|
||||
int pop_edge_distance(void) __banked
|
||||
{
|
||||
uint8_t t; int d;
|
||||
determine_col();
|
||||
@@ -629,7 +630,7 @@ int pop_edge_distance(void)
|
||||
return distance_to_edge_weight();
|
||||
}
|
||||
|
||||
uint8_t pop_edge_type(void) { return g_edge_type; }
|
||||
uint8_t pop_edge_type(void) __banked { return g_edge_type; }
|
||||
|
||||
/* ---- Прыжок вверх с зацепом (seg005 check_jump_up и производные) --- *
|
||||
* pop_jump_up_seq выбирает seq для ↑ в стойке: чистый прыжок (seq_28 в
|
||||
@@ -682,7 +683,7 @@ static uint8_t jump_up_or_grab(void)
|
||||
return grab_up_with_floor_behind();
|
||||
}
|
||||
|
||||
uint8_t pop_jump_up_seq(void)
|
||||
uint8_t pop_jump_up_seq(void) __banked
|
||||
{
|
||||
uint8_t through = get_tile_above_char();
|
||||
get_tile_front_above_char(); /* g_curr_tile = спереди-сверху */
|
||||
@@ -697,7 +698,7 @@ uint8_t pop_jump_up_seq(void)
|
||||
|
||||
/* Стена впереди достаточно близко для стопа бега? Детект (без сдвига —
|
||||
* позицию держит check_bumped=in_wall). d<=2: передний край почти у грани. */
|
||||
int pop_wall_ahead(void)
|
||||
int pop_wall_ahead(void) __banked
|
||||
{
|
||||
int d = pop_edge_distance();
|
||||
return (g_edge_type == EDGE_WALL && d <= 2);
|
||||
@@ -708,7 +709,7 @@ int pop_wall_ahead(void)
|
||||
* тайловые предикаты + выбор seq (+ выравнивание Kid.x). */
|
||||
|
||||
/* grab_timer истёк — можно подтягиваться? */
|
||||
uint8_t pop_hang_grab_ready(void) { return grab_timer == 0; }
|
||||
uint8_t pop_hang_grab_ready(void) __banked { return grab_timer == 0; }
|
||||
|
||||
/* can_climb_up (seg005:09DF): тайл над персонажем — обычный подъём (seq_10)
|
||||
* либо подъём к ЗАКРЫТОЙ калитке/зеркалу/чомперу (seq_73 = «влез и съехал
|
||||
@@ -716,7 +717,7 @@ uint8_t pop_hang_grab_ready(void) { return grab_timer == 0; }
|
||||
* curr_tile2 == tiles_4_gate && direction != right && modif >> 2 < 6
|
||||
* — под поднятой решёткой (modif >> 2 >= 6) подъём обычный. Без проверки
|
||||
* модификатора Kid срывался и с открытых ворот. */
|
||||
uint8_t pop_hang_climb_up_seq(void)
|
||||
uint8_t pop_hang_climb_up_seq(void) __banked
|
||||
{
|
||||
uint8_t t = get_tile_above_char();
|
||||
if (((t == TILE_MIRROR || t == TILE_CHOMPER) && Kid.direction == 0) ||
|
||||
@@ -728,7 +729,7 @@ uint8_t pop_hang_climb_up_seq(void)
|
||||
|
||||
/* Shift в висе: 1 = висит у стены/двери (caller играет seq_25); -1 =
|
||||
* сорваться (hang_fall); 0 = сверху пол, остаётся висеть (ничего). */
|
||||
int8_t pop_hang_wall(void)
|
||||
int8_t pop_hang_wall(void) __banked
|
||||
{
|
||||
uint8_t t = get_tile_at_char();
|
||||
if (Kid.action != ACT_HANGSTRAIGHT &&
|
||||
@@ -743,7 +744,7 @@ int8_t pop_hang_wall(void)
|
||||
/* hang_fall (seg005:0A46): сорваться. Нет пола ни сзади, ни под
|
||||
* персонажем — seq_23 (отпустить и падать); иначе прижать к стене (-7)
|
||||
* и seq_11 (встать, конец спуска). Меняет Kid.x, возвращает seq. */
|
||||
uint8_t pop_hang_fall_seq(void)
|
||||
uint8_t pop_hang_fall_seq(void) __banked
|
||||
{
|
||||
uint8_t behind = get_tile_behind_char();
|
||||
uint8_t at;
|
||||
@@ -760,7 +761,7 @@ uint8_t pop_hang_fall_seq(void)
|
||||
* либо спуск seq_68 через зацеп, либо отступ от передней кромки), 0 =
|
||||
* приседать. Меняет Kid.x. Kid развёрнут от края (край сзади) у кромки
|
||||
* пола + под соседним тайлом есть за что зацепиться → спуск на этаж вниз. */
|
||||
uint8_t pop_down_action(void)
|
||||
uint8_t pop_down_action(void) __banked
|
||||
{
|
||||
if (!tile_is_floor(get_tile_infrontof_char()) && distance_to_edge_weight() < 3) {
|
||||
Kid.x = (uint8_t)char_dx_forward(5); /* у передней кромки — отступ */
|
||||
@@ -805,7 +806,7 @@ static void do_pickup(int8_t obj_type, uint8_t tilepos)
|
||||
|
||||
/* proc_get_object (seg006:16CB): эффект поднятого предмета. Зовётся из
|
||||
* play_seq по опкоду SEQ_GET_ITEM с аргументом 1 (pop_kid). */
|
||||
void pop_proc_get_object(void)
|
||||
void pop_proc_get_object(void) __banked
|
||||
{
|
||||
if (pickup_obj_type == -1) {
|
||||
pop_have_sword = 1; /* в оригинале have_sword = -1 */
|
||||
@@ -821,7 +822,7 @@ void pop_proc_get_object(void)
|
||||
/* check_get_item + get_item (seg005:061F/073E). Возврат: 0 — предмета нет
|
||||
* (управление идёт обычной веткой); 1 — присесть (caller зовёт crouch());
|
||||
* 2 — поднять меч (caller ставит seq_91). */
|
||||
uint8_t pop_get_item_action(void)
|
||||
uint8_t pop_get_item_action(void) __banked
|
||||
{
|
||||
uint8_t t;
|
||||
int8_t icol;
|
||||
@@ -1113,7 +1114,7 @@ static void do_knock(int tile_row)
|
||||
/* check_knock (seg003:0706): по флагу knock (ставит play_seq на seqtbl-
|
||||
* командах KNOCK_UP/DOWN) тряхнуть ряд. KNOCK_DOWN (knock=-1, приземление) →
|
||||
* ряд curr_row; KNOCK_UP (knock=+1) → ряд curr_row-1. */
|
||||
void pop_check_knock(void)
|
||||
void pop_check_knock(void) __banked
|
||||
{
|
||||
if (knock) {
|
||||
do_knock(Kid.curr_row - (knock > 0));
|
||||
@@ -1124,7 +1125,7 @@ void pop_check_knock(void)
|
||||
/* Сброс состояния loose (при смене комнаты): pop_loose_modif/bake/rest
|
||||
* индексируются позицией тайла и не должны утечь из старой комнаты в новую.
|
||||
* Плюс останавливает падающий кусок (pop_bg). */
|
||||
void pop_loose_reset(void)
|
||||
void pop_loose_reset(void) __banked
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 30; i++) {
|
||||
@@ -1183,7 +1184,7 @@ static void check_loose_fall_on_kid(void)
|
||||
|
||||
/* animate_loose (seg007:0CBA) + перерисовка изменившихся тайлов на ТЕКУЩЕЙ
|
||||
* (back) странице. Звать из основного цикла ПОСЛЕ set_draw_page(back). */
|
||||
void pop_loose_tick(void)
|
||||
void pop_loose_tick(void) __banked
|
||||
{
|
||||
int pos;
|
||||
/* row/col ведём бегущими счётчиками, а НЕ через pos/10 и pos%10: у Z80
|
||||
@@ -1280,7 +1281,7 @@ void pop_loose_tick(void)
|
||||
* check_spike_below колонки берутся get_tile_div_mod БЕЗ −7.
|
||||
*
|
||||
* Возврат: КОМНАТНЫЙ y верхней границы (0 = клипа нет). */
|
||||
int pop_clip_char_top(int obj_x, int obj_y, uint16_t w, uint16_t h)
|
||||
int pop_clip_char_top(int obj_x, int obj_y, uint16_t w, uint16_t h) __banked
|
||||
{
|
||||
static const int16_t y_clip[5] = { -60, 3, 66, 129, 192 };
|
||||
int wh = ((int)w + 1) >> 1; /* char_width_half */
|
||||
@@ -1481,7 +1482,7 @@ static void check_spike_below(void)
|
||||
}
|
||||
}
|
||||
|
||||
void pop_phys_tick(void)
|
||||
void pop_phys_tick(void) __banked
|
||||
{
|
||||
if (pop_kid_dead) return; /* труп на пиках — без физики (только seq смерти) */
|
||||
if (grab_timer) grab_timer--;
|
||||
|
||||
Reference in New Issue
Block a user