cfgload.asm
bazz1tv_mac-zsnes-1_36/src/cfgload.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.

%include "macros.mac"

EXTSYM CMDLineStr,JoyAC,JoyBC,JoyLC,JoyRC,JoySelec,JoyStart
EXTSYM JoyXC,JoyYC,LoadDir,LoadDrive,SRAMDrive,mode7tab
EXTSYM pl1selk,pl1startk,pl1upk,pl2Ak,pl2Bk,pl2Lk,pl2Rk
EXTSYM pl2Xk,pl2Yk,pl2contrl,pl2downk,pl2leftk,pl2rightk
EXTSYM pl2selk,pl2startk,pl2upk,DontSavePath
EXTSYM Force8b,MusicRelVol,SRAMDir,SoundCompD,SoundQuality
EXTSYM StereoSound,antienab,cvidmode,enterpress,frameskip,guioff
EXTSYM newengen,per2exec,pl1Ak,pl1Bk,pl1Lk,pl1Rk,pl1Xk,pl1Yk
EXTSYM pl1contrl,pl1downk,pl1leftk,pl1rightk,scanlines,soundon
EXTSYM spcon,vsyncon,Open_File,Read_File
EXTSYM Create_File,Write_File,Close_File
%ifdef __LINUX__
; if TextFile==0, zlib functions aren't used
; useful to save the config file
EXTSYM TextFile, InitDir, InitDrive, Change_Dir
%endif

NEWSYM CfgLoadAsmStart



; [BITS 32]
; [ORG 0]

; .CFG variables
SECTION .data
NEWSYM cfgsoundon,      db 0
NEWSYM cfgSoundQuality, db 2
NEWSYM cfgStereoSound,  db 0
NEWSYM cfgguioff,       db 0
NEWSYM cfgper2exec,     db 100
NEWSYM cfgcvidmode,     db 4
NEWSYM cfgscanline,     db 0
NEWSYM cfginterp,       db 0
NEWSYM cfgenterskip,    db 0
NEWSYM cfgforce8b,      db 0
NEWSYM cfgloadsdir,     db 0
NEWSYM cfgloadgdir,     db 0
NEWSYM cfgnewgfx,       db 0
NEWSYM cfgvsync,        db 0
NEWSYM cfgvolume,       db 75
NEWSYM cfgecho,         db 0
NEWSYM RevStereo,       db 0
NEWSYM JoyStatRead,     db 0
NEWSYM pl12s34,         db 0
NEWSYM cfgdontsave,     db 0
NEWSYM cfgreinittime,   db 30
NEWSYM LoadDriveB, db 2
NEWSYM LoadDirB, times 128 db 0
SECTION .text

%macro checkitemcfg 3
    cmp al,%1
    jne %3
    mov al,%2
    jmp .insertnum
%3
%endmacro

%macro checkitemcfg2 3
    cmp al,%1
    jne %3
    mov eax,%2
    jmp .insertnum2
%3
%endmacro

%macro ConvertJoyMapHelp 2
    mov cl,[%1]
    cmp cl,bl
    ja %%skip
    or cl,cl
    jz %%skip
    add cl,81h
    mov [%2],cl
%%skip
%endmacro

NEWSYM ConvertJoyMap
    cmp byte[JoyStatRead],1
    je .convert
    ret
.convert
    call ConvertJoyMap1
    call ConvertJoyMap2
    ret

NEWSYM ConvertJoyMap1
    pushad
    mov al,[pl1contrl]
    ; Convert if 2,4,6, or sidewinder
    cmp al,2
    jne .no2button
    mov byte[pl1Bk],83h
    mov byte[pl1Yk],82h
    mov byte[pl1upk],0CCh
    mov byte[pl1downk],0CDh
    mov byte[pl1leftk],0CEh
    mov byte[pl1rightk],0CFh
.no2button
    cmp al,3
    je .4button
    xor bl,bl
    cmp al,4
    jne .no4button
.4button
    mov bl,4
.no4button
    cmp al,5
    jne .no6button
    mov bl,6
.no6button
    cmp bl,0
    je near .nojoy1
    ; Convert button data
    mov byte[pl1upk],0CCh
    mov byte[pl1downk],0CDh
    mov byte[pl1leftk],0CEh
    mov byte[pl1rightk],0CFh
    ConvertJoyMapHelp JoyStart,pl1startk
    ConvertJoyMapHelp JoySelec,pl1selk
    ConvertJoyMapHelp JoyBC,pl1Yk
    ConvertJoyMapHelp JoyYC,pl1Xk
    ConvertJoyMapHelp JoyAC,pl1Bk
    ConvertJoyMapHelp JoyXC,pl1Ak
    ConvertJoyMapHelp JoyLC,pl1Lk
    ConvertJoyMapHelp JoyRC,pl1Rk
.nojoy1
    cmp al,6
    jne .nosw
    mov byte[pl1upk],0D4h
    mov byte[pl1downk],0D5h
    mov byte[pl1leftk],0D6h
    mov byte[pl1rightk],0D7h
    mov byte[pl1startk],0C8h
    mov byte[pl1selk],0C9h
    mov byte[pl1Ak],089h
    mov byte[pl1Bk],088h
    mov byte[pl1Xk],08Ch
    mov byte[pl1Yk],08Bh
    mov byte[pl1Lk],08Eh
    mov byte[pl1Rk],08Fh
.nosw
    popad
    ret

NEWSYM ConvertJoyMap2
    pushad
    mov al,[pl2contrl]
    ; Convert if 2,4,6, or sidewinder
    ;If pl1contrl=2 and pl2contrl=2, then set pl2 buttons to 3 & 4
    cmp al,2
    jne .no2button2
    cmp byte[pl1contrl],2
    je .pl2b2
    mov byte[pl2Bk],83h
    mov byte[pl2Yk],82h
    mov byte[pl2upk],0CCh
    mov byte[pl2downk],0CDh
    mov byte[pl2leftk],0CEh
    mov byte[pl2rightk],0CFh
    jmp .finpl2
.pl2b2
    mov byte[pl2Bk],85h
    mov byte[pl2Yk],84h
    mov byte[pl2upk],0E8h
    mov byte[pl2downk],0E9h
    mov byte[pl2leftk],0EAh
    mov byte[pl2rightk],0EBh
.no2button2
.finpl2
    cmp al,3
    je .4button2
    xor bl,bl
    cmp al,4
    jne .no4button2
.4button2
    mov bl,4
.no4button2
    cmp al,5
    jne .no6button2
    mov bl,6
.no6button2
    cmp bl,0
    je near .nojoy2
    ; Convert button data
    mov byte[pl2upk],0CCh
    mov byte[pl2downk],0CDh
    mov byte[pl2leftk],0CEh
    mov byte[pl2rightk],0CFh
    ConvertJoyMapHelp JoyStart,pl2startk
    ConvertJoyMapHelp JoySelec,pl2selk
    ConvertJoyMapHelp JoyBC,pl2Yk
    ConvertJoyMapHelp JoyYC,pl2Xk
    ConvertJoyMapHelp JoyAC,pl2Bk
    ConvertJoyMapHelp JoyXC,pl2Ak
    ConvertJoyMapHelp JoyLC,pl2Lk
    ConvertJoyMapHelp JoyRC,pl2Rk
