Сейчас на форуме: Magister Yoda, vasilevradislav (+3 невидимых)

 eXeL@B —› Крэки, обсуждения —› Diablo II bug fix
Посл.ответ Сообщение

Ранг: 419.0 (мудрец), 647thx
Активность: 0.460.51
Статус: Участник
"Тибериумный реверсинг"

Создано: 22 апреля 2015 20:45
· Личное сообщение · #1

Дело было вечером!
Есть такая легендарная игрушка - Diablo II: Lord of Destruction. В ней можно устанавливать 2D и 3D режим (за последний ламеры не знают...впрочем, там особо и 3D нет-земля на текстуру натягивается и всё это в перспективе показывается, ну НЕ ВАЖНО короче!), Так вот, режимы меняются с помощью D2VidTst.exe, который валяется в том же каталоге с игрой. Файл изначально фурычит под 98-XP, но я его пропатчил (это просто!) - теперь в 2k3 и выше, при прямых видео-дровах он норм запуститься. Так вот, недавно я сменил видеокарту на новенькую AMD 7x00 series - до этого была старая и добрая HD 4850, где это 3D без проблем фурычило. А с новой 7 серией внезапно вываливается MessageBox диябловского обработчика с "необработанным ексепшеном 0xc0000005"
Code:
  1.  В ЛОГАХ:
  2.  ***** UNHANDLED EXCEPTION: ACCESS_VIOLATION (c0000005)
  3. Fault address:  6F84981F 01:0000881F S:\GMS\Diablo2\D2Direct3D.dll

Сначала я подумал, что гребаные и трижды треклятые криворукие говнокодеры из AMD снова накосячили и ситуация безнадежна. Однако, мой интерес не смог угаснуть и я, без особого энтузиазма, взял ольку и начал копать... (пропуская кучу технический подробностей), вышел я на следующее место в D2Direct3D.dll:
Code:
  1. 6F8497D4  |.  8B4424 10     MOV EAX,DWORD PTR SS:[ESP+10] // внизу ECX напрямую связан с аргументом
  2. 6F8497D8  |.  895424 08     MOV DWORD PTR SS:[ESP+8],EDX
  3. 6F8497DC  |.  2BC2          SUB EAX,EDX
  4. 6F8497DE  |.  55            PUSH EBP
  5. 6F8497DF  |.  99            CDQ
  6. 6F8497E0  |.  F7FB          IDIV EBX
  7. 6F8497E2  |.  56            PUSH ESI
  8. 6F8497E3  |.  8BF1          MOV ESI,ECX
  9. 6F8497E5  |.  57            PUSH EDI
  10. 6F8497E6  |.  895C24 10     MOV DWORD PTR SS:[ESP+10],EBX
  11. 6F8497EA  |.  3D 00040000   CMP EAX,400 // <<< - сначала смотри в самый низ, где memset aka rep stos :)
  12. 6F8497EF  |.  8906          MOV DWORD PTR DS:[ESI],EAX
  13. 6F8497F1      72 05         JL SHORT 6F8497F8  // we can seek! ;)
  14. 6F8497F3  |.  B8 00040000   MOV EAX,400
  15. 6F8497F8  |>  8906          MOV DWORD PTR DS:[ESI],EAX
  16. 6F8497FA  |.  6A 00         PUSH 0                                   ; /Arg2 = 0
  17. 6F8497FC  |.  C1E0 05       SHL EAX,5                                ; |
  18. 6F8497FF  |.  8BE8          MOV EBP,EAX                              ; |
  19. 6F849801  |.  6A 37         PUSH 37                                  ; |Arg1 = 37
  20. 6F849803  |.  BA 8C62856F   MOV EDX,OFFSET 6F85628C                  ; |ASCII "C:\Src\Diablo2\Source\D2Direct3D\Src\d3dTextureCache.cpp"
  21. 6F849808  |.  8BCD          MOV ECX,EBP                              ; |
  22. 6F84980A  |.  E8 4B180000   CALL <JMP.&Fog.#10042>                   ; \Fog.#10042 // судя по внутренностям - диябловский менеждер памяти (кучи)
  23. 6F84980F  |.  8BCD          MOV ECX,EBP
  24. 6F849811  |.  8BF8          MOV EDI,EAX
  25. 6F849813  |.  8BD1          MOV EDX,ECX
  26. 6F849815  |.  33C0          XOR EAX,EAX
  27. 6F849817  |.  C1E9 02       SHR ECX,2
  28. 6F84981A  |.  897E 18       MOV DWORD PTR DS:[ESI+18],EDI
  29. 6F84981D  |.  33ED          XOR EBP,EBP
  30. 6F84981F  |.  F3:AB         REP STOS DWORD PTR ES:[EDI] // <<<<<-- ПАДАЛО ТУТ!!! EDI- указатель корректный, а ECX -  огромное число

