DRAW-CHAR: отрисовка одна на всех Char; разгрузка банка 2 (90.4% -> 72.9%)
DRAW-CHAR. Отрисовка персонажа сведена к одному набору функций над Char — как физика после GUARD-PHYS. В оригинале add_kid_to_objtable (seg008:22F0) и add_guard_to_objtable (seg008:2324) имеют идентичное тело и различаются окном (loadkid/loadshad), набором спрайтов и типом объекта, а redraw_at_char/redraw_at_char2 гейтов по charid не имеют вовсе. pop_gdraw.c -> pop_cdraw.c: pop_char_draw/heal/fore(who), слот POP_CH_KID / POP_CH_OPP; состояние слотов pop_cd[] в _DATA — читается из любого банка без трамплина. Проход окклюзии тоже один (pop_fore_over_char), pop_fore_over_kid больше нет. Починилось само (расхождения, которые и были ценой дублирования): у соперника не было clip_char; у Кида не было клипа полем 192 и ветки брызг «мёртв/падение»; char_width_half СТРАЖА считался по спрайту КИДА. Замер: _CODE 24 881 -> 20 524 (куча 2023 -> 6333), BANK2 -265, итого -3.2 КБ. Проверено пользователем в MAME; циан-полоса профиля подросла — оптимизация заведена отдельной задачей DRAW-COST. MEM-BANK2, шаг 1: общие «листья» слоя фона в РЕЗИДЕНТ (pop_tile.c/.h). Ограничение платформы: писучие данные банка лежат в _DATA и видны всем, а const-таблицы — в странице банка, из другого банка их не прочитать; трамплин же выбирается объявлением, то есть __banked на листе бьёт и по горячим вызывающим (654 такта). W1 замаплено всегда — оттуда обе половины зовут листья прямым call и читают таблицы напрямую. MEM-BANK2, шаг 2: дедуп внутри банка. wall_pattern 808 -> 394 и wall_rnd 786 -> 654: четыре ветки по виду стены отличались только набором кусков и числами в одной серии prandom — сведены к таблицам WP_PARTS и WR_RULE, порядок вызовов prandom сохранён дословно. Заодно: kid_seq_off больше не static const в kid_data.h (230 Б мёртвой копии в каждом из 9 модулей) — генератор pop_extract_kid_data.py отдаёт макро-инициализатор, массив определяет один pop_kid.c. Итог: BANK2 14 815 -> 11 942 (72.9 %, свободно 4442 Б), _CODE 22 556, куча 4301 Б. tests-host зелёные (65/39/53/1723/1); в MAME комната 1 совпала с дорефакторным снимком попиксельно (0 из 227 520), комната 3 — та же раскладка кладки. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
#define POP_BG_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "pop_char.h" /* pop_char_t — общий проход отрисовки поверх Char */
|
||||
|
||||
/* ---- Вертикальный layout (PoP-экран 320×200 в нашем 320×256) --------- *
|
||||
* Игровой экран 200px центрируем по высоте: сдвиг всего рисунка вниз на
|
||||
@@ -51,47 +52,40 @@ void pop_room_draw(uint8_t room_num,
|
||||
* room_B(0, col-1). ОДИННАДЦАТЬ байт: [0..9] — колонки комнаты снизу,
|
||||
* [10] — тайл (0,9) комнаты СНИЗУ-СЛЕВА (сосед угла (2,0); см.
|
||||
* load_rowbelow, seg008:368). 0 — нет комнаты снизу. */
|
||||
void pop_room_set_below(const uint8_t *below_row0_fg) __banked;
|
||||
/* НЕ __banked: тело в резиденте (pop_tile.c) — из банка зовётся прямым call. */
|
||||
void pop_room_set_below(const uint8_t *below_row0_fg);
|
||||
|
||||
/* Задать ряд 2 (fg-коды + модификаторы, 10 шт.) комнаты СВЕРХУ — для полосы
|
||||
* кладки у потолка (seg008 draw_room доп. верхний ряд из room_A). 0 — нет
|
||||
* комнаты сверху (кромка уровня → пол). */
|
||||
void pop_room_set_above(const uint8_t *above_row2_fg, const uint8_t *above_row2_mod) __banked;
|
||||
void pop_room_set_above(const uint8_t *above_row2_fg, const uint8_t *above_row2_mod);
|
||||
|
||||
/* Перерисовать передний слой (fore) тайлов футпринта Kid ПОВЕРХ него —
|
||||
* звать ПОСЛЕ kid_draw. obj_x — ЛОГИЧЕСКАЯ X кадра (до ×8/7), obj_y — низ
|
||||
* спрайта, w/h — размер кадра, dir — направление Kid (<0 влево). Метрики
|
||||
* берутся из 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,
|
||||
int8_t dir, uint8_t frame, uint8_t action) __banked;
|
||||
/* Перерисовать передний слой (fore) и оверлеи тайлов ПОВЕРХ персонажа —
|
||||
* ОДИН проход на всех Char (Кид, страж, скелет, дальше тень/визирь): в
|
||||
* оригинале add_kid_to_objtable и add_guard_to_objtable имеют одинаковое
|
||||
* тело, а redraw_at_char/redraw_at_char2 гейтов по charid не имеют.
|
||||
* Звать ПОСЛЕ отрисовки спрайта, когда окно fore-клипа уже стоит
|
||||
* (pop_fore_set_clip) — перебор тайлов расширяется по нему.
|
||||
*
|
||||
* ch — персонаж (Kid/Guard): из него берутся direction/sword/frame/action и
|
||||
* curr_col/curr_row. obj_x — ЛОГИЧЕСКАЯ X кадра (до ×8/7), obj_y — низ
|
||||
* спрайта, w/h — размер кадра. См. redraw_at_char/set_char_collision. */
|
||||
void pop_fore_over_char(const pop_char_t *ch, int obj_x, int obj_y,
|
||||
uint16_t w, uint16_t h) __banked;
|
||||
|
||||
/* Окно fore-слоя: прямоугольник СПРАЙТА (экранные координаты, y уже с
|
||||
* POP_YOFF), поверх которого fore-проход возвращает куски тайлов. Ставит
|
||||
* тот, кто нарисовал спрайт (kid_draw / pop_guard_draw) — он один знает
|
||||
* тот, кто нарисовал спрайт (pop_char_draw) — он один знает
|
||||
* итоговый габарит (у Kid — с учётом клинка и обрезки clip_char). Вне
|
||||
* fore-проходов окно игнорируется: фон рисуется целиком. Мотивация и
|
||||
* замер — в pop_bg.c у fclip_on. */
|
||||
void pop_fore_set_clip(int x, int y, int w, int h) __banked;
|
||||
|
||||
/* То же для НЕ-Kid персонажа (страж): только слой fore + полоса потолка,
|
||||
* без оверлеев поз виса/полёта/подъёма. obj_x — ЛОГИЧЕСКАЯ координата
|
||||
* (до ×8/7), как у kid_fp_obj_x(). */
|
||||
/* __banked: отрисовка стража уехала в СВОЙ банк (pop_gdraw.c), поэтому
|
||||
* вызов стал кроссбанковым и обязан идти через трамплин. Зовётся раз в
|
||||
* кадр, других вызывающих нет — цена одного трамплина здесь не видна. */
|
||||
/* ex/ey/ew/eh — ОБЪЕДИНЁННЫЙ экранный прямоугольник «персонаж + клинок +
|
||||
* брызги» (тот же, что уходит в pop_fore_set_clip): перебор передних тайлов
|
||||
* идёт по нему, иначе меч и звёздочка удара остаются поверх кладки.
|
||||
* ew == 0 — расширения нет (только габарит кадра). */
|
||||
void pop_fore_over_char(int obj_x, int obj_y, uint16_t w, uint16_t h,
|
||||
int8_t dir, uint8_t sword,
|
||||
int ex, int ey, uint16_t ew, uint16_t eh,
|
||||
uint8_t action, int8_t ccol, int8_t crow) __banked;
|
||||
void pop_fore_set_clip(int x, int y, int w, int h);
|
||||
|
||||
/* Восстановить фон там, где в прошлых кадрах рисовался ОВЕРЛЕЙ
|
||||
* (draw_other_overlay/floor_overlay/полоса потолка): он выходит за
|
||||
* прямоугольник Kid, поэтому kid_heal его не убирает — на второй странице
|
||||
* дабл-буфера остаётся след и мерцает. Звать рядом с kid_heal. */
|
||||
* прямоугольник персонажа, поэтому его heal этого не убирает — на второй
|
||||
* странице дабл-буфера остаётся след и мерцает. Звать рядом с
|
||||
* pop_char_heal. */
|
||||
void pop_fore_heal(void) __banked;
|
||||
|
||||
/* Loose floors — динамическая отрисовка (состояние pop_loose_modif в
|
||||
@@ -154,7 +148,7 @@ void pop_loose_mob_reset(void) __banked; /* убрать все куски (С
|
||||
void pop_loose_mob_room_changed(void) __banked;
|
||||
|
||||
/* Кусок НИЖЕ Kid по obj_y → рисуется ПОВЕРХ него (порт sort_curr_objs,
|
||||
* seg008:1561). Звать после kid_draw, перед fore-слоем. */
|
||||
* seg008:1561). Звать после отрисовки персонажей, перед fore-слоем. */
|
||||
void pop_loose_mob_draw_over(void) __banked;
|
||||
|
||||
/* Позиция куска (колонка, y низа) для check_loose_fall_on_kid. 0 — нет. */
|
||||
@@ -169,7 +163,7 @@ void pop_clip_sprite(int x, int w, int sy_top, int h) __banked;
|
||||
/* Почистить борта (верхний + статус-полоса/нижний) — но ТОЛЬКО в кадрах,
|
||||
* где кто-то реально вышел за поле (гейт по флагу от pop_clip_sprite):
|
||||
* даром в покое, O(1) при падении (не зависит от числа спрайтов). Звать
|
||||
* КАЖДЫЙ кадр ПОСЛЕ kid_draw+fore на back-странице. */
|
||||
* КАЖДЫЙ кадр ПОСЛЕ персонажей и fore на back-странице. */
|
||||
void pop_room_clip_borders(void) __banked;
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user