;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.


; 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,SPC7110filep
EXTSYM SPC7_Convert_Upper,SPC7_Convert_Lower
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
EXTSYM NumofBanks

%include "cpu/regs.mac"
%include "cpu/regsw.mac"


SECTION .data

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

SECTION .text

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

SECTION .bss
NEWSYM SPCDecompFin, resd 1

SECTION .text

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
    dec ecx
    jnz .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

SECTION .bss
NEWSYM CurPtrVal, resd 1
NEWSYM CurCompCounter2, resd 1
NEWSYM CurPtrLen, resd 1
NEWSYM CurValUsed, resb 1
NEWSYM PrevDecompPtr, resw 1
NEWSYM CurDecompPtr, resw 1
NEWSYM CurDecompSize, resw 1
NEWSYM DecompArray, resb 65536
NEWSYM DecompAPtr, resd 1
lastentry resd 1

SECTION .text


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
    dec ecx
    jnz .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
    dec ecx
    jnz .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,dword[SPC7110filep]
    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
    dec ecx
    jnz .sploop2

    mov edx,SPC7110nfname
    call Open_File
    jnc .nocaseerror
    pushad
    call SPC7_Convert_Upper
    popad
    call Open_File
    jnc .nocaseerror
    pushad
    call SPC7_Convert_Lower
    popad
    call Open_File
    jc .error
.nocaseerror
    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

; 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

;$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

SECTION .data
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

SECTION .text

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


; SA-1 Start
; ----------

SECTION .data

; 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

NEWSYM BWShift, dd 0
NEWSYM BWAndAddr, dd 0
NEWSYM BWAnd, dd 0
NEWSYM BWRAnd, dd 0

SA1Reserved times 456 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

SECTION .text

%macro SA1QuickF 2
NEWSYM %1
    mov [%2],al
    ret
%endmacro

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 word[SA1Overflow],0
    ret

%macro BankSwitch 4
    push ecx
    push edx
    push eax
    mov [SA1BankVal+%1],al
    mov ebx,snesmmap+%2*4
    test al,80h
    jz .noupper
    cmp byte [NumofBanks],64
    jne .BSBigBank
    and eax,1
.BSBigBank
    and eax,07h
    shl eax,20
    push eax
    jmp .yesupper
.noupper
    cmp byte [NumofBanks],64
    jne .BSBigBank2
    and eax,1
.BSBigBank2
    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
    dec ecx
    jnz .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
    dec ecx
    jnz .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
    dec ecx
    jnz .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
EXTSYM BWUsed2
    mov [BWUsed2],al
    test al,80h
    jnz .upper
    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 .nosa1b
    mov dword[CurBWPtr],ebx
.nosa1b
    mov byte[BWShift],0
    mov byte[BWAndAddr],0
    mov byte[BWAnd],0FFh
    mov byte[BWRAnd],0h
    ret
.upper
    mov bl,al
    and ebx,7Fh
    test byte[SA1Overflow+1],80h
    jz .16col
    shl ebx,11
    mov byte[BWShift],2
    mov byte[BWAndAddr],03h
    mov byte[BWAnd],03h
    mov byte[BWRAnd],0FCh
    jmp .4col
.16col
    mov byte[BWShift],1
    mov byte[BWAndAddr],01h
    mov byte[BWAnd],0Fh
    mov byte[BWRAnd],0F0h
    and ebx,3Fh
    shl ebx,12
.4col
    add ebx,[romdata]
    add ebx,1024*4096
    mov dword[SA1BWPtr],ebx
    cmp byte[SA1Status],0
    je .nosa1
    mov dword[CurBWPtr],ebx
.nosa1
;    mov byte[debstop3],1
    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

SECTION .bss
NEWSYM sa1dmaptr, resd 1
NEWSYM sa1dmaptrs, resd 1

SECTION .text

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
    dec ecx
    jnz .loop
.notransfer
    pop ecx
    pop eax
    pop edx
    ret

SECTION .bss
tempblah resb 1

SECTION .text

%macro setbit2b 2
    test al,%1
    jz %%nosb
    or word[ebx],%2
%%nosb
%endmacro

%macro setbit2b2 2
    test al,%1
    jz %%nosb
    or word[ebx+16],%2
%%nosb
%endmacro

