⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spc700.asm

📁 十七种模拟器源代码 非常有用的作课程设计不可缺少的
💻 ASM
📖 第 1 页 / 共 5 页
字号:
;Copyright (C) 1997-2001 ZSNES Team ( zsknight@zsnes.com / _demo_@zsnes.com )
;
;This program is free software; you can redistribute it and/or
;modify it under the terms of the GNU General Public License
;as published by the Free Software Foundation; either
;version 2 of the License, or (at your option) any later
;version.
;
;This program is distributed in the hope that it will be useful,
;but WITHOUT ANY WARRANTY; without even the implied warranty of
;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;GNU General Public License for more details.
;
;You should have received a copy of the GNU General Public License
;along with this program; if not, write to the Free Software
;Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

%include "macros.mac"

EXTSYM DSPMem,spcWptr,debstop,disablespcclr,SPCSkipXtraROM,SPC700sh
EXTSYM cycpbl,spcRptr
EXTSYM spc700read
EXTSYM dspWptr
EXTSYM changeexecloop,curexecstate,SA1Enable,tableadb

NEWSYM Spc700AsmStart

%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 scanline


ALIGN32

;spcBuffer times 65536*4 db 0      ; The buffer of brr blocks... 4 bits -> 16 bits
;spcRamcmp times 65536   db 0      ; SPC Ram compare buffer
;spcPrevbf times 65536   db 0      ; SPC PrevX compare buffer
NEWSYM 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,099h

NEWSYM spcPCRam,
         dd 0     ; Program Counter (with spcRam added)
NEWSYM spcA,
         db 0     ; The A register (general purpose)
         db 0
         db 0
         db 0
NEWSYM spcX,
         db 0     ; The X register (general purpose)
         db 0
         db 0
         db 0
NEWSYM spcY,
         db 0     ; The Y register (general purpose)
         db 0
         db 0
         db 0
NEWSYM spcP,
         db 0     ; The processor status byte (Removed for each flags)
         db 0     ; NZ are not always processed...
         db 0
         db 0
NEWSYM 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 254

NEWSYM spcS,     dd 1FFh   ; The stack pointer (always from 100 to 1FF) (added Ram)
NEWSYM spcRamDP, dd 0     ; The direct page pointer 
NEWSYM spcCycle, dd 0     ; The Cycle Counter
NEWSYM reg1read, db 0     ; read from 65816
NEWSYM reg2read, db 0     ; read from 65816
NEWSYM reg3read, db 0     ; read from 65816
NEWSYM reg4read, db 0     ; read from 65816
NEWSYM timeron,  db 0     ; timer0 on
NEWSYM timincr0, db 0     ; # of ticks before incrementing
NEWSYM timincr1, db 0     ; # of ticks before incrementing
NEWSYM timincr2, db 0     ; # of ticks before incrementing
NEWSYM timinl0,  db 0     ; ticks left before incrementing
NEWSYM timinl1,  db 0     ; ticks left before incrementing
NEWSYM timinl2,  db 0     ; ticks left before incrementing
NEWSYM timrcall, db 0     ; alternating bit 0 to correctly timer timer1 & 2 to 8000hz

NEWSYM spcextraram, times 64 db 0 ; extra ram, used for tcall

NEWSYM FutureExpandS,  times 256-64 db 0

spcsave equ $-spcRam
; pharos equ hack *sigh*
NEWSYM PHspcsave, dd spcsave

; copy #2
NEWSYM 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,0FFh

%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 .rnormalmem2
  cmp ebx,0ffh+spcRam
  ja .rnormalmem
  sub ebx,spcRam
  call dword near [spcRptr+ebx*4-0f0h*4]
  jmp .rfinished
.rnormalmem
;  cmp ebx,0ffc0h+spcRam
;  jb .rnormalmem2
;  test byte [DSPMem+6Ch],10h
;  jz .rnormalmem2
;  mov al,[spcextraram+ebx-0FFC0h-spcRam]
;  jmp .rfinished
.rnormalmem2
   mov al,[ebx]
.rfinished
%endmacro

%macro ReadByte2 0
  cmp ebx,0f0h+spcRam
  jb .rnormalmem2
  cmp ebx,0ffh+spcRam
  ja .rnormalmem
  sub ebx,spcRam
  call dword near [spcRptr+ebx*4-0f0h*4]
  add ebx,spcRam
  jmp .rfinished
