1530 lines
29 KiB
NASM
1530 lines
29 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 ProcessSoundBuffer,DosExit,getenv,PrintStr,printhex,printnum,WaitForKey
|
|
EXTSYM SBHDMA,soundon,csounddisable,DisplayS,spcRam,DSPMem
|
|
EXTSYM Surround,StereoSound,SoundQuality,SoundSpeeds,SBToSPCSpeeds2
|
|
EXTSYM SoundSpeedt,DSPBuffer,BufferSize,BufferSizes,BufferSizeB
|
|
EXTSYM BufferSizeW,dssel
|
|
|
|
SECTION .text
|
|
|
|
NEWSYM SB_alloc_dma
|
|
|
|
mov ax,0100h ; Allocate DOS memory
|
|
mov bx,16384/16 ; Allocate 16384 bytes
|
|
int 31h
|
|
; To delocate this, use ax=0101h, dx=selector of block/int 31h
|
|
jc near .error
|
|
; Check which 8192 byte boundary doesn't cross a page
|
|
mov word[memoryloc+2],0
|
|
mov dword[memoryloc],0
|
|
mov [memoryloc],ax
|
|
mov [sbselec],dx
|
|
shl dword[memoryloc],4
|
|
mov edx,[memoryloc]
|
|
shr edx,16
|
|
mov al,dl
|
|
mov edx,[memoryloc]
|
|
add edx,8192
|
|
shr edx,16
|
|
mov dword[sbpmofs],0
|
|
cmp al,dl
|
|
je .nonextarea
|
|
mov dword[sbpmofs],8192
|
|
add dword[memoryloc],8192
|
|
.nonextarea
|
|
mov edi,[sbpmofs]
|
|
mov [SBBufferLoc],edi
|
|
mov dword[SBBufferMov],1
|
|
mov dword[SBBufferInc],4
|
|
; clear dos memory
|
|
push es
|
|
mov es,[sbselec]
|
|
mov edi,[sbpmofs]
|
|
mov ecx,2048
|
|
mov eax,0
|
|
rep stosd
|
|
pop es
|
|
ret
|
|
|
|
.error
|
|
mov edx,.nohand ;use extended
|
|
mov ah,9 ;DOS- API
|
|
int 21h ;to print a string
|
|
call DosExit
|
|
|
|
SECTION .data
|
|
.nohand db 'Unable to allocate conventional memory!',13,10,'$'
|
|
SECTION .text
|
|
|
|
|
|
NEWSYM DeInitSPC
|
|
cmp byte[SBDeinitType],0
|
|
je .nodoublereset
|
|
call SB_dsp_reset
|
|
call SB_dsp_reset
|
|
.nodoublereset
|
|
; Turn off speakers
|
|
mov al,0d3h
|
|
call SB_dsp_write
|
|
|
|
; k) Perform Halt DMA Operation, 8-bit command (0D0h - for virtual speaker)
|
|
mov al,0d0h
|
|
call SB_dsp_write
|
|
; l) Perform Exit Auto-Initialize DMA Operation, 8-bit command (0DAh)
|
|
cmp byte[SBHDMA],0
|
|
je .8b
|
|
mov al,0d9h
|
|
call SB_dsp_write
|
|
jmp .16b
|
|
.8b
|
|
mov al,0dAh
|
|
call SB_dsp_write
|
|
.16b
|
|
; m) Perform Halt DMA Operation, 8-bit command (0D0h - for virtual speaker)
|
|
mov al,0d0h
|
|
call SB_dsp_write
|
|
; Disable DMA
|
|
mov al,4
|
|
add al,[SBDMA]
|
|
mov dx,0ah
|
|
out dx,al
|
|
ret
|
|
|
|
section .data
|
|
|
|
;SoundBlaster DSP Ports
|
|
NEWSYM SBPort, dw 220
|
|
NEWSYM SBInt, db 5+8
|
|
NEWSYM SBIrq, db 5
|
|
NEWSYM SBDMA, db 1
|
|
NEWSYM SBDMAPage, db 83
|
|
;NEWSYM SBHDMA, db 0
|
|
NEWSYM SBHDMAPage, db 0
|
|
NEWSYM vibracard, db 0
|
|
|
|
NEWSYM SBBufferLoc, dd 0
|
|
NEWSYM SBBufferMov, dd 0
|
|
NEWSYM SBBufferInc, dd 0
|
|
NEWSYM SoundInterrupt, dd 0
|
|
|
|
|
|
; ViBRA16X fixes!
|
|
EXTSYM MsgCount ; points to counter
|
|
EXTSYM MessageOn ; points to "message" delay counter
|
|
EXTSYM Msgptr ; points to the message to be displayed
|
|
NEWSYM vibmsg, db 'VIBRA16X MODE ENABLED', 0
|
|
|
|
section .text
|
|
|
|
NEWSYM SB_dsp_reset
|
|
mov dx,[SBPort]
|
|
add dl,06h
|
|
mov al,01h
|
|
out dx,al
|
|
in al,dx
|
|
in al,dx
|
|
in al,dx
|
|
in al,dx
|
|
mov al,00h
|
|
out dx,al
|
|
|
|
mov si,200
|
|
mov dx,[SBPort]
|
|
add dl,0Eh
|
|
.readloop
|
|
|
|
; wait until port[SBDSPRdStat] AND 80h = 80h
|
|
mov cx,20000
|
|
.tryagain
|
|
in al,dx
|
|
dec cx
|
|
jz .cardfailed
|
|
or al,al
|
|
jns .tryagain
|
|
sub dx,4
|
|
in al,dx
|
|
cmp al,0AAh
|
|
jne .tryagain2
|
|
ret
|
|
.tryagain2
|
|
add dx,4
|
|
dec si
|
|
jnz .readloop
|
|
.cardfailed
|
|
mov ax,0003h
|
|
int 10h
|
|
mov edx,initfailed ;use extended
|
|
mov ah,9 ;DOS- API
|
|
int 21h ;to print a string
|
|
jmp DosExit
|
|
|
|
section .data
|
|
NEWSYM initfailed, db 'Sound card failed to initialize!',13,10,'$'
|
|
section .text
|
|
|
|
; Write AL into DSP port
|
|
NEWSYM SB_dsp_write
|
|
mov dx,[SBPort]
|
|
add dl,0Ch
|
|
mov bl,al
|
|
.tryagain
|
|
in al,dx
|
|
test al,80h
|
|
jnz .tryagain
|
|
mov al,bl
|
|
out dx,al
|
|
ret
|
|
|
|
; Read DSP port into AL
|
|
NEWSYM SB_dsp_read
|
|
mov dx,[SBPort]
|
|
add dl,0Eh
|
|
mov bl,al
|
|
.tryagain
|
|
in al,dx
|
|
test al,80h
|
|
jz .tryagain
|
|
mov dx,[SBPort]
|
|
add dl,0Ah
|
|
mov al,bl
|
|
in al,dx
|
|
ret
|
|
|
|
;****************************************************
|
|
; Sound Blaster Interrupt Stuff
|
|
;****************************************************
|
|
|
|
NEWSYM Interror
|
|
sti
|
|
mov edx,.nohand ;use extended
|
|
mov ah,9 ;DOS- API
|
|
int 21h ;to print a string
|
|
call DosExit
|
|
|
|
section .data
|
|
.nohand db 'Cannot process interrupt handler!',13,10,'$'
|
|
|
|
section .bss
|
|
|
|
NEWSYM oldhandSBs, resw 1
|
|
NEWSYM oldhandSBo, resd 1
|
|
NEWSYM SBswitch, resb 1 ; which block to process next
|
|
|
|
section .text
|
|
|
|
NEWSYM SBHandler
|
|
cli
|
|
push ds
|
|
push eax
|
|
|
|
|
|
NEWSYM handlersbseg
|
|
mov ax,[cs:dssel]
|
|
mov ds,ax
|
|
|
|
cmp byte[SBHDMA],0
|
|
jne near SBHandler16
|
|
|
|
; code added by peter santing
|
|
cmp byte[vibracard], 1
|
|
je near SBHandler16
|
|
|
|
push ebx
|
|
push ecx
|
|
push edx
|
|
push edi
|
|
push esi
|
|
push es
|
|
|
|
call GetCDMAPos
|
|
|
|
cmp byte[csounddisable],1
|
|
je near stopsbsound
|
|
test byte[DSPMem+6Ch],11000000b
|
|
jnz near stopsbsound
|
|
|
|
; Process the sound :I
|
|
|
|
mov es,[sbselec]
|
|
cmp byte[SBswitch],0
|
|
jne .2ndblock
|
|
mov edi,[sbpmofs]
|
|
jmp .startblockcopy
|
|
.2ndblock
|
|
; copy to 2nd block
|
|
; clear memory
|
|
mov edi,[sbpmofs]
|
|
add edi,[BufferSizeB]
|
|
.startblockcopy
|
|
|
|
mov esi,DSPBuffer
|
|
mov ecx,[BufferSizeB]
|
|
cmp byte[Surround],0
|
|
je .nosurround
|
|
cmp byte[StereoSound],0
|
|
je .surroundmono
|
|
; jmp .surroundmono
|
|
.nosurround
|
|
.loopb
|
|
mov eax,[esi]
|
|
cmp eax,-32768
|
|
jge .noneg3
|
|
mov eax,-32768
|
|
.noneg3
|
|
cmp eax,32767
|
|
jle .noneg4
|
|
mov eax,32767
|
|
.noneg4
|
|
xor ah,80h
|
|
mov [es:edi],ah
|
|
add esi,4
|
|
inc edi
|
|
dec ecx
|
|
jnz .loopb
|
|
jmp .sbend
|
|
%ifdef _I_LIKE_SUCKY_FILTERS_ ;bwahaha
|
|
.surroundstereo
|
|
shr ecx,1
|
|
.loopbs
|
|
mov eax,[esi]
|
|
cmp eax,-32768
|
|
jge .noneg3s
|
|
mov eax,-32768
|
|
.noneg3s
|
|
cmp eax,32767
|
|
jle .noneg4s
|
|
mov eax,32767
|
|
.noneg4s
|
|
xor ah,80h
|
|
mov [es:edi],ah
|
|
mov eax,[esi+4]
|
|
cmp eax,-32768
|
|
jge .noneg3s2
|
|
mov eax,-32768
|
|
.noneg3s2
|
|
cmp eax,32767
|
|
jle .noneg4s2
|
|
mov eax,32767
|
|
.noneg4s2
|
|
neg ah
|
|
xor ah,80h
|
|
mov [es:edi+1],ah
|
|
add esi,8
|
|
add edi,2
|
|
dec ecx
|
|
jnz .loopbs
|
|
jmp .sbend
|
|
%endif
|
|
.surroundmono
|
|
cmp byte[SBswitch],0
|
|
je .1stblock
|
|
add edi,[BufferSizeB]
|
|
.1stblock
|
|
.loopbm
|
|
mov eax,[esi]
|
|
cmp eax,-32768
|
|
jge .noneg3m
|
|
mov eax,-32768
|
|
.noneg3m
|
|
cmp eax,32767
|
|
jle .noneg4m
|
|
mov eax,32767
|
|
.noneg4m
|
|
xor ah,80h
|
|
mov [es:edi],ah
|
|
xor ah,80h
|
|
neg ah
|
|
xor ah,80h
|
|
mov [es:edi+1],ah
|
|
add esi,4
|
|
add edi,2
|
|
dec ecx
|
|
jnz .loopbm
|
|
.sbend
|
|
xor byte[SBswitch],1
|
|
|
|
; move the good data at spcRam+0f3h
|
|
xor eax,eax
|
|
mov al,[spcRam+0F2h]
|
|
mov bl,[DSPMem+eax]
|
|
mov [spcRam+0F3h],bl
|
|
; acknowledge SB for IRQing
|
|
mov dx,[SBPort]
|
|
add dl,0Eh
|
|
in al,dx
|
|
mov al,20h
|
|
out 20h,al
|
|
cmp byte[SBIrq],7
|
|
jbe .nohighirq
|
|
mov al,20h
|
|
out 0A0h,al
|
|
.nohighirq
|
|
sti
|
|
jmp Startprocsbdata
|
|
|
|
NEWSYM stopsbsound
|
|
; mov byte[Voice0Status],0
|
|
; mov byte[Voice1Status],0
|
|
; mov byte[Voice2Status],0
|
|
; mov byte[Voice3Status],0
|
|
; mov byte[Voice4Status],0
|
|
; mov byte[Voice5Status],0
|
|
; mov byte[Voice6Status],0
|
|
; mov byte[Voice7Status],0
|
|
|
|
mov ax,ds
|
|
mov es,ax
|
|
mov edi,DSPBuffer
|
|
mov ecx,[BufferSizeB]
|
|
xor eax,eax
|
|
rep stosd
|
|
|
|
cmp byte[SBswitch],0
|
|
jne near .2ndblock
|
|
|
|
; clear block
|
|
mov es,[sbselec]
|
|
mov edi,[sbpmofs]
|
|
mov ecx,[BufferSizeB]
|
|
shr ecx,2
|
|
.loopa
|
|
mov dword[es:edi],80808080h
|
|
add edi,4
|
|
dec ecx
|
|
jnz .loopa
|
|
jmp .sbend
|
|
.2ndblock
|
|
; copy to 2nd block
|
|
; clear memory
|
|
mov es,[sbselec]
|
|
mov edi,[sbpmofs]
|
|
add edi,[BufferSizeB]
|
|
mov ecx,[BufferSizeB]
|
|
shr ecx,2
|
|
.loopb
|
|
mov dword[es:edi],80808080h
|
|
add edi,4
|
|
dec ecx
|
|
jnz .loopb
|
|
.sbend
|
|
xor byte[SBswitch],1
|
|
|
|
; acknowledge SB for IRQing
|
|
mov dx,[SBPort]
|
|
add dl,0Eh
|
|
in al,dx
|
|
mov al,20h
|
|
out 20h,al
|
|
cmp byte[SBIrq],7
|
|
jbe .nohighirq
|
|
mov al,20h
|
|
out 0A0h,al
|
|
.nohighirq
|
|
|
|
pop es
|
|
pop esi
|
|
pop edi
|
|
pop edx
|
|
pop ecx
|
|
pop ebx
|
|
pop eax
|
|
pop ds
|
|
sti
|
|
iretd
|
|
|
|
section .bss
|
|
NEWSYM sbhandexec, resd 1
|
|
section .text
|
|
|
|
; Process 20 blocks * 8 voices (no pitch yet)
|
|
NEWSYM SBHandler16
|
|
push ebx
|
|
push ecx
|
|
push edx
|
|
push edi
|
|
push esi
|
|
push es
|
|
inc dword[sbhandexec]
|
|
|
|
cmp byte[vibracard], 1
|
|
je .donotcallcmdapos
|
|
call GetCDMAPos
|
|
.donotcallcmdapos
|
|
|
|
cmp byte[csounddisable],1
|
|
je near stopsbsound16
|
|
test byte[DSPMem+6Ch],11000000b
|
|
jnz near stopsbsound16
|
|
|
|
mov es,[sbselec]
|
|
|
|
cmp byte[SBswitch],0
|
|
jne near .2ndblock
|
|
mov edi,[sbpmofs]
|
|
jmp .doneblock
|
|
.2ndblock
|
|
; copy to 2nd block
|
|
; clear memory
|
|
mov edi,[sbpmofs]
|
|
add edi,[BufferSizeW]
|
|
.doneblock
|
|
mov esi,DSPBuffer
|
|
mov ecx,[BufferSizeB]
|
|
cmp byte[Surround],0
|
|
je .nosurround
|
|
cmp byte[StereoSound],0
|
|
; jne near .surroundstereo
|
|
je .surroundmono
|
|
; jmp .surroundmono
|
|
.nosurround
|
|
.loopb
|
|
mov eax,[esi]
|
|
cmp eax,-32768
|
|
jge .noneg5
|
|
mov eax,-32768
|
|
.noneg5
|
|
cmp eax,32767
|
|
jle .noneg6
|
|
mov eax,32767
|
|
.noneg6
|
|
mov [es:edi],ax
|
|
add esi,4
|
|
add edi,2
|
|
dec ecx
|
|
jnz .loopb
|
|
jmp .sbend
|
|
%ifdef _I_LIKE_SUCKY_FILTERS_ ;bwahaha
|
|
.surroundstereo
|
|
shr ecx,1
|
|
.loopbs
|
|
mov eax,[esi]
|
|
cmp eax,-32768
|
|
jge .noneg5s
|
|
mov eax,-32768
|
|
.noneg5s
|
|
cmp eax,32767
|
|
jle .noneg6s
|
|
mov eax,32767
|
|
.noneg6s
|
|
mov [es:edi],ax
|
|
mov eax,[esi+4]
|
|
cmp eax,-32768
|
|
jge .noneg5s2
|
|
mov eax,-32768
|
|
.noneg5s2
|
|
cmp eax,32767
|
|
jle .noneg6s2
|
|
mov eax,32767
|
|
.noneg6s2
|
|
neg ax
|
|
mov [es:edi+2],ax
|
|
add esi,8
|
|
add edi,4
|
|
dec ecx
|
|
jnz .loopbs
|
|
jmp .sbend
|
|
%endif
|
|
.surroundmono
|
|
cmp byte[SBswitch],0
|
|
je .1stblock
|
|
add edi,[BufferSizeW]
|
|
.1stblock
|
|
.loopbm
|
|
mov eax,[esi]
|
|
cmp eax,-32768
|
|
jge .noneg5m
|
|
mov eax,-32768
|
|
.noneg5m
|
|
cmp eax,32767
|
|
jle .noneg6m
|
|
mov eax,32767
|
|
.noneg6m
|
|
mov [es:edi],ax
|
|
neg ax
|
|
mov [es:edi+2],ax
|
|
add esi,4
|
|
add edi,4
|
|
dec ecx
|
|
jnz .loopbm
|
|
.sbend
|
|
xor byte[SBswitch],1
|
|
|
|
; acknowledge SB for IRQing
|
|
mov dx,[SBPort]
|
|
add dl,0Fh
|
|
in al,dx
|
|
mov al,20h
|
|
out 20h,al
|
|
cmp byte[SBIrq],7
|
|
jbe .nohighirq
|
|
mov al,20h
|
|
out 0A0h,al
|
|
.nohighirq
|
|
sti
|
|
|
|
|
|
Startprocsbdata:
|
|
push ebp
|
|
call ProcessSoundBuffer
|
|
pop ebp
|
|
pop es
|
|
pop esi
|
|
pop edi
|
|
pop edx
|
|
pop ecx
|
|
pop ebx
|
|
pop eax
|
|
pop ds
|
|
iretd
|
|
|
|
NEWSYM stopsbsound16
|
|
; mov byte[Voice0Status],0
|
|
; mov byte[Voice1Status],0
|
|
; mov byte[Voice2Status],0
|
|
; mov byte[Voice3Status],0
|
|
; mov byte[Voice4Status],0
|
|
; mov byte[Voice5Status],0
|
|
; mov byte[Voice6Status],0
|
|
; mov byte[Voice7Status],0
|
|
|
|
mov ax,ds
|
|
mov es,ax
|
|
mov edi,DSPBuffer
|
|
mov ecx,[BufferSizeB]
|
|
xor eax,eax
|
|
rep stosd
|
|
|
|
cmp byte[SBswitch],0
|
|
jne near .2ndblock
|
|
|
|
; clear block
|
|
mov es,[sbselec]
|
|
mov edi,[sbpmofs]
|
|
mov ecx,[BufferSizeB]
|
|
shr ecx,1
|
|
.loopa
|
|
mov dword[es:edi],00000000h
|
|
add edi,4
|
|
dec ecx
|
|
jnz .loopa
|
|
jmp .sbend
|
|
.2ndblock
|
|
; copy to 2nd block
|
|
; clear memory
|
|
mov es,[sbselec]
|
|
mov edi,[sbpmofs]
|
|
add edi,[BufferSizeW]
|
|
mov ecx,[BufferSizeB]
|
|
shr ecx,1
|
|
.loopb
|
|
mov dword[es:edi],00000000h
|
|
add edi,4
|
|
dec ecx
|
|
jnz .loopb
|
|
.sbend
|
|
xor byte[SBswitch],1
|
|
|
|
; acknowledge SB for IRQing
|
|
mov dx,[SBPort]
|
|
add dl,0Fh
|
|
in al,dx
|
|
mov al,20h
|
|
out 20h,al
|
|
cmp byte[SBIrq],7
|
|
jbe .nohighirq
|
|
mov al,20h
|
|
out 0A0h,al
|
|
.nohighirq
|
|
|
|
pop es
|
|
pop esi
|
|
pop edi
|
|
pop edx
|
|
pop ecx
|
|
pop ebx
|
|
pop eax
|
|
pop ds
|
|
sti
|
|
iretd
|
|
|
|
;****************************************************
|
|
; Sound Blaster Initialization Stuff
|
|
;****************************************************
|
|
|
|
section .bss
|
|
NEWSYM memoryloc, resd 1 ; Memory offset in conventional memory
|
|
NEWSYM memoryloc2, resd 1 ; Memory offset in conventional memory
|
|
NEWSYM sbselec, resw 1 ; Selector of Memory location
|
|
NEWSYM sbpmofs, resd 1 ; offset of Memory location
|
|
SBDeinitType resb 1
|
|
section .text
|
|
|
|
NEWSYM InitSB
|
|
mov eax,[SoundQuality]
|
|
cmp byte[StereoSound],1
|
|
jne .nostereobuf
|
|
mov ax,[BufferSizes+eax*2]
|
|
jmp .skipstereobuf
|
|
.nostereobuf
|
|
mov ax,[BufferSize+eax*2]
|
|
.skipstereobuf
|
|
|
|
mov [BufferSizeB],ax
|
|
add ax,ax
|
|
mov [BufferSizeW],ax
|
|
|
|
mov byte[SBswitch],0
|
|
; Allocate pointer
|
|
; Set up SB
|
|
call SB_dsp_reset
|
|
|
|
; code added by peter santing
|
|
cmp byte[vibracard], 1
|
|
je near .vibrafix2
|
|
|
|
cmp byte[SBHDMA],0
|
|
je .no16bit
|
|
cmp byte[SBHDMA],4
|
|
jb near .init16bitlowhdma
|
|
jmp .init16bit
|
|
.no16bit
|
|
|
|
; Determine Version #
|
|
mov al,0E1h
|
|
call SB_dsp_write
|
|
call SB_dsp_read
|
|
mov [.Versionnum],al
|
|
call SB_dsp_read
|
|
mov [.Versionnum+1],al
|
|
|
|
; Turn on speakers
|
|
mov al,0D1h
|
|
call SB_dsp_write
|
|
|
|
; Set Time-Constant Data ( = 256 - (1000000/sampling rate) )
|
|
; 8000=131, 22050=210, 44100=233, 11025=165
|
|
mov al,40h
|
|
call SB_dsp_write
|
|
|
|
; cmp byte[Surround],0
|
|
; jne .surround8b
|
|
cmp byte[StereoSound],1
|
|
jne .nostereo8b
|
|
.surround8b
|
|
mov eax,[SoundQuality]
|
|
cmp eax,2
|
|
jbe .okay
|
|
mov eax,2
|
|
.okay
|
|
mov al,[SoundSpeedt+eax]
|
|
call SB_dsp_write
|
|
; Set Stereo
|
|
mov dx, [SBPort]
|
|
add dx, 04h
|
|
mov al,0Eh
|
|
out dx,al
|
|
inc dx
|
|
in al,dx
|
|
or al,022h
|
|
out dx,al
|
|
jmp .donestereo
|
|
.nostereo8b
|
|
mov eax,[SoundQuality]
|
|
mov al,[SoundSpeeds+eax]
|
|
call SB_dsp_write
|
|
.donestereo
|
|
|
|
cmp byte[StereoSound],1
|
|
je .highmode
|
|
mov eax,[SoundQuality]
|
|
cmp byte[SoundSpeeds+eax],211
|
|
ja .highmode
|
|
mov byte[.Versionnum],1
|
|
.highmode
|
|
; Setup DMA
|
|
; Select DMA channel
|
|
mov al,[SBDMA]
|
|
add al,4
|
|
mov dx,000Ah
|
|
out dx,al
|
|
; Clear DMA
|
|
mov al,00h
|
|
mov dx,000Ch
|
|
out dx,al
|
|
; Set autoinit/write (set as DAC)
|
|
mov al,58h
|
|
add al,[SBDMA]
|
|
mov dx,000Bh
|
|
out dx,al
|
|
; Send Offset Address
|
|
mov al,[memoryloc]
|
|
mov dl,[SBDMA]
|
|
shl dl,1
|
|
out dx,al
|
|
mov al,[memoryloc+1]
|
|
out dx,al
|
|
; Send length of entire block
|
|
mov ax,[BufferSizeW]
|
|
dec ax
|
|
inc dx
|
|
out dx,al
|
|
mov al,ah
|
|
out dx,al
|
|
; Send page # (address/65536)
|
|
mov al,[memoryloc+2]
|
|
mov dl,[SBDMAPage]
|
|
out dx,al
|
|
; turn on DMA
|
|
mov al,[SBDMA]
|
|
mov dx,000Ah
|
|
out dx,al
|
|
|
|
; Prepare SB for the first block
|
|
; 8-bit auto-init, mono, unsigned
|
|
mov al,048h ; Sb 2.0 version...
|
|
call SB_dsp_write
|
|
|
|
; Send Length-1 to DSP port
|
|
mov ax,[BufferSizeB]
|
|
dec ax
|
|
call SB_dsp_write
|
|
mov al,ah
|
|
call SB_dsp_write
|
|
mov byte[SBDeinitType],1
|
|
mov al,090h ; Sb 2.0 version...
|
|
cmp byte[.Versionnum],2
|
|
jne .noversion2
|
|
cmp byte[.Versionnum+1],0
|
|
je .slowspeed
|
|
.noversion2
|
|
cmp byte[.Versionnum],1
|
|
ja .notversion1
|
|
.slowspeed
|
|
mov byte[SBDeinitType],0
|
|
mov al,1Ch
|
|
.notversion1
|
|
call SB_dsp_write
|
|
jmp .fixsurround
|
|
|
|
SECTION .bss
|
|
.Versionnum resw 1
|
|
SECTION .text
|
|
|
|
; *****************************************
|
|
; **** alternate ViBRA16X SB init code **** by Peter Santing
|
|
; ***************************************** copied portions of original code
|
|
; and modified it.
|
|
|
|
.vibrafix2
|
|
; notify user that we're in ViBRA16x mode..
|
|
push eax
|
|
mov dword[Msgptr], vibmsg
|
|
mov eax, [MsgCount]
|
|
mov [MessageOn], eax
|
|
pop eax
|
|
|
|
; Set Time-Constant Data ( = 256 - (1000000/sampling rate) )
|
|
; 8000=131, 22050=210, 44100=233, 11025=165
|
|
|
|
; Setup DMA
|
|
; Select DMA channel
|
|
mov al,[SBDMA]
|
|
add al,4
|
|
mov dx,000Ah
|
|
out dx,al
|
|
; Clear DMA
|
|
mov al,00h
|
|
mov dx,000Ch
|
|
out dx,al
|
|
; Set autoinit/write (set as DAC)
|
|
mov al,58h
|
|
add al,[SBDMA]
|
|
mov dx,000Bh
|
|
out dx,al
|
|
; Send Offset Address
|
|
mov al,[memoryloc]
|
|
mov dl,[SBDMA]
|
|
shl dl,1
|
|
out dx,al
|
|
mov al,[memoryloc+1]
|
|
out dx,al
|
|
; Send length of entire block
|
|
mov ax,[BufferSizeW]
|
|
shl ax, 1
|
|
dec ax
|
|
inc dx
|
|
out dx,al
|
|
mov al,ah
|
|
out dx,al
|
|
; Send page # (address/65536)
|
|
mov al,[memoryloc+2]
|
|
mov dh, 0
|
|
mov dl,[SBDMAPage]
|
|
out dx,al
|
|
; turn on DMA
|
|
mov al,[SBDMA]
|
|
mov dx,000Ah
|
|
out dx,al
|
|
|
|
mov al,41h
|
|
call SB_dsp_write
|
|
push ecx
|
|
mov ecx,[SoundQuality]
|
|
mov al,[SBToSPCSpeeds2+ecx*4+1]
|
|
pop ecx
|
|
call SB_dsp_write
|
|
push ecx
|
|
mov ecx,[SoundQuality]
|
|
mov al,[SBToSPCSpeeds2+ecx*4]
|
|
pop ecx
|
|
call SB_dsp_write
|
|
|
|
; Prepare SB for the first block
|
|
; 16-bit auto-init, mono, unsigned
|
|
mov al,0B6h ; Sb 16 version (DSP 4)
|
|
call SB_dsp_write
|
|
cmp byte[StereoSound],1
|
|
jne ._Mono
|
|
._surround
|
|
mov al,30h ; stereo/signed
|
|
call SB_dsp_write
|
|
jmp ._AfterStereo
|
|
._Mono
|
|
mov al,10h ; mono/signed
|
|
call SB_dsp_write
|
|
._AfterStereo
|
|
|
|
; Send Length-1 to DSP port
|
|
mov ax,[BufferSizeB]
|
|
dec ax
|
|
call SB_dsp_write
|
|
mov al,ah
|
|
call SB_dsp_write
|
|
|
|
; Turn on speakers
|
|
mov al,0D1h
|
|
call SB_dsp_write
|
|
|
|
jmp .fixsurround
|
|
|
|
; ******* end of alternate SB init code for ViBRA ********
|
|
|
|
.init16bitlowhdma
|
|
; Set Time-Constant Data ( = 256 - (1000000/sampling rate) )
|
|
; 8000=131, 22050=210, 44100=233, 11025=165
|
|
mov al,40h
|
|
call SB_dsp_write
|
|
|
|
push ecx
|
|
mov ecx,[SoundQuality]
|
|
mov al,[SoundSpeeds+ecx]
|
|
pop ecx
|
|
call SB_dsp_write
|
|
|
|
mov edx,[memoryloc]
|
|
shr edx,1
|
|
mov [memoryloc2],edx
|
|
|
|
; Setup DMA
|
|
|
|
; turn off DMA
|
|
; mov al,[SBHDMA]
|
|
; and al,03h
|
|
; or al,04h
|
|
; mov dx,00D4h
|
|
; out dx,al
|
|
|
|
; Setup DMA
|
|
; Select DMA channel
|
|
mov al,[SBHDMA]
|
|
and al,03h
|
|
or al,04h
|
|
mov dx,000Ah
|
|
out dx,al
|
|
|
|
; clear flip-flop
|
|
mov dx,00D8h
|
|
xor al,al
|
|
out dx,al
|
|
|
|
; Set autoinit/write (set as DAC)
|
|
mov al,[SBHDMA]
|
|
and al,3
|
|
add al,58h
|
|
mov dx,00D6h
|
|
out dx,al
|
|
|
|
; Send Offset Address
|
|
; mov al,[memoryloc2]
|
|
; mov dl,[SBHDMA]
|
|
; and dl,3
|
|
; shl dl,2
|
|
; add dl,0C0h
|
|
; out dx,al
|
|
; mov al,[memoryloc2+1]
|
|
; out dx,al
|
|
|
|
; Send Offset Address
|
|
mov al,[memoryloc]
|
|
mov dl,[SBDMA]
|
|
shl dl,1
|
|
out dx,al
|
|
mov al,[memoryloc+1]
|
|
out dx,al
|
|
|
|
; Send length of entire block
|
|
mov ax,[BufferSizeW]
|
|
dec ax
|
|
add dx,2
|
|
out dx,al
|
|
mov al,ah
|
|
out dx,al
|
|
|
|
; Send page # (address/65536)
|
|
mov al,[memoryloc+2]
|
|
mov dl,[SBHDMAPage]
|
|
out dx,al
|
|
|
|
; Prepare SB for the first block
|
|
; 16-bit auto-init, mono, unsigned
|
|
mov al,0B6h ; Sb 16 version (DSP 4)
|
|
call SB_dsp_write
|
|
; cmp byte[Surround],0
|
|
; jne .surroundl
|
|
cmp byte[StereoSound],1
|
|
jne .Monol
|
|
.surroundl
|
|
mov al,30h ; stereo/signed
|
|
call SB_dsp_write
|
|
jmp .AfterStereol
|
|
.Monol
|
|
mov al,10h ; mono/signed
|
|
call SB_dsp_write
|
|
.AfterStereol
|
|
|
|
; Send Length-1 to DSP port
|
|
mov ax,[BufferSizeB]
|
|
dec ax
|
|
call SB_dsp_write
|
|
mov al,ah
|
|
call SB_dsp_write
|
|
|
|
; turn on DMA
|
|
; mov al,[SBHDMA]
|
|
; and al,03h
|
|
; mov dx,00D4h
|
|
; out dx,al
|
|
|
|
; Setup DMA
|
|
; Select DMA channel
|
|
mov al,[SBHDMA]
|
|
and al,03h
|
|
mov dx,000Ah
|
|
out dx,al
|
|
|
|
; Turn on speakers
|
|
mov al,0D1h
|
|
call SB_dsp_write
|
|
jmp .fixsurround
|
|
|
|
.init16bit
|
|
; Set Time-Constant Data ( = 256 - (1000000/sampling rate) )
|
|
; 8000=131, 22050=210, 44100=233, 11025=165
|
|
mov al,41h
|
|
call SB_dsp_write
|
|
push ecx
|
|
mov ecx,[SoundQuality]
|
|
mov al,[SBToSPCSpeeds2+ecx*4+1]
|
|
pop ecx
|
|
call SB_dsp_write
|
|
push ecx
|
|
mov ecx,[SoundQuality]
|
|
mov al,[SBToSPCSpeeds2+ecx*4]
|
|
pop ecx
|
|
call SB_dsp_write
|
|
|
|
mov edx,[memoryloc]
|
|
shr edx,1
|
|
mov [memoryloc2],edx
|
|
|
|
; Setup DMA
|
|
|
|
; turn off DMA
|
|
mov al,[SBHDMA]
|
|
and al,03h
|
|
or al,04h
|
|
mov dx,00D4h
|
|
out dx,al
|
|
|
|
; clear flip-flop
|
|
mov dx,00D8h
|
|
xor al,al
|
|
out dx,al
|
|
|
|
; Set autoinit/write (set as DAC)
|
|
mov al,[SBHDMA]
|
|
and al,3
|
|
add al,58h
|
|
mov dx,00D6h
|
|
out dx,al
|
|
|
|
; Send Offset Address
|
|
mov al,[memoryloc2]
|
|
mov dl,[SBHDMA]
|
|
and dl,3
|
|
shl dl,2
|
|
add dl,0C0h
|
|
out dx,al
|
|
mov al,[memoryloc2+1]
|
|
out dx,al
|
|
|
|
; Send length of entire block
|
|
mov ax,[BufferSizeW]
|
|
dec ax
|
|
add dx,2
|
|
out dx,al
|
|
mov al,ah
|
|
out dx,al
|
|
|
|
; Send page # (address/65536)
|
|
mov al,[memoryloc+2]
|
|
mov dl,[SBHDMAPage]
|
|
and al,0FEh
|
|
out dx,al
|
|
|
|
; Prepare SB for the first block
|
|
; 16-bit auto-init, mono, unsigned
|
|
mov al,0B6h ; Sb 16 version (DSP 4)
|
|
call SB_dsp_write
|
|
; cmp byte[Surround],0
|
|
; jne .surround
|
|
cmp byte[StereoSound],1
|
|
jne .Mono
|
|
.surround
|
|
mov al,30h ; stereo/signed
|
|
call SB_dsp_write
|
|
jmp .AfterStereo
|
|
.Mono
|
|
mov al,10h ; mono/signed
|
|
call SB_dsp_write
|
|
.AfterStereo
|
|
|
|
; Send Length-1 to DSP port
|
|
mov ax,[BufferSizeB]
|
|
dec ax
|
|
call SB_dsp_write
|
|
mov al,ah
|
|
call SB_dsp_write
|
|
|
|
; Turn on speakers
|
|
mov al,0D1h
|
|
call SB_dsp_write
|
|
|
|
; turn on DMA
|
|
mov al,[SBHDMA]
|
|
and al,03h
|
|
mov dx,00D4h
|
|
out dx,al
|
|
|
|
.fixsurround
|
|
|
|
; Adjust byte lengths for mono surround sound
|
|
cmp byte[Surround],0
|
|
je .nosurroundadj
|
|
cmp byte[StereoSound],0
|
|
jne .nosurroundadj
|
|
; shr word[BufferSizeB],1
|
|
; shr word[BufferSizeW],1
|
|
.nosurroundadj
|
|
ret
|
|
|
|
|
|
GetCDMAPos:
|
|
; clear flipflop
|
|
xor ebx,ebx
|
|
mov bl,[SBDMA]
|
|
cmp byte[SBHDMA],4
|
|
jb .nohdma
|
|
mov bl,[SBHDMA]
|
|
mov dx,0Ch
|
|
.nohdma
|
|
mov dx,0D8h
|
|
xor al,al
|
|
out dx,al
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
mov dx,[.wordcountport+ebx*2]
|
|
|
|
in al,dx
|
|
nop
|
|
nop
|
|
mov bl,al
|
|
in al,dx
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
mov bh,al
|
|
cmp byte[SBHDMA],4
|
|
jb .ldma2
|
|
add bx,bx
|
|
.ldma2
|
|
; value returned = bx, # of bytes left for transfer
|
|
mov cx,[BufferSizeB]
|
|
mov dx,cx
|
|
add cx,cx
|
|
cmp byte[SBHDMA],4
|
|
jb .ldmab
|
|
add cx,cx
|
|
add dx,dx
|
|
.ldmab
|
|
sub cx,bx
|
|
mov byte[SBswitch],1
|
|
cmp cx,dx
|
|
jb .parta
|
|
mov byte[SBswitch],0
|
|
.parta
|
|
ret
|
|
SECTION .data
|
|
.wordcountport dw 1,3,5,7,0C2h,0C6h,0CAh,0CEh
|
|
SECTION .text
|
|
|
|
; old routines, doesn't work w/ sb live!
|
|
jmp .fin
|
|
|
|
.loop
|
|
in al,dx
|
|
nop
|
|
nop
|
|
mov cl,al
|
|
in al,dx
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
mov ch,al
|
|
in al,dx
|
|
nop
|
|
nop
|
|
mov bl,al
|
|
in al,dx
|
|
mov bh,al
|
|
sub cx,bx
|
|
test cx,8000h
|
|
jz .notneg
|
|
neg cx
|
|
.notneg
|
|
cmp byte[SBHDMA],4
|
|
jb .ldma
|
|
add cx,cx
|
|
add bx,bx
|
|
.ldma
|
|
cmp cx,4
|
|
ja .loop
|
|
|
|
.fin
|
|
|
|
NEWSYM SB_quality_limiter
|
|
cmp byte[StereoSound],1
|
|
jne .nostereo8b
|
|
cmp byte[SBHDMA],0
|
|
jne .nostereo8b
|
|
|
|
; *****************************************
|
|
; *** ViBRA16X support by Peter Santing ***
|
|
; *****************************************
|
|
; before REALLY switching back to 8-bit sucky mono mode
|
|
; check that we're dealing with a ViBRA16X Creative Labs Card
|
|
cmp byte[vibracard], 1
|
|
je .nostereo8b
|
|
|
|
cmp dword[SoundQuality],2
|
|
jbe .nostereo8b
|
|
mov dword[SoundQuality],2
|
|
.nostereo8b
|
|
ret
|
|
|
|
NEWSYM SB_blank
|
|
push es
|
|
mov es,[sbselec]
|
|
mov edi,[sbpmofs]
|
|
mov ecx,320
|
|
.loopa
|
|
mov dword[es:edi],0
|
|
add edi,4
|
|
dec ecx
|
|
jnz .loopa
|
|
pop es
|
|
ret
|
|
|
|
;*******************************************************
|
|
; Get Blaster Locates SET BLASTER environment
|
|
;*******************************************************
|
|
NEWSYM getblaster
|
|
mov edx,.string2s
|
|
push edx
|
|
call getenv
|
|
pop edx
|
|
cmp eax,0
|
|
je near .nfound
|
|
|
|
mov esi,eax
|
|
mov byte[.cursetting],0
|
|
.a
|
|
mov dl,[esi]
|
|
cmp dl,'a'
|
|
jb .nocap
|
|
cmp dl,'z'
|
|
ja .nocap
|
|
sub dl,'a'-'A'
|
|
.nocap
|
|
inc esi
|
|
mov byte[.blfound],1
|
|
cmp dl,'A'
|
|
jne .afound
|
|
mov byte[.cursetting],1
|
|
mov word[SBPort],0
|
|
jmp .src
|
|
.afound
|
|
cmp dl,'I'
|
|
jne .ifound
|
|
mov byte[.cursetting],2
|
|
mov byte[SBIrq],0
|
|
jmp .src
|
|
.ifound
|
|
cmp dl,'D'
|
|
jne .dfound
|
|
mov byte[.cursetting],3
|
|
mov byte[SBDMA],0
|
|
jmp .src
|
|
.dfound
|
|
cmp dl,'H'
|
|
jne .hfound
|
|
mov byte[.cursetting],4
|
|
mov byte[SBHDMA],0
|
|
jmp .src
|
|
.hfound
|
|
cmp dl,' '
|
|
je .src2
|
|
cmp dl,0
|
|
je .src2
|
|
jmp .src3
|
|
.src2
|
|
mov byte[.cursetting],0
|
|
jmp .src
|
|
.src3
|
|
cmp byte[.cursetting],1
|
|
jne .nproca
|
|
shl word[SBPort],4
|
|
sub dl,48
|
|
add byte[SBPort],dl
|
|
add dl,48
|
|
.nproca
|
|
cmp byte[.cursetting],2
|
|
jne .nproci
|
|
cmp byte[SBIrq],1
|
|
jne .no1
|
|
mov byte[SBIrq],10
|
|
.no1
|
|
sub dl,48
|
|
add [SBIrq],dl
|
|
add dl,48
|
|
.nproci
|
|
cmp byte[.cursetting],3
|
|
jne .nprocd
|
|
sub dl,48
|
|
mov [SBDMA],dl
|
|
add dl,48
|
|
.nprocd
|
|
cmp byte[.cursetting],4
|
|
jne .nproch
|
|
sub dl,48
|
|
mov [SBHDMA],dl
|
|
add dl,48
|
|
.nproch
|
|
.src
|
|
cmp dl,0
|
|
jne near .a
|
|
cmp byte[.blfound],0
|
|
je near .nfound
|
|
cmp byte[SBIrq],2
|
|
jne .noirq9
|
|
mov byte[SBIrq],9
|
|
.noirq9
|
|
mov al,[SBIrq]
|
|
add al,08h
|
|
cmp byte[SBIrq],7
|
|
jbe .nohighirq
|
|
add al,60h
|
|
add byte[PICRotateP],80h
|
|
add byte[PICMaskP],80h
|
|
.nohighirq
|
|
mov [SBInt],al
|
|
cmp byte[SBDMA],0
|
|
jne .dma0
|
|
mov byte[SBDMAPage],87h
|
|
.dma0
|
|
cmp byte[SBDMA],1
|
|
jne .dma1
|
|
mov byte[SBDMAPage],83h
|
|
.dma1
|
|
cmp byte[SBDMA],2
|
|
jne .dma2
|
|
mov byte[SBDMAPage],81h
|
|
.dma2
|
|
cmp byte[SBDMA],3
|
|
jne .dma3
|
|
mov byte[SBDMAPage],82h
|
|
.dma3
|
|
; ******************************************************
|
|
; **** this piece of code is added by Peter Santing ****
|
|
; **** it will enable ZSNES to use the full STEREO ****
|
|
; **** capability of the ViBRA16X line of creative ****
|
|
; **** instead of playing 8-bit MONOURAL sound ****
|
|
; ******************************************************
|
|
; cmp byte[SBHDMA], 0
|
|
; jne .vibradma0
|
|
; mov byte[SBDMAPage], 87h
|
|
; mov byte[vibracard], 1 ; set ViBRA16X mode
|
|
.vibradma0
|
|
cmp byte[SBHDMA], 1
|
|
jne .vibradma1
|
|
mov byte[SBDMAPage], 83h
|
|
mov byte[vibracard], 1 ; set ViBRA16X mode
|
|
.vibradma1
|
|
cmp byte[SBHDMA], 2
|
|
jne .vibradma2
|
|
mov byte[SBDMAPage], 81h
|
|
mov byte[vibracard], 1 ; set ViBRA16X mode
|
|
.vibradma2
|
|
cmp byte[SBHDMA], 3
|
|
jne .vibradma3
|
|
mov byte[SBDMAPage], 82h
|
|
mov byte[vibracard], 1 ; set ViBRA16X mode
|
|
.vibradma3
|
|
cmp byte[vibracard], 1
|
|
jne .vibrafix
|
|
push ax
|
|
mov al, [SBHDMA]
|
|
mov [SBDMA], al
|
|
pop ax
|
|
.vibrafix
|
|
cmp byte[SBHDMA],4
|
|
jae .hdma
|
|
; vibra implementation (make sure that zSNES doesn't go back
|
|
; to eight-bit-mode mono)
|
|
mov byte[SBHDMA],0
|
|
cmp byte[vibracard], 1
|
|
jne .hdma
|
|
push edx
|
|
mov edx, vibradetect
|
|
call PrintStr
|
|
;call WaitForKey
|
|
pop edx
|
|
|
|
; ********** END OF ViBRA16X implementation code **********
|
|
.hdma
|
|
cmp byte[SBHDMA],4
|
|
jne .hdma4
|
|
mov byte[SBHDMAPage],8Fh
|
|
.hdma4
|
|
cmp byte[SBHDMA],5
|
|
jne .hdma5
|
|
mov byte[SBHDMAPage],8Bh
|
|
.hdma5
|
|
cmp byte[SBHDMA],6
|
|
jne .hdma6
|
|
mov byte[SBHDMAPage],89h
|
|
.hdma6
|
|
cmp byte[SBHDMA],7
|
|
jne .hdma7
|
|
mov byte[SBHDMAPage],8Ah
|
|
.hdma7
|
|
cmp byte[DisplayS],1
|
|
je .displaysoundstuff
|
|
ret
|
|
.nfound
|
|
cmp byte[soundon],0
|
|
je .nosound
|
|
mov byte[soundon],0
|
|
mov edx, .blasterstr
|
|
call PrintStr
|
|
call WaitForKey
|
|
.nosound
|
|
ret
|
|
.displaysoundstuff
|
|
mov edx,.blasterinfo
|
|
call PrintStr
|
|
xor eax,eax
|
|
mov ax,[SBPort]
|
|
call printhex
|
|
mov edx,.blinfob
|
|
call PrintStr
|
|
xor eax,eax
|
|
mov al,[SBIrq]
|
|
call printnum
|
|
mov edx,.blinfoc
|
|
call PrintStr
|
|
xor eax,eax
|
|
mov al,[SBDMA]
|
|
call printnum
|
|
mov edx,.blinfod
|
|
call PrintStr
|
|
xor eax,eax
|
|
mov al,[SBHDMA]
|
|
call printnum
|
|
mov edx,.blasterstr2b
|
|
call PrintStr
|
|
call WaitForKey
|
|
ret
|
|
|
|
SECTION .bss
|
|
.blfound resb 1
|
|
.cursetting resb 1
|
|
|
|
SECTION .data
|
|
.string2s db 'BLASTER',0
|
|
.blasterstr db 'ERROR : SET BLASTER environment NOT found!',10,13
|
|
.blasterstr2 db 'Unable to enable sound.'
|
|
.blasterstr2b db 10,13,10,13
|
|
.blasterstr3 db 'Press any key to continue.',0
|
|
.blasterinfo db 'Sound Blaster Detection Values : ',10,13,10,13
|
|
.blinfoa db 'PORT : ',0
|
|
.blinfob db 13,10,'IRQ : ',0
|
|
.blinfoc db 13,10,'DMA : ',0
|
|
.blinfod db 13,10,'HDMA : ',0
|
|
|
|
NEWSYM PICRotateP, db 20h
|
|
NEWSYM PICMaskP, db 21h
|
|
|
|
; Line added by Peter Santing
|
|
NEWSYM vibradetect
|
|
db 'Creative ViBRA16X PnP card detected (support coded by Peter Santing)', 13, 10
|
|
db 'High-DMA is below dma #4', 13, 10
|
|
db 13,10, 'you have now full 16-bit stereo sound with the surround option!', 13, 10, 0
|
|
|
|
|