; Character Conversion DMA
sa1chconv:
;    or byte[SA1DoIRQ],4
    or byte[SA1DoIRQ],8
;    mov byte[debstop3],1


    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 near .2bit
    mov ebx,[sa1dmaptr]
    push ecx
    pop ecx
    ret
.4bit
    pushad
    mov edx,[sa1dmaptrs]
    mov ebx,[romdata]
    add ebx,4096*1024+1024*1024
    mov edi,16
.loop34b
    push ebx
    push edx
    mov ecx,32
.loop4b
    mov esi,8
    push ebx
    push edx
.loop24b
    mov word[ebx],0
    mov al,[edx+3]
    setbit2b 10h,0001h
    setbit2b 20h,0100h
    setbit2b2 40h,0001h
    setbit2b2 80h,0100h
    setbit2b 01h,0002h
    setbit2b 02h,0200h
    setbit2b2 04h,0002h
    setbit2b2 08h,0200h
    mov al,[edx+2]
    setbit2b 10h,0004h
    setbit2b 20h,0400h
    setbit2b2 40h,0004h
    setbit2b2 80h,0400h
    setbit2b 01h,0008h
    setbit2b 02h,0800h
    setbit2b2 04h,0008h
    setbit2b2 08h,0800h
    mov al,[edx+1]
    setbit2b 10h,0010h
    setbit2b 20h,1000h
    setbit2b2 40h,0010h
    setbit2b2 80h,1000h
    setbit2b 01h,0020h
    setbit2b 02h,2000h
    setbit2b2 04h,0020h
    setbit2b2 08h,2000h
    mov al,[edx]
    setbit2b 10h,0040h
    setbit2b 20h,4000h
    setbit2b2 40h,0040h
    setbit2b2 80h,4000h
    setbit2b 01h,0080h
    setbit2b 02h,8000h
    setbit2b2 04h,0080h
    setbit2b2 08h,8000h
    add ebx,2
    add edx,128
    dec esi
    jnz near .loop24b
    pop edx
    pop ebx
    add edx,4
    add ebx,32
    dec ecx
    jnz near .loop4b
    pop edx
    pop ebx
    add edx,128*8
    add ebx,128*8
    dec edi
    jnz near .loop34b

    mov ecx,10*128*8
    mov edx,[sa1dmaptrs]
    mov ebx,[romdata]
    add ebx,4096*1024+1024*1024
.next4b
    mov al,[ebx]
    mov [edx],al
    inc ebx
    inc edx
    dec ecx
    jnz .next4b

    popad
    ret

.2bit
    pushad
    mov edx,[sa1dmaptrs]
    mov ebx,[romdata]
    add ebx,4096*1024+1024*1024
    mov edi,16
.loop3
    push ebx
    push edx
    mov ecx,32
.loop
    mov esi,8
    push ebx
    push edx
.loop2
    mov word[ebx],0
    mov al,[edx+1]
    setbit2b 40h,0001h
    setbit2b 80h,0100h
    setbit2b 10h,0002h
    setbit2b 20h,0200h
    setbit2b 04h,0004h
    setbit2b 08h,0400h
    setbit2b 01h,0008h
    setbit2b 02h,0800h
    mov al,[edx]
    setbit2b 40h,0010h
    setbit2b 80h,1000h
    setbit2b 10h,0020h
    setbit2b 20h,2000h
    setbit2b 04h,0040h
    setbit2b 08h,4000h
    setbit2b 01h,0080h
    setbit2b 02h,8000h
    add ebx,2
    add edx,64
    dec esi
    jnz near .loop2
    pop edx
    pop ebx
    add edx,2
    add ebx,16
    dec ecx
    jnz near .loop
    pop edx
    pop ebx
    add edx,64*8
    add ebx,64*8
    dec edi
    jnz near .loop3

    mov ecx,10*64*8
    mov edx,[sa1dmaptrs]
    mov ebx,[romdata]
    add ebx,4096*1024+1024*1024
.next
    mov al,[ebx]
    mov [edx],al
    inc ebx
    inc edx
    dec ecx
    jnz .next

    popad
    ret
SECTION .bss
.numrows resd 1

SECTION .text

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
    dec ecx
    jnz .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
    ; Missing 2226-222A
    ; Missing 2240-224F (Bitmap register file)

    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
    dec ecx
    jnz .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


