Данная статья, является логичным продолжением предыдущей, в которой я описал свою идею, мотивацию и начало процесса вхождения в увлекательный мир 8bit. Эта статья будет короткой, опишу процесс разгребания вступительного мультика с целью идентификации необходимых для перевода ресурсов. Ресурсов раз два и три, но тем не менее, начало есть начало.
Загружаем «PRES» в Ghidra по известному ранее адресу 0x9000, добавляем области памяти
Точка входа нам известна из прошлой статьи, это 35074 или $8902, смотреть будем в «декомпилированный» код, он компактнее, хотя и не всегда соответствует действительности
void main(void) { undefined *puVar1; short in_DE; byte (*paabVar2) [8] [32]; byte *pbVar3; Set_Interrupts_and_Run(); CLS(); Clean8000to9000and5E00to6200(); Print_msg(&txt_FOR_CASSETTE); Colors_Fading(); Print_msg(&txt_PRESENTS); Colors_Fading(); Sprite(0,7,10); Sprite(1,10,0xe); Print_msg((HDmessage *)&txt_Delay); Colors_Fading(); FUN_ram_9b7c(in_DE); DAT_ram_ac2c = 200; DAT_ram_ac2d = 0x10; DAT_ram_ac41 = 0xe0; DAT_ram_ac42 = 0x10; DAT_ram_ac56 = 0xf0; DAT_ram_ac57 = 0x10; DAT_ram_ac6b = 200; DAT_ram_ac6c = 0x10; do { FUN_ram_9a4d(); BYTE_ram_9620 = 1; halt(); halt(); } while (0x27 < DAT_ram_ac2c); Print_msg((HDmessage *)&txt_Delay); Colors_Fading(); FUN_ram_9b8f(in_DE); DAT_ram_ac2c = 0; DAT_ram_ac2d = 0x28; DAT_ram_ac30 = 1; DAT_ram_ac41 = 0; DAT_ram_ac42 = 0x28; DAT_ram_ac45 = 1; DAT_ram_ac6a = 0xfd; DAT_ram_ac55 = 0xfd; do { FUN_ram_9a4d(); BYTE_ram_9620 = 1; halt(); halt(); } while (DAT_ram_ac40 != -3); Print_msg(&txt_START_TAPE); pbVar3 = &DAT_ram_b192; paabVar2 = SCR_BITS; puVar1 = &DAT_ram_1b00; do { *(byte *)paabVar2 = *pbVar3; paabVar2 = (byte (*) [8] [32])((short)paabVar2 + 1); pbVar3 = pbVar3 + 1; puVar1 = puVar1 + -1; } while (puVar1 != (undefined *)0x0); disableMaskableInterrupts(); setInterruptMode(0); enableMaskableInterrupts(); return;
Нас интересуют Print_msg и Sprite. Print_msg принимает ссылку на адрес комбинированной строки в регистре HL
ram:9a9c LD HL,txt_FOR_CASSETTE ram:9a9f CALL Print_msg ram:9aa2 CALL Colors_Fading ram:9aa5 LD HL,txt_PRESENTS ram:9aa8 CALL Print_msg ram:9aab CALL Colors_Fading
Текст может содержать в себе заголовок со всем необходимым
В тексте могут содержаться маркеры, которые могут задать 1 — координаты на экране для вывода сообщения, 2 — цвет, как фона так и текста, стандартный байт аттрибута, 3 — размер шрифта, сообщение может выводиться с увеличением высоты символа в x раз, 6 — задержка, 0 — закончили с текстом. Знакогенератор находится по адресу 0xAC7E
Со спрайтами чуть проще, координаты задаются при вызове функции, координаты измеряются не в точках а в знакоместах, как у текста, скорее всего, чтобы не заморачиваться с клэшингом. Необходимая нам процедура Sprite принимает номер спрайта и координаты в регистрах A, B, C
ram:9aae LD A,0x0 ram:9ab0 LD B,0x7 ram:9ab2 LD C,0xa ram:9ab4 CALL Sprite ram:9ab7 LD A,0x1 ram:9ab9 LD B,0xa ram:9abb LD C,0xe ram:9abd CALL Sprite
Адреса спрайтов получаются складыванием базового адреса 0xAA9c и смещение из таблицы смещений по адресу 0x9889
ram:9889 ushort[3] ram:9889 [0] 0h, 146h, 190h
, размер спрайта содержится в начале самого спрайта, размер тоже в знакоместах
ram:aa9a HDRsprite ram:aa9a db Ch width ram:aa9b db 3h height ram:aa9c ?? 0Fh ram:aa9d ?? F0h ram:aa9e ?? FFh
Colors_Fading осуществляет «красивую» очистку экрана, с переливающимися цветами. Вроде всё рассказал… Далее будет разбор файла самой игры, или сначала загрузчик переделаю, ещё не решил. Ниже текстовые сообщения, спрайты в заголовке статьи.
ссылка на оригинал статьи https://habr.com/ru/articles/936990/
Добавить комментарий