Files
ZSNES/zsnes/src/cpu/execute.asm
2005-07-06 20:44:34 +00:00

2230 lines
45 KiB
NASM

;Copyright (C) 1997-2005 ZSNES Team ( zsKnight, _Demo_, pagefault, Nach )
;
;http://www.zsnes.com
;http://sourceforge.net/projects/zsnes
;
;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.
%include "macros.mac"
EXTSYM KeyRewind,statesaver,timer2upd,Voice0Status,UpdateDPage
EXTSYM StartGUI,debuggeron,romdata,initvideo
EXTSYM vidbufferofsa,disable65816sh,GUISaveVars,virqnodisable
EXTSYM KeySaveState,KeyLoadState,KeyQuickExit,KeyQuickLoad,KeyQuickRst
EXTSYM GUIDoReset,GUIReset,KeyOnStA,KeyOnStB,ProcessKeyOn,C4Enable,KeyQuickClock
EXTSYM KeyQuickSaveSPC,TimerEnable,IRQHack,splitflags,joinflags
EXTSYM KeyQuickSnapShot,csounddisable,videotroub,ResetTripleBuf
EXTSYM Output_Text,Check_Key,Get_Key,Change_Dir
EXTSYM InitPreGame,Curtableaddr,curcyc,debugdisble,dmadata,guioff,memtabler8
EXTSYM SetupPreGame,memtablew8,regaccessbankr8,showmenu,snesmap2,snesmmap
EXTSYM DeInitPostGame,spcPCRam,startdebugger,xp,xpb,xpc,tablead,tableadb
EXTSYM tableadc,SA1UpdateDPage,Makemode7Table,nextmenupopup,MovieProcessing
EXTSYM OSExit,DosExit,InitDir,InitDrive,createnewcfg,sfxramdata,deinitvideo
EXTSYM SFXEnable,wramdata,cycpbl,cycpblt,irqon,spcnumread,spchalted,spcon
EXTSYM multchange,romispal,scrndis,sprlefttot,sprleftpr,processsprites
EXTSYM cachesprites,NextLineStart,FlipWait,LastLineStart,opcjmptab,CheatOn
EXTSYM INTEnab,JoyCRead,NMIEnab,NumCheats,CurrentExecSA1,ReadInputDevice
EXTSYM StartDrawNewGfx,VIRQLoc,cachevideo,cfield,cheatdata,curblank,curnmi
EXTSYM curypos,cycpl,doirqnext,drawline,exechdma,hdmadelay,intrset,newengen
EXTSYM oamaddr,oamaddrs,resolutn,showvideo,snesmouse,starthdma,switchtonmi
EXTSYM switchtovirq,totlines,updatetimer,SA1Swap,SA1DoIRQ,JoyAOrig,JoyANow
EXTSYM JoyBOrig,JoyBNow,JoyCOrig,JoyCNow,JoyDOrig,JoyDNow,JoyEOrig,JoyENow
EXTSYM SA1Message,MultiTapStat,idledetectspc,SA1Control,SA1Enable,SA1IRQEnable
EXTSYM SPC700read,SPC700write,numspcvblleft,spc700idle,SA1IRQExec,ForceNewGfxOff
EXTSYM LethEnData,GUIQuit,IRAM,SA1Ptr,SA1BWPtr,scrnon,scaddset,outofmemfix
EXTSYM yesoutofmemory,ProcessMovies,MovieStop,ppustatus,C4VBlank
EXTSYM ReturnFromSPCStall,scanlines,smallscreenon,ScreenScale,MainLoop
EXTSYM NumberOfOpcodes,SfxCLSR,SfxSCMR,SfxPOR,sfx128lineloc,sfx160lineloc
EXTSYM sfx192lineloc,sfxobjlineloc,sfxclineloc,PLOTJmpa,PLOTJmpb,FxTable
EXTSYM FxTableb,FxTablec,FxTabled,SfxPBR,SCBRrel,SfxSCBR,SfxCOLR,SFXCounter
EXTSYM fxbit01,fxbit01pcal,fxbit23,fxbit23pcal,fxbit45,fxbit45pcal,fxbit67
EXTSYM fxbit67pcal,SfxSFR,nosprincr,cpucycle,switchtovirqdeb,switchtonmideb
EXTSYM MovieSeekBehind,SaveSramData,BackupCVFrame,RestoreCVFrame,loadstate
EXTSYM KeyInsrtChap,KeyNextChap,KeyPrevChap,MovieInsertChapter,MovieSeekAhead
EXTSYM ResetDuringMovie,EMUPauseKey,INCRFrameKey,MovieWaiting,NoInputRead
EXTSYM AllocatedRewindStates,PauseFrameMode,RestorePauseFrame,BackupPauseFrame
%ifdef __MSDOS__
EXTSYM dssel,Game60hzcall
%endif
SECTION .data
NEWSYM tempedx, dd 0
NEWSYM tempesi, dd 0
NEWSYM tempedi, dd 0
NEWSYM tempebp, dd 0
NEWSYM RewindTimer, dd 0
NEWSYM BackState, db 1
NEWSYM BackStateSize, dd 6
SECTION .text
NEWSYM ResetExecStuff
mov dword[soundcycleft],0
mov dword[curexecstate],0
mov dword[nmiprevaddrl],0
mov dword[nmiprevaddrh],0
mov dword[nmirept],0
mov dword[nmiprevline],224
mov dword[nmistatus],0
mov byte[NextLineCache],0
mov dword[spcnumread],0
mov dword[spchalted],-1
mov dword[timer2upd],0
mov dword[HIRQCycNext],0
mov byte[HIRQNextExe],0
ret
NEWSYM ProcessRewind
mov eax,dword[KeyRewind]
cmp byte[pressed+eax],1
jne near .notokay
mov byte[pressed+eax],2
pushad
call RestoreCVFrame
popad
cmp byte[PauseFrameMode],1
jne .notpauserewind
pushad
call BackupPauseFrame
popad
.notpauserewind
mov esi,[tempesi]
mov edi,[tempedi]
mov ebp,[tempebp]
mov edx,[tempedx]
.notokay
ret
NEWSYM UpdateRewind
cmp byte[AllocatedRewindStates],0
je .norewinds
cmp dword[KeyRewind],0
je .norewinds
dec dword[RewindTimer]
jnz .checkrewind
mov [tempedx],edx
mov [tempesi],esi
mov [tempedi],edi
mov [tempebp],ebp
pushad
call BackupCVFrame
popad
.checkrewind
call ProcessRewind
.norewinds
ret
SECTION .data
NEWSYM MuteVoiceF, dd 0
SECTION .text
VoiceEndMute:
mov byte[MuteVoiceF],0
ret
%macro StartMute 1
mov al,[Voice0Status+%1]
or al,al
jz %%notmuted
or byte[MuteVoiceF],1 << %1
%%notmuted
%endmacro
VoiceStartMute:
mov byte[MuteVoiceF],0
push eax
StartMute 0
StartMute 1
StartMute 2
StartMute 3
StartMute 4
StartMute 5
StartMute 6
StartMute 7
pop eax
ret
%macro stim 0
%ifdef __MSDOS__
sti
%endif
%endmacro
%macro ProcessIRQStuff 0
; check for VIRQ/HIRQ
cmp byte[virqnodisable],1
je %%virqdo
test dl,04h
jnz %%virqdo
cmp byte[doirqnext],1
je near .virq
%%virqdo
test byte[INTEnab],20h
jz near %%novirq
mov ax,[VIRQLoc]
add ax,[IRQHack]
cmp ax,[resolutn]
jne %%notres
dec ax
; inc ax
%%notres
cmp ax,0FFFFh
jne %%notzero
xor ax,ax
%%notzero
cmp word[curypos],ax
jne near %%noirq
test byte[INTEnab],10h
jnz %%tryhirq
%%startirq
cmp byte[intrset],1
jne %%nointrseta
mov byte[intrset],2
%%nointrseta
mov byte[irqon],80h
test dl,04h
jnz %%irqd
jmp .virq
%%novirq
test byte[INTEnab],10h
jz %%noirq
%%setagain
cmp byte[intrset],2
jbe %%nointrseta3
dec byte[intrset]
cmp byte[intrset],2
ja %%noirq
%%nointrseta3
cmp byte[intrset],1
jne %%nointrseta2
test byte[INTEnab],80h
jz %%tryhirq
mov byte[intrset],8
jmp %%noirq
%%nointrseta2
test dl,04h
jnz %%noirq
%%tryhirq
jmp %%startirq
%%irqd
mov byte[doirqnext],1
%%noirq
%endmacro
; .returnfromsfx
; pexecs
; *** Copy to PC whenever a non-relative jump is executed
SECTION .data
NEWSYM romloadskip, db 0
NEWSYM SSKeyPressed, dd 0
NEWSYM SPCKeyPressed, dd 0
NEWSYM NoSoundReinit, dd 0
NEWSYM NextNGDisplay, db 0
NEWSYM TempVidInfo, dd 0
NEWSYM tempdh, db 0
SECTION .text
; this wonderful mess starts up the CPU and initialized the emulation state
NEWSYM start65816
call initvideo
cmp byte[videotroub],1
jne .notrouble
ret
.notrouble
mov edi,[vidbufferofsa]
mov ecx,37518
xor eax,eax
rep stosd
cmp byte[romloadskip],1
je near StartGUI
NEWSYM continueprog
; clear keyboard presses
mov esi,pressed
mov ecx,256+128+64
mov al,0
.loopa
mov [esi],al
inc esi
dec ecx
jnz .loopa
mov byte[romloadskip],0
mov byte[debuggeron],0
mov byte[exiter],0
call InitPreGame
jmp reexecute
NEWSYM continueprognokeys
mov byte[romloadskip],0
mov byte[debuggeron],0
mov byte[exiter],0
call InitPreGame
jmp reexecutenokeys
; Incorrect
NEWSYM reexecute
; clear keyboard presses
mov esi,pressed
mov ecx,256+128+64
mov al,0
.loopa
cmp byte[esi],2
jne .notclear
mov [esi],al
.notclear
inc esi
dec ecx
jnz .loopa
reexecutenokeys
jmp reexecuteb2
NEWSYM reexecuteb
%ifdef __MSDOS__
mov esi,pressed
mov ecx,256+128+64
mov al,0
.loopa
cmp byte[esi],2
jne .notclear
mov [esi],al
.notclear
inc esi
dec ecx
jnz .loopa
%endif
reexecuteb2:
cmp byte[NoSoundReinit],1
je .skippregame
call SetupPreGame
.skippregame
; initialize variables (Copy from variables)
call UpdateDPage
call SA1UpdateDPage
call Makemode7Table
cmp byte[SFXEnable],0
je .nosfxud
call UpdateSFX
.nosfxud
xor eax,eax
xor ebx,ebx
xor ecx,ecx
xor edx,edx
mov bl,[xpb]
mov ax,[xpc]
test ax,8000h
jz .loweraddr
mov esi,[snesmmap+ebx*4]
jmp .skiplower
.loweraddr
cmp ax,4300h
jb .lower
cmp dword[memtabler8+ebx*4],regaccessbankr8
je .dma
.lower
mov esi,[snesmap2+ebx*4]
jmp .skiplower
.dma
mov esi,dmadata-4300h
.skiplower
mov [initaddrl],esi
add esi,eax ; add program counter to address
mov dl,[xp] ; set flags
mov dh,[curcyc] ; set cycles
mov bl,dl
cmp byte[spcon],0
je .nosoundta
mov edi,[tableadc+ebx*4]
or byte[curexecstate],2
jmp .soundta
.nosoundta
mov edi,[tableadb+ebx*4]
and byte[curexecstate],0FDh
.soundta
mov ebp,[spcPCRam]
mov byte[NoSoundReinit],0
mov byte[csounddisable],0
mov byte[NextNGDisplay],0
call splitflags
call execute
call joinflags
; de-init variables (copy to variables)
mov [spcPCRam],ebp
mov [Curtableaddr],edi
mov [xp],dl
mov [curcyc],dh
mov eax,[initaddrl]
sub esi,eax ; subtract program counter by address
mov [xpc],si
call ResetTripleBuf
mov eax,[KeySaveState]
test byte[pressed+eax],1
jnz .soundreinit
mov eax,[KeyLoadState]
test byte[pressed+eax],1
jz .skipsoundreinit
.soundreinit
mov byte[NoSoundReinit],1
mov byte[csounddisable],1
.skipsoundreinit
cmp byte[NoSoundReinit],1
je .skippostgame
call DeInitPostGame
.skippostgame
; clear all keys
call Check_Key
cmp al,0
je .nokeys
.yeskeys
call Get_Key
call Check_Key
cmp al,0
jne .yeskeys
.nokeys
cmp byte[nextmenupopup],1
je near showmenu
cmp byte[ReturnFromSPCStall],1
je near .activatereset
mov eax,[KeySaveState]
test byte[pressed+eax],1
jz .nosavestt
mov byte[pressed+1],0
mov byte[pressed+eax],2
pushad
call statesaver
popad
jmp reexecuteb
.nosavestt
mov eax,[KeyLoadState]
test byte[pressed+eax],1
jz .noloadstt0
pushad
call loadstate
popad
jmp reexecuteb
.noloadstt0
mov eax,[KeyInsrtChap]
test byte[pressed+eax],1
jz .noinsertchapter
mov byte[pressed+eax],0
pushad
call MovieInsertChapter
popad
jmp continueprognokeys
.noinsertchapter
mov eax,[KeyNextChap]
test byte[pressed+eax],1
jz .nonextchapter
mov byte[pressed+eax],0
mov byte[multchange],1
pushad
call MovieSeekAhead
popad
jmp continueprognokeys
.nonextchapter
mov eax,[KeyPrevChap]
test byte[pressed+eax],1
jz .noprevchapter
mov byte[pressed+eax],0
mov byte[multchange],1
pushad
call MovieSeekBehind
popad
jmp continueprognokeys
.noprevchapter
cmp byte[SSKeyPressed],1
je near showmenu
cmp byte[SPCKeyPressed],1
je near showmenu
cmp byte[debugdisble],0
jne .nodebugger
test byte[pressed+59],1
jne near startdebugger
.nodebugger
test byte[pressed+59],1
jne near showmenu
mov eax,[KeyQuickRst]
test byte[pressed+eax],1
jz .noreset
.activatereset
pushad
mov byte[GUIReset],1
cmp byte[MovieProcessing],2 ;Recording
jne .nomovierecording
call ResetDuringMovie
jmp .movieendif
.nomovierecording
call GUIDoReset
.movieendif
popad
mov byte[ReturnFromSPCStall],0
jmp continueprog
.noreset
cmp byte[guioff],1
je near endprog
mov eax,[KeyQuickExit]
test byte[pressed+eax],1
jnz near endprog
jmp StartGUI
NEWSYM endprog
call deinitvideo
call SaveSramData
call createnewcfg
call GUISaveVars
pushad
call MovieStop
popad
; change dir to InitDrive/InitDir
mov dl,[InitDrive]
mov ebx,InitDir
call Change_Dir
jmp OSExit
NEWSYM interror
stim
call deinitvideo
mov edx,.nohand ;use extended
mov ah,9 ;DOS- API
call Output_Text ;to print a string
jmp DosExit
SECTION .data
.nohand db 'Cannot process interrupt handler!',13,10,0
; global variables
NEWSYM invalid, db 0
NEWSYM invopcd, db 0
NEWSYM pressed, times 256+128+64 db 0 ; keyboard pressed keys in scancode
NEWSYM exiter, db 0
NEWSYM oldhand9o, dd 0
NEWSYM oldhand9s, dw 0
NEWSYM oldhand8o, dd 0
NEWSYM oldhand8s, dw 0
NEWSYM opcd, dd 0
NEWSYM pdh, dd 0
NEWSYM pcury, dd 0
NEWSYM timercount, dd 0
NEWSYM initaddrl, dd 0 ; initial address location
NEWSYM NetSent, dd 0
NEWSYM nextframe, dd 0 ; tick count for timer
NEWSYM curfps, db 0 ; frame/sec for current screen
;NEWSYM newgfxerror, db 'NEED MEMORY FOR GFX ENGINE',0
;NEWSYM newgfxerror2, db 'NEED 320x240 FOR NEW GFX 16B',0
;newgfxerror db 'NEW GFX IN 16BIT IS N/A',0
NEWSYM HIRQCycNext, dd 0
NEWSYM HIRQNextExe, db 0
;*******************************************************
; Int 08h vector
;*******************************************************
; sets to either 60Hz or 50Hz depending on PAL/NTSC
NEWSYM init60hz
cmp byte[romispal],0
jne .dopal
mov al,00110110b
out 43h,al
mov ax,19900 ; 65536/(60/((65536*24+175)/(60*60*24)))
mov dword[timercount],19900
out 40h,al
mov al,ah
out 40h,al
ret
.dopal
mov al,00110110b
out 43h,al
mov ax,23863 ; 65536/(50/((65536*24+175)/(60*60*24)))
mov dword[timercount],23863
out 40h,al
mov al,ah
out 40h,al
ret
NEWSYM init18_2hz
mov al,00110110b
out 43h,al
mov ax,0
mov dword[timercount],65536
out 40h,al
mov al,ah
out 40h,al
ret
%ifdef __MSDOS__
NEWSYM handler8h
cli
push ds
push eax
; mov ax,0
mov ax,[cs:dssel]
NEWSYM handler8hseg
mov ds,ax
call Game60hzcall
mov eax,[timercount]
sub dword[timeradj],eax
jnc .noupd
add dword[timeradj],65536
pushf
call far [oldhand8o]
.noupd
mov al,20h
out 20h,al
pop eax
pop ds
sti
iretd
%endif
SECTION .data
NEWSYM timeradj, dd 65536
NEWSYM t1cc, dw 0
SECTION .text
;*******************************************************
; Int 09h vector
;*******************************************************
%ifdef __MSDOS__
SECTION .bss
NEWSYM skipnextkey42, resb 1
SECTION .text
NEWSYM handler9h
cli
push ds
push eax
push ebx
mov ax,[cs:dssel]
mov ds,ax
xor ebx,ebx
in al,60h ; get keyboard scan code
cmp al,42
jne .no42
cmp byte[skipnextkey42],0
je .no42
mov byte[skipnextkey42],0
jmp .skipkeyrel
.no42
cmp al,0E0h
jne .noE0
mov byte[skipnextkey42],1
jmp .skipkeyrel
.noE0
mov byte[skipnextkey42],0
mov bl,al
xor bh,bh
test bl,80h ; check if bit 7 is on (key released)
jnz .keyrel
cmp byte[pressed+ebx],0
jne .skipa
mov byte[pressed+ebx],1 ; if not, set key to pressed
.skipa
jmp .skipkeyrel
.keyrel
and ebx,7Fh
cmp ebx,59
je .skipkeyrel
cmp ebx,[KeySaveState]
je .skipkeyrel
cmp ebx,[KeyLoadState]
je .skipkeyrel
cmp ebx,[KeyQuickExit]
je .skipkeyrel
cmp ebx,[KeyQuickLoad]
je .skipkeyrel
cmp ebx,[KeyQuickRst]
je .skipkeyrel
cmp bl,1
je .skipkeyrel
mov byte[pressed+ebx],0 ; if not, set key to pressed
.skipkeyrel
mov byte[pressed],0
in al,61h
mov ah,al
or al,80h
out 61h,al
mov al,20h ; turn off interrupt mode
out 20h,al
pop ebx ; Pop registers off
pop eax ; stack in correct
pop ds
sti
iretd
%endif
SECTION .data
ALIGN32
NEWSYM soundcycleft, dd 0
NEWSYM curexecstate, dd 0
NEWSYM nmiprevaddrl, dd 0 ; observed address -5
NEWSYM nmiprevaddrh, dd 0 ; observed address +5
NEWSYM nmirept, dd 0 ; NMI repeat check, if 6 then okay
NEWSYM nmiprevline, dd 224 ; previous line
NEWSYM nmistatus, dd 0 ; 0 = none, 1 = waiting for nmi location,
; 2 = found, disable at next line
NEWSYM joycontren, dd 0 ; joystick read control check
NEWSYM NextLineCache, db 0
NEWSYM ZMVZClose, db 0
SECTION .text
Donextlinecache:
cmp word[curypos],0
je .nocache
mov ax,[resolutn]
dec ax
cmp word[curypos],ax
jae .nocache
test byte[scrndis],10h
jnz .nocache
cmp byte[curblank],0h
jne .nocache
push ecx
push ebx
push esi
push edi
xor ecx,ecx
mov cl,[curypos]
push edx
.next
mov byte[sprlefttot+ecx],0
mov dword[sprleftpr+ecx*4],0
inc cl
jnz .next
call processsprites
call cachesprites
pop edx
pop edi
pop esi
pop ebx
pop ecx
.nocache
mov byte[NextLineCache],0
ret
;*******************************************************
; 65816 execution
;*******************************************************
SECTION .data
SpeedHackSafeTable
db 1,0,1,0,0,0,1,0,1,0,1,1,0,0,0,0
db 0,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0
db 0,0,0,0,0,0,1,0,1,0,1,1,0,0,1,0
db 0,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0
db 0,0,0,0,0,1,1,1,1,1,1,1,0,1,1,1
db 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0
db 0,1,0,1,0,1,1,1,0,1,1,0,0,1,1,1
db 0,1,1,1,0,1,1,1,0,1,0,0,0,1,1,1
db 0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,1,0,1,0,1,0,0,0,1,0
db 0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0
db 0,1,0,1,0,1,1,1,1,1,0,0,0,1,1,1
db 0,1,1,1,0,1,1,1,0,1,0,0,0,1,1,1
SECTION .text
NEWSYM exitloop2
mov byte[ExecExitOkay],0
NEWSYM exitloop
ret
ALIGN16
%macro FlipCheck 0
cmp byte[FlipWait],0
je %%noflip
push edx
push eax
mov dx,3DAh ;VGA status port
in al,dx
test al,8
jz %%skipflip
push ebx
push ecx
mov ax,4F07h
mov bh,00h
mov bl,00h
xor cx,cx
mov dx,[NextLineStart]
mov [LastLineStart],dx
int 10h
mov byte[FlipWait],0
pop ecx
pop ebx
%%skipflip
pop eax
pop edx
%%noflip
%endmacro
NEWSYM execute
NEWSYM execloop
mov bl,dl
test byte[curexecstate],2
jnz .sound
mov edi,[tableadb+ebx*4]
mov bl,[esi]
inc esi
sub dh,[cpucycle+ebx]
jc .cpuover
.startagain
call dword near [edi+ebx*4]
.cpuover
jmp cpuover
.sound
mov edi,[tableadc+ebx*4]
%ifdef OPENSPC
pushad
mov bl,[esi]
movzx eax,byte[cpucycle+ebx]
mov ebx,0xC3A13DE6
mul ebx
add [ospc_cycle_frac],eax
adc [SPC_Cycles],edx
call OSPC_Run
popad
%else
sub dword[cycpbl],55
jnc .skipallspc
mov eax,[cycpblt]
mov bl,[ebp]
add dword[cycpbl],eax
; 1260, 10000/12625
inc ebp
call dword near [opcjmptab+ebx*4]
xor ebx,ebx
.skipallspc
%endif
mov bl,[esi]
inc esi
sub dh,[cpucycle+ebx]
jc .cpuovers
call dword near [edi+ebx*4]
.cpuovers
jmp cpuover
SECTION .data
ALIGN32
NEWSYM ExecExitOkay, db 1
NEWSYM JoyABack, dd 0
NEWSYM JoyBBack, dd 0
NEWSYM JoyCBack, dd 0
NEWSYM JoyDBack, dd 0
NEWSYM JoyEBack, dd 0
NEWSYM NetCommand, dd 0
NEWSYM spc700read, dd 0
NEWSYM lowestspc, dd 0
NEWSYM highestspc, dd 0
NEWSYM SA1UBound, dd 0
NEWSYM SA1LBound, dd 0
NEWSYM SA1SH, dd 0
NEWSYM SA1SHb, dd 0
NEWSYM NumberOfOpcodes2, dd 0
NEWSYM ChangeOps, dd 0
NEWSYM SFXProc, dd 0
NEWSYM EMUPause, db 0
NEWSYM INCRFrame, db 0
SECTION .text
NEWSYM cpuover
dec esi
cmp byte[HIRQNextExe],0
je .nohirq
add dh,[HIRQCycNext]
mov byte[HIRQCycNext],0
jmp .hirq
.nohirq
cmp byte[SA1Enable],0
je near .nosa1b
test byte[exiter],01h
jnz near .nosa1
mov byte[cycpl],150
test byte[SA1Control],60h
jnz near .nosa1
call SA1Swap
cmp byte[CurrentExecSA1],15
ja .nocontinueexec
xor ebx,ebx
mov bl,[esi]
inc esi
jmp execloop.startagain
.nocontinueexec
; check for sa-1 speed hacks
mov byte[SA1SHb],0
cmp word[IRAM+0A0h],80BFh
jne .noshb2
cmp word[IRAM+020h],0
jne .noshb2
mov ecx,[SA1Ptr] ; small speed hack
sub ecx,[romdata]
cmp ecx,83h
jb .skipsh
cmp ecx,97h
ja .skipsh
mov byte[SA1SHb],1
.skipsh
.noshb2
mov ecx,[SA1Ptr] ; small speed hack
cmp dword[ecx],0FCF04BA5h
je .shm
cmp dword[ecx-2],0FCF04BA5h
jne .skipshm
.shm
cmp byte[IRAM+4Bh],0
jne .skipshm
mov byte[SA1SHb],1
.skipshm
cmp dword[ecx],80602EEEh
jne .skipshc
sub ecx,[romdata]
cmp ecx,4E5h
jb .skipshc
cmp ecx,4E8h
ja .skipshc
mov byte[SA1SHb],1
mov ecx,[SA1BWPtr]
add word[ecx+602Eh],4
.skipshc
test word[IRAM+0Ah],8000h
jnz .noshb2b
test word[IRAM+0Eh],8000h
jz .noshb2b
mov ecx,[SA1Ptr] ; small speed hack
sub ecx,[romdata]
cmp ecx,0C93h
jb .skipshb
cmp ecx,0C9Bh
ja .skipshb
mov byte[SA1SHb],1
.skipshb
cmp ecx,0CB8h
jb .skipshb3
cmp ecx,0CC0h
ja .skipshb3
mov byte[SA1SHb],1
.skipshb3
.noshb2b
sub esi,[wramdata]
cmp esi,224h
jb .nosh
cmp esi,22Eh
ja .nosh
mov ecx,[wramdata]
mov dword[SA1LBound],224h
mov dword[SA1UBound],22Eh
add dword[SA1LBound],ecx
add dword[SA1UBound],ecx
mov byte[SA1SH],1
.nosh
cmp esi,1F7C6h
jb .noshb
cmp esi,1F7CCh
ja .noshb
mov ecx,[wramdata]
mov dword[SA1LBound],1F7C6h
mov dword[SA1UBound],1F7CCh
add dword[SA1LBound],ecx
add dword[SA1UBound],ecx
mov byte[SA1SH],1
.noshb
cmp esi,14h
jb .noshc
cmp esi,1Ch
ja .noshc
mov ecx,[wramdata]
cmp dword[ecx+14h],0F023002Ch
jne .noshc
mov dword[SA1LBound],14h
mov dword[SA1UBound],1Ch
add dword[SA1LBound],ecx
add dword[SA1UBound],ecx
mov byte[SA1SH],1
.noshc
add esi,[wramdata]
sub esi,[romdata]
cmp esi,0A56h
jb .noshbc
cmp esi,0A59h
ja .noshbc
mov ecx,[romdata]
mov dword[SA1LBound],0A56h
mov dword[SA1UBound],0A59h
add dword[SA1LBound],ecx
add dword[SA1UBound],ecx
mov byte[SA1SH],1
.noshbc
xor ecx,ecx
add esi,[romdata]
xor dh,dh
mov byte[cycpl],10
cmp byte[CurrentExecSA1],255
jne .notsa1255
mov byte[cycpl],160
.notsa1255
mov byte[CurrentExecSA1],0
test dl,04h
jnz .nosa1
test byte[SA1IRQEnable],80h
jz .nosa1
test byte[SA1DoIRQ],4
jz .nosa1
and byte[SA1DoIRQ],0FBh
mov al,byte[SA1Message+1]
mov byte[SA1Message+3],al
or byte[SA1IRQExec],1
; Start IRQ
add dh,10
jmp .virq
.nosa1
test byte[SA1IRQEnable],20h
jz .nosa1chirq
test byte[SA1DoIRQ],8
jz .nosa1chirq
; jmp .nosa1chirq
and byte[SA1DoIRQ],0F7h
mov al,byte[SA1Message+1]
mov byte[SA1Message+3],al
or byte[SA1IRQExec],2
; Start IRQ
add dh,10
jmp .virq
.nosa1chirq
.nosa1b
FlipCheck
cmp byte[NextLineCache],0
je .nosprcache
call Donextlinecache
.nosprcache
cmp byte[KeyOnStB],0
je .nokeyon
mov al,[KeyOnStB]
call ProcessKeyOn
.nokeyon
mov al,[KeyOnStA]
mov [KeyOnStB],al
mov byte[KeyOnStA],0
test byte[exiter],01h
jnz near exitloop2
test byte[SfxSFR],20h
jnz near StartSFX
.returnfromsfx
; inc dword[numinst] ;Temporary
inc word[curypos]
add dh,[cycpl]
mov ax,[totlines]
cmp word[curypos],ax
jae near .overy
cmp byte[spcon],0
je .nosound
call updatetimer
.nosound
mov ax,[resolutn]
inc ax
cmp [curypos],ax
je near .nmi
mov ax,[resolutn]
cmp [curypos],ax
je near .hdma
; add ax,2
; cmp [curypos],ax
; je near .hdma
.hdmacont
cmp byte[curypos],100
jne .noline100
mov ax,[scrnon]
mov [TempVidInfo],ax
mov ax,[scaddset]
mov [TempVidInfo+2],ax
.noline100
; check for VIRQ/HIRQ/NMI
ProcessIRQStuff
mov ax,[resolutn]
dec ax
cmp [curypos],ax
jb .drawline
; mov ax,[resolutn]
; cmp [curypos],ax
; jb .drawline
xor ebx,ebx
mov bl,[esi]
inc esi
jmp execloop.startagain
.hdma
call exechdma
jmp .hdmacont
.drawline
mov al,[nmiprevline]
cmp [curypos],al
jb near .noskip
cmp byte[nmirept],10
jb near .noskip
; if between correct address, decrease by 2, set nmistatus as 2
; if not, set nmistatus as 1, increase by 2
cmp byte[curexecstate],0
jne .nn
xor dh,dh
.nn
cmp byte[nmistatus],2
jae near .noskip
cmp esi,[nmiprevaddrl]
jb .failcheck2
cmp esi,[nmiprevaddrh]
ja .failcheck2
cmp byte[nmiprevline],20
jb .nodec
sub byte[nmiprevline],10
.nodec
xor eax,eax
mov al,[esi]
cmp byte[disable65816sh],1
je .ohno
cmp byte[SpeedHackSafeTable+eax],1
jne .okay
.ohno
mov byte[nmirept],0
mov dword[nmiprevaddrl],0FFFFFFFFh
mov dword[nmiprevaddrh],0
jmp .noskip
.okay
mov byte[nmistatus],2
and byte[curexecstate],0FEh
.nodis65816
jmp .noskip
.failcheck2
add byte[nmiprevline],1
mov byte[nmistatus],1
.noskip
cmp byte[hdmadelay],0
je .dohdma
dec byte[hdmadelay]
jmp .nodohdma
.dohdma
cmp word[curypos],1
jne .nooffby1line
test byte[INTEnab],20h
jz .nooffby1line
cmp word[VIRQLoc],0
je .nodohdma
.nooffby1line
call exechdma
.nodohdma
cmp word[curypos],1
jne .nocache
call cachevideo
.nocache
cmp byte[curblank],0
jne .nodrawlineb2
call drawline
.nodrawlineb2
cmp byte[curexecstate],2
je near pexecs
cmp byte[curexecstate],0
jne .yesexec
xor dh,dh
.yesexec
xor ebx,ebx
mov bl,[esi]
inc esi
jmp execloop.startagain
.nmi
mov byte[irqon],80h
mov byte[doirqnext],0
cmp byte[yesoutofmemory],1
jne .noout
call outofmemfix
.noout
dec word[curypos]
mov [tempdh],dh
xor dh,dh
; mov al,[SFXIRQFlag]
mov byte[doirqnext],0
call exechdma
call exechdma
mov byte[NextNGDisplay],1
cmp byte[newengen],0
je .nonewgfx
cmp byte[curblank],0
jne .nonewgfx
cmp byte[ForceNewGfxOff],0
jne .nonewgfx
; cmp byte[NextNGDisplay],0
; je .nonewgfx
call StartDrawNewGfx
.nonewgfx
cmp byte[GUIQuit],1
je near endprog
mov eax,dword[KeyQuickSnapShot]
or eax,eax
jz .nosskey
test byte[pressed+eax],1
jz .nosskey
mov byte[SSKeyPressed],1
mov byte[pressed+eax],2
jmp exitloop
.nosskey
mov eax,dword[KeyQuickClock]
or eax,eax
jz .noclockkey
test byte[pressed+eax],1
jz .noclockkey
xor byte[TimerEnable],1
mov byte[pressed+eax],2
.noclockkey
mov eax,dword[KeyQuickSaveSPC]
or eax,eax
jz .nosavespckey
test byte[pressed+eax],1
jz .nosavespckey
mov byte[SPCKeyPressed],1
mov byte[pressed+eax],2
jmp exitloop
.nosavespckey
mov eax,dword[EMUPauseKey]
or eax,eax
jz .nopausekey
test byte[pressed+eax],1
jz .nopausekey
xor byte[EMUPause],1
mov byte[pressed+eax],2
.nopausekey
mov eax,dword[INCRFrameKey]
or eax,eax
jz .noincrframekey
test byte[pressed+eax],1
jz .noincrframekey
xor byte[INCRFrame],1
mov byte[pressed+eax],2
.noincrframekey
test byte[pressed+1],01h
jnz near exitloop
test byte[pressed+59],01h
jnz near exitloop
cmp byte[nextmenupopup],1
je near exitloop
cmp byte[nextmenupopup],2
jb .skipmenupop
dec byte[nextmenupopup]
.skipmenupop
mov eax,[KeySaveState]
test byte[pressed+eax],01h
jnz near exitloop
mov eax,[KeyLoadState]
test byte[pressed+eax],01h
jnz near exitloop
mov eax,[KeyInsrtChap]
test byte[pressed+eax],01h
jnz near exitloop
mov eax,[KeyPrevChap]
test byte[pressed+eax],01h
jnz near exitloop
mov eax,[KeyNextChap]
test byte[pressed+eax],01h
jnz near exitloop
mov eax,[KeyQuickRst]
test byte[pressed+eax],01h
jnz near exitloop
mov eax,[KeyQuickExit]
test byte[pressed+eax],01h
jnz near exitloop
mov eax,[KeyQuickLoad]
test byte[pressed+eax],01h
jnz near exitloop
cmp byte[ExecExitOkay],0
je .returntoloop
dec byte[ExecExitOkay]
.returntoloop
mov dh,[tempdh]
inc word[curypos]
cmp byte[NoInputRead],1
je .noinputread
call ReadInputDevice
.noinputread
;Pause and Frame increment
cmp byte[PauseFrameMode],3
jne .nopauseframemode3
pushad
call RestorePauseFrame
popad
mov esi,[tempesi]
mov edi,[tempedi]
mov ebp,[tempebp]
mov edx,[tempedx]
.nopauseframemode3
cmp byte[EMUPause],1
jne .noemupause
cmp byte[PauseFrameMode],1
jne .nopauseframemode1
mov [tempedx],edx
mov [tempesi],esi
mov [tempedi],edi
mov [tempebp],ebp
pushad
call BackupPauseFrame
popad
.nopauseframemode1
call ProcessRewind
cmp byte[PauseFrameMode],2
jne .nopauseframemode2
mov byte[PauseFrameMode],3
jmp .noprocmovie
.nopauseframemode2
cmp byte[INCRFrame],1
jne .noframeincr
xor byte[INCRFrame],1
jmp .noemupause
.noframeincr
;Update screen
pushad
;call StartDrawNewGfx
call showvideo
call cachevideo
popad
jmp .nonewgfx
.noemupause
;Rewind update must be done before process this frame of movie, so rewind doesn't
;back up incremented values (some vars being for the next frame)
call UpdateRewind
cmp byte[MovieProcessing],0
je .noprocmovie
pushad
call ProcessMovies
popad
cmp byte[GUIReset],1
jne .notreset
mov byte[MovieWaiting],1
mov eax,[KeyQuickRst]
mov byte[pressed+eax],01h
jmp near exitloop
.notreset
cmp byte[MovieProcessing],0
jne .noprocmovie
cmp byte[ZMVZClose],1
jne .noprocmovie
jmp OSExit
.noprocmovie
cmp byte[snesmouse],4
jne .nolethalen
mov eax,[LethEnData]
mov [JoyBNow],eax
.nolethalen
test byte[INTEnab],1
jz .noresetjoy
mov eax,[JoyAOrig]
rol eax,16
mov [JoyANow],eax
mov eax,[JoyBOrig]
rol eax,16
mov [JoyBNow],eax
mov eax,[JoyCOrig]
rol eax,16
mov [JoyCNow],eax
mov eax,[JoyDOrig]
mov [JoyDNow],eax
mov eax,[JoyEOrig]
mov [JoyENow],eax
mov byte[JoyCRead],0
.noresetjoy
mov byte[MultiTapStat],80h
cmp byte[C4Enable],0
je .noC4
call C4VBlank
.noC4
; mov byte[hdmastartsc],0
mov byte[joycontren],0
test byte[curexecstate],01h
jnz .dis65816
or byte[curexecstate],01h
.dis65816
cmp byte[CheatOn],1
je near .cheater
.returncheat
mov ax,[VIRQLoc]
cmp word[curypos],ax
jne .novirqz
mov byte[doirqnext],1
.novirqz
mov ax,[oamaddrs]
mov [oamaddr],ax
mov byte[nosprincr],0
call showvideo
xor ebx,ebx
mov byte[NMIEnab],81h
test byte[INTEnab],80h
jz near .nonmi
; cmp byte[intrset],1
; je near .nonmi
.nmiokay
mov byte[curnmi],1
cmp byte[intrset],1
jne .nointrset
mov byte[intrset],2
.nointrset
cmp byte[nmistatus],1
jne .notnonmifound
mov byte[nmirept],0
.notnonmifound
mov byte[nmistatus],0
cmp byte[nmirept],0
jne .nocheck
mov al,[resolutn]
sub al,2
mov [nmiprevline],al
mov dword[nmiprevaddrl],0FFFFFFFFh
mov dword[nmiprevaddrh],0
mov byte[nmirept],1
mov byte[doirqnext],0
jmp switchtonmi
.nocheck
cmp byte[nmirept],10
je .nextcheck
cmp esi,[nmiprevaddrl]
jae .notlower
mov [nmiprevaddrl],esi
.notlower
cmp esi,[nmiprevaddrh]
jbe .notgreater
mov [nmiprevaddrh],esi
.notgreater
inc byte[nmirept]
jmp switchtonmi
.nextcheck
mov eax,[nmiprevaddrh]
sub eax,[nmiprevaddrl]
cmp eax,10
ja .failcheck
cmp esi,[nmiprevaddrl]
jb .failcheck
cmp esi,[nmiprevaddrh]
ja .failcheck
mov byte[doirqnext],0
jmp switchtonmi
.failcheck
mov byte[nmirept],0
mov dword[nmiprevaddrl],0FFFFFFFFh
mov dword[nmiprevaddrh],0
mov byte[doirqnext],0
jmp switchtonmi
.nonmi
cmp byte[intrset],1
jne .nointrset2w
mov byte[intrset],2
.nointrset2w
xor ebx,ebx
xor ecx,ecx
mov bl,[esi]
inc esi
jmp execloop.startagain
.overy
shr dh,1
cmp byte[smallscreenon],1
je .nocfield
cmp byte[ScreenScale],1
je .nocfield
cmp byte[scanlines],0
jne .nocfield
xor byte[cfield],1
.nocfield
mov word[curypos],0
xor byte[ppustatus],80h
cmp dword[numspcvblleft],0
je near .novblch
cmp [lowestspc],ebp
ja .failspc
cmp [highestspc],ebp
jb .failspc
jmp .okayspc
.failspc
mov eax,ebp
sub eax,10
mov [lowestspc],eax
add eax,20
mov [highestspc],eax
mov dword[spc700idle],0
.okayspc
cmp dword[SPC700write],0
jne .notwritespc
cmp dword[spc700read],0
je .notwritespc
cmp dword[SPC700read],1500
jb .notwritespc
inc dword[spc700idle]
cmp dword[spc700idle],30
jne .noidleend
call idledetectspc
cmp byte[ReturnFromSPCStall],1
jne .noidleend
mov byte[ExecExitOkay],0
jmp exitloop
.noidleend
jmp .notidle
.notwritespc
mov dword[spc700idle],0
.notidle
dec dword[numspcvblleft]
mov dword[SPC700write],0
mov dword[SPC700read],0
mov dword[spc700read],0
.novblch
mov byte[NMIEnab],01h
call starthdma
.noirqhack
; check for VIRQ/HIRQ/NMI
ProcessIRQStuff
xor ebx,ebx
mov bl,[esi]
inc esi
jmp execloop.startagain
.virq
test byte[curexecstate],01h
jnz .dis658162
or byte[curexecstate],01h
.dis658162
mov byte[doirqnext],0
xor ebx,ebx
mov ax,[resolutn]
cmp word[curypos],ax
jnb .nodrawline
cmp byte[hdmadelay],0
je .dohdma2
dec byte[hdmadelay]
jmp .nodohdma2
.dohdma2
call exechdma
.nodohdma2
cmp word[curypos],1
jne .nocache2
call cachevideo
.nocache2
cmp byte[curblank],0
jne .nodrawline
call drawline
.nodrawline
cmp byte[intrset],1
jne .nointrset2
mov byte[intrset],2
.nointrset2
; sub dh,8
jmp switchtovirq
.hirq
mov byte[HIRQNextExe],0
test byte[INTEnab],10h
jz .hirqnotokay
test byte[curexecstate],01h
jnz .dis658162h
or byte[curexecstate],01h
.dis658162h
mov byte[doirqnext],0
cmp byte[intrset],1
jne .nointrset2h
mov byte[intrset],2
.nointrset2h
test dl,04h
jnz .irqd
jmp switchtovirq
.irqd
mov byte[doirqnext],1
.hirqnotokay
jmp .nodrawlineh
.returnfromhirq
mov ax,[resolutn]
cmp word[curypos],ax
jnb .nodrawlineh
cmp byte[hdmadelay],0
je .dohdma2h
dec byte[hdmadelay]
jmp .nodohdma2h
.dohdma2h
call exechdma
.nodohdma2h
cmp word[curypos],1
jne .nocache2h
call cachevideo
.nocache2h
cmp byte[curblank],0
jne .nodrawlineh
call drawline
.nodrawlineh
xor ebx,ebx
mov bl,[esi]
inc esi
jmp execloop.startagain
.cheater
push eax
push ebx
push ecx
push edx
mov al,[NumCheats]
mov byte[.numcheat],al
xor edx,edx
.anothercheat
xor ebx,ebx
xor ecx,ecx
test byte[cheatdata+edx],5
jnz .nonormcheat
test byte[cheatdata+edx-28],80h
jnz .nonormcheat
test byte[cheatdata+edx],80h
jnz .cheatcodereflect
mov al,[cheatdata+edx+1]
mov cx,[cheatdata+edx+2]
mov bl,[cheatdata+edx+4]
push edx
call dword near [memtablew8+ebx*4]
pop edx
jmp .nonormcheat
.cheatcodereflect
cmp byte[.numcheat],1
je .nonormcheat
mov cx,[cheatdata+edx+2+28]
mov bl,[cheatdata+edx+4+28]
push edx
call dword near [memtabler8+ebx*4]
pop edx
mov cx,[cheatdata+edx+2]
mov bl,[cheatdata+edx+4]
push edx
call dword near [memtablew8+ebx*4]
pop edx
add edx,28
dec byte[.numcheat]
.nonormcheat
add edx,28
dec byte[.numcheat]
jnz near .anothercheat
pop edx
pop ecx
pop ebx
pop eax
jmp .returncheat
SECTION .bss
.numcheat resb 1
SECTION .text
ALIGN16
NEWSYM pexecs
mov byte[soundcycleft],30
.sloop
mov bl,[ebp]
; 1260, 10000/12625
inc ebp
call dword near [opcjmptab+ebx*4]
xor ebx,ebx
dec byte[soundcycleft]
jnz .sloop
xor dh,dh
xor ebx,ebx
mov bl,[esi]
inc esi
jmp execloop.startagain
NEWSYM pexecs2
.sloop
mov bl,[ebp]
; 1260, 10000/12625
inc ebp
call dword near [opcjmptab+ebx*4]
xor ebx,ebx
dec dword[soundcycleft]
jnz .sloop
ret
NEWSYM UpdatePORSCMR
push ebx
push eax
test byte[SfxPOR],10h
jnz .objmode
mov al,[SfxSCMR]
and al,00100100b ; 4 + 32
cmp al,4
je .lines160
cmp al,32
je .lines192
cmp al,36
je .objmode
mov eax,[sfx128lineloc]
jmp .donelines
.lines160
mov eax,[sfx160lineloc]
jmp .donelines
.lines192
mov eax,[sfx192lineloc]
jmp .donelines
.objmode
mov eax,[sfxobjlineloc]
.donelines
mov [sfxclineloc],eax
mov al,[SfxSCMR]
and eax,00000011b
mov bl,[SfxPOR]
and bl,0Fh
shl bl,2
or al,bl
mov ebx,[PLOTJmpb+eax*4]
mov eax,[PLOTJmpa+eax*4]
mov dword [FxTable+4Ch*4],eax
mov dword [FxTableb+4Ch*4],eax
mov dword [FxTablec+4Ch*4],eax
mov dword [FxTabled+4Ch*4],ebx
pop eax
pop ebx
ret
NEWSYM UpdateSCBRCOLR
push eax
push ebx
mov ebx,[SfxSCBR]
shl ebx,10
add ebx,[sfxramdata]
mov [SCBRrel],ebx
mov eax,[SfxCOLR]
mov ebx,[fxbit01+eax*4]
mov [fxbit01pcal],ebx
mov ebx,[fxbit23+eax*4]
mov [fxbit23pcal],ebx
mov ebx,[fxbit45+eax*4]
mov [fxbit45pcal],ebx
mov ebx,[fxbit67+eax*4]
mov [fxbit67pcal],ebx
pop ebx
pop eax
ret
NEWSYM UpdateCLSR
mov dword [NumberOfOpcodes2],350 ; 0FFFFFFFh;350
test byte[SfxCLSR],01h
jz .nohighsfx
mov dword [NumberOfOpcodes2],700 ;700
.nohighsfx
cmp byte[SFXCounter],1
je .noyi
mov dword [NumberOfOpcodes2],0FFFFFFFh
.noyi
ret
NEWSYM UpdateSFX
call UpdatePORSCMR
call UpdatePORSCMR
call UpdateCLSR
ret
NEWSYM StartSFX
push edx
push esi
push edi
push ebp
xor ebx,ebx
mov bl,[SfxPBR]
mov al,[SfxSCMR]
and bl,7Fh
cmp bl,70h
jae .ram
test al,10h
jz .noaccess
jmp .noram
.ram
test al,08h
jz .noaccess
.noram
mov eax,[NumberOfOpcodes2]
mov [NumberOfOpcodes],eax
call MainLoop
.noaccess
pop ebp
pop edi
pop esi
pop edx
xor ebx,ebx
xor ecx,ecx
jmp cpuover.returnfromsfx
NEWSYM StartSFXdebug
push edx
push esi
push edi
push ebx
mov bl,[SfxPBR]
mov al,[SfxSCMR]
and bl,7Fh
cmp bl,70h
jae .ram
test al,10h
jz .noaccess
jmp .noram
.ram
test al,08h
jz .noaccess
.noram
mov dword [NumberOfOpcodes],350 ; 0FFFFFFFh;350
test byte[SfxCLSR],01h
jz .nohighsfx
mov dword [NumberOfOpcodes],700 ;700
.nohighsfx
cmp byte[SFXCounter],1
jne .noyi
mov dword [NumberOfOpcodes],0FFFFFFFFh
.noyi
; call SFXDebugLoop
.noaccess
pop ebx
pop edi
pop esi
pop edx
xor ecx,ecx
jmp execsingle.returnfromsfx
NEWSYM StartSFXdebugb
push edx
push esi
push edi
push ebp
push ebx
test byte[SfxPOR],10h
jnz .objmode
mov al,[SfxSCMR]
and al,00100100b ; 4 + 32
cmp al,4
je .lines160
cmp al,32
je .lines192
cmp al,36
je .objmode
mov eax,[sfx128lineloc]
jmp .donelines
.lines160
mov eax,[sfx160lineloc]
jmp .donelines
.lines192
mov eax,[sfx192lineloc]
jmp .donelines
.objmode
mov eax,[sfxobjlineloc]
.donelines
mov [sfxclineloc],eax
mov al,[SfxSCMR]
and eax,00000011b
mov bl,[SfxPOR]
and bl,0Fh
shl bl,2
or al,bl
mov ebx,[PLOTJmpb+eax*4]
mov eax,[PLOTJmpa+eax*4]
mov dword [FxTable+4Ch*4],eax
mov dword [FxTableb+4Ch*4],eax
mov dword [FxTablec+4Ch*4],eax
mov dword [FxTabled+4Ch*4],ebx
mov ebx,[SfxSCBR]
shl ebx,10
add ebx,[sfxramdata]
mov [SCBRrel],ebx
mov eax,[SfxCOLR]
mov ebx,[fxbit01+eax*4]
mov [fxbit01pcal],ebx
mov ebx,[fxbit23+eax*4]
mov [fxbit23pcal],ebx
mov ebx,[fxbit45+eax*4]
mov [fxbit45pcal],ebx
mov ebx,[fxbit67+eax*4]
mov [fxbit67pcal],ebx
xor ebx,ebx
mov bl,[SfxPBR]
mov al,[SfxSCMR]
and bl,7Fh
cmp bl,70h
jae .ram
test al,10h
jz .noaccess
jmp .noram
.ram
test al,08h
jz .noaccess
.noram
mov dword [NumberOfOpcodes],400 ;678
test byte[SfxCLSR],01h
jz .nohighsfx
mov dword [NumberOfOpcodes],800 ;678*2
.nohighsfx
cmp byte[SFXCounter],1
jne .noyi
mov dword [NumberOfOpcodes],0FFFFFFFh
.noyi
call MainLoop
.noaccess
pop ebx
pop ebp
pop edi
pop esi
pop edx
xor ecx,ecx
jmp execsingle.returnfromsfx
NEWSYM StartSFXret
test byte[SfxSFR],20h
jz .endfx
pushad
mov bl,[SfxPBR]
mov al,[SfxSCMR]
and bl,7Fh
cmp bl,70h
jae .ram
test al,10h
jz .noaccess
jmp .noram
.ram
test al,08h
jz .noaccess
.noram
mov dword [NumberOfOpcodes],400 ;678
test byte[SfxCLSR],01h
jz .nohighsfx
mov dword [NumberOfOpcodes],800 ;678*2
.nohighsfx
mov dword [NumberOfOpcodes],0FFFFFFFFh
call MainLoop
.noaccess
popad
.endfx
ret
;*******************************************************
; Execute a Single 65816 instruction (debugging purpose)
;*******************************************************
NEWSYM execloopdeb
jmp exitloop2
NEWSYM execsingle
xor ebx,ebx
test byte[curexecstate],2
jz .nosoundb
sub dword[cycpbl],55
jnc .skipallspc
mov eax,[cycpblt]
mov bl,[ebp]
add dword[cycpbl],eax
; 1260, 10000/12625
inc ebp
call dword near [opcjmptab+ebx*4]
xor ebx,ebx
.skipallspc
.nosoundb
mov bl,dl
mov byte[exiter],01h
mov edi,[tablead+ebx*4]
mov bl,[esi]
inc esi
sub dh,[cpucycle+ebx]
jc .cpuover
mov [pdh],dh
xor dh,dh
jmp dword near [edi+ebx*4]
.cpuover
cmp byte[SA1Enable],0
je near .nosa1
mov byte[cycpl],150
test byte[SA1Control],60h
jnz near .nosa1
dec esi
call SA1Swap
mov bl,[esi]
inc esi
mov [pdh],dh
xor dh,dh
cmp byte[CurrentExecSA1],17
jb near cpuover
mov byte[CurrentExecSA1],0
mov byte[cycpl],5
jmp .nosa1
.nosa1
cmp byte[KeyOnStB],0
je .nokeyon
mov al,[KeyOnStB]
call ProcessKeyOn
.nokeyon
mov al,[KeyOnStA]
mov [KeyOnStB],al
mov byte[KeyOnStA],0
test byte[SfxSFR],20h
jnz near StartSFXdebugb
.returnfromsfx
add dh,[cycpl]
mov [pdh],dh
cmp byte[spcon],0
je .nosound
call updatetimer
push ebx
xor ebx,ebx
mov bl,dl
mov edi,[tablead+ebx*4]
pop ebx
.nosound
xor dh,dh
inc word[curypos]
mov ax,[resolutn]
inc ax
cmp word[curypos],ax
je near .nmi
mov ax,[totlines]
cmp word[curypos],ax
jae near .overy
; check for VIRQ/HIRQ/NMI
ProcessIRQStuff
; test dl,04h
; jnz .noirq
; test byte[INTEnab],20h
; jz .novirq
; mov ax,[VIRQLoc]
; cmp word[curypos],ax
; je near .virq
; jmp .noirq
;.novirq
; test byte[INTEnab],10h
; jnz near .virq
;.noirq
; test byte[INTEnab],20h
; jz .novirq2b
; mov ax,[VIRQLoc]
; cmp word[curypos],ax
; jne .novirq2b
; cmp byte[intrset],1
; jne .nointrset2b
; mov byte[intrset],2
;.nointrset2b
;.novirq2b
mov ax,[resolutn]
cmp word[curypos],ax
jb .drawline
jmp dword near [edi+ebx*4]
.drawline
cmp byte[hdmadelay],0
je .dohdma
dec byte[hdmadelay]
jmp .nodohdma
.dohdma
call exechdma
.nodohdma
cmp byte[curblank],0
jne .nodrawlineb
call drawline
.nodrawlineb
jmp dword near [edi+ebx*4]
.nmi
mov byte[irqon],80h
cmp byte[C4Enable],0
je .noC4
call C4VBlank
.noC4
; mov byte[hdmastartsc],0
mov byte[joycontren],0
mov ax,[VIRQLoc]
cmp word[curypos],ax
jne .novirqz
inc word[VIRQLoc]
.novirqz
call ReadInputDevice
test byte[INTEnab],1
jz .noresetjoy
mov eax,[JoyAOrig]
rol eax,16
mov [JoyANow],eax
mov eax,[JoyBOrig]
rol eax,16
mov [JoyBNow],eax
mov eax,[JoyCOrig]
rol eax,16
mov [JoyCNow],eax
mov eax,[JoyDOrig]
mov [JoyDNow],eax
mov byte[JoyCRead],0
.noresetjoy
cmp byte[snesmouse],4
jne .nolethalen
mov eax,[LethEnData]
mov [JoyBNow],eax
.nolethalen
mov byte[MultiTapStat],80h
mov byte[NMIEnab],81h
test byte[INTEnab],80h
jz .nonmi
mov byte[curnmi],1
dec esi
cmp byte[intrset],1
jne .nointrset
mov byte[intrset],2
.nointrset
jmp switchtonmideb
.nonmi
cmp byte[intrset],1
jne .nointrset2w
mov byte[intrset],2
.nointrset2w
cmp byte[esi],0CBh
jne .nowai
and dl,0FBh
.nowai
jmp dword near [edi+ebx*4]
.overy
shr dh,1
mov word[curypos],0
xor byte[ppustatus],80h
mov byte[NMIEnab],01h
add dword[opcd],170*262
call cachevideo
call starthdma
ProcessIRQStuff
; test dl,04h
; jnz .novirq2
; test byte[INTEnab],20h
; jz .novirq2
; mov ax,[VIRQLoc]
; cmp word[curypos],ax
; je near .virq
; mov ax,[VIRQLoc]
; cmp ax,[totlines]
; jae .virq
;.novirq2
jmp dword near [edi+ebx*4]
.virq
mov ax,[resolutn]
cmp word[curypos],ax
jnb .nodrawline
cmp byte[hdmadelay],0
je .dohdma2
dec byte[hdmadelay]
jmp .nodohdma2
.dohdma2
call exechdma
.nodohdma2
cmp byte[curblank],0
jne .nodrawline
call drawline
.nodrawline
dec esi
cmp byte[intrset],1
jne .nointrset2
mov byte[intrset],2
.nointrset2
jmp switchtovirqdeb