.nojoy2
    ;If both sidewinder, set pl2 buttons to sw2
    cmp al,6
    jne near .nosw2
    cmp byte[pl1contrl],6
    je .pl2sw2
    mov byte[pl2upk],0D4h
    mov byte[pl2downk],0D5h
    mov byte[pl2leftk],0D6h
    mov byte[pl2rightk],0D7h
    mov byte[pl2startk],0C8h
    mov byte[pl2selk],0C9h
    mov byte[pl2Ak],089h
    mov byte[pl2Bk],088h
    mov byte[pl2Xk],08Ch
    mov byte[pl2Yk],08Bh
    mov byte[pl2Lk],08Eh
    mov byte[pl2Rk],08Fh
    jmp .nosw2
.pl2sw2
    mov byte[pl2upk],0DCh
    mov byte[pl2downk],0DDh
    mov byte[pl2leftk],0DEh
    mov byte[pl2rightk],0DFh
    mov byte[pl2startk],0D0h
    mov byte[pl2selk],0D1h
    mov byte[pl2Ak],091h
    mov byte[pl2Bk],090h
    mov byte[pl2Xk],094h
    mov byte[pl2Yk],093h
    mov byte[pl2Lk],096h
    mov byte[pl2Rk],097h
    mov byte[pl2contrl],7
.nosw2
    popad
    ret

NEWSYM DOScreatenewcfg
    ; make a new file
    ; copy .cfgfiledata to mode7tab, replacing each %
%ifdef __LINUX__
    mov dl,[SRAMDrive]
    mov ebx,SRAMDir
    call Change_Dir
%endif
    mov esi,.cfgfiledata
    mov edi,mode7tab
    xor ecx,ecx
    mov edx,.cfgfilesize
.loop
    mov al,[esi]
    cmp al,'%'
    je .look4item
    mov [edi],al
    inc esi
    inc edi
    inc ecx
    dec edx
    jnz .loop
    cmp byte[cfgdontsave],1
    je .failed
    push ecx
    ; Save .CFG file
    mov edx,CMDLineStr
%ifdef __GZIP__
    mov byte[TextFile], 1
%endif
    call Create_File
    pop ecx
    jc .failed
    ; Save 65816 status, etc.
    mov bx,ax
    mov edx,mode7tab
    call Write_File
    call Close_File
%ifdef __GZIP__
    mov byte[TextFile], 0
%endif
.failed
    ret

.look4item
    inc esi
    dec edx
    mov al,[esi]
    inc esi
    dec edx
    mov byte[.temp],0
    mov byte[.temp2],1
    mov bl,[frameskip]
    cmp bl,0
    je .yframeskip
    dec bl
    mov [.temp],bl
    mov byte[.temp2],0
.yframeskip
    checkitemcfg '1', [.temp],.check1
    checkitemcfg '2', [.temp2],.check2
    checkitemcfg '3', [pl1contrl],.check3
    checkitemcfg '4', [pl2contrl],.check4
    checkitemcfg2 '5', [pl1rightk],.check5
    checkitemcfg2 '6', [pl1leftk],.check6
    checkitemcfg2 '7', [pl1downk],.check7
    checkitemcfg2 '8', [pl1upk],.check8
    checkitemcfg2 '9', [pl1startk],.check9
    checkitemcfg2 'A', [pl1selk],.checkA
    checkitemcfg2 'B', [pl1Bk],.checkB
    checkitemcfg2 'C', [pl1Yk],.checkC
    checkitemcfg2 'D', [pl1Ak],.checkD
    checkitemcfg2 'E', [pl1Xk],.checkE
    checkitemcfg2 'F', [pl1Lk],.checkF
    checkitemcfg2 'G', [pl1Rk],.checkG
    checkitemcfg2 'H', [pl2rightk],.checkH
    checkitemcfg2 'I', [pl2leftk],.checkI
    checkitemcfg2 'J', [pl2downk],.checkJ
    checkitemcfg2 'K', [pl2upk],.checkK
    checkitemcfg2 'L', [pl2startk],.checkL
    checkitemcfg2 'M', [pl2selk],.checkM
    checkitemcfg2 'N', [pl2Bk],.checkN
    checkitemcfg2 'O', [pl2Yk],.checkO
    checkitemcfg2 'P', [pl2Ak],.checkP
    checkitemcfg2 'Q', [pl2Xk],.checkQ
    checkitemcfg2 'R', [pl2Lk],.checkR
    checkitemcfg2 'S', [pl2Rk],.checkS
    checkitemcfg 'T', [cfgper2exec],.checkT
    checkitemcfg 'U', [cfgcvidmode],.checkU
    checkitemcfg 'V', [cfgsoundon],.checkV
    checkitemcfg 'W', [cfgSoundQuality],.checkW
    checkitemcfg 'X', [cfgStereoSound],.checkX
    checkitemcfg 'Y', [cfgguioff],.checkY
    checkitemcfg 'Z', [cfgscanline],.checkZ
    checkitemcfg 'a', [cfginterp],.checka
    checkitemcfg 'b', [cfgenterskip],.checkb
    checkitemcfg 'c', [cfgforce8b],.checkc
    cmp al,'d'
    je near .insertdira
    cmp al,'e'
    je near .insertdirb
    checkitemcfg 'f', [JoyStart],.checkf
    checkitemcfg 'g', [JoySelec],.checkg
    checkitemcfg 'h', [JoyBC],.checkh
    checkitemcfg 'i', [JoyYC],.checki
    checkitemcfg 'j', [JoyAC],.checkj
    checkitemcfg 'k', [JoyXC],.checkk
    checkitemcfg 'l', [JoyLC],.checkl
    checkitemcfg 'm', [JoyRC],.checkm
    checkitemcfg 'n', [cfgnewgfx],.checkn
    checkitemcfg 'p', [cfgvsync],.checkp
    checkitemcfg 'q', [cfgvolume],.checkq
    checkitemcfg 'r', [cfgecho],.checkr
    checkitemcfg 's', [RevStereo],.checks
    checkitemcfg 't', [pl12s34],.checkt
    checkitemcfg 'u', [cfgdontsave],.checku
    checkitemcfg 'v', [cfgreinittime],.checkv
    jmp .loop

.temp db 0
.temp2 db 0

.insertnum
    ; preserve ecx and edx, output al into edi
    cmp al,0
    jne .nozero
    mov byte[edi],'0'
    inc edi
    inc ecx
    jmp .loop
.nozero
    cmp al,99
    ja .digits3
    xor ah,ah
    mov bl,10
    div bl
    add al,48
    add ah,48
    cmp al,48
    jne .digits2
    mov byte[edi],ah
    inc edi
    inc ecx
    jmp .loop
