Cześć. Na wstepie wybaczcie, że się rozpisałem okropnie nawet jak na "moje standardy". Ale w wolnej chwili nadal męczyłem się z TSR'ami i "polskim Warcraftem". Swoje problemy opisuje poniżej.
Niestety @_13th_Dragon i @msm nie mogli mi pomóc (może teraz znajdą chwilę, bo wspomnę o nich w komentarzu :)), a jeśli nie to proszę innych o odpowiedź. Także jakoś udało mi się napisać na bazie tutoriala i kodu źródlowego autorstwa beanusa, który był zamieszczony w zinie BadIdea #1
napisać to co wklejam poniżej.
Kod działa prawidłowo, gra jest oszukiwana pod DOSBox'em zarówno w wersji CD jak i spatchowanej przeze mnie NOCD. Problem małem początkowo ze skorzystaniem z rejestru 32 bitowego, aby modyfikować pamięć pod adresem o wartości większej niż $FFFF. Poza tym teraz chciałbym się dowiedzieć jak w tym trainerze dopasować dwie rzeczy (kod poniżej).
Jak coś pod adresu http://olesio.eu/dos_asm.rar można pobrać moje "środowisko do działań z TASM'em pod DOS'em i potrzebnymi narzędziami (pliki *.asm kompilują się po naciśnięciu entera na nich pod NC, a po F4 otwierają się w skonfigurowanym Asm Edit). Natomiast z pod adresu: http://olesio.eu/polanie można pobrać wspomianą grę w wersji dyskietkowej (do niej trainer pisany na rejestracj 16 bitowych działa ok i jestem z kodu zadowolony), wersję z obrazem CD i wersję NOCD, z dołączonymi DOSBox'ami i trainerami.
Kod poniższego trainera jest też w mojej paczce DOS_ASM w pliku C:\ASM\polcd_t.asm
. Ok. I teraz co mi spędza sen z powiek ;) Po pierwsze czy da się instrukcje po porównaniu, czyli te...
mov ds:[esi],eax
mov eax,0C9h
mov esi,1A7FDBh
mov ds:[esi],eax
mov eax,08Dh
mov esi,1A7FDCh
mov ds:[esi],eax
mov eax,082h
mov esi,1A7FDDh
mov ds:[esi],eax
Napisac jakoś bardziej elegancko? Zapis pojedycznego bajtu C9h
pod 1A7FDBh
niestety nie skutkuje zmianą w działaniu gry. Natomiast próba zapisu po instrukcji mov esi,1A7FDAh
i porównaniu na przykład w sposób esi+1
też nie skutkuje zmianą w grze. Także czy można te patchowanie w pamięci zrobić jakoś bardziej elegancko pod względem zapisu? Prosił bym o przykład kodu.
Druga sprawa. Jak ustalać właściwy ds
dla obszaru jaki mamy zmieniać? Teraz w kodzie jest tak, jak widzicie - czyli:
mov ax,word ptr ss:[bp+4]
sub ax,05F3h
W ax
ląduje codesection gry (CS). Jednak wartość 05F3h
ustaliłem trochę lamerską techniką. Mianowicie w kodzie patchującym pamięć gry, bez sprawdzania wartości zapisałem unikalny ciąg bajtów pod adresem gdzie ustaliłem koniecznośc zmian. Konkratnie 3a 9e 3a 9e
. Później wyszukiwałem go w procesie DOSBox'a z uruchomioną grą i załadowanym TSR'em przy użyciu Cheat Engine. Następnie wyszukiwałem opcodów instrukcji w miejscu które trzeba patchowac, a które ustalilem debuggerem DOSBox'a, czyli bajty opcodów 89 C1 8D 82
. Początkowo bez odejmowania czegokolwiek od ax
różnica wyniosła o ile pamiętam $1680
. Później odjąłem od ax jeden. Sprawdzilem różnice pod Cheat Engine i na podstawie obliczeń Kalkulatorem Windows w wyszła mi ta liczba do odjęcia jako prawidlowa. No właśnie, ale w czasach powstanie tej gry, gdy na topie był chyba Windows 95, a pod nim chyba tylko GameHack, to nie wiem czy tak łatwo było te różnice ustalić.
Niestety dosowy Soft-ICE i jednoczęsnie gra w wersji NOCD nie chcą działać pod VMWare WorkStaton ani DOSBox'em z postawionym DOS'em. A maszyny z Windows 95 nie stawiałem jeszcze. Zaś Debugger DOSBox'a nie ma polecenia w stylu s
. Można tylko zrobić memdumpbin
o wielkości $1000000 i przeszukać go na przykład pod HIEW'em. Z pod tego co widzę pod DOSBox'owym Debuggerem to po założeniu bpint na 33h mamy CS=160,a DS=168, ale odejmowanie 8 czy dodawanie albo próba zapisu pod samo ax, zawierające CS skutkuje właśnie tym przesunietym "na plus" (dalej) zmienionym ciągiem bajtów, o $1680
.
O ile wiem to właśnie jedna wartość więcej w CS czy DS to chyba 16 ($10) bajtów - opcodów instrukcji. Także pewnie stąd ta różnica. Ale włąsnie jak takie rzeczy ustalać. Bo w kodzie w pliku gods_trn.asm
zawartym w moim środowisku ASM'owym mamy ;DS=CS-1DB6h
i według tego co opisano w pliku beanus01.txt
(katalog C:\ASM), to faktycznie jak uruchomię grę GODS i we właściwej fazie gry wejdę do debuggera, to różnica między CS, a DS tyle właśnie wynosi. A tutaj w przypadku Polan CD próba dodania do CS 8 albo $1680 powodowała zapiś odpowiednich wartości jeszcze gdzie indziej i to po kilka razy czasami, co wynikało z CHeat Engine. Może mi to ktoś wyjaśnić jak takie rzeczy ustalać nie po omacku ale przy użyciu DOSBox'owego Debuggera?
A oto kod całego trainera, jeśli ktoś chciałby pomóc bez ściągania mojego "środowiska" ASM:
.model tiny
.code
.386
org 100h
Start:
jmp RealStart
OldProc dd 0
TrainerProc:
push bp
mov bp,sp
pusha
push es
push ds
mov ax,word ptr ss:[bp+4]
sub ax,05F3h
mov ds,ax
mov eax,089h
mov esi,1A7FDAh
cmp dword ptr ds:[esi], 0828DC189h
jne EndOfTrainer
mov ds:[esi],eax
mov eax,0C9h
mov esi,1A7FDBh
mov ds:[esi],eax
mov eax,08Dh
mov esi,1A7FDCh
mov ds:[esi],eax
mov eax,082h
mov esi,1A7FDDh
mov ds:[esi],eax
EndOfTrainer:
pop ds
pop es
popa
pop bp
jmp dword ptr cs:[OldProc]
RealStart:
mov ax,3
int 10h
mov ah,9
mov dx,offset LogoText
int 21h
mov si,81h
mov ax,3533h
int 21h
cmp bx,offset TrainerProc
jne InstallNow
mov dx,word ptr es:[OldProc]
mov ax,word ptr es:[OldProc +2]
mov ds,ax
mov ax,2533h
int 21h
mov ah,49h
int 21h
mov ax,cs
mov ds,ax
mov ah,9
mov dx,offset UninstalledText
int 21h
mov ax,4c02h
int 21h
InstallNow:
mov ax,word ptr ds:[2ch]
mov es,ax
mov ah,49h
int 21h
mov ax,3533h
int 21h
mov word ptr cs:[OldProc],bx
mov word ptr cs:[OldProc +2],es
mov ax,2533h
mov dx,offset TrainerProc
int 21h
mov ah,9
mov dx,offset InstalledText
int 21h
mov dx,offset RealStart
int 27h
LogoText db 13,10,13,10
db ' ________ _________ ____ _________ __________ ____ ________'
db 13,10
db ' E _\ __/_/ \ \/ /_ _ /_\__ /_ \/ /_ / /_'
db 13,10
db ' H \ / / / / _/ ____/ _ _/ \ _/__ _/'
db 13,10
db ' T /________\______/___\/___\___/ /_________\___\____\/_______\spot'
db 13,10,13,10
db ' Polanie CD (v4.27) not decreasing milk - trainer by olesio'
db 13,10
db ' Adapted from source code of Gods trainer by beanus & CoxoC'
db 13,10,13,10,'$'
InstalledText db ' Trainer has been installed in memory.',13,10,13,10,'$'
UninstalledText db ' Trainer has been removed from memory.',13,10,13,10,'$'
end Start