Добро пожаловать, гость ( Вход | Регистрация )
![]() ![]() |
| Grom PE |
Jul 19 2026, 10:36
Сообщение
#1
|
![]() Advanced Member ![]() ![]() ![]() Группа: CTPAX-X Сообщений: 87 Регистрация: 7-February 08 Из: i@grompe.org Пользователь №: 3,120 Спасибо сказали: 98 раз(а) |
Некто мне напомнил о существовании такой игры, как MageSlayer.
Пожаловался на управление, а я помнил только, что нравилась игра, а про управление негативных впечатлений не осталось. Решил скачать и проверить. И что же я увидел? Вид сверху, бег можно настроить, чтоб WASD слал на все четыре стороны, настройка "tank strafe". А вот с мышью не заладилось. Игра умеет только воспринимать движение вверх-вниз, как бег вперёд-назад, а влево-вправо — как поворот. Так дело не пойдёт, решил я, и пропатчил игру, чтоб курсор мыши был точкой, куда смотрит персонаж. Теперь играется, словно современная игра. Попрактиковался с fasmg, где макросы для патчинга стали ещё проще, чем это требовалось в fasm 1, попрактиковался с Ghidra и x87 FPU. Игру берём отсюда: https://www.old-games.ru/game/496.html Дисковую версию, после патча до 1.1. Пока сильно не играл, на форуме old-games.ru говорят, что версия 1.1 портит прохождение, это ещё надо изучить. А вот версия 1.0 крашится при перемещении на первую локацию, если разрешение игры не 640x480x8. Что сделано: - пропатчил вызовы ShowCursor, чтоб курсор никогда не скрывался - пропатчил вызов SetCooperativeLevel, где был бит DISCL_EXCLUSIVE, чтоб курсор мыши не захватывался эксклюзивно, и опять же не скрывался из-за этого же - пропатчил место, где движения мыши вызывали движение и поворот персонажа - уникального значения "угол поворота персонажа" я не нашёл, поэтому пришлось обходным путём: нашёл место, где читается угол поворота разных объектов на уровне, а если вызов происходит из конкретной функции, то это персонаж, записываем угол. - используя текущий угол персонажа и положение курсора на экране, вычисляем скорость поворота, которую надо отправить в сетевой пакет. - чтоб поворот не случился больше нужного, заставляем функцию проверки ввода от мыши вызываться каждый кадр, а не только если координаты изменились Проверял на Wine 10.5, виртуалке Windows 2000 SP2, Windows XP SP3. Итак, вот мой патч: CODE ; mouse targeting patch for MageSlayer v1.1 ; use fasmg to assemble against mageslay.exe, sha256=1a970cd3d2d5065a93cdd1ee0b9fe370d0df107efbf3e4a2f1d4a9a47abfe8a7 format binary as 'exe' include 'p6.inc' calminstruction align? boundary,value:? compute boundary, (boundary-1)-((0 scaleof $)+boundary-1) mod boundary arrange value, =db boundary =dup value assemble value end calminstruction file 'mageslay.exe' macro patch cmd match =at= vaddr= =to= paddr,cmd offs = paddr virtual at vaddr end macro macro end?.patch! load mover:$ - $$ from $$ store mover:lengthof mover at :offs end virtual end match end macro use32 if $ <> 1121792 err 'wrong mageslay.exe version, if 1.0, patch to 1.1 first!' end if new_ep_rva = new_ep - 0x400000 store dword new_ep_rva at :0xA8 store dword 0xD9800 at :0x180; more space for code in .text store dword 0x01400 at :0x1F8; more space for data in .idata patch at 0x428FF4 to 0x283F4 jmp get_angle_of_object end patch patch at 0x42AC39 to 0x2A039 jmp go_catch_the_flag end patch store byte 0xEB at :0x352F8; no-cd ;patch at 0x4375DB to 0x369DB; original printf is broken?.. ; patch05:: ; push 1.1 ;end patch store byte 4 at :0x3A7CE; remove exclusive mouse access patch at 0x46CBBA to 0x6BFBA; make it always check for mouse input instead of only when moved, fixes spinning around jmp $+13 end patch patch at 0x46CC2C to 0x6C02C jmp handle_mouse_input end patch store "Version: 1.1mf":14 at :0xE65A8 label ShowCursor dword at 0x5A45CC label user32_dll dword at 0x4DCDB0 label LoadLibraryA dword at 0x5A4488 label GetProcAddress dword at 0x5A451C label str_percent_d at 0x4E3A6F label printf_to_console at 0x4132A0 label main_hwnd dword at 0x547F84 label GetClientRect dword at 0x5A4604 patch at 0x4DA6D8 to 0xD9AD8 disabled_ShowCursor: xor eax,eax ret 4 align 16, 0x90 new_ep: mov eax,disabled_ShowCursor mov [ShowCursor],eax push GetCursorPos push user32_dll call [LoadLibraryA] push eax call [GetProcAddress] mov [GetCursorPos],eax jmp 0x4A8060 ; align 16, 0x90 ;debug_print_float32: ; push eax ; fld dword [esp] ; push 10 ; fild dword [esp] ; fmulp st(1),st(0) ; fistp dword [esp] ; pop eax ; add esp,4 ; align 16, 0x90 ;debug_print_int32: ; push eax ; push str_percent_d ; call printf_to_console ; add esp,8 ; ret align 16, 0x90 go_catch_the_flag: xor ecx,ecx inc ecx mov [catch_flag],ecx call 0x427300; original func jmp 0x42AC3E; original place align 16, 0x90 get_angle_of_object: mov ecx,[catch_flag] test ecx,ecx jz no_catch mov ecx,[edx+eax*4] mov [current_angle],ecx xor ecx,ecx mov [catch_flag],ecx no_catch: jmp 0x42A0DC; original place handle_mouse_input: call 0x416B20; original func xor eax,eax mov [esp+0x38],eax; zero out forward/backward speed ; mov [esp+0x34],eax; zero out turning speed push CursorPos_point call [GetCursorPos] mov eax,[main_hwnd] push GetClientRect_rect push eax call [GetClientRect] mov eax,[CursorPos_point+4] mov edx,[GetClientRect_rect+12] shr edx,1 sub edx,eax push edx fild dword [esp] mov eax,[CursorPos_point] mov edx,[GetClientRect_rect+8] shr edx,1 sub eax,edx push eax fild dword [esp] fpatan fld [current_angle] fsubp st(1),st(0) fldpi fadd st(0),st(0) fxch st(1) fprem1 fstp st(1) push 0x40000; turning speed multiplier fimul dword [esp] add esp, 12 fistp dword [esp+0x34] jmp 0x46CC31; original place if $ >= 0x4DA800 err 'code too big, not enough space!' end if end patch patch at 0x5A5260 to 0xF3460 catch_flag dd 0; set to 1 if current object is player current_angle dd 0 label GetCursorPos dword db 'GetCursorPos',0 align 4 CursorPos_point: dd 0,0 GetClientRect_rect: dd 0,0,0,0 if $ >= 0x5A5400 err 'data too big, not enough space!' end if end patch Спасибо сказали:
|
| Grom PE |
Jul 19 2026, 11:23
Сообщение
#2
|
![]() Advanced Member ![]() ![]() ![]() Группа: CTPAX-X Сообщений: 87 Регистрация: 7-February 08 Из: i@grompe.org Пользователь №: 3,120 Спасибо сказали: 98 раз(а) |
С помощью худо-бедно скомпилированного vpack:
https://web.archive.org/web/19980502215605/...files/vpack.cpp выяснил, что версии 1.0 и 1.1 mage.vpk различаются следующими файлами внутри: MAPS/DEATH3.VBM MAPS/KEEP4.VBM MAPS/SEWSCRT1.VBM MAPS/TEMPLE4.VBM MAPS/TEMPLEBS.VBM MAPS/TMPSCRT1.VBM MAPS/TMPSCRT2.VDT MAPS/TOMB2.VBM Пока неясно, что с этим делать. В архиве с исходниками утилит https://web.archive.org/web/19980502215645/...es/rtsource.zip ещё есть bspbin.c, который эти VBM только генерирует. Спасибо сказали:
|
| -=CHE@TER=- |
Jul 19 2026, 13:02
Сообщение
#3
|
|
Walter Sullivan ![]() ![]() ![]() Группа: Root Admin Сообщений: 1,449 Регистрация: 4-February 08 Пользователь №: 3 Спасибо сказали: 332 раз(а) |
Welcome back, дружище!
С удовольствием прочитал твои изыскания, хотя игру видел всего один раз в жизни мельком в гостях. С помощью худо-бедно скомпилированного vpack: Если есть исходные коды распаковщика/упаковщика файлов игры, то можно по одному файлу заменять, смотреть что поменялось, чтобы сузить круг подозреваемых.... выяснил, что версии 1.0 и 1.1 mage.vpk различаются следующими файлами внутри: ... Пока неясно, что с этим делать. В версии 1.00 и 1.1 только эти файлы меняются? Исполняемый файл тот же самый? |
| Grom PE |
Jul 19 2026, 13:41
Сообщение
#4
|
![]() Advanced Member ![]() ![]() ![]() Группа: CTPAX-X Сообщений: 87 Регистрация: 7-February 08 Из: i@grompe.org Пользователь №: 3,120 Спасибо сказали: 98 раз(а) |
можно по одному файлу заменять, смотреть что поменялось Так и думаю сделать, когда дойду в игре до глючного места.QUOTE В версии 1.00 и 1.1 только эти файлы меняются? Исполняемый файл тот же самый? mageslay.exe тоже меняется, я изучал и патчил только 1.1. Не считая того, что no-cd подсмотрел из различий от 1.0 патченного и оригинала.Спасибо сказали:
|
![]() ![]() |
| Упрощённая версия | Сейчас: 21st July 2026 - 04:05 |