.digits2
    mov byte[edi],al
    mov byte[edi+1],ah
    add edi,2
    add ecx,2
    jmp .loop
.digits3
    xor ah,ah
    mov bl,100
    div bl
    add al,48
    mov byte[edi],al
    mov al,ah
    xor ah,ah
    mov bl,10
    div bl
    add al,48
    add ah,48
    mov byte[edi+1],al
    mov byte[edi+2],ah
    add edi,3
    add ecx,3
    jmp .loop

.insertnum2
    ; preserve ecx and edx, output al into edi
    cmp eax,0
    jne .nozeroi
    mov byte[edi],'0'
    inc edi
    inc ecx
    jmp .loop
.nozeroi
    cmp eax,99
    ja .digits3i
    xor ah,ah
    mov bl,10
    div bl
    add al,48
    add ah,48
    cmp al,48
    jne .digits2i
    mov byte[edi],ah
    inc edi
    inc ecx
    jmp .loop
.digits2i
    mov byte[edi],al
    mov byte[edi+1],ah
    add edi,2
    add ecx,2
    jmp .loop
.digits3i
    mov bl,100
    div bl
    add al,48
    mov byte[edi],al
    mov al,ah
    xor ah,ah
    mov bl,10
    div bl
    add al,48
    add ah,48
    mov byte[edi+1],al
    mov byte[edi+2],ah
    add edi,3
    add ecx,3
    jmp .loop

.insertdira
    cmp byte[cfgloadsdir],1
    je .yesloadsdir
    jmp .loop
.yesloadsdir
%ifndef __LINUX__
    mov al,[SRAMDrive]
    add al,65
    mov [edi],al
    mov byte[edi+1],':'
    mov byte[edi+2],'\'
    add edi,3
    add ecx,3
%endif    
    mov ebx,SRAMDir
.nextinsertdira
    mov al,[ebx]
    cmp al,0
    je .nomoredira
    mov [edi],al
    inc edi
    inc ecx
    inc ebx
    jmp .nextinsertdira
.nomoredira
    jmp .loop

.insertdirb
    cmp byte[DontSavePath],1
    je .insertdirc
%ifndef __LINUX__  
    mov al,[LoadDrive]
    add al,65
    mov [edi],al
    mov byte[edi+1],':'
    mov byte[edi+2],'\'
    add edi,3
    add ecx,3
%endif    
    mov ebx,LoadDir
.nextinsertdir
    mov al,[ebx]
    cmp al,0
    je .nomoredir
    mov [edi],al
    inc edi
    inc ecx
    inc ebx
    jmp .nextinsertdir
.nomoredir
    jmp .loop

.insertdirc
%ifndef __LINUX__
    mov al,[LoadDriveB]
    add al,65
    mov [edi],al
    mov byte[edi+1],':'
    mov byte[edi+2],'\'
    add edi,3
    add ecx,3
%endif    
    mov ebx,LoadDirB
.nextinsertdirc
    mov al,[ebx]
    cmp al,0
    je .nomoredirc
    mov [edi],al
    inc edi
    inc ecx
    inc ebx
    jmp .nextinsertdirc
.nomoredirc
    jmp .loop