падало на REP STOS из-за того, что ECX - принимало сумашедшее значение и инструкция врезалась в космос. Fog.#10042 - по виду, менеждер памяти, указатель выплевывал валидный. Крутим вверх:
* SHR ECX,2 - кол-во итераций уменьшается в 4 раза (закос комплиятора под DWORD реп стоса?).
* MOV ECX,EBP -> MOV EBP,EAX
* CMP EAX,400 и результирующий условный переход JL
* арифметика с EAX
* MOV EAX,DWORD PTR SS:[ESP+10] - EAX берется с аргумента (16 байт - 4го?)
в хекс-райс дает следующий код:
Code:
  1. int __fastcall sub_6F8497C0(int a1, signed int a2, signed int a3, int a4, int a5)
  2. {
  3.   signed int v5; // ebx@1
  4.   signed int v6; // eax@1
  5.  
  6.   v5 = a5 * a4 * dword_6F85BB58;
  7.   v23 = a2;
  8.   v6 = (a3 - a2) / v5;
  9.   v7 = a1;
  10.   v22 = a5 * a4 * dword_6F85BB58;
  11.   *(_DWORD *)a1 = v6;
  12.   if ( v6 >= 1024 )
  13.     v6 = 1024;
  14.   *(_DWORD *)a1 = v6;
  15.   v8 = 32 * v6;
  16.   v9 = (void *)Fog_10042(32 * v6, "C:\Src\Diablo2\Source\D2Direct3D\Src\d3dTextureCache.cpp", 55, 0);
  17.   v10 = v8;
  18.   v11 = v8 >> 2;
  19.   *(_DWORD *)(v7 + 24) = v9;
  20. ....

ТАК В ЧЕМ ЖЕ СПРЯТАН КОВАРНЫЙ БАГ??? Догадались?
А он кроется в
Code:
  1. CMP EAX,0x400 
  2. JL SHORT 6F8497F8

JL для signed int(!!!) - что в принципе неправильно, т.к. условие if ( v6 >= 1024 ) v6 = 1024; попросту не срабатывает, когда в аргументе белиберда (неважно, откуда она появляется). Поэтому, signed int число докатывается до memset (REP STOS DWORD...) и получается заезд за пределы выделенной памяти.

А ВЕДЬ ОЧЕВИДНО, ЧТО В НАШЕМ СЛУЧАЕ ДОЛЖНО БЫТЬ unsigned int (флаг переноса то), т.е. в D2Direct3D.dll должно быть Jump if below:
Code:
  1. CMP EAX,0x400 
  2. JB SHORT 6F8497F8

ОК! Исправил, сохранил, запустил - РАБОТАЕТ 3D! Даже скрины есть!

В связи с чем, шлю пламенный хакерский привет Blizzard Entertainment и прикладываю в аттаче пофикшенные D2VidTst.exe и D2Direct3D.dll

p.s. Не забывайте, что игрушка еще поддерживает Creative EAX - не тот EAX, что 32 битный регистр CPU, а «Environmental Audio Extensions»

8ab7_22.04.2015_EXELAB.rU.tgz - Diablo_II_3D_Fix__by_ELF.7z

| Сообщение посчитали полезным: kp0m, zNob, Coderess, VodoleY, Rainbow, [Nomad], Hellspawn, ==DJ==[ZLO], serilo, Aldi777, WiperX

Ранг: 431.7 (мудрец), 389thx
Активность: 0.730.32
Статус: Участник

Создано: 22 апреля 2015 20:54 · Поправил: dosprog
· Личное сообщение · #2

Хуже было бы, если бы не диабловский обработчик выдавал сообщение, а система.
А так естественно желание полезть взглянуть, что там за фигня.

Что касается <JL>, то лично я ею избегаю пользоваться вообще.
Эта инструкция - рудимент. Использование чревато такими вот багами.
Между тем в массе учебников по ассемблеру в примерах используется именно она,
видимо, потому, что звучит привычнее.

Справедливости ради замечу, что это скорей всего не диабловцевский баг,
он им самим достался вместе с библиотекой (компилятором).
--добавлено--
Хотя, если их переменная объявлена как int и по умолчанию действует signed
(а он в настройках по умолчанию таков), тогда да, их прокол.
--добавлено ещё--
Сам сейчас пользуюсь старинной WIN16 версией одной программы, которая всеми признана неудачной, глючной, и похерена ещё двадцать лет назад. Понадобился простой патч ошибки библиотеки компилятора - и вполне годная программа работает и меня устраивает.






Ранг: 241.9 (наставник), 107thx
Активность: 0.140.01
Статус: Участник

Создано: 22 апреля 2015 22:00
· Личное сообщение · #3

Еще в студенческие годы гамал в диаблу на каких-то патченных файлах. Там было исправлено несколько таких вылетов. Так что, если погуглить, то можно поискать чужой велосипед с круглыми колесами




Ранг: 324.3 (мудрец), 221thx
Активность: 0.480.37
Статус: Участник

Создано: 23 апреля 2015 00:12 · Поправил: DenCoder
· Личное сообщение · #4

ELF_7719116 пишет:
JL для signed int(!!!) - что в принципе неправильно, т.к. условие if ( v6 >= 1024 ) v6 = 1024; попросту не срабатывает, когда в аргументе белиберда (неважно, откуда она появляется).

Да, тут достаточно, чтобы было a3 < a2, либо одно из условий (a5 < 0) или (a4 < 0) или (dword_6F85BB58 < 0) = TRUE, а 2 других из них = FALSE или TRUE... да, странно использовать для подсчёта кол-ва выделяемой памяти тип знаковых целых.

Хорошо, когда время есть для собственных копаний... Мне не хватило вот, чтоб в d3d9.dll найти реальную причину вылетов... Запатчил только место, где имели место вылеты - вставил простенькую проверку на валидность указателя. )

