execute.asm
来自「linux下的任天堂模拟器代码。供大家参考。」· 汇编 代码 · 共 2,207 行 · 第 1/3 页
ASM
2,207 行
;Copyright (C) 1997-2007 ZSNES Team ( zsKnight, _Demo_, pagefault, Nach );;http://www.zsnes.com;http://sourceforge.net/projects/zsnes;https://zsnes.bountysource.com;;This program is free software; you can redistribute it and/or;modify it under the terms of the GNU General Public License;version 2 as published by the Free Software Foundation.;;This program is distributed in the hope that it will be useful,;but WITHOUT ANY WARRANTY; without even the implied warranty of;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the;GNU General Public License for more details.;;You should have received a copy of the GNU General Public License;along with this program; if not, write to the Free Software;Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.%include "macros.mac"EXTSYM KeyRewind,statesaver,Voice0Status,UpdateDPageEXTSYM StartGUI,romdata,initvideo,DosExit,sfxramdata,deinitvideoEXTSYM vidbufferofsa,device2,RawDumpInProgressEXTSYM KeySaveState,KeyLoadState,KeyQuickExit,KeyQuickLoad,KeyQuickRstEXTSYM GUIDoReset,GUIReset,KeyOnStA,KeyOnStB,ProcessKeyOn,C4Enable,KeyQuickClockEXTSYM KeyQuickSaveSPC,TimerEnable,splitflags,joinflagsEXTSYM KeyQuickSnapShot,csounddisable,videotroub,ResetTripleBufEXTSYM InitPreGame,Curtableaddr,curcyc,debugdisble,dmadata,guioff,memtabler8EXTSYM SetupPreGame,memtablew8,regaccessbankr8,showmenu,snesmap2,snesmmapEXTSYM DeInitPostGame,spcPCRam,xp,xpb,xpc,tableadEXTSYM tableadc,SA1UpdateDPage,Makemode7Table,nextmenupopup,MovieProcessingEXTSYM SFXEnable,wramdata,cycpbl,cycpblt,irqon,spconEXTSYM multchange,romispal,scrndis,sprlefttot,sprleftpr,processspritesEXTSYM cachesprites,opcjmptab,CheatOn,Output_Text,Check_Key,Get_Key,EXTSYM INTEnab,JoyCRead,NMIEnab,NumCheats,CurrentExecSA1,ReadInputDeviceEXTSYM StartDrawNewGfx,VIRQLoc,cachevideo,cfield,cheatdata,curblank,curnmiEXTSYM curypos,cycpl,doirqnext,drawline,exechdma,hdmadelay,intrset,newengenEXTSYM oamaddr,oamaddrs,resolutn,showvideo,starthdma,switchtonmiEXTSYM switchtovirq,totlines,updatetimer,SA1Swap,SA1DoIRQ,JoyAOrig,JoyANowEXTSYM JoyBOrig,JoyBNow,JoyCOrig,JoyCNow,JoyDOrig,JoyDNow,JoyEOrig,JoyENowEXTSYM SA1Message,MultiTapStat,idledetectspc,SA1Control,SA1Enable,SA1IRQEnableEXTSYM SPC700read,SPC700write,numspcvblleft,spc700idle,SA1IRQExec,ForceNewGfxOffEXTSYM LethEnData,GUIQuit,IRAM,SA1Ptr,SA1BWPtr,outofmemfixEXTSYM yesoutofmemory,ProcessMovies,MovieStop,ppustatus,C4VBlankEXTSYM ReturnFromSPCStall,scanlines,MainLoop,MoviePassWaiting,MovieDumpRawEXTSYM NumberOfOpcodes,SfxCLSR,SfxSCMR,SfxPOR,sfx128lineloc,sfx160linelocEXTSYM sfx192lineloc,sfxobjlineloc,sfxclineloc,PLOTJmpa,PLOTJmpb,FxTableEXTSYM FxTableb,FxTablec,FxTabled,SfxPBR,SCBRrel,SfxSCBR,SfxCOLR,SFXCounterEXTSYM fxbit01,fxbit01pcal,fxbit23,fxbit23pcal,fxbit45,fxbit45pcal,fxbit67EXTSYM fxbit67pcal,SfxSFR,nosprincr,cpucycle,switchtovirqdeb,switchtonmidebEXTSYM MovieSeekBehind,BackupCVFrame,RestoreCVFrame,loadstateEXTSYM KeyInsrtChap,KeyNextChap,KeyPrevChap,MovieInsertChapter,MovieSeekAheadEXTSYM ResetDuringMovie,EMUPauseKey,INCRFrameKey,MovieWaiting,NoInputReadEXTSYM AllocatedRewindStates,PauseFrameMode,RestorePauseFrame,BackupPauseFrame%ifndef NO_DEBUGGEREXTSYM debuggeron,startdebugger%endif%ifdef __MSDOS__EXTSYM dssel,Game60hzcall,NextLineStart,FlipWait,LastLineStart,smallscreenon,ScreenScaleEXTSYM cvidmode,GUI16VID,ScreenShotFormat%endifSECTION .dataNEWSYM tempedx, dd 0NEWSYM tempesi, dd 0NEWSYM tempedi, dd 0NEWSYM tempebp, dd 0NEWSYM RewindTimer, dd 0NEWSYM BackState, db 1NEWSYM BackStateSize, dd 6NEWSYM DblRewTimer, dd 0SECTION .textNEWSYM ProcessRewind mov eax,[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 call UpdateDPage mov esi,[tempesi] mov edi,[tempedi] mov ebp,[tempebp] mov edx,[tempedx].notokay retNEWSYM UpdateRewind cmp byte[AllocatedRewindStates],0 je .norewinds cmp dword[KeyRewind],0 je .norewinds dec dword[DblRewTimer] dec dword[RewindTimer] jnz .checkrewind mov [tempedx],edx mov [tempesi],esi mov [tempedi],edi mov [tempebp],ebp pushad call BackupCVFrame popad.checkrewind call ProcessRewind call UpdateDPage.norewinds retSECTION .dataNEWSYM MuteVoiceF, dd 0SECTION .textVoiceEndMute: mov byte[MuteVoiceF],0 ret%macro StartMute 1 mov al,[Voice0Status+%1] or al,al jz %%notmuted or byte[MuteVoiceF],1 << %1%%notmuted%endmacroVoiceStartMute: 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 test dl,04h jnz %%virqdo cmp byte[doirqnext],1 je near .virq%%virqdo test byte[INTEnab],20h jz near %%novirq mov ax,[VIRQLoc] 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 mov byte[doirqnext],1 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 executedSECTION .dataNEWSYM romloadskip, db 0NEWSYM SSKeyPressed, dd 0NEWSYM SPCKeyPressed, dd 0NEWSYM NoSoundReinit, dd 0NEWSYM NextNGDisplay, db 0NEWSYM TempVidInfo, dd 0NEWSYM tempdh, db 0SECTION .text; this wonderful mess starts up the CPU and initialized the emulation stateNEWSYM 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 StartGUINEWSYM 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%ifndef NO_DEBUGGER mov byte[debuggeron],0%endif mov byte[exiter],0 call InitPreGame jmp reexecuteNEWSYM continueprognokeys mov byte[romloadskip],0%ifndef NO_DEBUGGER mov byte[debuggeron],0%endif mov byte[exiter],0 call InitPreGame jmp reexecuteb2; IncorrectNEWSYM reexecuteb%ifndef __MSDOS__ jmp reexecuteb2%endifNEWSYM 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 .loopareexecuteb2: 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 mov edi,[tableadc+ebx*4] or byte[curexecstate],2 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 ;Multipass Movies cmp byte[MoviePassWaiting],1 jne .nomoviepasswaiting pushad call MovieDumpRaw popad jmp continueprog.nomoviepasswaiting ; 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%ifndef NO_DEBUGGER cmp byte[debugdisble],0 jne .nodebugger test byte[pressed+59],1 jne near startdebugger.nodebugger%endif 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 StartGUINEWSYM endprog call deinitvideo pushad call MovieStop popad jmp DosExitNEWSYM interror stim call deinitvideo mov edx,.nohand ;use extended mov ah,9 ;DOS- API call Output_Text ;to print a string jmp DosExitSECTION .data.nohand db 'Cannot process interrupt handler!',13,10,0; global variablesNEWSYM invalid, db 0NEWSYM invopcd, db 0NEWSYM pressed, times 256+128+64 db 0 ; keyboard pressed keys in scancodeNEWSYM exiter, db 0NEWSYM oldhand9o, dd 0NEWSYM oldhand9s, dw 0NEWSYM oldhand8o, dd 0NEWSYM oldhand8s, dw 0NEWSYM opcd, dd 0NEWSYM pdh, dd 0NEWSYM pcury, dd 0NEWSYM timercount, dd 0NEWSYM initaddrl, dd 0 ; initial address locationNEWSYM NetSent, dd 0NEWSYM nextframe, dd 0 ; tick count for timerNEWSYM 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',0NEWSYM HIRQCycNext, dd 0NEWSYM HIRQNextExe, db 0SECTION .text;*******************************************************; Int 08h vector;*******************************************************; sets to either 60Hz or 50Hz depending on PAL/NTSCNEWSYM 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 retNEWSYM 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%endifSECTION .dataNEWSYM timeradj, dd 65536NEWSYM t1cc, dw 0SECTION .text;*******************************************************; Int 09h vector;*******************************************************%ifdef __MSDOS__SECTION .bssNEWSYM skipnextkey42, resb 1SECTION .textNEWSYM 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%endifSECTION .dataALIGN32NEWSYM soundcycleft, dd 0NEWSYM curexecstate, dd 0NEWSYM nmiprevaddrl, dd 0 ; observed address -5NEWSYM nmiprevaddrh, dd 0 ; observed address +5NEWSYM nmirept, dd 0 ; NMI repeat check, if 6 then okayNEWSYM nmiprevline, dd 224 ; previous lineNEWSYM nmistatus, dd 0 ; 0 = none, 1 = waiting for nmi location, ; 2 = found, disable at next lineNEWSYM joycontren, dd 0 ; joystick read control checkNEWSYM NextLineCache, db 0NEWSYM ZMVZClose, db 0SECTION .textDonextlinecache: 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;*******************************************************
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?