.rnormalmem
;  cmp ebx,0ffc0h+spcRam
;  jb .rnormalmem2
;  test byte [DSPMem+6Ch],10h
;  jz .rnormalmem2
;  mov al,[spcextraram+ebx-0FFC0h-spcRam]
;  jmp .rfinished
.rnormalmem2
   mov al,[ebx]
.rfinished
%endmacro

NEWSYM timer2upd, dd 0
; 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 64khz

NEWSYM 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
      ret
NEWSYM 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
      ret
NEWSYM 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
      ret
NEWSYM 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
      ret
NEWSYM SPCRegF4
      mov [reg1read],al
      inc dword[spc700read]
      ret
NEWSYM SPCRegF5
      mov [reg2read],al
      inc dword[spc700read]
      ret
NEWSYM SPCRegF6
      mov [reg3read],al
      inc dword[spc700read]
      ret
NEWSYM SPCRegF7
      mov [reg4read],al
      inc dword[spc700read]
      ret
NEWSYM SPCRegF8
      mov [spcRam+ebx],al
      ret
NEWSYM SPCRegF9
      mov [spcRam+ebx],al
      ret
NEWSYM SPCRegFA
      mov [timincr0],al
      test byte[timinl0],0FFh
      jne .nowrite
      mov [timinl0],al
.nowrite
      mov [spcRam+ebx],al
      ret
NEWSYM SPCRegFB
      mov [timincr1],al
      test byte[timinl1],0FFh
      jne .nowrite
      mov [timinl1],al
.nowrite
      mov [spcRam+ebx],al
      ret
NEWSYM SPCRegFC
      mov [timincr2],al
      test byte[timinl2],0FFh
      jne .nowrite
      mov [timinl2],al
.nowrite
      mov [spcRam+ebx],al
      ret
NEWSYM SPCRegFD
      ret
NEWSYM SPCRegFE
      ret
NEWSYM SPCRegFF
      ret

; SPC Read Registers
; DO NOT MODIFY ANY REG!
; return data true al
NEWSYM RSPCRegF0
      mov al,[spcRam+0f0h]
      ret
NEWSYM RSPCRegF1
      mov al,[spcRam+0f1h]
      ret
NEWSYM RSPCRegF2
      mov al,[spcRam+0f2h]
      ret
NEWSYM RSPCRegF3
      mov al,[spcRam+0f3h]
      ret
NEWSYM RSPCRegF4
      mov al,[spcRam+0f4h]
      ret
NEWSYM RSPCRegF5
      mov al,[spcRam+0f5h]
      ret
NEWSYM RSPCRegF6
      mov al,[spcRam+0f6h]
      ret
NEWSYM RSPCRegF7
      mov al,[spcRam+0f7h]
      ret
NEWSYM RSPCRegF8
      mov al,0 ;[spcRam+0f8h]
      ret
NEWSYM RSPCRegF9
      mov al,0 ;[spcRam+0f9h]
      ret
NEWSYM RSPCRegFA
      mov al,[spcRam+0fah]
      ret
NEWSYM RSPCRegFB
      mov al,[spcRam+0fbh]
      ret
NEWSYM RSPCRegFC
      mov al,[spcRam+0fch]
      ret
NEWSYM RSPCRegFD
      mov al,[spcRam+0fdh]
      and al,0Fh
      cmp byte[spcRam+0fdh],0
      je spcnextskip
      mov byte [spcRam+0fdh],0
      mov byte [spcnumread],0
      ret
NEWSYM RSPCRegFE
      mov al,[spcRam+0feh]
      and al,0Fh
      cmp byte[spcRam+0feh],0
      je spcnextskip
      mov byte [spcRam+0feh],0
      mov byte [spcnumread],0
      ret
NEWSYM RSPCRegFF
      mov al,[spcRam+0ffh]
      and al,0Fh
      cmp byte[spcRam+0ffh],0
      je spcnextskip
      mov byte [spcRam+0ffh],0
      mov byte [spcnumread],0
      ret
NEWSYM spcnextskip
      inc byte[spcnumread]
      cmp byte[spcnumread],5
      je near haltspc
      ret

NEWSYM haltspc
      cmp byte[SPC700sh],1
      je .nochangestate
      mov dword[cycpbl],0FFFFFFFFh
      test byte[curexecstate],02h
      jz .nochangestate
      and byte[curexecstate],0FDh
      push ebx
      xor ebx,ebx
      mov bl,dl
      mov edi,[tableadb+ebx*4]
      pop ebx
.nochangestate
      mov byte[spcnumread],0
      ret

NEWSYM spcnumread, db 0


%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

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -