www.pudn.com > zsnes117b-src.zip > sa1regs.asm


;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 
 
%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 DIVIDEND: ($000000FF) low byte of low word, defval:00 
;$4821   16 BIT MULTIPLICAND: ($FF00) high byte, defval:00 
;        32 BIT DIVIDEND: ($0000FF00) high byte of low word, defval:00 
;$4822   32 BIT DIVIDEND: ($00FF0000) low byte of high word, defval:00 
;$4823   32 BIT DIVIDEND: ($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