; ZSNES SuperFX emulation code and wrappers
; (C) Copyright 1997-8 zsKnight and _Demo_

; Used with the kind permission of the copyright holders.
;

[BITS 32]
SECTION .data

%macro ALIGN32 0
  times ($$-$) & 7 nop    ; Long word alignment
%endmacro

%macro ALIGN16 0
  times ($$-$) & 1Fh nop    ; Long word alignment
%endmacro

%macro setregw 2
    mov edi,%1
    add edi,[regptw]
    mov eax,%2
    mov [edi],eax
%endmacro

%macro setreg 2
    mov edi,%1
    add edi,[regptr]
    mov eax,%2
    mov [edi],eax
%endmacro

flagnz   dd 0
romdata       dd 0              ; rom data  (4MB = 4194304)

regptr        dd 0              ; pointer to registers
regptw        dd 0              ; pointer to registers
regptra times 49152 db 0
regptwa times 49152 db 0

debstop db 0
SfxMemTable times 256 dd 0
sfxramdata    dd 0              ; SuperFX Ram Data
FxTable times 256 dd 0
FxTableA1 times 256 dd 0
FxTableA2 times 256 dd 0
FxTableA3 times 256 dd 0
FxTableb times 256 dd 0
FxTablebA1 times 256 dd 0
FxTablebA2 times 256 dd 0
FxTablebA3 times 256 dd 0
FxTablec times 256 dd 0
FxTablecA1 times 256 dd 0
FxTablecA2 times 256 dd 0
FxTablecA3 times 256 dd 0
FxTabled times 256 dd 0
FxTabledA1 times 256 dd 0
FxTabledA2 times 256 dd 0
FxTabledA3 times 256 dd 0

%INCLUDE "i386/fxtable.asm"
%INCLUDE "i386/sfxproc.asm"
%INCLUDE "i386/fxemu2.asm"
%INCLUDE "i386/fxemu2b.asm"
%INCLUDE "i386/fxemu2c.asm"

;
; Snes9x wrapper functions for the zsnes SuperFX code
; (C) Copyright 1998 Gary Henderson

SECTION .data

%ifdef __DJGPP__
%define SRAM _SRAM
%define ROM _ROM
%define RegRAM _RegRAM
%define S9xResetSuperFX _S9xResetSuperFX
%define S9xSuperFXWriteReg _S9xSuperFXWriteReg
%define S9xSuperFXReadReg _S9xSuperFXReadReg
%define S9xSuperFXExec _S9xSuperFXExec
%define S9xSuperFXPreSaveState _S9xSuperFXPreSaveState
%define S9xSuperFXPostSaveState _S9xSuperFXPostSaveState
%define S9xSuperFXPostLoadState _S9xSuperFXPostLoadState
%endif

EXTERN SRAM
EXTERN ROM
EXTERN RegRAM

SECTION .text

GLOBAL S9xResetSuperFX
GLOBAL S9xSuperFXWriteReg
GLOBAL S9xSuperFXReadReg
GLOBAL S9xSuperFXExec
GLOBAL S9xSuperFXPreSaveState
GLOBAL S9xSuperFXPostSaveState
GLOBAL S9xSuperFXPostLoadState

StartSFX:
StartSFXret:
	jmp S9xSuperFXExec

S9xResetSuperFX:
	push ebx
	push esi
	push edi
	push ebp

	mov dword[SfxR1],0
	mov dword[SfxR2],0

	mov eax,dword[SRAM]
	mov dword[sfxramdata],eax
	mov eax,dword[ROM]
	mov dword[romdata],eax

	call InitFxTables

	mov dword[SfxSFR],0
	mov byte[SfxSCMR],0
	mov dword[regptr],regptra
	sub dword[regptr],8000h   ; Since register address starts @ 2000h
	mov dword[regptw],regptwa
	sub dword[regptw],8000h   ; Since register address starts @ 2000h
	call initsfxregsw
	call initsfxregsr
	pop ebp
	pop edi
	pop esi
	pop ebx
	ret

S9xSuperFXWriteReg:
	mov eax,dword[esp+4]
	mov ecx,dword[esp+8]
	push ebx
	push esi
	push edi
	push ebp
	call dword[regptwa+ecx*4-8000h]
	pop ebp
	pop edi
	pop esi
	pop ebx
	ret

S9xSuperFXReadReg:
	mov ecx,dword[esp+4]
	push ebx
	push esi
	push edi
	push ebp
	test dword[regptra+ecx*4-8000h], ~0
	jz .skipread
	call dword[regptra+ecx*4-8000h]
.skipread:
	pop ebp
	pop edi
	pop esi
	pop ebx
	and eax, 255
	ret

S9xSuperFXExec:
    test byte[SfxSFR],20h
    jz .endfx
	push ebx
	push esi
	push edi
	push ebp
    mov bl,[SfxPBR]
    mov al,[SfxSCMR]
    and bl,7Fh
    cmp bl,70h
    jae .ram
    test al,10h
    jz .noaccess
    jmp .noram
.ram
    test al,08h
    jz .noaccess
.noram
    mov dword [NumberOfOpcodes],350 ;678
    test byte[SfxCLSR],01h
    jz .nohighsfx
    mov dword [NumberOfOpcodes],700 ;678*2
.nohighsfx
; XXX
;    mov dword [NumberOfOpcodes],0FFFFFFFFh
    call MainLoop
    test byte[SfxSFR],20h
    jnz .noaccess
    test byte[SfxSFR+1],80h
    jz .noaccess
; Trigger an IRQ
    
.noaccess
	pop ebp
	pop edi
	pop esi
	pop ebx
.endfx
    ret

S9xSuperFXPreSaveState:
    mov ecx,[SfxCROM]
    sub [SfxRomBuffer],ecx
    mov ecx,[SfxRAMMem]
    sub [SfxLastRamAdr],ecx
; Copy num2writesfxreg bytes from SfxR0 to a free area in RegRAM.
    push ebx
    mov ecx,SfxR0
    mov edx,[RegRAM]
    add edx,7000h
    mov ebx,num2writesfxreg
.loop
    mov al,[ecx]
    mov [edx],al
    inc ecx
    inc edx
    dec ebx
    jnz .loop
    pop ebx
    mov ecx,[SfxCROM]
    add [SfxRomBuffer],ecx
    mov ecx,[SfxRAMMem]
    add [SfxLastRamAdr],ecx
    ret

S9xSuperFXPostSaveState:
    ret

S9xSuperFXPostLoadState:
; Copy num2writesfxreg bytes a free area in RegRAM to SfxR0
    push ebx
    mov ecx,SfxR0
    mov edx,[RegRAM]
    add edx,7000h
    mov ebx,num2writesfxreg
.loop
    mov al,[edx]
    mov [ecx],al
    inc ecx
    inc edx
    dec ebx
    jnz .loop
    pop ebx
    xor ecx,ecx
    mov cl,[SfxPBR]
    mov ecx,[SfxMemTable+ecx*4]
    mov [SfxCPB],ecx

    xor ecx,ecx
    mov cl,[SfxROMBR]
    mov ecx,[SfxMemTable+ecx*4]
    mov [SfxCROM],ecx

    xor ecx,ecx
    mov cl,[SfxRAMBR]
    shl ecx,16
    add ecx,[sfxramdata]
    mov dword [SfxRAMMem],ecx

    mov ecx,[SfxCROM]
    add [SfxRomBuffer],ecx
    mov ecx,[SfxRAMMem]
    add [SfxLastRamAdr],ecx
    ret
