1387 lines
33 KiB
C
Executable File
1387 lines
33 KiB
C
Executable File
// "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman
|
|
// Ken Silverman's official web site: "http://www.advsys.net/ken"
|
|
// See the included license file "BUILDLIC.TXT" for license info.
|
|
// This file has been modified from Ken Silverman's original release
|
|
|
|
#include <malloc.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <fcntl.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
|
|
#include "platform.h"
|
|
#include "pragmas.h"
|
|
#include "cache1d.h"
|
|
|
|
|
|
#if (!defined PLATFORM_DOS)
|
|
#error This should only be compiled for the DOS/386 target.
|
|
#endif
|
|
|
|
|
|
#define NUMCHANNELS 16
|
|
#define MAXWAVES 256
|
|
#define MAXTRACKS 256
|
|
#define MAXNOTES 8192
|
|
#define MAXEFFECTS 16
|
|
|
|
//Actual sound parameters after initsb was called
|
|
long samplerate, numspeakers, bytespersample, intspersec, kdmqual;
|
|
|
|
//KWV wave variables
|
|
long numwaves;
|
|
char instname[MAXWAVES][16];
|
|
long wavleng[MAXWAVES];
|
|
long repstart[MAXWAVES], repleng[MAXWAVES];
|
|
long finetune[MAXWAVES];
|
|
|
|
//Other useful wave variables
|
|
long totsndbytes, totsndmem, wavoffs[MAXWAVES];
|
|
|
|
//Effects array
|
|
long eff[MAXEFFECTS][256];
|
|
|
|
//KDM song variables:
|
|
long kdmversionum, numnotes, numtracks;
|
|
char trinst[MAXTRACKS], trquant[MAXTRACKS];
|
|
char trvol1[MAXTRACKS], trvol2[MAXTRACKS];
|
|
long nttime[MAXNOTES];
|
|
char nttrack[MAXNOTES], ntfreq[MAXNOTES];
|
|
char ntvol1[MAXNOTES], ntvol2[MAXNOTES];
|
|
char ntfrqeff[MAXNOTES], ntvoleff[MAXNOTES], ntpaneff[MAXNOTES];
|
|
|
|
//Other useful song variables:
|
|
long timecount, notecnt, musicstatus, musicrepeat;
|
|
|
|
long kdmasm1, kdmasm2, kdmasm3, kdmasm4;
|
|
|
|
static char digistat = 0, musistat = 0;
|
|
|
|
char *snd = NULL, kwvname[20] = {""};
|
|
|
|
#define MAXBYTESPERTIC 1024+128
|
|
static long stemp[MAXBYTESPERTIC];
|
|
|
|
//Sound reading information
|
|
long splc[NUMCHANNELS], sinc[NUMCHANNELS], soff[NUMCHANNELS];
|
|
long svol1[NUMCHANNELS], svol2[NUMCHANNELS];
|
|
long volookup[NUMCHANNELS<<9];
|
|
long swavenum[NUMCHANNELS];
|
|
long frqeff[NUMCHANNELS], frqoff[NUMCHANNELS];
|
|
long voleff[NUMCHANNELS], voloff[NUMCHANNELS];
|
|
long paneff[NUMCHANNELS], panoff[NUMCHANNELS];
|
|
|
|
static long globposx, globposy, globxvect, globyvect;
|
|
static long xplc[NUMCHANNELS], yplc[NUMCHANNELS], vol[NUMCHANNELS];
|
|
static long vdist[NUMCHANNELS], sincoffs[NUMCHANNELS];
|
|
static char chanstat[NUMCHANNELS];
|
|
|
|
long frqtable[256];
|
|
|
|
static long mixerval = 0;
|
|
|
|
static long kdminprep = 0, kdmintinprep = 0;
|
|
static long dmacheckport, dmachecksiz;
|
|
|
|
void (__interrupt __far *oldsbhandler)();
|
|
void __interrupt __far sbhandler(void);
|
|
|
|
long samplediv, oldtimerfreq, chainbackcnt, chainbackstart;
|
|
char *pcsndptr, pcsndlookup[256], bufferside;
|
|
long samplecount, pcsndbufsiz, pcrealmodeint;
|
|
static short kdmvect = 0x8;
|
|
static unsigned short kdmpsel, kdmrseg, kdmroff;
|
|
static unsigned long kdmpoff;
|
|
|
|
void (__interrupt __far *oldpctimerhandler)();
|
|
#define KDMCODEBYTES 256
|
|
static char pcrealbuffer[KDMCODEBYTES] = //See pckdm.asm
|
|
{
|
|
0x50,0x53,0x51,0x52,0x32,0xC0,0xE6,0x42,0xB0,0x20,
|
|
0xE6,0x20,0x5A,0x59,0x5B,0x58,0xCF,
|
|
};
|
|
|
|
//Sound interrupt information
|
|
long sbport = 0x220, sbirq = 0x7, sbdma8 = 0x1, sbdma16 = 0x1;
|
|
char dmapagenum[8] = {0x87,0x83,0x81,0x82,0x8f,0x8b,0x89,0x8a};
|
|
long sbdma, sbver;
|
|
unsigned short sndselector;
|
|
volatile long sndoffs, sndoffsplc, sndoffsxor, sndplc, sndend;
|
|
static long bytespertic, sndbufsiz;
|
|
|
|
char qualookup[512*16];
|
|
long ramplookup[64];
|
|
|
|
unsigned short sndseg = 0;
|
|
|
|
#ifdef PLATFORM_DOS
|
|
extern long monolocomb(long,long,long,long,long,long);
|
|
#pragma aux monolocomb parm [eax][ebx][ecx][edx][esi][edi];
|
|
extern long monohicomb(long,long,long,long,long,long);
|
|
#pragma aux monohicomb parm [eax][ebx][ecx][edx][esi][edi];
|
|
extern long stereolocomb(long,long,long,long,long,long);
|
|
#pragma aux stereolocomb parm [eax][ebx][ecx][edx][esi][edi];
|
|
extern long stereohicomb(long,long,long,long,long,long);
|
|
#pragma aux stereohicomb parm [eax][ebx][ecx][edx][esi][edi];
|
|
extern long setuppctimerhandler(long,long,long,long,long,long);
|
|
#pragma aux setuppctimerhandler parm [eax][ebx][ecx][edx][esi][edi];
|
|
extern void interrupt pctimerhandler();
|
|
extern long pcbound2char(long,long,long);
|
|
#pragma aux pcbound2char parm [ecx][esi][edi];
|
|
extern long bound2char(long,long,long);
|
|
#pragma aux bound2char parm [ecx][esi][edi];
|
|
extern long bound2short(long,long,long);
|
|
#pragma aux bound2short parm [ecx][esi][edi];
|
|
|
|
static long oneshr10 = 0x3a800000, oneshl14 = 0x46800000;
|
|
void fsin(long *i1);
|
|
#pragma aux fsin =\
|
|
"fldpi",\
|
|
"fimul dword ptr [eax]",\
|
|
"fmul dword ptr [oneshr10]",\
|
|
"fsin",\
|
|
"fmul dword ptr [oneshl14]",\
|
|
"fistp dword ptr [eax]",\
|
|
parm [eax]\
|
|
|
|
unsigned short convallocate(long i1);
|
|
#pragma aux convallocate =\
|
|
"mov ax, 0x100",\
|
|
"int 0x31",\
|
|
"jnc nocarry",\
|
|
"mov ax, 0",\
|
|
"nocarry: mov sndselector, dx",\
|
|
parm [bx]\
|
|
modify [eax edx]\
|
|
|
|
void convdeallocate(long i1);
|
|
#pragma aux convdeallocate =\
|
|
"mov ax, 0x101",\
|
|
"mov dx, sndselector",\
|
|
"int 0x31",\
|
|
parm [dx]\
|
|
modify [eax edx]\
|
|
|
|
long resetsb(void);
|
|
#pragma aux resetsb =\
|
|
"mov edx, sbport",\
|
|
"add edx, 0x6",\
|
|
"mov al, 1",\
|
|
"out dx, al",\
|
|
"xor al, al",\
|
|
"delayreset: dec al",\
|
|
"jnz delayreset",\
|
|
"out dx, al",\
|
|
"mov ecx, 65536",\
|
|
"empty: mov edx, sbport",\
|
|
"add edx, 0xe",\
|
|
"in al, dx",\
|
|
"test al, al",\
|
|
"jns nextattempt",\
|
|
"sub dl, 4",\
|
|
"in al, dx",\
|
|
"cmp al, 0aah",\
|
|
"je resetok",\
|
|
"dec ecx",\
|
|
"nextattempt: jnz empty",\
|
|
"mov eax, -1",\
|
|
"jmp resetend",\
|
|
"resetok: xor eax, eax",\
|
|
"resetend:",\
|
|
modify [ebx ecx edx]\
|
|
|
|
long sbin(void);
|
|
#pragma aux sbin =\
|
|
"xor eax, eax",\
|
|
"mov dx, word ptr sbport[0]",\
|
|
"add dl, 0xe",\
|
|
"busy: in al, dx",\
|
|
"or al, al",\
|
|
"jns busy",\
|
|
"sub dl, 4",\
|
|
"in al, dx",\
|
|
modify [edx]\
|
|
|
|
void sbout(long i1);
|
|
#pragma aux sbout =\
|
|
"mov dx, word ptr sbport[0]",\
|
|
"add dl, 0xc",\
|
|
"mov ah, al",\
|
|
"busy: in al, dx",\
|
|
"or al, al",\
|
|
"js busy",\
|
|
"mov al, ah",\
|
|
"out dx, al",\
|
|
parm [eax]\
|
|
modify [edx]\
|
|
|
|
long sbmixin(long);
|
|
#pragma aux sbmixin =\
|
|
"mov dx, word ptr sbport[0]",\
|
|
"add dl, 0x4",\
|
|
"out dx, al",\
|
|
"inc dx",\
|
|
"xor eax, eax",\
|
|
"in al, dx",\
|
|
parm [eax]\
|
|
modify [edx]\
|
|
|
|
void sbmixout(long i1, long i2);
|
|
#pragma aux sbmixout =\
|
|
"mov dx, word ptr sbport[0]",\
|
|
"add dl, 0x4",\
|
|
"out dx, al",\
|
|
"inc dx",\
|
|
"mov al, bl",\
|
|
"out dx, al",\
|
|
parm [eax][ebx]\
|
|
modify [edx]\
|
|
|
|
void findpas(void);
|
|
#pragma aux findpas =\
|
|
"mov eax, 0x0000bc00",\
|
|
"mov ebx, 0x00003f3f",\
|
|
"int 0x2f",\
|
|
"xor bx, cx",\
|
|
"xor bx, dx",\
|
|
"cmp bx, 0x4d56",\
|
|
"stc",\
|
|
"jne nopasfound",\
|
|
"mov eax, 0x0000bc04",\
|
|
"int 0x2f",\
|
|
"mov edx, 0x0000ffff",\
|
|
"and ebx, edx",\
|
|
"and ecx, edx",\
|
|
"mov sbdma, ebx",\
|
|
"mov sbirq, ecx",\
|
|
"clc",\
|
|
"nopasfound:",\
|
|
"sbb eax, eax",\
|
|
modify [eax ebx ecx edx]\
|
|
|
|
void calcvolookupmono(long i1, long i2, long i3);
|
|
#pragma aux calcvolookupmono =\
|
|
"mov ecx, 64",\
|
|
"lea edx, [eax+ebx]",\
|
|
"add ebx, ebx",\
|
|
"begit: mov dword ptr [edi], eax",\
|
|
"mov dword ptr [edi+4], edx",\
|
|
"add eax, ebx",\
|
|
"add edx, ebx",\
|
|
"mov dword ptr [edi+8], eax",\
|
|
"mov dword ptr [edi+12], edx",\
|
|
"add eax, ebx",\
|
|
"add edx, ebx",\
|
|
"add edi, 16",\
|
|
"dec ecx",\
|
|
"jnz begit",\
|
|
parm [edi][eax][ebx]\
|
|
modify [ecx edx]\
|
|
|
|
void calcvolookupstereo(long i1, long i2, long i3, long i4, long i5);
|
|
#pragma aux calcvolookupstereo =\
|
|
"mov esi, 128",\
|
|
"begit: mov dword ptr [edi], eax",\
|
|
"mov dword ptr [edi+4], ecx",\
|
|
"add eax, ebx",\
|
|
"add ecx, edx",\
|
|
"mov dword ptr [edi+8], eax",\
|
|
"mov dword ptr [edi+12], ecx",\
|
|
"add eax, ebx",\
|
|
"add ecx, edx",\
|
|
"add edi, 16",\
|
|
"dec esi",\
|
|
"jnz begit",\
|
|
parm [edi][eax][ebx][ecx][edx]\
|
|
modify [esi]\
|
|
|
|
long gettimerval(void);
|
|
#pragma aux gettimerval =\
|
|
"xor eax, eax",\
|
|
"xor ebx, ebx",\
|
|
"mov ecx, 65536",\
|
|
"xor edx, edx",\
|
|
"loopit: mov al, 0x4",\
|
|
"out 0x43, al",\
|
|
"in al, 0x40",\
|
|
"mov dl, al",\
|
|
"in al, 0x40",\
|
|
"mov dh, al",\
|
|
"cmp ebx, edx",\
|
|
"dec ecx",\
|
|
"ja loopit",\
|
|
"jz endit",\
|
|
"mov ebx, edx",\
|
|
"jmp loopit",\
|
|
"endit: mov eax, ebx",\
|
|
modify [eax ebx ecx edx]\
|
|
|
|
#pragma aux klabs =\
|
|
"test eax, eax",\
|
|
"jns skipnegate",\
|
|
"neg eax",\
|
|
"skipnegate:",\
|
|
parm [eax]\
|
|
|
|
#pragma aux mulscale16 =\
|
|
"imul ebx",\
|
|
"shrd eax, edx, 16",\
|
|
parm nomemory [eax][ebx]\
|
|
modify exact [eax edx]\
|
|
|
|
#pragma aux mulscale24 =\
|
|
"imul ebx",\
|
|
"shrd eax, edx, 24",\
|
|
parm nomemory [eax][ebx]\
|
|
modify exact [eax edx]\
|
|
|
|
#pragma aux mulscale30 =\
|
|
"imul ebx",\
|
|
"shrd eax, edx, 30",\
|
|
parm nomemory [eax][ebx]\
|
|
modify exact [eax edx]\
|
|
|
|
#pragma aux dmulscale28 =\
|
|
"imul edx",\
|
|
"mov ebx, eax",\
|
|
"mov eax, esi",\
|
|
"mov esi, edx",\
|
|
"imul edi",\
|
|
"add eax, ebx",\
|
|
"adc edx, esi",\
|
|
"shrd eax, edx, 28",\
|
|
parm nomemory [eax][edx][esi][edi]\
|
|
modify exact [eax ebx edx esi]\
|
|
|
|
#pragma aux clearbuf =\
|
|
"snot: mov dword ptr [edi], eax",\
|
|
"add edi, 4",\
|
|
"loop snot",\
|
|
parm [edi][ecx][eax]\
|
|
|
|
#pragma aux copybuf =\
|
|
"snot: mov eax, dword ptr [esi]",\
|
|
"mov dword ptr [edi], eax",\
|
|
"add esi, 4",\
|
|
"add edi, 4",\
|
|
"loop snot",\
|
|
parm [esi][edi][ecx]\
|
|
modify [eax]\
|
|
|
|
#pragma aux koutp =\
|
|
"out dx, al",\
|
|
parm [edx][eax]\
|
|
|
|
#pragma aux koutpw =\
|
|
"out dx, ax",\
|
|
parm [edx][eax]\
|
|
|
|
#pragma aux kinp =\
|
|
"xor eax, eax",\
|
|
"in al, dx",\
|
|
parm [edx]\
|
|
|
|
#pragma aux msqrtasm =\
|
|
"mov eax, 0x40000000",\
|
|
"mov ebx, 0x20000000",\
|
|
"begit: cmp ecx, eax",\
|
|
"jl skip",\
|
|
"sub ecx, eax",\
|
|
"lea eax, [eax+ebx*4]",\
|
|
"skip: sub eax, ebx",\
|
|
"shr eax, 1",\
|
|
"shr ebx, 2",\
|
|
"jnz begit",\
|
|
"cmp ecx, eax",\
|
|
"sbb eax, -1",\
|
|
"shr eax, 1",\
|
|
parm nomemory [ecx]\
|
|
modify exact [eax ebx ecx]
|
|
#endif
|
|
|
|
void initsb(char dadigistat, char damusistat, long dasamplerate, char danumspeakers, char dabytespersample, char daintspersec, char daquality)
|
|
{
|
|
// DDOI - this should probably be stubbed in sdl_driver.c
|
|
#ifdef PLATFORM_DOS
|
|
long i, j, k;
|
|
|
|
digistat = dadigistat;
|
|
musistat = damusistat;
|
|
|
|
if ((digistat == 0) && (musistat != 1))
|
|
return;
|
|
|
|
samplerate = dasamplerate;
|
|
if (samplerate < 6000) samplerate = 6000;
|
|
if (samplerate > 48000) samplerate = 48000;
|
|
numspeakers = danumspeakers;
|
|
if (numspeakers < 1) numspeakers = 1;
|
|
if (numspeakers > 2) numspeakers = 2;
|
|
bytespersample = dabytespersample;
|
|
if (bytespersample < 1) bytespersample = 1;
|
|
if (bytespersample > 2) bytespersample = 2;
|
|
intspersec = daintspersec;
|
|
if (intspersec < 1) intspersec = 1;
|
|
if (intspersec > 120) intspersec = 120;
|
|
kdmqual = daquality;
|
|
if (kdmqual < 0) kdmqual = 0;
|
|
if (kdmqual > 1) kdmqual = 1;
|
|
|
|
switch(digistat)
|
|
{
|
|
case 1:
|
|
getsbset();
|
|
if (resetsb() != 0) { digistat = musistat = 0; break; }
|
|
|
|
sbout(0xe1);
|
|
sbver = (sbin()<<8);
|
|
sbver += sbin();
|
|
|
|
if (sbver < 0x0201) samplerate = min(samplerate,22050);
|
|
if (sbver < 0x0300) numspeakers = 1;
|
|
if (sbver < 0x0400)
|
|
{
|
|
samplerate = min(samplerate,44100>>(numspeakers-1));
|
|
bytespersample = 1;
|
|
}
|
|
|
|
if (bytespersample == 2) sbdma = sbdma16; else sbdma = sbdma8;
|
|
|
|
break;
|
|
case 2:
|
|
findpas(); // If == -1 then print not found & quit
|
|
koutp(0xf8a,128);
|
|
break;
|
|
case 13:
|
|
if (numspeakers == 2) numspeakers = 1;
|
|
if (bytespersample == 2) bytespersample = 1;
|
|
break;
|
|
}
|
|
|
|
bytespertic = (((samplerate/120)+1)&~1);
|
|
sndbufsiz = bytespertic*(120/intspersec);
|
|
|
|
if (sndseg == 0) //Allocate DMA buffer in conventional memory
|
|
{
|
|
if ((sndseg = convallocate(((sndbufsiz<<(bytespersample+numspeakers))+15)>>4)) == 0)
|
|
{
|
|
printf("Could not allocation conventional memory for digitized music\n");
|
|
exit(0);
|
|
}
|
|
sndoffs = (((long)sndseg)<<4);
|
|
|
|
if ((sndoffs&65535)+(sndbufsiz<<(bytespersample+numspeakers-1)) >= 65536) //64K DMA page check
|
|
sndoffs += (sndbufsiz<<(bytespersample+numspeakers-1));
|
|
|
|
sndoffsplc = sndoffs;
|
|
sndoffsxor = sndoffsplc ^ (sndoffsplc+(sndbufsiz<<(bytespersample+numspeakers-2)));
|
|
}
|
|
|
|
j = (((11025L*2093)/samplerate)<<13);
|
|
for(i=1;i<76;i++)
|
|
{
|
|
frqtable[i] = j;
|
|
j = mulscale30(j,1137589835); //(pow(2,1/12)<<30) = 1137589835
|
|
}
|
|
for(i=0;i>=-14;i--) frqtable[i&255] = (frqtable[(i+12)&255]>>1);
|
|
|
|
loadwaves("WAVES.KWV");
|
|
|
|
timecount = notecnt = musicstatus = musicrepeat = 0;
|
|
|
|
clearbuf((void *)(FP_OFF(stemp)),sizeof(stemp)>>2,32768L);
|
|
for(i=0;i<256;i++)
|
|
for(j=0;j<16;j++)
|
|
{
|
|
qualookup[(j<<9)+i] = (((-i)*j+8)>>4);
|
|
qualookup[(j<<9)+i+256] = (((256-i)*j+8)>>4);
|
|
}
|
|
for(i=0;i<(samplerate>>11);i++)
|
|
{
|
|
j = 1536 - (i<<10)/(samplerate>>11);
|
|
fsin(&j);
|
|
ramplookup[i] = ((16384-j)<<1);
|
|
}
|
|
|
|
for(i=0;i<256;i++)
|
|
{
|
|
j = i*90; fsin(&j);
|
|
eff[0][i] = 65536+j/9;
|
|
eff[1][i] = min(58386+((i*(65536-58386))/30),65536);
|
|
eff[2][i] = max(69433+((i*(65536-69433))/30),65536);
|
|
j = (i*2048)/120; fsin(&j);
|
|
eff[3][i] = 65536+(j<<2);
|
|
j = (i*2048)/30; fsin(&j);
|
|
eff[4][i] = 65536+j;
|
|
switch((i>>1)%3)
|
|
{
|
|
case 0: eff[5][i] = 65536; break;
|
|
case 1: eff[5][i] = 65536*330/262; break;
|
|
case 2: eff[5][i] = 65536*392/262; break;
|
|
}
|
|
eff[6][i] = min((i<<16)/120,65536);
|
|
eff[7][i] = max(65536-(i<<16)/120,0);
|
|
}
|
|
|
|
switch(digistat)
|
|
{
|
|
case 1: case 2:
|
|
if (sbirq < 8)
|
|
{
|
|
oldsbhandler = _dos_getvect(sbirq+0x8); //Set new IRQ7 vector
|
|
_disable(); _dos_setvect(sbirq+0x8, sbhandler); _enable();
|
|
koutp(0x21,kinp(0x21) & ~(1<<(sbirq&7)));
|
|
}
|
|
else
|
|
{
|
|
oldsbhandler = _dos_getvect(sbirq+0x68); //Set new SB IRQ vector
|
|
_disable(); _dos_setvect(sbirq+0x68, sbhandler); _enable();
|
|
koutp(0xa1,kinp(0xa1) & ~(1<<(sbirq&7)));
|
|
}
|
|
break;
|
|
}
|
|
|
|
musicoff();
|
|
|
|
if (digistat != 255)
|
|
{
|
|
preparesndbuf();
|
|
if (digistat != 13) preparesndbuf();
|
|
|
|
if ((digistat == 1) || (digistat == 2))
|
|
{
|
|
if (sbdma < 4)
|
|
{
|
|
dmacheckport = (sbdma<<1)+1;
|
|
dmachecksiz = (sndbufsiz<<(bytespersample+numspeakers-1))-1;
|
|
|
|
koutp(0xa,sbdma+4); //Set up DMA REGISTERS
|
|
koutp(0xc,0);
|
|
koutp(0xb,0x58+sbdma); //&H58 - auto-init, &H48 - 1 block only
|
|
koutp(sbdma<<1,sndoffs&255);
|
|
koutp(sbdma<<1,(sndoffs>>8)&255);
|
|
koutp(dmacheckport,dmachecksiz&255);
|
|
koutp(dmacheckport,(dmachecksiz>>8)&255);
|
|
koutp(dmapagenum[sbdma],((sndoffs>>16)&255));
|
|
koutp(0xa,sbdma);
|
|
}
|
|
else
|
|
{
|
|
dmacheckport = ((sbdma&3)<<2)+0xc2;
|
|
dmachecksiz = ((sndbufsiz<<(bytespersample+numspeakers-1))>>1)-1;
|
|
|
|
koutp(0xd4,sbdma); //Set up DMA REGISTERS
|
|
koutp(0xd8,0);
|
|
koutp(0xd6,0x58+(sbdma&3)); //&H58 - auto-init, &H48 - 1 block only
|
|
koutp(dmacheckport-2,(sndoffs>>1)&255);
|
|
koutp(dmacheckport-2,((sndoffs>>1)>>8)&255);
|
|
koutp(dmacheckport,dmachecksiz&255);
|
|
koutp(dmacheckport,(dmachecksiz>>8)&255);
|
|
koutp(dmapagenum[sbdma],((sndoffs>>16)&255));
|
|
koutp(0xd4,sbdma&3);
|
|
}
|
|
}
|
|
|
|
switch(digistat)
|
|
{
|
|
case 1:
|
|
sbout(0xd1); //SB Speaker on
|
|
|
|
if (sbver < 0x0400)
|
|
{
|
|
sbout(0x40); //SB Set speed
|
|
sbout(256-(1000000/(samplerate<<(numspeakers-1))));
|
|
}
|
|
|
|
if (sbver < 0x0200)
|
|
{
|
|
sbout(0x14); //SB 1-shot mode
|
|
i = sndbufsiz-1;
|
|
sbout(i&255);
|
|
sbout((i>>8)&255);
|
|
}
|
|
else
|
|
{
|
|
if (sbver < 0x0400)
|
|
{
|
|
//Set length for auto-init mode
|
|
i = (sndbufsiz<<(numspeakers+bytespersample-2))-1;
|
|
sbout(0x48);
|
|
sbout(i&255);
|
|
sbout((i>>8)&255);
|
|
if (numspeakers == 2) //SB set stereo
|
|
{
|
|
sbmixout(0L,0L);
|
|
sbmixout(0xe,sbmixin(0xe)|2);
|
|
}
|
|
if ((samplerate<<(numspeakers-1)) <= 22050)
|
|
sbout(0x1c); //Start SB interrupts!
|
|
else
|
|
sbout(0x90); //High Speed DMA
|
|
}
|
|
else
|
|
{
|
|
sbout(0x41);
|
|
sbout((samplerate>>8)&255);
|
|
sbout(samplerate&255);
|
|
|
|
sbout(0xc6-((bytespersample-1)<<4));
|
|
sbout(((bytespersample-1)<<4)+((numspeakers-1)<<5));
|
|
i = (sndbufsiz<<(numspeakers-1))-1;
|
|
sbout(i&255);
|
|
sbout((i>>8)&255);
|
|
}
|
|
}
|
|
break;
|
|
case 2:
|
|
koutp(0xf88,128);
|
|
koutp(0xb8a,0);
|
|
|
|
i = (1193180L>>(numspeakers-1)) / samplerate;
|
|
koutp(0x138b,0x36); koutp(0x1388,i&255); koutp(0x1388,i>>8);
|
|
i = (sndbufsiz<<(bytespersample+numspeakers-2));
|
|
koutp(0x138b,0x74); koutp(0x1389,i&255); koutp(0x1389,i>>8);
|
|
|
|
koutp(0x8389,0x3+((bytespersample-1)<<2)); //0x3=8bit/0x7=16bit
|
|
koutp(0xb89,0xdf);
|
|
koutp(0xb8b,0x8);
|
|
koutp(0xf8a,0xd9+((2-numspeakers)<<5)); //0xd9=play/0xc9=record
|
|
koutp(0xb8a,0xe1);
|
|
break;
|
|
case 13:
|
|
samplecount = sndbufsiz;
|
|
pcsndptr = (char *)sndoffs;
|
|
bufferside = 0;
|
|
pcsndbufsiz = sndbufsiz;
|
|
pcrealmodeint = 0;
|
|
|
|
samplediv = 1193280L / samplerate;
|
|
|
|
j = 0;
|
|
for(i=0;i<256;i++)
|
|
{
|
|
//Scale (65536 normal)
|
|
k = mulscale24(j-(samplediv<<7),160000) + (samplediv>>1);
|
|
if (k < 0) k = 0;
|
|
if (k > samplerate) k = samplerate;
|
|
pcsndlookup[i] = (char)(k+1);
|
|
j += samplediv;
|
|
}
|
|
|
|
oldtimerfreq = gettimerval();
|
|
chainbackstart = oldtimerfreq/samplediv;
|
|
chainbackcnt = chainbackstart;
|
|
setuppctimerhandler(sndoffs+sndbufsiz,oldtimerfreq,0L,0L,0L,0L);
|
|
|
|
_disable();
|
|
oldpctimerhandler = _dos_getvect(0x8);
|
|
installbikdmhandlers();
|
|
koutp(0x43,0x34); koutp(0x40,samplediv&255); koutp(0x40,(samplediv>>8)&255);
|
|
koutp(0x43,0x90);
|
|
koutp(97,kinp(97)|3);
|
|
_enable();
|
|
break;
|
|
}
|
|
}
|
|
#else
|
|
fprintf(stderr, "%s line %d; initsb() called\n", __FILE__, __LINE__);
|
|
#endif
|
|
}
|
|
|
|
void getsbset(void)
|
|
{
|
|
char *sbset;
|
|
long i;
|
|
|
|
sbset = getenv("BLASTER");
|
|
|
|
i = 0;
|
|
while (sbset[i] > 0)
|
|
{
|
|
switch(sbset[i])
|
|
{
|
|
case 'A': case 'a':
|
|
i++;
|
|
sbport = 0;
|
|
while (((sbset[i] >= 48) && (sbset[i] <= 57)) ||
|
|
((sbset[i] >= 'A') && (sbset[i] <= 'F')) ||
|
|
((sbset[i] >= 'a') && (sbset[i] <= 'f')))
|
|
{
|
|
sbport *= 16;
|
|
if ((sbset[i] >= 48) && (sbset[i] <= 57)) sbport += sbset[i]-48;
|
|
if ((sbset[i] >= 'A') && (sbset[i] <= 'F')) sbport += sbset[i]-55;
|
|
if ((sbset[i] >= 'a') && (sbset[i] <= 'f')) sbport += sbset[i]-55-32;
|
|
i++;
|
|
}
|
|
break;
|
|
case 'I': case 'i':
|
|
i++;
|
|
sbirq = 0;
|
|
while ((sbset[i] >= 48) && (sbset[i] <= 57))
|
|
{
|
|
sbirq *= 10;
|
|
sbirq += sbset[i]-48;
|
|
i++;
|
|
}
|
|
break;
|
|
case 'D': case 'd':
|
|
i++;
|
|
sbdma8 = 0;
|
|
while ((sbset[i] >= 48) && (sbset[i] <= 57))
|
|
{
|
|
sbdma8 *= 10;
|
|
sbdma8 += sbset[i]-48;
|
|
i++;
|
|
}
|
|
break;
|
|
case 'H': case 'h':
|
|
i++;
|
|
sbdma16 = 0;
|
|
while ((sbset[i] >= 48) && (sbset[i] <= 57))
|
|
{
|
|
sbdma16 *= 10;
|
|
sbdma16 += sbset[i]-48;
|
|
i++;
|
|
}
|
|
break;
|
|
default:
|
|
i++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef PLATFORM_DOS
|
|
void __interrupt __far sbhandler()
|
|
{
|
|
switch(digistat)
|
|
{
|
|
case 1:
|
|
if (sbver < 0x0200)
|
|
{
|
|
sbout(0x14); //SB 1-shot mode
|
|
sbout((sndbufsiz-1)&255);
|
|
sbout(((sndbufsiz-1)>>8)&255);
|
|
kinp(sbport+0xe); //Acknowledge SB
|
|
}
|
|
else
|
|
{
|
|
mixerval = sbmixin(0x82);
|
|
if (mixerval&1) kinp(sbport+0xe); //Acknowledge 8-bit DMA
|
|
if (mixerval&2) kinp(sbport+0xf); //Acknowledge 16-bit DMA
|
|
}
|
|
break;
|
|
case 2:
|
|
if ((kinp(0xb89)&8) > 0) koutp(0xb89,0);
|
|
break;
|
|
}
|
|
if (sbirq >= 8) koutp(0xa0,0x20);
|
|
koutp(0x20,0x20);
|
|
_enable(); preparesndbuf();
|
|
}
|
|
#endif
|
|
|
|
uninitsb()
|
|
{
|
|
#ifdef PLATFORM_DOS
|
|
if ((digistat == 0) && (musistat != 1))
|
|
return;
|
|
|
|
if (digistat != 255)
|
|
{
|
|
if ((digistat == 1) || (digistat == 2)) //Mask off DMA
|
|
{
|
|
if (sbdma < 4) koutp(0xa,sbdma+4); else koutp(0xd4,sbdma);
|
|
}
|
|
|
|
switch(digistat)
|
|
{
|
|
case 1:
|
|
if (sbver >= 0x0400) sbout(0xda-(bytespersample-1));
|
|
resetsb();
|
|
sbout(0xd3); //Turn speaker off
|
|
break;
|
|
case 2:
|
|
koutp(0xb8a,32); //Stop interrupts
|
|
koutp(0xf8a,0x9); //DMA stop
|
|
break;
|
|
case 13:
|
|
koutp(97,kinp(97)&252);
|
|
koutp(0x43,0x34); koutp(0x40,0); koutp(0x40,0);
|
|
koutp(0x43,0xbc);
|
|
uninstallbikdmhandlers();
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (snd != 0) free(snd), snd = 0;
|
|
if (sndseg != 0) convdeallocate(sndseg), sndseg = 0;
|
|
|
|
switch(digistat)
|
|
{
|
|
case 1: case 2:
|
|
if (sbirq < 8)
|
|
{
|
|
koutp(0x21,kinp(0x21) | (1<<(sbirq&7)));
|
|
_disable(); _dos_setvect(sbirq+0x8, oldsbhandler); _enable();
|
|
}
|
|
else
|
|
{
|
|
koutp(0xa1,kinp(0xa1) | (1<<(sbirq&7)));
|
|
_disable(); _dos_setvect(sbirq+0x68, oldsbhandler); _enable();
|
|
}
|
|
break;
|
|
}
|
|
#else
|
|
fprintf (stderr, "%s line %d, uninitsb() called\n",__FILE__,__LINE__);
|
|
#endif
|
|
}
|
|
|
|
void startwave(long wavnum, long dafreq, long davolume1, long davolume2, long dafrqeff, long davoleff, long dapaneff)
|
|
{
|
|
long i, /*j,*/ chanum;
|
|
|
|
if ((davolume1|davolume2) == 0) return;
|
|
|
|
chanum = 0;
|
|
for(i=NUMCHANNELS-1;i>0;i--)
|
|
if (splc[i] > splc[chanum])
|
|
chanum = i;
|
|
|
|
splc[chanum] = 0; //Disable channel temporarily for clean switch
|
|
|
|
if (numspeakers == 1)
|
|
calcvolookupmono(FP_OFF(volookup)+(chanum<<(9+2)),-(davolume1+davolume2)<<6,(davolume1+davolume2)>>1);
|
|
else
|
|
calcvolookupstereo(FP_OFF(volookup)+(chanum<<(9+2)),-(davolume1<<7),davolume1,-(davolume2<<7),davolume2);
|
|
|
|
sinc[chanum] = dafreq;
|
|
svol1[chanum] = davolume1;
|
|
svol2[chanum] = davolume2;
|
|
soff[chanum] = wavoffs[wavnum]+wavleng[wavnum];
|
|
splc[chanum] = -(wavleng[wavnum]<<12); //splc's modified last
|
|
swavenum[chanum] = wavnum;
|
|
frqeff[chanum] = dafrqeff; frqoff[chanum] = 0;
|
|
voleff[chanum] = davoleff; voloff[chanum] = 0;
|
|
paneff[chanum] = dapaneff; panoff[chanum] = 0;
|
|
chanstat[chanum] = 0; sincoffs[chanum] = 0;
|
|
}
|
|
|
|
void setears(long daposx, long daposy, long daxvect, long dayvect)
|
|
{
|
|
globposx = daposx;
|
|
globposy = daposy;
|
|
globxvect = daxvect;
|
|
globyvect = dayvect;
|
|
}
|
|
|
|
void wsayfollow(char *dafilename, long dafreq, long davol, long *daxplc, long *dayplc, char followstat)
|
|
{
|
|
char ch1, ch2, bad;
|
|
long i, wavnum, chanum;
|
|
|
|
if (digistat == 0) return;
|
|
if (davol <= 0) return;
|
|
|
|
for(wavnum=numwaves-1;wavnum>=0;wavnum--)
|
|
{
|
|
bad = 0;
|
|
|
|
i = 0;
|
|
while ((dafilename[i] > 0) && (i < 16))
|
|
{
|
|
ch1 = dafilename[i]; if ((ch1 >= 97) && (ch1 <= 123)) ch1 -= 32;
|
|
ch2 = instname[wavnum][i]; if ((ch2 >= 97) && (ch2 <= 123)) ch2 -= 32;
|
|
if (ch1 != ch2) {bad = 1; break;}
|
|
i++;
|
|
}
|
|
if (bad != 0) continue;
|
|
|
|
chanum = 0;
|
|
for(i=NUMCHANNELS-1;i>0;i--) if (splc[i] > splc[chanum]) chanum = i;
|
|
|
|
splc[chanum] = 0; //Disable channel temporarily for clean switch
|
|
|
|
if (followstat == 0)
|
|
{
|
|
xplc[chanum] = *daxplc;
|
|
yplc[chanum] = *dayplc;
|
|
}
|
|
else
|
|
{
|
|
xplc[chanum] = ((long)daxplc);
|
|
yplc[chanum] = ((long)dayplc);
|
|
}
|
|
vol[chanum] = davol;
|
|
vdist[chanum] = 0;
|
|
sinc[chanum] = (dafreq*11025)/samplerate;
|
|
svol1[chanum] = davol;
|
|
svol2[chanum] = davol;
|
|
sincoffs[chanum] = 0;
|
|
soff[chanum] = wavoffs[wavnum]+wavleng[wavnum];
|
|
splc[chanum] = -(wavleng[wavnum]<<12); //splc's modified last
|
|
swavenum[chanum] = wavnum;
|
|
chanstat[chanum] = followstat+1;
|
|
frqeff[chanum] = 0; frqoff[chanum] = 0;
|
|
voleff[chanum] = 0; voloff[chanum] = 0;
|
|
paneff[chanum] = 0; panoff[chanum] = 0;
|
|
return;
|
|
}
|
|
}
|
|
|
|
void getsndbufinfo(long *dasndoffsplc, long *dasndbufsiz)
|
|
{
|
|
*dasndoffsplc = sndoffsplc;
|
|
*dasndbufsiz = (sndbufsiz<<(bytespersample+numspeakers-2));
|
|
}
|
|
|
|
void preparesndbuf(void)
|
|
{
|
|
long i, j, k, voloffs1, voloffs2, *stempptr;
|
|
long daswave, dasinc, dacnt;
|
|
long ox, oy, x, y;
|
|
//char *sndptr, v1, v2;
|
|
|
|
kdmintinprep++;
|
|
if (kdminprep != 0) return;
|
|
|
|
if ((digistat == 1) || (digistat == 2))
|
|
{
|
|
i = kinp(dmacheckport); i += (kinp(dmacheckport)<<8);
|
|
if (i <= dmachecksiz)
|
|
{
|
|
i = ((i > 32) && (i <= (dmachecksiz>>1)+32));
|
|
if ((sndoffsplc<(sndoffsplc^sndoffsxor)) == i) kdmintinprep++;
|
|
}
|
|
}
|
|
|
|
kdminprep = 1;
|
|
while (kdmintinprep > 0)
|
|
{
|
|
sndoffsplc ^= sndoffsxor;
|
|
|
|
for (i=NUMCHANNELS-1;i>=0;i--)
|
|
if ((splc[i] < 0) && (chanstat[i] > 0))
|
|
{
|
|
if (chanstat[i] == 1)
|
|
{
|
|
ox = xplc[i];
|
|
oy = yplc[i];
|
|
}
|
|
else
|
|
{
|
|
stempptr = (long *)xplc[i]; ox = *stempptr;
|
|
stempptr = (long *)yplc[i]; oy = *stempptr;
|
|
}
|
|
ox -= globposx; oy -= globposy;
|
|
x = dmulscale28(oy,globxvect,-ox,globyvect);
|
|
y = dmulscale28(ox,globxvect,oy,globyvect);
|
|
|
|
if ((klabs(x) >= 32768) || (klabs(y) >= 32768))
|
|
{ splc[i] = 0; continue; }
|
|
|
|
j = vdist[i];
|
|
vdist[i] = msqrtasm(x*x+y*y);
|
|
if (j)
|
|
{
|
|
j = (sinc[i]<<10)/(min(max(vdist[i]-j,-768),768)+1024)-sinc[i];
|
|
sincoffs[i] = ((sincoffs[i]*7+j)>>3);
|
|
}
|
|
|
|
voloffs1 = min((vol[i]<<22)/(((x+1536)*(x+1536)+y*y)+1),255);
|
|
voloffs2 = min((vol[i]<<22)/(((x-1536)*(x-1536)+y*y)+1),255);
|
|
|
|
if (numspeakers == 1)
|
|
calcvolookupmono(FP_OFF(volookup)+(i<<(9+2)),-(voloffs1+voloffs2)<<6,(voloffs1+voloffs2)>>1);
|
|
else
|
|
calcvolookupstereo(FP_OFF(volookup)+(i<<(9+2)),-(voloffs1<<7),voloffs1,-(voloffs2<<7),voloffs2);
|
|
}
|
|
|
|
for(dacnt=0;dacnt<sndbufsiz;dacnt+=bytespertic)
|
|
{
|
|
if (musicstatus > 0) //Gets here 120 times/second
|
|
{
|
|
while ((notecnt < numnotes) && (timecount >= nttime[notecnt]))
|
|
{
|
|
j = trinst[nttrack[notecnt]];
|
|
k = mulscale24(frqtable[ntfreq[notecnt]],finetune[j]+748);
|
|
|
|
if (ntvol1[notecnt] == 0) //Note off
|
|
{
|
|
for(i=NUMCHANNELS-1;i>=0;i--)
|
|
if (splc[i] < 0)
|
|
if (swavenum[i] == j)
|
|
if (sinc[i] == k)
|
|
splc[i] = 0;
|
|
}
|
|
else //Note on
|
|
startwave(j,k,ntvol1[notecnt],ntvol2[notecnt],ntfrqeff[notecnt],ntvoleff[notecnt],ntpaneff[notecnt]);
|
|
|
|
notecnt++;
|
|
if (notecnt >= numnotes)
|
|
if (musicrepeat > 0)
|
|
notecnt = 0, timecount = nttime[0];
|
|
}
|
|
timecount++;
|
|
}
|
|
|
|
for(i=NUMCHANNELS-1;i>=0;i--)
|
|
{
|
|
if (splc[i] >= 0) continue;
|
|
|
|
dasinc = sinc[i]+sincoffs[i];
|
|
|
|
if (frqeff[i] != 0)
|
|
{
|
|
dasinc = mulscale16(dasinc,eff[frqeff[i]-1][frqoff[i]]);
|
|
frqoff[i]++; if (frqoff[i] >= 256) frqeff[i] = 0;
|
|
}
|
|
if ((voleff[i]) || (paneff[i]))
|
|
{
|
|
voloffs1 = svol1[i];
|
|
voloffs2 = svol2[i];
|
|
if (voleff[i])
|
|
{
|
|
voloffs1 = mulscale16(voloffs1,eff[voleff[i]-1][voloff[i]]);
|
|
voloffs2 = mulscale16(voloffs2,eff[voleff[i]-1][voloff[i]]);
|
|
voloff[i]++; if (voloff[i] >= 256) voleff[i] = 0;
|
|
}
|
|
|
|
if (numspeakers == 1)
|
|
calcvolookupmono(FP_OFF(volookup)+(i<<(9+2)),-(voloffs1+voloffs2)<<6,(voloffs1+voloffs2)>>1);
|
|
else
|
|
{
|
|
if (paneff[i])
|
|
{
|
|
voloffs1 = mulscale16(voloffs1,131072-eff[paneff[i]-1][panoff[i]]);
|
|
voloffs2 = mulscale16(voloffs2,eff[paneff[i]-1][panoff[i]]);
|
|
panoff[i]++; if (panoff[i] >= 256) paneff[i] = 0;
|
|
}
|
|
calcvolookupstereo(FP_OFF(volookup)+(i<<(9+2)),-(voloffs1<<7),voloffs1,-(voloffs2<<7),voloffs2);
|
|
}
|
|
}
|
|
|
|
daswave = swavenum[i];
|
|
voloffs1 = FP_OFF(volookup)+(i<<(9+2));
|
|
|
|
kdmasm1 = repleng[daswave];
|
|
kdmasm2 = wavoffs[daswave]+repstart[daswave]+repleng[daswave];
|
|
kdmasm3 = (repleng[daswave]<<12); //repsplcoff
|
|
kdmasm4 = soff[i];
|
|
if (numspeakers == 1)
|
|
{
|
|
if (kdmqual == 0) splc[i] = monolocomb(0L,voloffs1,bytespertic,dasinc,splc[i],FP_OFF(stemp));
|
|
else splc[i] = monohicomb(0L,voloffs1,bytespertic,dasinc,splc[i],FP_OFF(stemp));
|
|
}
|
|
else
|
|
{
|
|
if (kdmqual == 0) splc[i] = stereolocomb(0L,voloffs1,bytespertic,dasinc,splc[i],FP_OFF(stemp));
|
|
else splc[i] = stereohicomb(0L,voloffs1,bytespertic,dasinc,splc[i],FP_OFF(stemp));
|
|
}
|
|
soff[i] = kdmasm4;
|
|
|
|
if ((kdmqual == 0) || (splc[i] >= 0)) continue;
|
|
if (numspeakers == 1)
|
|
{
|
|
if (kdmqual == 0) monolocomb(0L,voloffs1,samplerate>>11,dasinc,splc[i],FP_OFF(stemp)+(bytespertic<<2));
|
|
else monohicomb(0L,voloffs1,samplerate>>11,dasinc,splc[i],FP_OFF(stemp)+(bytespertic<<2));
|
|
}
|
|
else
|
|
{
|
|
if (kdmqual == 0) stereolocomb(0L,voloffs1,samplerate>>11,dasinc,splc[i],FP_OFF(stemp)+(bytespertic<<3));
|
|
else stereohicomb(0L,voloffs1,samplerate>>11,dasinc,splc[i],FP_OFF(stemp)+(bytespertic<<3));
|
|
}
|
|
}
|
|
|
|
if (kdmqual)
|
|
{
|
|
if (numspeakers == 1)
|
|
{
|
|
for(i=(samplerate>>11)-1;i>=0;i--)
|
|
stemp[i] += mulscale16(stemp[i+1024]-stemp[i],ramplookup[i]);
|
|
j = bytespertic; k = (samplerate>>11);
|
|
copybuf(&stemp[j],&stemp[1024],k);
|
|
clearbuf(&stemp[j],k,32768);
|
|
}
|
|
else
|
|
{
|
|
for(i=(samplerate>>11)-1;i>=0;i--)
|
|
{
|
|
j = (i<<1);
|
|
stemp[j+0] += mulscale16(stemp[j+1024]-stemp[j+0],ramplookup[i]);
|
|
stemp[j+1] += mulscale16(stemp[j+1025]-stemp[j+1],ramplookup[i]);
|
|
}
|
|
j = (bytespertic<<1); k = ((samplerate>>11)<<1);
|
|
copybuf(&stemp[j],&stemp[1024],k);
|
|
clearbuf(&stemp[j],k,32768);
|
|
}
|
|
}
|
|
|
|
if (numspeakers == 1)
|
|
{
|
|
if (bytespersample == 1)
|
|
{
|
|
if (digistat == 13) pcbound2char(bytespertic>>1,FP_OFF(stemp),sndoffsplc+dacnt);
|
|
else bound2char(bytespertic>>1,FP_OFF(stemp),sndoffsplc+dacnt);
|
|
} else bound2short(bytespertic>>1,FP_OFF(stemp),sndoffsplc+(dacnt<<1));
|
|
}
|
|
else
|
|
{
|
|
if (bytespersample == 1) bound2char(bytespertic,FP_OFF(stemp),sndoffsplc+(dacnt<<1));
|
|
else bound2short(bytespertic,FP_OFF(stemp),sndoffsplc+(dacnt<<2));
|
|
}
|
|
}
|
|
kdmintinprep--;
|
|
}
|
|
kdminprep = 0;
|
|
}
|
|
|
|
void wsay(char *dafilename, long dafreq, long volume1, long volume2)
|
|
{
|
|
unsigned char ch1, ch2;
|
|
long i, j, bad;
|
|
|
|
if (digistat == 0) return;
|
|
|
|
i = numwaves-1;
|
|
do
|
|
{
|
|
bad = 0;
|
|
|
|
j = 0;
|
|
while ((dafilename[j] > 0) && (j < 16))
|
|
{
|
|
ch1 = dafilename[j]; if ((ch1 >= 97) && (ch1 <= 123)) ch1 -= 32;
|
|
ch2 = instname[i][j]; if ((ch2 >= 97) && (ch2 <= 123)) ch2 -= 32;
|
|
if (ch1 != ch2) {bad = 1; break;}
|
|
j++;
|
|
}
|
|
if (bad == 0)
|
|
{
|
|
startwave(i,(dafreq*11025)/samplerate,volume1,volume2,0L,0L,0L);
|
|
return;
|
|
}
|
|
|
|
i--;
|
|
} while (i >= 0);
|
|
}
|
|
|
|
void loadwaves(char *wavename)
|
|
{
|
|
long fil, i, j, dawaversionum;
|
|
char filename[80];
|
|
|
|
strcpy(filename,wavename);
|
|
if (strstr(filename,".KWV") == 0) strcat(filename,".KWV");
|
|
if ((fil = kopen4load(filename,0)) == -1)
|
|
if (strcmp(filename,"WAVES.KWV") != 0)
|
|
{
|
|
strcpy(filename,"WAVES.KWV");
|
|
fil = kopen4load(filename,0);
|
|
}
|
|
|
|
totsndbytes = 0;
|
|
|
|
if (fil != -1)
|
|
{
|
|
if (strcmp(kwvname,filename) == 0) { kclose(fil); return; }
|
|
strcpy(kwvname,filename);
|
|
|
|
kread(fil,&dawaversionum,4);
|
|
if (dawaversionum != 0) { kclose(fil); return; }
|
|
|
|
kread(fil,&numwaves,4);
|
|
for(i=0;i<numwaves;i++)
|
|
{
|
|
kread(fil,&instname[i][0],16);
|
|
kread(fil,&wavleng[i],4);
|
|
kread(fil,&repstart[i],4);
|
|
kread(fil,&repleng[i],4);
|
|
kread(fil,&finetune[i],4);
|
|
wavoffs[i] = totsndbytes;
|
|
totsndbytes += wavleng[i];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dawaversionum = 0;
|
|
numwaves = 0;
|
|
}
|
|
|
|
for(i=numwaves;i<MAXWAVES;i++)
|
|
{
|
|
for(j=0;j<16;j++) instname[i][j] = 0;
|
|
wavoffs[i] = totsndbytes;
|
|
wavleng[i] = 0L;
|
|
repstart[i] = 0L;
|
|
repleng[i] = 0L;
|
|
finetune[i] = 0L;
|
|
}
|
|
|
|
if (snd == 0)
|
|
{
|
|
if ((snd = (char *)malloc(totsndbytes+2)) == 0)
|
|
{ printf("Not enough memory for digital music!\n"); exit(0); }
|
|
}
|
|
for(i=0;i<MAXWAVES;i++) wavoffs[i] += FP_OFF(snd);
|
|
if (fil != -1)
|
|
{
|
|
kread(fil,snd,totsndbytes);
|
|
kclose(fil);
|
|
}
|
|
snd[totsndbytes] = snd[totsndbytes+1] = 128;
|
|
}
|
|
|
|
int loadsong(char *filename)
|
|
{
|
|
long /*i,*/ fil;
|
|
|
|
if (musistat != 1) return(0);
|
|
musicoff();
|
|
filename = strupr(filename);
|
|
if (strstr(filename,".KDM") == 0) strcat(filename,".KDM");
|
|
if ((fil = kopen4load(filename,0)) == -1)
|
|
{
|
|
printf("I cannot load %s.\n",filename);
|
|
uninitsb();
|
|
return(-1);
|
|
}
|
|
kread(fil,&kdmversionum,4);
|
|
if (kdmversionum != 0) return(-2);
|
|
kread(fil,&numnotes,4);
|
|
kread(fil,&numtracks,4);
|
|
kread(fil,trinst,numtracks);
|
|
kread(fil,trquant,numtracks);
|
|
kread(fil,trvol1,numtracks);
|
|
kread(fil,trvol2,numtracks);
|
|
kread(fil,nttime,numnotes<<2);
|
|
kread(fil,nttrack,numnotes);
|
|
kread(fil,ntfreq,numnotes);
|
|
kread(fil,ntvol1,numnotes);
|
|
kread(fil,ntvol2,numnotes);
|
|
kread(fil,ntfrqeff,numnotes);
|
|
kread(fil,ntvoleff,numnotes);
|
|
kread(fil,ntpaneff,numnotes);
|
|
kclose(fil);
|
|
return(0);
|
|
}
|
|
|
|
void musicon(void)
|
|
{
|
|
if (musistat != 1)
|
|
return;
|
|
|
|
notecnt = 0;
|
|
timecount = nttime[notecnt];
|
|
musicrepeat = 1;
|
|
musicstatus = 1;
|
|
}
|
|
|
|
void musicoff(void)
|
|
{
|
|
long i;
|
|
|
|
musicstatus = 0;
|
|
for(i=0;i<NUMCHANNELS;i++)
|
|
splc[i] = 0;
|
|
musicrepeat = 0;
|
|
timecount = 0;
|
|
notecnt = 0;
|
|
}
|
|
|
|
kdmconvalloc32 (long size)
|
|
{
|
|
#ifdef PLATFORM_DOS
|
|
union REGS r;
|
|
|
|
r.x.eax = 0x0100; //DPMI allocate DOS memory
|
|
r.x.ebx = ((size+15)>>4); //Number of paragraphs requested
|
|
int386(0x31,&r,&r);
|
|
|
|
if (r.x.cflag != 0) //Failed
|
|
return ((long)0);
|
|
return ((long)((r.x.eax&0xffff)<<4)); //Returns full 32-bit offset
|
|
#else
|
|
fprintf (stderr, "%s line %d; kdmconvalloc32() called\n", __FILE__,
|
|
__LINE__);
|
|
#endif
|
|
}
|
|
|
|
installbikdmhandlers()
|
|
{
|
|
#ifdef PLATFORM_DOS
|
|
union REGS r;
|
|
struct SREGS sr;
|
|
long lowp;
|
|
void far *fh;
|
|
|
|
//Get old protected mode handler
|
|
r.x.eax = 0x3500+kdmvect; /* DOS get vector (INT 0Ch) */
|
|
sr.ds = sr.es = 0;
|
|
int386x(0x21,&r,&r,&sr);
|
|
kdmpsel = (unsigned short)sr.es;
|
|
kdmpoff = r.x.ebx;
|
|
|
|
//Get old real mode handler
|
|
r.x.eax = 0x0200; /* DPMI get real mode vector */
|
|
r.h.bl = kdmvect;
|
|
int386(0x31,&r,&r);
|
|
kdmrseg = (unsigned short)r.x.ecx;
|
|
kdmroff = (unsigned short)r.x.edx;
|
|
|
|
|
|
//Allocate memory in low memory to store real mode handler
|
|
if ((lowp = kdmconvalloc32(KDMCODEBYTES)) == 0)
|
|
{
|
|
printf("Can't allocate conventional memory.\n");
|
|
exit;
|
|
}
|
|
memcpy((void *)lowp,(void *)pcrealbuffer,KDMCODEBYTES);
|
|
|
|
//Set new protected mode handler
|
|
r.x.eax = 0x2500+kdmvect; /* DOS set vector (INT 0Ch) */
|
|
fh = (void far *)pctimerhandler;
|
|
r.x.edx = FP_OFF(fh);
|
|
sr.ds = FP_SEG(fh); //DS:EDX == &handler
|
|
sr.es = 0;
|
|
int386x(0x21,&r,&r,&sr);
|
|
|
|
//Set new real mode handler (must be after setting protected mode)
|
|
r.x.eax = 0x0201;
|
|
r.h.bl = kdmvect; //CX:DX == real mode &handler
|
|
r.x.ecx = ((lowp>>4)&0xffff); //D32realseg
|
|
r.x.edx = 0L; //D32realoff
|
|
int386(0x31,&r,&r);
|
|
#else
|
|
fprintf(stderr,"%s line %d; installbikdmhandlers() called\n", __FILE__,
|
|
__LINE__);
|
|
#endif
|
|
}
|
|
|
|
uninstallbikdmhandlers()
|
|
{
|
|
#ifdef PLATFORM_DOS
|
|
union REGS r;
|
|
struct SREGS sr;
|
|
|
|
//restore old protected mode handler
|
|
r.x.eax = 0x2500+kdmvect; /* DOS set vector (INT 0Ch) */
|
|
r.x.edx = kdmpoff;
|
|
sr.ds = kdmpsel; /* DS:EDX == &handler */
|
|
sr.es = 0;
|
|
int386x(0x21,&r,&r,&sr);
|
|
|
|
//restore old real mode handler
|
|
r.x.eax = 0x0201; /* DPMI set real mode vector */
|
|
r.h.bl = kdmvect;
|
|
r.x.ecx = (unsigned long)kdmrseg; //CX:DX == real mode &handler
|
|
r.x.edx = (unsigned long)kdmroff;
|
|
int386(0x31,&r,&r);
|
|
#else
|
|
fprintf(stderr,"%s line %d; uninstallbikdmhandlers() called\n",
|
|
__FILE__, __LINE__);
|
|
#endif
|
|
}
|