Files
ZSNES/zsnes/src/ui.asm

937 lines
19 KiB
NASM

;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 PrintStr,WaitForKey,PrintChar,ram7fa,wramdataa,malloc,MMXSupport
EXTSYM MMXextSupport,statefileloc,LatestSave,firstsaveinc,Open_File
EXTSYM Get_File_Date,Close_File,Change_Dir,Get_Dir,romloadskip,cfgloadgdir
EXTSYM cfgloadsdir,init18_2hz,OSExit,SRAMDirCurDir,SRAMChdir,SRAMChdirFail
EXTSYM BitConv32Ptr,spcBuffera,spritetablea,vcache2bs,vcache4bs,vcache8bs
EXTSYM RGBtoYUVPtr,newgfx16b,vidbuffer,vidbufferofsa,vidbufferofsmos,ngwinptr
EXTSYM vidbufferofsb,headdata,romdata,sfxramdata,setaramdata,wramdata,ram7f,vram
EXTSYM sram,debugbuf,regptr,regptw,vcache2b,vcache4b,vcache8b,fname,fnames
EXTSYM fnamest,filefound,vidbufferofsc,Sup48mbit,Sup16mbit,guioff
%ifdef __UNIXSDL__
EXTSYM LinuxExit,GetFilename
%endif
; Function 0501h
; User Interface
; Search for CMDLINE= for commandline entry
SECTION .text
ALIGN32
NEWSYM outofmemory
mov edx,outofmem
call PrintStr
jmp DosExit
SECTION .data
NEWSYM mydebug, db '',13,10,0
NEWSYM outofmem, db 'You don',39,'t have enough memory to run this program!',13,10,0
;cpuidfname db 'nocpuzid.dat',0
;cpuidtext db 'NOTE: If ZSNES crashes here, then please re-run. ',0
;cpuidtext2 db 13,' ',13,0
NEWSYM YesMMX, db 'MMX support found and enabled.',13,10,13,10,0
; New Variables
;NEWSYM BetaUser, db 37,38,210,56,78,23,7,7,0
SECTION .text
;*******************************************************
; Set Noise Data
;*******************************************************
NEWSYM setnoise
mov edi,NoiseData
mov ebx,256
mov ecx,128
xor esi,esi
xor edx,edx
.next
mov al,[.samplenoise+esi]
add al,[.samplenoise+edx]
mov [edi],al
inc edi
inc esi
and esi,07Fh
dec edx
and edx,07Fh
dec ecx
jnz .next
dec edx
and edx,07Fh
mov ecx,128
dec ebx
jnz .next
ret
SECTION .data
.samplenoise:
db 27,232,234,138,187,246,176,81,25,241,1,127,154,190,195,103,231,165,220,238
db 232,189,57,201,123,75,63,143,145,159,13,236,191,142,56,164,222,80,88,13
db 148,118,162,212,157,146,176,0,241,88,244,238,51,235,149,50,77,212,186,241
db 88,32,23,206,1,24,48,244,248,210,253,77,19,100,83,222,108,68,11,58
db 152,161,223,245,4,105,3,82,15,130,171,242,141,2,172,218,152,97,223,157
db 93,75,83,238,104,238,131,70,22,252,180,82,110,123,106,133,183,209,48,230
db 157,205,27,21,107,63,85,164
SECTION .text
;*******************************************************
; Allocate Memory, ebx = size,eax returned = LFB pointer
;*******************************************************
NEWSYM AllocMem
%ifndef __UNIXSDL__
mov ax,0501h
mov cx,bx
shr ebx,16
int 31h
jc near outofmemory
mov ax,bx
shl eax,16
mov ax,cx
%endif
ret
;*******************************************************
; Get Command Line Locates SET CMDLINE environment
;*******************************************************
%ifdef __WIN32__
EXTSYM _imp__GetModuleFileNameA@12
EXTSYM memcpy
%elifdef __MSDOS__
EXTSYM argv
%endif
NEWSYM getcmdline
%ifdef __MSDOS__
%if 0
mov edx,.string2s
push edx
call getenv
pop edx
%else
mov eax,[argv]
%endif
cmp eax,0
je near .nfound
mov esi,eax
mov edi,CMDLineStr
cmp byte[esi],0
je near .nfound
.a
mov dl,[esi]
cmp dl,'a'
jb .nocap
cmp dl,'z'
ja .nocap
sub dl,'a'-'A'
.nocap
mov [edi],dl
mov [edi+256],dl
mov [edi+512],dl
inc esi
inc edi
cmp dl,32
je .b
cmp dl,0
jne .a
.b
%elifdef __WIN32__
push dword 256
push dword CMDLineStr
push byte +0
call [_imp__GetModuleFileNameA@12]
push eax
push eax
push dword CMDLineStr
push dword GUIFName
call memcpy
add esp,+12
mov eax,[esp]
push eax
push dword CMDLineStr
push dword GUICName
call memcpy
add esp,+12
pop edi
add edi,CMDLineStr
%else
mov esi,CMDLineStr
ret ; *sigh*
%endif
mov esi,CMDLineStr
mov eax,esi
.next2
cmp eax,edi
je .nomore
%ifdef __UNIXSDL__
cmp byte[eax],'/'
%else
cmp byte[eax],'\'
je .found
%endif
cmp byte[eax],':'
jne .next
.found
mov esi,eax
inc esi
.next
inc eax
jmp .next2
.nomore
mov [FilenameStart],esi
mov dword[esi],'zsne'
mov dword[esi+4],'s.cf'
mov byte[esi+8],'g'
mov byte[esi+9],0
mov dword[esi+256],'zgui'
mov dword[esi+256+4],'cfg.'
mov dword[esi+256+8],'dat '
mov byte[esi+256+11],0
mov dword[esi+512],'data'
mov dword[esi+512+4],'.cmb'
mov byte[esi+512+8],0
ret
.nfound
mov edx,.stringnf
call PrintStr
mov esi,CMDLineStr
mov [FilenameStart],esi
mov dword[esi],'zsne'
mov dword[esi+4],'s.cf'
mov byte[esi+8],'g'
mov byte[esi+9],0
mov dword[esi+256],'zgui'
mov dword[esi+256+4],'cfg.'
mov dword[esi+256+8],'dat '
mov byte[esi+256+11],0
mov dword[esi+512],'data'
mov dword[esi+4+512],'.cmb'
mov byte[esi+8+512],0
ret
SECTION .data
.string2s db 'CMDLINE',0
.stringnf db 'SET CMDLINE LINE NOT FOUND!',13,0
SECTION .bss
NEWSYM CMDLineStr, resb 256
NEWSYM GUIFName, resb 256
NEWSYM GUICName, resb 256
NEWSYM FilenameStart, resd 1
;SECTION .text
;*******************************************************
; Variable section
;*******************************************************
SECTION .bss
;ALIGN32
NEWSYM vrama, resb 65536
NEWSYM mode7tab, resb 65536
NEWSYM srama, resb 65536*2
NEWSYM debugbufa, resb 10000
NEWSYM wramreadptr, resd 1
NEWSYM regptra, resb 49152
NEWSYM wramwriteptr, resd 1
NEWSYM regptwa, resb 49152
; vcache.asm
; table.asm
; vesa2.asm
NEWSYM fulladdtab, resw 65536
; dspproc.asm
NEWSYM spcRamcmp, resb 65536
NEWSYM VolumeConvTable, resw 32768
NEWSYM dspWptr, resd 256
NEWSYM dspRptr, resd 256
NEWSYM NoiseData, resb 32768
; makevid.asm
; makevid.asm
NEWSYM vcache2ba, resb 262144+256
NEWSYM vcache4ba, resb 131072+256
NEWSYM vcache8ba, resb 65536+256
ZSNESBase resd 1
BlockSize resd 1 ; Set before calling
LinearAddress resd 1 ; Returned by function
BlockHandle resd 1 ; Returned by function
ZSNESAddress resd 1 ; Returned by function
SECTION .text
;*******************************************************
; Allocate Pointer Sets variables with pointer values
;*******************************************************
AllocateLDTDescriptor:
%ifndef __UNIXSDL__
;Get ZSNES Base
mov ax,ds
mov bx,ax
mov eax,0006h
int 31h
jc .FatalError
mov [ZSNESBase+2],cx
mov [ZSNESBase],dx
ret
.FatalError
; maybe dosexit?
%endif
ret
AllocateBlock:
%ifndef __UNIXSDL__
mov eax,0501h
mov bx,[BlockSize+2]
mov cx,[BlockSize]
int 31h
jc .FatalError
mov [LinearAddress+2],bx
mov [LinearAddress],cx
mov [BlockHandle+2],si
mov [BlockHandle],di
mov eax,[LinearAddress]
sub eax,[ZSNESBase]
and eax,0FFFFFFE0h
add eax,40h
mov [ZSNESAddress],eax
xor ebx,ebx
ret
.FatalError
mov ebx,1
%endif
ret
SECTION .bss
;ALIGN32
vbufaptr resd 1
vbufeptr resd 1
ngwinptrb resd 1
romaptr resd 1
vbufcptr resd 1
NEWSYM vbufdptr, resd 1
vc2bptr resd 1
vc4bptr resd 1
vc8bptr resd 1
cmemallocptr resd 1
memfreearray resd 12
SECTION .text
%macro AllocmemFail 3
mov ebx,%1
add ebx,1000h
push ebx
call malloc
pop ebx
cmp eax,0
je near %3
mov ebx,[cmemallocptr]
add dword[cmemallocptr],4
mov [ebx],eax
and eax,0FFFFFFE0h
add eax,40h
mov [%2],eax
%endmacro
%macro AllocmemOkay 3
mov ebx,%1
add ebx,1000h
push ebx
call malloc
pop ebx
push eax
and eax,0FFFFFFE0h
add eax,40h
mov [%2],eax
pop eax
cmp eax,0
je %%nomalloc
mov ebx,[cmemallocptr]
add dword[cmemallocptr],4
mov [ebx],eax
%%nomalloc
cmp eax,0
jne near %3
%endmacro
;NEWSYM allocspc7110
; AllocmemFail 8192*1024+4096,spc7110romptr,outofmemoryb
; ret
outofmemoryb
%ifdef __MSDOS__
mov ax,3
int 10h
%endif
jmp outofmemory
NEWSYM allocptr
mov dword[cmemallocptr],memfreearray
%ifndef __MSDOS__
AllocmemFail 4096+65536*16,BitConv32Ptr,outofmemory
%endif
; Memory Allocation
AllocmemFail 65536*4+4096,spcBuffera,outofmemory
AllocmemFail 256*512+4096,spritetablea,outofmemory
AllocmemFail 512*296*4+4096+512*296,vbufaptr,outofmemory
AllocmemFail 288*2*256+4096,vbufeptr,outofmemory
AllocmemFail 256*224+4096,ngwinptrb,outofmemory
AllocmemFail 1024*296,vbufdptr,outofmemory
AllocmemFail 65536*4*4+4096,vcache2bs,outofmemory
AllocmemFail 65536*4*2+4096,vcache4bs,outofmemory
AllocmemFail 65536*4+4096,vcache8bs,outofmemory
AllocmemFail 65536*4+4096,RGBtoYUVPtr,outofmemory
mov byte[newgfx16b],1
AllocmemOkay 4096*1024+32768*2+2048*1024+4096,romaptr,.memoryokay
mov byte[Sup48mbit],0
AllocmemOkay 4096*1024+32768*2+4096,romaptr,.donememalloc
mov byte[Sup16mbit],1
AllocmemOkay 2048*1024+32768*2+4096,romaptr,.donememalloc
jmp outofmemory
.memoryokay
.donememalloc
; Set up memory values
mov eax,[vbufaptr]
and eax,0FFFFFFF8h
add eax,8
mov [vidbuffer],eax
mov [vidbufferofsa],eax
add eax,75036
mov [vidbufferofsmos],eax
mov eax,[ngwinptrb]
and eax,0FFFFFFF8h
add eax,2048
mov [ngwinptr],eax
mov eax,[vbufeptr]
and eax,0FFFFFFF8h
add eax,8
mov [vidbufferofsb],eax
mov eax,[vbufdptr]
and eax,0FFFFFFF8h
add eax,8
mov [vidbufferofsc],eax
mov eax,[romaptr]
and eax,0FFFFFFF8h
add eax,8
mov [headdata],eax
mov [romdata],eax
add eax,4194304
mov [sfxramdata],eax
mov dword[setaramdata],eax ; share ram data with sfx
mov esi,[romdata]
cmp byte[Sup48mbit],0
je .no48mbit
add esi,4096*1024+2048*1024
jmp .done
.no48mbit
cmp byte[Sup16mbit],0
je .no16mbit
add esi,2048*1024
jmp .done
.no16mbit
add esi,4096*1024
.done
mov byte[esi],58h
mov byte[esi+1],80h
mov byte[esi+2],0FEh
mov dword[wramdata],wramdataa
mov dword[ram7f],ram7fa
mov dword[vram],vrama
mov dword[sram],srama
mov dword[debugbuf],debugbufa
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
; 2-bit = 256k
mov eax,vcache2ba
and eax,0FFFFFFF8h
add eax,8
mov [vcache2b],eax
; 4-bit = 128k
mov eax,vcache4ba
and eax,0FFFFFFF8h
add eax,8
mov [vcache4b],eax
; 8 bit = 64k
mov eax,vcache8ba
and eax,0FFFFFFF8h
add eax,8
mov [vcache8b],eax
ret
;*******************************************************
; Print Numbers Prints # in EAX to screen
;*******************************************************
NEWSYM printnum
; process through each digit
push edx
push eax
push ebx
push cx
xor edx,edx ; clear high byte
xor cx,cx ; clear counter variable
mov ebx,10
.loopa
div ebx ; get quotent and remainder
push edx ; store number to stack
inc cl
xor edx,edx
test eax,0FFFFFFFFh
jnz .loopa
.loopb
pop edx ; get number back from stack
add dl,30h ; adjust to ASCII value
call PrintChar
dec cl
jnz .loopb
pop cx
pop ebx
pop eax
pop edx
ret
NEWSYM convertnum
; process through each digit
push edx
push eax
push ebx
push cx
xor edx,edx ; clear high byte
xor cx,cx ; clear counter variable
mov ebx,10
.loopa
div ebx ; get quotent and remainder
push edx ; store number to stack
inc cl
xor edx,edx
test eax,0FFFFFFFFh
jnz .loopa
.loopb
pop edx ; get number back from stack
add dl,30h ; adjust to ASCII value
mov [esi],dl
inc esi
dec cl
jnz .loopb
pop cx
pop ebx
pop eax
pop edx
mov byte[esi],0
ret
; eax = value, ecx = # of bytes
NEWSYM converthex
mov ebx,ecx
mov ecx,4
sub ecx,ebx
shl ecx,3
shl eax,cl
mov ecx,ebx
xor ebx,ebx
add ecx,ecx
.loopb
mov ebx,eax
and ebx,0F0000000h
shr ebx,28
mov dl,[.hexdat+ebx]
mov [esi],dl
inc esi
shl eax,4
dec ecx
jnz .loopb
mov byte[esi],0
ret
section .data
.hexdat db '0123456789ABCDEF'
;*******************************************************
; Check Parameter This Processes the Parameters
;*******************************************************
SECTION .bss
newestfileloc resb 1
newestfiledate resd 1
SECTION .text
NEWSYM makeextension
xor ecx,ecx
xor ebx,ebx
xor ah,ah
mov cl,[fname]
mov [fnames],cl
mov [fnamest],cl
mov dl,cl
inc ebx
.loopc
mov al,[fname+ebx]
mov [fnames+ebx],al
mov [fnamest+ebx],al
inc ebx
inc ah
dec ecx
jnz .loopc
; find for '.' or '\'
mov cl,dl
mov edx,ebx
.loopz
dec edx
mov al,[fnames+edx]
%ifdef __UNIXSDL__
cmp al, '/'
%else
cmp al,'\'
%endif
je .addext
cmp al,'.'
je .addb
dec cl
jnz .loopz
jmp .addext
.addb
mov ebx,edx
.addext
mov byte[fnames+ebx],'.'
mov byte[fnamest+ebx],'.'
inc ebx
mov byte[fnames+ebx],'s'
mov byte[fnamest+ebx],'z'
inc ebx
mov byte[fnames+ebx],'r'
mov byte[fnamest+ebx],'s'
inc ebx
mov byte[fnames+ebx],'m'
mov byte[fnamest+ebx],'t'
mov [statefileloc],ebx
inc ebx
mov byte[fnames+ebx],0
mov byte[fnamest+ebx],0
add ah,4
mov [fnames],ah
mov [fnamest],ah
%ifdef __UNIXSDL__
pushad
call GetFilename
popad
%endif
mov byte[firstsaveinc],1
cmp byte[LatestSave],1
je .latestsave
ret
.latestsave
; change dir to Save Dir
pushad
call SRAMChdir
popad
call DetermineNewest
; change dir to LoadDrive/LoadDir
mov dl,[LoadDrive]
mov ebx,LoadDir
call Change_Dir
ret
%macro determinenewhelp 2
mov bl,%1
mov byte[fnamest+eax],%2
call DetermineNew
%endmacro
DetermineNew:
push eax
push ebx
mov edx,fnamest+1
call Open_File
jc near .nodraw
mov bx,ax
mov edx,fnamest+1
call Get_File_Date
%ifdef __MSDOS__
shl edx,16
mov dx,cx
%endif
push edx
call Close_File
pop edx
pop ebx
pop eax
; date = edx, position = bl
cmp edx,[newestfiledate]
jbe .notlatest
mov [newestfiledate],edx
mov [newestfileloc],bl
.notlatest
ret
.nodraw
pop ebx
pop eax
ret
DetermineNewest:
mov eax,[statefileloc]
mov dword[newestfiledate],0
mov byte[newestfileloc],0
determinenewhelp 0,'t'
determinenewhelp 1,'1'
determinenewhelp 2,'2'
determinenewhelp 3,'3'
determinenewhelp 4,'4'
determinenewhelp 5,'5'
determinenewhelp 6,'6'
determinenewhelp 7,'7'
determinenewhelp 8,'8'
determinenewhelp 9,'9'
mov bl,[newestfileloc]
add bl,'0'
cmp bl,'0'
jne .nott
mov bl,'t'
.nott
mov [fnamest+eax],bl
ret
;*******************************************************
; Get Parameters Get Parameters Individually
;*******************************************************
NEWSYM tparms
.donestring
test byte[.numparam],0FFh
jz .nochars
mov al,[filefound]
test al,0FFh
jz .nostring
ret
.nostring
cmp byte[guioff],0
je .yesgui
mov edx,.nostr
call PrintStr
jmp DosExit
.nochars
cmp byte[guioff],0
je .yesgui
cmp byte[fname],0
jne .yesgui
jmp DosExit
.yesgui
mov byte[romloadskip],1
ret
SECTION .bss
.numparam resb 1
SECTION .data
.nostr db 'This emulator will not work without a filename!',13,10,0
.waitkey db 'Press Any Key to Continue.',0
.ret db 13,10,0
SECTION .text
%ifndef __UNIXSDL__
NEWSYM obtaindir
cmp byte[cfgloadsdir],1
je .nosdriveb
pushad
call SRAMDirCurDir
popad
.nosdriveb
cmp byte[cfgloadgdir],1
je .noldriveb
mov ebx,LoadDir
mov edx,LoadDrive
call Get_Dir
.noldriveb
ret
%endif
NEWSYM preparedir
;Function 47h - Get current directory
;------------------------------------
;
; AH = 47h
; DL = drive number (0 = default, 1 = A: etc.)
; DS:ESI -> 64 byte buffer to receive ASCIZ pathname
; get current drive, ah = 19h, al = A=0,B=1, etc.
%ifndef __UNIXSDL__
cmp byte[cfgloadsdir],0
je near .nosdrivec
; verify sram drive/directory exists
; change dir to SRAMDrive/SRAMDir
pushad
call SRAMChdir
popad
cmp byte[SRAMChdirFail],0
je .yessdrive
mov dl,[InitDrive]
mov ebx,InitDir
call Change_Dir
mov byte[cfgloadsdir],0
; Get drive/dir
pushad
call SRAMDirCurDir
popad
mov edx,.sramerrorm
call PrintStr
call WaitForKey
cmp al,27
jne .noesc
jmp DosExit
.noesc
mov edx,.enter
call PrintStr
jmp .nosdrivec
.yessdrive
mov dl,[InitDrive]
mov ebx,InitDir
call Change_Dir
.nosdrivec
%endif
ret
SECTION .data
.sramerrorm db 'Invalid SRAM Directory in ZSNES.CFG!',13,10,13,10
db 'Press any key to continue.',0
.enter db 13,10,0
NEWSYM InitDrive, db 2
NEWSYM LoadDrive, db 2
%ifdef __UNIXSDL__
NEWSYM gotoroot, db '/',0
%else
NEWSYM gotoroot, db '\',0
%endif
SECTION .bss
NEWSYM InitDir, resb 512
NEWSYM LoadDir, resb 512
SECTION .text
NEWSYM DosExit ; Terminate Program
%ifdef __WIN32__
call OSExit
%elifdef __UNIXSDL__
call LinuxExit
%elifdef __MSDOS__
call init18_2hz
mov ax,4c00h ;terminate
int 21h
%endif
NEWSYM MMXCheck
; Check for cpu that doesn't support CPUID
cmp byte[MMXSupport],0
je .nommx
; Real way to check for presence of CPUID instruction -kode54
pushfd
pop eax
mov edx,eax
xor eax,1 << 21
push eax
popfd
pushfd
pop eax
xor eax,edx
jz .nommx
; MMX support
mov byte[MMXSupport],0
mov byte[MMXextSupport],0
mov eax,1
CPUID
test edx,1 << 23
jz .nommx
mov byte[MMXSupport],1
; Check if CPU has SSE (also support mmxext)
test edx,1 << 25
jz .tryextmmx
mov byte[MMXextSupport],1
jmp .nommx
.tryextmmx
; Test extended CPU flag
mov eax,80000001h
CPUID
test edx,1 << 22
jz .nommx
mov byte[MMXextSupport],1
.noprintstr
.nommx
ret