📄 sound.asm
字号:
;Copyright (C) 1997-2007 ZSNES Team ( zsKnight, _Demo_, pagefault, Nach );;http://www.zsnes.com;http://sourceforge.net/projects/zsnes;https://zsnes.bountysource.com;;This program is free software; you can redistribute it and/or;modify it under the terms of the GNU General Public License;version 2 as published by the Free Software Foundation.;;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,WaitForKeyEXTSYM SBHDMA,soundon,csounddisable,DisplayS,SPCRAM,DSPMemEXTSYM StereoSound,SoundQuality,SoundSpeeds,SBToSPCSpeeds2EXTSYM SoundSpeedt,DSPBuffer,BufferSize,BufferSizes,BufferSizeBEXTSYM BufferSizeW,dssel,PrintCharSECTION .textprintnum: ; 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 retNEWSYM 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 DosExitSECTION .data.nohand db 'Unable to allocate conventional memory!',13,10,'$'SECTION .textNEWSYM 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 retsection .data;SoundBlaster DSP PortsNEWSYM SBPort, dw 220NEWSYM SBInt, db 5+8NEWSYM SBIrq, db 5NEWSYM SBDMA, db 1NEWSYM SBDMAPage, db 83;NEWSYM SBHDMA, db 0NEWSYM SBHDMAPage, db 0NEWSYM vibracard, db 0NEWSYM SBBufferLoc, dd 0NEWSYM SBBufferMov, dd 0NEWSYM SBBufferInc, dd 0NEWSYM SoundInterrupt, dd 0; ViBRA16X fixes!EXTSYM MsgCount ; points to counterEXTSYM MessageOn ; points to "message" delay counterEXTSYM Msgptr ; points to the message to be displayedNEWSYM vibmsg, db 'VIBRA16X MODE ENABLED', 0section .textNEWSYM 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 DosExitsection .dataNEWSYM initfailed, db 'Sound card failed to initialize!',13,10,'$'section .text; Write AL into DSP portNEWSYM 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 ALNEWSYM 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 DosExitsection .data.nohand db 'Cannot process interrupt handler!',13,10,'$'section .bssNEWSYM oldhandSBs, resw 1NEWSYM oldhandSBo, resd 1NEWSYM SBswitch, resb 1 ; which block to process nextsection .textNEWSYM SBHandler cli push ds push eaxNEWSYM 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].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.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 StartprocsbdataNEWSYM 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 iretdsection .bssNEWSYM sbhandexec, resd 1section .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].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.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 stiStartprocsbdata: push ebp call ProcessSoundBuffer pop ebp pop es pop esi pop edi pop edx pop ecx pop ebx pop eax pop ds iretdNEWSYM 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 .bssNEWSYM memoryloc, resd 1 ; Memory offset in conventional memoryNEWSYM memoryloc2, resd 1 ; Memory offset in conventional memoryNEWSYM sbselec, resw 1 ; Selector of Memory locationNEWSYM sbpmofs, resd 1 ; offset of Memory locationSBDeinitType resb 1section .textNEWSYM 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[StereoSound],1 jne .nostereo8b.surround8b mov eax,[SoundQuality] cmp eax,4 je .okay 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -