1176 lines
21 KiB
NASM
1176 lines
21 KiB
NASM
; Hovertank 3-D Source Code
|
|
; Copyright (C) 1993-2014 Flat Rock Software
|
|
;
|
|
; 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.,
|
|
; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
|
ifndef ??version
|
|
?debug macro
|
|
endm
|
|
publicdll macro name
|
|
public name
|
|
endm
|
|
$comm macro name,dist,size,count
|
|
comm dist name:BYTE:count*size
|
|
endm
|
|
else
|
|
$comm macro name,dist,size,count
|
|
comm dist name[size]:BYTE:count
|
|
endm
|
|
endif
|
|
?debug S "jm_sb.c"
|
|
?debug C E9573E9E16076A6D5F73622E63
|
|
?debug C E900104D1613433A5C42435C494E434C5544455C646F732E68
|
|
?debug C E9DB749D16076A6D5F73622E68
|
|
?debug C E978749D16046A6D2E68
|
|
_TEXT segment byte public 'CODE'
|
|
_TEXT ends
|
|
DGROUP group _DATA,_BSS
|
|
assume cs:_TEXT,ds:DGROUP
|
|
_DATA segment word public 'DATA'
|
|
d@ label byte
|
|
d@w label word
|
|
_DATA ends
|
|
_BSS segment word public 'BSS'
|
|
b@ label byte
|
|
b@w label word
|
|
_BSS ends
|
|
_DATA segment word public 'DATA'
|
|
sbSamplePlaying label word
|
|
db 0
|
|
db 0
|
|
sbOldIntMask label byte
|
|
db 255
|
|
sbLocation label word
|
|
db 255
|
|
db 255
|
|
sbInterrupt label word
|
|
db 7
|
|
db 0
|
|
sbIntVec label word
|
|
db 15
|
|
db 0
|
|
sbIntVectors label word
|
|
db 255
|
|
db 255
|
|
db 255
|
|
db 255
|
|
db 10
|
|
db 0
|
|
db 11
|
|
db 0
|
|
db 255
|
|
db 255
|
|
db 13
|
|
db 0
|
|
db 255
|
|
db 255
|
|
db 15
|
|
db 0
|
|
_DATA ends
|
|
_TEXT segment byte public 'CODE'
|
|
;
|
|
; static void
|
|
;
|
|
assume cs:_TEXT
|
|
jmDelay proc near
|
|
push bp
|
|
mov bp,sp
|
|
push si
|
|
push di
|
|
mov di,word ptr [bp+4]
|
|
jmp short @1@122
|
|
@1@50:
|
|
;
|
|
; jmDelay(int usec)
|
|
; {
|
|
; // DEBUG - use real timing routines
|
|
; int i;
|
|
;
|
|
; while (usec--)
|
|
;
|
|
xor si,si
|
|
jmp short @1@98
|
|
@1@74:
|
|
inc si
|
|
@1@98:
|
|
cmp si,1000
|
|
jl short @1@74
|
|
@1@122:
|
|
mov ax,di
|
|
dec di
|
|
or ax,ax
|
|
jne short @1@50
|
|
;
|
|
; for (i = 0;i < 1000;i++)
|
|
; ;
|
|
;
|
|
pop di
|
|
pop si
|
|
pop bp
|
|
ret
|
|
jmDelay endp
|
|
;
|
|
; static longword
|
|
;
|
|
assume cs:_TEXT
|
|
jmPlaySeg proc near
|
|
push bp
|
|
mov bp,sp
|
|
sub sp,10
|
|
;
|
|
; jmPlaySeg(byte huge *data,longword length)
|
|
; {
|
|
; unsigned datapage;
|
|
; longword dataofs,uselen;
|
|
;
|
|
;
|
|
mov ax,word ptr [bp+10]
|
|
mov dx,word ptr [bp+8]
|
|
mov word ptr [bp-8],ax
|
|
mov word ptr [bp-10],dx
|
|
;
|
|
; uselen = length;
|
|
;
|
|
mov ax,word ptr [bp+6]
|
|
mov cl,12
|
|
shr ax,cl
|
|
mov word ptr [bp-2],ax
|
|
;
|
|
; datapage = FP_SEG(data) >> 12;
|
|
;
|
|
mov ax,word ptr [bp+6]
|
|
and ax,4095
|
|
mov cl,4
|
|
shl ax,cl
|
|
add ax,word ptr [bp+4]
|
|
mov word ptr [bp-4],0
|
|
mov word ptr [bp-6],ax
|
|
;
|
|
; dataofs = ( (FP_SEG(data)&0xfff)<<4 ) + FP_OFF(data);
|
|
;
|
|
cmp word ptr [bp-4],1
|
|
jb short @2@122
|
|
jne short @2@98
|
|
cmp word ptr [bp-6],0
|
|
jb short @2@122
|
|
@2@98:
|
|
;
|
|
; if (dataofs>=0x10000)
|
|
; {
|
|
;
|
|
inc word ptr [bp-2]
|
|
;
|
|
; datapage++;
|
|
;
|
|
sub word ptr [bp-6],0
|
|
sbb word ptr [bp-4],1
|
|
@2@122:
|
|
;
|
|
; dataofs-=0x10000;
|
|
; }
|
|
;
|
|
;
|
|
mov ax,word ptr [bp-4]
|
|
mov dx,word ptr [bp-6]
|
|
add dx,word ptr [bp-10]
|
|
adc ax,word ptr [bp-8]
|
|
cmp ax,1
|
|
jb short @2@218
|
|
ja short @2@194
|
|
or dx,dx
|
|
jbe short @2@218
|
|
@2@194:
|
|
;
|
|
; if (dataofs + uselen > 0x10000)
|
|
;
|
|
mov ax,1
|
|
xor dx,dx
|
|
sub dx,word ptr [bp-6]
|
|
sbb ax,word ptr [bp-4]
|
|
mov word ptr [bp-8],ax
|
|
mov word ptr [bp-10],dx
|
|
@2@218:
|
|
;
|
|
; uselen = 0x10000 - dataofs;
|
|
;
|
|
;
|
|
sub word ptr [bp-10],1
|
|
sbb word ptr [bp-8],0
|
|
;
|
|
; uselen--; // DEBUG
|
|
;
|
|
; // Program the DMA controller
|
|
;
|
|
mov dx,10
|
|
mov al,5
|
|
out dx,al
|
|
;
|
|
; outportb(0x0a,5); // Mask off channel 1 DMA
|
|
;
|
|
mov dx,12
|
|
mov al,0
|
|
out dx,al
|
|
;
|
|
; outportb(0x0c,0); // Clear byte ptr F/F to lower byte
|
|
;
|
|
mov dx,11
|
|
mov al,73
|
|
out dx,al
|
|
;
|
|
; outportb(0x0b,0x49); // Set transfer mode for D/A conv
|
|
;
|
|
mov dx,2
|
|
mov al,byte ptr [bp-6]
|
|
out dx,al
|
|
;
|
|
; outportb(0x02,(byte)dataofs); // Give LSB of address
|
|
;
|
|
mov dx,word ptr [bp-4]
|
|
mov ax,word ptr [bp-6]
|
|
mov cl,8
|
|
call near ptr N_LXURSH@
|
|
mov dx,2
|
|
out dx,al
|
|
;
|
|
; outportb(0x02,(byte)(dataofs >> 8)); // Give MSB of address
|
|
;
|
|
mov dx,131
|
|
mov al,byte ptr [bp-2]
|
|
out dx,al
|
|
;
|
|
; outportb(0x83,(byte)datapage); // Give page of address
|
|
;
|
|
mov dx,3
|
|
mov al,byte ptr [bp-10]
|
|
out dx,al
|
|
;
|
|
; outportb(0x03,(byte)uselen); // Give LSB of length
|
|
;
|
|
mov dx,word ptr [bp-8]
|
|
mov ax,word ptr [bp-10]
|
|
mov cl,8
|
|
call near ptr N_LXURSH@
|
|
mov dx,3
|
|
out dx,al
|
|
;
|
|
; outportb(0x03,(byte)(uselen >> 8)); // Give MSB of length
|
|
;
|
|
mov dx,10
|
|
mov al,1
|
|
out dx,al
|
|
jmp short @2@242
|
|
@2@242:
|
|
;
|
|
; outportb(0x0a,1); // Turn on channel 1 DMA
|
|
;
|
|
; // Start playing the thing
|
|
;
|
|
mov dx,word ptr DGROUP:sbLocation
|
|
add dx,524
|
|
in al,dx
|
|
mov ah,0
|
|
test ax,128
|
|
jne short @2@242
|
|
;
|
|
; sbWriteDelay();
|
|
;
|
|
mov dx,word ptr DGROUP:sbLocation
|
|
add dx,524
|
|
mov al,20
|
|
out dx,al
|
|
jmp short @2@290
|
|
@2@290:
|
|
;
|
|
; sbOut(sbWriteCmd,0x14);
|
|
;
|
|
mov dx,word ptr DGROUP:sbLocation
|
|
add dx,524
|
|
in al,dx
|
|
mov ah,0
|
|
test ax,128
|
|
jne short @2@290
|
|
;
|
|
; sbWriteDelay();
|
|
;
|
|
mov dx,word ptr DGROUP:sbLocation
|
|
add dx,524
|
|
mov al,byte ptr [bp-10]
|
|
out dx,al
|
|
jmp short @2@338
|
|
@2@338:
|
|
;
|
|
; sbOut(sbWriteData,(byte)uselen);
|
|
;
|
|
mov dx,word ptr DGROUP:sbLocation
|
|
add dx,524
|
|
in al,dx
|
|
mov ah,0
|
|
test ax,128
|
|
jne short @2@338
|
|
;
|
|
; sbWriteDelay();
|
|
;
|
|
mov dx,word ptr [bp-8]
|
|
mov ax,word ptr [bp-10]
|
|
mov cl,8
|
|
call near ptr N_LXURSH@
|
|
mov dx,word ptr DGROUP:sbLocation
|
|
add dx,524
|
|
out dx,al
|
|
;
|
|
; sbOut(sbWriteData,(byte)(uselen >> 8));
|
|
;
|
|
;
|
|
add word ptr [bp-10],1
|
|
mov ax,word ptr [bp-10]
|
|
adc word ptr [bp-8],0
|
|
mov dx,word ptr [bp-8]
|
|
jmp short @2@386
|
|
@2@386:
|
|
;
|
|
; return(++uselen);
|
|
;
|
|
mov sp,bp
|
|
pop bp
|
|
ret
|
|
jmPlaySeg endp
|
|
;
|
|
; void interrupt
|
|
;
|
|
assume cs:_TEXT
|
|
_jmSBService proc far
|
|
push ax
|
|
push bx
|
|
push cx
|
|
push dx
|
|
push es
|
|
push ds
|
|
push si
|
|
push di
|
|
push bp
|
|
mov bp,DGROUP
|
|
mov ds,bp
|
|
mov bp,sp
|
|
sub sp,4
|
|
;
|
|
; jmSBService(void)
|
|
; {
|
|
; longword used;
|
|
;
|
|
;
|
|
mov dx,word ptr DGROUP:sbLocation
|
|
add dx,526
|
|
in al,dx
|
|
;
|
|
; sbIn(sbDataAvail);
|
|
;
|
|
mov dx,32
|
|
mov al,32
|
|
out dx,al
|
|
;
|
|
; outportb(0x20,0x20);
|
|
;
|
|
;
|
|
xor cx,cx
|
|
xor bx,bx
|
|
mov dx,word ptr DGROUP:sbNextSegPtr+2
|
|
mov ax,word ptr DGROUP:sbNextSegPtr
|
|
call near ptr N_PCMP@
|
|
je short @3@194
|
|
;
|
|
; if (sbNextSegPtr)
|
|
; {
|
|
;
|
|
push word ptr DGROUP:sbNextSegLen+2
|
|
push word ptr DGROUP:sbNextSegLen
|
|
push word ptr DGROUP:sbNextSegPtr+2
|
|
push word ptr DGROUP:sbNextSegPtr
|
|
call near ptr jmPlaySeg
|
|
add sp,8
|
|
mov word ptr [bp-2],dx
|
|
mov word ptr [bp-4],ax
|
|
;
|
|
; used = jmPlaySeg(sbNextSegPtr,sbNextSegLen);
|
|
;
|
|
mov ax,word ptr DGROUP:sbNextSegLen+2
|
|
mov dx,word ptr DGROUP:sbNextSegLen
|
|
cmp ax,word ptr [bp-2]
|
|
ja short @3@146
|
|
jne short @3@122
|
|
cmp dx,word ptr [bp-4]
|
|
ja short @3@146
|
|
@3@122:
|
|
;
|
|
; if (sbNextSegLen <= used)
|
|
;
|
|
mov word ptr DGROUP:sbNextSegPtr+2,0
|
|
mov word ptr DGROUP:sbNextSegPtr,0
|
|
jmp short @3@170
|
|
@3@146:
|
|
;
|
|
; sbNextSegPtr = nil;
|
|
; else
|
|
; {
|
|
;
|
|
mov cx,word ptr [bp-2]
|
|
mov bx,word ptr [bp-4]
|
|
mov dx,ds
|
|
mov ax,offset DGROUP:sbNextSegPtr
|
|
call near ptr N_PADA@
|
|
;
|
|
; sbNextSegPtr += used;
|
|
;
|
|
mov ax,word ptr [bp-2]
|
|
mov dx,word ptr [bp-4]
|
|
sub word ptr DGROUP:sbNextSegLen,dx
|
|
sbb word ptr DGROUP:sbNextSegLen+2,ax
|
|
@3@170:
|
|
;
|
|
; sbNextSegLen -= used;
|
|
; }
|
|
;
|
|
jmp short @3@218
|
|
@3@194:
|
|
;
|
|
; }
|
|
; else
|
|
;
|
|
call near ptr _jmStopSample
|
|
@3@218:
|
|
;
|
|
; jmStopSample();
|
|
;
|
|
mov sp,bp
|
|
pop bp
|
|
pop di
|
|
pop si
|
|
pop ds
|
|
pop es
|
|
pop dx
|
|
pop cx
|
|
pop bx
|
|
pop ax
|
|
iret
|
|
_jmSBService endp
|
|
;
|
|
; void
|
|
;
|
|
assume cs:_TEXT
|
|
_jmPlaySample proc near
|
|
push bp
|
|
mov bp,sp
|
|
sub sp,24
|
|
push si
|
|
mov si,word ptr [bp+4]
|
|
;
|
|
; jmPlaySample(sound)
|
|
; int sound;
|
|
; {
|
|
; byte huge *data,
|
|
; timevalue;
|
|
; longword used;
|
|
; SampledSound sample;
|
|
;
|
|
;
|
|
call near ptr _jmStopSample
|
|
;
|
|
; jmStopSample();
|
|
;
|
|
;
|
|
dec si
|
|
lea ax,word ptr [bp-24]
|
|
push ss
|
|
push ax
|
|
mov ax,si
|
|
cwd
|
|
push ax
|
|
push dx
|
|
xor dx,dx
|
|
mov ax,14
|
|
pop cx
|
|
pop bx
|
|
call near ptr N_LXMUL@
|
|
push ax
|
|
push dx
|
|
mov dx,word ptr DGROUP:sbSamples+2
|
|
mov ax,word ptr DGROUP:sbSamples
|
|
pop cx
|
|
pop bx
|
|
call near ptr N_PADD@
|
|
push dx
|
|
push ax
|
|
mov cx,14
|
|
call near ptr N_SCOPY@
|
|
;
|
|
; sample = sbSamples[--sound];
|
|
;
|
|
;
|
|
mov dx,word ptr DGROUP:sbSamples+2
|
|
mov ax,word ptr DGROUP:sbSamples
|
|
mov cx,word ptr [bp-22]
|
|
mov bx,word ptr [bp-24]
|
|
call near ptr N_PADD@
|
|
mov word ptr [bp-2],dx
|
|
mov word ptr [bp-4],ax
|
|
;
|
|
; data = ((byte huge *)sbSamples) + sample.offset;
|
|
;
|
|
push word ptr [bp-14]
|
|
push word ptr [bp-16]
|
|
mov ax,15
|
|
mov dx,16960
|
|
push ax
|
|
push dx
|
|
call near ptr N_LUDIV@
|
|
mov dl,0
|
|
sub dl,al
|
|
mov byte ptr [bp-5],dl
|
|
jmp short @4@50
|
|
@4@50:
|
|
;
|
|
; timevalue = 256 - (1000000 / sample.hertz);
|
|
;
|
|
; // printf("sample #%d ",sound);
|
|
; // printf("%ld bytes, %ldHz, tc=%d\n",sample.length,sample.hertz,timevalue);
|
|
;
|
|
; // printf("setting time constant\n");
|
|
; // Set the SoundBlaster DAC time constant
|
|
;
|
|
mov dx,word ptr DGROUP:sbLocation
|
|
add dx,524
|
|
in al,dx
|
|
mov ah,0
|
|
test ax,128
|
|
jne short @4@50
|
|
;
|
|
; sbWriteDelay();
|
|
;
|
|
mov dx,word ptr DGROUP:sbLocation
|
|
add dx,524
|
|
mov al,64
|
|
out dx,al
|
|
jmp short @4@98
|
|
@4@98:
|
|
;
|
|
; sbOut(sbWriteCmd,0x40);
|
|
;
|
|
mov dx,word ptr DGROUP:sbLocation
|
|
add dx,524
|
|
in al,dx
|
|
mov ah,0
|
|
test ax,128
|
|
jne short @4@98
|
|
;
|
|
; sbWriteDelay();
|
|
;
|
|
mov dx,word ptr DGROUP:sbLocation
|
|
add dx,524
|
|
mov al,byte ptr [bp-5]
|
|
out dx,al
|
|
;
|
|
; sbOut(sbWriteData,timevalue);
|
|
;
|
|
;
|
|
push word ptr [bp-18]
|
|
push word ptr [bp-20]
|
|
push word ptr [bp-2]
|
|
push word ptr [bp-4]
|
|
call near ptr jmPlaySeg
|
|
add sp,8
|
|
mov word ptr [bp-8],dx
|
|
mov word ptr [bp-10],ax
|
|
;
|
|
; used = jmPlaySeg(data,sample.length);
|
|
;
|
|
mov ax,word ptr [bp-18]
|
|
mov dx,word ptr [bp-20]
|
|
cmp ax,word ptr [bp-8]
|
|
ja short @4@218
|
|
jne short @4@194
|
|
cmp dx,word ptr [bp-10]
|
|
ja short @4@218
|
|
@4@194:
|
|
;
|
|
; if (sample.length <= used)
|
|
;
|
|
mov word ptr DGROUP:sbNextSegPtr+2,0
|
|
mov word ptr DGROUP:sbNextSegPtr,0
|
|
jmp short @4@242
|
|
@4@218:
|
|
;
|
|
; sbNextSegPtr = nil;
|
|
; else
|
|
; {
|
|
;
|
|
mov dx,word ptr [bp-2]
|
|
mov ax,word ptr [bp-4]
|
|
mov cx,word ptr [bp-8]
|
|
mov bx,word ptr [bp-10]
|
|
call near ptr N_PADD@
|
|
mov word ptr DGROUP:sbNextSegPtr+2,dx
|
|
mov word ptr DGROUP:sbNextSegPtr,ax
|
|
;
|
|
; sbNextSegPtr = data + used;
|
|
;
|
|
mov ax,word ptr [bp-18]
|
|
mov dx,word ptr [bp-20]
|
|
sub dx,word ptr [bp-10]
|
|
sbb ax,word ptr [bp-8]
|
|
mov word ptr DGROUP:sbNextSegLen+2,ax
|
|
mov word ptr DGROUP:sbNextSegLen,dx
|
|
@4@242:
|
|
;
|
|
; sbNextSegLen = sample.length - used;
|
|
; }
|
|
;
|
|
; // printf("enabling SB irq #%d\n",sbInterrupt);
|
|
; // Save old interrupt status and unmask ours
|
|
;
|
|
mov dx,33
|
|
in al,dx
|
|
mov byte ptr DGROUP:sbOldIntMask,al
|
|
;
|
|
; sbOldIntMask = inportb(0x21);
|
|
;
|
|
mov al,1
|
|
mov cl,byte ptr DGROUP:sbInterrupt
|
|
shl al,cl
|
|
not al
|
|
push ax
|
|
mov al,byte ptr DGROUP:sbOldIntMask
|
|
pop dx
|
|
and al,dl
|
|
mov dx,33
|
|
out dx,al
|
|
jmp short @4@266
|
|
@4@266:
|
|
;
|
|
; outportb(0x21,sbOldIntMask & ~(1 << sbInterrupt));
|
|
;
|
|
; // printf("enabling DSP DMA request\n");
|
|
;
|
|
mov dx,word ptr DGROUP:sbLocation
|
|
add dx,524
|
|
in al,dx
|
|
mov ah,0
|
|
test ax,128
|
|
jne short @4@266
|
|
;
|
|
; sbWriteDelay();
|
|
;
|
|
mov dx,word ptr DGROUP:sbLocation
|
|
add dx,524
|
|
mov al,212
|
|
out dx,al
|
|
;
|
|
; sbOut(sbWriteCmd,0xd4); // Make sure DSP DMA is enabled
|
|
;
|
|
; // printf("sound should be playing\n");
|
|
;
|
|
mov word ptr DGROUP:sbSamplePlaying,1
|
|
;
|
|
; sbSamplePlaying = true;
|
|
;
|
|
pop si
|
|
mov sp,bp
|
|
pop bp
|
|
ret
|
|
_jmPlaySample endp
|
|
;
|
|
; void
|
|
;
|
|
assume cs:_TEXT
|
|
_jmStopSample proc near
|
|
push bp
|
|
mov bp,sp
|
|
;
|
|
; jmStopSample(void)
|
|
; {
|
|
; byte is;
|
|
;
|
|
;
|
|
cmp word ptr DGROUP:sbSamplePlaying,0
|
|
je short @5@194
|
|
jmp short @5@74
|
|
@5@74:
|
|
;
|
|
; if (sbSamplePlaying)
|
|
; {
|
|
; // printf("turning off DSP DMA\n");
|
|
;
|
|
mov dx,word ptr DGROUP:sbLocation
|
|
add dx,524
|
|
in al,dx
|
|
mov ah,0
|
|
test ax,128
|
|
jne short @5@74
|
|
;
|
|
; sbWriteDelay();
|
|
;
|
|
mov dx,word ptr DGROUP:sbLocation
|
|
add dx,524
|
|
mov al,208
|
|
out dx,al
|
|
;
|
|
; sbOut(sbWriteCmd,0xd0); // Turn off DSP DMA
|
|
;
|
|
; // printf("restoring interrupt\n");
|
|
;
|
|
mov dx,33
|
|
in al,dx
|
|
mov bl,al
|
|
;
|
|
; is = inportb(0x21); // Restore interrupt mask bit
|
|
;
|
|
mov ax,1
|
|
mov cl,byte ptr DGROUP:sbInterrupt
|
|
shl ax,cl
|
|
mov dl,byte ptr DGROUP:sbOldIntMask
|
|
mov dh,0
|
|
test ax,dx
|
|
je short @5@146
|
|
;
|
|
; if (sbOldIntMask & (1 << sbInterrupt))
|
|
;
|
|
mov al,1
|
|
mov cl,byte ptr DGROUP:sbInterrupt
|
|
shl al,cl
|
|
or bl,al
|
|
jmp short @5@170
|
|
@5@146:
|
|
;
|
|
; is |= (1 << sbInterrupt);
|
|
; else
|
|
;
|
|
mov al,1
|
|
mov cl,byte ptr DGROUP:sbInterrupt
|
|
shl al,cl
|
|
not al
|
|
and bl,al
|
|
@5@170:
|
|
;
|
|
; is &= ~(1 << sbInterrupt);
|
|
;
|
|
mov dx,33
|
|
mov al,bl
|
|
out dx,al
|
|
;
|
|
; outportb(0x21,is);
|
|
;
|
|
;
|
|
;
|
|
mov word ptr DGROUP:sbSamplePlaying,0
|
|
@5@194:
|
|
;
|
|
; sbSamplePlaying = false;
|
|
; }
|
|
;
|
|
pop bp
|
|
ret
|
|
_jmStopSample endp
|
|
;
|
|
; static boolean
|
|
;
|
|
assume cs:_TEXT
|
|
jmCheckSB proc near
|
|
push bp
|
|
mov bp,sp
|
|
push si
|
|
;
|
|
; jmCheckSB(int port)
|
|
; {
|
|
; int i;
|
|
;
|
|
;
|
|
mov ax,word ptr [bp+4]
|
|
mov cl,4
|
|
shl ax,cl
|
|
mov word ptr DGROUP:sbLocation,ax
|
|
;
|
|
; sbLocation = port << 4; // Initialize stuff for later use
|
|
;
|
|
;
|
|
mov dx,word ptr DGROUP:sbLocation
|
|
add dx,518
|
|
mov al,1
|
|
out dx,al
|
|
;
|
|
; sbOut(sbReset,true); // Reset the SoundBlaster DSP
|
|
;
|
|
mov ax,4
|
|
push ax
|
|
call near ptr jmDelay
|
|
pop cx
|
|
;
|
|
; jmDelay(4); // Wait 4usec
|
|
;
|
|
mov dx,word ptr DGROUP:sbLocation
|
|
add dx,518
|
|
mov al,0
|
|
out dx,al
|
|
;
|
|
; sbOut(sbReset,false); // Turn off sb DSP reset
|
|
;
|
|
mov ax,100
|
|
push ax
|
|
call near ptr jmDelay
|
|
pop cx
|
|
;
|
|
; jmDelay(100); // Wait 100usec
|
|
;
|
|
xor si,si
|
|
jmp short @6@194
|
|
@6@50:
|
|
;
|
|
; for (i = 0;i < 100;i++)
|
|
; {
|
|
;
|
|
mov dx,word ptr DGROUP:sbLocation
|
|
add dx,526
|
|
in al,dx
|
|
test al,128
|
|
je short @6@170
|
|
;
|
|
; if (sbIn(sbDataAvail) & 0x80) // If data is available...
|
|
; {
|
|
;
|
|
mov dx,word ptr DGROUP:sbLocation
|
|
add dx,522
|
|
in al,dx
|
|
cmp al,170
|
|
jne short @6@146
|
|
;
|
|
; if (sbIn(sbReadData) == 0xaa) // If it matches correct value
|
|
;
|
|
mov ax,1
|
|
jmp short @6@242
|
|
jmp short @6@170
|
|
@6@146:
|
|
;
|
|
; return(true);
|
|
; else
|
|
; {
|
|
;
|
|
mov word ptr DGROUP:sbLocation,65535
|
|
;
|
|
; sbLocation = -1; // Otherwise not a SoundBlaster
|
|
;
|
|
xor ax,ax
|
|
jmp short @6@242
|
|
@6@170:
|
|
inc si
|
|
@6@194:
|
|
cmp si,100
|
|
jl short @6@50
|
|
;
|
|
; return(false);
|
|
; }
|
|
; }
|
|
; }
|
|
;
|
|
mov word ptr DGROUP:sbLocation,65535
|
|
;
|
|
; sbLocation = -1; // Retry count exceeded - fail
|
|
;
|
|
xor ax,ax
|
|
jmp short @6@242
|
|
@6@242:
|
|
;
|
|
; return(false);
|
|
;
|
|
pop si
|
|
pop bp
|
|
ret
|
|
jmCheckSB endp
|
|
;
|
|
; boolean
|
|
;
|
|
assume cs:_TEXT
|
|
_jmDetectSoundBlaster proc near
|
|
push bp
|
|
mov bp,sp
|
|
push si
|
|
push di
|
|
mov si,word ptr [bp+4]
|
|
;
|
|
; jmDetectSoundBlaster(int port)
|
|
; {
|
|
; int i;
|
|
;
|
|
;
|
|
or si,si
|
|
jne short @7@74
|
|
;
|
|
; if (port == 0) // If user specifies default address, use 2
|
|
;
|
|
mov si,2
|
|
@7@74:
|
|
;
|
|
; port = 2;
|
|
;
|
|
cmp si,65535
|
|
jne short @7@266
|
|
;
|
|
; if (port == -1)
|
|
; {
|
|
;
|
|
mov di,1
|
|
jmp short @7@194
|
|
@7@122:
|
|
;
|
|
; for (i = 1;i <= 6;i++) // Scan through possible SB locations
|
|
; {
|
|
;
|
|
push di
|
|
call near ptr jmCheckSB
|
|
pop cx
|
|
or ax,ax
|
|
je short @7@170
|
|
;
|
|
; if (jmCheckSB(i)) // If found at this address,
|
|
;
|
|
mov ax,1
|
|
jmp short @7@290
|
|
@7@170:
|
|
inc di
|
|
@7@194:
|
|
cmp di,6
|
|
jle short @7@122
|
|
;
|
|
; return(true); // return success
|
|
; }
|
|
;
|
|
xor ax,ax
|
|
jmp short @7@290
|
|
;
|
|
; return(false); // All addresses failed, return failure
|
|
;
|
|
jmp short @7@290
|
|
@7@266:
|
|
;
|
|
; }
|
|
; else
|
|
;
|
|
push si
|
|
call near ptr jmCheckSB
|
|
pop cx
|
|
jmp short @7@290
|
|
@7@290:
|
|
;
|
|
; return(jmCheckSB(port)); // User specified address or default
|
|
;
|
|
pop di
|
|
pop si
|
|
pop bp
|
|
ret
|
|
_jmDetectSoundBlaster endp
|
|
;
|
|
; void
|
|
;
|
|
assume cs:_TEXT
|
|
_jmSetSBInterrupt proc near
|
|
push bp
|
|
mov bp,sp
|
|
;
|
|
; jmSetSBInterrupt(int num)
|
|
; {
|
|
;
|
|
mov ax,word ptr [bp+4]
|
|
mov word ptr DGROUP:sbInterrupt,ax
|
|
;
|
|
; sbInterrupt = num;
|
|
;
|
|
mov bx,word ptr DGROUP:sbInterrupt
|
|
shl bx,1
|
|
mov ax,word ptr DGROUP:sbIntVectors[bx]
|
|
mov word ptr DGROUP:sbIntVec,ax
|
|
;
|
|
; sbIntVec = sbIntVectors[sbInterrupt];
|
|
;
|
|
pop bp
|
|
ret
|
|
_jmSetSBInterrupt endp
|
|
;
|
|
; void
|
|
;
|
|
assume cs:_TEXT
|
|
_jmStartSB proc near
|
|
push bp
|
|
mov bp,sp
|
|
;
|
|
; jmStartSB(void)
|
|
; {
|
|
; // printf("setting interrupt #0x%02x handler\n",sbIntVec);
|
|
;
|
|
push word ptr DGROUP:sbIntVec
|
|
call near ptr _getvect
|
|
pop cx
|
|
mov word ptr DGROUP:sbOldIntHand+2,dx
|
|
mov word ptr DGROUP:sbOldIntHand,ax
|
|
;
|
|
; sbOldIntHand = getvect(sbIntVec); // Get old interrupt handler
|
|
;
|
|
push cs
|
|
mov ax,offset _jmSBService
|
|
push ax
|
|
push word ptr DGROUP:sbIntVec
|
|
call near ptr _setvect
|
|
add sp,6
|
|
jmp short @9@50
|
|
@9@50:
|
|
;
|
|
; setvect(sbIntVec,jmSBService); // Set mine
|
|
;
|
|
; // printf("setting DSP modes\n");
|
|
;
|
|
mov dx,word ptr DGROUP:sbLocation
|
|
add dx,524
|
|
in al,dx
|
|
mov ah,0
|
|
test ax,128
|
|
jne short @9@50
|
|
;
|
|
; sbWriteDelay();
|
|
;
|
|
mov dx,word ptr DGROUP:sbLocation
|
|
add dx,524
|
|
mov al,209
|
|
out dx,al
|
|
;
|
|
; sbOut(sbWriteCmd,0xd1); // Turn on DSP speaker
|
|
;
|
|
pop bp
|
|
ret
|
|
_jmStartSB endp
|
|
;
|
|
; void
|
|
;
|
|
assume cs:_TEXT
|
|
_jmShutSB proc near
|
|
push bp
|
|
mov bp,sp
|
|
;
|
|
; jmShutSB(void)
|
|
; {
|
|
;
|
|
call near ptr _jmStopSample
|
|
;
|
|
; jmStopSample();
|
|
;
|
|
; // printf("restoring interrupt vector\n");
|
|
;
|
|
push word ptr DGROUP:sbOldIntHand+2
|
|
push word ptr DGROUP:sbOldIntHand
|
|
push word ptr DGROUP:sbIntVec
|
|
call near ptr _setvect
|
|
add sp,6
|
|
;
|
|
; setvect(sbIntVec,sbOldIntHand); // Set vector back
|
|
;
|
|
pop bp
|
|
ret
|
|
_jmShutSB endp
|
|
;
|
|
; boolean
|
|
;
|
|
assume cs:_TEXT
|
|
_jmSamplePlaying proc near
|
|
push bp
|
|
mov bp,sp
|
|
;
|
|
; jmSamplePlaying(void)
|
|
; {
|
|
;
|
|
mov ax,word ptr DGROUP:sbSamplePlaying
|
|
jmp short @11@50
|
|
@11@50:
|
|
;
|
|
; return(sbSamplePlaying);
|
|
;
|
|
pop bp
|
|
ret
|
|
_jmSamplePlaying endp
|
|
;
|
|
; void
|
|
;
|
|
assume cs:_TEXT
|
|
_jmSetSamplePtr proc near
|
|
push bp
|
|
mov bp,sp
|
|
;
|
|
; jmSetSamplePtr(s)
|
|
; SampledSound huge *s;
|
|
; {
|
|
;
|
|
mov ax,word ptr [bp+6]
|
|
mov dx,word ptr [bp+4]
|
|
mov word ptr DGROUP:sbSamples+2,ax
|
|
mov word ptr DGROUP:sbSamples,dx
|
|
;
|
|
; sbSamples = s;
|
|
;
|
|
pop bp
|
|
ret
|
|
_jmSetSamplePtr endp
|
|
_TEXT ends
|
|
_BSS segment word public 'BSS'
|
|
sbSamples label dword
|
|
db 4 dup (?)
|
|
sbNextSegLen label word
|
|
db 4 dup (?)
|
|
sbOldIntHand label dword
|
|
db 4 dup (?)
|
|
sbNextSegPtr label dword
|
|
db 4 dup (?)
|
|
?debug C E9
|
|
_BSS ends
|
|
_DATA segment word public 'DATA'
|
|
s@ label byte
|
|
_DATA ends
|
|
_TEXT segment byte public 'CODE'
|
|
_TEXT ends
|
|
_sbIntVec equ sbIntVec
|
|
public _jmSBService
|
|
_jmPlaySeg equ jmPlaySeg
|
|
extrn _setvect:near
|
|
_jmCheckSB equ jmCheckSB
|
|
public _jmStartSB
|
|
extrn _getvect:near
|
|
_jmDelay equ jmDelay
|
|
public _jmShutSB
|
|
_sbSamplePlaying equ sbSamplePlaying
|
|
public _jmDetectSoundBlaster
|
|
extrn N_SCOPY@:far
|
|
_sbNextSegPtr equ sbNextSegPtr
|
|
_sbOldIntMask equ sbOldIntMask
|
|
_sbIntVectors equ sbIntVectors
|
|
extrn N_LUDIV@:far
|
|
public _jmSetSBInterrupt
|
|
_sbOldIntHand equ sbOldIntHand
|
|
extrn N_LXURSH@:far
|
|
_sbInterrupt equ sbInterrupt
|
|
extrn N_LXMUL@:far
|
|
_sbNextSegLen equ sbNextSegLen
|
|
public _jmSamplePlaying
|
|
extrn N_PCMP@:far
|
|
public _jmSetSamplePtr
|
|
_sbLocation equ sbLocation
|
|
extrn N_PADD@:far
|
|
extrn N_PADA@:far
|
|
_sbSamples equ sbSamples
|
|
public _jmStopSample
|
|
public _jmPlaySample
|
|
end
|
|
|