5d31ed086f
MEM-COLD3, шаг 1-2 из плана разгрузки резидента: * pop_redraw.c целиком -> банк 7 (к pop_room.c: он и есть единственный потребитель разбора пометок). Два модуля в одном банке линкуются в один сегмент — проверено на .map (BANK7 7928 -> 8556). * pop_level.c расколот по частоте вызова: горячая половина (чтение тайлов, связи, дверные таблицы, живые стражи — зовут все банки, местами на каждый тайл) осталась в резиденте, холодная (чтение файла уровня, разбор комнаты, рестарт, потабличные различия) уехала в pop_level_cold.c -> банк 8. Общее состояние объявлено в _pop_level.h: данные банковых модулей всё равно линкуются в общий _DATA, в банк уехал только КОД. Побочно найден баг кодогена SDCC: `return 1;` из ветки не кладёт 1 в A — до __banked он маскировался случайным ненулевым остатком в A. Репро и разбор — docs/bugs/sdcc-z80-ret-const-lost/, стаб t_char починен одним выходом через переменную. Аудит всех .asm roomtest: других мест нет. _CODE 25628 -> 23005, куча 902 -> 3525 Б. tests-host 6/6.
76 lines
3.9 KiB
C
76 lines
3.9 KiB
C
/*
|
||
* _pop_level.h — ВНУТРЕННИЙ контракт между двумя половинами уровня:
|
||
*
|
||
* pop_level.c — ГОРЯЧАЯ (резидент W1): чтение тайлов/связей/дверных
|
||
* таблиц, живое состояние стражей. Её зовут все банки
|
||
* и кадровый путь главного цикла, местами на каждый тайл.
|
||
* pop_level_cold.c — ХОЛОДНАЯ (банк 8): чтение файла уровня, разбор комнаты,
|
||
* рестарт, потабличные различия уровней. Всё это
|
||
* отрабатывает раз на уровень или раз на комнату, и
|
||
* держать ~1.9 КБ в дефицитном W1 незачем.
|
||
*
|
||
* Общее состояние (страница уровня, копии дверных таблиц, живые стражи)
|
||
* живёт в ГОРЯЧЕЙ половине и объявлено здесь: данные банковых модулей
|
||
* линкуются в общий _DATA (--bank-data мы не включаем), поэтому обе
|
||
* половины видят их как обычные глобалы — в банк уехал только КОД.
|
||
*
|
||
* Заголовок НЕ публичный: снаружи уровень виден только через pop_level.h.
|
||
*/
|
||
#ifndef _POP_LEVEL_H
|
||
#define _POP_LEVEL_H
|
||
|
||
#include <stdint.h>
|
||
|
||
/* Раскладка страницы уровня (Table 6 POP-DAT); подробности — в pop_level.c. */
|
||
#define LVL_DATA_OFF 0x100u /* данные с 0x100; 0x00..0xFF — ISR-стаб */
|
||
#define LVL_PRISTINE_OFF 0x1000u /* эталон foretable для рестарта уровня */
|
||
|
||
#define BP_FG 0u
|
||
#define BP_BG 720u
|
||
#define BP_LINKLOC 1440u
|
||
#define BP_LINKMAP 1696u
|
||
#define BP_LINKS 1952u
|
||
#define BP_GTILE 2119u
|
||
#define BP_GDIR 2143u
|
||
#define BP_GX 2167u
|
||
#define BP_GSEQLO 2191u
|
||
#define BP_GSKILL 2215u
|
||
#define BP_GSEQHI 2239u
|
||
#define BP_GCOLOR 2263u
|
||
#define BP_START 2112u
|
||
#define ROOM_TILES 30u
|
||
#define MIN_SIZE (BP_START + 3u)
|
||
|
||
/* Живое состояние стражей: 6 байт на комнату (порт level.guards_*). */
|
||
#define GS_TILE 0
|
||
#define GS_DIR 1
|
||
#define GS_X 2
|
||
#define GS_SKILL 3
|
||
#define GS_SEQL 4
|
||
#define GS_SEQH 5
|
||
|
||
/* ---- общее состояние (определено в pop_level.c) ---------------------- */
|
||
extern uint8_t pop_lvl_blk; /* EMM-блок страницы уровня */
|
||
extern uint8_t pop_lvl_page; /* её номер (маппится в W0/W3) */
|
||
extern uint8_t pop_lvl_ok; /* уровень загружен */
|
||
extern uint8_t pop_dl1[256]; /* LINKLOC как в файле */
|
||
extern uint8_t pop_dl2[256]; /* LINKMAP, МУТАБЕЛЬНА (таймеры кнопок) */
|
||
extern uint8_t pop_gstate[24 * 6];
|
||
|
||
/* Указатели на тайлы комнаты r (1..24) в W0-пространстве — страницу мапит
|
||
* вызывающий. static-инлайн в обеих половинах: две команды сложения, звать
|
||
* их через границу банка было бы дороже самого вычисления. */
|
||
static const uint8_t *room_fg_ptr(uint8_t r)
|
||
{
|
||
return (const uint8_t *)(LVL_DATA_OFF + BP_FG) + (uint16_t)(r - 1) * ROOM_TILES;
|
||
}
|
||
static const uint8_t *room_bg_ptr(uint8_t r)
|
||
{
|
||
return (const uint8_t *)(LVL_DATA_OFF + BP_BG) + (uint16_t)(r - 1) * ROOM_TILES;
|
||
}
|
||
|
||
/* Живая копия стражей из данных уровня (загрузка/рестарт) — в холодной. */
|
||
void pop_gstate_init(void) __banked;
|
||
|
||
#endif /* _POP_LEVEL_H */
|