1166 lines
23 KiB
PHP
1166 lines
23 KiB
PHP
;Copyright (C) 1997-2007 ZSNES Team ( zsKnight, _Demo_, pagefault, Nach )
|
|
;
|
|
;http://www.zsnes.com
|
|
;http://sourceforge.net/projects/zsnes
|
|
;https://zsnes.bountysource.com
|
|
;
|
|
;This program is free software; you can redistribute it and/or
|
|
;modify it under the terms of the GNU General Public License
|
|
;version 2 as published by the Free Software Foundation.
|
|
;
|
|
;This program is distributed in the hope that it will be useful,
|
|
;but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
;GNU General Public License for more details.
|
|
;
|
|
;You should have received a copy of the GNU General Public License
|
|
;along with this program; if not, write to the Free Software
|
|
;Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
|
|
SECTION .text
|
|
|
|
; GUI Cheat Code Routines
|
|
|
|
AddCSCheatCode:
|
|
cmp byte[CSInputDisplay],'_'
|
|
je .nodisplay
|
|
jmp .okay
|
|
.nodisplay
|
|
ret
|
|
.okay
|
|
mov eax,[curentryval]
|
|
mov [curaddrvalcs],eax
|
|
mov eax,[CSCurValue]
|
|
mov [curvaluecs],eax
|
|
xor ecx,ecx
|
|
mov cl,[CheatSrcByteSize]
|
|
inc cl
|
|
cmp byte[CheatUpperByteOnly],0
|
|
je .cspardisploop
|
|
mov cl,1
|
|
.cspardispagain
|
|
cmp dword[curvaluecs],0FFh
|
|
jbe .cspardisploop
|
|
shr dword[curvaluecs],8
|
|
inc dword[curaddrvalcs]
|
|
jmp .cspardispagain
|
|
.cspardisploop
|
|
push ecx
|
|
mov esi,GUICSrcTextG1
|
|
mov ecx,3
|
|
mov eax,[curaddrvalcs]
|
|
add eax,7E0000h
|
|
mov bl,[curvaluecs]
|
|
; write bl at address eax
|
|
call AddCheatCode
|
|
|
|
shr dword[curvaluecs],8
|
|
mov byte[GUItextcolor],223
|
|
|
|
add dword[CheatSearchYPos],10
|
|
inc dword[curaddrvalcs]
|
|
pop ecx
|
|
dec ecx
|
|
jnz near .cspardisploop
|
|
mov byte[CheatWinMode],2
|
|
ret
|
|
|
|
%macro SearchCMPByte 0
|
|
mov bl,[edi]
|
|
cmp bl,[esi]
|
|
%endmacro
|
|
|
|
%macro SearchCMP2Bytes 0
|
|
mov bx,[edi]
|
|
cmp bx,[esi]
|
|
%endmacro
|
|
|
|
%macro SearchCMP3Bytes 0
|
|
push ecx
|
|
mov ebx,[edi]
|
|
mov ecx,[esi]
|
|
and ebx,0FFFFFFh
|
|
and ecx,0FFFFFFh
|
|
cmp ebx,ecx
|
|
pop ecx
|
|
%endmacro
|
|
|
|
%macro SearchCMP4Bytes 0
|
|
mov ebx,[edi]
|
|
cmp ebx,[esi]
|
|
%endmacro
|
|
|
|
%macro SearchMacro 2
|
|
mov dl,0FEh
|
|
%%searchloop
|
|
%2
|
|
%1 %%nofail
|
|
and [eax],dl
|
|
%%nofail
|
|
inc edi
|
|
inc esi
|
|
cmp dl,7Fh
|
|
jne %%noinceax
|
|
inc eax
|
|
%%noinceax
|
|
rol dl,1
|
|
; loop %%searchloop
|
|
dec ecx
|
|
jnz %%searchloop
|
|
%endmacro
|
|
|
|
%macro SearchMacroB 1
|
|
cmp byte[CheatCompareValue],0
|
|
je near %%greater
|
|
cmp byte[CheatCompareValue],1
|
|
je near %%lessthan
|
|
cmp byte[CheatCompareValue],3
|
|
je near %%notequalthan
|
|
SearchMacro je, %1
|
|
jmp .end
|
|
%%greater
|
|
SearchMacro ja, %1
|
|
jmp .end
|
|
%%lessthan
|
|
SearchMacro jb, %1
|
|
jmp .end
|
|
%%notequalthan
|
|
SearchMacro jne, %1
|
|
jmp .end
|
|
%endmacro
|
|
|
|
CheatCodeSearchProcess:
|
|
cmp byte[CheatSrcSearchType],1
|
|
je near .comparative
|
|
cmp byte[CSInputDisplay],0
|
|
je near .nodisplay
|
|
cmp byte[CSInputDisplay],'_'
|
|
je near .nodisplay
|
|
cmp byte[CSOverValue],1
|
|
je near .nodisplay
|
|
mov byte[CSInputDisplay],'_'
|
|
mov byte[CSInputDisplay+1],0
|
|
; Process Cheat Search
|
|
mov ecx,65536*2
|
|
xor ebx,ebx
|
|
mov bl,[CheatSrcByteSize]
|
|
sub ecx,ebx
|
|
mov edx,[SrcMask+ebx*4]
|
|
mov edi,[vidbuffer]
|
|
add edi,129600+65536*2
|
|
mov esi,[wramdata]
|
|
mov bl,0FEh
|
|
mov bh,01h
|
|
.exactloop
|
|
mov eax,[esi]
|
|
and eax,edx
|
|
cmp eax,[CSCurValue]
|
|
je .found
|
|
inc eax
|
|
and eax,edx
|
|
cmp eax,[CSCurValue]
|
|
je .foundb
|
|
.failedfind
|
|
and [edi],bl
|
|
jmp .foundc
|
|
.found
|
|
test byte[edi+16384],bh
|
|
jz .failedfind
|
|
jmp .foundc
|
|
.foundb
|
|
cmp byte[FirstSearch],1
|
|
je .clear
|
|
test byte[edi+16384],bh
|
|
jnz .failedfind
|
|
jmp .foundc
|
|
.clear
|
|
and byte[edi+16384],bl
|
|
.foundc
|
|
cmp bl,7Fh
|
|
jne .noincedi
|
|
inc edi
|
|
.noincedi
|
|
rol bl,1
|
|
rol bh,1
|
|
inc esi
|
|
dec ecx
|
|
jnz .exactloop
|
|
mov byte[CopyRamToggle],1
|
|
mov byte[CheatSearchStatus],1
|
|
.nodisplay
|
|
ret
|
|
.comparative
|
|
mov byte[CSInputDisplay],'_'
|
|
mov byte[CSInputDisplay+1],0
|
|
mov byte[CheatSearchStatus],1
|
|
mov eax,[vidbuffer]
|
|
add eax,129600+65536*2
|
|
mov esi,[vidbuffer]
|
|
add esi,129600
|
|
mov edi,[wramdata]
|
|
mov ecx,65536*2
|
|
cmp byte[CheatSrcByteSize],1
|
|
je near .bytesize2
|
|
cmp byte[CheatSrcByteSize],2
|
|
je near .bytesize3
|
|
cmp byte[CheatSrcByteSize],3
|
|
je near .bytesize4
|
|
SearchMacroB SearchCMPByte
|
|
.bytesize2
|
|
dec ecx
|
|
SearchMacroB SearchCMP2Bytes
|
|
.bytesize3
|
|
sub ecx,2
|
|
SearchMacroB SearchCMP3Bytes
|
|
.bytesize4
|
|
sub ecx,3
|
|
SearchMacroB SearchCMP4Bytes
|
|
.end
|
|
mov byte[CopyRamToggle],1
|
|
ret
|
|
|
|
SECTION .bss
|
|
CopyRamToggle resb 1
|
|
FirstSearch resb 1
|
|
SECTION .text
|
|
|
|
CheatCodeSearchInit:
|
|
mov byte[CSInputDisplay],'_'
|
|
mov byte[CSInputDisplay+1],0
|
|
mov byte[CheatWinMode],1
|
|
mov byte[CheatSearchStatus],0
|
|
mov byte[FirstSearch],1
|
|
mov eax,[vidbuffer]
|
|
add eax,129600
|
|
; copy 128k ram
|
|
mov ebx,[wramdata]
|
|
mov ecx,32768
|
|
.loop
|
|
mov edx,[ebx]
|
|
mov [eax],edx
|
|
add ebx,4
|
|
add eax,4
|
|
dec ecx
|
|
jnz .loop
|
|
; fill searched buffer with 0xFF
|
|
mov eax,[vidbuffer]
|
|
add eax,129600+65536*2
|
|
mov ecx,8192
|
|
.loop2
|
|
mov dword[eax],0FFFFFFFFh
|
|
add eax,4
|
|
dec ecx
|
|
jnz .loop2
|
|
cmp byte[CheatSrcSearchType],1
|
|
jne .nottype1
|
|
mov byte[CheatSearchStatus],1
|
|
.nottype1
|
|
mov dword[CheatCompareValue],0
|
|
mov eax,[vidbuffer]
|
|
add eax,129600+65536*2
|
|
cmp byte[CheatSrcByteSize],1
|
|
je near .bytesize2
|
|
cmp byte[CheatSrcByteSize],2
|
|
je near .bytesize3
|
|
cmp byte[CheatSrcByteSize],3
|
|
je near .bytesize4
|
|
ret
|
|
.bytesize2
|
|
and byte[eax+16383],07Fh
|
|
ret
|
|
.bytesize3
|
|
and byte[eax+16383],03Fh
|
|
ret
|
|
.bytesize4
|
|
and byte[eax+16383],01Fh
|
|
ret
|
|
|
|
NEWSYM DisableCheatsOnLoad
|
|
; Disable all codes
|
|
mov esi,cheatdata
|
|
mov ecx,[NumCheats]
|
|
cmp ecx,0
|
|
je .skip
|
|
.loop2
|
|
test byte[esi],4
|
|
jnz .disabled2
|
|
push esi
|
|
push ecx
|
|
call DisableCheatCode
|
|
pop ecx
|
|
pop esi
|
|
.disabled2
|
|
add esi,28
|
|
dec ecx
|
|
jnz .loop2
|
|
.skip
|
|
ret
|
|
|
|
NEWSYM EnableCheatsOnLoad
|
|
; Enable all ON toggled cheat codes
|
|
mov esi,cheatdata
|
|
mov ecx,[NumCheats]
|
|
cmp ecx,0
|
|
je .skip2
|
|
.loop
|
|
test byte[esi],4
|
|
jnz .disabled
|
|
push esi
|
|
push ecx
|
|
call EnableCheatCode
|
|
pop ecx
|
|
pop esi
|
|
.disabled
|
|
add esi,28
|
|
dec ecx
|
|
jnz .loop
|
|
.skip2
|
|
ret
|
|
|
|
CheatCodeRemove:
|
|
mov byte[GUICBHold],0
|
|
cmp dword[NumCheats],0
|
|
jne .nonone
|
|
ret
|
|
.nonone
|
|
mov esi,[GUIcurrentcheatcursloc]
|
|
shl esi,5
|
|
sub esi,[GUIcurrentcheatcursloc]
|
|
sub esi,[GUIcurrentcheatcursloc]
|
|
sub esi,[GUIcurrentcheatcursloc]
|
|
sub esi,[GUIcurrentcheatcursloc]
|
|
add esi,cheatdata
|
|
push esi
|
|
call DisableCheatCode
|
|
pop esi
|
|
mov eax,255
|
|
sub eax,[GUIcurrentcheatcursloc]
|
|
mov ebx,eax
|
|
shl eax,4
|
|
add eax,ebx
|
|
add eax,ebx
|
|
.loop
|
|
mov bl,[esi+28]
|
|
mov [esi],bl
|
|
inc esi
|
|
dec eax
|
|
jnz .loop
|
|
dec dword[NumCheats]
|
|
mov eax,[GUIcurrentcheatcursloc]
|
|
cmp dword[NumCheats],0
|
|
je .okay
|
|
cmp eax,[NumCheats]
|
|
jne .okay
|
|
dec eax
|
|
mov [GUIcurrentcheatcursloc],eax
|
|
sub eax,11
|
|
mov [GUIcurrentcheatviewloc],eax
|
|
test dword[GUIcurrentcheatviewloc],80000000h
|
|
jz .noview
|
|
mov dword[GUIcurrentcheatviewloc],0
|
|
.noview
|
|
.okay
|
|
cmp byte[NumCheats],0
|
|
jne .cheatexists
|
|
mov byte[CheatOn],0
|
|
.cheatexists
|
|
ret
|
|
|
|
CheatCodeFix:
|
|
mov byte[GUICBHold],0
|
|
cmp dword[NumCheats],0
|
|
jne .nonone
|
|
ret
|
|
.nonone
|
|
mov esi,[GUIcurrentcheatcursloc]
|
|
shl esi,5
|
|
sub esi,[GUIcurrentcheatcursloc]
|
|
sub esi,[GUIcurrentcheatcursloc]
|
|
sub esi,[GUIcurrentcheatcursloc]
|
|
sub esi,[GUIcurrentcheatcursloc]
|
|
add esi,cheatdata
|
|
push esi
|
|
call DisableCheatCode
|
|
pop esi
|
|
xor byte[esi+3],80h
|
|
call EnableCheatCodeNoPrevMod
|
|
ret
|
|
|
|
CheatCodeToggle:
|
|
mov byte[GUICBHold],0
|
|
cmp dword[NumCheats],0
|
|
jne .nonone
|
|
ret
|
|
.nonone
|
|
mov esi,[GUIcurrentcheatcursloc]
|
|
shl esi,5
|
|
sub esi,[GUIcurrentcheatcursloc]
|
|
sub esi,[GUIcurrentcheatcursloc]
|
|
sub esi,[GUIcurrentcheatcursloc]
|
|
sub esi,[GUIcurrentcheatcursloc]
|
|
add esi,cheatdata
|
|
test byte[esi],4
|
|
jz DisableCheatCode
|
|
jmp EnableCheatCodeNoPrevMod
|
|
|
|
DisableCheatCode:
|
|
; code is at esi
|
|
xor ecx,ecx
|
|
xor ebx,ebx
|
|
or byte[esi],4
|
|
test byte[esi],1
|
|
jnz .gfrom
|
|
mov al,[esi+5]
|
|
mov cx,[esi+2]
|
|
mov bl,[esi+4]
|
|
mov byte[writeon],1
|
|
test byte[esi],80h
|
|
jnz .nowrite
|
|
test byte[esi-28],80h
|
|
jnz .nowrite
|
|
call dword near [memtablew8+ebx*4]
|
|
.nowrite
|
|
mov byte[writeon],0
|
|
ret
|
|
.gfrom
|
|
mov al,[esi+5]
|
|
mov ecx,[esi+2]
|
|
and ecx,0FFFFFFh
|
|
mov esi,[romdata]
|
|
mov [esi+ecx],al
|
|
ret
|
|
.gfram
|
|
mov al,[esi+5]
|
|
mov ecx,[esi+2]
|
|
and ecx,0FFFFFFh
|
|
mov esi,[sram]
|
|
mov [esi+ecx],al
|
|
ret
|
|
|
|
EnableCheatCode:
|
|
; code is at esi
|
|
xor ecx,ecx
|
|
xor ebx,ebx
|
|
and byte[esi],0FBh
|
|
test byte[esi],1
|
|
jnz .gfrom
|
|
mov al,[esi+1]
|
|
mov cx,[esi+2]
|
|
mov bl,[esi+4]
|
|
push ecx
|
|
push eax
|
|
push ebx
|
|
push edx
|
|
call dword near [memtabler8+ebx*4]
|
|
pop edx
|
|
mov [esi+5],al
|
|
pop ebx
|
|
pop eax
|
|
pop ecx
|
|
mov byte[writeon],1
|
|
test byte[esi],80h
|
|
jnz .nowrite
|
|
test byte[esi-28],80h
|
|
jnz .nowrite
|
|
call dword near [memtablew8+ebx*4]
|
|
.nowrite
|
|
mov byte[writeon],0
|
|
ret
|
|
.gfrom
|
|
mov al,[esi+1]
|
|
mov ecx,[esi+2]
|
|
and ecx,0FFFFFFh
|
|
mov esi,[romdata]
|
|
mov bl,[esi+ecx]
|
|
mov [esi+ecx],al
|
|
mov [esi+5],bl
|
|
ret
|
|
.gfram
|
|
mov al,[esi+1]
|
|
mov ecx,[esi+2]
|
|
and ecx,0FFFFFFh
|
|
mov esi,[sram]
|
|
mov bl,[esi+ecx]
|
|
mov [esi+ecx],al
|
|
mov [esi+5],bl
|
|
ret
|
|
|
|
EnableCheatCodeNoPrevMod:
|
|
; code is at esi
|
|
xor ecx,ecx
|
|
xor ebx,ebx
|
|
and byte[esi],0FBh
|
|
test byte[esi],1
|
|
jnz .gfrom
|
|
mov al,[esi+1]
|
|
mov cx,[esi+2]
|
|
mov bl,[esi+4]
|
|
mov byte[writeon],1
|
|
test byte[esi],80h
|
|
jnz .nowrite
|
|
test byte[esi-28],80h
|
|
jnz .nowrite
|
|
call dword near [memtablew8+ebx*4]
|
|
.nowrite
|
|
mov byte[writeon],0
|
|
ret
|
|
.gfrom
|
|
mov al,[esi+1]
|
|
mov ecx,[esi+2]
|
|
and ecx,0FFFFFFh
|
|
mov esi,[romdata]
|
|
mov bl,[esi+ecx]
|
|
mov [esi+ecx],al
|
|
mov [esi+5],bl
|
|
ret
|
|
.gfram
|
|
mov al,[esi+1]
|
|
mov ecx,[esi+2]
|
|
and ecx,0FFFFFFh
|
|
mov esi,[sram]
|
|
mov bl,[esi+ecx]
|
|
mov [esi+ecx],al
|
|
mov [esi+5],bl
|
|
ret
|
|
|
|
AddCheatCode:
|
|
mov byte[GUICBHold],0
|
|
cmp dword[NumCheats],255
|
|
jne .okay
|
|
ret
|
|
.okay
|
|
push eax
|
|
push ebx
|
|
; transfer description
|
|
mov eax,[NumCheats]
|
|
shl eax,5
|
|
sub eax,[NumCheats]
|
|
sub eax,[NumCheats]
|
|
sub eax,[NumCheats]
|
|
sub eax,[NumCheats]
|
|
add eax,cheatdata
|
|
mov edx,eax
|
|
push edx
|
|
add eax,6
|
|
mov ebx,CSDescDisplay
|
|
mov ecx,20
|
|
.dloop
|
|
mov dl,[ebx]
|
|
mov [eax+2],dl
|
|
mov [eax+18+2],dl
|
|
mov [eax+18*2+2],dl
|
|
inc ebx
|
|
inc eax
|
|
dec ecx
|
|
jnz .dloop
|
|
pop edx
|
|
pop ebx
|
|
pop eax
|
|
; toggle, value, address, pvalue, name(12)
|
|
mov byte[edx],0
|
|
mov [edx+1],bl
|
|
push eax
|
|
sub eax,7E0000h
|
|
add eax,[wramdata]
|
|
mov bh,[eax]
|
|
mov [eax],bl
|
|
pop eax
|
|
mov [edx+2],eax
|
|
mov [edx+5],bh
|
|
inc dword[NumCheats]
|
|
mov edx,7
|
|
mov al,[GUIpmenupos]
|
|
push eax
|
|
call CheckMenuItemHelp
|
|
pop eax
|
|
mov [GUIpmenupos],al
|
|
mov byte[CheatOn],1
|
|
ret
|
|
|
|
ProcessCheatCode:
|
|
mov byte[GUICBHold],0
|
|
cmp dword[NumCheats],255
|
|
je .fail
|
|
cmp byte[GUICheatPosA],0
|
|
je .fail
|
|
jmp .okay
|
|
.fail
|
|
ret
|
|
.okay
|
|
; make sure flashing cursor doesn't exist
|
|
xor ebx,ebx
|
|
mov bl,[GUICheatPosB]
|
|
mov byte[GUICheatTextZ2+ebx],0
|
|
; transfer description
|
|
mov eax,[NumCheats]
|
|
shl eax,5
|
|
sub eax,[NumCheats]
|
|
sub eax,[NumCheats]
|
|
sub eax,[NumCheats]
|
|
sub eax,[NumCheats]
|
|
add eax,cheatdata
|
|
add eax,6
|
|
mov ebx,GUICheatTextZ2
|
|
mov ecx,20
|
|
.dloop
|
|
mov dl,[ebx]
|
|
mov [eax+2],dl
|
|
mov [eax+18+2],dl
|
|
mov [eax+18*2+2],dl
|
|
inc ebx
|
|
inc eax
|
|
dec ecx
|
|
jnz .dloop
|
|
; determine whether it is gamegenie, par, or GF
|
|
; uppercase all codes if necessary
|
|
mov eax,GUICheatTextZ1
|
|
mov ecx,14
|
|
.loop
|
|
mov bl,[eax]
|
|
cmp bl,'a'
|
|
jb .nolower
|
|
cmp bl,'z'
|
|
ja .nolower
|
|
sub bl,'a'-'A'
|
|
mov [eax],bl
|
|
.nolower
|
|
inc eax
|
|
dec ecx
|
|
jnz .loop
|
|
mov byte[guicheatvalrep],0
|
|
xor eax,eax
|
|
mov al,[GUICheatPosA]
|
|
dec al
|
|
cmp byte[GUICheatTextZ1+eax],'R'
|
|
jne .notrep
|
|
mov byte[guicheatvalrep],80h
|
|
dec byte[GUICheatPosA]
|
|
.notrep
|
|
cmp byte[GUICheatPosA],8
|
|
je near .par
|
|
cmp byte[GUICheatPosA],9
|
|
je near .gg
|
|
cmp byte[GUICheatPosA],14
|
|
je near .gf
|
|
.invalidpar
|
|
jmp guicheaterror
|
|
.par
|
|
; check if code is valid
|
|
mov eax,GUICheatTextZ1
|
|
mov ecx,8
|
|
.looppar
|
|
mov bl,[eax]
|
|
cmp bl,'0'
|
|
jb .invalidpar
|
|
cmp bl,'9'
|
|
jbe .okaypar
|
|
cmp bl,'A'
|
|
jb .invalidpar
|
|
cmp bl,'F'
|
|
ja .invalidpar
|
|
.okaypar
|
|
inc eax
|
|
dec ecx
|
|
jnz .looppar
|
|
jmp decodepar
|
|
.invalidgg
|
|
jmp guicheaterror
|
|
.gg
|
|
; check if code is valid
|
|
mov eax,GUICheatTextZ1
|
|
mov ecx,9
|
|
.loopgg
|
|
cmp ecx,5
|
|
jne .nomid
|
|
cmp byte[eax],'-'
|
|
jne .invalidgg
|
|
inc eax
|
|
dec ecx
|
|
.nomid
|
|
mov bl,[eax]
|
|
cmp bl,'0'
|
|
jb .invalidgg
|
|
cmp bl,'9'
|
|
jbe .okaygg
|
|
cmp bl,'A'
|
|
jb .invalidgg
|
|
cmp bl,'F'
|
|
ja .invalidgg
|
|
.okaygg
|
|
inc eax
|
|
dec ecx
|
|
jnz .loopgg
|
|
jmp decodegg
|
|
ret
|
|
.invalidgf
|
|
jmp guicheaterror
|
|
.gf
|
|
; check if code is valid
|
|
mov eax,GUICheatTextZ1
|
|
mov ecx,5
|
|
.loopgf
|
|
mov bl,[eax]
|
|
cmp bl,'0'
|
|
jb .invalidgf
|
|
cmp bl,'9'
|
|
jbe .okaygf
|
|
cmp bl,'A'
|
|
jb .invalidgf
|
|
cmp bl,'F'
|
|
ja .invalidgf
|
|
.okaygf
|
|
inc eax
|
|
dec ecx
|
|
jnz .loopgf
|
|
mov eax,GUICheatTextZ1+5
|
|
mov ecx,6
|
|
.loopgf2
|
|
mov bl,[eax]
|
|
cmp bl,'X'
|
|
je .okaygf2
|
|
cmp bl,'0'
|
|
jb .invalidgf
|
|
cmp bl,'9'
|
|
jbe .okaygf2
|
|
cmp bl,'A'
|
|
jb near .invalidgf
|
|
cmp bl,'F'
|
|
ja near .invalidgf
|
|
.okaygf2
|
|
inc eax
|
|
dec ecx
|
|
jnz .loopgf2
|
|
mov bl,[GUICheatTextZ1+13]
|
|
cmp bl,'0'
|
|
je .okaygf3
|
|
cmp bl,'1'
|
|
jne near .invalidgf
|
|
.okaygf3
|
|
jmp decodegf
|
|
|
|
decodegf:
|
|
; convert code to number format
|
|
mov ecx,14
|
|
mov esi,GUICheatTextZ1
|
|
.loopb2
|
|
mov al,[esi]
|
|
cmp al,'X'
|
|
je .let2
|
|
cmp al,'A'
|
|
jb .num2
|
|
sub al,'A'
|
|
add al,10
|
|
jmp .let2
|
|
.num2
|
|
sub al,'0'
|
|
.let2
|
|
mov [esi],al
|
|
inc esi
|
|
dec ecx
|
|
jnz .loopb2
|
|
|
|
; get address
|
|
xor ebx,ebx
|
|
xor ecx,ecx
|
|
mov cl,[GUICheatTextZ1]
|
|
shl ecx,4
|
|
add cl,[GUICheatTextZ1+1]
|
|
shl ecx,4
|
|
add cl,[GUICheatTextZ1+2]
|
|
shl ecx,4
|
|
add cl,[GUICheatTextZ1+3]
|
|
shl ecx,4
|
|
add cl,[GUICheatTextZ1+4]
|
|
|
|
mov edx,[NumCheats]
|
|
shl edx,5
|
|
sub edx,[NumCheats]
|
|
sub edx,[NumCheats]
|
|
sub edx,[NumCheats]
|
|
sub edx,[NumCheats]
|
|
|
|
; Write data to memory
|
|
cmp byte[GUICheatTextZ1+13],1
|
|
je near .modifysram
|
|
|
|
; get data
|
|
cmp byte[GUICheatTextZ1+5],'X'
|
|
je near .nocode
|
|
cmp byte[GUICheatTextZ1+6],'X'
|
|
je near .nocode
|
|
mov bl,[GUICheatTextZ1+5]
|
|
shl bl,4
|
|
add bl,[GUICheatTextZ1+6]
|
|
mov esi,[romdata]
|
|
mov al,[esi+ecx]
|
|
mov [esi+ecx],bl
|
|
mov byte[cheatdata+edx],1
|
|
mov [cheatdata+edx+2],ecx
|
|
mov [cheatdata+edx+1],bl
|
|
mov [cheatdata+edx+5],al
|
|
push eax
|
|
mov al,[guicheatvalrep]
|
|
or [cheatdata+edx],al
|
|
pop eax
|
|
inc byte[NumCheats]
|
|
add edx,28
|
|
.nocode
|
|
inc ecx
|
|
cmp byte[GUICheatTextZ1+7],'X'
|
|
je near .nocode1
|
|
cmp byte[GUICheatTextZ1+8],'X'
|
|
je near .nocode1
|
|
cmp byte[NumCheats],255
|
|
je near .nocode1
|
|
mov bl,[GUICheatTextZ1+7]
|
|
shl bl,4
|
|
add bl,[GUICheatTextZ1+8]
|
|
mov esi,[romdata]
|
|
mov al,[esi+ecx]
|
|
mov [esi+ecx],bl
|
|
mov byte[cheatdata+edx],1
|
|
mov [cheatdata+edx+2],ecx
|
|
mov [cheatdata+edx+1],bl
|
|
mov [cheatdata+edx+5],al
|
|
inc byte[NumCheats]
|
|
add edx,28
|
|
.nocode1
|
|
inc ecx
|
|
cmp byte[GUICheatTextZ1+9],'X'
|
|
je near .nocode2
|
|
cmp byte[GUICheatTextZ1+10],'X'
|
|
je near .nocode2
|
|
cmp byte[NumCheats],255
|
|
je near .nocode2
|
|
mov bl,[GUICheatTextZ1+9]
|
|
shl bl,4
|
|
add bl,[GUICheatTextZ1+10]
|
|
mov esi,[romdata]
|
|
mov al,[esi+ecx]
|
|
mov [esi+ecx],bl
|
|
mov byte[cheatdata+edx],1
|
|
mov [cheatdata+edx+2],ecx
|
|
mov [cheatdata+edx+1],bl
|
|
mov [cheatdata+edx+5],al
|
|
inc byte[NumCheats]
|
|
.nocode2
|
|
jmp .quit
|
|
|
|
.modifysram
|
|
cmp ecx,65535
|
|
ja near .quit
|
|
mov esi,[sram]
|
|
; get data
|
|
cmp byte[GUICheatTextZ1+5],'X'
|
|
je .nocodeb
|
|
cmp byte[GUICheatTextZ1+6],'X'
|
|
je .nocodeb
|
|
mov bl,[GUICheatTextZ1+5]
|
|
shl bl,4
|
|
add bl,[GUICheatTextZ1+6]
|
|
mov al,[esi+ecx]
|
|
mov [esi+ecx],bl
|
|
mov byte[cheatdata+edx],2
|
|
mov [cheatdata+edx+2],ecx
|
|
mov [cheatdata+edx+1],bl
|
|
mov [cheatdata+edx+5],al
|
|
inc byte[NumCheats]
|
|
add edx,28
|
|
.nocodeb
|
|
inc ecx
|
|
cmp byte[GUICheatTextZ1+7],'X'
|
|
je .nocode1b
|
|
cmp byte[GUICheatTextZ1+8],'X'
|
|
je .nocode1b
|
|
cmp byte[NumCheats],255
|
|
je .nocode1b
|
|
cmp ecx,65535
|
|
ja .nocode1b
|
|
mov bl,[GUICheatTextZ1+7]
|
|
shl bl,4
|
|
add bl,[GUICheatTextZ1+8]
|
|
mov al,[esi+ecx+1]
|
|
mov [esi+ecx+1],bl
|
|
mov byte[cheatdata+edx],2
|
|
mov [cheatdata+edx+2],ecx
|
|
mov [cheatdata+edx+1],bl
|
|
mov [cheatdata+edx+5],al
|
|
inc byte[NumCheats]
|
|
add edx,28
|
|
.nocode1b
|
|
inc ecx
|
|
cmp byte[GUICheatTextZ1+9],'X'
|
|
je .nocode2c
|
|
cmp byte[GUICheatTextZ1+10],'X'
|
|
je .nocode2c
|
|
cmp byte[NumCheats],255
|
|
je .nocode2c
|
|
cmp ecx,65535
|
|
ja .nocode2c
|
|
mov bl,[GUICheatTextZ1+9]
|
|
shl bl,4
|
|
add bl,[GUICheatTextZ1+10]
|
|
mov al,[esi+ecx+2]
|
|
mov [esi+ecx+2],bl
|
|
mov byte[cheatdata+edx],2
|
|
mov [cheatdata+edx+2],ecx
|
|
mov [cheatdata+edx+1],bl
|
|
mov [cheatdata+edx+5],al
|
|
inc byte[NumCheats]
|
|
.nocode2c
|
|
|
|
.quit
|
|
cmp byte[NumCheats],0
|
|
je .nocheat
|
|
mov byte[CheatOn],1
|
|
mov dword[GUIcurrentcheatwin],1
|
|
mov eax,[NumCheats]
|
|
dec eax
|
|
mov [GUIcurrentcheatcursloc],eax
|
|
sub eax,11
|
|
mov [GUIcurrentcheatviewloc],eax
|
|
test dword[GUIcurrentcheatviewloc],80000000h
|
|
jz .noview
|
|
mov dword[GUIcurrentcheatviewloc],0
|
|
.noview
|
|
.nocheat
|
|
mov dword[GUICheatTextZ1],0
|
|
mov dword[GUICheatTextZ2],0
|
|
mov byte[GUICheatPosA],0
|
|
mov byte[GUICheatPosB],0
|
|
ret
|
|
|
|
decodegg:
|
|
;Genie Hex: D F 4 7 0 9 1 5 6 B C 8 A 2 3 E
|
|
;Normal Hex: 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
|
; 4 6 D E 2 7 8 3 B 5 C 9 A 0 F 1
|
|
; Convert code
|
|
mov esi,GUICheatTextZ1
|
|
mov eax,[esi+5]
|
|
mov [esi+4],eax
|
|
; convert code to number format
|
|
mov ecx,8
|
|
xor eax,eax
|
|
.loopb3
|
|
mov al,[esi]
|
|
cmp al,'A'
|
|
jb .num3
|
|
sub al,'A'
|
|
add al,10
|
|
jmp .let3
|
|
.num3
|
|
sub al,'0'
|
|
.let3
|
|
mov al,[.GG2Norm+eax]
|
|
mov [esi],al
|
|
inc esi
|
|
dec ecx
|
|
jnz .loopb3
|
|
|
|
mov esi,GUICheatTextZ1
|
|
xor ecx,ecx
|
|
mov cl,[esi+2]
|
|
shl ecx,4
|
|
add cl,[esi+3]
|
|
shl ecx,4
|
|
add cl,[esi+4]
|
|
shl ecx,4
|
|
add cl,[esi+5]
|
|
shl ecx,4
|
|
add cl,[esi+6]
|
|
shl ecx,4
|
|
add cl,[esi+7]
|
|
; 0123456789ABCDEF01234567
|
|
; 24bit encoded address: ijklqrstopabcduvwxefghmn
|
|
; abcdefghijklmnopqrstuvwx
|
|
; >8 >12 >6<10 >6 <14 <10
|
|
mov ebx,ecx
|
|
and ebx,000000000011110000000000b ;abcd
|
|
shl ebx,10
|
|
mov eax,ecx
|
|
and eax,000000000000000000111100b ;efgh
|
|
shl eax,14
|
|
add ebx,eax
|
|
mov eax,ecx
|
|
and eax,111100000000000000000000b ;ijkl
|
|
shr eax,8
|
|
add ebx,eax
|
|
mov eax,ecx
|
|
and eax,000000000000000000000011b ;mn
|
|
shl eax,10
|
|
add ebx,eax
|
|
mov eax,ecx
|
|
and eax,000000001100000000000000b ;op
|
|
shr eax,6
|
|
add ebx,eax
|
|
mov eax,ecx
|
|
and eax,000011110000000000000000b ;qrst
|
|
shr eax,12
|
|
add ebx,eax
|
|
mov eax,ecx
|
|
and eax,000000000000001111000000b ;uvwx
|
|
shr eax,6
|
|
add ebx,eax
|
|
xor ecx,ecx
|
|
mov cx,bx
|
|
shr ebx,16
|
|
test bl,40h
|
|
jz .noover
|
|
; xor cx,8000h
|
|
.noover
|
|
mov al,[esi]
|
|
shl al,4
|
|
add al,[esi+1]
|
|
|
|
; store into cheatdata
|
|
mov edx,[NumCheats]
|
|
shl edx,5
|
|
sub edx,[NumCheats]
|
|
sub edx,[NumCheats]
|
|
sub edx,[NumCheats]
|
|
sub edx,[NumCheats]
|
|
mov byte[cheatdata+edx],0
|
|
mov [cheatdata+edx+1],al
|
|
mov [cheatdata+edx+2],cx
|
|
mov [cheatdata+edx+4],bl
|
|
push eax
|
|
mov al,[guicheatvalrep]
|
|
or [cheatdata+edx],al
|
|
pop eax
|
|
push ecx
|
|
push eax
|
|
push ebx
|
|
push edx
|
|
call dword near [memtabler8+ebx*4]
|
|
pop edx
|
|
mov [cheatdata+edx+5],al
|
|
pop ebx
|
|
pop eax
|
|
pop ecx
|
|
|
|
mov byte[writeon],1
|
|
|
|
test byte[cheatdata+edx],80h
|
|
jnz .nowrite
|
|
test byte[cheatdata+edx-28],80h
|
|
jnz .nowrite
|
|
call dword near [memtablew8+ebx*4]
|
|
.nowrite
|
|
|
|
mov byte[writeon],0
|
|
mov byte[CheatOn],1
|
|
inc byte[NumCheats]
|
|
mov dword[GUICheatTextZ1],0
|
|
mov dword[GUICheatTextZ2],0
|
|
mov byte[GUICheatPosA],0
|
|
mov byte[GUICheatPosB],0
|
|
mov dword[GUIcurrentcheatwin],1
|
|
mov eax,[NumCheats]
|
|
dec eax
|
|
mov [GUIcurrentcheatcursloc],eax
|
|
sub eax,11
|
|
mov [GUIcurrentcheatviewloc],eax
|
|
test dword[GUIcurrentcheatviewloc],80000000h
|
|
jz .noview
|
|
mov dword[GUIcurrentcheatviewloc],0
|
|
.noview
|
|
ret
|
|
SECTION .data
|
|
.GG2Norm db 04h,06h,0Dh,0Eh,02h,07h,08h,03h,0Bh,05h,0Ch,09h,0Ah,00h,0Fh,01h
|
|
SECTION .text
|
|
|
|
decodepar:
|
|
; convert code to number format
|
|
mov ecx,8
|
|
mov esi,GUICheatTextZ1
|
|
.loopb
|
|
mov al,[esi]
|
|
cmp al,'A'
|
|
jb .num
|
|
sub al,'A'
|
|
add al,10
|
|
jmp .let
|
|
.num
|
|
sub al,'0'
|
|
.let
|
|
mov [esi],al
|
|
inc esi
|
|
dec ecx
|
|
jnz .loopb
|
|
; get address
|
|
xor ebx,ebx
|
|
xor ecx,ecx
|
|
mov bl,[GUICheatTextZ1]
|
|
shl bl,4
|
|
add bl,[GUICheatTextZ1+1]
|
|
mov cl,[GUICheatTextZ1+2]
|
|
shl cx,4
|
|
add cl,[GUICheatTextZ1+3]
|
|
shl cx,4
|
|
add cl,[GUICheatTextZ1+4]
|
|
shl cx,4
|
|
add cl,[GUICheatTextZ1+5]
|
|
mov al,[GUICheatTextZ1+6]
|
|
shl al,4
|
|
add al,[GUICheatTextZ1+7]
|
|
|
|
; store into cheatdata
|
|
xor edx,edx
|
|
mov dl,[NumCheats]
|
|
push ebx
|
|
mov ebx,edx
|
|
shl edx,5
|
|
sub edx,ebx
|
|
sub edx,ebx
|
|
sub edx,ebx
|
|
sub edx,ebx
|
|
pop ebx
|
|
mov byte[cheatdata+edx],0
|
|
mov [cheatdata+edx+1],al
|
|
mov [cheatdata+edx+2],cx
|
|
mov [cheatdata+edx+4],bl
|
|
push eax
|
|
mov al,[guicheatvalrep]
|
|
or [cheatdata+edx],al
|
|
pop eax
|
|
push ecx
|
|
push eax
|
|
push ebx
|
|
push edx
|
|
call dword near [memtabler8+ebx*4]
|
|
pop edx
|
|
mov [cheatdata+edx+5],al
|
|
pop ebx
|
|
pop eax
|
|
pop ecx
|
|
|
|
mov byte[writeon],1
|
|
test byte[cheatdata+edx],80h
|
|
jnz .nowrite
|
|
test byte[cheatdata+edx-28],80h
|
|
jnz .nowrite
|
|
call dword near [memtablew8+ebx*4]
|
|
.nowrite
|
|
mov byte[writeon],0
|
|
mov byte[CheatOn],1
|
|
inc dword[NumCheats]
|
|
mov dword[GUICheatTextZ1],0
|
|
mov dword[GUICheatTextZ2],0
|
|
mov byte[GUICheatPosA],0
|
|
mov byte[GUICheatPosB],0
|
|
mov dword[GUIcurrentcheatwin],1
|
|
mov eax,[NumCheats]
|
|
dec eax
|
|
mov [GUIcurrentcheatcursloc],eax
|
|
sub eax,11
|
|
mov [GUIcurrentcheatviewloc],eax
|
|
test dword[GUIcurrentcheatviewloc],80000000h
|
|
jz .noview
|
|
mov dword[GUIcurrentcheatviewloc],0
|
|
.noview
|
|
ret
|
|
|
|
SECTION .bss
|
|
guicheatvalrep resb 1
|