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

%include "macros.mac"

EXTSYM DSPMem,FPSOn,Makemode7Table,MessageOn,vesa2red10,scanlines,smallscreenon
EXTSYM MsgCount,Msgptr,OutputGraphicString,OutputGraphicString16b
EXTSYM PrepareSaveState,ResetState,breakatsignb,breakatsignc,cvidmode
EXTSYM cbitmode,copyvid,curblank,drawhline,drawhline16b,drawvline
EXTSYM drawvline16b,fnames,frameskip,mode7tab,pressed,spcA
EXTSYM spcBuffera,spcNZ,spcP,spcPCRam,spcRam,spcRamDP,spcS,spcX,spcY
EXTSYM spcon,vesa2_bpos,vesa2_clbit,vesa2_gpos,vesa2_rpos,vesa2selec
EXTSYM vidbuffer,spritetablea,sprlefttot,newengen,spcextraram,resolutn
EXTSYM Open_File,Close_File,Read_File,Write_File,Create_File,Get_Key,Get_Date
EXTSYM continueprognokeys,ForceNonTransp,GUIOn,Check_Key,JoyRead
EXTSYM GetScreen,SSKeyPressed,SPCKeyPressed,StopSound,StartSound    
EXTSYM ExecExitOkay,t1cc
EXTSYM Clear2xSaIBuffer
EXTSYM romdata,romtype,ScreenShotFormat
EXTSYM Voice0Disable,Voice1Disable,Voice2Disable,Voice3Disable
EXTSYM Voice4Disable,Voice5Disable,Voice6Disable,Voice7Disable
EXTSYM SRAMChdir, SPCPath, SnapPath, Change_Dir, CHPath, ZFileCHDir
%ifndef NO_PNG
EXTSYM Grab_PNG_Data
%endif

%macro ChangeDir 1
    cmp byte[%1],0
    je %%end
    pushad
    mov ebx,%1
    mov [CHPath],ebx
    call ZFileCHDir
    popad
%%end
%endmacro

%macro ChangeDirSRAM 0
    pushad
    call SRAMChdir
    popad
%endmacro

GUIBufferData:
    mov ecx,16384
    cmp byte[cbitmode],1
    jne near .16b
    add ecx,16384
.16b
    ; copy to spritetable
    mov esi,[vidbuffer]
    mov edi,[spritetablea]
.loop
    mov eax,[esi]
    mov [edi],eax
    add esi,4
    add edi,4
    dec ecx
    jnz .loop
    mov edi,sprlefttot
    mov ecx,64*5
.a
    mov dword[edi],0
    add edi,4
    dec ecx
    jnz .a
    ret

GUIUnBuffer:
    mov ecx,16384
    cmp byte[cbitmode],1
    jne near .16b
    add ecx,16384
.16b
    ; copy from spritetable
    mov esi,[vidbuffer]
    mov edi,[spritetablea]
.loop
    mov eax,[edi]
    mov [esi],eax
    add esi,4
    add edi,4
    dec ecx
    jnz .loop
    ret

SECTION .bss
NEWSYM nextmenupopup, resb 1
NEWSYM NoInputRead, resb 1
NEWSYM PrevMenuPos, resb 1
NEWSYM MenuDisplace, resd 1
NEWSYM MenuDisplace16, resd 1
NEWSYM MenuNoExit, resb 1
NEWSYM SPCSave, resb 1

%ifdef SPCDUMP
SECTION .data
NEWSYM SPCSave_dump, db 0
SECTION .bss

EXTSYM SPCSave_buffer, SPCSave_ports
NEWSYM SPCSave_handle, resd 1
%endif

SECTION .text

NEWSYM showmenu
    mov byte[ForceNonTransp],1
    cmp byte[cbitmode],1
    je near .nopalread
    mov edi,[vidbuffer]
    add edi,100000
    mov dx,03C7h
    mov al,0
    out dx,al
    mov dx,03C9h
    mov ecx,768
    mov byte[edi],12
    inc edi
.b
    in al,dx
    shl al,2
    mov [edi],al
    inc edi
    dec ecx
    jnz .b
.nopalread

    cmp byte[cbitmode],1
    je near .nopal16b
    ; set palette of colors 128,144, and 160 to white, blue, and red
    mov al,128
    mov dx,03C8h
    out dx,al
    inc dx
    mov al,63
    out dx,al
    out dx,al
    out dx,al
    mov al,144
    mov dx,03C8h
    out dx,al
    inc dx
    xor al,al
    out dx,al
    out dx,al
    mov al,50
    out dx,al
    mov al,160
    mov dx,03C8h
    out dx,al
    inc dx
    mov al,45
    out dx,al
    xor al,al
    out dx,al
    out dx,al
.nopal16b

    mov byte[NoInputRead],0
    cmp byte[newengen],0
    je .nong16b
    cmp byte[cbitmode],0
    je .nong16b
    call GetScreen
.nong16b
    cmp byte[SSKeyPressed],1
    jne .nosskey
    mov byte[SSKeyPressed],0
    call savepcx
    jmp .nopalwrite
.nosskey
    cmp byte[SPCKeyPressed],1
    je near .savespckey
    test byte[pressed+14],1
    jz .nof12
    call savepcx
    jmp .nopalwrite
.nof12
    mov dword[menucloc],0
    cmp byte[nextmenupopup],0
    je .nomenuinc2
    mov byte[pressed+1Ch],0
    mov dword[menucloc],40*288
    cmp byte[PrevMenuPos],1
    jne .nomenuinc
    mov dword[menucloc],50*288