.cfgfiledata
db '; ZSNES Configuration file',13,10
db '',13,10
db '; Frame Skip = 0 .. 9',13,10
db '',13,10
db 'FrameSkip = %1',13,10
db '',13,10
db '; Auto Frame Skip = 0 or 1 (1 = ON)',13,10
db '',13,10
db 'AutoFrameSkip = %2',13,10
db '',13,10
db '; Player 1/2 Input Device.  Use the GUI to set these values',13,10
db '; NOTE : Using this to select joysticks manually will NOT work!',13,10
db '',13,10
db 'Player1Device = %3',13,10
db 'Player2Device = %4',13,10
db '',13,10
db '; Keyboard Scancodes/Joystick Mappings for Keyboard 1 & 2',13,10
db '; In order of Right, Left, Down, Up, Start, Select, B, Y, A, X, L, R',13,10
db '; Use the GUI to set these values',13,10
db '',13,10
db 'ScanKey1 = %5, %6, %7, %8, %9, %A, %B, %C, %D, %E, %F, %G',13,10
db 'ScanKey2 = %H, %I, %J, %K, %L, %M, %N, %O, %P, %Q, %R, %S',13,10
db '',13,10
db '; Share Player 3 and 4 control inputs with Player 1 and 2 to allow',13,10
db '; 2 devices to be shared on a single player.  This feature automatically',13,10
db '; disables MultiTap (Multiplayer 5) support.  Set this to 1 to enable.',13,10
db '',13,10
db 'Pl34to12Share = %t',13,10
db '',13,10
db '; Percent to Execute [50 .. 150]',13,10
db '',13,10
db 'Execute = %T',13,10
db '',13,10
%ifdef __WIN32__
db '; Video Mode, 0 - 32',13,10
db ';   0 = 256x224 R WIN         1 = 256x224 R FULL',13,10
db ';   2 = 512x448 R WIN         3 = 512x448 DR WIN',13,10
db ';   4 = 640x480 S WIN         5 = 640x480 DS WIN',13,10
db ';   6 = 640x480 DR FULL       7 = 640x480 DS FULL',13,10
db ';   8 = 640x480 S FULL        9 = 768x672 R WIN',13,10
db ';   10 = 768x672 DR WIN       11 = 800x600 S WIN',13,10
db ';   12 = 800x600 DS WIN       13 = 800x600 S FULL',13,10
db ';   14 = 800x600 DR FULL      15 = 800x600 DS FULL',13,10
db ';   16 = 1024x768 S WIN       17 = 1024x768 DS WIN',13,10
db ';   18 = 1024x768 S FULL      19 = 1024x768 DR FULL',13,10
db ';   20 = 1024x768 DS FULL     21 = 1024x896 R WIN',13,10
db ';   22 = 1024x896 DR WIN      23 = 1280x960 S WIN',13,10
db ';   24 = 1280x960 DS WIN      25 = 1280x960 S FULL',13,10
db ';   26 = 1280x960 DR FULL     27 = 1280x960 DS FULL',13,10
db ';   28 = 1280x1024 S WIN      29 = 1280x1024 DS WIN',13,10
db ';   30 = 1280x1024 S FULL     31 = 1280x1024 DR FULL',13,10
db ';   32 = 1280x1024 DS FULL',13,10
db '',13,10
db 'VideoModeWin = %U',13,10
db '',13,10
%endif
%ifdef __LINUX__
%ifdef __OPENGL__
db '; Video Mode, 0 - 15',13,10
%else
db '; Video Mode, 0 - 3',13,10
%endif
db ';   0 = 256x224 WIN           1 = 256x224 FULL',13,10
db ';   2 = 512x448 WIN           3 = 640x480 FULL',13,10
%ifdef __OPENGL__
db ';   4 = 256x224  OGL WIN      5 = 512x448  OGL WIN',13,10
db ';   6 = 640x480  OGL FULL     7 = 640x576  OGL WIN',13,10
db ';   8 = 768x672  OGL WIN      9 = 896x784  OGL WIN',13,10
db ';  10 = 1024x896 OGL WIN     11 = 800x600  OGL FULL',13,10
db ';  12 = 1024x768 OGL FULL    13 = 640x480  OGL WIN',13,10
db ';  14 = 800x600  OGL WIN     15 = 1024x768 OGL WIN',13,10
db ';  16 = VARIABLE OGL WIN',13,10
%endif
db '',13,10
db 'VideoModeLin = %U',13,10
db '',13,10
%endif
%ifdef __MSDOS__
db '; Video Mode, 0 - 18',13,10
db ';  0 = 256x224x8B  (MODEQ)  1 = 256x240x8B (MODEQ)',13,10
db ';  2 = 256x256x8B  (MODEQ)  3 = 320x224x8B (MODEX)',13,10
db ';  4 = 320x240x8B  (MODEX)  5 = 320x256x8B (MODEX)',13,10
db ';  6 = 640x480x16B (VESA1)  7 = 320x240x8B (VESA2)',13,10
db ';  8 = 320x240x16B (VESA2)  9 = 320x480x8B (VESA2)',13,10
db '; 10 = 320x480x16B (VESA2) 11 = 512x384x8B (VESA2)',13,10
db '; 12 = 512x384x16B (VESA2) 13 = 640x400x8B (VESA2)',13,10
db '; 14 = 640x400x16B (VESA2) 15 = 640x480x8B (VESA2)',13,10
db '; 16 = 640x480x16B (VESA2) 17 = 800x600x8B (VESA2)',13,10
db '; 18 = 800x600x16B (VESA2)',13,10
db '',13,10
db 'VideoModeDos = %U',13,10
db '',13,10
%endif
db '; Sound Emulation = 0 or 1 (1 = ON)',13,10
db '',13,10
db 'Sound = %V',13,10
db '',13,10
db '; Sound Sampling Rate',13,10
db ';   0 =  8,000 Hz, 1 = 11,025 Hz, 2 = 22,050 Hz',13,10
db ';   3 = 44,100 Hz, 4 = 16,000 Hz, 5 = 32,000 Hz',13,10
db '',13,10                               
db 'SoundRate = %W',13,10
db '',13,10
db '; Stereo (0 = off, 1 = on)',13,10
db '',13,10
db 'Stereo = %X',13,10
db '',13,10
db '; Stereo Reversed.  Swaps left channel with right. (0 = off, 1 = L <-> R)',13,10
db '',13,10
db 'ReverseStereo = %s',13,10
db '',13,10
%ifdef __MSDOS__
db '; GUI Disable (1 = Disable GUI, 0 = Enable GUI)',13,10
db '',13,10
db 'GUIDisable = %Y',13,10
db '',13,10
%endif
db '; New Graphics Engine (1 = Enable, 0 = Disable)',13,10
%ifdef __MSDOS__
db '; All 256 color modes and 320x240x65536 supported',13,10
%endif
db '',13,10
db 'NewGfx = %n',13,10
db '',13,10
db '; Scanlines (0 = Disable, 1 = Full, 2 = 25%, 3 = 50%)',13,10
%ifdef __MSDOS__
db '; 256x256x256 or 640x480 modes only (25% and 50% in 640x480x65536 mode only)',13,10
%endif
db '',13,10
db 'Scanlines = %Z',13,10
db '',13,10
%ifdef __MSDOS__
db '; Interpolation (1 = Enable, 0 = Disable) - 640x480x65536 mode only',13,10
db '; This option also Enables EAGLE          - 640x480x256 mode only',13,10
%else
db '; Interpolation (1 = Enable, 0 = Disable)',13,10
%endif
db '',13,10
db 'Interpolation = %a',13,10
db '',13,10
%ifndef __LINUX__
db '; VSync (1 = Enable, 0 = Disable) - Wait for Vertical Sync (Fast cpu reqd)',13,10
db '',13,10
db 'VSync = %p',13,10
db '',13,10
%endif
%ifdef __MSDOS__
db '; Skip Enter Press at Beginning  (1 = Yes, 0 = No)',13,10
db '',13,10
db 'EnterSkip = %b',13,10
db '',13,10
db '; Force 8-bit sound on  (1 = Yes, 0 = No)',13,10
db '',13,10
db 'Force8bit = %c',13,10
db '',13,10
%endif
db '; Disable Echo  (1 = Yes, 0 = No)',13,10
db '',13,10
db 'EchoDisable = %r',13,10
db '',13,10
db '; Sound Volume Level (0 .. 100)',13,10
db '; Note : Setting this too high can cause sound overflow which degrades quality',13,10
db '',13,10
db 'Volume = %q',13,10
db '',13,10
db '; Set this to 1 if you do not want ZSNES to save the configuration files.',13,10
db '',13,10
db 'DontSave = %u',13,10
db '',13,10
db '; Savefile directory.  Leave it blank if you want the save files to be in the',13,10
db '; same directory as the games.  It should be in a format like : C:\dir\dir',13,10
db '',13,10
db 'SaveDirectory = %d',13,10
db '',13,10
db '; Game directory.  This is the directory where the GUI starts at.',13,10
db '; ZSNES automatically writes the current directory here upon exit.',13,10
db '',13,10
db 'GameDirectory = %e',13,10
.cfgfilesize equ $-.cfgfiledata

NEWSYM getcfg
    mov byte[.forceauto],0
    ; open file
    mov edx,CMDLineStr
    call Open_File
    jc .failed
    mov [.fileloc],ax
    mov byte[.eofile],0
.noteof
    call .readstring
    cmp dword[.stralen],1
    jbe .skipstpr
    call .splitstring
.skipstpr
    cmp byte[.eofile],0
    je .noteof
    
    mov bx,[.fileloc]
    call Close_File
    ret

.failed
    call DOScreatenewcfg
    ret

.readstring:
    mov dword[.strlen],0
    mov dword[.stralen],0
    mov byte[.ignore],0
.startloop
    mov bx,[.fileloc]
    mov ecx,1
    mov edx,.cchar
    call Read_File
    cmp eax,0
    je .endoffile
    cmp byte[.cchar],';'
    je .comment
    cmp byte[.cchar],13
    je .eoline
    cmp byte[.cchar],10
    je .startloop
    mov ecx,[.strlen]
    mov al,[.cchar]
    cmp ecx,127
    ja .nocopy
    cmp byte[.ignore],1
    je .nocopy
    mov [.string+ecx],al
    inc dword[.stralen]
.nocopy
    inc dword[.strlen]
    jmp .startloop
    ret
.comment
    inc dword[.strlen]
    mov byte[.ignore],1
    jmp .startloop
    ret
.eoline
    ret
.endoffile
    mov byte[.eofile],1
    ret

.splitstring:
    ; search for ='s
    mov ecx,[.stralen]
    dec ecx
    xor eax,eax
    xor ebx,ebx
.next
    cmp byte[.string+eax],'='
    jne .noeq
    inc ebx
.noeq
    inc eax
    dec ecx
    jnz .next
    cmp ebx,1
    je .onequal
    ret

