Полная Версия: Fallout Script Debugger
The Master
Товарищ Hexxx не перестаёт радовать своими открытиями в области ковыряния движка, но помимо этого ещё успевает писать архиполезнейшие утилиты! Удивительный человек, снимаю шляпу :)
F2ScriptDebugger — это первое подобие скриптового отладчика для SSL скриптов в Fallout'e

Скачать, инструкция внутри

Как пользоваться:
1) Положить файлы ssldebug.ini, SslDebug.dll и F2ScriptDebugger.exe рядом с exe-файлом игры
2) Изменить в ssldebug.ini имя исполняемого файла, если вы отлаживаете не FalloutOfNevada.exe (см ниже)
3) Запустить exe-файл игры и дождаться пока появится шлавное меню
4) Переключиться в explorer по ALT-Tab и запустить F2ScriptDebugger.exe
5) Вернуться в игру и делать все что хочется, выполнение скриптов логируется в Debug.log

Особенности:
1) Прервать работу F2ScriptDebugger.exe можно в любой момент. Но он не умеет атачиться повторно. Придется перезапускать игру
2) Лог полностью сбрасывается на диск только когда выходишь из F2ScriptDebugger.exe. То есть пока он работает в Debug.log может отображаться не вся информация, часть информации может быть все еще в буфере.
3) В лог пишется очень много информации (если не включены фильтры), примерно 20 мб в минуту.
4) Адрес таблицы обработчиков скриптовых опкодов установлен для Fallout 2 v1.2 English. Если вы собрались юзать на какой-то другой версии, нужно выяснять какой адрес таблицы в вашем exe.

Опции в ssldebug.ini:
Game — имя исполняемого файла игры

Scripts — список скриптов, которые вы хотите логировать. Остальные логироваться не будут. Разделитель — точка с запятой. Позволяет сократить поток спама идущего в debug.log :) Изначально закоментировано, для того чтобы писался полный поток.

ScriptHandlerTableAddress — адрес глобальной переменной где лежат обработчики скриптов. Это для тех кто рискнет и захочет попробовать использовать дебагер на других версиях игры.

В основе лежит следующая идея:
Скриптовый движок для выполнения опкодов использует массив/таблица функций-обработчиков. Т.е. в нем столько обработчиков, сколько зарегистрировано опкодов. Перезаписав адреса обработчиков на свои, мы имеем возможность контролировать выполнение скрипта.
Сейчас именно так и сделано. В процесс игры инжектится DLL, она хучит все обработчики на адрес собственного обработчика опкодв. Собственный обработчик просто собирает информацию об опкоде, который выполняется в данный момент и шлет по IPC в процесс дебагера, где производится логирование. А дальше вызывается оригинальный обработчик опкода.

Проблема: массив инициализируется во время старта игры, поэтому нужно дождаться пока игра запустится, перед тем как перебивать адреса в массиве.

Небольшое пояснение про формат лога. В логе идут записи вида:
QUOTE
Script: scripts\hvpiter.int opcode: 80bc name: self_obj ip: 2068
Script: scripts\hvpiter.int opcode: 80bf name: dude_obj ip: 206a
Script: scripts\hvpiter.int opcode: 80dc name: obj_can_see_obj ip: 206c
Script: scripts\hvpiter.int opcode: 803e name: and ip: 206e
Script: scripts\hvpiter.int opcode: 80bc name: self_obj ip: 2070
Script: scripts\hvpiter.int opcode: 80d4 name: tile_num ip: 2072
Script: scripts\hvpiter.int opcode: 80bf name: dude_obj ip: 2074
Script: scripts\hvpiter.int opcode: 80d4 name: tile_num ip: 2076
Script: scripts\hvpiter.int opcode: 80d2 name: tile_distance ip: 2078
Script: scripts\hvpiter.int opcode: c001 name: unknown ip: 207a


"Script" — Имя скрипта, в котором щас идет выполнение,
"opcode" — опкод скрипта,
"name" — имя функции которая соответствует данному опкоду
"ip" — внутренний регистр интерпретатора, который показывает смещение в текущем скрипте. Значение ip можно использовать совместно с инфой из int2ssl, только надо запускать с -d и тогда там будут видны смещения опкодов в скрипте.

Пример использования с int2ssl:

1) Смотрим в лог дебагера и видим:

QUOTE
Script: scripts\vvcity.int opcode: 80c6 name: "set_global_var" ip: 1610
Script: scripts\vvcity.int opcode: c001 name: "const" ip: 1612
Script: scripts\vvcity.int opcode: 800d name: "d_to_a" ip: 1618
Script: scripts\vvcity.int opcode: 8019 name: "swapa" ip: 161a


Где это в реальном скрипте?

2) запускаем int2ssl -d vvcity.int — получаем VVCity.dump

3) Ищем в VVCity.dump "1610", находим:

QUOTE
0x00001610: 0x80C6 — O_SET_GLOBAL_VAR
0x00001612: 0xC001 0x00000000 — O_INTOP(0x00000000) // 0 (0)
0x00001618: 0x800D — O_D_TO_A
0x0000161A: 0x8019 — O_SWAPA


4) Листаем вверх по VVCity.dump и видим:

QUOTE
3: map_enter_p_proc (0x00000ae6)
===============================
0x00000AE6: 0x802B — O_PUSH_BASE


То есть выполнялся код процедуры map_enter_p_proc в vvcity.int
The Master
Программа обновлена, ссылка в первом посте. 25.08.12
Добавлено: English Readme, анализ операндов стека и для строковых аргументов:
QUOTE
Script: scripts\hvdoctr.int opcode: 80bf name: "dude_obj" ip: 1cfe operands: 4 (dynstr) "Да-да, ", c, 0, 0, 3, 0, 0, 0,
Script: scripts\hvdoctr.int opcode: 80a4 name: "obj_name" ip: 1d00 operands: 2e91a80, 4 (dynstr) "Да-да, ", c, 0, 0, 3, 0, 0,
Script: scripts\hvdoctr.int opcode: 8039 name: "+" ip: 1d02 operands: 10 (dynstr) "Слэш", 4 (dynstr) "Да-да, ", c, 0, 0, 3, 0, 0,
Script: scripts\hvdoctr.int opcode: c001 name: "const" ip: 1d04 operands: c,
Script: scripts\hvdoctr.int opcode: c001 name: "const" ip: 1d0a operands: 67,
Script: scripts\hvdoctr.int opcode: 8105 name: "message_str" ip: 1d10 operands: 67, c, 1a (dynstr) "Да-да, Слэш", c, 0, 0, 3, 0,
Script: scripts\hvdoctr.int opcode: 8039 name: "+" ip: 1d12 operands: 2a (dynstr) "? Чем я могу тебе помочь?", 1a (dynstr) "Да-да, Слэш", c, 0, 0, 3, 0, 0,
Script: scripts\hvdoctr.int opcode: 811e name: "gsay_reply" ip: 1d14 operands: 48 (dynstr) "Да-да, Слэш? Чем я могу тебе помочь?", c, 0, 0, 3, 0, 0, 0,

Комментарий автора:
QUOTE
Частично, потому что там есть два типа строк: динамические(dynstr) и статические(statstr). Динамические — это те которые образуются в переменных скрипта во время выполнения. Статические — это которые лежат прямо в int файле. Вот для динамических я разобрался как получать значения, а для статических еще нет.

Анализ операндов делается довольно тупо, потому что информации о количестве операндов для конкретного опкода — нет. Поэтому я просто считаю что максимальное количество операндов = 8. И пытаюсь достать все 8 из стека.

Enjoy!
Ваш ответ: