Вступление
Добрый всем, хочу рассказать про тёплую и ламповую стратегию детства — Противостояние. Игра была выпущена в 1996-98 гг нашей Российской фирмой Дока.
Игра — стратегия в реальном времени про вторую мировую войну. Спустя много лет я решил сперва пройти её и записать прохождение, а затем постараться по максимуму продлить удовольствие от игры, распаковывая ресурсы и пытаясь понять игровую логику.
Под катом я опишу процесс извлечения музыки, графики и немножко не дотяну до редактора карт.
Так же в описании будут отсылки на 8-битную палитру цветов, псевдоархивы, RLE-сжатие и чуток HEX-редактора. В самом коде я подсмотрел только алгоритм декодирования изображений, сжатый RLE.
Изначальный план был — достать музыку и отключить туман войны, затем немного увлекся и распаковал 9 файлов (.ADW, .DAW, .RUS).
Я играю и рекомендую полную 2в1 версия (Противостояние: Военная хроника) с пятью cd-audio треками, то есть полный рип последней версии игры всё-в-одном.
Если бы была возможность, то купил бы её еще раз, так как моего оригинального диска, купленного в 98г не сохранилось.
Музыка
Очевидное и простое решение — запустить игру под dosbox и записать всю музыку, что я и сделал в первую очередь. Плейлист с музыкой.
Затем подумал, что это неправильно. Получается, что эта музыка не оригинальная, а пропущенная через фильтры dosbox. Решил распаковать до wav состояния, взяв оригинальные данные.
Открыл файл music.dat в winhex. Так как в музыке есть голосовые вставки, то предположил, что там цифровой поток.
Спасибо форуму old-games где мне подсказали, что чаще всего для аудио использовали несжатый «сырой» поток данных, просто звук с определенными параметрами(11025 Гц/22050 Гц как наиболее часто используемые, 8-16 бит, моно/стерео, Intel/Motorola) который посылался напрямую в звуковую карту.
Открыв в hex увидел следующее:
Начало файла — 4 байта содержат число 20 (00 00 00 14h). Треков в игре 20. Затем следующие 20 групп по 4 байта это смещения начал мелодий. Последние 4 байта (33 A5 4B 01 = 01 4B A5 33h ) равны размеру файла music.dat, размер каждого трека равен разнице между двух смещений. Всё оказалось приятно и легко.
Таблицу смещений легко определить — это могут быть последовательно увеличивающиеся цифры, но иногда таблица файлов содержит непоследовательные смещения (Например, таблица шрифтов игры I have no mouth and I must scream). Число-смещение находится в диапазоне от 0 до размера файла. В данном случае таблица идет по увеличению.
В шапке каждого трека прослеживаются названия треков по фиксированному смещению +16: Maintune, Technoish, Terrible, Requiem, Track 0, Lazy reggae, U97:Was is das, Hold, GETDOWN!, Scramble, Gone, Rainman, Guitar song, Cool Jazz, Fir plates plant, REGRET.
Эксперименты с кусками в программе Game Audio Player (GAP) показали, что музыка воспроизводится со следующими параметрами — 22кГц, 8 bit, mono, unsigned. Причем, если выставить 11кГц, то музыка всё равно будет воспроизводиться, но в 2 раза медленней. Моно/стерео тоже изменяет темп воспроизведения.
Вдохновленный результатом я начал слушать все файлы игры… Слушал я их три дня. По звуку очень похоже на загрузку игр с кассет на спектруме или шум аналогового модема. Выяснил, что звуки в игре воспроизводятся как 11кГц, 8 бит, моно. Также выяснил, что все звуки в игре, звук в видеовставках, музыка — это сырые нежатые данные с указателями.
Заголовок каждого трека 68 байт, его нужно отбросить, иначе получается щелчок перед музыкой.
Итогом написал распаковщик-парсер music.dat.
Полученные файлы можно послушать в GAP и сконвертировать их в любой формат.
Квест по извлечению оригинальной музыки был выполнен.
Графика
С графикой всё оказалось немного запутанней. Некоторые изображения оказались сжатыми по RLE, некоторые не сжаты, у части в заголовке файла есть разрешение изображения, причем может попасться последовательность как X,Y так и Y,X. Некоторые изображения не содержали никаких заголовков и были размером 32х32 пикселя.
Содержимое псевдоархива и RLE сжатие:
Сначала идет заголовок — это группы из четырех байт, где указаны смещения на начало блока данных.
Последние числа 67 A9 07 00 равны длине файла, число конца первого блока.
Затем идет второй блок данных, конкретно для файла adddata.adw — это изображение «вставьте диск» для обычной кампании и опаленного снега.
(кол-во файлов) и 4 смещения,
04 00 00 00 — 10 00 00 00 — C3 A3 01 00 — C3 A6 01 00 — 52 40 03 00 — 8002 E001
Последние числа 0280h и 01E0h — это числа 640 и 480, то есть разрешение. Числа задают цикл для процедуры декодирования блока со сжатием RLE.
Алгоритм декодирования:
Число меньше или равное 7Fh (127) задает число повторов следующего идущего байта, на примере выше — это 7Fh (127) раз повторить ноль.
Если первое число больше 80h, то значит следующие (X-80h) байт — это просто байты, которые нужно скопировать в новое место.
Последовательность 82h 01 02 означает, что это числа 01 и 02 без всякого сжатия.
Если на место числа повторов попадает ноль, пропускаем.
Насчет судьбы числа 80h я так и не понял, оно не должно встречаться, т.к. разница 80 и 80 даст ноль).
По идее нужны 2 блока — само изображение и палитра.
Начало блока2 принимается за ноль и все идущие дальше смещения указывают от ноля. То есть если смотреть в hex-редакторе, то надо прибавить начальные 24 байта, плюс 4 байта (04 00 00 00). Итого +28 байт или +1Ch
04 00 00 00 — 4 файла.
10 00 00 00 + 1Ch который указывает на начало блока изображения 8002(640), E001(480), то есть задаем цикл декодирования, не длинее 640×480
C3 A3 01 00 + 1Ch указывает на палитру 256 цветов RGB, 768 байт. Подробнее здесь.
C3 A6 01 00 + 1Ch указывает на изображения, опять 640х480
52 40 03 00 + 1Ch указывает на палитру
Дело осталось за малым, разобрать файлы на блоки, распаковать сжатые участки и склеить с палитрой.
Декодированное сжатое изображение:
Игровые спрайты:
Вынутые из ресурсов изображения оказались темными, нужно сделать битовый сдвиг влево на 2 на каждом канале R, G, B.
r=r shl 2; (ну или умножить на 4, кому больше нравится)
g=g shl2;
b=b shl 2;
Немного картинок для расслабления. Оригинальные, без фильтров, тру.
Эти картинки нарисованы справа на панели, когда выбираешь юнита.
Видео
С видео получился следующий фейл, там тоже сырые потоки данных, картинки(под вопросом в каком формате) вперемешку со звуком. Вынул первое видео из movie.adw на 1.64МБ, засунул в GAP (22кГц, 8бит, моно, unsigned) — идет вперемешку шум-звуки-шум-звуки, где шум это поток картинок в 320х200х256, а звук в raw.
Предполагаю, что если пошариться внимательно по файлу, то звук должен быть отделен какими-то смещениями. Видео начинается с букв DLM, его легко найти плюс если проверить начальную таблицу смещений в movie.adw, то они будут указывать на DLM.
Видео:
— Заголовок 4 байта — «DLM» + 00
— Размер видео + звук — 4 байта (Совпадает с выдраным видеокуском)
— Непонятные 4 байта (типа, E3 00 00 00 = 227, количество смещений)
— Размер по горизонтали, 4 байта, 40 01 00 00 = 320
— Размер по вертикали, 4 байта, C8 00 00 00 = 200
— Какой-то разделитель в 4 байта = 04 00 00 00
— Затем 227 смещений в файле по 4 байта
— Затем снова разделитель 04 00 00 00
— И похоже до конца поток данных
И на этом с видео всё.
Чуть-чуть редактора карт
Ковырял файл CD:DATAMISSIONS73UNITS.DAT, выяснил следующее
[DEUTCHE]
[TIGER]
6,80,3,50,100,0,142
Информация о юнитах на карте:
— Первые два числа через запятую — это координаты X и Y юнита, ноль начинается в левом-верхнем углу. Максимум равен 128, размер карты 128х128, вроде бы фиксированный; целое число, 0-128
— Третье число — спрайт поворота юнита, в 8 направлениях должны быть + поворот башни тоже анимирован; целое число 0-7. Башня повернута по направлению взгляда юнита.
— Четвертое число — количество жизни юнита, целое число 0-100, похоже в процентах от максимума каждого юнита;
— Пятое число — количество боеприпасов, похоже в процентах от максимума. 0-100.
— Последние два не понял что за числа, менял на 1, 142 и на 2, 12, в юните ничего не изменилось. Не атака/защита, проверил. (шестой, предпоследний — у вражеских юнитов обозначает видимость, 0 — не виден игроку, 1 — видим)
— Последнее седьмое число пока хз. Похоже как-то связано с патрулированием, от начала игры ездят по разному танки вражеские. Похоже на скрипт поведения, по номеру. От 0 до хз 255
Для домов параметры следующие:
[DOMES]
29,33,70,100,1
1) Тип здания, значения от 0 до 35.
2,3) Координаты X, Y левого верхнего начала здания, рисуется вправо и вниз. Значения примерно от 1 до 128.
4) Количество «жизней» здания, в %. 0-100. Пробовал и 1000%, тогда здание можно уничтожить с 6 динамитами, вместо 2х за обычное большое.
5) Условие, нужно ли уничтожить здание, чтобы победить в миссии. 1 — обычное здание, за уничтожение нет бонусов, 2 — здание необходимо уничтожить для победы в миссии.
описание юнитов из файла units.dat
[RUSSIAN] — Ветка описания русских юнитов, раздел
[RBTANK] — Советский Т34, средний танк,
[RLTANK] — Легкий танк, Т26,
[RGUN] — русская пушечка против пехоты и танков,
[RTROOP] — русская пехота,
[RSAMO] — русская ПТ, типа су100
[IS] — тяжелый русский танк ИС
[BAT] — Скорострельная неуправляемая пушка,
[RGAUB] — русская управляемая гаубица,
[KATYA] — катюша,
[RBTR] — пулеметная бтр, маленькая машинка,
[RFURG] — грузовик для пехоты,
[TOWER] — башня с пулеметом,
[RZENIT] — русская зенитка против самолетов,
[CAR] — машина с vip персоной,
[RMZ] — Русская передвижная машина с зениткой против самолетов
[DEUTCHE] — ветка описания немецких юнитов, раздел
[DGUN] — немецкая пушечка,
[DLTANK] — немецкий легкий танк,
[DBTANK] — немецкий средний танк,
[TIGER] — Тигр,
[DBIKE] — мотоциклетка,
[DTROOP] — пехота,
[RFURG] — фургон-грузовик, русский, можно захватывать или использовать как свой.
[DBTR] — пулеметная бтр-машинка
[DSAMO] — немецкая пт, типа фердинанда
[DGAUB] — немецкая управляемая гаубица
[ART] — Скоростная, точная пушка, которой можно управлять.
[DZENIT] — Зенитные орудия против самолетов,
[DMZ] — Передвижная зенитка против самолетов,
[STIG] — Немецкий убер-танк с мощной пушкой и слабой броней, Штурмтигр,
А еще, например, если играешь за немцев, ветку описаний ИСов кладешь под своим описанием, под [DEUTCHE], то все ИСы становятся под твой контроль.
В итоге набросал минимод — Дружба народов:
И безумное видео:
Но в итоге руки доделать редактор так и не дошли, так как не был до конца изучен формат карт.
Тема на форуме old-games, вдруг кто поможет допилить недопиленное. Исходники доступны, к сожалению, на Делфи7.
Плейлисты прохождений:
— Кампания за СССР,
— Кампания за Германию,
— Дополнительные миссии — опаленный снег.
Автор: jack7277