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:
@@ -6,18 +6,22 @@ EXAMPLE := roomtest
|
|||||||
# small: W1+W2 как единое 32КБ-пространство, DATA сразу за CODE (иначе
|
# small: W1+W2 как единое 32КБ-пространство, DATA сразу за CODE (иначе
|
||||||
# CODE ~23КБ переполняет W1 и лезет в фиксированный DATA@0x8000 в huge).
|
# CODE ~23КБ переполняет W1 и лезет в фиксированный DATA@0x8000 в huge).
|
||||||
MEMORY ?= huge # small-раскладка + банки кода в W3 (стражи)
|
MEMORY ?= huge # small-раскладка + банки кода в W3 (стражи)
|
||||||
# --w3 берёт ОДИН файл на флаг (флагов можно несколько). В W3-резиденте
|
# Резидента --w3 БОЛЬШЕ НЕТ: отрисовка уехала в БАНК 2 (pop_bg + pop_gdraw
|
||||||
# держим ТОЛЬКО отрисовку, которую зовёт лишь главный цикл: pop_bg (тайлы)
|
# в одной странице — вызовы между ними прямые, если функция не помечена
|
||||||
# и pop_gdraw (спрайт стража). Всё остальное живёт в W1/W2, чтобы
|
# __banked). Так снято главное ограничение резидента: из банка его было
|
||||||
# оставаться достижимым из __banked-модулей (guards.c): из банка
|
# не достать ни прямо, ни транзитивно, а банк→банк работает (трамплин
|
||||||
# резидентная страница W3 не видна — ни напрямую, ни транзитивно.
|
# сохраняет страницу окна на СТЕКЕ, проверено вложенной цепочкой
|
||||||
# См. docs/layout_plan_v2.md §2 (R2), §4.
|
# банк1→банк2→банк1 в MAME 2026-07-30). Теперь в банки можно уводить и
|
||||||
EXTRA_FLAGS ?= --gfx 256 --w3 pop_bg.c --w3 pop_gdraw.c --bank 1=guards.c $(PROF_FLAGS)
|
# логику, которая рисует. См. docs/layout_plan_v2.md §2, memory
|
||||||
# make PROF=1 — профилирование полосами бордюра (см. PROF() в roomtest.c):
|
# sdcc_banked_call_rules.
|
||||||
# каждая фаза кадра красит бордюр в свой цвет, высота полосы на скриншоте
|
EXTRA_FLAGS ?= --gfx 256 --bank 2=pop_bg.c --bank 2=pop_gdraw.c --bank 3=pop_map.c --bank 1=guards.c $(PROF_FLAGS)
|
||||||
|
# Профилирование полосами бордюра (см. PROF() в roomtest.c) — ВКЛЮЧЕНО по
|
||||||
|
# умолчанию, пока идёт работа с производительностью; make PROF=0 выключает.
|
||||||
|
# Каждая фаза кадра красит бордюр в свой цвет, высота полосы на скриншоте
|
||||||
# MAME = время фазы в растровых строках.
|
# MAME = время фазы в растровых строках.
|
||||||
PROF_FLAGS := $(if $(PROF),-DPROF_BORDER)
|
PROF ?= 1
|
||||||
EXTRA_SRCS := pop_kid.c pop_ctrl.c pop_level.c pop_map.c pop_trob.c pop_redraw.c pop_geom.c pop_guard.c
|
PROF_FLAGS := -DPROF_BORDER=$(PROF)
|
||||||
|
EXTRA_SRCS := pop_state.c pop_kid.c pop_ctrl.c pop_level.c pop_trob.c pop_redraw.c pop_geom.c pop_guard.c
|
||||||
|
|
||||||
BG_DIR := $(CURDIR)/../poc/res/bg
|
BG_DIR := $(CURDIR)/../poc/res/bg
|
||||||
KID_DIR := $(CURDIR)/../poc/res/kid
|
KID_DIR := $(CURDIR)/../poc/res/kid
|
||||||
@@ -67,4 +71,4 @@ $(KID_DATA): $(TC)/pop_pack_kid.py $(TC)/pop_pack_bg.py
|
|||||||
kid_data.h $(KID_BIN): $(TC)/pop_extract_kid_data.py
|
kid_data.h $(KID_BIN): $(TC)/pop_extract_kid_data.py
|
||||||
cd $(TC) && python3 pop_extract_kid_data.py
|
cd $(TC) && python3 pop_extract_kid_data.py
|
||||||
|
|
||||||
$(EXAMPLE).exe: guards.c pop_guard.c pop_guard.h pop_gdraw.c pop_cheat.h pop_bg.c pop_bg.h pop_geom.c pop_geom.h pop_redraw.c pop_redraw.h pop_kid.c pop_kid.h pop_ctrl.c pop_ctrl.h pop_map.c pop_map.h pop_level.c pop_level.h pop_trob.c pop_trob.h kid_data.h $(BG_DATA) $(KID_DATA) $(KID_BIN) $(LVL_DATA)
|
$(EXAMPLE).exe: guards.c pop_guard.c pop_guard.h pop_gdraw.c pop_state.c pop_state.h pop_cheat.h pop_bg.c pop_bg.h pop_geom.c pop_geom.h pop_redraw.c pop_redraw.h pop_kid.c pop_kid.h pop_ctrl.c pop_ctrl.h pop_map.c pop_map.h pop_level.c pop_level.h pop_trob.c pop_trob.h kid_data.h $(BG_DATA) $(KID_DATA) $(KID_BIN) $(LVL_DATA)
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include "pop_bg.h"
|
#include "pop_bg.h"
|
||||||
|
#include "pop_state.h"
|
||||||
#include "pop_geom.h"
|
#include "pop_geom.h"
|
||||||
#include "pop_level.h" /* pop_doorlink2 — состояние нажатия кнопки */
|
#include "pop_level.h" /* pop_doorlink2 — состояние нажатия кнопки */
|
||||||
#include "pop_kid.h" /* Kid.curr_col/curr_row — порядок оверлеев (см. ниже) */
|
#include "pop_kid.h" /* Kid.curr_col/curr_row — порядок оверлеев (см. ниже) */
|
||||||
@@ -32,7 +33,7 @@ static const char *const ENV_ATL[5] = {
|
|||||||
"BG\\pop_env3.atl", "BG\\pop_env4.atl"
|
"BG\\pop_env3.atl", "BG\\pop_env4.atl"
|
||||||
};
|
};
|
||||||
|
|
||||||
int pop_bg_load(void)
|
int pop_bg_load(void) __banked
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < 5; i++)
|
for (i = 0; i < 5; i++)
|
||||||
@@ -43,7 +44,7 @@ int pop_bg_load(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pop_bg_free(void)
|
void pop_bg_free(void) __banked
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < 5; i++)
|
for (i = 0; i < 5; i++)
|
||||||
@@ -76,7 +77,7 @@ static int g_clip_top;
|
|||||||
static int fclip_x0, fclip_y0, fclip_x1, fclip_y1;
|
static int fclip_x0, fclip_y0, fclip_x1, fclip_y1;
|
||||||
static uint8_t fclip_on;
|
static uint8_t fclip_on;
|
||||||
|
|
||||||
void pop_fore_set_clip(int x, int y, int w, int h)
|
void pop_fore_set_clip(int x, int y, int w, int h) __banked
|
||||||
{
|
{
|
||||||
fclip_x0 = x; fclip_y0 = y;
|
fclip_x0 = x; fclip_y0 = y;
|
||||||
fclip_x1 = x + w; fclip_y1 = y + h;
|
fclip_x1 = x + w; fclip_y1 = y + h;
|
||||||
@@ -169,7 +170,7 @@ static void ov_mark(int x, int y, int w, int h)
|
|||||||
ov_pending = 3; /* обе страницы */
|
ov_pending = 3; /* обе страницы */
|
||||||
}
|
}
|
||||||
|
|
||||||
void pop_fore_heal(void)
|
void pop_fore_heal(void) __banked
|
||||||
{
|
{
|
||||||
uint8_t pg = gfx_get_draw_page() & 1;
|
uint8_t pg = gfx_get_draw_page() & 1;
|
||||||
if (!(ov_pending & (1 << pg))) return;
|
if (!(ov_pending & (1 << pg))) return;
|
||||||
@@ -293,12 +294,12 @@ static uint8_t g_room;
|
|||||||
* floorright, когда тайл нижнего ряда стал видимым (empty после падения
|
* floorright, когда тайл нижнего ряда стал видимым (empty после падения
|
||||||
* loose): «стена вниз» = топрайт тайла room_B(0, col-1). 0 — нет комнаты
|
* loose): «стена вниз» = топрайт тайла room_B(0, col-1). 0 — нет комнаты
|
||||||
* снизу (кромка уровня = стена). */
|
* снизу (кромка уровня = стена). */
|
||||||
void pop_room_set_below(const uint8_t *below_row0_fg) { g_below = below_row0_fg; }
|
void pop_room_set_below(const uint8_t *below_row0_fg) __banked { g_below = below_row0_fg; }
|
||||||
|
|
||||||
/* Задать ряд 2 (fg-коды + модификаторы) комнаты СВЕРХУ — для полосы кладки
|
/* Задать ряд 2 (fg-коды + модификаторы) комнаты СВЕРХУ — для полосы кладки
|
||||||
* у потолка (seg008 draw_room: доп. верхний ряд из room_A, draw_tile_aboveroom
|
* у потолка (seg008 draw_room: доп. верхний ряд из room_A, draw_tile_aboveroom
|
||||||
* при draw_main_y=-1). 0 — нет комнаты сверху (кромка уровня → пол). */
|
* при draw_main_y=-1). 0 — нет комнаты сверху (кромка уровня → пол). */
|
||||||
void pop_room_set_above(const uint8_t *above_row2_fg, const uint8_t *above_row2_mod)
|
void pop_room_set_above(const uint8_t *above_row2_fg, const uint8_t *above_row2_mod) __banked
|
||||||
{ g_above = above_row2_fg; g_abovemod = above_row2_mod; }
|
{ g_above = above_row2_fg; g_abovemod = above_row2_mod; }
|
||||||
|
|
||||||
static uint8_t tile_code(int row, int col)
|
static uint8_t tile_code(int row, int col)
|
||||||
@@ -746,7 +747,7 @@ static void draw_tile(int row, int col)
|
|||||||
* Порт SDLPoP redraw_tile_height: каждый кадр анимации перерисовать
|
* Порт SDLPoP redraw_tile_height: каждый кадр анимации перерисовать
|
||||||
* ПОЛНОСТЬЮ и loose-тайл, и ПРАВЫЙ СОСЕД (грани loose анимируются по modif
|
* ПОЛНОСТЬЮ и loose-тайл, и ПРАВЫЙ СОСЕД (грани loose анимируются по modif
|
||||||
* внутри draw_tile). */
|
* внутри draw_tile). */
|
||||||
void pop_loose_shake_draw(int row, int col)
|
void pop_loose_shake_draw(int row, int col) __banked
|
||||||
{
|
{
|
||||||
int x = COL_XH[col] * 8;
|
int x = COL_XH[col] * 8;
|
||||||
/* heal возвращает печёный фон обоих тайлов из ОЗУ-копии, поверх —
|
/* heal возвращает печёный фон обоих тайлов из ОЗУ-копии, поверх —
|
||||||
@@ -768,7 +769,7 @@ void pop_loose_shake_draw(int row, int col)
|
|||||||
* читает lmod = g_bg[row*10+col] = живой modif пики). g_bg должен указывать
|
* читает lmod = g_bg[row*10+col] = живой modif пики). g_bg должен указывать
|
||||||
* на room_modif (enter_room передаёт его как bg). Порт redraw_21h/draw_tile.
|
* на room_modif (enter_room передаёт его как bg). Порт redraw_21h/draw_tile.
|
||||||
* heal берёт печёный статич. фон, поверх — динамич. кадр (шипы над полом). */
|
* heal берёт печёный статич. фон, поверх — динамич. кадр (шипы над полом). */
|
||||||
void pop_spike_redraw(int row, int col)
|
void pop_spike_redraw(int row, int col) __banked
|
||||||
{
|
{
|
||||||
int x = COL_XH[col] * 8;
|
int x = COL_XH[col] * 8;
|
||||||
/* Порт redraw_21h -> redraw_tile_height (seg007:0218): wipe + ПОЛНЫЙ
|
/* Порт redraw_21h -> redraw_tile_height (seg007:0218): wipe + ПОЛНЫЙ
|
||||||
@@ -795,7 +796,7 @@ void pop_spike_redraw(int row, int col)
|
|||||||
* room_modif соседа перед вызовом). Bar-в-чёрный + redraw (как loose bake):
|
* room_modif соседа перед вызовом). Bar-в-чёрный + redraw (как loose bake):
|
||||||
* heal вернул бы ЗАПЕЧЁННОЕ состояние ворот → при открытии нижние бары
|
* heal вернул бы ЗАПЕЧЁННОЕ состояние ворот → при открытии нижние бары
|
||||||
* оставались бы; чёрная плита стирает старые бары в VRAM+ОЗУ-копию. */
|
* оставались бы; чёрная плита стирает старые бары в VRAM+ОЗУ-копию. */
|
||||||
void pop_room_redraw_seam_left(void)
|
void pop_room_redraw_seam_left(void) __banked
|
||||||
{
|
{
|
||||||
gfx_set_bank(GFX_BANK_NORMAL);
|
gfx_set_bank(GFX_BANK_NORMAL);
|
||||||
setfillstyle(SOLID_FILL, BLACK);
|
setfillstyle(SOLID_FILL, BLACK);
|
||||||
@@ -817,7 +818,7 @@ void pop_room_redraw_seam_left(void)
|
|||||||
* после провала (NORMAL, в ОЗУ-копию, чтобы heal её сохранял). */
|
* после провала (NORMAL, в ОЗУ-копию, чтобы heal её сохранял). */
|
||||||
#define CEIL_BAND_H 8 /* видимая высота полосы (room-space y 0..7) */
|
#define CEIL_BAND_H 8 /* видимая высота полосы (room-space y 0..7) */
|
||||||
|
|
||||||
void pop_ceil_shake_draw(int col)
|
void pop_ceil_shake_draw(int col) __banked
|
||||||
{
|
{
|
||||||
int x = COL_XH[col] * 8;
|
int x = COL_XH[col] * 8;
|
||||||
heal_off(x, 0, 64, CEIL_BAND_H); /* фон полосы обоих тайлов */
|
heal_off(x, 0, 64, CEIL_BAND_H); /* фон полосы обоих тайлов */
|
||||||
@@ -829,7 +830,7 @@ void pop_ceil_shake_draw(int col)
|
|||||||
gfx_set_bank(GFX_BANK_NORMAL);
|
gfx_set_bank(GFX_BANK_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pop_ceil_bake_empty(int col)
|
void pop_ceil_bake_empty(int col) __banked
|
||||||
{
|
{
|
||||||
int x = COL_XH[col] * 8;
|
int x = COL_XH[col] * 8;
|
||||||
gfx_set_bank(GFX_BANK_NORMAL);
|
gfx_set_bank(GFX_BANK_NORMAL);
|
||||||
@@ -852,7 +853,7 @@ void pop_ceil_bake_empty(int col)
|
|||||||
* draw_main_y − 40). Зелье: маска (23, «прорезает» фон) + кадр пузырька
|
* draw_main_y − 40). Зелье: маска (23, «прорезает» фон) + кадр пузырька
|
||||||
* potion_fram_bubb[modif & 7] на xh+3/xl=1, ybottom = draw_main_y −
|
* potion_fram_bubb[modif & 7] на xh+3/xl=1, ybottom = draw_main_y −
|
||||||
* (pot_size<<2) − 14 (seg008:668). */
|
* (pot_size<<2) − 14 (seg008:668). */
|
||||||
void pop_torch_draw(int row, int col, uint8_t modif)
|
void pop_torch_draw(int row, int col, uint8_t modif) __banked
|
||||||
{
|
{
|
||||||
/* Пламя рисует ПРАВЫЙ сосед со своим draw_xh: xh = COL_XH[col+1] + 1
|
/* Пламя рисует ПРАВЫЙ сосед со своим draw_xh: xh = COL_XH[col+1] + 1
|
||||||
* (seg008:560), т.е. x = (col+1)*32 + 8 — как и основание факела (env
|
* (seg008:560), т.е. x = (col+1)*32 + 8 — как и основание факела (env
|
||||||
@@ -869,7 +870,7 @@ void pop_torch_draw(int row, int col, uint8_t modif)
|
|||||||
gfx_set_bank(GFX_BANK_NORMAL);
|
gfx_set_bank(GFX_BANK_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pop_potion_draw(int row, int col, uint8_t modif)
|
void pop_potion_draw(int row, int col, uint8_t modif) __banked
|
||||||
{
|
{
|
||||||
uint8_t type = potion_type(modif);
|
uint8_t type = potion_type(modif);
|
||||||
int pot_size = (type >= 2 && type < 5) ? 1 : 0;
|
int pot_size = (type >= 2 && type < 5) ? 1 : 0;
|
||||||
@@ -887,7 +888,7 @@ void pop_potion_draw(int row, int col, uint8_t modif)
|
|||||||
* (draw_tile подставляет пол/stuck по таймеру связи). Bar-в-чёрный +
|
* (draw_tile подставляет пол/stuck по таймеру связи). Bar-в-чёрный +
|
||||||
* redraw — иначе «шишка» отжатой кнопки (base 147) осталась бы при переходе
|
* redraw — иначе «шишка» отжатой кнопки (base 147) осталась бы при переходе
|
||||||
* в пол. Звать из pop_process_trobs для кнопок текущей комнаты. */
|
* в пол. Звать из pop_process_trobs для кнопок текущей комнаты. */
|
||||||
void pop_floor_bake(int row, int col)
|
void pop_floor_bake(int row, int col) __banked
|
||||||
{
|
{
|
||||||
int x = COL_XH[col] * 8;
|
int x = COL_XH[col] * 8;
|
||||||
int yb = POP_YOFF + 63 * row;
|
int yb = POP_YOFF + 63 * row;
|
||||||
@@ -905,13 +906,13 @@ void pop_floor_bake(int row, int col)
|
|||||||
gfx_set_bank(GFX_BANK_NORMAL);
|
gfx_set_bank(GFX_BANK_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pop_button_redraw(int row, int col) { pop_floor_bake(row, col); }
|
void pop_button_redraw(int row, int col) __banked { pop_floor_bake(row, col); }
|
||||||
|
|
||||||
/* Перерисовать ПРАВУЮ половину двери уровня (в её ячейке рисуется створка,
|
/* Перерисовать ПРАВУЮ половину двери уровня (в её ячейке рисуется створка,
|
||||||
* см. draw_leveldoor) на back-странице С ЗАПЕЧКОЙ в ОЗУ-копию: створка едет,
|
* см. draw_leveldoor) на back-странице С ЗАПЕЧКОЙ в ОЗУ-копию: створка едет,
|
||||||
* а heal обязан возвращать её ТЕКУЩЕЕ положение, а не запечённое закрытое.
|
* а heal обязан возвращать её ТЕКУЩЕЕ положение, а не запечённое закрытое.
|
||||||
* Куски двери непрозрачные — wipe не нужен. */
|
* Куски двери непрозрачные — wipe не нужен. */
|
||||||
void pop_leveldoor_redraw(int row, int col)
|
void pop_leveldoor_redraw(int row, int col) __banked
|
||||||
{
|
{
|
||||||
gfx_set_bank(GFX_BANK_TRANSPARENT);
|
gfx_set_bank(GFX_BANK_TRANSPARENT);
|
||||||
draw_tile(row, col);
|
draw_tile(row, col);
|
||||||
@@ -924,7 +925,7 @@ void pop_leveldoor_redraw(int row, int col)
|
|||||||
* рисовал loose-правый-край env_b(42); теперь пусто → чистая грань).
|
* рисовал loose-правый-край env_b(42); теперь пусто → чистая грань).
|
||||||
* g_fg[pos] уже = 0 (pop_map). Чёрная плита (NORMAL) стирает старые
|
* g_fg[pos] уже = 0 (pop_map). Чёрная плита (NORMAL) стирает старые
|
||||||
* пиксели пола в видео-ОЗУ + ОЗУ-копию, поверх — новый статич. фон. */
|
* пиксели пола в видео-ОЗУ + ОЗУ-копию, поверх — новый статич. фон. */
|
||||||
void pop_loose_bake_empty(int row, int col)
|
void pop_loose_bake_empty(int row, int col) __banked
|
||||||
{
|
{
|
||||||
int x = COL_XH[col] * 8;
|
int x = COL_XH[col] * 8;
|
||||||
int xr = COL_XH[col + 1] * 8;
|
int xr = COL_XH[col + 1] * 8;
|
||||||
@@ -987,7 +988,8 @@ static mob_t mobs[MOB_MAX];
|
|||||||
|
|
||||||
/* Кусок «приземлился» (порт loose_land): 0 = нет, иначе tilepos+1 тайла, на
|
/* Кусок «приземлился» (порт loose_land): 0 = нет, иначе tilepos+1 тайла, на
|
||||||
* который он лёг → приложение/pop_map ставит debris + do_knock. */
|
* который он лёг → приложение/pop_map ставит debris + do_knock. */
|
||||||
uint8_t pop_loose_landed;
|
/* pop_loose_landed переехал в pop_state.c: его читает pop_map (W1/W2), а
|
||||||
|
* писучие данные банкового модуля недоступны снаружи (см. pop_state.h). */
|
||||||
|
|
||||||
/* y_loose_land / y_something (seg007): [row+1], row = −1..3. Ряд −1 —
|
/* y_loose_land / y_something (seg007): [row+1], row = −1..3. Ряд −1 —
|
||||||
* плита-потолок (ряд 2 комнаты сверху): в оригинале это отрицательный
|
* плита-потолок (ряд 2 комнаты сверху): в оригинале это отрицательный
|
||||||
@@ -996,7 +998,7 @@ static const int16_t MOB_Y_LAND[5] = {2, 65, 128, 191, 254};
|
|||||||
static const int16_t MOB_Y_BOUND[5] = {-1, 62, 125, 188, 25};
|
static const int16_t MOB_Y_BOUND[5] = {-1, 62, 125, 188, 25};
|
||||||
#define MOB_Y_NONE 0x7FFF
|
#define MOB_Y_NONE 0x7FFF
|
||||||
|
|
||||||
void pop_loose_mob_spawn(int row, int col)
|
void pop_loose_mob_spawn(int row, int col) __banked
|
||||||
{
|
{
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
mob_t *m = 0;
|
mob_t *m = 0;
|
||||||
@@ -1033,7 +1035,7 @@ static int8_t obj_col, obj_row;
|
|||||||
|
|
||||||
static void mob_render(mob_t *m, uint8_t pg);
|
static void mob_render(mob_t *m, uint8_t pg);
|
||||||
|
|
||||||
void pop_loose_mob_reset(void)
|
void pop_loose_mob_reset(void) __banked
|
||||||
{
|
{
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
for (i = 0; i < MOB_MAX; i++) {
|
for (i = 0; i < MOB_MAX; i++) {
|
||||||
@@ -1098,7 +1100,7 @@ static void mob_tick_one(mob_t *m, uint8_t pg)
|
|||||||
mob_render(m, pg);
|
mob_render(m, pg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pop_loose_mob_tick(void)
|
void pop_loose_mob_tick(void) __banked
|
||||||
{
|
{
|
||||||
uint8_t pg = gfx_get_draw_page() & 1, i;
|
uint8_t pg = gfx_get_draw_page() & 1, i;
|
||||||
for (i = 0; i < MOB_MAX; i++)
|
for (i = 0; i < MOB_MAX; i++)
|
||||||
@@ -1148,7 +1150,7 @@ static void mob_render(mob_t *m, uint8_t pg)
|
|||||||
|
|
||||||
/* Отложенная отрисовка куска ПОВЕРХ Kid (он ниже Kid по obj_y). Звать
|
/* Отложенная отрисовка куска ПОВЕРХ Kid (он ниже Kid по obj_y). Звать
|
||||||
* после kid_draw, до fore-слоя. */
|
* после kid_draw, до fore-слоя. */
|
||||||
void pop_loose_mob_draw_over(void)
|
void pop_loose_mob_draw_over(void) __banked
|
||||||
{
|
{
|
||||||
uint8_t pg = gfx_get_draw_page() & 1, i;
|
uint8_t pg = gfx_get_draw_page() & 1, i;
|
||||||
for (i = 0; i < MOB_MAX; i++)
|
for (i = 0; i < MOB_MAX; i++)
|
||||||
@@ -1157,7 +1159,7 @@ void pop_loose_mob_draw_over(void)
|
|||||||
|
|
||||||
/* Позиция падающего куска для check_loose_fall_on_kid (pop_map): колонка и
|
/* Позиция падающего куска для check_loose_fall_on_kid (pop_map): колонка и
|
||||||
* y (низ куска). 0 — куска нет. */
|
* y (низ куска). 0 — куска нет. */
|
||||||
uint8_t pop_loose_mob_pos(int *col, int *y)
|
uint8_t pop_loose_mob_pos(int *col, int *y) __banked
|
||||||
{
|
{
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
for (i = 0; i < MOB_MAX; i++)
|
for (i = 0; i < MOB_MAX; i++)
|
||||||
@@ -1172,7 +1174,7 @@ uint8_t pop_loose_mob_pos(int *col, int *y)
|
|||||||
* кадрах падения — гейт по флагу). */
|
* кадрах падения — гейт по флагу). */
|
||||||
static uint8_t border_dirty;
|
static uint8_t border_dirty;
|
||||||
|
|
||||||
void pop_clip_sprite(int x, int w, int sy_top, int h)
|
void pop_clip_sprite(int x, int w, int sy_top, int h) __banked
|
||||||
{
|
{
|
||||||
int sy_bot = sy_top + h;
|
int sy_bot = sy_top + h;
|
||||||
(void)x; (void)w;
|
(void)x; (void)w;
|
||||||
@@ -1184,7 +1186,7 @@ void pop_clip_sprite(int x, int w, int sy_top, int h)
|
|||||||
* вышел за поле в последние 2 кадра) — иначе ноль стоимости. Возвращает
|
* вышел за поле в последние 2 кадра) — иначе ноль стоимости. Возвращает
|
||||||
* чёрный из ОЗУ-копии (вне поля она чёрная) в верхний борт и статус-полосу
|
* чёрный из ОЗУ-копии (вне поля она чёрная) в верхний борт и статус-полосу
|
||||||
* + нижний борт. Звать КАЖДЫЙ кадр ПОСЛЕ всей отрисовки спрайтов. */
|
* + нижний борт. Звать КАЖДЫЙ кадр ПОСЛЕ всей отрисовки спрайтов. */
|
||||||
void pop_room_clip_borders(void)
|
void pop_room_clip_borders(void) __banked
|
||||||
{
|
{
|
||||||
if (!border_dirty) return;
|
if (!border_dirty) return;
|
||||||
border_dirty--;
|
border_dirty--;
|
||||||
@@ -1194,7 +1196,7 @@ void pop_room_clip_borders(void)
|
|||||||
|
|
||||||
void pop_room_draw(uint8_t room_num,
|
void pop_room_draw(uint8_t room_num,
|
||||||
const uint8_t *fg, const uint8_t *bg,
|
const uint8_t *fg, const uint8_t *bg,
|
||||||
const uint8_t *lcol_fg, const uint8_t *lcol_bg)
|
const uint8_t *lcol_fg, const uint8_t *lcol_bg) __banked
|
||||||
{
|
{
|
||||||
int row, col;
|
int row, col;
|
||||||
g_room = room_num;
|
g_room = room_num;
|
||||||
@@ -1502,7 +1504,7 @@ static void char_footprint(int obj_x, int obj_y, uint16_t w, uint16_t h,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void pop_fore_over_kid(int obj_x, int obj_y, uint16_t w, uint16_t h,
|
void pop_fore_over_kid(int obj_x, int obj_y, uint16_t w, uint16_t h,
|
||||||
int8_t dir, uint8_t frame, uint8_t action)
|
int8_t dir, uint8_t frame, uint8_t action) __banked
|
||||||
{
|
{
|
||||||
int8_t cL, cR, cLraw, rT, rB, rTraw, r, c;
|
int8_t cL, cR, cLraw, rT, rB, rTraw, r, c;
|
||||||
fclip_on = 1; /* окно = прямоугольник спрайта */
|
fclip_on = 1; /* окно = прямоугольник спрайта */
|
||||||
|
|||||||
@@ -28,10 +28,10 @@
|
|||||||
/* Загрузить 7 атласов фона. Звать ДО initgraph (как poc.c — atlas_load
|
/* Загрузить 7 атласов фона. Звать ДО initgraph (как poc.c — atlas_load
|
||||||
* трогает W3; проверенный порядок). Палитру pop_bg.pal грузит ПРИЛОЖЕНИЕ
|
* трогает W3; проверенный порядок). Палитру pop_bg.pal грузит ПРИЛОЖЕНИЕ
|
||||||
* после initgraph (gfx_pal_fload). 0 — OK, -1 — ошибка. */
|
* после initgraph (gfx_pal_fload). 0 — OK, -1 — ошибка. */
|
||||||
int pop_bg_load(void);
|
int pop_bg_load(void) __banked;
|
||||||
|
|
||||||
/* Освободить EMM-страницы атласов. */
|
/* Освободить EMM-страницы атласов. */
|
||||||
void pop_bg_free(void);
|
void pop_bg_free(void) __banked;
|
||||||
|
|
||||||
/* Нарисовать комнату: fg[30]/bg[30] — foretable-коды/backtable-модификаторы
|
/* Нарисовать комнату: fg[30]/bg[30] — foretable-коды/backtable-модификаторы
|
||||||
* (по строкам, row*10+col). lcol_fg/lcol_bg — 3 тайла правого столбца
|
* (по строкам, row*10+col). lcol_fg/lcol_bg — 3 тайла правого столбца
|
||||||
@@ -39,24 +39,24 @@ void pop_bg_free(void);
|
|||||||
* тогда левая кромка = стена. room_num — номер комнаты (зерно стен). */
|
* тогда левая кромка = стена. room_num — номер комнаты (зерно стен). */
|
||||||
void pop_room_draw(uint8_t room_num,
|
void pop_room_draw(uint8_t room_num,
|
||||||
const uint8_t *fg, const uint8_t *bg,
|
const uint8_t *fg, const uint8_t *bg,
|
||||||
const uint8_t *lcol_fg, const uint8_t *lcol_bg);
|
const uint8_t *lcol_fg, const uint8_t *lcol_bg) __banked;
|
||||||
|
|
||||||
/* Задать ряд 0 комнаты СНИЗУ (fg-коды, 10 шт.) — для draw_tile_topright,
|
/* Задать ряд 0 комнаты СНИЗУ (fg-коды, 10 шт.) — для draw_tile_topright,
|
||||||
* когда тайл нижнего ряда стал empty (после падения loose): «стена вниз»
|
* когда тайл нижнего ряда стал empty (после падения loose): «стена вниз»
|
||||||
* рисуется по коду room_B(0, col-1). 0 — нет комнаты снизу. */
|
* рисуется по коду room_B(0, col-1). 0 — нет комнаты снизу. */
|
||||||
void pop_room_set_below(const uint8_t *below_row0_fg);
|
void pop_room_set_below(const uint8_t *below_row0_fg) __banked;
|
||||||
|
|
||||||
/* Задать ряд 2 (fg-коды + модификаторы, 10 шт.) комнаты СВЕРХУ — для полосы
|
/* Задать ряд 2 (fg-коды + модификаторы, 10 шт.) комнаты СВЕРХУ — для полосы
|
||||||
* кладки у потолка (seg008 draw_room доп. верхний ряд из room_A). 0 — нет
|
* кладки у потолка (seg008 draw_room доп. верхний ряд из room_A). 0 — нет
|
||||||
* комнаты сверху (кромка уровня → пол). */
|
* комнаты сверху (кромка уровня → пол). */
|
||||||
void pop_room_set_above(const uint8_t *above_row2_fg, const uint8_t *above_row2_mod);
|
void pop_room_set_above(const uint8_t *above_row2_fg, const uint8_t *above_row2_mod) __banked;
|
||||||
|
|
||||||
/* Перерисовать передний слой (fore) тайлов футпринта Kid ПОВЕРХ него —
|
/* Перерисовать передний слой (fore) тайлов футпринта Kid ПОВЕРХ него —
|
||||||
* звать ПОСЛЕ kid_draw. obj_x — ЛОГИЧЕСКАЯ X кадра (до ×8/7), obj_y — низ
|
* звать ПОСЛЕ kid_draw. obj_x — ЛОГИЧЕСКАЯ X кадра (до ×8/7), obj_y — низ
|
||||||
* спрайта, w/h — размер кадра, dir — направление Kid (<0 влево). Метрики
|
* спрайта, w/h — размер кадра, dir — направление Kid (<0 влево). Метрики
|
||||||
* берутся из pop_kid (kid_fp_*). См. redraw_at_char/set_char_collision. */
|
* берутся из pop_kid (kid_fp_*). См. redraw_at_char/set_char_collision. */
|
||||||
void pop_fore_over_kid(int obj_x, int obj_y, uint16_t w, uint16_t h,
|
void pop_fore_over_kid(int obj_x, int obj_y, uint16_t w, uint16_t h,
|
||||||
int8_t dir, uint8_t frame, uint8_t action);
|
int8_t dir, uint8_t frame, uint8_t action) __banked;
|
||||||
|
|
||||||
/* Окно fore-слоя: прямоугольник СПРАЙТА (экранные координаты, y уже с
|
/* Окно fore-слоя: прямоугольник СПРАЙТА (экранные координаты, y уже с
|
||||||
* POP_YOFF), поверх которого fore-проход возвращает куски тайлов. Ставит
|
* POP_YOFF), поверх которого fore-проход возвращает куски тайлов. Ставит
|
||||||
@@ -64,7 +64,7 @@ void pop_fore_over_kid(int obj_x, int obj_y, uint16_t w, uint16_t h,
|
|||||||
* итоговый габарит (у Kid — с учётом клинка и обрезки clip_char). Вне
|
* итоговый габарит (у Kid — с учётом клинка и обрезки clip_char). Вне
|
||||||
* fore-проходов окно игнорируется: фон рисуется целиком. Мотивация и
|
* fore-проходов окно игнорируется: фон рисуется целиком. Мотивация и
|
||||||
* замер — в pop_bg.c у fclip_on. */
|
* замер — в pop_bg.c у fclip_on. */
|
||||||
void pop_fore_set_clip(int x, int y, int w, int h);
|
void pop_fore_set_clip(int x, int y, int w, int h) __banked;
|
||||||
|
|
||||||
/* То же для НЕ-Kid персонажа (страж): только слой fore + полоса потолка,
|
/* То же для НЕ-Kid персонажа (страж): только слой fore + полоса потолка,
|
||||||
* без оверлеев поз виса/полёта/подъёма. obj_x — ЛОГИЧЕСКАЯ координата
|
* без оверлеев поз виса/полёта/подъёма. obj_x — ЛОГИЧЕСКАЯ координата
|
||||||
@@ -76,74 +76,74 @@ void pop_fore_over_char(int obj_x, int obj_y, uint16_t w, uint16_t h,
|
|||||||
* (draw_other_overlay/floor_overlay/полоса потолка): он выходит за
|
* (draw_other_overlay/floor_overlay/полоса потолка): он выходит за
|
||||||
* прямоугольник Kid, поэтому kid_heal его не убирает — на второй странице
|
* прямоугольник Kid, поэтому kid_heal его не убирает — на второй странице
|
||||||
* дабл-буфера остаётся след и мерцает. Звать рядом с kid_heal. */
|
* дабл-буфера остаётся след и мерцает. Звать рядом с kid_heal. */
|
||||||
void pop_fore_heal(void);
|
void pop_fore_heal(void) __banked;
|
||||||
|
|
||||||
/* Loose floors — динамическая отрисовка (состояние pop_loose_modif в
|
/* Loose floors — динамическая отрисовка (состояние pop_loose_modif в
|
||||||
* pop_map). Звать на ТЕКУЩЕЙ (back) странице из pop_loose_tick.
|
* pop_map). Звать на ТЕКУЩЕЙ (back) странице из pop_loose_tick.
|
||||||
* shake_draw — дрожащий кадр (heal+SPRITE); bake_empty — запечь пустоту
|
* shake_draw — дрожащий кадр (heal+SPRITE); bake_empty — запечь пустоту
|
||||||
* после падения (NORMAL, в ОЗУ-копию). */
|
* после падения (NORMAL, в ОЗУ-копию). */
|
||||||
void pop_loose_shake_draw(int row, int col);
|
void pop_loose_shake_draw(int row, int col) __banked;
|
||||||
void pop_loose_bake_empty(int row, int col);
|
void pop_loose_bake_empty(int row, int col) __banked;
|
||||||
|
|
||||||
/* Плита-ПОТОЛОК (loose ряда 2 комнаты СВЕРХУ, наш ряд −1): дрожащий кадр в
|
/* Плита-ПОТОЛОК (loose ряда 2 комнаты СВЕРХУ, наш ряд −1): дрожащий кадр в
|
||||||
* полосе у потолка / «запечь» пустоту (колодец наверх) после провала.
|
* полосе у потолка / «запечь» пустоту (колодец наверх) после провала.
|
||||||
* Состояние — pop_ceil_modif[10] в pop_map. */
|
* Состояние — pop_ceil_modif[10] в pop_map. */
|
||||||
void pop_ceil_shake_draw(int col);
|
void pop_ceil_shake_draw(int col) __banked;
|
||||||
void pop_ceil_bake_empty(int col);
|
void pop_ceil_bake_empty(int col) __banked;
|
||||||
|
|
||||||
/* Кусок приземлился (loose_land): 0 = нет, иначе tilepos+1 тайла, на который
|
/* Кусок приземлился (loose_land) — переехал в pop_state.h: переменную
|
||||||
* он лёг. Ставит pop_loose_mob_tick, разбирает pop_loose_tick (debris+knock). */
|
* читают по обе стороны банковой границы. */
|
||||||
extern uint8_t pop_loose_landed;
|
#include "pop_state.h"
|
||||||
|
|
||||||
/* Пики (spike) — перерисовка тайла (row,col) на back-странице по живому
|
/* Пики (spike) — перерисовка тайла (row,col) на back-странице по живому
|
||||||
* modif (pop_trob). Звать из pop_process_trobs. См. pop_bg.c. */
|
* modif (pop_trob). Звать из pop_process_trobs. См. pop_bg.c. */
|
||||||
void pop_spike_redraw(int row, int col);
|
void pop_spike_redraw(int row, int col) __banked;
|
||||||
|
|
||||||
/* Анимация факела/зелья (динамика каждый кадр; фон запечён без них):
|
/* Анимация факела/зелья (динамика каждый кадр; фон запечён без них):
|
||||||
* modif — живой room_modif тайла. Для факела col — колонка САМОГО факела
|
* modif — живой room_modif тайла. Для факела col — колонка САМОГО факела
|
||||||
* (пламя рисуется в ячейке правого соседа). */
|
* (пламя рисуется в ячейке правого соседа). */
|
||||||
void pop_torch_draw(int row, int col, uint8_t modif);
|
void pop_torch_draw(int row, int col, uint8_t modif) __banked;
|
||||||
void pop_potion_draw(int row, int col, uint8_t modif);
|
void pop_potion_draw(int row, int col, uint8_t modif) __banked;
|
||||||
|
|
||||||
/* Ворота на ЛЕВОМ шве (col0) — перерисовать по живому modif соседа слева.
|
/* Ворота на ЛЕВОМ шве (col0) — перерисовать по живому modif соседа слева.
|
||||||
* g_lbg (lcol_bg) должен быть обновлён вызывающим. Звать из основного цикла
|
* g_lbg (lcol_bg) должен быть обновлён вызывающим. Звать из основного цикла
|
||||||
* на back-странице, когда сосед слева анимируется. См. pop_bg.c. */
|
* на back-странице, когда сосед слева анимируется. См. pop_bg.c. */
|
||||||
void pop_room_redraw_seam_left(void);
|
void pop_room_redraw_seam_left(void) __banked;
|
||||||
|
|
||||||
/* Перерисовать ПОЛ тайла (row,col) + правую грань в соседе на back-странице
|
/* Перерисовать ПОЛ тайла (row,col) + правую грань в соседе на back-странице
|
||||||
* (wipe по площади пола, БЕЗ стены ряда ниже). Для смены тайла на месте:
|
* (wipe по площади пола, БЕЗ стены ряда ниже). Для смены тайла на месте:
|
||||||
* кнопка нажата/отжата, floor → debris от упавшей плиты. */
|
* кнопка нажата/отжата, floor → debris от упавшей плиты. */
|
||||||
void pop_floor_bake(int row, int col);
|
void pop_floor_bake(int row, int col) __banked;
|
||||||
void pop_button_redraw(int row, int col); /* = pop_floor_bake (кнопка) */
|
void pop_button_redraw(int row, int col) __banked; /* = pop_floor_bake (кнопка) */
|
||||||
|
|
||||||
/* Дверь уровня: перерисовать её ПРАВУЮ половину (row, col = правая) с
|
/* Дверь уровня: перерисовать её ПРАВУЮ половину (row, col = правая) с
|
||||||
* запечкой — створка анимируется (pop_trob animate_leveldoor). */
|
* запечкой — створка анимируется (pop_trob animate_leveldoor). */
|
||||||
void pop_leveldoor_redraw(int row, int col);
|
void pop_leveldoor_redraw(int row, int col) __banked;
|
||||||
|
|
||||||
/* Падающий кусок loose (mob, seg007 move_loose): спавн при падении тайла
|
/* Падающий кусок loose (mob, seg007 move_loose): спавн при падении тайла
|
||||||
* (row,col) и покадровое продвижение+отрисовка на back-странице. tick
|
* (row,col) и покадровое продвижение+отрисовка на back-странице. tick
|
||||||
* зовётся каждый кадр (внутри pop_loose_tick); клип низа делает clip. */
|
* зовётся каждый кадр (внутри pop_loose_tick); клип низа делает clip. */
|
||||||
void pop_loose_mob_spawn(int row, int col);
|
void pop_loose_mob_spawn(int row, int col) __banked;
|
||||||
void pop_loose_mob_tick(void);
|
void pop_loose_mob_tick(void) __banked;
|
||||||
void pop_loose_mob_reset(void); /* остановить кусок (смена комнаты) */
|
void pop_loose_mob_reset(void) __banked; /* остановить кусок (смена комнаты) */
|
||||||
|
|
||||||
/* Кусок НИЖЕ Kid по obj_y → рисуется ПОВЕРХ него (порт sort_curr_objs,
|
/* Кусок НИЖЕ Kid по obj_y → рисуется ПОВЕРХ него (порт sort_curr_objs,
|
||||||
* seg008:1561). Звать после kid_draw, перед fore-слоем. */
|
* seg008:1561). Звать после kid_draw, перед fore-слоем. */
|
||||||
void pop_loose_mob_draw_over(void);
|
void pop_loose_mob_draw_over(void) __banked;
|
||||||
|
|
||||||
/* Позиция куска (колонка, y низа) для check_loose_fall_on_kid. 0 — нет. */
|
/* Позиция куска (колонка, y низа) для check_loose_fall_on_kid. 0 — нет. */
|
||||||
uint8_t pop_loose_mob_pos(int *col, int *y);
|
uint8_t pop_loose_mob_pos(int *col, int *y) __banked;
|
||||||
|
|
||||||
/* Детектор выхода спрайта за поле: если спрайт [x,w] с ЭКРАННЫМ верхом
|
/* Детектор выхода спрайта за поле: если спрайт [x,w] с ЭКРАННЫМ верхом
|
||||||
* sy_top и высотой h заходит ниже поля (статус-полоса/борт) или выше
|
* sy_top и высотой h заходит ниже поля (статус-полоса/борт) или выше
|
||||||
* верхнего борта — взводит внутренний флаг «борта грязные» на 2 кадра.
|
* верхнего борта — взводит внутренний флаг «борта грязные» на 2 кадра.
|
||||||
* Звать СРАЗУ после блита падающего объекта (Kid/кусок). */
|
* Звать СРАЗУ после блита падающего объекта (Kid/кусок). */
|
||||||
void pop_clip_sprite(int x, int w, int sy_top, int h);
|
void pop_clip_sprite(int x, int w, int sy_top, int h) __banked;
|
||||||
|
|
||||||
/* Почистить борта (верхний + статус-полоса/нижний) — но ТОЛЬКО в кадрах,
|
/* Почистить борта (верхний + статус-полоса/нижний) — но ТОЛЬКО в кадрах,
|
||||||
* где кто-то реально вышел за поле (гейт по флагу от pop_clip_sprite):
|
* где кто-то реально вышел за поле (гейт по флагу от pop_clip_sprite):
|
||||||
* даром в покое, O(1) при падении (не зависит от числа спрайтов). Звать
|
* даром в покое, O(1) при падении (не зависит от числа спрайтов). Звать
|
||||||
* КАЖДЫЙ кадр ПОСЛЕ kid_draw+fore на back-странице. */
|
* КАЖДЫЙ кадр ПОСЛЕ kid_draw+fore на back-странице. */
|
||||||
void pop_room_clip_borders(void);
|
void pop_room_clip_borders(void) __banked;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ static int gx_l[2], gy_l[2];
|
|||||||
static uint16_t gw_l[2], gh_l[2];
|
static uint16_t gw_l[2], gh_l[2];
|
||||||
static uint8_t gvalid[2];
|
static uint8_t gvalid[2];
|
||||||
|
|
||||||
int pop_guard_load(void)
|
int pop_guard_load(void) __banked
|
||||||
{
|
{
|
||||||
static const char *const names[GUARD_PAGES] = {
|
static const char *const names[GUARD_PAGES] = {
|
||||||
"GUARD\\g0.atl", "GUARD\\g1.atl", "GUARD\\g2.atl",
|
"GUARD\\g0.atl", "GUARD\\g1.atl", "GUARD\\g2.atl",
|
||||||
@@ -42,7 +42,7 @@ int pop_guard_load(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pop_guard_free(void)
|
void pop_guard_free(void) __banked
|
||||||
{
|
{
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
if (!g_ok) return;
|
if (!g_ok) return;
|
||||||
@@ -50,14 +50,14 @@ void pop_guard_free(void)
|
|||||||
g_ok = 0;
|
g_ok = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pop_guard_heal(void)
|
void pop_guard_heal(void) __banked
|
||||||
{
|
{
|
||||||
uint8_t p = gfx_get_draw_page() & 1;
|
uint8_t p = gfx_get_draw_page() & 1;
|
||||||
if (gvalid[p]) gfx_heal(gx_l[p], gy_l[p] + POP_YOFF, gw_l[p], gh_l[p]);
|
if (gvalid[p]) gfx_heal(gx_l[p], gy_l[p] + POP_YOFF, gw_l[p], gh_l[p]);
|
||||||
gvalid[p] = 0;
|
gvalid[p] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pop_guard_draw(void)
|
void pop_guard_draw(void) __banked
|
||||||
{
|
{
|
||||||
int obj_x, obj_y, top, fwd, fp_x, bx0 = 0, top0 = 0;
|
int obj_x, obj_y, top, fwd, fp_x, bx0 = 0, top0 = 0;
|
||||||
uint8_t page, idx, p, flip;
|
uint8_t page, idx, p, flip;
|
||||||
|
|||||||
@@ -56,8 +56,8 @@ uint8_t pop_guard_present(void);
|
|||||||
|
|
||||||
/* Атласы стража (GUARD\\g0..g4.atl) — грузить ДО initgraph, как Kid.
|
/* Атласы стража (GUARD\\g0..g4.atl) — грузить ДО initgraph, как Kid.
|
||||||
* 0 — OK, -1 — ошибка (тогда страж просто не рисуется). */
|
* 0 — OK, -1 — ошибка (тогда страж просто не рисуется). */
|
||||||
int pop_guard_load(void);
|
int pop_guard_load(void) __banked;
|
||||||
void pop_guard_free(void);
|
void pop_guard_free(void) __banked;
|
||||||
|
|
||||||
/* Вход в комнату: поднять стража из данных уровня (порт enter_guard,
|
/* Вход в комнату: поднять стража из данных уровня (порт enter_guard,
|
||||||
* seg002:0112) либо убрать его, если в комнате стража нет. */
|
* seg002:0112) либо убрать его, если в комнате стража нет. */
|
||||||
@@ -66,8 +66,8 @@ void pop_guard_enter(uint8_t room);
|
|||||||
/* Нарисовать текущий кадр стража на back-странице (банк GFX_BANK_SPRITE,
|
/* Нарисовать текущий кадр стража на back-странице (банк GFX_BANK_SPRITE,
|
||||||
* как kid_draw) и стереть прошлый (heal). Реализация — pop_gdraw.c
|
* как kid_draw) и стереть прошлый (heal). Реализация — pop_gdraw.c
|
||||||
* (резидент W3), поэтому звать ТОЛЬКО из главного цикла, не из банка. */
|
* (резидент W3), поэтому звать ТОЛЬКО из главного цикла, не из банка. */
|
||||||
void pop_guard_heal(void);
|
void pop_guard_heal(void) __banked;
|
||||||
void pop_guard_draw(void);
|
void pop_guard_draw(void) __banked;
|
||||||
|
|
||||||
/* Убрать стража со сцены (смена комнаты / инициализация). */
|
/* Убрать стража со сцены (смена комнаты / инициализация). */
|
||||||
void pop_guard_reset(void);
|
void pop_guard_reset(void);
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
* есть то, что понадобится стражам, чиста от графики. Разделение mob на
|
* есть то, что понадобится стражам, чиста от графики. Разделение mob на
|
||||||
* логику и отрисовку — задел следующей фазы. */
|
* логику и отрисовку — задел следующей фазы. */
|
||||||
#include "pop_bg.h"
|
#include "pop_bg.h"
|
||||||
|
#include "pop_state.h"
|
||||||
#include "pop_trob.h" /* room_modif + trob-список (пики/ворота) */
|
#include "pop_trob.h" /* room_modif + trob-список (пики/ворота) */
|
||||||
|
|
||||||
/* ---- Тайлы / действия / seq id (подмножество PoP) ------------------ */
|
/* ---- Тайлы / действия / seq id (подмножество PoP) ------------------ */
|
||||||
@@ -149,13 +150,13 @@ uint8_t pop_ceil_fell; /* 0 = нет; иначе col+1 провал
|
|||||||
|
|
||||||
uint8_t pop_debris_at; /* 0 = нет; иначе tilepos+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). */
|
/* take_hp (seg006:06BD, только Kid): count>=hitp → смерть (return 1). */
|
||||||
static uint8_t take_hp(uint8_t count)
|
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,
|
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;
|
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]; }
|
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;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pop_edge_distance(void)
|
int pop_edge_distance(void) __banked
|
||||||
{
|
{
|
||||||
uint8_t t; int d;
|
uint8_t t; int d;
|
||||||
determine_col();
|
determine_col();
|
||||||
@@ -629,7 +630,7 @@ int pop_edge_distance(void)
|
|||||||
return distance_to_edge_weight();
|
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 и производные) --- *
|
/* ---- Прыжок вверх с зацепом (seg005 check_jump_up и производные) --- *
|
||||||
* pop_jump_up_seq выбирает seq для ↑ в стойке: чистый прыжок (seq_28 в
|
* 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();
|
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();
|
uint8_t through = get_tile_above_char();
|
||||||
get_tile_front_above_char(); /* g_curr_tile = спереди-сверху */
|
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: передний край почти у грани. */
|
* позицию держит check_bumped=in_wall). d<=2: передний край почти у грани. */
|
||||||
int pop_wall_ahead(void)
|
int pop_wall_ahead(void) __banked
|
||||||
{
|
{
|
||||||
int d = pop_edge_distance();
|
int d = pop_edge_distance();
|
||||||
return (g_edge_type == EDGE_WALL && d <= 2);
|
return (g_edge_type == EDGE_WALL && d <= 2);
|
||||||
@@ -708,7 +709,7 @@ int pop_wall_ahead(void)
|
|||||||
* тайловые предикаты + выбор seq (+ выравнивание Kid.x). */
|
* тайловые предикаты + выбор seq (+ выравнивание Kid.x). */
|
||||||
|
|
||||||
/* grab_timer истёк — можно подтягиваться? */
|
/* 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)
|
/* can_climb_up (seg005:09DF): тайл над персонажем — обычный подъём (seq_10)
|
||||||
* либо подъём к ЗАКРЫТОЙ калитке/зеркалу/чомперу (seq_73 = «влез и съехал
|
* либо подъём к ЗАКРЫТОЙ калитке/зеркалу/чомперу (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
|
* curr_tile2 == tiles_4_gate && direction != right && modif >> 2 < 6
|
||||||
* — под поднятой решёткой (modif >> 2 >= 6) подъём обычный. Без проверки
|
* — под поднятой решёткой (modif >> 2 >= 6) подъём обычный. Без проверки
|
||||||
* модификатора Kid срывался и с открытых ворот. */
|
* модификатора 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();
|
uint8_t t = get_tile_above_char();
|
||||||
if (((t == TILE_MIRROR || t == TILE_CHOMPER) && Kid.direction == 0) ||
|
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 =
|
/* Shift в висе: 1 = висит у стены/двери (caller играет seq_25); -1 =
|
||||||
* сорваться (hang_fall); 0 = сверху пол, остаётся висеть (ничего). */
|
* сорваться (hang_fall); 0 = сверху пол, остаётся висеть (ничего). */
|
||||||
int8_t pop_hang_wall(void)
|
int8_t pop_hang_wall(void) __banked
|
||||||
{
|
{
|
||||||
uint8_t t = get_tile_at_char();
|
uint8_t t = get_tile_at_char();
|
||||||
if (Kid.action != ACT_HANGSTRAIGHT &&
|
if (Kid.action != ACT_HANGSTRAIGHT &&
|
||||||
@@ -743,7 +744,7 @@ int8_t pop_hang_wall(void)
|
|||||||
/* hang_fall (seg005:0A46): сорваться. Нет пола ни сзади, ни под
|
/* hang_fall (seg005:0A46): сорваться. Нет пола ни сзади, ни под
|
||||||
* персонажем — seq_23 (отпустить и падать); иначе прижать к стене (-7)
|
* персонажем — seq_23 (отпустить и падать); иначе прижать к стене (-7)
|
||||||
* и seq_11 (встать, конец спуска). Меняет Kid.x, возвращает seq. */
|
* и 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 behind = get_tile_behind_char();
|
||||||
uint8_t at;
|
uint8_t at;
|
||||||
@@ -760,7 +761,7 @@ uint8_t pop_hang_fall_seq(void)
|
|||||||
* либо спуск seq_68 через зацеп, либо отступ от передней кромки), 0 =
|
* либо спуск seq_68 через зацеп, либо отступ от передней кромки), 0 =
|
||||||
* приседать. Меняет Kid.x. Kid развёрнут от края (край сзади) у кромки
|
* приседать. Меняет 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) {
|
if (!tile_is_floor(get_tile_infrontof_char()) && distance_to_edge_weight() < 3) {
|
||||||
Kid.x = (uint8_t)char_dx_forward(5); /* у передней кромки — отступ */
|
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): эффект поднятого предмета. Зовётся из
|
/* proc_get_object (seg006:16CB): эффект поднятого предмета. Зовётся из
|
||||||
* play_seq по опкоду SEQ_GET_ITEM с аргументом 1 (pop_kid). */
|
* 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) {
|
if (pickup_obj_type == -1) {
|
||||||
pop_have_sword = 1; /* в оригинале have_sword = -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 — предмета нет
|
/* check_get_item + get_item (seg005:061F/073E). Возврат: 0 — предмета нет
|
||||||
* (управление идёт обычной веткой); 1 — присесть (caller зовёт crouch());
|
* (управление идёт обычной веткой); 1 — присесть (caller зовёт crouch());
|
||||||
* 2 — поднять меч (caller ставит seq_91). */
|
* 2 — поднять меч (caller ставит seq_91). */
|
||||||
uint8_t pop_get_item_action(void)
|
uint8_t pop_get_item_action(void) __banked
|
||||||
{
|
{
|
||||||
uint8_t t;
|
uint8_t t;
|
||||||
int8_t icol;
|
int8_t icol;
|
||||||
@@ -1113,7 +1114,7 @@ static void do_knock(int tile_row)
|
|||||||
/* check_knock (seg003:0706): по флагу knock (ставит play_seq на seqtbl-
|
/* check_knock (seg003:0706): по флагу knock (ставит play_seq на seqtbl-
|
||||||
* командах KNOCK_UP/DOWN) тряхнуть ряд. KNOCK_DOWN (knock=-1, приземление) →
|
* командах KNOCK_UP/DOWN) тряхнуть ряд. KNOCK_DOWN (knock=-1, приземление) →
|
||||||
* ряд curr_row; KNOCK_UP (knock=+1) → ряд curr_row-1. */
|
* ряд curr_row; KNOCK_UP (knock=+1) → ряд curr_row-1. */
|
||||||
void pop_check_knock(void)
|
void pop_check_knock(void) __banked
|
||||||
{
|
{
|
||||||
if (knock) {
|
if (knock) {
|
||||||
do_knock(Kid.curr_row - (knock > 0));
|
do_knock(Kid.curr_row - (knock > 0));
|
||||||
@@ -1124,7 +1125,7 @@ void pop_check_knock(void)
|
|||||||
/* Сброс состояния loose (при смене комнаты): pop_loose_modif/bake/rest
|
/* Сброс состояния loose (при смене комнаты): pop_loose_modif/bake/rest
|
||||||
* индексируются позицией тайла и не должны утечь из старой комнаты в новую.
|
* индексируются позицией тайла и не должны утечь из старой комнаты в новую.
|
||||||
* Плюс останавливает падающий кусок (pop_bg). */
|
* Плюс останавливает падающий кусок (pop_bg). */
|
||||||
void pop_loose_reset(void)
|
void pop_loose_reset(void) __banked
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < 30; i++) {
|
for (i = 0; i < 30; i++) {
|
||||||
@@ -1183,7 +1184,7 @@ static void check_loose_fall_on_kid(void)
|
|||||||
|
|
||||||
/* animate_loose (seg007:0CBA) + перерисовка изменившихся тайлов на ТЕКУЩЕЙ
|
/* animate_loose (seg007:0CBA) + перерисовка изменившихся тайлов на ТЕКУЩЕЙ
|
||||||
* (back) странице. Звать из основного цикла ПОСЛЕ set_draw_page(back). */
|
* (back) странице. Звать из основного цикла ПОСЛЕ set_draw_page(back). */
|
||||||
void pop_loose_tick(void)
|
void pop_loose_tick(void) __banked
|
||||||
{
|
{
|
||||||
int pos;
|
int pos;
|
||||||
/* row/col ведём бегущими счётчиками, а НЕ через pos/10 и pos%10: у Z80
|
/* row/col ведём бегущими счётчиками, а НЕ через pos/10 и pos%10: у Z80
|
||||||
@@ -1280,7 +1281,7 @@ void pop_loose_tick(void)
|
|||||||
* check_spike_below колонки берутся get_tile_div_mod БЕЗ −7.
|
* check_spike_below колонки берутся get_tile_div_mod БЕЗ −7.
|
||||||
*
|
*
|
||||||
* Возврат: КОМНАТНЫЙ y верхней границы (0 = клипа нет). */
|
* Возврат: КОМНАТНЫЙ 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 };
|
static const int16_t y_clip[5] = { -60, 3, 66, 129, 192 };
|
||||||
int wh = ((int)w + 1) >> 1; /* char_width_half */
|
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 (pop_kid_dead) return; /* труп на пиках — без физики (только seq смерти) */
|
||||||
if (grab_timer) grab_timer--;
|
if (grab_timer) grab_timer--;
|
||||||
|
|||||||
@@ -17,25 +17,25 @@
|
|||||||
* col<0/>9 или row<0/>2 трактуются как стена (край уровня). Массив
|
* col<0/>9 или row<0/>2 трактуются как стена (край уровня). Массив
|
||||||
* МУТАБЕЛЬНЫЙ (loose-пол при падении → empty) — передавать ту же копию,
|
* МУТАБЕЛЬНЫЙ (loose-пол при падении → empty) — передавать ту же копию,
|
||||||
* что и в pop_room_draw, чтобы отрисовка видела изменения. */
|
* что и в pop_room_draw, чтобы отрисовка видела изменения. */
|
||||||
void pop_map_set(uint8_t *fg);
|
void pop_map_set(uint8_t *fg) __banked;
|
||||||
|
|
||||||
/* Связи комнаты (0=нет соседа; иначе номер) + кромки швов для коллизии:
|
/* Связи комнаты (0=нет соседа; иначе номер) + кромки швов для коллизии:
|
||||||
* lcol_fg[6] = col9 левого соседа (за col0) в [0..2] и его col8 (колонка −2)
|
* lcol_fg[6] = col9 левого соседа (за col0) в [0..2] и его col8 (колонка −2)
|
||||||
* в [3..5]; rcol_fg[6] симметрично (col0 / col1 = колонки 10 и 11). Вторая
|
* в [3..5]; rcol_fg[6] симметрично (col0 / col1 = колонки 10 и 11). Вторая
|
||||||
* колонка нужна, когда Kid стоит В шве и смотрит наружу. Звать в enter_room. */
|
* колонка нужна, когда Kid стоит В шве и смотрит наружу. Звать в enter_room. */
|
||||||
void pop_map_set_edges(uint8_t left, uint8_t right, uint8_t up, uint8_t down,
|
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;
|
||||||
|
|
||||||
/* Номер ТЕКУЩЕЙ комнаты (для доступа к room_modif пик/ворот в pop_trob).
|
/* Номер ТЕКУЩЕЙ комнаты (для доступа к room_modif пик/ворот в pop_trob).
|
||||||
* Звать в enter_room. */
|
* Звать в enter_room. */
|
||||||
void pop_map_set_room(uint8_t room);
|
void pop_map_set_room(uint8_t room) __banked;
|
||||||
|
|
||||||
/* HP/смерть. pop_kid_dead=1 когда Kid убит (пики); hitp_curr — текущее HP.
|
/* HP/смерть. pop_kid_dead=1 когда Kid убит (пики); hitp_curr — текущее HP.
|
||||||
* pop_kid_hp_reset() ставит старт HP и снимает смерть (звать в kid_init/
|
* pop_kid_hp_reset() ставит старт HP и снимает смерть (звать в kid_init/
|
||||||
* респавн). */
|
* респавн). */
|
||||||
extern uint8_t pop_kid_dead;
|
extern uint8_t pop_kid_dead;
|
||||||
extern uint8_t hitp_curr;
|
extern uint8_t hitp_curr;
|
||||||
void pop_kid_hp_reset(void);
|
void pop_kid_hp_reset(void) __banked;
|
||||||
|
|
||||||
/* Предметы (seg005 check_get_item/get_item, seg006 do_pickup/proc_get_object).
|
/* Предметы (seg005 check_get_item/get_item, seg006 do_pickup/proc_get_object).
|
||||||
* pop_have_sword — «меч у Кида» (порт have_sword). pop_item_taken — 0 или
|
* pop_have_sword — «меч у Кида» (порт have_sword). pop_item_taken — 0 или
|
||||||
@@ -46,8 +46,8 @@ extern uint8_t pop_item_taken;
|
|||||||
/* Вспышка фона (do_flash/set_bg_attr, seg001:0908): счётчик кадров, пока
|
/* Вспышка фона (do_flash/set_bg_attr, seg001:0908): счётчик кадров, пока
|
||||||
* НУЛЕВАЯ запись палитры подменена ярко-жёлтым. Тикает вызывающий. */
|
* НУЛЕВАЯ запись палитры подменена ярко-жёлтым. Тикает вызывающий. */
|
||||||
extern uint8_t pop_flash_time;
|
extern uint8_t pop_flash_time;
|
||||||
uint8_t pop_get_item_action(void); /* 0 нет / 1 присесть / 2 поднять меч */
|
uint8_t pop_get_item_action(void) __banked; /* 0 нет / 1 присесть / 2 поднять меч */
|
||||||
void pop_proc_get_object(void); /* эффект — из play_seq (опкод GET_ITEM) */
|
void pop_proc_get_object(void) __banked; /* эффект — из play_seq (опкод GET_ITEM) */
|
||||||
|
|
||||||
/* Уход из комнаты ВБОК/ВВЕРХ: 0=нет; 1=left,2=right,3=up (= side+1 для
|
/* Уход из комнаты ВБОК/ВВЕРХ: 0=нет; 1=left,2=right,3=up (= side+1 для
|
||||||
* pop_room_link). Координаты Kid уже репроецированы (x∓140 / y+189).
|
* pop_room_link). Координаты Kid уже репроецированы (x∓140 / y+189).
|
||||||
@@ -66,8 +66,8 @@ extern uint8_t pop_leave_timer;
|
|||||||
* на ТЕКУЩЕЙ странице; звать в основном цикле ПОСЛЕ set_draw_page(back),
|
* на ТЕКУЩЕЙ странице; звать в основном цикле ПОСЛЕ set_draw_page(back),
|
||||||
* рядом с kid-отрисовкой. */
|
* рядом с kid-отрисовкой. */
|
||||||
extern uint8_t pop_loose_modif[30];
|
extern uint8_t pop_loose_modif[30];
|
||||||
void pop_loose_tick(void);
|
void pop_loose_tick(void) __banked;
|
||||||
void pop_loose_reset(void); /* сброс loose-состояния при смене комнаты */
|
void pop_loose_reset(void) __banked; /* сброс loose-состояния при смене комнаты */
|
||||||
|
|
||||||
/* Установлен в tilepos+1 в кадре, когда loose-пол упал (кусок улетел ВНИЗ).
|
/* Установлен в tilepos+1 в кадре, когда loose-пол упал (кусок улетел ВНИЗ).
|
||||||
* Приложение: определить debris-приземление в комнате снизу. Снять (=0). */
|
* Приложение: определить debris-приземление в комнате снизу. Снять (=0). */
|
||||||
@@ -81,7 +81,7 @@ extern uint8_t pop_loose_fell;
|
|||||||
* pop_loose_modif), читает pop_bg. Сигналы приложению (для персистентности
|
* pop_loose_modif), читает pop_bg. Сигналы приложению (для персистентности
|
||||||
* между входами в комнату): pop_ceil_fell = col+1 провалившейся плиты,
|
* между входами в комнату): pop_ceil_fell = col+1 провалившейся плиты,
|
||||||
* pop_debris_at = tilepos+1 щебня, оставшегося в ЭТОЙ комнате. Снимать (=0). */
|
* pop_debris_at = tilepos+1 щебня, оставшегося в ЭТОЙ комнате. Снимать (=0). */
|
||||||
void pop_map_set_above(uint8_t *above_row2_fg);
|
void pop_map_set_above(uint8_t *above_row2_fg) __banked;
|
||||||
extern uint8_t pop_ceil_modif[10];
|
extern uint8_t pop_ceil_modif[10];
|
||||||
extern uint8_t pop_ceil_fell;
|
extern uint8_t pop_ceil_fell;
|
||||||
extern uint8_t pop_debris_at;
|
extern uint8_t pop_debris_at;
|
||||||
@@ -92,7 +92,7 @@ extern uint8_t pop_kid_hurt;
|
|||||||
|
|
||||||
/* check_knock (seg003): по флагу knock (play_seq) тряхнуть loose-полы ряда
|
/* check_knock (seg003): по флагу knock (play_seq) тряхнуть loose-полы ряда
|
||||||
* приземления/удара. Зовётся из pop_phys_tick. */
|
* приземления/удара. Зовётся из pop_phys_tick. */
|
||||||
void pop_check_knock(void);
|
void pop_check_knock(void) __banked;
|
||||||
|
|
||||||
/* Установлен в 1, когда Kid пересёк НИЖНЮЮ границу комнаты (провал в дыру
|
/* Установлен в 1, когда Kid пересёк НИЖНЮЮ границу комнаты (провал в дыру
|
||||||
* или спуск-зацеп с кромки). Координаты Kid УЖЕ репроецированы в кадр
|
* или спуск-зацеп с кромки). Координаты Kid УЖЕ репроецированы в кадр
|
||||||
@@ -104,14 +104,14 @@ extern uint8_t pop_fell_out;
|
|||||||
/* Пер-кадровая физика ПОСЛЕ kid_tick(play_seq): fall_accel + fall_speed +
|
/* Пер-кадровая физика ПОСЛЕ kid_tick(play_seq): fall_accel + fall_speed +
|
||||||
* determine_col + check_action (триггер падения / do_fall / приземление).
|
* determine_col + check_action (триггер падения / do_fall / приземление).
|
||||||
* Порядок как в оригинале (seg000 play_kid_frame). */
|
* Порядок как в оригинале (seg000 play_kid_frame). */
|
||||||
void pop_phys_tick(void);
|
void pop_phys_tick(void) __banked;
|
||||||
|
|
||||||
/* clip_char (seg006:1749), верхняя граница клипа спрайта персонажа: если тайл
|
/* clip_char (seg006:1749), верхняя граница клипа спрайта персонажа: если тайл
|
||||||
* над головой — стена/пол, всё выше линии своей полосы не рисуется (Kid,
|
* над головой — стена/пол, всё выше линии своей полосы не рисуется (Kid,
|
||||||
* ушедший головой под пол при спуске/висе, не просвечивает сквозь щели).
|
* ушедший головой под пол при спуске/висе, не просвечивает сквозь щели).
|
||||||
* obj_x — ЛОГИЧЕСКАЯ X кадра (до ×8/7), obj_y — низ спрайта, w/h — размер.
|
* obj_x — ЛОГИЧЕСКАЯ X кадра (до ×8/7), obj_y — низ спрайта, w/h — размер.
|
||||||
* Возврат: КОМНАТНЫЙ y границы, 0 = клипа нет. Зовёт kid_draw. */
|
* Возврат: КОМНАТНЫЙ y границы, 0 = клипа нет. Зовёт kid_draw. */
|
||||||
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;
|
||||||
|
|
||||||
/* Тип препятствия/края ВПЕРЕДИ по направлению (pop_edge_type после
|
/* Тип препятствия/края ВПЕРЕДИ по направлению (pop_edge_type после
|
||||||
* pop_edge_distance): для control (бежать / осторожный шаг / стоп у стены). */
|
* pop_edge_distance): для control (бежать / осторожный шаг / стоп у стены). */
|
||||||
@@ -120,26 +120,26 @@ int pop_clip_char_top(int obj_x, int obj_y, uint16_t w, uint16_t h);
|
|||||||
#define EDGE_FLOOR 2 /* пол (нет препятствия рядом, дистанция = 11) */
|
#define EDGE_FLOOR 2 /* пол (нет препятствия рядом, дистанция = 11) */
|
||||||
|
|
||||||
/* Расстояние до края/стены впереди + побочно g_edge_type (pop_edge_type). */
|
/* Расстояние до края/стены впереди + побочно g_edge_type (pop_edge_type). */
|
||||||
int pop_edge_distance(void);
|
int pop_edge_distance(void) __banked;
|
||||||
uint8_t pop_edge_type(void);
|
uint8_t pop_edge_type(void) __banked;
|
||||||
|
|
||||||
/* Стена впереди в пределах стопа? Если да — прижимает Kid.x к корректной
|
/* Стена впереди в пределах стопа? Если да — прижимает Kid.x к корректной
|
||||||
* позиции (передний край у стены, симметрично) и возвращает 1. Для
|
* позиции (передний край у стены, симметрично) и возвращает 1. Для
|
||||||
* control_running (чистый стоп у стены). */
|
* control_running (чистый стоп у стены). */
|
||||||
int pop_wall_ahead(void);
|
int pop_wall_ahead(void) __banked;
|
||||||
|
|
||||||
/* Прыжок вверх в стойке (↑): seq чистого прыжка (seq_28/seq_14) ЛИБО
|
/* Прыжок вверх в стойке (↑): seq чистого прыжка (seq_28/seq_14) ЛИБО
|
||||||
* прыжка-с-зацепом за уступ выше (seq_8/24/16) + выравнивание Kid.x.
|
* прыжка-с-зацепом за уступ выше (seq_8/24/16) + выравнивание Kid.x.
|
||||||
* check_jump_up/grab_up (K4.4). control_up гасит caller. */
|
* check_jump_up/grab_up (K4.4). control_up гасит caller. */
|
||||||
uint8_t pop_jump_up_seq(void);
|
uint8_t pop_jump_up_seq(void) __banked;
|
||||||
|
|
||||||
/* ---- Вис/зацеп/спуск (K4.2/K4.3) — тайловые решения для pop_ctrl --- *
|
/* ---- Вис/зацеп/спуск (K4.2/K4.3) — тайловые решения для pop_ctrl --- *
|
||||||
* Управление (control_hanging/can_climb_up/hang_fall/down_pressed) в
|
* Управление (control_hanging/can_climb_up/hang_fall/down_pressed) в
|
||||||
* pop_ctrl; здесь — предикаты + выбор seq (+ выравнивание Kid.x). */
|
* pop_ctrl; здесь — предикаты + выбор seq (+ выравнивание Kid.x). */
|
||||||
uint8_t pop_hang_grab_ready(void); /* grab_timer истёк — можно climb-up */
|
uint8_t pop_hang_grab_ready(void) __banked; /* grab_timer истёк — можно climb-up */
|
||||||
uint8_t pop_hang_climb_up_seq(void); /* seq_10 / seq_73 (подтягивание) */
|
uint8_t pop_hang_climb_up_seq(void) __banked; /* seq_10 / seq_73 (подтягивание) */
|
||||||
int8_t pop_hang_wall(void); /* Shift в висе: 1=у стены,-1=fall,0=держ.*/
|
int8_t pop_hang_wall(void) __banked; /* Shift в висе: 1=у стены,-1=fall,0=держ.*/
|
||||||
uint8_t pop_hang_fall_seq(void); /* seq_23 / seq_11 (сорваться), +Kid.x */
|
uint8_t pop_hang_fall_seq(void) __banked; /* seq_23 / seq_11 (сорваться), +Kid.x */
|
||||||
uint8_t pop_down_action(void); /* 1=обработано(спуск/отступ), 0=присед */
|
uint8_t pop_down_action(void) __banked; /* 1=обработано(спуск/отступ), 0=присед */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* pop_state.c — данные, которые читают ОБЕ стороны банковой границы.
|
||||||
|
*
|
||||||
|
* Зачем отдельный модуль: sprinter-cc собирает банковый модуль с
|
||||||
|
* --dataseg BANKn, поэтому ВСЯ его писучая память (глобалы, file-static,
|
||||||
|
* статики внутри функций) линкуется В СТРАНИЦУ БАНКА и снаружи не читается
|
||||||
|
* — проверено на .map (2026-07-30: глобал банкового модуля лёг по
|
||||||
|
* 0x0001C000, а не в _DATA). Значит любую переменную, к которой нужен
|
||||||
|
* доступ и из банка, и снаружи, надо держать в НЕбанковом модуле — здесь.
|
||||||
|
*
|
||||||
|
* Модуль обязан оставаться в W1/W2: его читают и главный цикл, и банки.
|
||||||
|
*/
|
||||||
|
#include "pop_state.h"
|
||||||
|
|
||||||
|
uint8_t pop_loose_landed;
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
* pop_state.h — состояние, общее для банков и W1/W2. См. pop_state.c.
|
||||||
|
*
|
||||||
|
* Правило: если переменную читают/пишут по обе стороны банковой границы —
|
||||||
|
* её место здесь, а НЕ в банковом модуле (там она уедет в страницу банка).
|
||||||
|
*/
|
||||||
|
#ifndef POP_STATE_H
|
||||||
|
#define POP_STATE_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/* Кусок loose приземлился (loose_land, seg007:11E8): 0 = нет, иначе
|
||||||
|
* tilepos+1 тайла, на который он лёг. Ставит отрисовка mob (банк),
|
||||||
|
* разбирает логика loose-полов (pop_map, W1/W2). */
|
||||||
|
extern uint8_t pop_loose_landed;
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -21,28 +21,33 @@
|
|||||||
|
|
||||||
__sfr __at (0xFE) io_border;
|
__sfr __at (0xFE) io_border;
|
||||||
|
|
||||||
/* ПРОФИЛИРОВАНИЕ ПОЛОСАМИ БОРДЮРА (make PROF=1). Цвет бордюра держится,
|
/* ПРОФИЛИРОВАНИЕ ПОЛОСАМИ БОРДЮРА (включено по умолчанию; make PROF=0 —
|
||||||
* пока фаза считает, поэтому высота полосы на скриншоте = время фазы в
|
* выключить). Цвет бордюра держится, пока фаза считает, поэтому высота
|
||||||
* растровых строках (1 строка ≈ 224 такта Z80 при 3.5 МГц). Это
|
* полосы на скриншоте = время фазы в растровых строках. Это единственный
|
||||||
* единственный способ мерить здесь: мост MAME отвечает из фреймового
|
* способ смотреть профиль без дебаггера: выборка PC вырождается (мост MAME
|
||||||
* колбэка, поэтому выборка PC вырождается (100 % сэмплов в обработчике
|
* отвечает из фреймового колбэка, все сэмплы падают в обработчик
|
||||||
* прерывания). Фазы:
|
* прерывания); точные такты — breakpoint'ы с {printf totalcycles; g}.
|
||||||
|
*
|
||||||
|
* ЦВЕТА: у бордюра Sprinter бит 0 (красный) ИГНОРИРУЕТСЯ, работают только
|
||||||
|
* бит 1 (синий) и бит 2 (зелёный) — значит различимых состояний ровно
|
||||||
|
* ЧЕТЫРЕ, и значения обязаны быть чётными. Отсюда фазы сгруппированы по
|
||||||
|
* четыре, а не по семь (нечётные номера раньше сливались с соседями и
|
||||||
|
* полосы не читались):
|
||||||
* 0 чёрный — ожидание vsync (запас кадра)
|
* 0 чёрный — ожидание vsync (запас кадра)
|
||||||
* 1 синий — ввод + heal (стереть прошлые спрайты)
|
* 2 синий — ввод, heal и ЛОГИКА (kid_tick/физика/страж)
|
||||||
* 2 красный — логика (kid_tick/физика/страж в банке)
|
* 4 зелёный — слой ФОНА (loose/trobs/redraw_needed/шов)
|
||||||
* 3 лиловый — слой фона (loose/trobs/redraw_needed/шов)
|
* 6 циан — СПРАЙТЫ (страж, Kid, fore поверх них) */
|
||||||
* 4 зелёный — kid_draw
|
#ifndef PROF_BORDER
|
||||||
* 5 циан — guard_draw + fore поверх стража
|
#define PROF_BORDER 1
|
||||||
* 6 жёлтый — fore поверх Kid + чистка бортов
|
#endif
|
||||||
* 7 белый — флип */
|
#if PROF_BORDER
|
||||||
#ifdef PROF_BORDER
|
|
||||||
#define PROF(n) io_border = (n)
|
#define PROF(n) io_border = (n)
|
||||||
#else
|
#else
|
||||||
#define PROF(n) ((void)0)
|
#define PROF(n) ((void)0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Сколько банков грузит crt0_banked (читает его стартовый код). */
|
/* Сколько банков грузит crt0_banked (читает его стартовый код). */
|
||||||
const uint8_t n_banks = 1;
|
const uint8_t n_banks = 3;
|
||||||
|
|
||||||
/* Режим читов (pop_cheat.h): на время разработки включаем в main. */
|
/* Режим читов (pop_cheat.h): на время разработки включаем в main. */
|
||||||
uint8_t pop_cheats;
|
uint8_t pop_cheats;
|
||||||
@@ -287,7 +292,7 @@ int main(void)
|
|||||||
/* SPACE — тумблер дабл-буфера (edge, чтоб одно нажатие = один
|
/* SPACE — тумблер дабл-буфера (edge, чтоб одно нажатие = один
|
||||||
* переключ). Выключение возвращает показ на страницу 0. */
|
* переключ). Выключение возвращает показ на страницу 0. */
|
||||||
|
|
||||||
PROF(1); /* ввод + heal */
|
PROF(2); /* ввод + heal */
|
||||||
|
|
||||||
uint8_t sp = kbd_raw_down(KBD_SPACE);
|
uint8_t sp = kbd_raw_down(KBD_SPACE);
|
||||||
if (sp && !sp_prev) {
|
if (sp && !sp_prev) {
|
||||||
@@ -355,7 +360,7 @@ int main(void)
|
|||||||
kid_heal(); /* стереть прошлый кадр ЭТОЙ страницы */
|
kid_heal(); /* стереть прошлый кадр ЭТОЙ страницы */
|
||||||
pop_guard_heal(); /* и прошлый кадр стража */
|
pop_guard_heal(); /* и прошлый кадр стража */
|
||||||
pop_fore_heal(); /* + следы оверлея (шире прямоугольника Kid) */
|
pop_fore_heal(); /* + следы оверлея (шире прямоугольника Kid) */
|
||||||
PROF(2); /* логика */
|
PROF(2); /* логика (тот же синий) */
|
||||||
kid_tick(); /* play_seq: следующий кадр */
|
kid_tick(); /* play_seq: следующий кадр */
|
||||||
pop_phys_tick(); /* K3: падение/приземление/стена */
|
pop_phys_tick(); /* K3: падение/приземление/стена */
|
||||||
pop_guard_tick(); /* логика стража — В БАНКЕ (guards.c) */
|
pop_guard_tick(); /* логика стража — В БАНКЕ (guards.c) */
|
||||||
@@ -381,7 +386,7 @@ int main(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PROF(3); /* слой фона */
|
PROF(4); /* слой фона */
|
||||||
|
|
||||||
pop_loose_tick(); /* loose-полы: анимация + перерисовка (СЛОЙ ФОНА */
|
pop_loose_tick(); /* loose-полы: анимация + перерисовка (СЛОЙ ФОНА */
|
||||||
/* — ДО Kid, чтобы Kid всегда был поверх плиты) */
|
/* — ДО Kid, чтобы Kid всегда был поверх плиты) */
|
||||||
@@ -466,9 +471,9 @@ int main(void)
|
|||||||
flash_on = 1;
|
flash_on = 1;
|
||||||
}
|
}
|
||||||
update_kid_render_dx(); /* straddle: смещение спрайта, если kid_room≠cur_room */
|
update_kid_render_dx(); /* straddle: смещение спрайта, если kid_room≠cur_room */
|
||||||
PROF(5); /* страж: спрайт + fore поверх него */
|
PROF(6); /* спрайты: страж, Kid, fore поверх */
|
||||||
pop_guard_draw(); /* страж — ДО Kid (порядок как в оригинале) */
|
pop_guard_draw(); /* страж — ДО Kid (порядок как в оригинале) */
|
||||||
PROF(4); /* kid_draw */
|
PROF(6); /* kid_draw (тот же циан) */
|
||||||
kid_draw(); /* нарисовать новый кадр (детект выхода за поле) */
|
kid_draw(); /* нарисовать новый кадр (детект выхода за поле) */
|
||||||
pop_loose_mob_draw_over(); /* падающая плита НИЖЕ Kid → поверх него (y-порядок) */
|
pop_loose_mob_draw_over(); /* падающая плита НИЖЕ Kid → поверх него (y-порядок) */
|
||||||
if (pop_kid_hurt) { /* HP убавилось → «брызги» удара (draw_hurt_splash) */
|
if (pop_kid_hurt) { /* HP убавилось → «брызги» удара (draw_hurt_splash) */
|
||||||
|
|||||||
+17
-1
@@ -33,6 +33,9 @@
|
|||||||
# --data-loc 0xN override SDCC --data-loc (default: derived from --memory)
|
# --data-loc 0xN override SDCC --data-loc (default: derived from --memory)
|
||||||
# -Wl FLAG extra linker flag (repeatable)
|
# -Wl FLAG extra linker flag (repeatable)
|
||||||
# --bank N=FILE.c compile FILE.c as bank N; repeatable; pulls crt0_banked
|
# --bank N=FILE.c compile FILE.c as bank N; repeatable; pulls crt0_banked
|
||||||
|
# --bank-data put bank modules' writable data INTO the bank page
|
||||||
|
# (default: it goes to the shared _DATA in W1/W2, which
|
||||||
|
# stays mapped and is visible from everywhere)
|
||||||
# automatically and adds -Wl-b_BANKN=0x{N}C000
|
# automatically and adds -Wl-b_BANKN=0x{N}C000
|
||||||
# --w3 FILE.c place FILE.c resident in window 3 (0xC000), called
|
# --w3 FILE.c place FILE.c resident in window 3 (0xC000), called
|
||||||
# DIRECTLY (no trampoline). Repeatable. Defaults to
|
# DIRECTLY (no trampoline). Repeatable. Defaults to
|
||||||
@@ -108,6 +111,7 @@ MKEXE_EXTRA=()
|
|||||||
BANK_SPECS=() # entries like "1=engine.c"
|
BANK_SPECS=() # entries like "1=engine.c"
|
||||||
W3_SPECS=() # entries like "mod.c" — резидентные модули окна W3 (--w3)
|
W3_SPECS=() # entries like "mod.c" — резидентные модули окна W3 (--w3)
|
||||||
USER_DEFS=() # -DFOO / -DFOO=bar — пробрасываются в sdcc как есть
|
USER_DEFS=() # -DFOO / -DFOO=bar — пробрасываются в sdcc как есть
|
||||||
|
BANK_LOCAL_DATA=0 # 1 (--bank-data): писучие данные банков — В СТРАНИЦУ банка
|
||||||
W3_RELS=() # заполняется при компиляции W3-модулей
|
W3_RELS=() # заполняется при компиляции W3-модулей
|
||||||
W3_LD_FLAGS=() # -Wl-b_W3CODE=0xC000, если есть --w3
|
W3_LD_FLAGS=() # -Wl-b_W3CODE=0xC000, если есть --w3
|
||||||
USER_SET_MEMORY="" # непусто, если --memory задан явно (для --w3 авто-small)
|
USER_SET_MEMORY="" # непусто, если --memory задан явно (для --w3 авто-small)
|
||||||
@@ -143,6 +147,7 @@ while [[ $# -gt 0 ]]; do
|
|||||||
-Wl) LD_EXTRA+=("$2"); shift 2;;
|
-Wl) LD_EXTRA+=("$2"); shift 2;;
|
||||||
-D*) USER_DEFS+=("$1"); shift;;
|
-D*) USER_DEFS+=("$1"); shift;;
|
||||||
--bank) BANK_SPECS+=("$2"); shift 2;;
|
--bank) BANK_SPECS+=("$2"); shift 2;;
|
||||||
|
--bank-data) BANK_LOCAL_DATA=1; shift;;
|
||||||
--mkexe) MKEXE_EXTRA+=("$2"); shift 2;;
|
--mkexe) MKEXE_EXTRA+=("$2"); shift 2;;
|
||||||
--max-allocs) MAX_ALLOCS="$2"; shift 2;;
|
--max-allocs) MAX_ALLOCS="$2"; shift 2;;
|
||||||
--gfx) GFX_MODE="$2"; shift 2;;
|
--gfx) GFX_MODE="$2"; shift 2;;
|
||||||
@@ -423,8 +428,19 @@ if [[ "$CRT0_TYPE" == "banked" ]]; then
|
|||||||
bank_n="${spec%%=*}"
|
bank_n="${spec%%=*}"
|
||||||
bank_src="${spec#*=}"
|
bank_src="${spec#*=}"
|
||||||
rel="$WORK/bank${bank_n}_$(basename "$bank_src" .c).rel"
|
rel="$WORK/bank${bank_n}_$(basename "$bank_src" .c).rel"
|
||||||
|
# По умолчанию --dataseg НЕ задаём: писучие данные банкового
|
||||||
|
# модуля (глобалы, file-static, статики функций) остаются в
|
||||||
|
# общем _DATA, то есть в W1/W2 — они замаплены всегда и видны
|
||||||
|
# и банку, и остальному коду. С --dataseg BANKn они уезжают в
|
||||||
|
# СТРАНИЦУ БАНКА и снаружи не читаются (проверено на .map:
|
||||||
|
# глобал банкового модуля лёг по 0x0001C000): это экономит
|
||||||
|
# W1/W2, но требует ручного контроля видимости, поэтому
|
||||||
|
# включается явно через --bank-data.
|
||||||
|
bank_data_flags=()
|
||||||
|
[[ $BANK_LOCAL_DATA -eq 1 ]] && bank_data_flags=(--dataseg "BANK${bank_n}")
|
||||||
run "$SDCC" "${CC_FLAGS[@]}" \
|
run "$SDCC" "${CC_FLAGS[@]}" \
|
||||||
--codeseg "BANK${bank_n}" --constseg "BANK${bank_n}" --dataseg "BANK${bank_n}" \
|
--codeseg "BANK${bank_n}" --constseg "BANK${bank_n}" \
|
||||||
|
"${bank_data_flags[@]}" \
|
||||||
-c -o "$rel" "$bank_src"
|
-c -o "$rel" "$bank_src"
|
||||||
BANK_RELS+=("$rel")
|
BANK_RELS+=("$rel")
|
||||||
# Virtual address: bank_n in upper byte, BANK_LOW16 in low half.
|
# Virtual address: bank_n in upper byte, BANK_LOW16 in low half.
|
||||||
|
|||||||
Reference in New Issue
Block a user