.nomenuinc
    cmp byte[PrevMenuPos],2
    jne .nomenuinc2
    mov dword[menucloc],60*288
.nomenuinc2
    cmp byte[PrevMenuPos],3
    jne .nomenuinc3
    mov dword[menucloc],70*288
.nomenuinc3

    mov dword[menudrawbox8b.stringi+13],' BMP'
%ifndef NO_PNG 
    cmp byte[ScreenShotFormat],0
    je .normalscrn
    mov dword[menudrawbox8b.stringi+13],' PNG'
%endif
.normalscrn
    cmp byte[cbitmode],1
    je near .nopcx
    mov dword[menudrawbox8b.stringi+13],' PCX'
.nopcx
    mov byte[nextmenupopup],0
    mov byte[menu16btrans],0
    mov byte[pressed+1],0
    mov byte[pressed+59],0
    mov byte[curblank],00h
    call GUIBufferData
    ; Draw box
    call menudrawbox8b
    call menudrawbox8b
    cmp byte[newengen],0
    je .notng
    mov byte[GUIOn],1
.notng
    pushad
    call copyvid
    popad
    call StopSound
.nextkey
    call GUIUnBuffer
    call menudrawbox8b
    push eax
    call copyvid
    pop eax

    call JoyRead
    call Check_Key
    or al,al
    jz .nextkey
    call Get_Key
    cmp al,0
    jne near .processextend

    call Get_Key
    cmp al,72
    jne .noup
    cmp dword[menucloc],0
    jne .nogoup
    add dword[menucloc],80*288
.nogoup
    sub dword[menucloc],10*288
    call menudrawbox8b
;    mov al,[newengen]                  ; WTF?
;    mov byte[newengen],0

;    mov [newengen],al
    jmp .nextkey
.noup
    cmp al,80
    jne .nodown
    cmp dword[menucloc],70*288
    jne .nogodown
    sub dword[menucloc],80*288
.nogodown
    add dword[menucloc],10*288
    call menudrawbox8b
;    mov al,[newengen]
;    mov byte[newengen],0
;    push eax
    call copyvid
;    pop eax
;    mov [newengen],al
    jmp .nextkey
.nodown
    jmp .nextkey
.processextend
    cmp al,27
    je near .exitloop
    cmp al,13
    je .done
    jmp .nextkey
.done
    call GUIUnBuffer
;    mov al,[newengen]
;    mov byte[newengen],0
;    push eax
    call copyvid
;    pop eax
;    mov [newengen],al
    cmp dword[menucloc],0
    jne .nosavepcx
    call savepcx
.nosavepcx
    cmp dword[menucloc],40*288
    jne .nosavepcx2
    call savepcx
    mov byte[ExecExitOkay],0
    mov byte[nextmenupopup],3
    mov byte[NoInputRead],1
    mov byte[t1cc],0
    mov byte[PrevMenuPos],0
.nosavepcx2
    cmp dword[menucloc],50*288
    jne .noskipframe
    mov byte[ExecExitOkay],0
    mov byte[nextmenupopup],3
    mov byte[NoInputRead],1
    mov byte[t1cc],0
    mov byte[PrevMenuPos],1
.noskipframe
    cmp dword[menucloc],70*288
    jne .noimagechange
    cmp byte[cbitmode],0
    je .noimagechange
    xor byte[ScreenShotFormat],1
    mov byte[MenuNoExit],1
    mov byte[ExecExitOkay],0
    mov byte[nextmenupopup],1
    mov byte[NoInputRead],1
    mov byte[t1cc],0
    mov byte[PrevMenuPos],3
.noimagechange
    cmp dword[menucloc],60*288
    jne .nomovewin
    mov byte[MenuNoExit],1
    mov byte[ExecExitOkay],0
    mov byte[nextmenupopup],1
    mov byte[NoInputRead],1
    mov byte[t1cc],0
    mov byte[PrevMenuPos],2
    cmp dword[MenuDisplace],0
    je .movewin
    mov dword[MenuDisplace],0
    mov dword[MenuDisplace16],0
    jmp .nomovewin
.movewin
    mov dword[MenuDisplace],90*288
    mov dword[MenuDisplace16],90*288*2
.nomovewin
    cmp dword[menucloc],10*288
    jne .nofps
    cmp byte[frameskip],0
    je .yesfs
    mov dword[Msgptr],.unablefps
    mov eax,[MsgCount]
    mov [MessageOn],eax
    jmp .nofps
.yesfs
    xor byte[FPSOn],1
.nofps
    cmp dword[menucloc],20*288
    jne near .nospcsave
.savespckey
    cmp byte[spcon],0
    je .nospc

%ifdef SPCDUMP
	cmp byte[SPCSave_dump], 1
	jne .start_dump

	mov ebx, [SPCSave_handle]
	mov eax, -1
	mov [SPCSave_buffer], eax
	mov ecx, 4
	mov edx, SPCSave_buffer
	call Write_File
	call Close_File
	mov byte[SPCSave_dump], 0
	jmp .nospcsave
.start_dump
%endif

;    cmp byte[newengen],1
;    je .unablespc
    mov dword[Msgptr],.search
    mov eax,[MsgCount]
    mov [MessageOn],eax
;    mov al,[newengen]
;    mov byte[newengen],0
;    push eax
    call copyvid
;    pop eax
;    mov [newengen],al
;    call breakatsignc
;    cmp byte[prbreak],1
;    je .yesesc
    mov byte[SPCSave],1
    call breakatsignb
    mov byte[SPCSave],0
