PoP: roomtest — объекты/обломки/переходы комнат + арт
Порт Prince of Persia (applications/PoP/roomtest): развитие уровня, объекты (loose-полы/обломки), переходы между комнатами, фон-упаковка; планы (room_model/size_optimization), bug_list, pop_trob. Арт third_party/16x16-RPG-characters. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -20,12 +20,16 @@ extern void _gfx_w0_isr(void);
|
||||
/* Смещения блоков blueprnt относительно начала данных (Table 6). */
|
||||
#define BP_FG 0u
|
||||
#define BP_BG 720u
|
||||
#define BP_LINKLOC 1440u /* doorlink1 (LINKLOC), 256 Б */
|
||||
#define BP_LINKMAP 1696u /* doorlink2 (LINKMAP), 256 Б */
|
||||
#define BP_LINKS 1952u
|
||||
#define BP_START 2112u
|
||||
#define ROOM_TILES 30u
|
||||
#define MIN_SIZE (BP_START + 3u) /* минимум, чтобы прочитать старт */
|
||||
|
||||
static uint8_t lvl_blk, lvl_page, lvl_ok;
|
||||
/* Копии таблиц дверных связей в W2 (LINKMAP мутабельна — таймеры кнопок). */
|
||||
static uint8_t dl1[256], dl2[256];
|
||||
|
||||
int pop_level_load(const char *path)
|
||||
{
|
||||
@@ -47,11 +51,17 @@ int pop_level_load(const char *path)
|
||||
/* Файл целиком в offset 0x100 (ESTEX READ пишет в W3 — как atlas_load). */
|
||||
n = read(fd, pg + LVL_DATA_OFF, 16384 - LVL_DATA_OFF);
|
||||
if (n >= (int)MIN_SIZE) { /* пропатчить ISR-стаб */
|
||||
uint16_t i;
|
||||
stub = (uint16_t)&_gfx_w0_isr;
|
||||
pg[0x38] = 0xC3; /* JP _gfx_w0_isr */
|
||||
pg[0x39] = (uint8_t)(stub & 0xFF);
|
||||
pg[0x3A] = (uint8_t)(stub >> 8);
|
||||
pg[0x66] = 0xED; pg[0x67] = 0x45; /* RETN (NMI-хвост) */
|
||||
/* Скопировать таблицы дверных связей в W2 (страница ещё в W3). */
|
||||
for (i = 0; i < 256; i++) {
|
||||
dl1[i] = pg[LVL_DATA_OFF + BP_LINKLOC + i];
|
||||
dl2[i] = pg[LVL_DATA_OFF + BP_LINKMAP + i];
|
||||
}
|
||||
}
|
||||
sprinter_page_w3(saved_w3);
|
||||
close(fd);
|
||||
@@ -154,6 +164,49 @@ int8_t pop_room_col_landing(uint8_t room, uint8_t col)
|
||||
return res;
|
||||
}
|
||||
|
||||
uint8_t pop_doorlink1(uint8_t i) { return dl1[i]; }
|
||||
uint8_t pop_doorlink2(uint8_t i) { return dl2[i]; }
|
||||
void pop_doorlink2_set(uint8_t i, uint8_t v) { dl2[i] = v; }
|
||||
|
||||
uint8_t pop_level_tile(uint8_t room, uint8_t tilepos)
|
||||
{
|
||||
uint8_t v;
|
||||
if (!lvl_ok || room < 1 || room > 24 || tilepos >= ROOM_TILES) return 0;
|
||||
gfx_w0_map(lvl_page);
|
||||
v = (uint8_t)(room_fg_ptr(room)[tilepos] & 0x1F);
|
||||
gfx_w0_unmap();
|
||||
return v;
|
||||
}
|
||||
|
||||
/* Батч-доступ: смаппить страницу уровня в W0 ОДИН раз, прочитать много
|
||||
* тайлов через pop_level_tile_raw, размаппить один раз. Экономит N свапов
|
||||
* окна 0 в горячих циклах (pop_process_trobs звал pop_level_tile на каждый
|
||||
* trob каждый кадр). Между begin/end НЕЛЬЗЯ рисовать/звать код, которому
|
||||
* нужно окно 0 в исходном состоянии — только сырые чтения уровня. */
|
||||
void pop_level_access_begin(void) { if (lvl_ok) gfx_w0_map(lvl_page); }
|
||||
void pop_level_access_end(void) { if (lvl_ok) gfx_w0_unmap(); }
|
||||
|
||||
uint8_t pop_level_tile_raw(uint8_t room, uint8_t tilepos)
|
||||
{
|
||||
if (!lvl_ok || room < 1 || room > 24 || tilepos >= ROOM_TILES) return 0;
|
||||
return (uint8_t)(room_fg_ptr(room)[tilepos] & 0x1F);
|
||||
}
|
||||
|
||||
void pop_level_room_bg(uint8_t room, uint8_t *out30)
|
||||
{
|
||||
const uint8_t *rbg;
|
||||
uint8_t i;
|
||||
if (!out30) return;
|
||||
if (!lvl_ok || room < 1 || room > 24) {
|
||||
for (i = 0; i < ROOM_TILES; i++) out30[i] = 0;
|
||||
return;
|
||||
}
|
||||
gfx_w0_map(lvl_page);
|
||||
rbg = room_bg_ptr(room);
|
||||
for (i = 0; i < ROOM_TILES; i++) out30[i] = rbg[i];
|
||||
gfx_w0_unmap();
|
||||
}
|
||||
|
||||
uint8_t pop_room_link(uint8_t room, uint8_t side)
|
||||
{
|
||||
uint8_t v;
|
||||
|
||||
Reference in New Issue
Block a user