|
|
|
Канал X2: The Threat: «X2-ASM - это проcто!» |
|
|
Zman 65 EGP
Репутация: 12 Сообщения: 54 Откуда: Galaxy far, far away... Зарегистрирован: 17.01.2006 |
|
аааа.... ни за что бы не догадался
в дельфи вот немного не так - если объявлена процедура, то это фактически функция, которая не возвращает значение. В то же время при вызове функций, которые всегда возвращают значение, можно его (возвращаемое значение) игнорировать
_________________ THX2U |
|
|
CheckerTwo 550 EGP
Рейтинг канала: 4(96) Репутация: 103 Сообщения: 412 Откуда: Tomsk Зарегистрирован: 18.08.2004 |
|
Поправил косяк в ассемблере, не позволяющий компилить для Х3.
Спасибо Darth Revan.
Поправленная версия
|
|
|
CheckerTwo 550 EGP
Рейтинг канала: 4(96) Репутация: 103 Сообщения: 412 Откуда: Tomsk Зарегистрирован: 18.08.2004 |
|
Начиная с 03.20 версии пытался поднять скорость компиляции. В результате получил совершенно нерабочую двадцатку. Сорри. Все выходные правил. Вроде все подравнял.
Ассемблер.
Может работать с длинными строками, исправил ошибки при генерации кода...
Дизассемблер тоже пришлось править.
Можно попытаться оттранслировать целиком весь файл. Для этого нужно:
1. В asm-файле строку .loadobj "x2story.obj" - закоментарить. При этом obj-файл не будет грузиться. Все таблицы будут создаваться "с нуля".
2. Неизвестные команды работы с фиксированной запятой
unknown 03F50624Dh, 0D2F1A9FCh
unknown 040808000h, 000000000h
нужно будет заменить на эквиволентную последовательность
Код: |
;unknown 03F50624Dh, 0D2F1A9FCh
.word 005Ch
.long 03F50624Dh, 0D2F1A9FCh
|
EDIT: С макросами сейчас разберусь. Пока не пашет.
3. Теперь нужно разобраться с ошибками егософта. Их немного, но пока не очень понятно их происхождение.
3.1. В процедуре TSHIP.Cmd_EscortObject(arg1) вызывается нигде неописанная Cmd_EscortObject_T. Сама TSHIP.Cmd_EscortObject вроде нигде не вызывается.
3.2. В процедуре TCLIENT.InitClient(arg1) идет код для инициализации сетевой версии игры. И в нем вызывается неописанная SetLatency. Вроде по коду это место недостижимо, наверное можно закомментарить.
3.3. В процедуре TCLIENT.MakeXenonShips, которая нигде не вызывается и похоже является огрызком от недоделанного квеста встречается вызовы двух неописанных процедур SetLeader и SetRelativePos.
3.4. В диалоге "Archives" в процедуре TObj08EA.SpecialUpdate есть вызов двух неизвестных функций GetQtyLogRecords, возвращающая число записей лога и GetLogRecord, читающая эти записи. Собственно этого диалогового окна с заголовком "Archives" я что-то не припомню.
3.5. В патче 1.4 появился квест TQUEST_275, который похоже был недоделан. Этот квест использует функцию TObj17A0.UnrestrictShip, которая ссылается на неописанную SetTurretLaserMask. Эта функция реализована в Х3, но тянет за собой довольно много исправлений.
3.6. Ну и наконец в TQUEST_221.DialogHandler егософт вместо DisableAnswers написал DisableAnswer.
Странно все это. Неужели КС не проверяет наличие/отсутствие функций?
PS:У меня пока не получилось заставить Х2 работать с новым obj-файлом. Похоже что-то упустил... Может есть у кого есть желание поэкспериментировать?
|
|
|
CheckerTwo 550 EGP
Рейтинг канала: 4(96) Репутация: 103 Сообщения: 412 Откуда: Tomsk Зарегистрирован: 18.08.2004 |
|
YES!!!
Удалось на полностью перекомпиленных обжах не только полетать, но и выполнить пару миссий! Глюков не замечено.
Походу исправил несколько косяков. Основные проблемы оказались с командой push, под именем которой скрывалось несколько разных. Вроде поправил.
Как транслировать x2intro.obj
Начинать нужно с простого. И этот файл как нельзя лучше подходит для экспериментов. Этот обж грузит начальные менюшки, где происходит выбор уровня сложности, савок и прочее. И у него есть особенность. В этом файле используются классы, описанные в основном x2story.obj. Поэтому ассемблер в нем находит довольно много "неизвестных" процедур. Решается это просто - в самом начале этого файла нужно объявить эти процедуры директивой .extern и все. То есть, начало асм-файла будет выглядеть примерно вот так:
Код: |
.title x2intro.obj
.ident X2
.radix 16d
;.loadobj "x2intro.obj"
.extern GetEnvironment, GetSector, IsClassType, GetMusicTrack
.extern GetX, GetY, SetSceneState, GetGalaxyScene, GetSectorScene
.extern GetDustScene, DisableAnswers
.extern SpeakQuestionWithDuration, InitAnswers, GetGalaxyCut
.macro unknown a1, a2
.word 005Ch
.long a1, a2
.endm
; дальше идет длинный список .extern
|
Как транслировать x2story.obj
В предыдущем посте я уже говорил, что этот файл содержит косяки разработчиков. Если разбираться с ними не охота, то можно поступить таким же способом, как и в x2intro.obj:
Код: |
.title x2_out.obj
.ident X2
.radix 16d
;.loadobj "x2_out.obj"
.extern Cmd_EscortObject_T, SetLatency, SetLeader, SetRelativePos
.extern GetQtyLogRecords, GetLogRecord, SetTurretLaserMask, DisableAnswer
.macro unknown a1, a2
.word 005Ch
.long a1, a2
.endm
; дальше идет длиннющий список .extern
|
После ассемблирования стори файла, его размер уменьшается примерно на 100Кб. Это за счет того, что в новом файле отсутствует секция PTCH и некоторые команды заменены более коротким аналогом. Кроме того часть кода удаляется как "недоступная" для выполнения. Естественно, что игру придется начинать сначала.
Ассемблер.
Дизассемблер
|
|
|
Darth Revan 345 EGP
Рейтинг канала: 5(153) Репутация: 42 Сообщения: 349 Откуда: Belarus Prime Зарегистрирован: 01.02.2006 |
|
А если с нуля компилировать, то, наверное, можно добавлять свойства в классы с потомками? Это же ведь камень преткновения в реализации многих полезных вещей.
З.Ы. Пока работает обж, поэспериментирую. ! То, что очень нужно.
|
|
|
CheckerTwo 550 EGP
Рейтинг канала: 4(96) Репутация: 103 Сообщения: 412 Откуда: Tomsk Зарегистрирован: 18.08.2004 |
|
Darth Revan : |
А если с нуля компилировать, то, наверное, можно добавлять свойства в классы с потомками? Это же ведь камень преткновения в реализации многих полезных вещей.
|
Именно! А кроме того можно попробовать посмотреть какие из процедур самые тормозные или вызываются большое число раз во время работы. И попытаться оптимизировать их работу.
А кроме того, полная перекомпиляция подтверждает одну очень важную гипотезу - то что секция PTCH используется только во время загрузки савок от старых версий и никак не влияет на нормальную работу. А это намного упрощает написание компилятора, если такой когда-либо будет делаться.
Darth Revan : |
З.Ы. Пока работает обж, поэспериментирую. ! ! То, что очень нужно.
|
Ага, давай. С пристрастием! Все косяки, если попадутся - сюда.
|
|
|
Darth Revan 345 EGP
Рейтинг канала: 5(153) Репутация: 42 Сообщения: 349 Откуда: Belarus Prime Зарегистрирован: 01.02.2006 |
|
Дык работает. Вот нормальные локальные переменные работают! А то в Egosoftе свои мозги пропили . Так, как реализована set local variable - убить надо.
CheckerTwo : |
А кроме того можно попробовать посмотреть какие из процедур самые тормозные или вызываются большое число раз во время работы. И попытаться оптимизировать их работу.
|
TSHIP.__galaxyFlightStep, TFactory.Production. Реально садят производительность с той задержкой, которая по умолчанию.
Но это проблемы времени задержки, а не оптимальности процедуры. Реально же, findы много выполняются, их можно оптимизировать, но много не выжать. И ещё, похоже, что GS_Route вычисляет путь при каждом вызове. Можно просчитать разок, а потом просто возвращать значение вместо вызова (особенно в find). Если добавляем врата, то ставим что-нибудь в единичку, а сами потихоньку просчитываем. Просчитали - выставили обратно в 0. А в findах проверяем, если 0, то используем уже просчитанное, если 1, то GS_Route.
Хотя я пока делаю так. Патч, который уже есть, компилю, декомпилю, вставляю в результат новые переменные и чуток кода записи и чтения их, компилю большой файл и OK. Позволяет не компилить без особой надобности большой файл и не привязываться сильно ни к новым адресам, ни к записи кода дизассемблера - вдруг изменится чуток, если глюки будут
Кстати, что-то странное просходит с генерацией файла .err. То ли иногда в конец дописивается, а не стирается, то ли ещё непонятно что. Проверял: компилю большой файл с ошибкой, исправляю. Пока старый .err не сотру, эта ошибка изображается после компиляции исправленного файла.
Кстати, дизассемблировав свой патч, нашёл у себя страшную описку в нескольких местах в разборе параметров из скрипта (stack phase error - своими руками 3 на 5 нечаянно переправил, а потом раскопировал по всему патчу). Повезло, что не вылетало Завтра выложу фикс с новой командой.
|
|
|
CheckerTwo 550 EGP
Рейтинг канала: 4(96) Репутация: 103 Сообщения: 412 Откуда: Tomsk Зарегистрирован: 18.08.2004 |
|
Darth Revan : |
Кстати, что-то странное просходит с генерацией файла .err.
|
Ага есть такая фигня. Старый файл не прибивается. Поправлю.
|
|
|
SD 251 EGP
Рейтинг канала: 2(21) Репутация: 30 Сообщения: 2468
Зарегистрирован: 05.03.2006 |
|
У меня при дизассемблировании стандартного x2story 1.4 в лог ошибок пишется довольно много сообщений типа "Error : "Overflow stack at command addr = 00010E26; stack = 1 limit = 0".
Это проблема дизассемблера или обжа?
|
|
|
Shaddie 556 EGP
Рейтинг канала: 4(60) Репутация: 118 Сообщения: 261 Откуда: Томск Зарегистрирован: 09.09.2004 |
|
SD : |
Это проблема дизассемблера или обжа?
|
Это проблема обжа: неправильно задан размер выделяемого стека.
Большая разница (где то около 18) между требуемым и выделенным стеком приводит к вылетам из игры.
В оригинальном x2story.obj наибольшая разница равна 1 (stack = 1 limit = 0), что не является существенным.
_________________ Быстро едешь, тихо понесут... |
|
|
SD 251 EGP
Рейтинг канала: 2(21) Репутация: 30 Сообщения: 2468
Зарегистрирован: 05.03.2006 |
|
Команда write везде где я видел сопровождается командой pop. Она что - не вынимает число из стека или кладет туда, скажем, старое значение переменной?
|
|
|
Darth Revan 345 EGP
Рейтинг канала: 5(153) Репутация: 42 Сообщения: 349 Откуда: Belarus Prime Зарегистрирован: 01.02.2006 |
|
Не выталкивает значение из стека.
|
|
|
SD 251 EGP
Рейтинг канала: 2(21) Репутация: 30 Сообщения: 2468
Зарегистрирован: 05.03.2006 |
|
Что именно значат и чем потенциально грозят сообщения типа "pass2:(x2story.asm:2755) Note: Name of type is ignored." при компиляции?
|
|
|
Darth Revan 345 EGP
Рейтинг канала: 5(153) Репутация: 42 Сообщения: 349 Откуда: Belarus Prime Зарегистрирован: 01.02.2006 |
|
Ничем не грозят и на код не влияют. При вызове в asmе метода класса тип класса определяется типом проталкиваемого в стек перед вызовом метода объекта. Поэтому вызовы ClassName.Method и Method компилируются в один и тот же код, но в первом случае генерируется замечание. Часто просто первым способом удобнее пользоваться, т.к. в тексте asmы видно тип класса при вызове. Ну и если куски из дизассемблера брать. Так что просто не обращай на них внимание.
|
|
|
SD 251 EGP
Рейтинг канала: 2(21) Репутация: 30 Сообщения: 2468
Зарегистрирован: 05.03.2006 |
|
После полной перекомпиляции x2story у меня в игре полностью отпал строковый ввод: ни корабль переименовать ни в скриптовом редакторе строку набрать...
Кто-нибудь может подтвердить?
|
|
|
Darth Revan 345 EGP
Рейтинг канала: 5(153) Репутация: 42 Сообщения: 349 Откуда: Belarus Prime Зарегистрирован: 01.02.2006 |
|
У меня то же самое...
|
|
|
ULiX 320 EGP
Репутация: 146 Сообщения: 573 Откуда: Комсомольск на-Амуре Зарегистрирован: 12.07.2005 |
|
При попытке дизасемблить x3config.obj
dobj.exe выпадает c ошибкой винды
А можно как нибудь поправить внешние команды, примеру SE_StringSub? Ну, или хотяб перезадать. В языке С есть возможность перегружать функции, вот, скажем, перегрузить некоторые функции для определенных классов.
Проблема в обрезании строк функцией SE_StringSub для кодировки Utf-8 не англоязычного формата.
Есть какой-нибудь справочник по командам, чтоб глупых вопросов не задавать? (ну наверняка кто-то начиркал справочник) В частности интересует, как какая команда меняет указатель стека. Есть сложности в нахождении определения локальных переменных Loc%d, так как указано где они впервые используются, а чтоб найти, где были присвоены, приходится мыслено откатываться назад, и часто очень прилично. К примеру были неурядицы при встече команд вызова процедур, которые НЕ требуют аргументов
Код: |
push 0
push SP[7] ; loc1
call TSHIP.GetStrength ; 00002BF7
|
Второй push помещал в стек указатель на объект.
Функция GetStrength не требует аргументов, однако изимает из стека два значения, как я понял этот самый идентификатор объекта.
Пока я это не понял, я долго выискивал, чему же равны loc5 и loc6, определённые до двух таких вызовов, а первое их использованние происходило много ниже.
Нельзя ли в новой версии дизассемблера добавить в коментах указывать первое инициирование локальной переменной?
_________________ Новое ещё не значит лучшее |
|
|
Darth Revan 345 EGP
Рейтинг канала: 5(153) Репутация: 42 Сообщения: 349 Откуда: Belarus Prime Зарегистрирован: 01.02.2006 |
|
Внешние команды прошиты в exe, ничего уж не сделаешь... Главное, что X3story.obj нормально дизассемблится.
|
|
|
CheckerTwo 550 EGP
Рейтинг канала: 4(96) Репутация: 103 Сообщения: 412 Откуда: Tomsk Зарегистрирован: 18.08.2004 |
|
ULiX : |
При попытке дизасемблить x3config.obj dobj.exe выпадает c ошибкой винды Расстроен.
|
А от какой версии не дизассемблируется?
На 1.3 проходило все без ошибок...
ULiX : |
Есть какой-нибудь справочник по командам,
|
Увы. справочник написать сил не хватило. Можно смотреть по состоянию текущего стека.
Код: |
;
; === _Init =====================================================
; procedure _Init(arg1);
;
0000000A: 0055 0003 | 0000 _Init: setmem 3
0000000E: 0009 | 0000 push 0
00000010: 005A 00000001 | 0001 callasm SE_TableAlloc ; 00000001
00000016: 0029 0001 | 0001 writevar global.gs_TextFileTable ; [1]
0000001A: 002C | 0001 pop
0000001C: 000B | 0000 push 2
0000001E: 0005 0005 | 0001 push SP[4] ; arg1
00000022: 000B | 0002 push 2
00000024: 0058 00000016 0000000F | 0003 call58 global.LoadText ; 00000016, 0000000F
0000002E: 002C | 0001 pop
00000030: 0009 | 0000 push 0
00000032: 0035 | 0001 ret
|
Колонка из цифр после символа | - это оно и есть.
ULiX : |
Нельзя ли в новой версии дизассемблера добавить в коментах указывать первое инициирование локальной переменной?
|
Если на работе будет просвет с работой то попробую что-нибудь сделать.
|
|
|
ULiX 320 EGP
Репутация: 146 Сообщения: 573 Откуда: Комсомольск на-Амуре Зарегистрирован: 12.07.2005 |
|
CheckerTwo : |
А от какой версии не дизассемблируется?
На 1.3 проходило все без ошибок...
|
От версии патча 1.4.02
Следующие патчи пока obj не содержат.
После опыта перевода вручную одной функции этого псевдо асма на родительский си, я начал многие моменты распозновать как функции языка си. Кстати, вполне возможно сделать и детранслятор до языка си, нужно только помозговать, ну коль сделали перевод в асм, до си осталось совсем немного, стандартные конструкции не плохо распознаются, ну покрайней мере для меня визуально точно.
Правда моменты подобно:
if (expression1 && expression2 && expression3){
procedure1;
procedure2;
}
Прийдётся распозновать как:
if expression1 && expression2 {
if expression3 {
procedure1;
procedure2;
} // Adr1 -> Adr2
} // Adr2
Так как каждая проверка свыше второй в случае неудачи ссылается на свой адрес AdrN, но с которого всё равно происходит скачек к следующему адресу Adr(N+1).
Тройных конструкци OR в исследуемой функции не встречал, поэтому по данному факту ничего сказать не могу.
Одиночная проверка, или элемент AND:
if SP[0]=SP[1] then push 0 else push 1
if SP[0]=0 then jump Lxxxxxxxx
Элементы NOT
if SP[0]=0 then push 1 else push 0
if SP[0]<>0 then jump Lxxxxxxxx
push SP[n]
if SP[0]=0 then jump Lxxxxxxxx
Элемент OR
if SP[0]<>SP[1] then push 0 else push 1
if SP[0]<>0 then jump Lxxxxxxxx
Заметте в этих конструкциях логическое тождество:
A OR B == !(!A AND !B)
Вот ещё добавление, может пригодится.
Код: |
begin_critical
if SP[0]<>0 then jump Lxxxxxxxx
...
...
...
end_critical
Lxxxxxxxx:
...
...
...
|
Соответствуют в языке си:
Код: |
try {
...
...
...
}
cath(...){
Lxxxxxxxx:
};
...
...
...
|
Я пока встречал только подобный блок с игнорированием исключений, но теоретически возможен обработчик ошибки.
Используется в местах, которые могут вызвать ошибки, к примеру недопустимого метода для объекта, деление на 0. В случае, который я исследовал, это был момент когда враг покидает корабль. В этом случае возможна ошибка, если корабль был уничтожен раньше, чем тот успел выпрыгнуть, тогда метод LeaveShip для объекта вызовет исключение, так как объекта больше не существует. Данный блок помогает игнорировать данный факт и продолжать работать как ни в чем ни бывало.
В readmy вопросы напротив этих команд, так что решил вам помочь.
_________________ Новое ещё не значит лучшее |
|
|
|
|
|
Канал X2: The Threat: «X2-ASM - это проcто!» |
|