;    cmp byte[prbreak],1
;    je .yesesc
    call savespcdata

    mov byte[curblank],40h
    mov dword[Msgptr],.saved
    mov eax,[MsgCount]
    mov [MessageOn],eax
    jmp .nospcsave
.nospc
    mov dword[Msgptr],.nosound
    mov eax,[MsgCount]
    mov [MessageOn],eax
    jmp .nospcsave
.unablespc
    mov dword[Msgptr],.unable
    mov eax,[MsgCount]
    mov [MessageOn],eax
    jmp .nospcsave
.yesesc
    mov dword[Msgptr],.escpress
    mov eax,[MsgCount]
    mov [MessageOn],eax
.nospcsave
    cmp dword[menucloc],30*288
    jne .nosnddmp
    call dumpsound
    mov dword[Msgptr],.sndbufsav
    mov eax,[MsgCount]
    mov [MessageOn],eax
.nosnddmp
    cmp byte[SPCKeyPressed],1
    jne .exitloop
    mov byte[SPCKeyPressed],0
    jmp .nopalwrite
.exitloop
    call GUIUnBuffer
;    mov al,[newengen]
;    mov byte[newengen],0
;    push eax
    call copyvid
;    pop eax
;    mov [newengen],al
    cmp byte[cbitmode],1
    je near .nopalwrite
    mov edi,[vidbuffer]
    add edi,100000
    mov dx,03C8h
    mov al,0
    out dx,al
    mov dx,03C9h
    mov ecx,768
    inc edi
.c
    mov al,[edi]
    shr al,2
    out dx,al
    inc edi
    dec ecx
    jnz .c
.nopalwrite
    mov eax,pressed
    mov ecx,256
.looppr
    cmp byte[eax],1
    jne .notpr
    mov byte[eax],2
.notpr
    inc eax
    dec ecx
    jnz .looppr
;    mov byte[pressed+1],2
;    cmp byte[pressed+59],1
;    jne .not59
;    mov byte[pressed+59],2
;.not59
;    cmp byte[pressed+28],1
;    jne .not28
;    mov byte[pressed+28],2
;.not28
    call StartSound
    mov byte[ForceNonTransp],0
    mov byte[GUIOn],0
    call Clear2xSaIBuffer
    cmp byte[MenuNoExit],1
    je .noexitmenu
    jmp continueprognokeys
.noexitmenu
    mov byte[MenuNoExit],0
    jmp showmenu

SECTION .data
.unablefps db 'NEED AUTO FRAMERATE ON',0
.sndbufsav db 'BUFFER SAVED AS SOUNDDMP.RAW',0
.search    db 'SEARCHING FOR SONG START.',0
.nosound   db 'SOUND MUST BE ENABLED.',0
.unable    db 'CANNOT USE IN NEW GFX ENGINE.',0
.escpress  db 'ESC TERMINATED SEARCH.',0
.saved     db '.SPC FILE SAVED.',0
SECTION .text

NEWSYM menudrawbox8b
    cmp byte[cbitmode],1
    je near menudrawbox16b
    ; draw a small blue box with a white border
    mov esi,40+20*288
    add esi,[vidbuffer]
    add esi,[MenuDisplace]
    mov ecx,150
    mov al,95
.loop
    mov byte[esi],144
    inc esi
    dec ecx
    jnz .loop
    add esi,288-150
    dec al
    mov ecx,150
    jnz .loop
    mov al,128
    ; Draw lines
    mov esi,40+20*288
    add esi,[vidbuffer]
    add esi,[MenuDisplace]
    mov ecx,150
    call drawhline
    mov esi,40+20*288
    add esi,[vidbuffer]
    add esi,[MenuDisplace]
    mov ecx,95
    call drawvline
    mov esi,40+114*288
    add esi,[vidbuffer]
    add esi,[MenuDisplace]
    mov ecx,150
    call drawhline
    mov esi,40+32*288
    add esi,[vidbuffer]
    add esi,[MenuDisplace]
    mov ecx,150
    call drawhline
    mov esi,189+20*288
    add esi,[vidbuffer]
    add esi,[MenuDisplace]
    mov ecx,95
    call drawvline
    call menudrawcursor8b

    mov esi,45+23*288
    add esi,[vidbuffer]
    add esi,[MenuDisplace]
    mov edi,.string
    call OutputGraphicString
    mov esi,45+35*288
    add esi,[vidbuffer]
    add esi,[MenuDisplace]
    mov edi,.stringa
    call OutputGraphicString
    mov esi,45+45*288
    add esi,[vidbuffer]
    add esi,[MenuDisplace]
    mov edi,.stringb
    test byte[FPSOn],1
    jz .nofps
    mov edi,.stringc
.nofps
    call OutputGraphicString
    mov esi,45+55*288
    add esi,[vidbuffer]
    add esi,[MenuDisplace]
    mov edi,.stringd
    call OutputGraphicString
    mov esi,45+65*288
    add esi,[vidbuffer]
    add esi,[MenuDisplace]
    mov edi,.stringe
    call OutputGraphicString
    mov esi,45+75*288
    add esi,[vidbuffer]
    add esi,[MenuDisplace]
    mov edi,.stringf
    call OutputGraphicString
    mov esi,45+85*288
    add esi,[vidbuffer]
    add esi,[MenuDisplace]
    mov edi,.stringg
    call OutputGraphicString
    mov esi,45+95*288
    add esi,[vidbuffer]
    add esi,[MenuDisplace]
    mov edi,.stringh
    call OutputGraphicString
    mov esi,45+105*288
    add esi,[vidbuffer]
    add esi,[MenuDisplace]
    mov edi,.stringi
    call OutputGraphicString