Место вылетов - CD3DDDIDX8::SetPixelShaderConstantF + 0x32
Code:
  1. .text:4FE14E80 010 8B D1 mov     edx, ecx
  2. .text:4FE14E82 010 8B 1A mov     ebx, [edx]


заменил на
Code:
  1. 4FE14E80 010 EB BF jmp     short loc_4FE14E41

адрес по прыжку - свовободное место между функциями для выравнивания по границе 16 байт, уложил патчик в него:
Code:
  1. .text:4FE14E41 010 89 CA mov     edx, ecx
  2. .text:4FE14E43 010 81 F9 00 10 00 00 cmp     ecx, 1000h
  3. .text:4FE14E49 010 76 58 jbe     short loc_4FE14EA3; <- на выход
  4. 4FE14E4B 010 EB 35 jmp     short loc_4FE14E82


Ошибка проявляла себя при включенном аппаратном ускорении с видюхой ATI Radeon X1050 в некоторых играх, unity3D, или при переключении в полноэкранный режим видеоролика на ютубе. Конечно, пользоваться таким патчем не айс, поскольку ролика в режиме "на всю" не было вообще видно, а в юнити всё мерцало разными цветами. Но хотя бы браузеры перестали падать.

Кому интересно продолжить, а может и улучшить (на случай вдруг тоже нестыковки с видюхой) - --> на РГ <--, а то большеват файл для аттача.

-----
IZ.RU


| Сообщение посчитали полезным: ELF_7719116


Ранг: 1131.7 (!!!!), 447thx
Активность: 0.670.2
Статус: Участник

Создано: 23 апреля 2015 08:15 · Поправил: Gideon Vi
· Личное сообщение · #5

Ждите отстоя пены... тьфу! Делайте сигнатурные патчи Версий диаблы вагон, ни каждый играет на первом/последнем патче.




Ранг: 355.4 (мудрец), 55thx
Активность: 0.320
Статус: Uploader
5KRT

Создано: 23 апреля 2015 09:21
· Личное сообщение · #6

Аж поиграть захотелось, а это была когда-то моя любимая игра.
2ALL> А нет ли патчей для игры с большим разрешением

-----
Gutta cavat lapidem. Feci, quod potui. Faciant meliora potentes




Ранг: 262.5 (наставник), 337thx
Активность: 0.340.25
Статус: Участник

Создано: 23 апреля 2015 09:45
· Личное сообщение · #7

http://www.playground.ru/files/diablo_ii_unofficial_resolution_patch-20301/

| Сообщение посчитали полезным: Coderess

Ранг: 488.1 (мудрец), 272thx
Активность: 0.350
Статус: Участник

Создано: 23 апреля 2015 09:50 · Поправил: VodoleY
· Личное сообщение · #8

