Шаг C: дворцовая кладка стен (wall_pattern, паласная ветка)
Во дворце тело стены — не кирпичи-спрайты, а шесть СПЛОШНЫХ ЗАЛИВОК плюс пять моно-разделителей поверх (seg008:1946). Порт целиком: - gen_palace_wall_colors (seg000:1942): 3 ряда × 4 подряда × 11 колонок = 132 цвета, сид = номер комнаты, подряды 1/3 из 0x61..0x64, подряды 0/2 из 0x66..0x69, соседние по горизонтали не повторяются. Одиннадцать колонок, а не десять: заливки 3 и 5 берут цвет СЛЕДУЮЩЕЙ колонки. Пересчёт на смене комнаты — там же, где сбрасывается кэш кладки (wall_pattern_reset). Таблица не static: writable-данные банка живут в _DATA/W2. - Геометрия заливок дословно из add_wipetable(layer, left, bottom, height, width): прямоугольник = x..x+width-1, (bottom-height+1)..bottom. - Пять prandom(2) на тайл кэшируются так же, как подземельные решения (wp_a/wp_b переиспользуются — наборы в одной комнате не сосуществуют). Сохранён квирк порядка: при which_part == 0 разыгрывается ОДНО значение, и нижний разделитель берёт ПЕРВОЕ из серии, а не пятое. - Заливки режутся по окну fore-клипа: иначе легли бы поверх областей, которые в этом кадре никто не восстанавливает. Вне fore-прохода — pop_cd_touch, потому что bar идёт мимо pop_blit_b. - wall_fram_bottom / wall_fram_main во дворце НЕ рисуются (seg008:576, 711) — и в горячей половине слоя (pop_bg.c), и в холодной (pop_room.c). - Упаковщик: дворцовые wall-id 3..17 пакуются силуэтом в цвете 6 общей 16-цветной палитры (blitters_46h_mono_6). В подземелье те же id — обычные кирпичи, поэтому mono только у паласного набора. ИЗВЕСТНОЕ РАСХОЖДЕНИЕ: рисунок цветов не совпадает с SDLPoP попиксельно, потому что наш prandom — 16-битный xorshift, а не LCG оригинала (замена сделана раньше по бюджету кадра, prng_alternatives.md). Совпадают геометрия, диапазоны цветов и правило «соседние не повторяются». Проверено в MAME: уровень 4 — песочный мрамор с разделителями, структурно как эталон SDLPoP; уровень 1 не изменился. tests-host 5/5. Остаётся расхождение по двери уровня (мы заполняем проём плетёнкой целиком, оригинал рисует несколько кусков лестницы) — отдельным шагом. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Binary file not shown.
@@ -120,10 +120,45 @@ static void draw_right_mark(uint16_t dv, int arg1, int row, int col)
|
|||||||
#define WP_N 40
|
#define WP_N 40
|
||||||
static uint8_t wp_a[WP_N], wp_b[WP_N], wp_ok[WP_N];
|
static uint8_t wp_a[WP_N], wp_b[WP_N], wp_ok[WP_N];
|
||||||
|
|
||||||
|
/* ---- Цвета дворцовой кладки (gen_palace_wall_colors, seg000:1942) ---- *
|
||||||
|
* Тело стены во дворце — не кирпичи-спрайты, а СПЛОШНЫЕ ЗАЛИВКИ; их цвета
|
||||||
|
* разыгрываются на КОМНАТУ: сид = номер комнаты, 3 ряда × 4 подряда × 11
|
||||||
|
* колонок. Подряды 1 и 3 берут 0x61..0x64, подряды 0 и 2 — 0x66..0x69
|
||||||
|
* (это слоты wall-палитры, во дворце они песочные); соседние по горизонтали
|
||||||
|
* не повторяются. Одиннадцать колонок, а не десять: заливки 3 и 5 берут
|
||||||
|
* цвет СЛЕДУЮЩЕЙ колонки.
|
||||||
|
*
|
||||||
|
* Не static: таблицу читает и холодная половина слоя (pop_room.c, банк 7).
|
||||||
|
* Writable-данные банка живут в _DATA/W2 и видны отовсюду — в отличие от
|
||||||
|
* const-таблиц, которые из чужого банка не прочитать. */
|
||||||
|
uint8_t pop_pal_wall_col[3 * 44];
|
||||||
|
|
||||||
|
static void gen_palace_wall_colors(uint8_t room)
|
||||||
|
{
|
||||||
|
pop_rnd_t saved = pop_t_seed;
|
||||||
|
uint8_t row, sub, col;
|
||||||
|
uint8_t *p = pop_pal_wall_col;
|
||||||
|
pop_prandom_set(pop_t_seed, room);
|
||||||
|
prandom(1); /* сброс, как в оригинале */
|
||||||
|
for (row = 0; row < 3; row++)
|
||||||
|
for (sub = 0; sub < 4; sub++) {
|
||||||
|
uint8_t base = (uint8_t)((sub & 1) ? 0x61 : 0x66);
|
||||||
|
uint8_t prev = 0; /* 0 — «цвета ещё не было» */
|
||||||
|
for (col = 0; col < 11; col++) {
|
||||||
|
uint8_t c;
|
||||||
|
do { c = (uint8_t)(base + prandom(3)); } while (c == prev);
|
||||||
|
*p++ = c;
|
||||||
|
prev = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pop_t_seed = saved;
|
||||||
|
}
|
||||||
|
|
||||||
static void wall_pattern_reset(void) /* смена комнаты — сид другой */
|
static void wall_pattern_reset(void) /* смена комнаты — сид другой */
|
||||||
{
|
{
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
for (i = 0; i < WP_N; i++) wp_ok[i] = 0;
|
for (i = 0; i < WP_N; i++) wp_ok[i] = 0;
|
||||||
|
if (pop_palace) gen_palace_wall_colors(pop_t_room);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Выходы wall_rnd — в файловых статиках: возвращать девять значений
|
/* Выходы wall_rnd — в файловых статиках: возвращать девять значений
|
||||||
@@ -219,11 +254,97 @@ static const uint8_t WP_PARTS[4] = {
|
|||||||
WP_RND | WP_MID | WP_BOT | WP_RIGHT | WP_LEFT, /* 3 WWW */
|
WP_RND | WP_MID | WP_BOT | WP_RIGHT | WP_LEFT, /* 3 WWW */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* ---- Кладка ДВОРЦА (seg008:1946) ------------------------------------ *
|
||||||
|
* Тело стены — не кирпичи-спрайты, а шесть СПЛОШНЫХ ЗАЛИВОК цветами из
|
||||||
|
* pop_pal_wall_col, поверх — пять разделителей chtab_7 (mono, цвет 6).
|
||||||
|
* Геометрия дословно из add_wipetable(layer, left, bottom, height, width):
|
||||||
|
* прямоугольник = x..x+width-1, (bottom-height+1)..bottom.
|
||||||
|
*
|
||||||
|
* Порядок prandom важен так же, как в подземелье: при which_part == 0
|
||||||
|
* разыгрывается ОДНО значение, и нижний разделитель берёт ПЕРВОЕ из серии,
|
||||||
|
* а не пятое. */
|
||||||
|
static uint8_t wpp_d[5]; /* пять prandom(2), 0..2 */
|
||||||
|
|
||||||
|
static void wall_rnd_palace(int row, int col)
|
||||||
|
{
|
||||||
|
int idx = (col >= 0 && col < 10) ? (row + 1) * 10 + col : -1;
|
||||||
|
pop_rnd_t saved;
|
||||||
|
uint8_t i;
|
||||||
|
if (idx >= 0 && idx < WP_N && wp_ok[idx]) {
|
||||||
|
uint8_t a = wp_a[idx];
|
||||||
|
wpp_d[0] = (uint8_t)(a & 3); wpp_d[1] = (uint8_t)((a >> 2) & 3);
|
||||||
|
wpp_d[2] = (uint8_t)((a >> 4) & 3); wpp_d[3] = (uint8_t)((a >> 6) & 3);
|
||||||
|
wpp_d[4] = wp_b[idx];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
saved = pop_t_seed;
|
||||||
|
pop_prandom_set(pop_t_seed, pop_t_room + TBL_LINE[row < 0 ? 2 : row] + col);
|
||||||
|
prandom(1); /* сброс */
|
||||||
|
for (i = 0; i < 5; i++) wpp_d[i] = (uint8_t)prandom(2);
|
||||||
|
pop_t_seed = saved;
|
||||||
|
if (idx >= 0 && idx < WP_N) {
|
||||||
|
wp_a[idx] = (uint8_t)(wpp_d[0] | (wpp_d[1] << 2) |
|
||||||
|
(wpp_d[2] << 4) | (wpp_d[3] << 6));
|
||||||
|
wp_b[idx] = wpp_d[4];
|
||||||
|
wp_ok[idx] = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Заливка куска стены. x/ytop — уже ЭКРАННЫЕ (с POP_YOFF). В fore-проходе
|
||||||
|
* режем по окну клипа: без этого заливка легла бы поверх областей, которые
|
||||||
|
* в этом кадре никто не восстанавливает. */
|
||||||
|
static void wpp_fill(int x, int ytop, int w, int h, uint8_t colour)
|
||||||
|
{
|
||||||
|
int x2 = x + w - 1, y2 = ytop + h - 1;
|
||||||
|
if (pop_t_fclip_on) {
|
||||||
|
if (x < pop_t_fclip_x0) x = pop_t_fclip_x0;
|
||||||
|
if (ytop < pop_t_fclip_y0) ytop = pop_t_fclip_y0;
|
||||||
|
if (x2 >= pop_t_fclip_x1) x2 = pop_t_fclip_x1 - 1;
|
||||||
|
if (y2 >= pop_t_fclip_y1) y2 = pop_t_fclip_y1 - 1;
|
||||||
|
}
|
||||||
|
if (pop_t_clip_top && ytop < pop_t_clip_top) ytop = pop_t_clip_top;
|
||||||
|
if (x < 0) x = 0;
|
||||||
|
if (ytop < 0) ytop = 0;
|
||||||
|
if (x2 > 319) x2 = 319;
|
||||||
|
if (y2 > 255) y2 = 255;
|
||||||
|
if (x2 < x || y2 < ytop) return;
|
||||||
|
setfillstyle(SOLID_FILL, colour);
|
||||||
|
bar(x, ytop, x2, y2);
|
||||||
|
if (!pop_t_fclip_on) pop_cd_touch(x, ytop, x2 - x + 1, y2 - ytop + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wall_pattern_palace(int row, int col, int which_part)
|
||||||
|
{
|
||||||
|
int xh = POP_COL_XH[col];
|
||||||
|
int dbys = 63 * row + 65; /* база БЕЗ POP_YOFF — для блитов */
|
||||||
|
int dmys = dbys - 3;
|
||||||
|
int dby = dbys + POP_YOFF, dmy = dmys + POP_YOFF; /* экранные — для заливок */
|
||||||
|
/* Цвета лежат по рядам 0..2; полоса у потолка (row −1) — это ряд 2
|
||||||
|
* комнаты сверху, оригинал и сид для неё берёт по ряду 2. */
|
||||||
|
const uint8_t *cl = pop_pal_wall_col + 44 * (row < 0 ? 2 : row) + col;
|
||||||
|
wall_rnd_palace(row, col);
|
||||||
|
if (which_part) {
|
||||||
|
wpp_fill(xh * 8, dmy - 59, 32, 20, cl[0]);
|
||||||
|
wpp_fill(xh * 8, dmy - 39, 16, 21, cl[11]);
|
||||||
|
wpp_fill((xh + 2) * 8, dmy - 39, 16, 21, cl[12]);
|
||||||
|
wpp_fill(xh * 8, dmy - 18, 8, 19, cl[22]);
|
||||||
|
wpp_fill((xh + 1) * 8, dmy - 18, 24, 19, cl[23]);
|
||||||
|
pop_wall_b((uint8_t)(wpp_d[0] + 3), (xh + 3) * 8, dmys - 53);
|
||||||
|
pop_wall_b((uint8_t)(wpp_d[1] + 6), xh * 8, dmys - 34);
|
||||||
|
pop_wall_b((uint8_t)(wpp_d[2] + 9), xh * 8, dmys - 13);
|
||||||
|
pop_wall_b((uint8_t)(wpp_d[3] + 12), xh * 8, dmys);
|
||||||
|
}
|
||||||
|
wpp_fill(xh * 8, dby - 2, 32, 3, cl[33]);
|
||||||
|
pop_wall_b((uint8_t)((which_part ? wpp_d[4] : wpp_d[0]) + 15), xh * 8, dbys);
|
||||||
|
}
|
||||||
|
|
||||||
static void wall_pattern(int row, int col, int which_part)
|
static void wall_pattern(int row, int col, int which_part)
|
||||||
{
|
{
|
||||||
int xh = POP_COL_XH[col];
|
int xh = POP_COL_XH[col];
|
||||||
int dby = 63 * row + 65;
|
int dby = 63 * row + 65;
|
||||||
uint8_t parts = WP_PARTS[pop_wall_modifier(row, col)];
|
uint8_t parts;
|
||||||
|
if (pop_palace) { wall_pattern_palace(row, col, which_part); return; }
|
||||||
|
parts = WP_PARTS[pop_wall_modifier(row, col)];
|
||||||
|
|
||||||
wall_rnd(row, col);
|
wall_rnd(row, col);
|
||||||
if (which_part) {
|
if (which_part) {
|
||||||
@@ -359,6 +480,9 @@ static void fore_only_tile(int row, int col)
|
|||||||
if (!FORE_ANY[code]) return; /* ранний выход, как в оригинале */
|
if (!FORE_ANY[code]) return; /* ранний выход, как в оригинале */
|
||||||
t = &pop_tile_table[code];
|
t = &pop_tile_table[code];
|
||||||
if (code == 20) {
|
if (code == 20) {
|
||||||
|
/* Во дворце тело стены даёт wall_pattern заливками, а спрайтовая
|
||||||
|
* грань не рисуется вовсе (seg008:711). */
|
||||||
|
if (!pop_palace)
|
||||||
pop_wall_b(POP_WALL_FRAM_MAIN[pop_wall_modifier(row, col)], x, dmy);
|
pop_wall_b(POP_WALL_FRAM_MAIN[pop_wall_modifier(row, col)], x, dmy);
|
||||||
wall_pattern(row, col, 1);
|
wall_pattern(row, col, 1);
|
||||||
return;
|
return;
|
||||||
@@ -399,6 +523,7 @@ static void ceil_over_kid_tile(int col)
|
|||||||
int x = POP_COL_XH[col] * 8;
|
int x = POP_COL_XH[col] * 8;
|
||||||
int dby = 63 * (-1) + 65; /* = 2 */
|
int dby = 63 * (-1) + 65; /* = 2 */
|
||||||
if (code == 20) { /* draw_tile_bottom: стена */
|
if (code == 20) { /* draw_tile_bottom: стена */
|
||||||
|
if (!pop_palace) /* seg008:576 */
|
||||||
pop_wall_b(POP_WALL_FRAM_BOTTOM[pop_wall_modifier(-1, col)], x, dby);
|
pop_wall_b(POP_WALL_FRAM_BOTTOM[pop_wall_modifier(-1, col)], x, dby);
|
||||||
wall_pattern(-1, col, 0);
|
wall_pattern(-1, col, 0);
|
||||||
} else if (t->bottom_id) {
|
} else if (t->bottom_id) {
|
||||||
@@ -535,6 +660,7 @@ static void overlay_mid_tile(int row, int col)
|
|||||||
}
|
}
|
||||||
if (code == 20) { /* draw_tile_bottom */
|
if (code == 20) { /* draw_tile_bottom */
|
||||||
uint8_t wmod = pop_wall_modifier(row, col);
|
uint8_t wmod = pop_wall_modifier(row, col);
|
||||||
|
if (!pop_palace) /* seg008:576 */
|
||||||
pop_wall_b(POP_WALL_FRAM_BOTTOM[wmod], x, dby);
|
pop_wall_b(POP_WALL_FRAM_BOTTOM[wmod], x, dby);
|
||||||
wall_pattern(row, col, 0);
|
wall_pattern(row, col, 0);
|
||||||
} else if (t->bottom_id) {
|
} else if (t->bottom_id) {
|
||||||
|
|||||||
@@ -363,7 +363,9 @@ static void draw_tile(int row, int col)
|
|||||||
/* --- draw_tile_bottom (seg008.c:570) --- */
|
/* --- draw_tile_bottom (seg008.c:570) --- */
|
||||||
if (code == 20) {
|
if (code == 20) {
|
||||||
wmod = pop_wall_modifier(row, col);
|
wmod = pop_wall_modifier(row, col);
|
||||||
pop_wall_b(POP_WALL_FRAM_BOTTOM[wmod], x, dby); /* сплошная нижняя грань */
|
if (!PALACE) /* во дворце тело стены даёт */
|
||||||
|
pop_wall_b(POP_WALL_FRAM_BOTTOM[wmod], x, dby); /* wall_pattern */
|
||||||
|
/* заливками (seg008:576) */
|
||||||
pop_wall_pattern_b(row, col, 0);
|
pop_wall_pattern_b(row, col, 0);
|
||||||
} else if (t->bottom_id) {
|
} else if (t->bottom_id) {
|
||||||
pop_env_b(t->bottom_id, x, dby);
|
pop_env_b(t->bottom_id, x, dby);
|
||||||
@@ -422,6 +424,7 @@ static void draw_tile(int row, int col)
|
|||||||
/* --- draw_tile_fore (seg008.c:690) --- */
|
/* --- draw_tile_fore (seg008.c:690) --- */
|
||||||
if (code == 20) {
|
if (code == 20) {
|
||||||
wmod = pop_wall_modifier(row, col);
|
wmod = pop_wall_modifier(row, col);
|
||||||
|
if (!PALACE) /* seg008:711 */
|
||||||
pop_wall_b(POP_WALL_FRAM_MAIN[wmod], x, dmy); /* основная грань */
|
pop_wall_b(POP_WALL_FRAM_MAIN[wmod], x, dmy); /* основная грань */
|
||||||
pop_wall_pattern_b(row, col, 1);
|
pop_wall_pattern_b(row, col, 1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -95,6 +95,7 @@ GATE_ANIM_ENV_IDS = {50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 67}
|
|||||||
GATE_TOP_ENV_IDS = {60, 61, 62, 63, 64, 65, 66, 67}
|
GATE_TOP_ENV_IDS = {60, 61, 62, 63, 64, 65, 66, 67}
|
||||||
GATE_TOP_MASK_ID = 68
|
GATE_TOP_MASK_ID = 68
|
||||||
|
|
||||||
|
|
||||||
# НАЖАТАЯ кнопка-closer (get_tile_to_draw seg008:2FE: при таймере связи >1
|
# НАЖАТАЯ кнопка-closer (get_tile_to_draw seg008:2FE: при таймере связи >1
|
||||||
# tiles_6_closer рисуется как tiles_5_stuck). tile_table[5] = база 41 (уже
|
# tiles_6_closer рисуется как tiles_5_stuck). tile_table[5] = база 41 (уже
|
||||||
# есть), правая грань 35, нижняя 36 — оба id встречаются ТОЛЬКО в этом
|
# есть), правая грань 35, нижняя 36 — оба id встречаются ТОЛЬКО в этом
|
||||||
@@ -131,6 +132,16 @@ POT_MASK_COLOR = VGA16_PAL_BASE + 0 # чёрный (blitters_40h_mono без
|
|||||||
POT_BUBBLE_COLOR = VGA16_PAL_BASE + 12 # ярко-красный (color 12: «лечение»)
|
POT_BUBBLE_COLOR = VGA16_PAL_BASE + 12 # ярко-красный (color 12: «лечение»)
|
||||||
CHOMPER_BLOOD_COLOR = VGA16_PAL_BASE + 12 # тот же mono-цвет 12 (seg008:678)
|
CHOMPER_BLOOD_COLOR = VGA16_PAL_BASE + 12 # тот же mono-цвет 12 (seg008:678)
|
||||||
|
|
||||||
|
# Кладка ДВОРЦА (wall_pattern, seg008:1928, ветка palace): тело стены —
|
||||||
|
# сплошные заливки цветом из palace_wall_colors, а поверх идут ПЯТЬ
|
||||||
|
# разделителей chtab_7 id 3..17 (prandom(2) + 3/6/9/12/15), и рисуются они
|
||||||
|
# blitters_46h_mono_6 — mono-блитом ОДНИМ цветом 6 общей 16-цветной палитры
|
||||||
|
# экрана. В подземелье те же id — обычные спрайты кирпичей (wall_fram_main/
|
||||||
|
# bottom), поэтому силуэтом пакуем ТОЛЬКО дворцовый набор.
|
||||||
|
PALACE_WALL_MONO_IDS = set(range(3, 18))
|
||||||
|
PALACE_WALL_MONO_COLOR = VGA16_PAL_BASE + 6
|
||||||
|
|
||||||
|
|
||||||
# Основание факела (seg008:489 draw_tile_right: при левом соседе-факеле
|
# Основание факела (seg008:489 draw_tile_right: при левом соседе-факеле
|
||||||
# рисуется chtab_6 id 146). В статический render_room не попадает.
|
# рисуется chtab_6 id 146). В статический render_room не попадает.
|
||||||
TORCH_ENV_IDS = {146}
|
TORCH_ENV_IDS = {146}
|
||||||
@@ -505,7 +516,12 @@ def main():
|
|||||||
print(f" (env стр {pg}: пусто)")
|
print(f" (env стр {pg}: пусто)")
|
||||||
|
|
||||||
# WALL -> idx=id
|
# WALL -> idx=id
|
||||||
wall_entries = {id: load_indexed(R.CHTAB_WALL, id) for id in wall_ids}
|
wall_entries = {id: load_indexed(
|
||||||
|
R.CHTAB_WALL, id, False,
|
||||||
|
PALACE_WALL_MONO_COLOR
|
||||||
|
if (set_name == "palace" and id in PALACE_WALL_MONO_IDS)
|
||||||
|
else None)
|
||||||
|
for id in wall_ids}
|
||||||
cnt, sz = pack_atlas(os.path.join(OUT_DIR, prefix + "wall.atl"), wall_entries)
|
cnt, sz = pack_atlas(os.path.join(OUT_DIR, prefix + "wall.atl"), wall_entries)
|
||||||
total_bytes += sz
|
total_bytes += sz
|
||||||
print(f" {prefix}wall.atl: {len(wall_ids)} спрайтов, каталог {cnt}, {sz} Б")
|
print(f" {prefix}wall.atl: {len(wall_ids)} спрайтов, каталог {cnt}, {sz} Б")
|
||||||
|
|||||||
Reference in New Issue
Block a user