L9-INVERT: зеркальный слой фона + вход в комнату в банк 8
II.3: pop_upside проведён в единственную точку тайлового слоя (pop_blit_b / blit_b_clip): позиция через FLIP_TOP, блит — vflip-двойник. Этим зеркалятся полная отрисовка комнаты, точечные редрои, trob-анимации, fore-слой и кладка. В клипованном пути обрезка сверху экрана съедает нижние строки источника, поэтому кусок пересчитывается как sy' = h - sy - dh. MEM-COLD2 п.1: enter_room_side/enter_room — в банк 8 (куча 450 -> 1231 Б). Рабочие массивы комнаты остались в _DATA, в банк уехал только код. Проверено в MAME (уровень 9, чит U): комната перевёрнута целиком, пол вверху, дверь и кладка вверх ногами. tests-host 6/6, size-check OK. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -10,7 +10,8 @@
|
||||
#include <graphics.h>
|
||||
#include <gfx.h>
|
||||
#include <sprite.h>
|
||||
#include "pop_bg.h" /* POP_YOFF */
|
||||
#include "pop_bg.h" /* POP_YOFF, POP_PLAYFIELD_H */
|
||||
#include "pop_map.h" /* pop_upside — переворот (зелье инверсии) */
|
||||
#include "pop_cdraw.h" /* POP_CD_TOUCH — фон тронут, персонажей перерисовать */
|
||||
#include "pop_tile.h"
|
||||
#include "pop_level.h" /* pop_doorlink2 — подстановка нажатой кнопки */
|
||||
@@ -262,6 +263,12 @@ void pop_cd_clear(uint8_t p)
|
||||
* платили и блиты БЕЗ клипа (`ld -n(ix)` = 19 тактов номинала, у нас ~46).
|
||||
* А блитов без клипа большинство: весь фон вне fore-прохода — факелы, зелья,
|
||||
* перерисовка тайлов — идёт с pop_t_fclip_on == 0. */
|
||||
/* Экранный y при ПЕРЕВОРОТЕ (зелье инверсии): поле отражается внутри себя,
|
||||
* борта не трогаются. Одна формула на весь слой фона — если её продублируют
|
||||
* где-то ещё, получим двойной переворот (см. l9_invert_plan.md §II.2:
|
||||
* зеркалит ТОЛЬКО вызывающий, у примитивов семантика не меняется). */
|
||||
#define FLIP_TOP(top, h) (2 * POP_YOFF + POP_PLAYFIELD_H - (top) - (int)(h))
|
||||
|
||||
static void blit_b_clip(const uint8_t *img, int x, int top, int w, int h)
|
||||
{
|
||||
int dx = x, dy = top, dw = w, dh = h, sx = 0, sy = 0;
|
||||
@@ -275,6 +282,20 @@ static void blit_b_clip(const uint8_t *img, int x, int top, int w, int h)
|
||||
if (dy + dh > pop_t_fclip_y1) dh = pop_t_fclip_y1 - dy;
|
||||
}
|
||||
if (dw <= 0 || dh <= 0) return;
|
||||
/* ПЕРЕВОРОТ: экранная строка (dy+i) берёт источник (h-1-i), поэтому
|
||||
* обрезка СВЕРХУ экрана съедает НИЖНИЕ строки источника. В терминах
|
||||
* куска источника это sy' = h - sy - dh (при обрезке только сверху даёт
|
||||
* 0, при обрезке только снизу — верхний край). */
|
||||
if (pop_upside) {
|
||||
int fsy = h - sy - dh;
|
||||
if (fsy < 0) fsy = 0;
|
||||
if (dx >= 0 && dy >= 0 && dw < 256 && dh < 256 &&
|
||||
dx + dw <= 320 && dy + dh <= 256 && w < 256)
|
||||
gfx_blit_part_noclip_vflip(dx, dy, img, (uint8_t)sx, (uint8_t)fsy,
|
||||
(uint8_t)dw, (uint8_t)dh);
|
||||
else
|
||||
gfx_blit_part_vflip(dx, dy, img, sx, fsy, dw, dh);
|
||||
} else
|
||||
if (dx >= 0 && dy >= 0 && dw < 256 && dh < 256 &&
|
||||
dx + dw <= 320 && dy + dh <= 256 && w < 256) {
|
||||
if (sx == 0 && sy == 0 && dw == w && dh == h)
|
||||
@@ -313,6 +334,10 @@ void pop_blit_b(atlas_t *a, uint8_t idx, int x, int ybottom)
|
||||
w = (uint16_t)(img[0] | ((uint16_t)img[1] << 8));
|
||||
h = (uint16_t)(img[2] | ((uint16_t)img[3] << 8));
|
||||
top = ybottom - (int)h + 1 + POP_YOFF; /* +YOFF: центрирование */
|
||||
/* Переворот применяем ЗДЕСЬ, до клипа: дальше вся геометрия (окно
|
||||
* fore-слоя, полоса у потолка, отсев по экрану) считается уже в
|
||||
* экранных координатах результата. */
|
||||
if (pop_upside) top = FLIP_TOP(top, h);
|
||||
if (w && h) {
|
||||
if (!pop_t_fclip_on && !pop_t_clip_top) {
|
||||
/* БЫСТРЫЙ путь: клипа нет вовсе. Так идут все блиты фона вне
|
||||
@@ -321,10 +346,13 @@ void pop_blit_b(atlas_t *a, uint8_t idx, int x, int ybottom)
|
||||
* платит за клип/16-бит/split, а не за пиксели). W3-скобку
|
||||
* ставит сама libbgi: из кода с --w3 её вызывать нельзя. */
|
||||
if (x >= 0 && top >= 0 && w < 256 && h < 256 &&
|
||||
x + (int)w <= 320 && top + (int)h <= 256)
|
||||
gfx_blit_noclip(x, top, img);
|
||||
else
|
||||
gfx_blit_part(x, top, img, 0, 0, (int)w, (int)h);
|
||||
x + (int)w <= 320 && top + (int)h <= 256) {
|
||||
if (pop_upside) gfx_blit_noclip_vflip(x, top, img);
|
||||
else gfx_blit_noclip(x, top, img);
|
||||
} else {
|
||||
if (pop_upside) gfx_blit_part_vflip(x, top, img, 0, 0, (int)w, (int)h);
|
||||
else gfx_blit_part(x, top, img, 0, 0, (int)w, (int)h);
|
||||
}
|
||||
pop_cd_touch(x, top, (int)w, (int)h);
|
||||
} else {
|
||||
blit_b_clip(img, x, top, (int)w, (int)h);
|
||||
|
||||
Reference in New Issue
Block a user