L9-INVERT II.4: персонажи рисуются перевёрнутыми (зеркальные страницы атласов)
Спрайты персонажей хранятся column-major (ради бесплатного H-флипа), а вертикальное зеркало у такой раскладки — разворот байтов ВНУТРИ колонки, чего accel не умеет. Поэтому pop_vflip.c готовит зеркальные КОПИИ страниц атласов: копия побайтово повторяет раскладку .atl (заголовок, каталог, смещения лент), развёрнуты только пиксели — значит вызывающему достаточно подменить номер страницы, которую он мапит в W0. * Кэш ленивый (страница зеркалится при первом обращении в перевёрнутом виде) и живёт до смены уровня — зелье переключает состояние туда-обратно, перезеркаливать по 16 КБ на каждый переворот незачем. EMM хватает: 34 страницы из ~215 свободных. * pop_cdraw/pop_kdraw: страница + позиция (top = 191 - obj_y для персонажа, 192 - top - h для клинка). «Пропустить skip строк сверху» у зеркальной ленты = «срезать снизу» у оригинала, поэтому клипы считаются как обычно. * Модуль резидентный: он маппит W3 (приёмник копии) — банку так нельзя. * pop_vflip_reset на смене уровня: копии сделаны из старых страниц. Проверено в MAME: чит U переворачивает всё разом, Кид и факелы вверх ногами, полоса HP на месте, бег без следов на фоне (heal бьёт в те же координаты). ОСТАЁТСЯ (L9-CLIPCHAR): clip_char в перевороте должен резать снизу, а не сверху — пока при pop_upside не режем вовсе. Тени/брызг это не касается.
This commit is contained in:
@@ -20,7 +20,8 @@
|
||||
#include <sprite.h>
|
||||
#include "pop_guard.h"
|
||||
#include "pop_kid.h"
|
||||
#include "_pop_kdraw.h" /* меч + блит по id — сосед по банку 4 */ /* атласы/кадр Кида, pop_sword_draw, окна Char */
|
||||
#include "_pop_kdraw.h"
|
||||
#include "pop_vflip.h" /* зеркальные страницы атласов (зелье инверсии) */ /* меч + блит по id — сосед по банку 4 */ /* атласы/кадр Кида, pop_sword_draw, окна Char */
|
||||
#include "pop_cdraw.h"
|
||||
#include "pop_bg.h" /* POP_YOFF, pop_fore_over_char, pop_fore_set_clip */
|
||||
#include "_pop_draw.h" /* pop_onscreen_cols / pop_heal_fast */
|
||||
@@ -521,7 +522,18 @@ void pop_char_draw(uint8_t who) __banked
|
||||
idx = (uint8_t)(fr->image & 7);
|
||||
if (page >= npages) return; /* страница набора не загружена */
|
||||
img = (const uint8_t *)atlas_image(&pages[page], idx);
|
||||
gfx_w0_map(pages[page].page);
|
||||
/* ПЕРЕВОРОТ (зелье инверсии): тот же атлас, но страница с вертикально
|
||||
* зеркальными пикселями — смещения лент и размеры кадров у копии те же,
|
||||
* поэтому меняется ровно номер страницы (pop_vflip.h). Если EMM не
|
||||
* дала страницу — рисуем обычной: неперевёрнутый кадр лучше дыры. */
|
||||
{
|
||||
uint8_t vpg = pages[page].page;
|
||||
if (pop_upside) {
|
||||
uint8_t f = pop_vflip_page(vpg);
|
||||
if (f) vpg = f;
|
||||
}
|
||||
gfx_w0_map(vpg);
|
||||
}
|
||||
w = (uint16_t)(img[0] | ((uint16_t)img[1] << 8));
|
||||
h = (uint16_t)(img[2] | ((uint16_t)img[3] << 8));
|
||||
dp = gfx_get_draw_page() & 1;
|
||||
@@ -534,13 +546,24 @@ void pop_char_draw(uint8_t who) __banked
|
||||
bx = obj_x;
|
||||
if (flip) bx -= (int)w;
|
||||
top = obj_y - (int)h + 1;
|
||||
/* Поле переворачивается вокруг своей середины: строка t уходит в
|
||||
* (POP_PLAYFIELD_H - 1 - t), значит верх кадра [top, top+h) —
|
||||
* в 192 - top - h, что при top = obj_y-h+1 даёт ровно 191 - obj_y.
|
||||
* Пиксели уже зеркальны (страница выше), поэтому дальше всё
|
||||
* считается как обычно: «пропустить skip строк сверху» у зеркальной
|
||||
* ленты означает «срезать снизу» у оригинала — ровно то, что нужно. */
|
||||
if (pop_upside) top = (POP_PLAYFIELD_H - 1) - obj_y;
|
||||
vis_w = w;
|
||||
lskip = 0;
|
||||
skip = 0;
|
||||
/* clip_char (seg006:1231/1749): тайл над головой — стена/пол → всё
|
||||
* выше линии полосы своего ряда НЕ рисуется, иначе персонаж
|
||||
* просвечивает сквозь щели кладки при спуске/висе. */
|
||||
ct = pop_clip_char_top(fp_x, obj_y, w, h);
|
||||
/* clip_char в перевёрнутом виде должен резать СНИЗУ, а не сверху
|
||||
* (тайл над головой стал тайлом под ногами) — отдельная задача
|
||||
* L9-CLIPCHAR; пока в перевороте не режем вовсе: артефакт мельче,
|
||||
* чем срезанный не с той стороны персонаж. */
|
||||
ct = pop_upside ? -1000 : pop_clip_char_top(fp_x, obj_y, w, h);
|
||||
if (ct > top) {
|
||||
skip = ct - top;
|
||||
if (skip > (int)h) skip = (int)h; /* обрезан целиком */
|
||||
|
||||
Reference in New Issue
Block a user