;    mov al,[newengen]
;    mov byte[newengen],0
;    push eax
    call copyvid
;    pop eax
;    mov [newengen],al
    ret

SECTION .data
.string db 'MISC OPTIONS',0
.stringa db 'SAVE SNAPSHOT',0
.stringb db 'SHOW FPS',0
.stringc db 'HIDE FPS',0
.stringd db 'SAVE SPC DATA',0
.stringe db 'SOUND BUFFER DUMP',0
.stringf db 'SNAPSHOT/INCR FRM',0
.stringg db 'INCR FRAME ONLY',0
.stringh db 'MOVE THIS WINDOW',0
.stringi db 'IMAGE FORMAT: ---',0
SECTION .text

NEWSYM menudrawcursor8b
    cmp byte[cbitmode],1
    je near menudrawcursor16b
    ; draw a small red box
    mov esi,41+34*288
    add esi,[menucloc]
    add esi,[vidbuffer]
    add esi,[MenuDisplace]
    mov ecx,148
    mov al,9
.loop
    mov byte[esi],160
    inc esi
    dec ecx
    jnz .loop
    add esi,288-148
    dec al
    mov ecx,148
    jnz .loop

    mov al,128
    ret

SECTION .bss
NEWSYM menucloc, resd 1
SECTION .text

NEWSYM menudrawbox16b
    ; draw shadow behind box
    cmp byte[menu16btrans],0
    jne .noshadow
    mov byte[menu16btrans],1
    mov esi,50*2+30*288*2
    add esi,[vidbuffer]
    add esi,[MenuDisplace16]
    mov ecx,150
    mov al,85
    mov ah,5
.loop16b2
    mov dx,[esi]
    and dx,[vesa2_clbit]
    shr dx,1
    mov [esi],dx
    add esi,2
    dec ecx
    jnz .loop16b2
    add esi,288*2-150*2
    dec al
    mov ecx,150
    jnz .loop16b2
.noshadow

    mov ax,01Fh
    mov cl,[vesa2_rpos]
    shl ax,cl
    mov [.allred],ax
    mov ax,012h
    mov cl,[vesa2_bpos]
    shl ax,cl
    mov dx,ax
    mov ax,01h
    mov cl,[vesa2_gpos]
    shl ax,cl
    mov bx,ax
    mov ax,01h
    mov cl,[vesa2_rpos]
    shl ax,cl
    or bx,ax

    ; draw a small blue box with a white border
    mov esi,40*2+20*288*2
    add esi,[vidbuffer]
    add esi,[MenuDisplace16]
    mov ecx,150
    mov al,95
    mov ah,5
.loop16b
    mov [esi],dx
    add esi,2
    dec ecx
    jnz .loop16b
    add esi,288*2-150*2
    dec ah
    jnz .nocolinc16b
    add dx,bx
    mov ah,5
.nocolinc16b
    dec al
    mov ecx,150
    jnz .loop16b

    ; Draw lines
    mov ax,0FFFFh
    mov esi,40*2+20*288*2
    add esi,[vidbuffer]
    add esi,[MenuDisplace16]
    mov ecx,150
    call drawhline16b
    mov esi,40*2+20*288*2
    add esi,[vidbuffer]
    add esi,[MenuDisplace16]
    mov ecx,95
    call drawvline16b
    mov esi,40*2+114*288*2
    add esi,[vidbuffer]
    add esi,[MenuDisplace16]
    mov ecx,150
    call drawhline16b
    mov esi,40*2+32*288*2
    add esi,[vidbuffer]
    add esi,[MenuDisplace16]
    mov ecx,150
    call drawhline16b
    mov esi,189*2+20*288*2
    add esi,[vidbuffer]
    add esi,[MenuDisplace16]
    mov ecx,95
    call drawvline16b
    call menudrawcursor16b

    mov esi,45*2+23*288*2
    add esi,[vidbuffer]
    add esi,[MenuDisplace16]
    mov edi,menudrawbox8b.string
    call OutputGraphicString16b
    mov esi,45*2+35*288*2
    add esi,[vidbuffer]
    add esi,[MenuDisplace16]
    mov edi,menudrawbox8b.stringa
    call OutputGraphicString16b
    mov esi,45*2+45*288*2
    add esi,[vidbuffer]
    add esi,[MenuDisplace16]
    mov edi,menudrawbox8b.stringb
    test byte[FPSOn],1
    jz .nofps
    mov edi,menudrawbox8b.stringc
.nofps
    call OutputGraphicString16b
    mov esi,45*2+55*288*2
    add esi,[vidbuffer]
    add esi,[MenuDisplace16]
    mov edi,menudrawbox8b.stringd
    call OutputGraphicString16b
    mov esi,45*2+65*288*2
    add esi,[vidbuffer]
    add esi,[MenuDisplace16]
    mov edi,menudrawbox8b.stringe
    call OutputGraphicString16b
    mov esi,45*2+75*288*2
    add esi,[vidbuffer]
    add esi,[MenuDisplace16]
    mov edi,menudrawbox8b.stringf
    call OutputGraphicString16b
    mov esi,45*2+85*288*2
    add esi,[vidbuffer]
    add esi,[MenuDisplace16]
    mov edi,menudrawbox8b.stringg
    call OutputGraphicString16b
    mov esi,45*2+95*288*2
    add esi,[vidbuffer]
    add esi,[MenuDisplace16]
    mov edi,menudrawbox8b.stringh
    call OutputGraphicString16b
    mov esi,45*2+105*288*2
    add esi,[vidbuffer]
    add esi,[MenuDisplace16]
    mov edi,menudrawbox8b.stringi
    call OutputGraphicString16b