.onequal
    xor eax,eax
    xor ebx,ebx
    mov ecx,[.stralen]
    mov dword[.strlena],0
    mov dword[.strlenb],0
.loopa
    mov dl,[.string+eax]
    cmp dl,'='
    je .nextb
    cmp dl,' '
    je .skipcopy
    cmp dl,'a'
    jb .nocapneeded
    cmp dl,'z'
    ja .nocapneeded
    sub dl,'a'-'A'
.nocapneeded
    mov [.stringa+ebx],dl
    inc dword[.strlena]
    inc ebx
.skipcopy
    inc eax
    dec ecx
    jnz .loopa
    ret
.nextb
    inc eax
    dec ecx
    jnz .noblank
.yesblank
    ret
.noblank
    xor ebx,ebx
    mov byte[.usespace],0
.loopb
    mov dl,[.string+eax]
    cmp byte[.usespace],0
    jne .nospaceskip
    cmp dl,' '
    je .skipcopyb
.nospaceskip
%ifndef __LINUX__
    cmp dl,'a'
    jb .nocapneededb
    cmp dl,'z'
    ja .nocapneededb
    sub dl,'a'-'A'
%endif    
.nocapneededb
    mov byte[.usespace],1
    mov [.stringb+ebx],dl
    inc dword[.strlenb]
    inc ebx
.skipcopyb
    inc eax
    dec ecx
    jnz .loopb
    cmp dword[.strlena],0
    je .nostr
    cmp dword[.strlenb],0
    je .nostr
    jmp .process
.nostr
    ret

.process
    mov ecx,[.strlena]
    cmp ecx,[.stra]
    jne .nostra
    mov edx,.stra+4
    mov eax,.stringa
    call .cmpstr
    cmp bl,1
    je .nostra
    call .getframeskip
.nostra
    mov ecx,[.strlena]
    cmp ecx,[.strb]
    jne .nostrb
    mov edx,.strb+4
    mov eax,.stringa
    call .cmpstr
    cmp bl,1
    je .nostrb
    call .getautoframeskip
.nostrb
    mov ecx,[.strlena]
    cmp ecx,[.strc]
    jne .nostrc
    mov edx,.strc+4
    mov eax,.stringa
    call .cmpstr
    cmp bl,1
    je .nostrc
    call .getplayer1device
.nostrc
    mov ecx,[.strlena]
    cmp ecx,[.strd]
    jne .nostrd
    mov edx,.strd+4
    mov eax,.stringa
    call .cmpstr
    cmp bl,1
    je .nostrd
    call .getplayer2device
.nostrd
    mov ecx,[.strlena]
    cmp ecx,[.stre]
    jne .nostre
    mov edx,.stre+4
    mov eax,.stringa
    call .cmpstr
    cmp bl,1
    je .nostre
    call .getscankey1
.nostre
    mov ecx,[.strlena]
    cmp ecx,[.strf]
    jne .nostrf
    mov edx,.strf+4
    mov eax,.stringa
    call .cmpstr
    cmp bl,1
    je .nostrf
    call .getscankey2
.nostrf
    mov ecx,[.strlena]
    cmp ecx,[.strg]
    jne .nostrg
    mov edx,.strg+4
    mov eax,.stringa
    call .cmpstr
    cmp bl,1
    je .nostrg
    call .getsound
.nostrg
    mov ecx,[.strlena]
    cmp ecx,[.strh]
    jne .nostrh
    mov edx,.strh+4
    mov eax,.stringa
    call .cmpstr
    cmp bl,1
    je .nostrh
    call .getsoundrate
.nostrh
    mov ecx,[.strlena]
    cmp ecx,[.stri]
    jne .nostri
    mov edx,.stri+4
    mov eax,.stringa
    call .cmpstr
    cmp bl,1
    je .nostri
    call .getvideo
.nostri
    mov ecx,[.strlena]
    cmp ecx,[.strj]
    jne .nostrj
    mov edx,.strj+4
    mov eax,.stringa
    call .cmpstr
    cmp bl,1
    je .nostrj
    call .getexecute
.nostrj
    mov ecx,[.strlena]
    cmp ecx,[.strk]
    jne .nostrk
    mov edx,.strk+4
    mov eax,.stringa
    call .cmpstr
    cmp bl,1
    je .nostrk
    call .getbufdisable
.nostrk
    mov ecx,[.strlena]
    cmp ecx,[.strm]
    jne .nostrm
    mov edx,.strm+4
    mov eax,.stringa
    call .cmpstr
    cmp bl,1
    je .nostrm
    call .getstereo
.nostrm
    mov ecx,[.strlena]
    cmp ecx,[.strn]
    jne .nostrn
    mov edx,.strn+4
    mov eax,.stringa
    call .cmpstr
    cmp bl,1
    je .nostrn
    call .guidisable
.nostrn
    mov ecx,[.strlena]
    cmp ecx,[.stro]
    jne .nostro
    mov edx,.stro+4
    mov eax,.stringa
    call .cmpstr
    cmp bl,1
    je .nostro
    call .scanlines
.nostro
    mov ecx,[.strlena]
    cmp ecx,[.strp]
    jne .nostrp
    mov edx,.strp+4
    mov eax,.stringa
    call .cmpstr
    cmp bl,1
    je .nostrp
    call .interpolation
.nostrp
    mov ecx,[.strlena]
    cmp ecx,[.strq]
    jne .nostrq
    mov edx,.strq+4
    mov eax,.stringa
    call .cmpstr
    cmp bl,1
    je .nostrq
    call .enterskip
.nostrq
    mov ecx,[.strlena]
    cmp ecx,[.strr]
    jne .nostrr
    mov edx,.strr+4
    mov eax,.stringa
    call .cmpstr
    cmp bl,1
    je .nostrr
    call .force8b
.nostrr
    mov ecx,[.strlena]
    cmp ecx,[.strs]
    jne .nostrs
    mov edx,.strs+4
    mov eax,.stringa
    call .cmpstr
    cmp bl,1
    je .nostrs
    call .getsavedir
.nostrs
    mov ecx,[.strlena]
    cmp ecx,[.strt]
    jne .nostrt
    mov edx,.strt+4
    mov eax,.stringa
    call .cmpstr
    cmp bl,1
    je .nostrt
    call .getloaddir
.nostrt
    mov ecx,[.strlena]
    cmp ecx,[.stru]
    jne .nostru
    mov edx,.stru+4
    mov eax,.stringa
    call .cmpstr
    cmp bl,1
    je .nostru
    call .getjoymapping
.nostru
    mov ecx,[.strlena]
    cmp ecx,[.strv]
    jne .nostrv
    mov edx,.strv+4
    mov eax,.stringa
    call .cmpstr
    cmp bl,1
    je .nostrv
    call .getnewgfx
.nostrv
    mov ecx,[.strlena]
    cmp ecx,[.strw]
    jne .nostrw
    mov edx,.strw+4
    mov eax,.stringa
    call .cmpstr
    cmp bl,1
    je .nostrw
    call .getvsync
