1340 lines
27 KiB
PHP
1340 lines
27 KiB
PHP
;Copyright (C) 1997-2001 ZSNES Team ( zsknight@zsnes.com / _demo_@zsnes.com )
|
||
;
|
||
;This program is free software; you can redistribute it and/or
|
||
;modify it under the terms of the GNU General Public License
|
||
;as published by the Free Software Foundation; either
|
||
;version 2 of the License, or (at your option) any later
|
||
;version.
|
||
;
|
||
;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.
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
; 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,GUICSrcTextQ
|
||
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
|
||
%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,byte[CheatSrcByteSize]
|
||
sub ecx,ebx
|
||
mov edx,[SrcMask+ebx*4]
|
||
mov edi,dword[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
|
||
loop .exactloop
|
||
; CSCurValue dd 0
|
||
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,dword[vidbuffer]
|
||
add eax,129600+65536*2
|
||
mov esi,dword[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
|
||
|
||
CopyRamToggle db 0
|
||
FirstSearch db 0
|
||
|
||
CheatCodeSearchInit:
|
||
mov byte[CSInputDisplay],'_'
|
||
mov byte[CSInputDisplay+1],0
|
||
mov byte[CheatWinMode],1
|
||
mov byte[CheatSearchStatus],0
|
||
cmp byte[CopyRamToggle],0
|
||
mov byte[FirstSearch],1
|
||
mov eax,dword[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
|
||
loop .loop
|
||
; fill searched buffer with 0xFF
|
||
mov eax,dword[vidbuffer]
|
||
add eax,129600+65536*2
|
||
mov ecx,8192
|
||
.loop2
|
||
mov dword[eax],0FFFFFFFFh
|
||
add eax,4
|
||
loop .loop2
|
||
cmp byte[CheatSrcSearchType],1
|
||
jne .nottype1
|
||
mov byte[CheatSearchStatus],1
|
||
.nottype1
|
||
mov dword[CheatCompareValue],0
|
||
mov eax,dword[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
|
||
|
||
CheatCodeSave:
|
||
cmp byte[NumCheats],0
|
||
jne .okay
|
||
mov byte[GUICBHold],0
|
||
ret
|
||
.okay
|
||
mov byte[cheatdata+6],254
|
||
mov byte[cheatdata+7],252
|
||
|
||
call SRAMDirc
|
||
mov byte[GUICBHold],0
|
||
mov ebx,[statefileloc]
|
||
sub ebx,2
|
||
mov eax,[fnamest+ebx]
|
||
mov dword[fnamest+ebx],'CHT'
|
||
push eax
|
||
push ebx
|
||
mov edx,fnamest+1
|
||
call Create_File
|
||
jc .cheatsavefail
|
||
mov bx,ax
|
||
mov ecx,[NumCheats]
|
||
mov edx,ecx
|
||
shl ecx,4
|
||
shl edx,2
|
||
add ecx,edx
|
||
add ecx,edx
|
||
add ecx,edx
|
||
mov edx,cheatdata
|
||
call Write_File
|
||
call Close_File
|
||
.cheatsavefail
|
||
pop ebx
|
||
pop eax
|
||
mov [fnamest+ebx],eax
|
||
call LOADDir
|
||
ret
|
||
|
||
CheatCodeLoad:
|
||
call SRAMDirc
|
||
mov byte[GUICBHold],0
|
||
mov ebx,[statefileloc]
|
||
sub ebx,2
|
||
mov eax,[fnamest+ebx]
|
||
mov dword[fnamest+ebx],'CHT'
|
||
push eax
|
||
push ebx
|
||
mov edx,fnamest+1
|
||
call Open_File
|
||
jc near .fail
|
||
mov bx,ax
|
||
; Disable all codes
|
||
push ebx
|
||
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
|
||
pop ebx
|
||
mov ecx,255*28
|
||
mov edx,cheatdata
|
||
call Read_File
|
||
push eax
|
||
call Close_File
|
||
pop eax
|
||
cmp byte[cheatdata+6],254
|
||
jne .notnewformat
|
||
cmp byte[cheatdata+7],252
|
||
jne .notnewformat
|
||
jmp .newformat
|
||
.notnewformat
|
||
; Convert format
|
||
mov esi,cheatdata
|
||
mov ebx,18
|
||
push eax
|
||
xor edx,edx
|
||
div ebx
|
||
push edx
|
||
mov [NumCheats],eax
|
||
mov ebx,28
|
||
mul ebx
|
||
mov ecx,eax
|
||
pop edx
|
||
pop eax
|
||
sub eax,edx
|
||
.convloop
|
||
sub ecx,28
|
||
sub eax,18
|
||
mov ebx,6
|
||
.convloopb
|
||
mov dl,[cheatdata+eax+ebx-1]
|
||
mov [cheatdata+ecx+ebx-1],dl
|
||
dec ebx
|
||
jnz .convloopb
|
||
mov ebx,12
|
||
.convloopd
|
||
mov dl,[cheatdata+eax+ebx+5]
|
||
mov [cheatdata+ecx+ebx+7],dl
|
||
dec ebx
|
||
jnz .convloopd
|
||
mov ebx,8
|
||
.convloopc
|
||
mov byte[cheatdata+ecx+ebx+19],0
|
||
dec ebx
|
||
jnz .convloopc
|
||
or ecx,ecx
|
||
jnz .convloop
|
||
jmp .fin
|
||
.newformat
|
||
mov ebx,28
|
||
xor edx,edx
|
||
div ebx
|
||
mov [NumCheats],eax
|
||
.fin
|
||
pop ebx
|
||
pop eax
|
||
mov [fnamest+ebx],eax
|
||
; 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
|
||
mov eax,[NumCheats]
|
||
cmp eax,[GUIcurrentcheatcursloc]
|
||
ja .noconf
|
||
dec eax
|
||
mov dword[GUIcurrentcheatcursloc],eax
|
||
.noconf
|
||
cmp dword[NumCheats],0
|
||
jne .nozero
|
||
mov dword[GUIcurrentcheatcursloc],0
|
||
mov byte[CheatOn],0
|
||
call LOADDir
|
||
ret
|
||
.nozero
|
||
mov byte[CheatOn],1
|
||
call LOADDir
|
||
ret
|
||
.fail
|
||
pop ebx
|
||
pop eax
|
||
mov [fnamest+ebx],eax
|
||
call LOADDir
|
||
ret
|
||
|
||
CheatCodeRemove:
|
||
cmp dword[NumCheats],0
|
||
jne .nonone
|
||
mov byte[GUICBHold],0
|
||
ret
|
||
.nonone
|
||
mov byte[GUICBHold],0
|
||
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 dword[GUIcurrentcheatcursloc]
|
||
.okay
|
||
cmp byte[NumCheats],0
|
||
jne .cheatexists
|
||
mov byte[CheatOn],0
|
||
.cheatexists
|
||
ret
|
||
|
||
CheatCodeFix:
|
||
cmp dword[NumCheats],0
|
||
jne .nonone
|
||
mov byte[GUICBHold],0
|
||
ret
|
||
.nonone
|
||
mov byte[GUICBHold],0
|
||
call DisableCheatCode
|
||
mov esi,[GUIcurrentcheatcursloc]
|
||
shl esi,5
|
||
sub esi,[GUIcurrentcheatcursloc]
|
||
sub esi,[GUIcurrentcheatcursloc]
|
||
sub esi,[GUIcurrentcheatcursloc]
|
||
sub esi,[GUIcurrentcheatcursloc]
|
||
add esi,cheatdata
|
||
xor byte[esi+3],80h
|
||
call EnableCheatCodeNoPrevMod
|
||
ret
|
||
|
||
CheatCodeToggle:
|
||
cmp dword[NumCheats],0
|
||
jne .nonone
|
||
mov byte[GUICBHold],0
|
||
ret
|
||
.nonone
|
||
mov byte[GUICBHold],0
|
||
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 byte[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
|
||
loop .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[GUICheatTextA+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,GUICheatTextA
|
||
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
|
||
loop .dloop
|
||
; determine whether it is gamegenie, par, or GF
|
||
; uppercase all codes if necessary
|
||
mov eax,GUICheatText9
|
||
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
|
||
loop .loop
|
||
mov byte[guicheatvalrep],0
|
||
xor eax,eax
|
||
mov al,[GUICheatPosA]
|
||
dec al
|
||
cmp byte[GUICheatText9+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,GUICheatText9
|
||
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
|
||
loop .looppar
|
||
jmp decodepar
|
||
.invalidgg
|
||
jmp guicheaterror
|
||
.gg
|
||
; check if code is valid
|
||
mov eax,GUICheatText9
|
||
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
|
||
loop .loopgg
|
||
jmp decodegg
|
||
ret
|
||
.invalidgf
|
||
jmp guicheaterror
|
||
.gf
|
||
; check if code is valid
|
||
mov eax,GUICheatText9
|
||
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
|
||
loop .loopgf
|
||
mov eax,GUICheatText9+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
|
||
loop .loopgf2
|
||
mov bl,[GUICheatText9+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,GUICheatText9
|
||
.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,[GUICheatText9]
|
||
shl ecx,4
|
||
add cl,[GUICheatText9+1]
|
||
shl ecx,4
|
||
add cl,[GUICheatText9+2]
|
||
shl ecx,4
|
||
add cl,[GUICheatText9+3]
|
||
shl ecx,4
|
||
add cl,[GUICheatText9+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[GUICheatText9+13],1
|
||
je near .modifysram
|
||
|
||
; get data
|
||
cmp byte[GUICheatText9+5],'X'
|
||
je near .nocode
|
||
cmp byte[GUICheatText9+6],'X'
|
||
je near .nocode
|
||
mov bl,[GUICheatText9+5]
|
||
shl bl,4
|
||
add bl,[GUICheatText9+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[GUICheatText9+7],'X'
|
||
je near .nocode1
|
||
cmp byte[GUICheatText9+8],'X'
|
||
je near .nocode1
|
||
cmp byte[NumCheats],255
|
||
je near .nocode1
|
||
mov bl,[GUICheatText9+7]
|
||
shl bl,4
|
||
add bl,[GUICheatText9+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[GUICheatText9+9],'X'
|
||
je near .nocode2
|
||
cmp byte[GUICheatText9+10],'X'
|
||
je near .nocode2
|
||
cmp byte[NumCheats],255
|
||
je near .nocode2
|
||
mov bl,[GUICheatText9+9]
|
||
shl bl,4
|
||
add bl,[GUICheatText9+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[GUICheatText9+5],'X'
|
||
je .nocodeb
|
||
cmp byte[GUICheatText9+6],'X'
|
||
je .nocodeb
|
||
mov bl,[GUICheatText9+5]
|
||
shl bl,4
|
||
add bl,[GUICheatText9+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[GUICheatText9+7],'X'
|
||
je .nocode1b
|
||
cmp byte[GUICheatText9+8],'X'
|
||
je .nocode1b
|
||
cmp byte[NumCheats],255
|
||
je .nocode1b
|
||
cmp ecx,65535
|
||
ja .nocode1b
|
||
mov bl,[GUICheatText9+7]
|
||
shl bl,4
|
||
add bl,[GUICheatText9+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[GUICheatText9+9],'X'
|
||
je .nocode2c
|
||
cmp byte[GUICheatText9+10],'X'
|
||
je .nocode2c
|
||
cmp byte[NumCheats],255
|
||
je .nocode2c
|
||
cmp ecx,65535
|
||
ja .nocode2c
|
||
mov bl,[GUICheatText9+9]
|
||
shl bl,4
|
||
add bl,[GUICheatText9+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[GUICheatText9],0
|
||
mov dword[GUICheatTextA],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,GUICheatText9
|
||
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,GUICheatText9
|
||
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 byte[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[GUICheatText9],0
|
||
mov dword[GUICheatTextA],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
|
||
.GG2Norm db 04h,06h,0Dh,0Eh,02h,07h,08h,03h,0Bh,05h,0Ch,09h,0Ah,00h,0Fh,01h
|
||
|
||
decodepar:
|
||
; convert code to number format
|
||
mov ecx,8
|
||
mov esi,GUICheatText9
|
||
.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,[GUICheatText9]
|
||
shl bl,4
|
||
add bl,[GUICheatText9+1]
|
||
mov cl,[GUICheatText9+2]
|
||
shl cx,4
|
||
add cl,[GUICheatText9+3]
|
||
shl cx,4
|
||
add cl,[GUICheatText9+4]
|
||
shl cx,4
|
||
add cl,[GUICheatText9+5]
|
||
mov al,[GUICheatText9+6]
|
||
shl al,4
|
||
add al,[GUICheatText9+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 byte[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[GUICheatText9],0
|
||
mov dword[GUICheatTextA],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
|
||
|
||
guicheaterror:
|
||
xor ebx,ebx
|
||
mov ecx,256+128+64
|
||
.a
|
||
mov byte[pressed+ebx],0
|
||
inc ebx
|
||
loop .a
|
||
.again
|
||
call GUIUnBuffer
|
||
call DisplayBoxes
|
||
call DisplayMenu
|
||
GUIBox 75,95,192,143,160
|
||
GUIBox 75,95,192,95,162
|
||
GUIBox 75,95,75,143,161
|
||
GUIBox 192,95,192,143,159
|
||
GUIBox 75,143,192,143,158
|
||
GUIOuttext 81,101,guicheaterror1,220-15
|
||
GUIOuttext 80,100,guicheaterror1,220
|
||
GUIOuttext 81,109,guicheaterror2,220-15
|
||
GUIOuttext 80,108,guicheaterror2,220
|
||
GUIOuttext 81,117,guicheaterror3,220-15
|
||
GUIOuttext 80,116,guicheaterror3,220
|
||
GUIOuttext 81,125,guicheaterror4,220-15
|
||
GUIOuttext 80,124,guicheaterror4,220
|
||
GUIOuttext 81,135,guicheaterror5,220-15
|
||
GUIOuttext 80,134,guicheaterror5,220
|
||
call vidpastecopyscr
|
||
call JoyRead
|
||
xor ebx,ebx
|
||
mov ecx,256+128+64
|
||
.b
|
||
cmp byte[pressed+ebx],0
|
||
jne .pressedokay
|
||
inc ebx
|
||
loop .b
|
||
cmp byte[MouseDis],1
|
||
je .mousedis
|
||
call Get_MouseData
|
||
test bx,01h
|
||
jnz .pressedokay
|
||
.mousedis
|
||
jmp .again
|
||
.pressedokay
|
||
.again2
|
||
call Check_Key
|
||
or al,al
|
||
jz .nokey
|
||
call Get_Key
|
||
jmp .again2
|
||
.nokey
|
||
cmp byte[MouseDis],1
|
||
je .mousedis2
|
||
push ebx
|
||
; mov eax,0Bh
|
||
; int 33h
|
||
pop ebx
|
||
.mousedis2
|
||
mov dword[GUIcurrentcheatwin],1
|
||
mov byte[GUIpclicked],1
|
||
ret
|
||
guicheaterror1 db 'INVALID CODE! YOU',0
|
||
guicheaterror2 db 'MUST ENTER A VALID',0
|
||
guicheaterror3 db 'GAME GENIE,PAR, OR',0
|
||
guicheaterror4 db 'GOLD FINGER CODE.',0
|
||
guicheaterror5 db 'PRESS ANY KEY.',0
|
||
guicheatvalrep db 0
|
||
|
||
|