;    mov al,[newengen]
;    mov byte[newengen],0
;    push eax
    call copyvid
;    pop eax
;    mov [newengen],al
    ret

SECTION .bss
.allred resw 1
.blue   resw 1
.stepb  resw 1

NEWSYM menu16btrans, resb 1

SECTION .text

NEWSYM menudrawcursor16b
    ; draw a small red box
    mov esi,41*2+34*288*2
    add esi,[menucloc]
    add esi,[menucloc]
    add esi,[vidbuffer]
    add esi,[MenuDisplace16]
    mov ecx,148
    mov al,9
    mov bx,[menudrawbox16b.allred]
.loop
    mov [esi],bx
    add esi,2
    dec ecx
    jnz .loop
    add esi,288*2-148*2
    dec al
    mov ecx,148
    jnz .loop
    mov al,128
    ret

NEWSYM savespcdata
    sub dword[spcPCRam],spcRam
    ; Assemble N/Z flags into P
    and byte[spcP],0FDh
    test byte[spcNZ],0FFh
    jnz .nozero
    or byte[spcP],02h
.nozero
    and byte[spcP],07Fh
    test byte[spcNZ],80h
    jz .noneg
    or byte[spcP],80h
.noneg
    mov ax,[spcPCRam]
    mov [ssdatst+37],ax
    mov al,[spcA]
    mov [ssdatst+39],al
    mov al,[spcX]
    mov [ssdatst+40],al
    mov al,[spcY]
    mov [ssdatst+41],al
    mov al,[spcP]
    mov [ssdatst+42],al
    mov al,[spcS]
    mov [ssdatst+43],al
    add dword[spcPCRam],spcRam
.savestuff
    ChangeDir SPCPath
    pushad
    call PrepareSaveState
    popad
    ; Copy from fnames to .spcfname, replacing .srm with .spc
    mov esi,fnames+1
    mov edi,.spcfname
.next
    mov al,[esi]
    mov [edi],al
    inc esi
    inc edi
    cmp al,'.'
    jne .next
    ; Save stuff
    mov byte[edi],'s'
    mov byte[edi+1],'p'
    mov byte[edi+2],'c'
    mov byte[edi+3],0
    ; Find an unoccupied file
.tryagainspc
    mov edx,.spcfname
    call Open_File
    jc .nofileopen
    mov bx,ax
    call Close_File
    cmp byte[edi+2],'c'
    jne .notc
    mov byte[edi+2],'1'
    jmp .tryagainspc
.notc
    cmp byte[edi+2],'9'
    je .donext10
    inc byte[edi+2]
    jmp .tryagainspc
.donext10
    mov al,[edi+1]
    cmp al,[edi+2]
    je .nofileopen
    cmp byte[edi+1],'p'
    jne .notp
    mov byte[edi+1],'0'
.notp
    inc byte[edi+1]
    mov byte[edi+2],'0'
    jmp .tryagainspc
.nofileopen
    xor al,al
    mov al,[edi+1]
    mov [showmenu.saved+2],al
    mov al,[edi+2]
    mov [showmenu.saved+3],al
    ; copy spcextra ram to dspmem+192
    mov esi,spcextraram
    mov edi,DSPMem+192
    mov ecx,64
.loop
    mov al,[esi]
    mov [edi],al
    inc esi
    inc edi
    dec ecx
    jnz .loop

    ; Copy Game Title

    mov esi,[romdata]
    add esi,7FC0h
    cmp byte[romtype],2
    jne .nohirom2
    add esi,8000h
.nohirom2
    mov ecx,20
    mov edi,ssdatst+46+32
.romloop
    mov al,[esi]
    mov [edi],al
    inc esi
    inc edi
    dec ecx
    jnz .romloop
    ; Copy Date of spc dumped
    call Get_Date
    mov [ssdatst+09Eh],dl
    mov [ssdatst+09Fh],dh
    mov [ssdatst+0A0h],cx

    ; Set Channel Disables
    mov byte[ssdatst+0D0h],0
    cmp byte[Voice0Disable],1
    je .enable0
    or byte[ssdatst+0D0h],1
.enable0
    cmp byte[Voice1Disable],1
    je .enable1
    or byte[ssdatst+0D0h],2
.enable1
    cmp byte[Voice2Disable],1
    je .enable2
    or byte[ssdatst+0D0h],4
.enable2
    cmp byte[Voice3Disable],1
    je .enable3
    or byte[ssdatst+0D0h],8
.enable3
    cmp byte[Voice4Disable],1
    je .enable4
    or byte[ssdatst+0D0h],16
.enable4
    cmp byte[Voice5Disable],1
    je .enable5
    or byte[ssdatst+0D0h],32
.enable5
    cmp byte[Voice6Disable],1
    je .enable6
    or byte[ssdatst+0D0h],64
.enable6
    cmp byte[Voice7Disable],1
    je .enable7
    or byte[ssdatst+0D0h],128
.enable7

;  times 32  ; Title of game (Offset 48)
;  times 32  ; Song Name
;  times 32  ; Author of Song
;  times 32  ; Name of dumper
;  times 32  ; Comments
;  times 4   ; date of spc dumped
;  times 4   ; time in milliseconds before fading out
;  times 2   ; fade-out length in milliseconds
;  0         ; default channel enables

    mov edx,.spcfname
    call Create_File
    mov bx,ax
    mov ecx,256
    mov edx,ssdatst
    call Write_File

    ; Save SPC stuff
    mov ecx,65536
    mov edx,spcRam
    call Write_File
    mov ecx,256
    mov edx,DSPMem
    call Write_File

