📄 spc700.asm
字号:
;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 DSPMem,spcWptr,disablespcclr,SPCSkipXtraROM,cycpbl,spcRptrEXTSYM spc700read,dspWptr,curexecstate,tableadc%include "cpu/regsw.mac"%include "cpu/spcdef.inc"%include "cpu/spcaddr.inc"; SPC 700 Emulation by _Demo_; Version 2.0; Little info on functions :; Write byte : write al at [ebx]; Read byte : read al from [ebx]; update timer : update the timers, called every scanlineSECTION .dataALIGN32;spcBuffer times 65536*4 db 0 ; The buffer of brr blocks... 4 bits -> 16 bits;spcPrevbf times 65536 db 0 ; SPC PrevX compare bufferNEWSYM SPCRAM, times 65472 db 0FFh ; Pointer to the SPC's RAM; copy #1; THE SPC ROM :) db 0CDh,0EFh,0BDh,0E8h,000h,0C6h,01Dh,0D0h,0FCh,08Fh,0AAh,0F4h,08Fh,0BBh,0F5h,078h db 0CCh,0F4h,0D0h,0FBh,02Fh,019h,0EBh,0F4h,0D0h,0FCh,07Eh,0F4h,0D0h,00Bh,0E4h,0F5h db 0CBh,0F4h,0D7h,000h,0FCh,0D0h,0F3h,0ABh,001h,010h,0EFh,07Eh,0F4h,010h,0EBh,0BAh db 0F6h,0DAh,000h,0BAh,0F4h,0C4h,0F4h,0DDh,05Dh,0D0h,0DBh,01Fh,000h,000h,0C0h,0FFh db 0AAh,0BBh,0CCh,0DDh,0EEh,0FFh,000h,011h,022h,033h,044h,055h,066h,077h,088h,099hNEWSYM spcPCRam, dd 0 ; Program Counter (with SPCRAM added)NEWSYM spcA, db 0 ; The A register (general purpose) db 0 db 0 db 0NEWSYM spcX, db 0 ; The X register (general purpose) db 0 db 0 db 0NEWSYM spcY, db 0 ; The Y register (general purpose) db 0 db 0 db 0NEWSYM spcP, db 0 ; The processor status byte (Removed for each flags) db 0 ; NZ are not always processed... db 0 db 0NEWSYM spcNZ, db 0 ; The processor NZ flag (little speed up hack :) ) db 0 db 0 db 0;spcNF db 0 ; The Negative Flag 128 or 127;spcOF db 0 ; The Overflow Flag 64 or 191;spcDPF db 0 ; Direct Page Flag 32 or 223;spcUF db 0 ; The Unused Flag ? 16 or 239;spcHCF db 0 ; The Half Carry Flag 8 or 247;spcIF db 0 ; The interrupt flag 4 or 251;spcZF db 0 ; The Zero Flag 2 or 253;spcCF db 0 ; The Carry Flag 1 or 254NEWSYM spcS, dd 1FFh ; The stack pointer (always from 100 to 1FF) (added Ram)NEWSYM spcRamDP, dd 0 ; The direct page pointerNEWSYM spcCycle, dd 0 ; The Cycle CounterNEWSYM reg1read, db 0 ; read from 65816NEWSYM reg2read, db 0 ; read from 65816NEWSYM reg3read, db 0 ; read from 65816NEWSYM reg4read, db 0 ; read from 65816NEWSYM timeron, db 0 ; timer0 onNEWSYM timincr0, db 0 ; # of ticks before incrementingNEWSYM timincr1, db 0 ; # of ticks before incrementingNEWSYM timincr2, db 0 ; # of ticks before incrementingNEWSYM timinl0, db 0 ; ticks left before incrementingNEWSYM timinl1, db 0 ; ticks left before incrementingNEWSYM timinl2, db 0 ; ticks left before incrementingNEWSYM timrcall, db 0 ; alternating bit 0 to correctly timer timer1 & 2 to 8000hzNEWSYM spcextraram, times 64 db 0 ; extra ram, used for tcallNEWSYM FutureExpandS, times 256-64 db 0spcsave equ $-SPCRAM; pharos equ hack *sigh*NEWSYM PHspcsave, dd spcsave; copy #2NEWSYM SPCROM db 0CDh,0EFh,0BDh,0E8h,000h,0C6h,01Dh,0D0h,0FCh,08Fh,0AAh,0F4h,08Fh,0BBh,0F5h,078h db 0CCh,0F4h,0D0h,0FBh,02Fh,019h,0EBh,0F4h,0D0h,0FCh,07Eh,0F4h,0D0h,00Bh,0E4h,0F5h db 0CBh,0F4h,0D7h,000h,0FCh,0D0h,0F3h,0ABh,001h,010h,0EFh,07Eh,0F4h,010h,0EBh,0BAh db 0F6h,0DAh,000h,0BAh,0F4h,0C4h,0F4h,0DDh,05Dh,0D0h,0DBh,01Fh,000h,000h,0C0h,0FFhSECTION .text%macro WriteByte 0 cmp ebx,0ffh+SPCRAM ja %%extramem cmp ebx,0f0h+SPCRAM jb %%normalmem sub ebx,SPCRAM call dword near [spcWptr+ebx*4-0f0h*4] jmp %%finished%%extramem cmp ebx,0ffc0h+SPCRAM jb %%normalmem mov [spcextraram+ebx-0FFC0h-SPCRAM],al test byte[SPCRAM+0F1h],80h jnz %%finished; push ecx; mov cl,[DSPMem+06Ch]; test cl,20h; pop ecx; jz .finished%%normalmem mov [ebx],al%%finished%endmacro%macro ReadByte 0 cmp ebx,0f0h+SPCRAM jb %%normalmem2 cmp ebx,0ffh+SPCRAM ja %%normalmem sub ebx,SPCRAM call dword near [spcRptr+ebx*4-0f0h*4] jmp %%finished%%normalmem; cmp ebx,0ffc0h+SPCRAM; jb .rnormalmem2; test byte[DSPMem+6Ch],10h; jz .rnormalmem2; mov al,[spcextraram+ebx-0FFC0h-SPCRAM]; jmp .rfinished%%normalmem2 mov al,[ebx]%%finished%endmacro%macro ReadByte2 0 cmp ebx,0f0h+SPCRAM jb %%normalmem2 cmp ebx,0ffh+SPCRAM ja %%normalmem sub ebx,SPCRAM call dword near [spcRptr+ebx*4-0f0h*4] add ebx,SPCRAM jmp %%finished%%normalmem; cmp ebx,0ffc0h+SPCRAM; jb .rnormalmem2; test byte[DSPMem+6Ch],10h; jz .rnormalmem2; mov al,[spcextraram+ebx-0FFC0h-SPCRAM]; jmp .rfinished%%normalmem2 mov al,[ebx]%%finished%endmacroSECTION .dataNEWSYM timer2upd, dd 0SECTION .text; This function is called every scanline (262*60 times/sec); Make it call 0.9825 times (393/400) (skip when divisible by 64); 2 8khz, 1 64khzNEWSYM updatetimer; inc dword[timer2upd]; cmp dword[timer2upd],400; jne .nowrap; mov dword[timer2upd],0;.nowrap;.again; mov eax,dword[timer2upd]; shr eax,6; shl eax,6; cmp eax,dword[timer2upd]; je near .noin2d.another xor byte[timrcall],01h test byte[timrcall],01h jz near .notimer test byte[timeron],1 jz .noin0 dec byte[timinl0] jnz .noin0 inc byte[SPCRAM+0FDh] mov al,[timincr0] mov [timinl0],al cmp byte[SPCRAM+0FDh],1 jne .noin0 reenablespc mov dword[cycpbl],0.noin0 test byte[timeron],2 jz .noin1 dec byte[timinl1] jnz .noin1 inc byte[SPCRAM+0FEh] mov al,[timincr1] mov [timinl1],al cmp byte[SPCRAM+0FEh],1 jne .noin1 reenablespc mov dword[cycpbl],0.noin1.notimer test byte[timeron],4 jz near .noin2d2 dec byte[timinl2] jnz .noin2 inc byte[SPCRAM+0FFh] mov al,[timincr2] mov [timinl2],al cmp byte[SPCRAM+0FFh],1 jne .noin2 reenablespc mov dword[cycpbl],0.noin2 dec byte[timinl2] jnz .noin2b inc byte[SPCRAM+0FFh] mov al,[timincr2] mov [timinl2],al cmp byte[SPCRAM+0FFh],1 jne .noin2b reenablespc mov dword[cycpbl],0.noin2b dec byte[timinl2] jnz .noin2c inc byte[SPCRAM+0FFh] mov al,[timincr2] mov [timinl2],al cmp byte[SPCRAM+0FFh],1 jne .noin2c reenablespc mov dword[cycpbl],0.noin2c dec byte[timinl2] jnz .noin2d inc byte[SPCRAM+0FFh] mov al,[timincr2] mov [timinl2],al cmp byte[SPCRAM+0FFh],1 jne .noin2d reenablespc mov dword[cycpbl],0.noin2d.noin2d2; inc dword[timer2upd]; cmp dword[timer2upd],31; jne .nowrap; mov dword[timer2upd],0; jmp .again;.nowrap inc dword[timer2upd] cmp dword[timer2upd],60 jne .noanother mov dword[timer2upd],0 jmp .another.noanother ret; SPC Write Registers; DO NOT MODIFY DX OR ECX!NEWSYM SPCRegF0 mov [SPCRAM+0F0h],al retNEWSYM SPCRegF1 cmp byte[disablespcclr],1 je .No23Clear test al,10h jz .No01Clear mov byte[SPCRAM+0F4h],0 mov byte[SPCRAM+0F5h],0.No01Clear test al,20h jz .No23Clear mov byte[SPCRAM+0F6h],0 mov byte[SPCRAM+0F7h],0.No23Clear cmp byte[SPCSkipXtraROM],1 je near .AfterNoROM test al,80h jz .NoROM push eax push ebx xor eax,eax.loopa mov bl,[SPCROM+eax] mov [SPCRAM+0FFC0h+eax],bl inc eax cmp eax,040h jne .loopa pop ebx pop eax jmp .AfterNoROM.NoROM push eax push ebx xor eax,eax.loopb mov bl,[spcextraram+eax] mov [SPCRAM+0FFC0h+eax],bl inc eax cmp eax,040h jne .loopb pop ebx pop eax.AfterNoROM mov [SPCRAM+0F1h],al and al,0Fh mov [timeron],al retNEWSYM SPCRegF2 mov [SPCRAM+0F2h],al push eax push ebx xor eax,eax mov al,[SPCRAM+0F2h] mov bl,[DSPMem+eax] mov [SPCRAM+0F3h],bl pop ebx pop eax retNEWSYM SPCRegF3 push ebx xor ebx,ebx mov bl,[SPCRAM+0F2h] and bl,07fh call dword near [dspWptr+ebx*4] pop ebx mov [SPCRAM+ebx],al retNEWSYM SPCRegF4 mov [reg1read],al inc dword[spc700read] retNEWSYM SPCRegF5 mov [reg2read],al inc dword[spc700read] retNEWSYM SPCRegF6 mov [reg3read],al inc dword[spc700read] retNEWSYM SPCRegF7 mov [reg4read],al inc dword[spc700read] retNEWSYM SPCRegF8 mov [SPCRAM+ebx],al retNEWSYM SPCRegF9 mov [SPCRAM+ebx],al retNEWSYM SPCRegFA mov [timincr0],al test byte[timinl0],0FFh jne .nowrite mov [timinl0],al.nowrite mov [SPCRAM+ebx],al retNEWSYM SPCRegFB mov [timincr1],al test byte[timinl1],0FFh jne .nowrite mov [timinl1],al.nowrite mov [SPCRAM+ebx],al retNEWSYM SPCRegFC mov [timincr2],al test byte[timinl2],0FFh jne .nowrite mov [timinl2],al.nowrite mov [SPCRAM+ebx],al retNEWSYM SPCRegFD retNEWSYM SPCRegFE retNEWSYM SPCRegFF ret; SPC Read Registers; DO NOT MODIFY ANY REG!; return data true alNEWSYM RSPCRegF0 mov al,[SPCRAM+0f0h] retNEWSYM RSPCRegF1 mov al,[SPCRAM+0f1h] retNEWSYM RSPCRegF2 mov al,[SPCRAM+0f2h] retNEWSYM RSPCRegF3 mov al,[SPCRAM+0f3h] retNEWSYM RSPCRegF4 mov al,[SPCRAM+0f4h] retNEWSYM RSPCRegF5 mov al,[SPCRAM+0f5h] retNEWSYM RSPCRegF6 mov al,[SPCRAM+0f6h] retNEWSYM RSPCRegF7 mov al,[SPCRAM+0f7h] retNEWSYM RSPCRegF8 mov al,0 ;[SPCRAM+0f8h] retNEWSYM RSPCRegF9 mov al,0 ;[SPCRAM+0f9h] retNEWSYM RSPCRegFA mov al,[SPCRAM+0fah] retNEWSYM RSPCRegFB mov al,[SPCRAM+0fbh] retNEWSYM RSPCRegFC mov al,[SPCRAM+0fch] retNEWSYM RSPCRegFD mov al,[SPCRAM+0fdh] and al,0Fh mov byte[SPCRAM+0fdh],0 mov byte[spcnumread],0 retNEWSYM RSPCRegFE mov al,[SPCRAM+0feh] and al,0Fh mov byte[SPCRAM+0feh],0 mov byte[spcnumread],0 retNEWSYM RSPCRegFF mov al,[SPCRAM+0ffh] and al,0Fh mov byte[SPCRAM+0ffh],0 mov byte[spcnumread],0 retSECTION .dataNEWSYM spcnumread, db 0SECTION .text%macro SPCSetFlagnzc 0 js .setsignflag jz .setzeroflag mov byte[spcNZ],1 jc .setcarryflag and byte[spcP],0FEh ret.setsignflag mov byte[spcNZ],80h jc .setcarryflag and byte[spcP],0FEh ret.setzeroflag mov byte[spcNZ],0 jc .setcarryflag and byte[spcP],0FEh ret.setcarryflag or byte[spcP],1 ret%endmacro%macro SPCSetFlagnzcnoret 0 js .setsignflag jz .setzeroflag mov byte[spcNZ],1 jc .setcarryflag and byte[spcP],0FEh jmp .skipflags.setsignflag mov byte[spcNZ],80h jc .setcarryflag and byte[spcP],0FEh jmp .skipflags.setzeroflag mov byte[spcNZ],0 jc .setcarryflag and byte[spcP],0FEh jmp .skipflags.setcarryflag or byte[spcP],1.skipflags%endmacro%macro SPCSetFlagnvhzc 0 lahf js .setsignflag jz .setzeroflag mov byte[spcNZ],1 jo .setoverflowflag and byte[spcP],0BFh jmp .skipflags.setsignflag mov byte[spcNZ],80h jo .setoverflowflag and byte[spcP],0BFh jmp .skipflags.setzeroflag mov byte[spcNZ],0 jo .setoverflowflag and byte[spcP],0BFh jmp .skipflags.setoverflowflag or byte[spcP],40h.skipflags and byte[spcP],0F6h test ah,01h jz .noCarry or byte[spcP],1.noCarry test ah,10h jz .nohf or byte[spcP],8.nohf ret%endmacro%macro SPCSetFlagnvhzcnoret 0 lahf js .setsignflag jz .setzeroflag mov byte[spcNZ],1 jo .setoverflowflag and byte[spcP],0BFh jmp .skipflags.setsignflag mov byte[spcNZ],80h jo .setoverflowflag and byte[spcP],0BFh jmp .skipflags.setzeroflag mov byte[spcNZ],0 jo .setoverflowflag and byte[spcP],0BFh jmp .skipflags.setoverflowflag or byte[spcP],40h.skipflags and byte[spcP],0F6h test ah,01h jz .noCarry or byte[spcP],1.noCarry test ah,10h jz .nohf or byte[spcP],8.nohf%endmacro;************************************************; Misc Opcodes;************************************************NEWSYM Op00 ; NOP retNEWSYM OpEF ; SLEEP standby SLEEP mode ......... dec ebp retNEWSYM OpFF ; STOP standby STOP mode ......... inc dword[spc700read] dec ebp retNEWSYM Op9F ; XCN A A(7-4) <-> A(3-0) N......Z. ror byte[spcA],4 mov al,[spcA] mov [spcNZ],al ret;************************************************; Branch Stuff;************************************************NEWSYM Op10 ; BPL Branch on N=0 test byte[spcNZ],128 jz .branch spcbrancherNEWSYM Op30 ; BMI Branch on N=1 test byte[spcNZ],128 jnz .branch spcbrancherNEWSYM Op50 ; BVC Branch on V=0 test byte[spcP],64 jz .branch spcbrancherNEWSYM Op70 ; BVS Branch on V=1 test byte[spcP],64 jnz .branch spcbrancherNEWSYM Op90 ; BCC Branc on c=0 test byte[spcP],1 jz .branch spcbrancherNEWSYM OpB0 ; BCS Branch on C=1 test byte[spcP],1 jnz .branch spcbrancherNEWSYM OpD0 ; BNE branch on Z=0 test byte[spcNZ],255 jnz .branch spcbrancherNEWSYM OpF0 ; BEQ Branch on Z=1 test byte[spcNZ],0FFh jz .branch spcbrancherNEWSYM Op2F ; BRA rel branch always ... movsx ebx,byte[ebp] inc ebp add ebp,ebx ret;************************************************; Clear/Set Flag bits
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -