Давненько уже во время просмотра стрима демо–версии ретро–шутера Ion Maiden глаз наткнулся на казалось бы знакомый фрагмент ретро–кода на ассемблере MOS 6502: MOS 6502 — знатный представитель 8–битных процессоров, трудившийся в таких эпохальных машинах как Apple II, Commodore 64, Atari и Famicom/NES/Денди. Типовой ассемблерный код для этого процессора щедро обсыпан инструкциями LDA, LDX, LDY, STA, STX и STY — от LOAD/STORE (сохранения и загрузки) соответствующих трёх регистров общего назначения A, X и Y. Но глаз мой зацепился за знакомое словосочетание "...MOVE DATA FOR VTOC..." в комментариях программы. Судя по всему это отсылка к (уже тоже «ретро») фильму «Терминатор», где для пущей убедительности кадры со зрением из глаз самого бездушного киборга–ассасина из будущего были украшены высокотехнологичными на тот момент буквами и цифрами компьютерного происхождения. Вот конкретный кадр, который и вызвал этот факт из моей памяти: Давно уже я читал в разных местах, что это были листинги ассемблерного кода для компьютера Apple II, но в этот раз решил разобраться поосновательнее и докопался до полного разбора полётов в следующем видео (на английском языке): Оказалось, что подавляющая часть листингов и таблиц были взяты из компьютерного журнала Nibble — конкретно августовского и сентябрьского выпусков 1984 года. Вышеприведённый фрагмент это кусок кода драйвера RAM–диска с названием Ram.Disk.64 или NEWRAM (то самое сокращение VTOC — это Volume Table Of Contents, а AUXMEM — дополнительная память в которой оно всё и размещается). Кроме того использованы коды программы HIRESEX (Hi–Res–Ex, а не Hire Sex!), выводящей картинки на экран, выводы программ MON.E и Key Perfect 4.0 (последняя использовалась чтобы проверять корректность машинного кода с помощью сверочных кодов и выводила в терминаторе она сверочные коды для файла OVLY.OBJ). Использовалась даже таблица параметров орбит нескольких советских и одного западного искусственных спутников Земли! Конечно сейчас это воспринимается комично — неужели тот самый терминатор был 8–битным и работал с RAM–диском в десятки килобайт? Или он, попав в прошлое, разграбил где–то по пути компьютерный магазин и фетишировал на своих доисторических предков? Так или иначе, если всмотреться в код из игры Ion Maiden, то легко заметить, что он хоть и похож на код из терминатора, но им не является. Это что–то другое. Заинтересовавшись я начал его анализировать и сперва пришёл к выводу, что это скорее всего набитая «с потолка» отсебятина, напоминающая код для MOS 6502, но по сути являющаяся бессмыслицей. Так, например, первые строки кода в терминаторе: Код (Text): LDA #<VTOC STA A1 LDA #>VTOC STA A1+1 загружают в аккумулятор и потом сохраняют в параметр A1 верхний и нижний байты адреса пересылаемого блока для процедуры AUXMOVE (# означает, что данное будет зашито в инструкцию, иначе оно бы воспринималось как адрес откуда данное надо взять, а > и < уже означают нижний и верхний байты адреса) — она пересылает куски байт между основной памятью и расширенной (замапленной на последние 8Кб памяти со страничным переключением — AUXMEM собственно). Так вот, в коде из Ion Maiden происходит бессмыслица: Код (Text): LDA #!PROC STA $314 LDA #!PROC STA $315 Во первых — в ассемблере 6502 знак! означает, как я понял, либо признак десятичной системы исчисления перед числом, ибо двоичную операцию XOR и его использование в этом месте является бессмыслицей. Во вторых два идентичных значения #!PROC в те времена, когда экономился каждый байт никакой программист не грузил бы в аккумулятор, это просто расточительно, достаточно было одного, первого LDA. В третьих — PROC это адрес процедуры идущей ниже по коду и в 8–битный аккумулятор оно просто не влезло бы. В общем сперва я подумал, что это просто набросанное нечто просто по мотивам реальных исходников. Но по прошествии чуть более года вещи внезапно оказались куда интереснее. Т.к. для разработки на денди я зарегистрировался на англоязычных форумах nesdev.com, то решил упомянуть вышерассказанное там (http://forums.nesdev.com/viewtopic.php?f=5&t=20160) и вопрос сдвинулся с мёртвой точки! Один из администраторов сайта с ником Memblers написал, что нагуглил, что инструкция JMP $EA31 есть прыжок в процедуру обработки прерывания IRQ в KERNAL (аналог BIOS) у 8–битного компьютера Commodore 64 (очень популярного в Северной Америке), а многочисленные упоминания ячеек памяти вида $D4xx — это явно порты звукового чипа SID этого же ПК. Уже хорошо разбираясь в командах процессора MOS 6502 который как понятно использовался и в Commodore 64 я уже легко понял, что этот код выполняет воспроизведение музыкального фрагмента на двух каналах чипа SID и музыка эта зашифрована в байтах лежащих по метке DATA. Перенести эту программу на рабочую машину я еще не готов, но зная уже что тут происходит я начал вбивать в поисковик комбинации слов "Ion Fury music Commodore 64" и довольно быстро открыл для себя истину: https://csdb.dk/release/?id=182055 Действительно еще в 2019 программист с никами Mr.Mouse и Xentax расковырял этот фрагмент кода и перенёс его корректно на ассемблер для этой машины. По ссылке выложен образ, поэтому я загрузил его в эмулятор Commodore 64 и вот результат (это я загрузил его образ в эмулятор C64): Тадаааа!!! Для большинства ретрогеймеров эта мелодия конечно мёд для ушей — заглавная мелодия Duke Nukem 3D собственной персоной, исполненная на двух каналах звукового чипа SID 8–битного компьютера Commodore 64 ассемблерной программой размещённой картинкой на плакате кинопроектора в комнате совещаний в игре Ion Maiden на уровне Corporate Chaos! И действительно комментарий предваряющий код где написано про "VTOC" это отсылка к виду из глаз из фильма Терминатор. Красота! Погуглив еще обнаружил, что адреса $0314–0315 куда процедура SETUP сохраняет адрес PROC это ничто иное как адрес процедуры обслуживания прерывания IRQ в Commodore Basic и поэтому в видео видно, что бейсик спокойно сосуществует с этой подпрограммой как с TSR и то что я там набираю на клавиатуре никак не мешает работать периодическому выводу мелодии. Осталось только так и непонятым мною почему в листинге из игры используется некий оператор! и как он должен работать, но в реализации от Mr.Mouse он логично заменён на взятие нижней и верхней половины адреса < и >. Так же там все.dword заменены на.byte. Возможно если бы не эти затуманившие мне мозг вещи я бы и сам смог докопаться до истины ранее. Хотя тогда я знал MOS 6502 и ассемблер для него намного хуже. Так или иначе — пасхалка супер!