PoP roomtest: блеск лежащего меча, клинок в руке, вспышка фона
Три расхождения с оригиналом на сцене подъёма меча (комната 15): 1. Лежащий меч не блестел. Порт animate_sword (seg007:0425) + start_anim_sword (seg007:087C): при входе в комнату тайлу даётся случайная фаза (prandom & 0x1F), каждый кадр счётчик вниз, на 0 — новый период 0x28..0x67. Кадр блеска рисуется РОВНО на modif==1 ((modif==1)+10 в draw_tile), т.е. одиночная вспышка раз в 40..103 тика. Перерисовка тайла — по смене видимого кадра, схемой кнопки (текущая страница сразу, вторая через rest-цикл). 2. В кадрах «нашёл меч» клинка не было видно. Порт add_sword_to_objtable (seg006:1798): клинок — ОТДЕЛЬНЫЙ спрайт chtab_0 поверх Kid со смещением из sword_tbl. Смещения в ЭКРАННЫХ пикселях (оригинал применяет их после calc_screen_x_coord), поэтому берём уже масштабированный obj_x. Из таблицы взяты только строки 35..42 (кадры 229..236) — бой не портирован. Новый атлас sword.atl (8 спрайтов, 1.6 КБ) + палитра chtab_0 в слотах 0x80..0x8F. Прямоугольник heal расширяется объединением с клинком, иначе он оставлял след за габаритом Kid. 3. Не было вспышки фона. do_flash = set_bg_attr(0, color) — оригинал подменяет НУЛЕВУЮ запись палитры, вспыхивает всё чёрное поле экрана; proc_get_object ставит flash_color=14, flash_time=8. У нас gfx_pal_set на обе страницы. ВАЖНО: вызов gfx_pal_set(0,0,0,0,0) пятью литералами ломает SDCC 4.5 (эмитит невалидный `ld hl, a`) — обёрнуто в функцию с параметрами. Попутно: TROBS_MAX 24 -> 30 (как в оригинале) + при входе в комнату из списка выбрасываются «декоративные» trob ДРУГИХ комнат (факелы/зелья/ меч анимируются только в отрисованной). Без этого отладочный обход всех 24 комнат забивал список, и новые анимации молча не заводились. Проверено в MAME: блеск (брейк на редрое тайла срабатывает), клинок в руке виден, фон вспыхивает жёлтым. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
#define TILE_DEBRIS 0x0E /* button_type для «насовсем открыть» (died_on_button) */
|
||||
#define TILE_OPENER 0x0F
|
||||
#define TILE_POTION 0x0A
|
||||
#define TILE_SWORD 0x16 /* меч-предмет на полу */
|
||||
#define TILE_TORCH 0x13
|
||||
#define TILE_TORCH_DEBRIS 0x1E
|
||||
|
||||
@@ -23,7 +24,7 @@ static uint8_t room_seen[POP_NROOMS]; /* modif проинициализиро
|
||||
|
||||
/* ---- Список анимируемых тайлов ------------------------------------ */
|
||||
typedef struct { uint8_t room, tilepos; int8_t type; } trob_t;
|
||||
#define TROBS_MAX 24
|
||||
#define TROBS_MAX 30 /* как в оригинале (types.h) */
|
||||
static trob_t trobs[TROBS_MAX];
|
||||
static uint8_t trobs_count;
|
||||
static uint8_t trob_code[TROBS_MAX]; /* префетч кодов тайлов на кадр (1 map W0) */
|
||||
@@ -121,6 +122,25 @@ void pop_trob_anim_room(uint8_t room)
|
||||
uint8_t i, code;
|
||||
if (!mod) return;
|
||||
pop_level_access_begin();
|
||||
/* Освободить список от «декоративных» trob ДРУГИХ комнат: факел, зелье и
|
||||
* блеск меча анимируются только в ОТРИСОВАННОЙ комнате, а место в списке
|
||||
* занимают. Оригинал их копит и на 30-й выдаёт «Trobs Overflow»; у нас
|
||||
* отладочный обход всех 24 комнат упирается в лимит за пару минут, после
|
||||
* чего новые анимации молча не заводятся. Механику (ворота/пики/кнопки,
|
||||
* в т.ч. кросс-комнатные) чистка не трогает. */
|
||||
{
|
||||
uint8_t k, wr = 0;
|
||||
for (k = 0; k < trobs_count; k++) {
|
||||
uint8_t c = (uint8_t)(pop_level_tile_raw(trobs[k].room,
|
||||
trobs[k].tilepos) & 0x1F);
|
||||
if (trobs[k].room != room &&
|
||||
(c == TILE_TORCH || c == TILE_TORCH_DEBRIS ||
|
||||
c == TILE_POTION || c == TILE_SWORD))
|
||||
continue;
|
||||
trobs[wr++] = trobs[k];
|
||||
}
|
||||
trobs_count = wr;
|
||||
}
|
||||
for (i = 0; i < POP_ROOMTILES; i++) {
|
||||
code = (uint8_t)(pop_level_tile_raw(room, i) & 0x1F);
|
||||
if (code == TILE_TORCH || code == TILE_TORCH_DEBRIS) {
|
||||
@@ -129,6 +149,10 @@ void pop_trob_anim_room(uint8_t room)
|
||||
} else if (code == TILE_POTION) {
|
||||
mod[i] = (uint8_t)((mod[i] & 0xF8) | (trob_prandom(6) + 1));
|
||||
pop_add_trob(room, i, 1);
|
||||
} else if (code == TILE_SWORD) {
|
||||
/* start_anim_sword (seg007:087C): случайная фаза счётчика блеска. */
|
||||
mod[i] = (uint8_t)(trob_prandom(0xFF) & 0x1F);
|
||||
pop_add_trob(room, i, 1);
|
||||
}
|
||||
}
|
||||
pop_level_access_end();
|
||||
@@ -375,6 +399,15 @@ void pop_process_trobs(uint8_t cur_room)
|
||||
if (room == cur_room)
|
||||
mod[tp] = (uint8_t)((mod[tp] & 0xF8) | bubble_next_frame(mod[tp] & 7));
|
||||
break;
|
||||
case TILE_SWORD:
|
||||
/* animate_sword (seg007:0425): счётчик вниз; на 0 — новый период
|
||||
* 0x28..0x67. Блеск рисуется РОВНО на modif==1 (draw_tile берёт
|
||||
* кадр (modif==1)+10), т.е. одиночная вспышка раз в 40..103 тика. */
|
||||
if (room == cur_room) {
|
||||
if (--mod[tp] == 0)
|
||||
mod[tp] = (uint8_t)((trob_prandom(255) & 0x3F) + 0x28);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
type = -1;
|
||||
break;
|
||||
@@ -406,6 +439,19 @@ void pop_process_trobs(uint8_t cur_room)
|
||||
* его уже никто не положит: ставим отложенный редрой. */
|
||||
if (type < 0) { spike_rest[tp] = 1; rest_pending++; }
|
||||
}
|
||||
if (room == cur_room && code == TILE_SWORD) {
|
||||
/* МЕЧ — редрой только на смене видимого кадра (блеск = modif==1):
|
||||
* спрайт запечён в фон (draw_tile), поэтому перерисовываем тайл
|
||||
* той же схемой, что и кнопку — текущая страница сразу, вторая
|
||||
* следующим кадром через rest-цикл. */
|
||||
uint8_t sig = (uint8_t)(mod[tp] == 1);
|
||||
if (sig != trob_drawn[tp]) {
|
||||
uint8_t trow = tp / 10, tcol = tp % 10;
|
||||
pop_button_redraw(trow, tcol);
|
||||
button_rest[tp] = 1; rest_pending++;
|
||||
trob_drawn[tp] = sig;
|
||||
}
|
||||
}
|
||||
if (room == cur_room && (code == TILE_OPENER || code == TILE_CLOSER)) {
|
||||
/* КНОПКА — редрой только при смене видимого состояния (нажата =
|
||||
* таймер связи >1): пока Кид её держит, картинка стабильна.
|
||||
|
||||
Reference in New Issue
Block a user