.nostrw
    mov ecx,[.strlena]
    cmp ecx,[.strx]
    jne .nostrx
    mov edx,.strx+4
    mov eax,.stringa
    call .cmpstr
    cmp bl,1
    je .nostrx
    call .getvolume
.nostrx
    mov ecx,[.strlena]
    cmp ecx,[.stry]
    jne .nostry
    mov edx,.stry+4
    mov eax,.stringa
    call .cmpstr
    cmp bl,1
    je .nostry
    call .getecho
.nostry
    mov ecx,[.strlena]
    cmp ecx,[.strz]
    jne .nostrz
    mov edx,.strz+4
    mov eax,.stringa
    call .cmpstr
    cmp bl,1
    je .nostrz
    call .getreverses
.nostrz
    mov ecx,[.strlena]
    cmp ecx,[.str1]
    jne .nostr1
    mov edx,.str1+4
    mov eax,.stringa
    call .cmpstr
    cmp bl,1
    je .nostr1
    call .getplay1234
.nostr1
    mov ecx,[.strlena]
    cmp ecx,[.str2]
    jne .nostr2
    mov edx,.str2+4
    mov eax,.stringa
    call .cmpstr
    cmp bl,1
    je .nostr2
    call .getdontsave
.nostr2
    mov ecx,[.strlena]
    cmp ecx,[.str3]
    jne .nostr3
    mov edx,.str3+4
    mov eax,.stringa
    call .cmpstr
    cmp bl,1
    je .nostr3
    call .getreinit
.nostr3
    ret

.cmpstr
    xor bl,bl
.loopcmp
    mov bh,[eax]
    cmp [edx],bh
    jne .nocmp
    inc eax
    inc edx
    dec ecx
    jnz .loopcmp
    ret
.nocmp
    mov bl,1
    ret

.getframeskip
    cmp dword[.strlenb],1
    jne .noframeskip
    mov al,[.stringb]
    cmp al,'0'
    jb .noframeskip
    cmp al,'9'
    ja .noframeskip
    cmp byte[.forceauto],1
    je .noframeskip
    sub al,47
    mov [frameskip],al
.noframeskip
    ret

.getautoframeskip
    cmp dword[.strlenb],1
    jne .noautoframeskip
    cmp byte[.stringb],'1'
    jne .noautoframeskip
    mov byte[.forceauto],1
    mov byte[frameskip],0
.noautoframeskip
    ret

.getplayer1device
    cmp dword[.strlenb],2
    je .double
    cmp dword[.strlenb],1
    jne .noplay1
    mov al,[.stringb]
    cmp al,'0'
    jb .noplay1
    cmp al,'9'
    ja .noplay1
    sub al,48
    mov [pl1contrl],al
.noplay1
    ret
.double
    mov al,[.stringb]
    cmp al,'1'
    jne .noplay1
    mov al,[.stringb+1]
    cmp al,'0'
    jb .noplay1
    cmp al,'8'
    ja .noplay1
    sub al,38
    mov [pl1contrl],al
    ret

.getplayer2device
    cmp dword[.strlenb],2
    je .double2
    cmp dword[.strlenb],1
    jne .noplay2
    mov al,[.stringb]
    cmp al,'0'
    jb .noplay2
    cmp al,'9'
    ja .noplay2
    sub al,48
    mov [pl2contrl],al
.noplay2
    ret
.double2
    mov al,[.stringb]
    cmp al,'1'
    jne .noplay2
    mov al,[.stringb+1]
    cmp al,'0'
    jb .noplay2
    cmp al,'8'
    ja .noplay2
    sub al,38
    mov [pl2contrl],al
    ret

.getscankey1
    mov ecx,.stringb
    xor ebx,ebx
    xor eax,eax
.checknextscan1
    cmp dword[.strlenb],0
    je near .noscankey1
    mov bl,[ecx]
    inc ecx
    dec dword[.strlenb]
    cmp bl,','
    je near .finstr1
    cmp bl,'0'
    jb near .nextstr1
    cmp bl,'9'
    ja near .nextstr1
    sub bl,48
    push ebx
    mov ebx,10
    mul ebx
    pop ebx
    mov edx,ebx
    and edx,0FFh
    add eax,edx
    cmp dword[.strlenb],0
    je near .finstr1
    jmp .nextstr1
.finstr1
    ; determine which variable according to bh & write
    ; In order of Right, Left, Down, Up, Start, Select, A, B, X, Y, L, R
    cmp bh,0
    jne .nextaa
    mov [pl1rightk],eax
.nextaa
    cmp bh,1
    jne .nextba
    mov [pl1leftk],eax
.nextba
    cmp bh,2
    jne .nextca
    mov [pl1downk],eax
.nextca
    cmp bh,3
    jne .nextda
    mov [pl1upk],eax
.nextda
    cmp bh,4
    jne .nextea
    mov [pl1startk],eax
.nextea
    cmp bh,5
    jne .nextfa
    mov [pl1selk],eax
.nextfa
    cmp bh,6
    jne .nextga
    mov [pl1Bk],eax
.nextga
    cmp bh,7
    jne .nextha
    mov [pl1Yk],eax
.nextha
    cmp bh,8
    jne .nextia
    mov [pl1Ak],eax
.nextia
    cmp bh,9
    jne .nextja
    mov [pl1Xk],eax
.nextja
    cmp bh,10
    jne .nextka
    mov [pl1Lk],eax
.nextka
    cmp bh,11
    jne .nextla
    mov [pl1Rk],eax
.nextla
    xor eax,eax
    inc bh
.nextstr1
    jmp .checknextscan1
.noscankey1
    ret

.getscankey2
    mov ecx,.stringb
    xor ebx,ebx
    xor eax,eax
.checknextscan2
    cmp dword[.strlenb],0
    je near .noscankey2
    mov bl,[ecx]
    inc ecx
    dec dword[.strlenb]
    cmp bl,','
    je near .finstr2
    cmp bl,'0'
    jb near .nextstr2
    cmp bl,'9'
    ja near .nextstr2
    sub bl,48
    push ebx
    mov ebx,10
    mul ebx
    pop ebx
    mov edx,ebx
    and edx,0FFh
    add eax,edx
    cmp dword[.strlenb],0
    je near .finstr2
    jmp .nextstr2
.finstr2
    ; determine which variable according to bh & write
    ; In order of Right, Left, Down, Up, Start, Select, A, B, X, Y, L, R
    cmp bh,0
    jne .nextaa2
    mov [pl2rightk],eax
.nextaa2
    cmp bh,1
    jne .nextba2
    mov [pl2leftk],eax
.nextba2
    cmp bh,2
    jne .nextca2
    mov [pl2downk],eax
.nextca2
    cmp bh,3
    jne .nextda2
    mov [pl2upk],eax
.nextda2
    cmp bh,4
    jne .nextea2
    mov [pl2startk],eax
.nextea2
    cmp bh,5
    jne .nextfa2
    mov [pl2selk],eax
