PoP roomtest: интерпретатор последовательностей стал общим (Char) — стражи

Пункт 1 плана стражей.  play_seq был прибит к Киду, поэтому страж стоял на
захардкоженном кадре 166.  Теперь как в оригинале: интерпретатор работает
с АКТИВНЫМ персонажем Char, а вокруг стоят loadkid/savekid и
loadshad/saveshad (порт seg006:809..825).

Почему копия, а не указатель: так в оригинале, и на Z80 это быстрее —
горячий цикл обращается к глобалу абсолютной адресацией, а 16-байтовое
копирование платится один раз на переключение персонажа, тогда как
указатель дал бы индексную адресацию в каждом обращении.

Сопутствующее:
- kid_t и pop_char_t слиты в один pop_char_t (pop_char.h): в оригинале
  char_type один на всех, и без этого общий интерпретатор невозможен.
  Kid получил поля room/charid/sword/alive — они и так нужны боёвке;
- load_frame выбирает таблицу кадров по Char.charid (у стража своя,
  frame_tbl_guard с индексом frame + add_frame − 149, seg006:0293);
- cur_frame разведён на два кэша: страж тикает ПОСЛЕ Кида, и без этого
  kid_draw брал бы кадр стража.  savekid/saveshad раскладывают кадр по
  своему персонажу;
- kid_set_seq пишет ИМЕННО Kid (его зовут pop_ctrl/pop_map вне окна Char,
  иначе loadkid затёр бы), для окна Char добавлен pop_char_set_seq —
  порт seqtbl_offset_char;
- в pop_map 9 голых play_seq() заменены на pop_kid_play() (load+play+save);
- страж входит в комнату через seq_77_guard_stand_inactive (seg002:0208),
  а не через прибитый кадр.

Проверено в MAME: Kid бегает и упирается в стену как прежде, в комнате 12
плиты проваливаются со щебнем (правка задела 9 вызовов play_seq в
физике), страж в комнате 3 рисуется в той же позе, но теперь
curr_seq=0x19A9 и charid=2 — кадр получен прокруткой последовательности,
а не константой.

Бюджет (комната 3, 150 кадров): 380 292..381 282 тактов против
370 140..371 160 до правки, то есть +10 150 (+2.7 %).  Основное — не
копии Char, а то, что страж теперь реально крутит интерпретатор каждый
кадр, а раньше стоял замороженным.  0.887 кадра, запас 48 718.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-30 10:11:10 +03:00
parent 565ba98852
commit 8bbc6b4d07
7 changed files with 158 additions and 73 deletions
+8 -7
View File
@@ -9,7 +9,7 @@
#include "pop_guard.h"
#include "pop_geom.h"
#include "pop_level.h"
#include "pop_kid.h" /* pop_kid_data_frame — таблицы в EMM-странице */
#include "pop_kid.h" /* Char/play_seq — интерпретатор общий */
#include "kid_data.h"
pop_char_t Guard;
@@ -80,12 +80,13 @@ void pop_guard_enter(uint8_t room)
Guard.alive = -1;
Guard.action = 1; /* actions_1_run_jump */
Guard.fall_x = Guard.fall_y = 0;
/* seq_77_guard_stand_inactive даёт кадр 166 (frame_166_stand_inactive,
* seqtbl.c:266). Интерпретатор последовательностей для стража придёт
* вместе с ИИ (следующая фаза) — сейчас ставим кадр напрямую, чтобы
* страж просто СТОЯЛ и было что рисовать/убивать читом. */
Guard.frame = 166;
guardhp_max = guardhp_curr = 3; /* get_guard_hp: skill 0, уровень 1 */
guardhp_delta = 0;
pop_guard_load_frame();
/* enter_guard (seg002:0208): seqtbl_offset_char(seq_77_guard_stand_inactive).
* Последовательность крутит общий интерпретатор (pop_guard_play), а
* таблицу кадров он выбирает по Char.charid — у стража своя. */
pop_loadshad();
pop_char_set_seq(SEQ_77_GUARD_STAND_INACTIVE);
pop_saveshad();
pop_guard_play(); /* до первого кадра */
}