L9-INVERT: состояние переворота, зелье типа 4 и pop_flip_screen
Шаг II.1 плана. pop_upside/pop_upside_dirty (порт upside_down и need_redraw_because_flipped), ветка case 4 в proc_get_object (только тоггл — ни вспышки, ни урона, как в оригинале), сброс стартом уровня и смертью Кида. pop_flip_screen (банк 8) переворачивает уже нарисованное двумя копиями акселератора: VFLIP в скрытую страницу, показ, DIRECT во вторую; затем инвалидация слотов персонажей, метки фона и полосы HP. Чит-клавиша U — порт seg000:0793 (в оригинале переворот тоже на чите): без неё эффект не проверить, чит-телепорт до зелья в комнате 7 не дотягивается. Проверено в MAME на уровне 9: комната переворачивается целиком за кадр, повторное нажатие возвращает. Персонажи и факелы пока не зеркалятся — это шаги II.3/II.4. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -19,6 +19,8 @@
|
||||
#include "pop_guard.h"
|
||||
#include "pop_state.h"
|
||||
#include "pop_geom.h"
|
||||
#include "pop_cdraw.h" /* pop_cd — инвалидация слотов после переворота */
|
||||
#include <sprite.h> /* gfx_copy_page */
|
||||
#include "pop_tune.h"
|
||||
|
||||
#define SEQ_STAND 2
|
||||
@@ -73,6 +75,11 @@ void pop_start_level(void) __banked
|
||||
|
||||
pop_leveldoor_open = 0; /* seg003:97 — дверь прошлого уровня не в счёт */
|
||||
pop_feather = 0; /* seg003:189 — перо не переживает старт уровня */
|
||||
/* upside_down тоже сбрасывается стартом уровня (seg003:38/188). Если
|
||||
* картинка была перевёрнута, отрисовка комнаты ниже уже пойдёт обычной
|
||||
* стороной, поэтому переворачивать ничего не надо — только снять флаги. */
|
||||
pop_upside = 0;
|
||||
pop_upside_dirty = 0;
|
||||
entry_pose = pop_level_entry_pose(pop_current_level);
|
||||
start_room = pop_level_start_room();
|
||||
pos = pop_level_start_pos();
|
||||
@@ -247,3 +254,49 @@ void pop_dbg_room_label(uint8_t room) __banked
|
||||
for (i = 0; i < (uint8_t)(room % 10); i++) bar(130 + i * 5, 0, 131 + i * 5, 5);
|
||||
room_label_redraw--;
|
||||
}
|
||||
|
||||
/* ---- Переворот уже нарисованного (зелье инверсии, уровень 9) --------- *
|
||||
*
|
||||
* Порт need_redraw_because_flipped (seg000:15E9 + 939/946). Оригинал
|
||||
* держит готовый offscreen и переворачивает его на выводе; у нас страниц
|
||||
* ровно две, рабочей третьей нет, поэтому переворачиваем то, что уже
|
||||
* нарисовано, — построчной копией акселератора (gfx_copy_page).
|
||||
*
|
||||
* Почему это законно и почему heal после не ломается: accel ЧИТАЕТ
|
||||
* ОЗУ-копию, значит копируется ЧИСТЫЙ ФОН без персонажей, а пишет банком
|
||||
* 0x50 — и в видео, и в копию приёмника. После двух проходов обе страницы
|
||||
* дабл-буфера содержат перевёрнутый фон в обеих плоскостях, и heal
|
||||
* восстанавливает уже его (memory accel_port_y_between_triggers,
|
||||
* регресс — tests/pageflip).
|
||||
*
|
||||
* Порядок: перевернуть в СКРЫТУЮ, показать её, скопировать оттуда во
|
||||
* вторую (теперь скрытую) — прямой копией. Так игрок видит результат
|
||||
* сразу, а не после второго прохода.
|
||||
*
|
||||
* Переворачиваем ТОЛЬКО игровое поле (POP_PLAYFIELD_H): полоса HP лежит
|
||||
* ниже него и в оригинале тоже не переворачивается. */
|
||||
void pop_flip_screen(void) __banked
|
||||
{
|
||||
gfx_rect_t area;
|
||||
uint8_t back = (uint8_t)(gfx_get_visible_page() ^ 1);
|
||||
|
||||
area.x = 0; area.y = POP_YOFF;
|
||||
area.w = 320; area.h = POP_PLAYFIELD_H;
|
||||
|
||||
gfx_set_draw_page(back);
|
||||
gfx_copy_page(&area, GFX_COPY_VFLIP); /* источник — видимая страница */
|
||||
gfx_set_visible_page(back);
|
||||
|
||||
gfx_set_draw_page((uint8_t)(back ^ 1));
|
||||
gfx_copy_page(&area, GFX_COPY_DIRECT); /* вторую страницу — прямой копией */
|
||||
|
||||
/* Всё, что рисуется поверх фона, надо положить заново: прошлые
|
||||
* прямоугольники персонажей относятся к СТАРОЙ (неперевёрнутой)
|
||||
* картинке, и heal по ним стёр бы не то место. */
|
||||
pop_cd[POP_CH_KID].valid[0] = pop_cd[POP_CH_KID].valid[1] = 0;
|
||||
pop_cd[POP_CH_KID].ovalid[0] = pop_cd[POP_CH_KID].ovalid[1] = 0;
|
||||
pop_cd[POP_CH_OPP].valid[0] = pop_cd[POP_CH_OPP].valid[1] = 0;
|
||||
pop_cd[POP_CH_OPP].ovalid[0] = pop_cd[POP_CH_OPP].ovalid[1] = 0;
|
||||
POP_CD_TOUCH_ALL(); /* фон трогали целиком */
|
||||
pop_hp_invalidate(); /* полосу HP перерисовать */
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user