%ifdef SPCDUMP
	mov [SPCSave_handle], ebx
%else
    call Close_File
%endif

    pushad
    call ResetState
    popad

%ifdef SPCDUMP

; w00t, reg dump crapola
; using a time reference because I don't feel like adding
; cycle counting to the SPC emulation just for this

	mov byte[SPCSave_dump],1

	mov eax, [spcRam+0F4h]
	mov [SPCSave_ports], eax
	xor eax, eax
	mov [SPCSave_buffer], eax

%endif
    ChangeDirSRAM
    ret

SECTION .bss
.spcfname resb 128

SECTION .data
;.SPC File Format

;Offset 00000h - File Header : SNES-SPC700 Sound File Data v0.10
;Offset 00021h - 0x26,0x26,0x26
;Offset 00024h - Version #(/100)
;Offset 00025h - PC Register value (1 Word)
;Offset 00027h - A Register Value (1 byte)
;Offset 00028h - X Register Value (1 byte)
;Offset 00029h - Y Register Value (1 byte)

;Offset 0002Ah - Status Flags Value (1 byte)
;Offset 0002Bh - Stack Register Value (1 byte)
;Offset 0002Ch-000FFh - Reserved For Future Use
;Offset 00100h-100FFh - SPCRam
;Offset 10100h-101FFh - DSPRam

;Offset 0002Eh-0004Dh - SubTitle/Song Name
;Offset 0004Eh-0006Dh - Title of Game
;Offset 0006Eh-0007Dh - Name of Dumper
;Offset 0007Eh-0009Dh - Comments
;Offset 0009Eh-000A4h - Date of SPC Dumped in decimal (DD/MM/YYYY)
;Offset 000A9h-000ABh - Time in seconds for the spc to play before fading
;Offset 000ACh-000AFh - Fade out time in milliseconds
;Offset 000B0h-000CFh - Author of Song
;Offset 000D0h        - Default Channel Disables (0 = enable, 1 = disable)
;Offset 000D1h        - Emulator used to dump .spc file
;                       (0 = UNKNOWN, 1 = ZSNES, 2 = SNES9X)
;                       (Note : Contact the authors if you're an snes emu
;                       author with an .spc capture in order to assign
;                       you a number)

;Offset 0002Eh-0004Dh - Name of SPC (32 bytes)
;Offset 0004Eh-0005Dh - Name of Game (16 bytes)
;Offset 0006Eh-0007Dh - Name of SPC dumper (16 bytes)
;Offset 0007Eh-0009Dh - Comments (32 bytes)
;Offset 0009Eh-000A8h - Date the SPC was Dumped (10 bytes)
;Offset 000A9h-000ABh - Internal SPC timer (3 bytes)

NEWSYM ssdatst
  db 'SNES-SPC700 Sound File Data v0.30',26,26,26     ; offset 0
  db 10 ; Version #(/100), offset 36
  ; SPC Registers
  dw 0  ; PC, offset 37
  db 0  ; A, offset 39
  db 0  ; X, offset 40
  db 0  ; Y, offset 41
  db 0  ; P, offset 42
  db 0  ; S, offset 43
  db 0,0 ; offset 44 (reserved)

  times 32 db 0 ; Title of game (Offset 46)
  times 32 db 0 ; Song Name
  times 16 db 0 ; Name of dumper
  times 32 db 0 ; Comments
  times 10 db 0 ; date of spc dumped
  times 4  db 0 ; time in seconds before fading out
  times 4  db 0 ; fade-out length in milliseconds
  times 32 db 0 ; Author of Song
  db 0          ; default channel enables
  db 1          ; emulator used to dump .spc files
  ; 32*5+20 = 180

  times 48 db 0        ;(reserved), offset 224
  ; SPCRAM (offset 256), 64k
  ; DSPRAM (offset 256+65536), 256 bytes

SECTION .text

NEWSYM dumpsound
    mov cx,0
    mov edx,.filename
    call Create_File
    ; Process sound data
    mov bx,ax
    xor ecx,ecx
    xor esi,esi
.loop
    push eax
    mov eax,[spcBuffera]
    mov edx,dword[eax+ecx*4]
    pop eax
    cmp edx,0
    je .nowrite
    mov [mode7tab+esi],edx
    add esi,4
    cmp esi,65536
    je .savenow
.return
.nowrite
    inc cx
    jnz .loop
    cmp esi,0
    je .nosave
    mov ecx,esi
    mov edx,mode7tab
    call Write_File
.nosave
    call Close_File
    call Makemode7Table
    ret

.savenow
    push ecx
    mov ecx,65536
    mov edx,mode7tab
    call Write_File
    pop ecx
    xor esi,esi
    jmp .return

SECTION .data
.filename db 'SOUNDDMP.RAW',0

NEWSYM pcxheader
          db 10,5,1,8
          dw 0,0,255,223
          dw 256,224
          times 48 db 0
          db 0,1
.bpline   dw 256
          times 128-68 db 0

SECTION .bss

NEWSYM picnum, resw 1

SECTION .data

NEWSYM savepcx
%ifndef NO_PNG
    cmp byte[ScreenShotFormat],1
    jne .notpng
    ChangeDir SnapPath
    pushad
    call Grab_PNG_Data
    popad
    ChangeDirSRAM
    ret
