Files
Sprinter-SDCC/applications/PoP/roomtest/_pop_level.h
T
snark13 055d6d7c89 Фикс: чтение файлов нельзя выносить в банк — банковый код сам живёт в W3
Первый запуск после разгрузки встал в 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.
2026-08-12 22:17:18 +03:00

84 lines
4.6 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* _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 */