ELF_7719116 пишет:
Diablo II: Lord of Destruction

поклон в ножки.. как же я на него залипал.. это был ппц
ЗЫ просто за тему получи лайк)))

-----
Наша работа во тьме, Мы делаем, что умеем. Мы отдаем, что имеем, Наша работа во тьме....


| Сообщение посчитали полезным: ELF_7719116

Ранг: 33.9 (посетитель), 22thx
Активность: 0.030
Статус: Участник

Создано: 23 апреля 2015 17:22
· Личное сообщение · #9

ELF_7719116 пишет:
Даже скрины есть!


а где скрины?



Ранг: 419.0 (мудрец), 647thx
Активность: 0.460.51
Статус: Участник
"Тибериумный реверсинг"

Создано: 23 апреля 2015 17:28
· Личное сообщение · #10

VodoleY пишет:
ЗЫ просто за тему получи лайк)))

Взаимовыгодный обмен
Coderess пишет:
А нет ли патчей для игры с большим разрешением

Там вроде окно через CreateWindow создается изначально и можно добавить, сколь угодное душе, разрешение - оно в переменных потом пропишется.
dosprog пишет:
Хуже было бы, если бы не диабловский обработчик выдавал сообщение, а система.

Так олька же всё равно отловит исключение первой, в случае с 0xc0000005 - это не шибко кретично.
DenCoder пишет:
да, странно использовать для подсчёта кол-ва выделяемой памяти тип знаковых целых.

Я, чес говоря, больше не понимаю, почему v6 = (a3 - a2) / v5; нельзя было вывести за пределы функи, т.е. если позволяет код программы, компиль мог static посчитать результат и прописать. И вообще, вроде, можно функу можно оптимизировать и по кол-ву аргмуентов и по коду внутри. Ну и SSE2 добавить (инфа для разрабов)-там работа с массивами.

Добавлено спустя 3 минуты
скриншотэ (3D DIrectX 12)




Ранг: 0.9 (гость), 1thx
Активность: 0=0
Статус: Участник

Создано: 23 апреля 2015 19:03
· Личное сообщение · #11

меня смущает эта строчка

Code:
  1. 6F8497F1      72 05         JL SHORT 6F8497F8  // we can seek! ;)


скопипастил уже пофиксеный кодес?



Ранг: 419.0 (мудрец), 647thx
Активность: 0.460.51
Статус: Участник
"Тибериумный реверсинг"

Создано: 23 апреля 2015 19:21
· Личное сообщение · #12

Xorik пишет:
скопипастил уже пофиксеный кодес?

Ба! Blizzard? Не?

Уже сказал же выше: JL -> JB




Ранг: 990.2 (! ! !), 380thx
Активность: 0.680
Статус: Модератор
Author of DiE

Создано: 27 апреля 2015 08:51
· Личное сообщение · #13

ELF_7719116 скрин не кликабелен ((( а лучше 2 запили, для сравнения
з.ы. помню давно прошел диаблу 2, а потом узнал,
что есть есть expansion pack и прошел еще раз.
3-я часть уже не то, хз почему.

-----
[nice coder and reverser]





Ранг: 241.9 (наставник), 107thx
Активность: 0.140.01
Статус: Участник

Создано: 27 апреля 2015 13:46
· Личное сообщение · #14

Узнай что такое The Grapes Of Wrath, Zy-El, MedianXL и пройди еще раз
Никогда не забуду как поставил один из них, выбежал и умер от падших. По сравнению с классикой намного интереснее.



Ранг: 13.9 (новичок), 9thx
Активность: 0.010
Статус: Участник

Создано: 03 мая 2015 01:13
· Личное сообщение · #15

[OFFTOP]
>По сравнению с классикой намного интереснее.
И "хардкорнее". Сейчас с товарищем на пару проходим MedianXL. Уже разбито две клавиатуры. И это только до первого испытания добрались (Тран атлуа).
[/OFFTOP]


 eXeL@B —› Крэки, обсуждения —› Diablo II bug fix
:: Ваш ответ
Жирный  Курсив  Подчеркнутый  Перечеркнутый  {mpf5}  Код  Вставить ссылку 
:s1: :s2: :s3: :s4: :s5: :s6: :s7: :s8: :s9: :s10: :s11: :s12: :s13: :s14: :s15: :s16:


Максимальный размер аттача: 500KB.
Ваш логин: german1505 » Выход » ЛС
   Для печати Для печати