Files
ZSNES/zsnes/src/chips/sa1regs.asm
2001-04-10 04:28:44 +00:00

2580 lines
53 KiB
NASM

;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.
; SPC7110 emulation. Information fully reverse engineered
; by Dark Force and John Weidman, ZSNES code by zsKnight
; SA-1 emulation. Information provided by Ivar of Snes9x.
; coded by zsKnight
; SDD-1 emulation. SDD-1 MMC reverse engineered by zsKnight,
; SDD-1 decompress Dark Force and John Weidman,
; - Add MMC support
; - Add end of DMA IRQ support
; - Add Char Conversion #1
; - Add Char Conversion #2
; - Add Memory Disables (Guess this isn't needed)
; IRQs - IRQ Clear (also clear 2300), IRQ Disable, and IRQ Enable
; Mario RPG Level-up not working - it was using one of the IRQ functions
; that no other place in the game is using, which I suppose is the cause
; of the problem, but it's been so long since I worked on SA-1, that
; I forgot which part.
%include "macros.mac"
EXTSYM regptr,regptw,romdata,SA1Status,debstop4,SDD1BankA,curromsize
EXTSYM debuggeron
EXTSYM Get_Time,Get_TimeDate
EXTSYM spc7110romptr,SPC7110Entries
EXTSYM SPC7110IndexSize,SPC7110nfname
EXTSYM Open_File,Close_File,Read_File,File_Seek
; EXTSYM Msgptr,MessageOn
EXTSYM irqv2,irqv,nmiv2,nmiv
EXTSYM snesmmap,snesmap2
EXTSYM curypos,CurrentExecSA1
EXTSYM debstop3
EXTSYM memaccessbankr8sdd1,memtabler8,AddrNoIncr
NEWSYM Sa1RegsAsmStart
%include "cpu/regs.mac"
%include "cpu/regsw.mac"
ALIGN32
NEWSYM SPCMultA, dd 0
NEWSYM SPCMultB, dd 0
NEWSYM SPCDivEnd, dd 0
NEWSYM SPCMulRes, dd 0
NEWSYM SPCDivRes, dd 0
NEWSYM SPC7110BankA, dd 020100h
NEWSYM SPC7110RTCStat, dd 0
NEWSYM SPC7110RTC, db 00,00,00,00,00,00,01,00,01,00,00,00,00,00,0Fh,00
NEWSYM SPC7110RTCB, db 00,00,00,00,00,00,01,00,01,00,00,00,00,01,0Fh,06
NEWSYM SPCROMPtr, dd 0
NEWSYM SPCROMtoI, dd SPCROMPtr
NEWSYM SPCROMAdj, dd 0
NEWSYM SPCROMInc, dd 0
NEWSYM SPCROMCom, dd 0
NEWSYM SPCCompPtr, dd 0
NEWSYM SPCDecmPtr, dd 0
NEWSYM SPCCompCounter, dd 0
NEWSYM SPCCompCommand, dd 0
NEWSYM SPCCheckFix, dd 0
NEWSYM SPCSignedVal, dd 0
num2writespc7110reg equ $-SPCMultA
NEWSYM PHnum2writespc7110reg, dd num2writespc7110reg
NEWSYM RTCData, db 0Fh,0,0,0,0,0,0,0,0,0,0,0,0,0,0Fh,0
NEWSYM RTCPtr, dd 0
NEWSYM RTCPtr2, dd 0
NEWSYM RTCRest, dd 0
NEWSYM SPC7110TempPosition, dd 0
NEWSYM SPC7110TempLength, dd 0
NEWSYM SPCPrevCompPtr, dd 0
RTC2800:
push ebx
cmp dword[RTCRest],100
; je .go
; inc dword[RTCRest]
; jmp .notfirst
.go
cmp dword[RTCPtr],0
jne near .notfirst
cmp byte[debuggeron],1
je near .notfirst
; fill time/date
push ebx
push eax
call Get_Time
mov bl,al
and bl,0Fh
mov [RTCData+1],bl ; seconds
shr eax,4
mov bl,al
and bl,0Fh
mov [RTCData+2],bl
; jmp .done
shr eax,4
cmp word[RTCData+1],0
; jne .notminch
mov bl,al
and bl,0Fh
mov [RTCData+3],bl ; minutes
shr eax,4
mov bl,al
and bl,0Fh
mov [RTCData+4],bl
.notminch
; jmp .done
shr eax,4
mov bl,al
and bl,0Fh
mov [RTCData+5],bl ; hours
shr eax,4
mov bl,al
and bl,0Fh
mov [RTCData+6],bl
call Get_TimeDate
mov bl,al
and bl,0Fh
mov [RTCData+7],bl ; day
shr eax,4
mov bl,al
and bl,0Fh
mov bl,al
and bl,0Fh
mov [RTCData+8],bl
shr eax,4
mov bl,al
and bl,0Fh
mov [RTCData+9],bl ; month
shr eax,8
mov bl,al
and bl,0Fh
mov [RTCData+10],bl ; year
shr eax,4
mov bl,al
and bl,01Fh
xor bh,bh
.notokay
cmp bl,9
jbe .okay
inc bh
sub bl,10
jmp .notokay
.okay
mov [RTCData+11],bl
add bh,9
mov [RTCData+12],bh
shr eax,8
and al,0Fh
mov [RTCData+13],al ; day of week
.done
pop eax
pop ebx
.notfirst
mov ebx,[RTCPtr]
mov al,[RTCData+ebx]
inc dword[RTCPtr]
cmp dword[RTCPtr],0Fh
jne .notclear
mov dword[RTCPtr],0
.notclear
pop ebx
ret
RTC2801w:
mov byte[debstop3],1
mov dword[RTCRest],0
mov dword[RTCPtr],0
cmp al,0Eh
jne .notreset
mov dword[RTCPtr2],0
ret
.notreset
cmp al,0Dh
jne .notstop
mov dword[RTCPtr2],0
ret
.notstop
push ebx
mov ebx,dword[RTCPtr2]
cmp ebx,0
je .next
cmp ebx,13
ja .nomore
mov [RTCData+ebx],al
.next
inc dword[RTCPtr2]
.nomore
pop ebx
ret
NEWSYM RTCinit
mov dword[RTCPtr],0
ret
NEWSYM RTCReset
setreg 2800h*4,RTC2800
ret
NEWSYM RTCReset2
setregw 2801h*4,RTC2801w
ret
SPC4850:
mov al,[SPC7110RTC]
ret
SPC4851:
mov al,[SPC7110RTC+01h]
ret
SPC4852:
mov al,[SPC7110RTC+02h]
ret
SPC4853:
mov al,[SPC7110RTC+03h]
ret
SPC4854:
mov al,[SPC7110RTC+04h]
ret
SPC4855:
mov al,[SPC7110RTC+05h]
ret
SPC4856:
mov al,[SPC7110RTC+06h]
ret
SPC4857:
mov al,[SPC7110RTC+07h]
ret
SPC4858:
mov al,[SPC7110RTC+08h]
ret
SPC4859:
mov al,[SPC7110RTC+09h]
ret
SPC485A:
mov al,[SPC7110RTC+0Ah]
ret
SPC485B:
mov al,[SPC7110RTC+0Bh]
ret
SPC485C:
mov al,[SPC7110RTC+0Ch]
ret
SPC485D:
mov al,[SPC7110RTC+0Dh]
ret
SPC485E:
mov al,[SPC7110RTC+0Eh]
ret
SPC485F:
mov al,[SPC7110RTC+0Fh]
ret
NEWSYM SPCDecompFin, dd 0
NEWSYM SPC7110init
mov dword[SPCMultA],0
mov dword[SPCMultB],0
mov dword[SPCDivEnd],0
mov dword[SPCMulRes],0
mov dword[SPCDivRes],0
mov dword[SPC7110BankA],020100h
mov dword[SPC7110RTCStat],0
mov dword[SPC7110RTCStat],0
mov dword[SPCROMPtr],0
mov dword[SPCROMtoI],SPCROMPtr
mov dword[SPCROMAdj],0
mov dword[SPCROMInc],0
mov dword[SPCROMCom],0
mov dword[SPCDecompFin],0
mov dword[SPCCompPtr],0
mov dword[SPCDecmPtr],0
mov dword[SPCCompCounter],0
mov dword[SPCCompCommand],0
mov dword[SPCCheckFix],0
mov dword[SPCPrevCompPtr],0
ret
NEWSYM SPC7110Reset
setregw 4801h*4,SPC4801w
setregw 4802h*4,SPC4802w
setregw 4803h*4,SPC4803w
setregw 4804h*4,SPC4804w
setregw 4805h*4,SPC4805w
setregw 4806h*4,SPC4806w
setregw 4807h*4,SPC4807w
setregw 4808h*4,SPC4808w
setregw 4809h*4,SPC4809w
setregw 480Ah*4,SPC480Aw
setregw 480Bh*4,SPC480Bw
setregw 4811h*4,SPC4811w
setregw 4812h*4,SPC4812w
setregw 4813h*4,SPC4813w
setregw 4814h*4,SPC4814w
setregw 4815h*4,SPC4815w
setregw 4816h*4,SPC4816w
setregw 4817h*4,SPC4817w
setregw 4818h*4,SPC4818w
setregw 4820h*4,SPC4820w
setregw 4821h*4,SPC4821w
setregw 4822h*4,SPC4822w
setregw 4823h*4,SPC4823w
setregw 4824h*4,SPC4824w
setregw 4825h*4,SPC4825w
setregw 4826h*4,SPC4826w
setregw 4827h*4,SPC4827w
setregw 482Eh*4,SPC482Ew
setregw 4831h*4,SPC4831w
setregw 4832h*4,SPC4832w
setregw 4833h*4,SPC4833w
setregw 4840h*4,SPC4840w
setregw 4841h*4,SPC4841w
setregw 4842h*4,SPC4842w
ret
NEWSYM initSPC7110regs
setreg 4800h*4,SPC4800
setreg 4801h*4,SPC4801
setreg 4802h*4,SPC4802
setreg 4803h*4,SPC4803
setreg 4804h*4,SPC4804
setreg 4805h*4,SPC4805
setreg 4806h*4,SPC4806
setreg 4807h*4,SPC4807
setreg 4808h*4,SPC4808
setreg 4809h*4,SPC4809
setreg 480Ah*4,SPC480A
setreg 480Bh*4,SPC480B
setreg 480Ch*4,SPC480C
setreg 4810h*4,SPC4810
setreg 4811h*4,SPC4811
setreg 4812h*4,SPC4812
setreg 4813h*4,SPC4813
setreg 4814h*4,SPC4814
setreg 4815h*4,SPC4815
setreg 4816h*4,SPC4816
setreg 4817h*4,SPC4817
setreg 4818h*4,SPC4818
setreg 481Ah*4,SPC481A
setreg 4820h*4,SPC4820
setreg 4821h*4,SPC4821
setreg 4822h*4,SPC4822
setreg 4823h*4,SPC4823
setreg 4824h*4,SPC4824
setreg 4825h*4,SPC4825
setreg 4826h*4,SPC4826
setreg 4827h*4,SPC4827
setreg 4828h*4,SPC4828
setreg 4829h*4,SPC4829
setreg 482Ah*4,SPC482A
setreg 482Bh*4,SPC482B
setreg 482Ch*4,SPC482C
setreg 482Dh*4,SPC482D
setreg 482Eh*4,SPC482E
setreg 482Fh*4,SPC482F
setreg 4831h*4,SPC4831
setreg 4832h*4,SPC4832
setreg 4833h*4,SPC4833
setreg 4834h*4,SPC4834
setreg 4840h*4,SPC4840
setreg 4841h*4,SPC4841
setreg 4842h*4,SPC4842
setreg 4850h*4,SPC4850
setreg 4851h*4,SPC4851
setreg 4852h*4,SPC4852
setreg 4853h*4,SPC4853
setreg 4854h*4,SPC4854
setreg 4855h*4,SPC4855
setreg 4856h*4,SPC4856
setreg 4857h*4,SPC4857
setreg 4858h*4,SPC4858
setreg 4859h*4,SPC4859
setreg 485Ah*4,SPC485A
setreg 485Bh*4,SPC485B
setreg 485Ch*4,SPC485C
setreg 485Dh*4,SPC485D
setreg 485Eh*4,SPC485E
setreg 485Fh*4,SPC485F
ret
%macro BankSwitchSPC7110 2
push ecx
push edx
push eax
mov [SPC7110BankA+%1],al
inc al
cmp byte[curromsize],13
jne .mbit24
.mbit40
cmp al,5
jb .okaymbit
sub al,4
jmp .mbit40
.mbit24
cmp al,3
jb .okaymbit
sub al,2
jmp .mbit24
.okaymbit
and eax,07h
shl eax,20
add eax,[romdata]
mov ecx,10h
mov ebx,snesmap2+%2*4
mov edx,snesmmap+%2*4
.mmaploop2
mov [ebx],eax
mov [edx],eax
add eax,10000h
add ebx,4
add edx,4
loop .mmaploop2
pop eax
pop edx
pop ecx
ret
%endmacro
NEWSYM LastLog
pushad
cmp byte[CurValUsed],0
je near .novalue
xor ebx,ebx
mov edx,DecompArray
mov eax,[CurPtrVal]
cmp dword[DecompAPtr],0
je .noptr
.loop
mov ecx,[edx]
cmp ecx,eax
je .match
add edx,8
inc ebx
cmp ebx,[DecompAPtr]
jne .loop
.noptr
cmp dword[DecompAPtr],8192
je .novalue
mov [edx],eax
xor eax,eax
mov ax,[CurDecompSize]
mov [edx+4],ax
mov ax,[CurPtrLen]
mov [edx+6],ax
mov al,[CurPtrLen+2]
mov [edx+3],al
inc dword[DecompAPtr]
jmp .novalue
.match
add edx,4
mov bx,[CurDecompSize]
xor ebx,ebx
cmp [edx],bx
jae .novalue
mov [edx],bx
.novalue
mov [lastentry],edx
mov byte[CurValUsed],1
mov eax,[SPCCompPtr]
and eax,0FFFFFFh
mov [CurPtrVal],eax
popad
ret
SPC4800:
; mov byte[debstop3],1
; cmp word[SPCCompCounter],0FFFFh
; jne .notzero
; xor al,al
; ret
;.notzero
cmp byte[SPCCompCommand],0
je .manual
xor al,al
dec word[SPCCompCounter]
push ebx
xor ebx,ebx
; mov ebx,[SPCCompPtr]
; and ebx,0FFFFFFh
; add ebx,[romdata]
; add ebx,100000h
mov bx,[SPCDecmPtr]
add ebx,[romdata]
add ebx,510000h
mov al,[ebx]
pop ebx
; xor al,al
inc dword[SPCCompPtr]
push eax
inc word[SPCDecmPtr]
mov ax,[SPCDecmPtr]
mov [CurDecompPtr],ax
sub ax,[PrevDecompPtr]
mov [CurDecompSize],ax
pop eax
; cmp word[SPCCompCounter],0FFFFh
; jne .exit
; mov byte[SPCDecompFin],80h
;.exit
ret
.manual
xor al,al
push ebx
xor ebx,ebx
mov bx,[SPCDecmPtr]
add ebx,[romdata]
add ebx,510000h
mov al,[ebx]
pop ebx
dec word[SPCCompCounter]
inc dword[SPCCompPtr]
inc word[SPCDecmPtr]
inc word[CurDecompSize]
; cmp word[SPCCompCounter],0FFFFh
; jne .exit2
; mov byte[SPCDecompFin],80h
;.exit2
ret
SPC4801:
mov al,[SPCCompPtr]
ret
SPC4802:
mov al,[SPCCompPtr+1]
ret
SPC4803:
mov al,[SPCCompPtr+2]
ret
SPC4804:
mov al,[SPCCompPtr+3]
ret
SPC4805:
mov al,[SPCDecmPtr]
ret
SPC4806:
mov al,[SPCDecmPtr+1]
ret
SPC4807:
xor al,al
ret
SPC4808:
xor al,al
ret
SPC4809:
mov al,[SPCCompCounter]
ret
SPC480A:
mov al,[SPCCompCounter+1]
ret
SPC480B:
mov al,[SPCCompCommand]
mov dword[SPCDecmPtr],0
ret
SPC480C: ; decompression finished status
mov al,[SPCDecompFin]
mov byte[SPCDecompFin],0
ret
NEWSYM CurPtrVal, dd 0
NEWSYM CurCompCounter2, dd 0
NEWSYM CurPtrLen, dd 0
NEWSYM CurValUsed, db 0
NEWSYM PrevDecompPtr, dw 0
NEWSYM CurDecompPtr, dw 0
NEWSYM CurDecompSize, dw 0
NEWSYM DecompArray, times 65536 db 0
NEWSYM DecompAPtr, dd 0
lastentry dd 0
NEWSYM UpdateRTC
test byte[SPC7110RTC+0Dh],02h
jnz .notimer
.notimer
ret
SPC4801w:
mov [SPCCompPtr],al
ret
SPC4802w:
mov [SPCCompPtr+1],al
ret
SPC4803w:
mov [SPCCompPtr+2],al
ret
SPC4804w:
mov [SPCCompPtr+3],al
ret
SPC4805w:
mov [SPCDecmPtr],al
ret
SPC4806w:
mov [SPCDecmPtr+1],al
cmp dword[SPCCompPtr],0124AD48h
jne .nodata
mov byte[debstop3],1
.nodata
pushad
cmp byte[CurValUsed],0
je near .novalue
xor ebx,ebx
mov edx,DecompArray
mov eax,[CurPtrVal]
; and eax,0FFFFFFh
cmp dword[DecompAPtr],0
je .noptr
.loop
mov ecx,[edx]
; and ecx,0FFFFFFh
cmp ecx,eax
je .match
add edx,8
inc ebx
cmp ebx,[DecompAPtr]
jne .loop
.noptr
cmp dword[DecompAPtr],8192
je .novalue
mov [edx],eax
xor eax,eax
mov ax,[CurDecompSize]
mov [edx+4],ax
mov ax,[CurPtrLen]
mov [edx+6],ax
mov al,[CurPtrLen+2]
mov [edx+3],al
inc dword[DecompAPtr]
jmp .novalue
.match
add edx,4
xor ebx,ebx
mov bx,[CurDecompSize]
cmp [edx],bx
jae .novalue
mov [edx],bx
.novalue
mov [lastentry],edx
mov byte[CurValUsed],1
mov eax,[SPCCompPtr]
and eax,0FFFFFFh
mov [CurPtrVal],eax
popad
mov word[CurDecompSize],0
push eax
mov al,[SPCCompPtr+3]
mov [CurPtrLen+2],al
mov ax,[SPCDecmPtr] ;CurCompCounter2]
mov [CurPtrLen],ax
mov eax,[SPCCompPtr]
mov [CurPtrVal],eax
mov ax,[SPCDecmPtr]
mov [PrevDecompPtr],ax
mov [CurDecompPtr],ax
mov word[CurDecompSize],0
pop eax
mov byte[SPCDecompFin],0h
; Start Decompression
pushad
mov eax,[SPCCompPtr]
cmp [SPCPrevCompPtr],eax
je near .previousequal
mov [SPCPrevCompPtr],eax
mov ecx,[SPC7110Entries]
mov ebx,[SPCCompPtr]
and ebx,0FFFFFFh
mov eax,[spc7110romptr]
or ecx,ecx
jz .noentries
.loopc
mov edx,[eax]
cmp dl,[SPCCompPtr+3]
jne .notfound
shr edx,8
cmp ebx,edx
je .found
.notfound
add eax,12
loop .loopc
jmp .noentries
.found
xor word[CurPtrLen],0FFFFh
mov ecx,[eax+8]
mov ebx,[eax+4]
xor edx,edx
mov dx,[SPCDecmPtr]
add edx,[romdata]
add edx,510000h
push eax
.loopb
mov al,[ebx]
mov [edx],al
inc ebx
inc edx
loop .loopb
pop eax
mov ebx,[eax+4]
mov edx,[lastentry]
; mov [edx+4],ebx
mov ebx,[eax]
; mov [edx],ebx
jmp .foundentry
.noentries
mov ecx,[SPC7110IndexSize]
; Address/index, pointer, length, SPC7110nfname
mov edx,[romdata]
add edx,580000h
.sploop
mov eax,[SPCCompPtr]
shl eax,8
mov al,[SPCCompPtr+3]
cmp [edx],eax
je .foundsp
add edx,12
sub ecx,12
jc .overflow
jnz .sploop
.overflow
jmp .notfoundentry
.foundsp
mov eax,[edx+4]
mov [SPC7110TempPosition],eax
mov eax,[edx+8]
mov [SPC7110TempLength],eax
mov edx,SPC7110nfname
add edx,9
mov eax,[SPCCompPtr]
and eax,0FFFFFFh
mov ecx,6
.sploop2
mov ebx,eax
shr ebx,20
and ebx,0Fh
cmp bl,9
jbe .below9
add bl,55-48
.below9
add bl,48
mov [edx],bl
inc edx
shl eax,4
loop .sploop2
mov edx,SPC7110nfname
call Open_File
jc .error
mov bx,ax
mov dx,[SPC7110TempPosition]
mov cx,[SPC7110TempPosition+2]
call File_Seek
xor edx,edx
mov dx,[SPCDecmPtr]
add edx,[romdata]
add edx,510000h
mov ecx,[SPC7110TempLength]
call Read_File
call Close_File
jmp .foundentry
.error
; mov dword[Msgptr],SPC7110nfname
; mov dword[MessageOn],60*6
.notfoundentry
.foundentry
.previousequal
popad
.fin
.blah
; Finished
; mov word[SPCCompCounter],0FFFFh
mov byte[SPCDecompFin],80h
ret
SPC4807w:
ret
SPC4808w:
ret
SPC4809w:
mov [SPCCompCounter],al
mov [CurCompCounter2],al
ret
SPC480Aw:
mov [SPCCompCounter+1],al
mov [CurCompCounter2+1],al
ret
SPC480Bw:
mov [SPCCompCommand],al
ret
;NEWSYM SPCROMPtr, dd 0
;NEWSYM SPCROMAdj, dd 0
;NEWSYM SPCROMInc, dd 0
;NEWSYM SPCROMCom, dd 0
; 01,
;$4810 DATA ROM CONTINUOUS READ PORT: returns a byte from data rom at data
; rom pointer location, defval:00
;$4811 DATA ROM POINTER: ($0000FF) r/w low offset, defval:00
;$4812 DATA ROM POINTER: ($00FF00) r/w high offset, defval:00
;$4813 DATA ROM POINTER: ($FF0000) r/w bank offset, defval:00
; bank offset is zero based from start of data rom: banks $00-$3f
; data rom -> $10-$4f full rom
;$4814 DATA ROM POINTER ADJUST: ($00FF) low byte, defval:00
;$4815 DATA ROM POINTER ADJUST: ($FF00) high byte, defval:00
;$4816 DATA ROM POINTER INCREMENT: ($00FF) low byte, defval:00
;$4817 DATA ROM POINTER INCREMENT: ($FF00) high byte, defval:00
;$4818 DATA ROM COMMAND MODE: bit field control of data rom pointer (see
; data rom command mode byte), defval:00
; write: set command mode,
; read: performs action instead of returning value, unknown purpose,
; command mode is loaded to $4818 but only set after writing to both
; $4814 and $4815 in any order
;$481A DATA ROM READ AFTER ADJUST PORT: returns a byte from data rom at
; data rom pointer location + adjust value ($4814/5), defval:00
SPC4810:
cmp dword[SPCCheckFix],0
jne .okay
xor al,al
ret
.okay
push ebx
push ecx
mov ebx,[SPCROMPtr]
add ebx,[romdata]
add ebx,100000h
mov al,[ebx]
cmp byte[SPCROMCom+1],0
jne .noincr1
mov ebx,[SPCROMtoI]
inc dword[ebx]
.noincr1
cmp byte[SPCROMCom+1],1 ; add 4816 after 4810 read
jne .noincr1b
mov ebx,[SPCROMtoI]
mov ecx,[SPCROMInc]
add dword[ebx],ecx
.noincr1b
pop ecx
pop ebx
ret
SPC4811:
mov al,[SPCROMPtr]
ret
SPC4812:
mov al,[SPCROMPtr+1]
ret
SPC4813:
mov al,[SPCROMPtr+2]
ret
SPC4814:
mov al,[SPCROMAdj]
ret
SPC4815:
mov al,[SPCROMAdj+1]
ret
SPC4816:
mov al,[SPCROMInc]
ret
SPC4817:
mov al,[SPCROMInc+1]
ret
SPC4818:
mov al,[SPCROMCom]
ret
SPC481A:
cmp dword[SPCCheckFix],0
jne .okay
xor al,al
ret
.okay
push ebx
push ecx
xor ebx,ebx
xor ecx,ecx
mov bx,[SPCROMAdj]
add ebx,[SPCROMPtr]
add ebx,[romdata]
add ebx,100000h
mov al,[ebx]
cmp byte[SPCROMCom+1],4 ; 16bit 4814
jne .notincr
mov ecx,[SPCROMtoI]
mov ebx,[SPCROMAdj]
add [ecx],ebx
.notincr
pop ecx
pop ebx
ret
SPC4811w:
mov [SPCROMPtr],al
mov byte[SPCCheckFix],1
ret
SPC4812w:
mov [SPCROMPtr+1],al
ret
SPC4813w:
mov [SPCROMPtr+2],al
ret
SPC4814w:
mov [SPCROMAdj],al
cmp byte[SPCROMCom+1],2 ; 8 bit 4814
jne .notincr
mov ebx,[SPCROMtoI]
xor ecx,ecx
mov cl,[SPCROMAdj]
test byte[SPCROMCom],08h
jz .noneg
movsx ecx,byte[SPCROMAdj]
.noneg
add dword[ebx],ecx
.notincr
ret
SPC4815w:
mov [SPCROMAdj+1],al
mov word[SPCROMAdj+2],0
test byte[SPCROMCom],08h
jz .noneg
test byte[SPCROMAdj+1],80h
jz .noneg
mov word[SPCROMAdj+2],0FFFFh
.noneg
cmp byte[SPCROMCom+1],3 ; 16bit 4814
jne .notincr
push ebx
push ecx
mov ecx,[SPCROMtoI]
mov ebx,[SPCROMAdj]
add [ecx],ebx
pop ecx
pop ebx
.notincr
ret
SPC4816w:
mov [SPCROMInc],al
ret
SPC4817w:
mov [SPCROMInc+1],al
mov word[SPCROMInc+2],0
test byte[SPCROMCom],04h
jz .noneg
test byte[SPCROMInc+1],40h
jz .noneg
mov word[SPCROMInc+2],0FFFFh
.noneg
ret
SPC4818w:
mov [SPCROMCom],al
mov word[SPCROMAdj+2],0
test byte[SPCROMCom],08h
jz .noneg
test byte[SPCROMAdj+1],80h
jz .noneg
mov word[SPCROMAdj+2],0FFFFh
.noneg
mov word[SPCROMInc+2],0
test byte[SPCROMCom],04h
jz .noneg2
test byte[SPCROMInc+1],40h
jz .noneg2
mov word[SPCROMInc+2],0FFFFh
.noneg2
mov dword[SPCROMtoI],SPCROMPtr
test byte[SPCROMCom],10h
jz .nouseadjust
mov dword[SPCROMtoI],SPCROMAdj
.nouseadjust
test al,02h
jz .no4814
test al,40h
jz .no16b
test al,20h
jz .not481A
mov byte[SPCROMCom+1],4 ; 16bit 4814 after 481A
jmp .fin
.not481A
mov byte[SPCROMCom+1],3 ; 16bit 4814
jmp .fin
.no16b
test al,20h
jz .nooffsetadd
mov byte[SPCROMCom+1],2 ; 8 bit 4814
jmp .fin
.nooffsetadd
mov byte[SPCROMCom+1],0FFh
jmp .fin
.no4814
test al,01h
jz .incrval0
mov byte[SPCROMCom+1],1 ; add 4816 after 4810 read
jmp .fin
.incrval0
mov byte[SPCROMCom+1],0 ; add 1 after 4810 read
.fin
ret
;Data Rom Command Mode Byte:
;X6543210
;||||||||
;|||||| \__ : 00 - use 1 as the offset increment value, add immediately after reading $4810
;|||||| : 01 - use $4816 as offset increment, add immediately after reading $4810
;|||||| : 10 - use $4814 as offset increment, see below for when to add
;|||||| : 11 - unused
;||||||____ : 0 - unsigned calculation for $4816
;||||| 1 - signed calculation for $4816
;|||||_____ : 0 - unsigned calculation for $4814
;|||| 1 - signed calculation for $4814
;||||______ : 0 - offset increment gets added to $4811/2/3
;||| 1 - offset increment gets added to $4814/5
;| \_______ : 00 - disable offset addition
;| : 01 - 8 bit offset addition using $4814, immediately after writing to $4814/5
;| : 10 - 16 bit offset addition using $4814/5, immediately after writing to $4814/5
;| : 11 - 16 bit offset addition using $4814/5, only after reading $481A
;|_________ : unused
SPC4820:
mov al,[SPCMultA]
; mov byte[debstop3],1
ret
SPC4821:
mov al,[SPCMultA+1]
ret
SPC4822:
mov al,[SPCMultA+2]
ret
SPC4823:
mov al,[SPCMultA+3]
ret
SPC4824:
mov al,[SPCMultB]
ret
SPC4825:
mov al,[SPCMultB+1]
ret
SPC4826:
mov al,[SPCDivEnd]
ret
SPC4827:
mov al,[SPCDivEnd+1]
ret
SPC4820w:
mov [SPCMultA],al
ret
SPC4821w:
mov [SPCMultA+1],al
ret
SPC4822w:
mov [SPCMultA+2],al
ret
SPC4823w:
mov [SPCMultA+3],al
ret
SPC4824w:
mov [SPCMultB],al
ret
SPC4825w:
mov [SPCMultB+1],al
; Calculate SPCMultA*SPCMultB -> SPCMulRes
test byte[SPCSignedVal],1
jnz .signed
push edx
push eax
push ebx
xor eax,eax
xor ebx,ebx
mov ax,[SPCMultA]
mov bx,[SPCMultB]
mul ebx
mov [SPCMulRes],eax
pop ebx
pop eax
pop edx
ret
.signed
push edx
push eax
push ebx
movsx eax,word[SPCMultA]
movsx ebx,word[SPCMultB]
imul ebx
mov [SPCMulRes],eax
pop ebx
pop eax
pop edx
ret
SPC4826w:
mov [SPCDivEnd],al
ret
SPC4827w:
mov [SPCDivEnd+1],al
; Calculte SPCMultA/SPCDivEnd -> SPCMulRes, rem SPCDivRes
cmp word[SPCDivEnd],0
je near .nodivide
test byte[SPCSignedVal],1
jnz .signed
push edx
push eax
push ebx
xor edx,edx
xor ebx,ebx
mov eax,[SPCMultA]
mov bx,[SPCDivEnd]
div ebx
mov [SPCMulRes],eax
mov [SPCDivRes],dx
pop ebx
pop eax
pop edx
ret
.signed
push edx
push eax
push ebx
xor edx,edx
mov eax,[SPCMultA]
test eax,80000000h
jz .nd
mov edx,0FFFFFFFFh
.nd
movsx ebx,word[SPCDivEnd]
idiv ebx
mov [SPCMulRes],eax
mov [SPCDivRes],dx
pop ebx
pop eax
pop edx
ret
.nodivide
mov dword[SPCMulRes],0FFFFFFFFh
mov dword[SPCDivRes],0FFFFh
ret
SPC4828:
mov al,[SPCMulRes]
ret
SPC4829:
mov al,[SPCMulRes+1]
ret
SPC482A:
mov al,[SPCMulRes+2]
ret
SPC482B:
mov al,[SPCMulRes+3]
ret
SPC482C:
mov al,[SPCDivRes]
ret
SPC482D:
mov al,[SPCDivRes+1]
ret
SPC482E:
xor al,al
ret
SPC482Ew:
mov byte[SPCSignedVal],al
mov dword[SPCMultA],0
mov dword[SPCMultB],0
mov dword[SPCDivEnd],0
mov dword[SPCMulRes],0
mov dword[SPCDivRes],0
ret
SPC482F:
xor al,al
ret
SPC4831w:
BankSwitchSPC7110 0,0D0h
ret
SPC4832w:
BankSwitchSPC7110 1,0E0h
ret
SPC4833w:
; mov byte[debstop3],1
BankSwitchSPC7110 2,0F0h
ret
SPC4831:
mov al,[SPC7110BankA]
ret
SPC4832:
mov al,[SPC7110BankA+1]
ret
SPC4833:
mov al,[SPC7110BankA+2]
ret
SPC4834:
xor al,al
ret
;NEWSYM SPC7110RTCStat, dd 0
;NEWSYM SPC7110RTC, db 00,00,00,00,00,00,01,00,01,00,00,00,00,01,0F,06
;$4840 RTC CHIP ENABLE/DISABLE: bit 0: on = enable, off = disable, defval:00
;$4841 RTC INDEX/DATA PORT:
; first write after rtc enable: rtc command mode byte (see rtc command modes)
; subsequent writes: index of rtc register to read/write (00-0f)
; read: returns value of indexed rtc register
; auto-increment of register index occurs after each subsequent read/write
;$4842 RTC READY STATUS: bit 7: on = ready, off = still processing, tested before reading rtc data
; high bit cleared after successful read
SPC4840w:
test al,1
jz .notreset
mov byte[SPC7110RTCStat],al
mov byte[SPC7110RTCStat+1],0FEh
.notreset
ret
SPC4841w:
cmp byte[SPC7110RTCStat+1],0FEh
je .commandbyte
cmp byte[SPC7110RTCStat+1],0FFh
je .commandindex
push ebx
xor ebx,ebx
mov bl,[SPC7110RTCStat+1]
mov [SPC7110RTC+ebx],al
cmp ebx,0Fh
jne .notlast
test al,01h
jz .notlast
mov dword[SPC7110RTC],0
mov dword[SPC7110RTC+4],010000h
mov dword[SPC7110RTC+8],01h
mov byte[SPC7110RTC+12],0
.notlast
pop ebx
inc byte[SPC7110RTCStat+1]
and byte[SPC7110RTCStat+1],0Fh
ret
.commandbyte
inc byte[SPC7110RTCStat+1]
mov byte[SPC7110RTCStat+2],al
ret
.commandindex
push eax
and al,0Fh
mov byte[SPC7110RTCStat+1],al
pop eax
ret
SPC4842w:
ret
SPC4840:
mov al,[SPC7110RTCStat]
ret
SPC4841:
cmp byte[SPC7110RTCStat+1],0FEh
je near .commandbyte
cmp byte[SPC7110RTCStat+1],0FFh
je near .commandbyte
push ebx
xor ebx,ebx
mov bl,[SPC7110RTCStat+1]
or ebx,ebx
jnz near .dontupdate
test byte[SPC7110RTC+0Fh],03h
jnz near .dontupdate
test byte[SPC7110RTC+0Dh],01h
jnz near .dontupdate
;00 - seconds 1's digit 00
;01 - seconds 10's digit 00
;02 - minutes 1's digit 00
;03 - minutes 10's digit 00
;04 - hours 1's digit 00
;05 - hours 10's digit 00
;06 - day of month 1's digit 01
;07 - day of month 10's digit 00
;08 - month 1's digit 01
;09 - month 10's digit 00
;0a - year 1's digit 00
;0b - year 10's digit 00
;0c - day of week 00
cmp byte[debuggeron],1
je near .dontupdate
; fill time/date
push ebx
push eax
call Get_Time
mov bl,al
and bl,0Fh
mov [SPC7110RTC],bl ; seconds
shr eax,4
mov bl,al
and bl,0Fh
mov [SPC7110RTC+1],bl
shr eax,4
mov bl,al
and bl,0Fh
mov [SPC7110RTC+2],bl ; minutes
shr eax,4
mov bl,al
and bl,0Fh
mov [SPC7110RTC+3],bl
test byte[SPC7110RTC+0Fh],4
; jz .not24hrs
; jmp .not24hrs
shr eax,4
mov bl,al
and bl,0Fh
mov [SPC7110RTC+4],bl ; hours
shr eax,4
mov bl,al
and bl,0Fh
mov [SPC7110RTC+5],bl
jmp .24hrs
.not24hrs
shr eax,4
xor ebx,ebx
mov bl,al
mov al,[SPCTimerVal+ebx]
mov bl,al
and bl,0Fh
mov [SPC7110RTC+4],bl ; hours
shr eax,4
mov bl,al
and bl,0Fh
mov [SPC7110RTC+5],bl
.24hrs
call Get_TimeDate
mov bl,al
and bl,0Fh
mov [SPC7110RTC+6],bl ; day
shr eax,4
mov bl,al
and bl,0Fh
mov [SPC7110RTC+7],bl
shr eax,4
mov bl,al
and bl,0Fh
xor bh,bh
cmp bl,9
jbe .less
sub bl,10
mov bh,1
.less
mov [SPC7110RTC+8],bl ; month
mov [SPC7110RTC+9],bh ; month
shr eax,8
mov bl,al
and bl,0Fh
mov [SPC7110RTC+10],bl ; year
shr eax,4
mov bl,al
and bl,01Fh
xor bh,bh
.notokay
cmp bl,9
jbe .okay
inc bh
sub bl,10
jmp .notokay
.okay
mov [SPC7110RTC+11],bl
shr eax,8
and al,0Fh
mov [SPC7110RTC+12],al ; day of week
.done
pop eax
pop ebx
.dontupdate
; test byte[SPC7110RTC+0Fh],1
; jz .realtime
; cmp ebx,0Dh
; jae .realtime
; mov al,[SPC7110RTCB+ebx]
; jmp .next
;.realtime
mov al,[SPC7110RTC+ebx]
;.next
pop ebx
inc byte[SPC7110RTCStat+1]
and byte[SPC7110RTCStat+1],0Fh
ret
.commandbyte
inc byte[SPC7110RTCStat+1]
mov al,byte[SPC7110RTCStat+2]
ret
SPCTimerVal
db 12h,01h,02h,03h,04h,05h,06h,07h,08h,09h,0,0,0,0,0,0
db 10h,11h,32h,21h,22h,23h,24h,25h,26h,27h,0,0,0,0,0,0
db 28h,29h
SPC4842:
mov al,80h
ret
;$4820 16 BIT MULTIPLICAND: ($00FF) low byte, defval:00
; 32 BIT DIVI: ($000000FF) low byte of low word, defval:00
;$4821 16 BIT MULTIPLICAND: ($FF00) high byte, defval:00
; 32 BIT DIVI: ($0000FF00) high byte of low word, defval:00
;$4822 32 BIT DIVI: ($00FF0000) low byte of high word, defval:00
;$4823 32 BIT DIVI: ($FF000000) high byte of high word, defval:00
;$4824 16 BIT MULTIPLIER: ($00FF) low byte, defval:00
;$4825 16 BIT MULTIPLIER: ($FF00) high byte, defval:00
;$4826 16 BIT DIVISOR: ($00FF), defval:00
;$4827 16 BIT DIVISOR: ($FF00), defval:00
;$4828 32 BIT PRODUCT: ($000000FF) low byte of low word, defval:00
; 32 BIT QUOTIENT:($000000FF) low byte of low word, defval:00
;$4829 32 BIT PRODUCT: ($0000FF00) high byte of low word, defval:00
; 32 BIT QUOTIENT:($0000FF00) high byte of low word, defval:00
;$482A 32 BIT PRODUCT: ($00FF0000) low byte of high word, defval:00
; 32 BIT QUOTIENT:($00FF0000) low byte of high word, defval:00
;$482B 32 BIT PRODUCT: ($FF000000) high byte of high word, defval:00
; 32 BIT QUOTIENT:($FF000000) high byte of high word, defval:00
;$482C 16 BIT REMAINDER: ($00FF) low byte, defval:00
;$482D 16 BIT REMAINDER: ($FF00) high byte, defval:00
;$482E MUL/DIV RESET, write = reset $4820 to $482D, defval:00
;$482F MUL/DIV FINISHED STATUS: bit 7: on = processing, off = finished,
; high bit is set after a write to multiplier or divisor regs $4825/$4827, defval:00
ALIGN32
; IRQ Stuff
NEWSYM SA1Mode, dd 0 ; 0 = SNES CPU, 1 = SA1 CPU
NEWSYM SA1Control, dd 0 ; don't execute if b5 or 6 are set
NEWSYM SA1BankPtr, dd 0
NEWSYM SA1ResetV, dd 0
NEWSYM SA1NMIV, dd 0
NEWSYM SA1IRQV, dd 0
NEWSYM SA1RV, dd 0
NEWSYM CurBWPtr, dd 0
NEWSYM SA1TempVar, dd 0
NEWSYM SA1IRQEn, dd 0
NEWSYM SA1Message, dd 0
NEWSYM SA1IRQExec, dd 0
NEWSYM SA1IRQEnable, dd 0
NEWSYM SA1DoIRQ, dd 0
; Arithmetic Stuff
NEWSYM SA1ARC, dd 0
NEWSYM SA1AR1, dd 0
NEWSYM SA1AR2, dd 0
NEWSYM SA1ARR1, dd 0
NEWSYM SA1ARR2,dd 0
NEWSYM SA1Stat, dd 0
NEWSYM SNSNMIV, dd 0
NEWSYM SNSIRQV, dd 0
NEWSYM SA1DMACount, dd 0
NEWSYM SA1DMAInfo, dd 0
NEWSYM SA1DMAChar, dd 0
NEWSYM SA1DMASource, dd 0
NEWSYM SA1DMADest, dd 0
NEWSYM SA1IRQTemp, dd 0
NEWSYM SA1BankSw, dd 1
NEWSYM SA1BankVal, db 0,1,2,3
SA1Reserved times 472 db 0
; SA1 Swap Stuff
NEWSYM SA1xa, dd 0
NEWSYM SA1xx, dd 0
NEWSYM SA1xy, dd 0
NEWSYM SA1xd, dd 0
NEWSYM SA1xdb, dd 0
NEWSYM SA1xpb, dd 0
NEWSYM SA1xs, dd 0
NEWSYM SA1RegP, dd 0
NEWSYM SA1RegE, dd 0
NEWSYM SA1RegPCS,dd 0
NEWSYM SA1BWPtr,dd 0
NEWSYM SA1Ptr, dd 0 ; Current PC, SA-1
NEWSYM SA1Overflow, dd 0
NEWSYM VarLenAddr, dd 0
NEWSYM VarLenAddrB, dd 0
NEWSYM VarLenBarrel, dd 0
NEWSYM SA1TimerVal, dd 0
NEWSYM SA1TimerSet, dd 0
NEWSYM SA1TimerCount, dd 0
NEWSYM SA1IRQData, dd 0
; SNES Swap Stuff
NEWSYM SNSRegP, dd 0
NEWSYM SNSRegE, dd 0
NEWSYM SNSRegPCS,dd 0
NEWSYM SNSBWPtr,dd 0
NEWSYM SNSPtr, dd 0 ; Current PC, SNES
NEWSYM IRAM, times 2049 db 0 ;2 kbytes of iram
num2writesa1reg equ $-SA1Mode
NEWSYM PHnum2writesa1reg, dd num2writesa1reg
NEWSYM SA1RAMArea, dd 0
NEWSYM SA1Temp, dd 0
NEWSYM Sdd1Mode, dd 0
NEWSYM Sdd1Bank, dd 0
NEWSYM Sdd1Addr, dd 0
NEWSYM Sdd1NewAddr, dd 0
%macro SA1QuickF 2
NEWSYM %1
mov [%2],al
ret
%endmacro
NEWSYM RestoreSA1
mov eax,[romdata]
add [SA1RegPCS],eax
add [CurBWPtr],eax
add [SA1BWPtr],eax
add [SNSBWPtr],eax
cmp byte[SA1Stat],1
jne .notsa1stat
mov dword[SA1RegPCS],IRAM
.notsa1stat
cmp byte[SA1Stat],2
jne .notsa1stat2
mov dword[SA1RegPCS],IRAM-3000h
.notsa1stat2
mov eax,[SA1RegPCS]
add [SA1Ptr],eax
mov eax,[romdata]
add eax,4096*1024
mov [SA1RAMArea],eax
pushad
call UpdateBanks
popad
ret
NEWSYM SaveSA1
mov byte[SA1Stat],0
mov eax,[SA1RegPCS]
sub [SA1Ptr],eax
cmp dword[SA1RegPCS],IRAM
jne .notiram
mov byte[SA1Stat],1
.notiram
cmp dword[SA1RegPCS],IRAM-3000h
jne .notiram2
mov byte[SA1Stat],2
.notiram2
mov eax,[romdata]
sub [SA1RegPCS],eax
sub [CurBWPtr],eax
sub [SA1BWPtr],eax
sub [SNSBWPtr],eax
ret
NEWSYM SA1Reset
mov byte[SA1IRQData+1],0
mov byte[SA1Mode],0
mov byte[SA1Status],0
mov byte[SA1Control],20h
mov dword[SA1DoIRQ],0
mov ax,[irqv2]
mov [irqv],ax
mov ax,[nmiv2]
mov [nmiv],ax
mov eax,[romdata]
sub eax,8000h
mov [SA1RegPCS],eax
mov eax,[romdata]
add eax,4096*1024
mov [SA1RAMArea],eax
mov eax,[romdata]
add eax,4096*1024-6000h
mov dword[CurBWPtr],eax
mov dword[SA1BWPtr],eax
mov dword[SNSBWPtr],eax
mov dword[SA1xa],0
mov dword[SA1xx],0
mov dword[SA1xy],0
mov dword[SA1xd],0
mov dword[SA1xdb],0
mov dword[SA1xpb],0
mov dword[SA1xs],1FFh
mov dword[SA1RegP],0
mov dword[SA1RegE],0
mov dword[SA1IRQExec],0
mov dword[SA1IRQEnable],0
mov dword[SA1Message],0
mov byte[SA1Overflow],0
ret
NEWSYM UpdateBanks
cmp byte[SA1BankSw],1
jne .noswap
mov al,[SA1BankVal]
call sa12220w
mov al,[SA1BankVal+1]
call sa12221w
mov al,[SA1BankVal+2]
call sa12222w
mov al,[SA1BankVal+3]
call sa12223w
.noswap
ret
NEWSYM UpdateBanksSDD1
pushad
cmp dword[SDD1BankA],0
je .nobank
mov al,[SDD1BankA]
call sdd14804w
mov al,[SDD1BankA+1]
call sdd14805w
mov al,[SDD1BankA+2]
call sdd14806w
mov al,[SDD1BankA+3]
call sdd14807w
.nobank
popad
ret
%macro BankSwitch 4
push ecx
push edx
push eax
mov [SA1BankVal+%1],al
mov ebx,snesmmap+%2*4
test al,80h
jz .noupper
and eax,07h
shl eax,20
push eax
jmp .yesupper
.noupper
and eax,07h
shl eax,20
push eax
mov eax,%4
.yesupper
mov ecx,20h
add eax,[romdata]
sub eax,8000h
.mmaploop
mov [ebx],eax
add eax,8000h
add ebx,4
loop .mmaploop
pop eax
add eax,[romdata]
mov ecx,10h
mov ebx,snesmap2+%3*4
mov edx,snesmmap+%3*4
.mmaploop2
mov [ebx],eax
mov [edx],eax
add eax,10000h
add ebx,4
add edx,4
loop .mmaploop2
pop eax
pop edx
pop ecx
ret
%endmacro
NEWSYM sa12220w
BankSwitch 0,0,0C0h,0
NEWSYM sa12221w
BankSwitch 1,20h,0D0h,100000h
NEWSYM sa12222w
BankSwitch 2,80h,0E0h,200000h
NEWSYM sa12223w
BankSwitch 3,0A0h,0F0h,300000h
%macro BankSwitchSDD1 2
push ecx
push edx
push eax
mov [SDD1BankA+%1],al
and eax,07h
shl eax,20
add eax,[romdata]
mov ecx,10h
mov ebx,snesmap2+%2*4
mov edx,snesmmap+%2*4
.mmaploop2
mov [ebx],eax
mov [edx],eax
add eax,10000h
add ebx,4
add edx,4
loop .mmaploop2
pop eax
pop edx
pop ecx
ret
%endmacro
sdd14804:
mov al,[SDD1BankA]
ret
sdd14805:
mov al,[SDD1BankA+1]
ret
sdd14806:
mov al,[SDD1BankA+2]
ret
sdd14807:
mov al,[SDD1BankA+3]
ret
NEWSYM sdd14804w
BankSwitchSDD1 0,0C0h
NEWSYM sdd14805w
BankSwitchSDD1 1,0D0h
NEWSYM sdd14806w
BankSwitchSDD1 2,0E0h
NEWSYM sdd14807w
BankSwitchSDD1 3,0F0h
NEWSYM sa12200w
mov bl,al
and bl,0Fh
mov byte[SA1Message],bl
test al,80h
jz .noirq
or byte[SA1DoIRQ],1
.noirq
test al,10h
jz .nonmi
or byte[SA1DoIRQ],2
.nonmi
test byte[SA1Control],20h
jz .noreset
test al,20h
jnz .noreset
mov [SA1Control],al
mov ebx,[romdata]
mov [SA1BankPtr],ebx
xor ebx,ebx
mov bx,[SA1ResetV]
add ebx,[romdata]
sub ebx,8000h
mov [SA1Ptr],ebx
mov byte[SA1xpb],0
mov word[SA1xs],1FFh
mov ebx,[romdata]
sub ebx,8000h
mov [SA1RegPCS],ebx
xor ebx,ebx
ret
.noreset
mov [SA1Control],al
ret
NEWSYM sa12201w ; IRQ Enable
mov byte[SA1IRQEnable],al
ret
NEWSYM sa12202w ; IRQ Clear
test al,80h
jz .noirqclear
and byte[SA1IRQExec],0FEh
and byte[SA1DoIRQ],0FBh
.noirqclear
test al,20h
jz .nocdmairqclear
and byte[SA1IRQExec],0FDh
and byte[SA1DoIRQ],0F7h
.nocdmairqclear
ret
SA1QuickF sa12203w, SA1ResetV
SA1QuickF sa12204w, SA1ResetV+1
SA1QuickF sa12205w, SA1NMIV
SA1QuickF sa12206w, SA1NMIV+1
SA1QuickF sa12207w, SA1IRQV
SA1QuickF sa12208w, SA1IRQV+1
NEWSYM sa12209w ; IRQ Stuff
mov [SA1IRQData+1],al
test al,80h
jz .noirq
; execute IRQ on the SNES
or byte[SA1DoIRQ],4
.noirq
mov bl,al
and bl,0Fh
mov byte[SA1Message+1],bl
mov bx,[irqv2]
test al,40h
jz .noirqchange
mov bx,[SNSIRQV]
.noirqchange
mov [irqv],bx
mov bx,[nmiv2]
test al,10h
jz .nonmichange
mov bx,[SNSNMIV]
.nonmichange
mov [nmiv],bx
ret
SA1QuickF sa1220Aw, SA1IRQEn
NEWSYM sa1220Bw ; SA-1 IRQ Clear
test al,80h
jz .noirqclear
mov byte[SA1IRQExec+1],0
and byte[SA1DoIRQ],0FEh
.noirqclear
test al,20h
jz .nocdmairqclear
.nocdmairqclear
test al,10h
jz .nonmiclear
mov byte[SA1IRQExec+2],0
and byte[SA1DoIRQ],0FDh
.nonmiclear
ret
SA1QuickF sa1220Cw, SNSNMIV
SA1QuickF sa1220Dw, SNSNMIV+1
SA1QuickF sa1220Ew, SNSIRQV
SA1QuickF sa1220Fw, SNSIRQV+1
NEWSYM sa12224w ; BWRAM
mov bl,al
and ebx,1Fh
shl ebx,13
add ebx,[romdata]
add ebx,1024*4096-6000h
mov dword[SNSBWPtr],ebx
cmp byte[SA1Status],0
jne .nosnes
mov dword[CurBWPtr],ebx
.nosnes
ret
NEWSYM sa12225w ; BWRAM
mov bl,al
and ebx,1Fh
shl ebx,13
add ebx,[romdata]
add ebx,1024*4096-6000h
mov dword[SA1BWPtr],ebx
cmp byte[SA1Status],0
je .nosa1
mov dword[CurBWPtr],ebx
.nosa1
ret
NEWSYM sa12250w
mov byte[SA1ARC],al
mov byte[SA1ARC+1],1
test al,2
jz .notcumul
mov word[SA1ARR1],0
mov word[SA1ARR1+2],0
mov word[SA1ARR1+4],0
.notcumul
ret
NEWSYM sa12251w
mov byte[SA1AR1],al
mov byte[SA1ARC+1],1
ret
NEWSYM sa12252w
mov byte[SA1AR1+1],al
mov byte[SA1ARC+1],1
ret
NEWSYM sa12253w
mov byte[SA1AR2],al
mov byte[SA1ARC+1],1
ret
NEWSYM sa12254w
mov byte[SA1AR2+1],al
mov byte[SA1ARC+1],1
test byte[SA1ARC],2
jnz .cumul
call UpdateArithStuff
ret
; set overflow bit if exceeds 40bits
.cumul
pushad
xor edx,edx
mov ax,[SA1AR1]
mov bx,[SA1AR2]
imul bx
shl edx,16
mov dx,ax
mov byte[SA1Overflow],0
add [SA1ARR1],edx
adc byte[SA1ARR2],0
jnc .notoverflow
mov byte[SA1Overflow],80h
.notoverflow
popad
ret
UpdateArithStuff:
cmp byte[SA1ARC+1],1
jne .noarith
pushad
mov byte[SA1ARC+1],0
test byte[SA1ARC],3
jz .multiply
test byte[SA1ARC],2
jnz near .cumulativesum
test byte[SA1ARC],1
jnz .division
.multiply
xor edx,edx
mov ax,[SA1AR1]
mov bx,[SA1AR2]
imul bx
mov [SA1ARR1],ax
mov [SA1ARR1+2],dx
popad
.noarith
ret
.division
movsx eax,word[SA1AR1]
xor edx,edx
test eax,80000000h
jz .notneg
mov edx,0FFFFFFFFh
.notneg
xor ebx,ebx
mov bx,[SA1AR2]
or ebx,ebx
jz .invalid
idiv ebx
mov [SA1ARR1],ax
mov [SA1ARR1+2],dx
; mov word[SA1AR1],0
; mov word[SA1AR2],0
popad
ret
.invalid
mov word[SA1ARR1],0
mov word[SA1ARR1+2],0
popad
ret
.cumulativesum
popad
ret
sa12300r:
mov al,[SA1Message+1]
test byte[SA1IRQExec],1
jz .notexecuted
or al,80h
.notexecuted
test byte[SA1IRQExec],2
jz .notexecutedi
or al,20h
.notexecutedi
mov bl,[SA1IRQData+1]
and bl,50h
or al,bl
ret
sa12301r:
mov al,[SA1Message]
test byte[SA1IRQExec+1],1
jz .notexecuted
or al,80h
.notexecuted
ret
sa12306r:
; call UpdateArithStuff
mov al,[SA1ARR1]
ret
sa12307r:
; call UpdateArithStuff
mov al,[SA1ARR1+1]
ret
sa12308r:
; call UpdateArithStuff
mov al,[SA1ARR1+2]
ret
sa12309r:
; call UpdateArithStuff
mov al,[SA1ARR1+3]
ret
sa1230Ar:
; call UpdateArithStuff
mov al,[SA1ARR2]
ret
sa1230Br:
mov al,[SA1Overflow]
ret
NEWSYM IRamRead
mov al,[IRAM+ecx-3000h]
ret
NEWSYM IRamWrite
mov [IRAM+ecx-3000h],al
ret
NEWSYM IRamWrite2
mov [IRAM+ecx-3000h],al
xor dh,dh
ret
NEWSYM sa1223Fw
mov [SA1Overflow+1],al
ret
; Variable Length Data
NEWSYM sa12258w
mov [VarLenBarrel+2],al
mov bl,al
and bl,0Fh
cmp bl,0
jne .not0
mov bl,16
.not0
mov [VarLenBarrel+3],bl
test al,80h
jz .notchange
mov [VarLenBarrel],bl
mov [VarLenBarrel+1],bl
.notchange
ret
NEWSYM sa12259w
mov [VarLenAddr],al
mov [VarLenAddrB],al
mov byte[VarLenBarrel],0
mov byte[VarLenBarrel+1],0
ret
NEWSYM sa1225Aw
mov [VarLenAddr+1],al
mov [VarLenAddrB+1],al
mov byte[VarLenBarrel],0
mov byte[VarLenBarrel+1],0
ret
NEWSYM sa1225Bw
mov [VarLenAddr+2],al
mov [VarLenAddrB+2],al
mov byte[VarLenBarrel],0
mov byte[VarLenBarrel+1],0
ret
; Variable Length Read
NEWSYM sa1230Cr
push ecx
xor ebx,ebx
xor ecx,ecx
mov bl,[VarLenAddr+2]
mov cx,[VarLenAddr]
test ecx,8000h
jz .loweraddr
add ecx,[snesmmap+ebx*4]
jmp .upperaddr
.loweraddr
add ecx,[snesmap2+ebx*4]
.upperaddr
mov ebx,[ecx]
mov cl,[VarLenBarrel+1]
shr ebx,cl
mov al,bl
pop ecx
test byte[VarLenBarrel+2],80h
jnz .autoinc
ret
.autoinc
mov bl,[VarLenBarrel+3]
add [VarLenBarrel],bl
mov bl,[VarLenBarrel]
cmp bl,16
jbe .notover
sub byte[VarLenBarrel],16
add dword[VarLenAddr],2
mov byte[VarLenAddr+3],0
.notover
ret
NEWSYM sa1230Dr
push ecx
xor ebx,ebx
xor ecx,ecx
mov bl,[VarLenAddrB+2]
mov cx,[VarLenAddrB]
test ecx,8000h
jz .loweraddr
add ecx,[snesmmap+ebx*4]
jmp .upperaddr
.loweraddr
add ecx,[snesmap2+ebx*4]
.upperaddr
mov ebx,[ecx]
mov cl,[VarLenBarrel+1]
shr ebx,cl
mov al,bh
pop ecx
test byte[VarLenBarrel+2],80h
jnz .autoinc
ret
.autoinc
mov bl,[VarLenBarrel+3]
add [VarLenBarrel+1],bl
mov bl,[VarLenBarrel+1]
cmp bl,16
jbe .notover
sub byte[VarLenBarrel+1],16
add dword[VarLenAddrB],2
mov byte[VarLenAddrB+3],0
.notover
ret
NEWSYM sa1230Er
mov al,10h
ret
; Approximate H loc
NEWSYM sa12302r
test byte[SA1TimerSet],80h
jnz .timeron
mov al,byte[CurrentExecSA1]
shl al,2
add al,dh
ret
.timeron
mov al,[SA1TimerCount]
ret
NEWSYM sa12303r
test byte[SA1TimerSet],80h
jnz .timeron
mov al,byte[CurrentExecSA1]
shr al,3
ret
.timeron
mov al,[SA1TimerCount+1]
and al,1
ret
NEWSYM sa12304r
test byte[SA1TimerSet],80h
jnz .timeron
mov al,[curypos]
ret
.timeron
mov bx,[SA1TimerCount+1]
shr bx,1
mov al,bl
ret
NEWSYM sa12305r
test byte[SA1TimerSet],80h
jnz .timeron
mov al,[curypos+1]
ret
.timeron
mov bx,[SA1TimerCount+2]
shr bx,1
mov al,bl
and al,1
ret
NEWSYM sa12210w ; Timer Settings
mov [SA1TimerSet],al
ret
NEWSYM sa12211w ; Timer Clear
mov dword[SA1TimerVal],0
ret
NEWSYM sa12212w
mov [SA1TimerCount],al
ret
NEWSYM sa12213w
mov [SA1TimerCount+1],al
ret
NEWSYM sa12214w
mov [SA1TimerCount+2],al
ret
NEWSYM sa12215w
mov [SA1TimerCount+3],al
ret
NEWSYM sa12230w
mov [SA1DMAInfo],al
ret
NEWSYM sa12231w
mov [SA1DMAChar],al
; if b7=1, then end of chdma process
ret
SA1QuickF sa12232w, SA1DMASource
SA1QuickF sa12233w, SA1DMASource+1
SA1QuickF sa12234w, SA1DMASource+2
SA1QuickF sa12235w, SA1DMADest
NEWSYM sa12236w
mov [SA1DMADest+1],al
test byte[SA1DMAInfo],10h
jnz near sa1chconv
test byte[SA1DMAInfo],4
jnz .noiram
jmp sa1dmairam
.noiram
ret
NEWSYM sa12237w
mov [SA1DMADest+2],al
test byte[SA1DMAInfo],10h
jnz .nobwram
test byte[SA1DMAInfo],4
jz .nobwram
jmp sa1dmabwram
.nobwram
ret
NEWSYM sa12238w
mov [SA1DMACount],al
ret
NEWSYM sa12239w
mov [SA1DMACount+1],al
ret
NEWSYM sa1dmaptr, dd 0
NEWSYM sa1dmaptrs, dd 0
NEWSYM sa1dmairam
mov ebx,[SA1DMADest]
and ebx,7FFh
add ebx,IRAM
mov [sa1dmaptr],ebx
jmp executesa1dma
NEWSYM sa1dmabwram
mov ebx,[SA1DMADest]
and ebx,3FFFFh
add ebx,[SA1RAMArea]
mov [sa1dmaptr],ebx
executesa1dma:
test byte[SA1DMAInfo],1
jz .nobwram
mov ebx,[SA1DMASource]
and ebx,3FFFFh
add ebx,[SA1RAMArea]
mov [sa1dmaptrs],ebx
jmp .doneram
.nobwram
test byte[SA1DMAInfo],2
jz .noiram
mov ebx,[SA1DMASource]
and ebx,7FFh
add ebx,IRAM
mov [sa1dmaptrs],ebx
jmp .doneram
.noiram
xor ebx,ebx
mov bl,[SA1DMASource+2]
mov ebx,[snesmmap+ebx*4]
push ecx
xor ecx,ecx
mov cx,[SA1DMASource]
add ebx,ecx
mov [sa1dmaptrs],ebx
pop ecx
.doneram
push edx
push eax
push ecx
mov ecx,[SA1DMACount]
or ecx,ecx
jz .notransfer
mov ebx,[sa1dmaptrs]
mov edx,[sa1dmaptr]
.loop
mov al,[ebx]
mov [edx],al
inc ebx
inc edx
loop .loop
.notransfer
pop ecx
pop eax
pop edx
ret
; Character Conversion DMA
sa1chconv:
; or byte[SA1DoIRQ],4
or byte[SA1DoIRQ],8
ret
mov ebx,[SA1DMADest]
mov byte[debstop4],1
; and ebx,7FFh
and ebx,3FFFFh
add ebx,[SA1RAMArea]
mov [sa1dmaptr],ebx
mov ebx,[SA1DMASource]
and ebx,3FFFFh
add ebx,[SA1RAMArea]
mov [sa1dmaptrs],ebx
; 4 colors = 32 bytes, 16 colors = 64 bytes, 256 colors = 128 bytes
; SA1DMAChar,bit 2-4 = # of 8x8 tiles/horizontal row (0=1,1=2,2=3,..,5=32)
; SA1DMAChar,bit 0-1 = Color Mode (0=8b,1=4b,2=2b,3=?)
test byte[SA1DMAChar],1
jnz .4bit
test byte[SA1DMAChar],2
jnz .2bit
mov ebx,[sa1dmaptr]
push ecx
pop ecx
ret
.4bit
mov ebx,[sa1dmaptr]
push ecx
pop ecx
ret
.2bit
push ecx
mov ecx,8
mov ebx,[sa1dmaptr]
push edx
mov edx,[sa1dmaptrs]
; sub ebx,1000h
jmp .skipall
mov ecx,1000h
.loops
and edx,07FFh
mov al,[ebx]
mov [IRAM+edx],al
inc ebx
inc edx
loop .loops
pop edx
pop ecx
ret
.skipall
jmp .conv
; repeat for 320 tiles
mov ecx,320
.chl2
mov al,[ebx]
mov dword[.numrows],16
.chl
mov [edx],al
inc edx
dec dword[.numrows]
jne .chl
inc ebx
dec ecx
jnz .chl2
pop edx
pop ecx
ret
; Convert 10 rows into bitplane from ebx to edx
.conv
mov dword[.numrows],10
.cloop3
mov ch,32
.cloop
mov cl,8
.cloop2
mov ax,[ebx]
add ax,ax
rcl byte[edx+8],1
add ax,ax
rcl byte[edx],1
add ax,ax
rcl byte[edx+8],1
add ax,ax
rcl byte[edx],1
add ax,ax
rcl byte[edx+8],1
add ax,ax
rcl byte[edx],1
add ax,ax
rcl byte[edx+8],1
add ax,ax
rcl byte[edx],1
add ax,ax
rcl byte[edx+8],1
add ax,ax
rcl byte[edx],1
add ax,ax
rcl byte[edx+8],1
add ax,ax
rcl byte[edx],1
add ax,ax
rcl byte[edx+8],1
add ax,ax
rcl byte[edx],1
add ax,ax
rcl byte[edx+8],1
add ax,ax
rcl byte[edx],1
add ebx,64
inc edx
dec cl
jnz near .cloop2
add edx,8
sub ebx,64*8-2
dec ch
jnz near .cloop
sub ebx,2*32
add ebx,8*64
dec dword[.numrows]
jnz near .cloop3
pop edx
pop ecx
mov ebx,[sa1dmaptr]
push ecx
mov ecx,32
.loop
; mov dword[IRAM+ebx],0FFFFFFFFh
add ebx,4
loop .loop
pop ecx
ret
.numrows dd 0
NEWSYM initSA1regs
setreg 2300h*4,sa12300r
setreg 2301h*4,sa12301r
setreg 2302h*4,sa12302r
setreg 2303h*4,sa12303r
setreg 2304h*4,sa12304r
setreg 2305h*4,sa12305r
setreg 2306h*4,sa12306r
setreg 2307h*4,sa12307r
setreg 2308h*4,sa12308r
setreg 2309h*4,sa12309r
setreg 230Ah*4,sa1230Ar
setreg 230Bh*4,sa1230Br
setreg 230Ch*4,sa1230Cr
setreg 230Dh*4,sa1230Dr
setreg 230Eh*4,sa1230Er
; Set IRam, memory address 3000-37FF
mov edi,3000h*4
add edi,[regptr]
mov eax,IRamRead
mov ecx,800h
.loopr
mov [edi],eax
add edi,4
loop .loopr
ret
NEWSYM initSA1regsw
setregw 2200h*4,sa12200w
setregw 2201h*4,sa12201w
setregw 2202h*4,sa12202w
setregw 2203h*4,sa12203w
setregw 2204h*4,sa12204w
setregw 2205h*4,sa12205w
setregw 2206h*4,sa12206w
setregw 2207h*4,sa12207w
setregw 2208h*4,sa12208w
setregw 2209h*4,sa12209w
setregw 220Ah*4,sa1220Aw
setregw 220Bh*4,sa1220Bw
setregw 220Ch*4,sa1220Cw
setregw 220Dh*4,sa1220Dw
setregw 220Eh*4,sa1220Ew
setregw 220Fh*4,sa1220Fw
setregw 2210h*4,sa12210w
setregw 2211h*4,sa12211w
setregw 2212h*4,sa12212w
setregw 2213h*4,sa12213w
setregw 2214h*4,sa12214w
setregw 2215h*4,sa12215w
setregw 2220h*4,sa12220w
setregw 2221h*4,sa12221w
setregw 2222h*4,sa12222w
setregw 2223h*4,sa12223w
setregw 2224h*4,sa12224w
setregw 2225h*4,sa12225w
setregw 2230h*4,sa12230w
setregw 2231h*4,sa12231w
setregw 2232h*4,sa12232w
setregw 2233h*4,sa12233w
setregw 2234h*4,sa12234w
setregw 2235h*4,sa12235w
setregw 2236h*4,sa12236w
setregw 2237h*4,sa12237w
setregw 2238h*4,sa12238w
setregw 2239h*4,sa12239w
setregw 223Fh*4,sa1223Fw
setregw 2250h*4,sa12250w
setregw 2251h*4,sa12251w
setregw 2252h*4,sa12252w
setregw 2253h*4,sa12253w
setregw 2254h*4,sa12254w
setregw 2259h*4,sa12259w
setregw 225Ah*4,sa1225Aw
setregw 225Bh*4,sa1225Bw
mov edi,3000h*4
add edi,[regptw]
mov eax,IRamWrite
mov ecx,800h
.loopw
mov [edi],eax
add edi,4
loop .loopw
setregw 3000h*4,IRamWrite2
ret
NEWSYM SDD1Reset
setregw 4801h*4,sdd14801w
setregw 4802h*4,dbstop
setregw 4803h*4,dbstop
setregw 4804h*4,sdd14804w
setregw 4805h*4,sdd14805w
setregw 4806h*4,sdd14806w
setregw 4807h*4,sdd14807w
setregw 4808h*4,dbstop
setregw 4809h*4,dbstop
setregw 480Ah*4,dbstop
setregw 480Bh*4,dbstop
setregw 480Ch*4,dbstop
setregw 480Dh*4,dbstop
setregw 480Eh*4,dbstop
setregw 480Fh*4,dbstop
ret
NEWSYM initSDD1regs
setreg 4804h*4,sdd14804
setreg 4805h*4,sdd14805
setreg 4806h*4,sdd14806
setreg 4807h*4,sdd14807
ret
dbstop:
mov byte[debstop3],1
ret
NEWSYM sdd14801w
cmp al,0
jne .notzero
ret
.notzero
mov byte[AddrNoIncr],0
; set banks C0h-FFh to decompressing routine
push eax
push ebx
mov eax,memtabler8+0C0h*4
mov ebx,40h
.loop
mov dword[eax],memaccessbankr8sdd1
add eax,4
dec ebx
jnz .loop
mov dword[Sdd1Mode],1
pop ebx
pop eax
ret
NEWSYM Sa1RegsAsmEnd