.nextfa2
    cmp bh,6
    jne .nextga2
    mov [pl2Bk],eax
.nextga2
    cmp bh,7
    jne .nextha2
    mov [pl2Yk],eax
.nextha2
    cmp bh,8
    jne .nextia2
    mov [pl2Ak],eax
.nextia2
    cmp bh,9
    jne .nextja2
    mov [pl2Xk],eax
.nextja2
    cmp bh,10
    jne .nextka2
    mov [pl2Lk],eax
.nextka2
    cmp bh,11
    jne .nextla2
    mov [pl2Rk],eax
.nextla2
    xor eax,eax
    inc bh
.nextstr2
    jmp .checknextscan2
.noscankey2
    ret

.getsound
    cmp dword[.strlenb],1
    jne .nosound
    mov al,[.stringb]
    cmp al,'1'
    jne .nosound
    mov byte[spcon],1        ; SPC Enabled
    mov byte[soundon],1
    mov byte[cfgsoundon],1
.nosound
    ret

.getsoundrate
    cmp dword[.strlenb],1
    jne .nosoundrate
    mov al,[.stringb]
    cmp al,'0'
    jb .nosoundrate
    cmp al,'6'
    ja .nosoundrate
    sub al,48
    mov [SoundQuality],al
    mov [cfgSoundQuality],al
.nosoundrate
    ret

.getvideo
    cmp dword[.strlenb],2
    je .videob
    cmp dword[.strlenb],1
    jne .novideo
    mov al,[.stringb]
    cmp al,'0'
    jb .novideo
    cmp al,'9'
    ja .novideo
    sub al,48
    mov [cvidmode],al
    mov [cfgcvidmode],al
.novideo
    ret
.videob
    cmp byte[.stringb],'1'
    jne .novideo2
    mov al,[.stringb+1]
    sub al,38
    mov [cvidmode],al
    mov [cfgcvidmode],al
    ret
.novideo2
    cmp byte[.stringb],'2'
    jne .novideo3
    mov al,[.stringb+1]
    sub al,28
    mov [cvidmode],al
    mov [cfgcvidmode],al
    ret
.novideo3
    cmp byte[.stringb],'3'
    jne .novideo
    mov al,[.stringb+1]
    sub al,18
    mov [cvidmode],al
    mov [cfgcvidmode],al
    ret

.getexecute
    cmp dword[.strlenb],0
    je .noexecute
    mov cl,[.strlenb]
    mov esi,.stringb
    mov byte[.per2exec],0
.getnextperc
    mov bl,10
    mov al,[.per2exec]
    cmp al,100
    jae .noexecute
    mul bl
    mov [.per2exec],al
    mov al,[esi]
    cmp al,'0'
    jb .noexecute
    cmp al,'9'
    ja .noexecute
    sub al,48
    add [.per2exec],al
    inc esi                     ; next character
    dec cl
    jz .nonextperc
    jmp .getnextperc
.nonextperc
    cmp byte[.per2exec],150
    ja .noexecute
    cmp byte[.per2exec],50
    jb .noexecute
    mov al,[.per2exec]
    mov [per2exec],al
    mov [cfgper2exec],al
.noexecute
    ret

.getreinit
    cmp dword[.strlenb],0
    je .nogetreinit
    mov cl,[.strlenb]
    mov esi,.stringb
    mov byte[.per2exec],0
.getnextgetreinit
    mov bl,10
    mov al,[.per2exec]
    cmp al,100
    jae .nogetreinit
    mul bl
    mov [.per2exec],al
    mov al,[esi]
    cmp al,'0'
    jb .nogetreinit
    cmp al,'9'
    ja .nogetreinit
    sub al,48
    add [.per2exec],al
    inc esi                     ; next character
    dec cl
    jz .nonextgetreinit
    jmp .getnextgetreinit
.nonextgetreinit
    cmp byte[.per2exec],150
    ja .nogetreinit
    cmp byte[.per2exec],5
    jb .nogetreinit
    mov al,[.per2exec]
    mov [cfgreinittime],al
.nogetreinit
    ret

.getbufdisable
    cmp dword[.strlenb],1
    jne .nobufdisable
    cmp byte[.stringb],'1'
    jne .nobufdisable
    mov byte[SoundCompD],1
.nobufdisable
    ret

.getstereo
    cmp dword[.strlenb],1
    jne .nostereo
    cmp byte[.stringb],'1'
    jne .nostereo
    mov byte[StereoSound],1
    mov byte[cfgStereoSound],1
.nostereo
    ret

.guidisable
    cmp dword[.strlenb],1
    jne .noguidisable
    cmp byte[.stringb],'1'
    jne .noguidisable
    mov byte[guioff],1
    mov byte[cfgguioff],1
.noguidisable
    ret

.scanlines
    cmp dword[.strlenb],1
    jne .noscanlines
    cmp byte[.stringb],'1'
    jne .noscanlines
    mov byte[scanlines],1
    mov byte[cfgscanline],1
.noscanlines
    cmp byte[.stringb],'2'
    jne .noscanlinesh2
    mov byte[scanlines],2
    mov byte[cfgscanline],2
.noscanlinesh2
    cmp byte[.stringb],'3'
    jne .noscanlinesh3
    mov byte[scanlines],3
    mov byte[cfgscanline],3
.noscanlinesh3
    ret

.interpolation
    cmp dword[.strlenb],1
    jne .nointerpolation
    cmp byte[.stringb],'1'
    jne .nointerpolation
    mov byte[antienab],1
    mov byte[cfginterp],1
.nointerpolation
    ret

.enterskip
    cmp dword[.strlenb],1
    jne .noenterskip
    cmp byte[.stringb],'1'
    jne .noenterskip
    mov byte[enterpress],1
    mov byte[cfgenterskip],1
.noenterskip
    ret

.force8b
    cmp dword[.strlenb],1
    jne .noforce8b
    cmp byte[.stringb],'1'
    jne .noforce8b
    mov byte[Force8b],1
    mov byte[cfgforce8b],1
.noforce8b
    ret

.getsavedir
    cmp dword[.strlenb],3
    jb .nosavedir
%ifndef __LINUX__
    cmp byte[.stringb+1],':'
    jne .nosavedir
    cmp byte[.stringb+2],'\'
    jne .nosavedir
    mov byte[cfgloadsdir],1
    mov al,[.stringb]
    sub al,65
    mov [SRAMDrive],al
%else
    mov byte[cfgloadsdir],1
%endif    
    push ecx
    push esi
    push edi
    mov ecx,[.strlenb]
%ifndef __LINUX__    
    sub ecx,3
    mov esi,.stringb+3
%else
    mov esi,.stringb
%endif        
    mov edi,SRAMDir
    cmp ecx,0
    je .ndird
.ndirc
    mov al,[esi]
    mov [edi],al
    inc esi
    inc edi
    dec ecx
    jnz .ndirc
.ndird
    mov byte[edi],0
    pop edi
    pop esi
    pop ecx
.nosavedir
    ret