.notpng
%endif
    
    mov byte[pressed+1],0
    mov byte[pressed+59],0
    cmp byte[cbitmode],1
    je near .save16b
    mov edi,pcxheader
    mov ecx,128
.clearhead
    mov byte[edi],0
    inc edi
    dec ecx
    jnz .clearhead
    mov byte[pcxheader+0],10
    mov byte[pcxheader+1],5
    mov byte[pcxheader+2],1
    mov byte[pcxheader+3],8
    mov word[pcxheader+8],255
    mov word[pcxheader+10],222
    mov byte[pcxheader.bpline-1],1
    mov word[pcxheader.bpline],256
    cmp byte[resolutn],224
    je .res224ph
    mov word[pcxheader+10],237
.res224ph

    ChangeDir SnapPath

    mov ecx,0    ;GetFreeFile use ecx==0 to tell if it's PCX
    call GetFreeFile

    call Create_File
    ; Save header
    mov bx,ax
    mov ecx,128
    mov edx,pcxheader
    call Write_File
    ; Save picture Data
    mov byte[.rowsleft],223
    cmp byte[resolutn],224
    je .res224p
    mov byte[.rowsleft],238
.res224p
    mov ecx,256
    mov edx,[vidbuffer]
    add edx,16+288
.a
    xor ecx,ecx
    mov esi,edx
    mov edi,mode7tab
    push ebx
    mov ebx,256
.loopp
    mov al,[esi]
    mov [edi],al
    mov ah,al
    and ah,0C0h
    cmp ah,0C0h
    jne .norep
    mov byte[edi],0C1h
    inc edi
    inc ecx
    mov byte[edi],al
.norep
    inc ecx
    inc esi
    inc edi
    dec ebx
    jnz .loopp
    pop ebx
    xor al,al
    push edx
    mov edx,mode7tab
    call Write_File
    pop edx
    add edx,288
    dec byte[.rowsleft]
    jnz .a
    ; Save Palette
    mov ecx,769
    mov edx,[vidbuffer]
    add edx,100000
    call Write_File
    call Makemode7Table
    call Close_File
;    mov dword[Msgptr],.pcxsaved
;    mov eax,[MsgCount]
;    mov [MessageOn],eax
    ChangeDirSRAM
    ret

.save16b
    test byte[pressed+14],1
    jnz near save16b2
    call prepare16b
    mov edi,pcxheader
    mov ecx,128
.clearhead2
    mov byte[edi],0
    inc edi
    dec ecx
    jnz .clearhead2
    ; Initial header = 14 bytes
    mov byte[pcxheader],'B'
    mov byte[pcxheader+1],'M'
    mov dword[pcxheader+2],02A01Ah-768
    mov dword[pcxheader+10],26

    mov dword[pcxheader+14],12
    mov word[pcxheader+18],256
    mov word[pcxheader+20],223
    mov word[pcxheader+22],1
    mov word[pcxheader+24],24

    cmp byte[resolutn],224
    je .res224b
    add dword[pcxheader+2],768*15
    mov word[pcxheader+20],238
.res224b

    ChangeDir SnapPath

    mov ecx,1    ;GetFreeFile use ecx==1 to tell if it's BMP
    call GetFreeFile

    call Create_File
    ; Save header
    mov bx,ax
    mov ecx,26
    mov edx,pcxheader
    call Write_File
    ; Save picture Data
    mov byte[.rowsleft],223
    mov esi,[vidbuffer]
    add esi,32+288*2*223
    cmp byte[resolutn],224
    je .res224b2
    mov byte[.rowsleft],238
    add esi,288*2*15
.res224b2
    mov [.curdptr],esi
.a2
    mov ecx,256
    mov edi,mode7tab
    mov esi,[.curdptr]
    sub dword[.curdptr],288*2
.b2
    push ecx
    mov ax,[esi]
    mov cl,[vesa2_bpos]
    shr ax,cl
    and ax,1Fh
    shl al,3
    mov byte[edi],al
    mov ax,[esi]
    mov cl,[vesa2_gpos]
    shr ax,cl
    and ax,1Fh
    shl al,3
    mov byte[edi+1],al
    mov ax,[esi]
    mov cl,[vesa2_rpos]
    shr ax,cl
    and ax,1Fh
    shl al,3
    mov byte[edi+2],al
    pop ecx
    add edi,3
    add esi,2
    dec ecx
    jnz .b2
    push edx
    mov ecx,768
    mov edx,mode7tab
    call Write_File
    pop edx
    add edx,288*2
    dec byte[.rowsleft]
    jnz near .a2
    call Makemode7Table
    call Close_File
;    mov dword[Msgptr],.rawsaved
;    mov eax,[MsgCount]
;    mov [MessageOn],eax
    call restore16b
    ChangeDirSRAM
    ret


SECTION .bss
.rowsleft resb 1
.curdptr resd 1

SECTION .text

NEWSYM GetFreeFile
%ifdef __MSDOS__
    cmp ecx,0
    jne .isbmp
    mov byte[.filename+9],'p'
    mov byte[.filename+10],'c'
    mov byte[.filename+11],'x'
    jmp .doneextselect
.isbmp
    mov byte[.filename+9],'b'
    mov byte[.filename+10],'m'
    mov byte[.filename+11],'p'
.doneextselect
    mov byte[.filename+12],0
    mov word[picnum],0
