;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,MessageOn EXTSYM MsgCount,Msgptr,StartGUI,cbitmode,debuggeron,romdata,initvideo,newgfx16b EXTSYM cvidmode,vidbuffer,vidbufferofsa,disable65816sh,GUISaveVars,virqnodisable EXTSYM KeySaveState,KeyLoadState,KeyQuickExit,KeyQuickLoad,KeyQuickRst EXTSYM GUIDoReset,GUIReset,KeyOnStA,KeyOnStB,ProcessKeyOn,C4Enable,KeyQuickClock EXTSYM KeyQuickSaveSPC,TimerEnable,IRQHack,HIRQLoc,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,copyvid 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,SlowDownLock %ifdef __MSDOS__ EXTSYM dssel %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 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 ProcessIRQStuffB 0 ; check for VIRQ/HIRQ/NMI 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 %endmacro %macro ProcessIRQStuffC 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 %%startirq cmp byte[intrset],1 jne %%nointrseta mov byte[intrset],2 %%nointrseta mov byte[irqon],80h test dl,04h jnz %%irqd test byte[INTEnab],10h jnz %%tryhirq jmp .virq %%novirq test byte[INTEnab],10h jz %%noirq %%tryhirq jmp .virq jmp %%startirq %%irqd mov byte[doirqnext],1 %%noirq %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 abcdefg, dd 0 NEWSYM abcdefg1, dd 0 NEWSYM abcdefg2, dd 0 NEWSYM abcdefg3, dd 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 NEWSYM start65816 call initvideo cmp byte[videotroub],1 jne .notrouble ret .notrouble jmp .nonewgfxcheck cmp byte[cbitmode],1 jne .nonewgfxcheck cmp byte[newengen],1 jne .nonewgfxcheck cmp byte[cvidmode],3 jne .nocorrectmode cmp byte[newgfx16b],1 je .nonewgfxcheck jmp .correctmode .nocorrectmode mov dword[Msgptr],newgfxerror2 jmp .correctmode mov dword[Msgptr],newgfxerror .correctmode mov eax,[MsgCount] mov [MessageOn],eax mov byte[newengen],0 .nonewgfxcheck 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 jmp .nomovie .movie mov edi,[tableadc+ebx*4] test byte[curexecstate],2 jnz .nomovie mov edi,[tableadb+ebx*4] .nomovie mov ebp,[spcPCRam] mov byte[NoSoundReinit],0 mov byte[csounddisable],0 mov byte[NextNGDisplay],0 call splitflags ; cmp byte[MovieProcessing],0 ; jne .movie2 call execute jmp .nomovie2 .movie2 call cpuover.returntoloop .nomovie2 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 NEWSYM Game60hzcall inc word[t1cc] inc byte[nextframe] 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],0h 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[INCRFrame],1 jne .noframeincr xor byte[INCRFrame],1 jmp .noemupause .noframeincr cmp byte[EMUPause],1 jne .noemupause mov byte[SlowDownLock],0 ; prevents some random desyncs call ProcessRewind ;Update screen (we should also kill sound) pushad call showvideo popad ;jmp .nocache 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 cmp byte[esi],0CBh jne .nowai jmp .nowai test dl,04h jz .nowai or byte[INTEnab],80h .nowai 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[INTEnab],10h jz .skiphirq cmp word[HIRQLoc],0 je .skiphirq jmp .skiphirq cmp word[HIRQLoc],339 jbe .hirqnotover mov word[HIRQLoc],339 .hirqnotover ; first dh = HIRQLoc*DHAdd/340, second dh = DHAdd-first dh push edx mov ax,[HIRQLoc] xor ecx,ecx mov cl,[cycpl] mul cx mov cx,340 div cx pop edx mov dh,al mov cl,[cycpl] sub cl,al xor cl,cl mov [HIRQCycNext],cl mov byte[HIRQNextExe],1 ; jmp .hirq jmp .returnfromhirq .skiphirq 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