.getloaddir
    cmp dword[.strlenb],3
    jb .noloaddir
%ifndef __LINUX__    
    cmp byte[.stringb+1],':'
    jne .noloaddir
    cmp byte[.stringb+2],'\'
    jne .noloaddir
    mov byte[cfgloadgdir],1
    mov al,[.stringb]
    sub al,65
    mov [LoadDrive],al
    mov [LoadDriveB],al
%else
    mov byte[cfgloadgdir],1
%endif        
    push ecx
    push esi
    push edi
    push ebx
    mov ecx,[.strlenb]
%ifndef __LINUX__    
    sub ecx,3
    mov esi,.stringb+3
%else
    mov esi,.stringb
%endif        
    mov edi,LoadDir
    mov ebx,LoadDirB
    cmp ecx,0
    je .ndirb
.ndir
    mov al,[esi]
    mov [edi],al
    mov [ebx],al
    inc esi
    inc edi
    inc ebx
    dec ecx
    jnz .ndir
.ndirb
    mov byte[edi],0
    pop ebx
    pop edi
    pop esi
    pop ecx
.noloaddir
    ret

.getjoymapping
    mov byte[JoyStatRead],1
    mov ecx,.stringb
    xor ebx,ebx
    xor eax,eax
.checknextscan3
    cmp dword[.strlenb],0
    je near .noscankey3
    mov bl,[ecx]
    inc ecx
    dec dword[.strlenb]
    cmp bl,','
    je near .finstr3
    cmp bl,'0'
    jb near .nextstr3
    cmp bl,'9'
    ja near .nextstr3
    sub bl,48
    mov dl,10
    mul dl
    add al,bl
    cmp dword[.strlenb],0
    je near .finstr3
    jmp .nextstr3
.finstr3
    ; determine which variable according to bh & write
    ; In order of Start, Select, B, Y, A, X, L, R
    cmp bh,0
    jne .nextaa3
    mov byte[JoyStart],al
.nextaa3
    cmp bh,1
    jne .nextba3
    mov byte[JoySelec],al
.nextba3
    cmp bh,2
    jne .nextca3
    mov byte[JoyBC],al
.nextca3
    cmp bh,3
    jne .nextda3
    mov byte[JoyYC],al
.nextda3
    cmp bh,4
    jne .nextea3
    mov byte[JoyAC],al
.nextea3
    cmp bh,5
    jne .nextfa3
    mov byte[JoyXC],al
.nextfa3
    cmp bh,6
    jne .nextga3
    mov byte[JoyLC],al
.nextga3
    cmp bh,7
    jne .nextha3
    mov byte[JoyRC],al
.nextha3
    xor eax,eax
    inc bh
.nextstr3
    jmp .checknextscan3
.noscankey3
    ret

.getnewgfx
    cmp dword[.strlenb],1
    jne .nonewgfx
    cmp byte[.stringb],'1'
    jne .nonewgfx
    mov byte[newengen],1
    mov byte[cfgnewgfx],1
.nonewgfx
    ret

.getvsync
    cmp dword[.strlenb],1
    jne .novsync
    cmp byte[.stringb],'1'
    jne .novsync
    mov byte[vsyncon],1
    mov byte[cfgvsync],1
.novsync
    ret

.getecho
    cmp dword[.strlenb],1
    jne .nodecho
    cmp byte[.stringb],'1'
    jne .nodecho
    mov byte[cfgecho],1
.nodecho
    ret

.getplay1234
    cmp dword[.strlenb],1
    jne .nop1234
    cmp byte[.stringb],'1'
    jne .nop1234
    mov byte[pl12s34],1
.nop1234
    ret

.getdontsave
    cmp dword[.strlenb],1
    jne .nodontsave
    cmp byte[.stringb],'1'
    jne .nodontsave
    mov byte[cfgdontsave],1
.nodontsave
    ret

.getreverses
    cmp dword[.strlenb],1
    jne .nors
    cmp byte[.stringb],'1'
    jne .nors
    mov byte[RevStereo],1
.nors
    ret

.getvolume
    cmp dword[.strlenb],0
    je .novolume
    mov cl,[.strlenb]
    mov esi,.stringb
    mov byte[.volume],0
.getnextvol
    mov bl,10
    mov al,[.volume]
    cmp al,100
    jae .novolume
    mul bl
    mov [.volume],al
    mov al,[esi]
    cmp al,'0'
    jb .novolume
    cmp al,'9'
    ja .novolume
    sub al,48
    add [.volume],al
    inc esi                     ; next character
    dec cl
    jz .nonextvol
    jmp .getnextvol
.nonextvol
    cmp byte[.volume],100
    ja .novolume
    mov al,[.volume]
    mov [MusicRelVol],al
    mov [cfgvolume],al
.novolume
    ret

SECTION .data

.per2exec db 0
.volume   db 0
.fileloc dw 0
.eofile  db 0
.ignore  db 0
.strlen  dd 0
.stralen dd 0    ; actual string length
.strlena dd 0
.strlenb dd 0
.cchar   db 0
.forceauto db 0
.string  times 128 db 0  ; full string
.stringa times 128 db 0
.stringb times 128 db 0
.cfgfname db 'zsnes.cfg',0
.stra dd 9
      db 'FRAMESKIP'
.strb dd 13
      db 'AUTOFRAMESKIP'
.strc dd 13
      db 'PLAYER1DEVICE'
.strd dd 13
      db 'PLAYER2DEVICE'
.stre dd 8
      db 'SCANKEY1'
.strf dd 8
      db 'SCANKEY2'
.strg dd 5
      db 'SOUND'
.strh dd 9
      db 'SOUNDRATE'
%ifdef __WIN32__
.stri dd 12
      db 'VIDEOMODEWIN'
%endif
%ifdef __LINUX__
.stri dd 12
      db 'VIDEOMODELIN'
%endif
%ifdef __MSDOS__
.stri dd 12
      db 'VIDEOMODEDOS'
%endif
.strj dd 7
      db 'EXECUTE'
.strk dd 15
      db 'SOUNDBUFDISABLE'
.strm dd 6
      db 'STEREO'
.strn dd 10
      db 'GUIDISABLE'
.stro dd 9
      db 'SCANLINES'
.strp dd 13
      db 'INTERPOLATION'
.strq dd 9
      db 'ENTERSKIP'
.strr dd 9
      db 'FORCE8BIT'
.strs dd 13
      db 'SAVEDIRECTORY'
.strt dd 13
      db 'GAMEDIRECTORY'
.stru dd 7
      db 'JOYMAP1'
.strv dd 6
      db 'NEWGFX'
.strw dd 5
      db 'VSYNC'
.strx dd 6
      db 'VOLUME'
.stry dd 11
      db 'ECHODISABLE'
.strz dd 13
      db 'REVERSESTEREO'
.str1 dd 13
      db 'PL34TO12SHARE'
.str2 dd 8
      db 'DONTSAVE'
.str3 dd 10
      db 'REINITTIME'
.usespace db 0

SECTION .text

NEWSYM CfgLoadAsmEnd