.findagain
    mov edx,.filename
    call Open_File
    jc near .nofile
    mov bx,ax
    call Close_File

    inc word[picnum]
    cmp word[picnum],1000
    je .nofile

    mov ax,[picnum]
    xor edx,edx
    mov bx,100
    div bx
    mov cl,al
    mov ax,dx
    xor edx,edx
    mov bx,10
    div bx
    mov esi,.filename+5
    add cl,48
    add al,48
    add dl,48
    mov esi,.filename+5
    mov byte[esi],cl
    mov byte[esi+1],al
    mov byte[esi+2],dl
    jmp .findagain
.nofile
    mov edx,.filename

%else
    mov esi,fnames+1
    mov ebx,.imagefname
.end1
    mov al,[esi]
    inc esi
    cmp al,0
    jne .end1
.end2
    dec esi
    mov al,[esi]
    cmp al,'.'
    jne .end2
    mov edx,fnames+1
.next
    mov al,[edx]
    mov [ebx],al
    inc edx
    inc ebx
    cmp edx,esi
    jne .next
    mov esi,ebx
    mov byte[esi],' '
    mov byte[esi+1],'0'
    mov byte[esi+2],'0'
    mov byte[esi+3],'0'
    mov byte[esi+4],'0'
    mov byte[esi+5],'.'
    cmp ecx,0
    jne .isbmp
    mov byte[esi+6],'p'
    mov byte[esi+7],'c'
    mov byte[esi+8],'x'
    jmp .doneextselect
.isbmp
    mov byte[esi+6],'b'
    mov byte[esi+7],'m'
    mov byte[esi+8],'p'
.doneextselect
    mov byte[esi+9],0

    mov word[picnum],0
.findagain
    mov edx,.imagefname
    call Open_File
    jc near .nofile
    mov bx,ax
    call Close_File

    inc word[picnum]
    cmp word[picnum],10000
    je .nofile
    mov ax,[picnum]
    xor edx,edx
    mov bx,1000
    div bx
    add al,48
    mov byte[esi+1],al
    mov ax,dx
    xor edx,edx
    mov bx,100
    div bx
    add al,48
    mov byte[esi+2],al
    mov ax,dx
    xor edx,edx
    mov bx,10
    div bx
    add al,48
    add dl,48
    mov byte[esi+3],al
    mov byte[esi+4],dl
    jmp .findagain
.nofile
    mov edx,.imagefname
%endif
    ret

SECTION .data
.filename db 'image000.pcx',0,0,0,0
;.pcxsaved db 'SNAPSHOT SAVED TO '
;.rawsaved db 'SNAPSHOT SAVED TO '
SECTION .bss
.imagefname resb 128
SECTION .text


NEWSYM save16b2
    call prepare16b
    mov byte[pressed+14],2
    push es
    mov edi,pcxheader
    mov ecx,128
.clearhead2
    mov byte[edi],0
    inc edi
    dec ecx
    jnz .clearhead2
    ; Initial header = 14 bytes
    mov byte[pcxheader],'B'
    mov byte[pcxheader+1],'M'
    mov dword[pcxheader+2],02A01Ah-256*224*3+512*448*3
    mov dword[pcxheader+10],26
    mov dword[pcxheader+14],12
    mov word[pcxheader+18],512
    mov word[pcxheader+20],448
    mov word[pcxheader+22],1
    mov word[pcxheader+24],24

    ChangeDir SnapPath

    mov ecx,1    ;GetFreeFile use ecx==1 to tell if it's BMP
    call GetFreeFile

    mov cx,0
    call Create_File
    ; Save header
    mov bx,ax
    mov ecx,26
    mov edx,pcxheader
    call Write_File
    ; Save picture Data
    mov dword[.rowsleft],448
    mov ax,[vesa2selec]
    mov es,ax
    mov esi,32*2+640*2*223*2+640*2
    mov [.curdptr],esi
.a2
    mov ecx,512
    mov edi,mode7tab
    mov esi,[.curdptr]
    sub dword[.curdptr],640*2
.b2
    push ecx
    mov ax,[es:esi]
    mov cl,[vesa2_bpos]
    shr ax,cl
    and ax,1Fh
    shl al,3
    mov byte[edi],al
    mov ax,[es:esi]
    mov cl,[vesa2_gpos]
    shr ax,cl
    and ax,1Fh
    shl al,3
    mov byte[edi+1],al
    mov ax,[es:esi]
    mov cl,[vesa2_rpos]
    shr ax,cl
    and ax,1Fh
    shl al,3
    mov byte[edi+2],al
    pop ecx
    add edi,3
    add esi,2
    dec ecx
    jnz .b2
    push edx
    mov ecx,768*2
    mov edx,mode7tab
    call Write_File
    pop edx
    add edx,288*2
    dec dword[.rowsleft]
    jnz near .a2
    call Makemode7Table
    call Close_File
;    mov dword[Msgptr],.rawsaved
;    mov eax,[MsgCount]
;    mov [MessageOn],eax
    pop es
    call restore16b
    ChangeDirSRAM
    ret

SECTION .data
;.rawsaved db 'SNAPSHOT SAVED TO '
SECTION .bss
.rowsleft resd 1
.curdptr resd 1
SECTION .text

prepare16b:
   cmp byte[vesa2red10],1
   jne .nored
   cmp byte[cvidmode],5
   jne .nored
   cmp byte[scanlines],1
   je .nored
   cmp byte[smallscreenon],1
   je .nored
   mov byte[vesa2_rpos],10
   mov byte[vesa2_gpos],5
.nored
   ret
restore16b:
   cmp byte[vesa2red10],1
   jne .nored
   mov byte[vesa2_rpos],11
   mov byte[vesa2_gpos],6
.nored
   ret

