055d6d7c89
Первый запуск после разгрузки встал в halt по мусору в 0xC40E. Причина: pop_level_read_file и pop_kid_data_load маппят страницу данных в W3 на время read() (файл читается по 0xC000), а модули банка исполняются ИЗ ЭТОГО ЖЕ окна — после sprinter_page_w3() следующая инструкция приходит уже из чужой страницы. Обе функции вернулись в резидент; в банке остался код, который ходит через W0 (gfx_w0_map) или окон не трогает вовсе. Правило записано в _pop_level.h и _pop_kid.h: банковый модуль НЕ маппит W3 (через W0 — можно). Поэтому же в резиденте живёт весь libbgi. Куча 6095 Б (было 902 до разгрузки). Проверено в MAME: игра стартует, комната рисуется, Кид управляем. tests-host 6/6.
84 lines
4.6 KiB
C
84 lines
4.6 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;
|
||
}
|
||
|
||
/* ПРАВИЛО ОКНА W3. Банковый модуль исполняется ИЗ W3, поэтому сам он
|
||
* менять это окно НЕ МОЖЕТ: после sprinter_page_w3(другая_страница)
|
||
* следующая инструкция читается уже из чужой страницы. Всё чтение файлов
|
||
* (оно грузит данные по 0xC000) обязано жить в резиденте — отсюда
|
||
* pop_level_read_file здесь, а не в pop_level_cold.c. Через W0
|
||
* (gfx_w0_map) банкам работать можно: это другое окно. */
|
||
int pop_level_read_file(const char *path);
|
||
|
||
/* Живая копия стражей из данных уровня (загрузка/рестарт) — в холодной. */
|
||
void pop_gstate_init(void) __banked;
|
||
|
||
#endif /* _POP_LEVEL_H */
|