1 #include <malloc.h>
2 #include <conio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <stdio.h>
6 #include <dos.h>
7 #include <fcntl.h>
8 #include <io.h>
9 #include <sys\types.h>
10 #include <sys\stat.h>
11 
12 #define NUMCHANNELS 16
13 #define MAXWAVES 256
14 #define MAXTRACKS 256
15 #define MAXNOTES 8192
16 #define MAXEFFECTS 16
17 
18 	//Actual sound parameters after initsb was called
19 long samplerate, numspeakers, bytespersample, intspersec, kdmqual;
20 
21 	//KWV wave variables
22 long numwaves;
23 char instname[MAXWAVES][16];
24 long wavleng[MAXWAVES];
25 long repstart[MAXWAVES], repleng[MAXWAVES];
26 long finetune[MAXWAVES];
27 
28 	//Other useful wave variables
29 long totsndbytes, totsndmem, wavoffs[MAXWAVES];
30 
31 	//Effects array
32 long eff[MAXEFFECTS][256];
33 
34 	//KDM song variables:
35 long kdmversionum, numnotes, numtracks;
36 char trinst[MAXTRACKS], trquant[MAXTRACKS];
37 char trvol1[MAXTRACKS], trvol2[MAXTRACKS];
38 long nttime[MAXNOTES];
39 char nttrack[MAXNOTES], ntfreq[MAXNOTES];
40 char ntvol1[MAXNOTES], ntvol2[MAXNOTES];
41 char ntfrqeff[MAXNOTES], ntvoleff[MAXNOTES], ntpaneff[MAXNOTES];
42 
43 	//Other useful song variables:
44 long timecount, notecnt, musicstatus, musicrepeat;
45 
46 long kdmasm1, kdmasm2, kdmasm3, kdmasm4;
47 
48 static char digistat = 0, musistat = 0;
49 
50 char *snd = NULL, kwvname[20] = {""};
51 
52 #define MAXBYTESPERTIC 1024+128
53 static long stemp[MAXBYTESPERTIC];
54 
55 	//Sound reading information
56 long splc[NUMCHANNELS], sinc[NUMCHANNELS], soff[NUMCHANNELS];
57 long svol1[NUMCHANNELS], svol2[NUMCHANNELS];
58 long volookup[NUMCHANNELS<<9];
59 long swavenum[NUMCHANNELS];
60 long frqeff[NUMCHANNELS], frqoff[NUMCHANNELS];
61 long voleff[NUMCHANNELS], voloff[NUMCHANNELS];
62 long paneff[NUMCHANNELS], panoff[NUMCHANNELS];
63 
64 static long globposx, globposy, globxvect, globyvect;
65 static long xplc[NUMCHANNELS], yplc[NUMCHANNELS], vol[NUMCHANNELS];
66 static long vdist[NUMCHANNELS], sincoffs[NUMCHANNELS];
67 static char chanstat[NUMCHANNELS];
68 
69 long frqtable[256];
70 
71 static long mixerval = 0;
72 
73 static long kdminprep = 0, kdmintinprep = 0;
74 static long dmacheckport, dmachecksiz;
75 
76 void (__interrupt __far *oldsbhandler)();
77 void __interrupt __far sbhandler(void);
78 
79 long samplediv, oldtimerfreq, chainbackcnt, chainbackstart;
80 char *pcsndptr, pcsndlookup[256], bufferside;
81 long samplecount, pcsndbufsiz, pcrealmodeint;
82 static short kdmvect = 0x8;
83 static unsigned short kdmpsel, kdmrseg, kdmroff;
84 static unsigned long kdmpoff;
85 
86 void (__interrupt __far *oldpctimerhandler)();
87 #define KDMCODEBYTES 256
88 static char pcrealbuffer[KDMCODEBYTES] =        //See pckdm.asm
89 {
90 	0x50,0x53,0x51,0x52,0x32,0xC0,0xE6,0x42,0xB0,0x20,
91 	0xE6,0x20,0x5A,0x59,0x5B,0x58,0xCF,
92 };
93 
94 	//Sound interrupt information
95 long sbport = 0x220, sbirq = 0x7, sbdma8 = 0x1, sbdma16 = 0x1;
96 char dmapagenum[8] = {0x87,0x83,0x81,0x82,0x8f,0x8b,0x89,0x8a};
97 long sbdma, sbver;
98 unsigned short sndselector;
99 volatile long sndoffs, sndoffsplc, sndoffsxor, sndplc, sndend;
100 static long bytespertic, sndbufsiz;
101 
102 char qualookup[512*16];
103 long ramplookup[64];
104 
105 unsigned short sndseg = 0;
106 
107 extern long monolocomb(long,long,long,long,long,long);
108 #pragma aux monolocomb parm [eax][ebx][ecx][edx][esi][edi];
109 extern long monohicomb(long,long,long,long,long,long);
110 #pragma aux monohicomb parm [eax][ebx][ecx][edx][esi][edi];
111 extern long stereolocomb(long,long,long,long,long,long);
112 #pragma aux stereolocomb parm [eax][ebx][ecx][edx][esi][edi];
113 extern long stereohicomb(long,long,long,long,long,long);
114 #pragma aux stereohicomb parm [eax][ebx][ecx][edx][esi][edi];
115 extern long setuppctimerhandler(long,long,long,long,long,long);
116 #pragma aux setuppctimerhandler parm [eax][ebx][ecx][edx][esi][edi];
117 extern void interrupt pctimerhandler();
118 extern long pcbound2char(long,long,long);
119 #pragma aux pcbound2char parm [ecx][esi][edi];
120 extern long bound2char(long,long,long);
121 #pragma aux bound2char parm [ecx][esi][edi];
122 extern long bound2short(long,long,long);
123 #pragma aux bound2short parm [ecx][esi][edi];
124 
125 static long oneshr10 = 0x3a800000, oneshl14 = 0x46800000;
126 #pragma aux fsin =\
127 	"fldpi",\
128 	"fimul dword ptr [eax]",\
129 	"fmul dword ptr [oneshr10]",\
130 	"fsin",\
131 	"fmul dword ptr [oneshl14]",\
132 	"fistp dword ptr [eax]",\
133 	parm [eax]\
134 
135 #pragma aux convallocate =\
136 	"mov ax, 0x100",\
137 	"int 0x31",\
138 	"jnc nocarry",\
139 	"mov ax, 0",\
140 	"nocarry: mov sndselector, dx",\
141 	parm [bx]\
142 	modify [eax edx]\
143 
144 #pragma aux convdeallocate =\
145 	"mov ax, 0x101",\
146 	"mov dx, sndselector",\
147 	"int 0x31",\
148 	parm [dx]\
149 	modify [eax edx]\
150 
151 #pragma aux resetsb =\
152 	"mov edx, sbport",\
153 	"add edx, 0x6",\
154 	"mov al, 1",\
155 	"out dx, al",\
156 	"xor al, al",\
157 	"delayreset: dec al",\
158 	"jnz delayreset",\
159 	"out dx, al",\
160 	"mov ecx, 65536",\
161 	"empty: mov edx, sbport",\
162 	"add edx, 0xe",\
163 	"in al, dx",\
164 	"test al, al",\
165 	"jns nextattempt",\
166 	"sub dl, 4",\
167 	"in al, dx",\
168 	"cmp al, 0aah",\
169 	"je resetok",\
170 	"dec ecx",\
171 	"nextattempt: jnz empty",\
172 	"mov eax, -1",\
173 	"jmp resetend",\
174 	"resetok: xor eax, eax",\
175 	"resetend:",\
176 	modify [ebx ecx edx]\
177 
178 #pragma aux sbin =\
179 	"xor eax, eax",\
180 	"mov dx, word ptr sbport[0]",\
181 	"add dl, 0xe",\
182 	"busy: in al, dx",\
183 	"or al, al",\
184 	"jns busy",\
185 	"sub dl, 4",\
186 	"in al, dx",\
187 	modify [edx]\
188 
189 #pragma aux sbout =\
190 	"mov dx, word ptr sbport[0]",\
191 	"add dl, 0xc",\
192 	"mov ah, al",\
193 	"busy: in al, dx",\
194 	"or al, al",\
195 	"js busy",\
196 	"mov al, ah",\
197 	"out dx, al",\
198 	parm [eax]\
199 	modify [edx]\
200 
201 #pragma aux sbmixin =\
202 	"mov dx, word ptr sbport[0]",\
203 	"add dl, 0x4",\
204 	"out dx, al",\
205 	"inc dx",\
206 	"xor eax, eax",\
207 	"in al, dx",\
208 	parm [eax]\
209 	modify [edx]\
210 
211 #pragma aux sbmixout =\
212 	"mov dx, word ptr sbport[0]",\
213 	"add dl, 0x4",\
214 	"out dx, al",\
215 	"inc dx",\
216 	"mov al, bl",\
217 	"out dx, al",\
218 	parm [eax][ebx]\
219 	modify [edx]\
220 
221 #pragma aux findpas =\
222 	"mov eax, 0x0000bc00",\
223 	"mov ebx, 0x00003f3f",\
224 	"int 0x2f",\
225 	"xor bx, cx",\
226 	"xor bx, dx",\
227 	"cmp bx, 0x4d56",\
228 	"stc",\
229 	"jne nopasfound",\
230 	"mov eax, 0x0000bc04",\
231 	"int 0x2f",\
232 	"mov edx, 0x0000ffff",\
233 	"and ebx, edx",\
234 	"and ecx, edx",\
235 	"mov sbdma, ebx",\
236 	"mov sbirq, ecx",\
237 	"clc",\
238 	"nopasfound:",\
239 	"sbb eax, eax",\
240 	modify [eax ebx ecx edx]\
241 
242 #pragma aux calcvolookupmono =\
243 	"mov ecx, 64",\
244 	"lea edx, [eax+ebx]",\
245 	"add ebx, ebx",\
246 	"begit: mov dword ptr [edi], eax",\
247 	"mov dword ptr [edi+4], edx",\
248 	"add eax, ebx",\
249 	"add edx, ebx",\
250 	"mov dword ptr [edi+8], eax",\
251 	"mov dword ptr [edi+12], edx",\
252 	"add eax, ebx",\
253 	"add edx, ebx",\
254 	"add edi, 16",\
255 	"dec ecx",\
256 	"jnz begit",\
257 	parm [edi][eax][ebx]\
258 	modify [ecx edx]\
259 
260 #pragma aux calcvolookupstereo =\
261 	"mov esi, 128",\
262 	"begit: mov dword ptr [edi], eax",\
263 	"mov dword ptr [edi+4], ecx",\
264 	"add eax, ebx",\
265 	"add ecx, edx",\
266 	"mov dword ptr [edi+8], eax",\
267 	"mov dword ptr [edi+12], ecx",\
268 	"add eax, ebx",\
269 	"add ecx, edx",\
270 	"add edi, 16",\
271 	"dec esi",\
272 	"jnz begit",\
273 	parm [edi][eax][ebx][ecx][edx]\
274 	modify [esi]\
275 
276 #pragma aux gettimerval =\
277 	"xor eax, eax",\
278 	"xor ebx, ebx",\
279 	"mov ecx, 65536",\
280 	"xor edx, edx",\
281 	"loopit: mov al, 0x4",\
282 	"out 0x43, al",\
283 	"in al, 0x40",\
284 	"mov dl, al",\
285 	"in al, 0x40",\
286 	"mov dh, al",\
287 	"cmp ebx, edx",\
288 	"dec ecx",\
289 	"ja loopit",\
290 	"jz endit",\
291 	"mov ebx, edx",\
292 	"jmp loopit",\
293 	"endit: mov eax, ebx",\
294 	modify [eax ebx ecx edx]\
295 
296 #pragma aux klabs =\
297 	"test eax, eax",\
298 	"jns skipnegate",\
299 	"neg eax",\
300 	"skipnegate:",\
301 	parm [eax]\
302 
303 #pragma aux mulscale16 =\
304 	"imul ebx",\
305 	"shrd eax, edx, 16",\
306 	parm nomemory [eax][ebx]\
307 	modify exact [eax edx]\
308 
309 #pragma aux mulscale24 =\
310 	"imul ebx",\
311 	"shrd eax, edx, 24",\
312 	parm nomemory [eax][ebx]\
313 	modify exact [eax edx]\
314 
315 #pragma aux mulscale30 =\
316 	"imul ebx",\
317 	"shrd eax, edx, 30",\
318 	parm nomemory [eax][ebx]\
319 	modify exact [eax edx]\
320 
321 #pragma aux dmulscale28 =\
322 	"imul edx",\
323 	"mov ebx, eax",\
324 	"mov eax, esi",\
325 	"mov esi, edx",\
326 	"imul edi",\
327 	"add eax, ebx",\
328 	"adc edx, esi",\
329 	"shrd eax, edx, 28",\
330 	parm nomemory [eax][edx][esi][edi]\
331 	modify exact [eax ebx edx esi]\
332 
333 #pragma aux clearbuf =\
334 	"snot: mov dword ptr [edi], eax",\
335 	"add edi, 4",\
336 	"loop snot",\
337 	parm [edi][ecx][eax]\
338 
339 #pragma aux copybuf =\
340 	"snot: mov eax, dword ptr [esi]",\
341 	"mov dword ptr [edi], eax",\
342 	"add esi, 4",\
343 	"add edi, 4",\
344 	"loop snot",\
345 	parm [esi][edi][ecx]\
346 	modify [eax]\
347 
348 #pragma aux koutp =\
349 	"out dx, al",\
350 	parm [edx][eax]\
351 
352 #pragma aux koutpw =\
353 	"out dx, ax",\
354 	parm [edx][eax]\
355 
356 #pragma aux kinp =\
357 	"xor eax, eax",\
358 	"in al, dx",\
359 	parm [edx]\
360 
361 #pragma aux msqrtasm =\
362 	"mov eax, 0x40000000",\
363 	"mov ebx, 0x20000000",\
364 	"begit: cmp ecx, eax",\
365 	"jl skip",\
366 	"sub ecx, eax",\
367 	"lea eax, [eax+ebx*4]",\
368 	"skip: sub eax, ebx",\
369 	"shr eax, 1",\
370 	"shr ebx, 2",\
371 	"jnz begit",\
372 	"cmp ecx, eax",\
373 	"sbb eax, -1",\
374 	"shr eax, 1",\
375 	parm nomemory [ecx]\
376 	modify exact [eax ebx ecx]\
377 
initsb(char dadigistat,char damusistat,long dasamplerate,char danumspeakers,char dabytespersample,char daintspersec,char daquality)378 initsb(char dadigistat, char damusistat, long dasamplerate, char danumspeakers, char dabytespersample, char daintspersec, char daquality)
379 {
380 	long i, j, k;
381 
382 	digistat = dadigistat;
383 	musistat = damusistat;
384 
385 	if ((digistat == 0) && (musistat != 1))
386 		return;
387 
388 	samplerate = dasamplerate;
389 	if (samplerate < 6000) samplerate = 6000;
390 	if (samplerate > 48000) samplerate = 48000;
391 	numspeakers = danumspeakers;
392 	if (numspeakers < 1) numspeakers = 1;
393 	if (numspeakers > 2) numspeakers = 2;
394 	bytespersample = dabytespersample;
395 	if (bytespersample < 1) bytespersample = 1;
396 	if (bytespersample > 2) bytespersample = 2;
397 	intspersec = daintspersec;
398 	if (intspersec < 1) intspersec = 1;
399 	if (intspersec > 120) intspersec = 120;
400 	kdmqual = daquality;
401 	if (kdmqual < 0) kdmqual = 0;
402 	if (kdmqual > 1) kdmqual = 1;
403 
404 	switch(digistat)
405 	{
406 		case 1:
407 			getsbset();
408 			if (resetsb() != 0) { digistat = musistat = 0; break; }
409 
410 			sbout(0xe1);
411 			sbver = (sbin()<<8);
412 			sbver += sbin();
413 
414 			if (sbver < 0x0201) samplerate = min(samplerate,22050);
415 			if (sbver < 0x0300) numspeakers = 1;
416 			if (sbver < 0x0400)
417 			{
418 				samplerate = min(samplerate,44100>>(numspeakers-1));
419 				bytespersample = 1;
420 			}
421 
422 			if (bytespersample == 2) sbdma = sbdma16; else sbdma = sbdma8;
423 
424 			break;
425 		case 2:
426 			findpas();        // If == -1 then print not found & quit
427 			koutp(0xf8a,128);
428 			break;
429 		case 13:
430 			if (numspeakers == 2) numspeakers = 1;
431 			if (bytespersample == 2) bytespersample = 1;
432 			break;
433 	}
434 
435 	bytespertic = (((samplerate/120)+1)&~1);
436 	sndbufsiz = bytespertic*(120/intspersec);
437 
438 	if (sndseg == 0)    //Allocate DMA buffer in conventional memory
439 	{
440 		if ((sndseg = convallocate(((sndbufsiz<<(bytespersample+numspeakers))+15)>>4)) == 0)
441 		{
442 			printf("Could not allocation conventional memory for digitized music\n");
443 			exit(0);
444 		}
445 		sndoffs = (((long)sndseg)<<4);
446 
447 		if ((sndoffs&65535)+(sndbufsiz<<(bytespersample+numspeakers-1)) >= 65536)   //64K DMA page check
448 			sndoffs += (sndbufsiz<<(bytespersample+numspeakers-1));
449 
450 		sndoffsplc = sndoffs;
451 		sndoffsxor = sndoffsplc ^ (sndoffsplc+(sndbufsiz<<(bytespersample+numspeakers-2)));
452 	}
453 
454 	j = (((11025L*2093)/samplerate)<<13);
455 	for(i=1;i<76;i++)
456 	{
457 		frqtable[i] = j;
458 		j = mulscale30(j,1137589835);  //(pow(2,1/12)<<30) = 1137589835
459 	}
460 	for(i=0;i>=-14;i--) frqtable[i&255] = (frqtable[(i+12)&255]>>1);
461 
462 	loadwaves("WAVES.KWV");
463 
464 	timecount = notecnt = musicstatus = musicrepeat = 0;
465 
466 	clearbuf(FP_OFF(stemp),sizeof(stemp)>>2,32768L);
467 	for(i=0;i<256;i++)
468 		for(j=0;j<16;j++)
469 		{
470 			qualookup[(j<<9)+i] = (((-i)*j+8)>>4);
471 			qualookup[(j<<9)+i+256] = (((256-i)*j+8)>>4);
472 		}
473 	for(i=0;i<(samplerate>>11);i++)
474 	{
475 		j = 1536 - (i<<10)/(samplerate>>11);
476 		fsin(&j);
477 		ramplookup[i] = ((16384-j)<<1);
478 	}
479 
480 	for(i=0;i<256;i++)
481 	{
482 		j = i*90; fsin(&j);
483 		eff[0][i] = 65536+j/9;
484 		eff[1][i] = min(58386+((i*(65536-58386))/30),65536);
485 		eff[2][i] = max(69433+((i*(65536-69433))/30),65536);
486 		j = (i*2048)/120; fsin(&j);
487 		eff[3][i] = 65536+(j<<2);
488 		j = (i*2048)/30; fsin(&j);
489 		eff[4][i] = 65536+j;
490 		switch((i>>1)%3)
491 		{
492 			case 0: eff[5][i] = 65536; break;
493 			case 1: eff[5][i] = 65536*330/262; break;
494 			case 2: eff[5][i] = 65536*392/262; break;
495 		}
496 		eff[6][i] = min((i<<16)/120,65536);
497 		eff[7][i] = max(65536-(i<<16)/120,0);
498 	}
499 
500 	switch(digistat)
501 	{
502 		case 1: case 2:
503 			if (sbirq < 8)
504 			{
505 				oldsbhandler = _dos_getvect(sbirq+0x8);           //Set new IRQ7 vector
506 				_disable(); _dos_setvect(sbirq+0x8, sbhandler); _enable();
507 				koutp(0x21,kinp(0x21) & ~(1<<(sbirq&7)));
508 			}
509 			else
510 			{
511 				oldsbhandler = _dos_getvect(sbirq+0x68);    //Set new SB IRQ vector
512 				_disable(); _dos_setvect(sbirq+0x68, sbhandler); _enable();
513 				koutp(0xa1,kinp(0xa1) & ~(1<<(sbirq&7)));
514 			}
515 			break;
516 	}
517 
518 	musicoff();
519 
520 	if (digistat != 255)
521 	{
522 		preparesndbuf();
523 		if (digistat != 13) preparesndbuf();
524 
525 		if ((digistat == 1) || (digistat == 2))
526 		{
527 			if (sbdma < 4)
528 			{
529 				dmacheckport = (sbdma<<1)+1;
530 				dmachecksiz = (sndbufsiz<<(bytespersample+numspeakers-1))-1;
531 
532 				koutp(0xa,sbdma+4);             //Set up DMA REGISTERS
533 				koutp(0xc,0);
534 				koutp(0xb,0x58+sbdma);          //&H58 - auto-init, &H48 - 1 block only
535 				koutp(sbdma<<1,sndoffs&255);
536 				koutp(sbdma<<1,(sndoffs>>8)&255);
537 				koutp(dmacheckport,dmachecksiz&255);
538 				koutp(dmacheckport,(dmachecksiz>>8)&255);
539 				koutp(dmapagenum[sbdma],((sndoffs>>16)&255));
540 				koutp(0xa,sbdma);
541 			}
542 			else
543 			{
544 				dmacheckport = ((sbdma&3)<<2)+0xc2;
545 				dmachecksiz = ((sndbufsiz<<(bytespersample+numspeakers-1))>>1)-1;
546 
547 				koutp(0xd4,sbdma);               //Set up DMA REGISTERS
548 				koutp(0xd8,0);
549 				koutp(0xd6,0x58+(sbdma&3));      //&H58 - auto-init, &H48 - 1 block only
550 				koutp(dmacheckport-2,(sndoffs>>1)&255);
551 				koutp(dmacheckport-2,((sndoffs>>1)>>8)&255);
552 				koutp(dmacheckport,dmachecksiz&255);
553 				koutp(dmacheckport,(dmachecksiz>>8)&255);
554 				koutp(dmapagenum[sbdma],((sndoffs>>16)&255));
555 				koutp(0xd4,sbdma&3);
556 			}
557 		}
558 
559 		switch(digistat)
560 		{
561 			case 1:
562 				sbout(0xd1);                                    //SB Speaker on
563 
564 				if (sbver < 0x0400)
565 				{
566 					sbout(0x40);                            //SB Set speed
567 					sbout(256-(1000000/(samplerate<<(numspeakers-1))));
568 				}
569 
570 				if (sbver < 0x0200)
571 				{
572 					sbout(0x14);                                 //SB 1-shot mode
573 					i = sndbufsiz-1;
574 					sbout(i&255);
575 					sbout((i>>8)&255);
576 				}
577 				else
578 				{
579 					if (sbver < 0x0400)
580 					{
581 							//Set length for auto-init mode
582 						i = (sndbufsiz<<(numspeakers+bytespersample-2))-1;
583 						sbout(0x48);
584 						sbout(i&255);
585 						sbout((i>>8)&255);
586 						if (numspeakers == 2)                   //SB set stereo
587 						{
588 							sbmixout(0L,0L);
589 							sbmixout(0xe,sbmixin(0xe)|2);
590 						}
591 						if ((samplerate<<(numspeakers-1)) <= 22050)
592 							sbout(0x1c);                         //Start SB interrupts!
593 						else
594 							sbout(0x90);                         //High Speed DMA
595 					}
596 					else
597 					{
598 						sbout(0x41);
599 						sbout((samplerate>>8)&255);
600 						sbout(samplerate&255);
601 
602 						sbout(0xc6-((bytespersample-1)<<4));
603 						sbout(((bytespersample-1)<<4)+((numspeakers-1)<<5));
604 						i = (sndbufsiz<<(numspeakers-1))-1;
605 						sbout(i&255);
606 						sbout((i>>8)&255);
607 					}
608 				}
609 				break;
610 			case 2:
611 				koutp(0xf88,128);
612 				koutp(0xb8a,0);
613 
614 				i = (1193180L>>(numspeakers-1)) / samplerate;
615 				koutp(0x138b,0x36); koutp(0x1388,i&255); koutp(0x1388,i>>8);
616 				i = (sndbufsiz<<(bytespersample+numspeakers-2));
617 				koutp(0x138b,0x74); koutp(0x1389,i&255); koutp(0x1389,i>>8);
618 
619 				koutp(0x8389,0x3+((bytespersample-1)<<2)); //0x3=8bit/0x7=16bit
620 				koutp(0xb89,0xdf);
621 				koutp(0xb8b,0x8);
622 				koutp(0xf8a,0xd9+((2-numspeakers)<<5));    //0xd9=play/0xc9=record
623 				koutp(0xb8a,0xe1);
624 				break;
625 			case 13:
626 				samplecount = sndbufsiz;
627 				pcsndptr = (char *)sndoffs;
628 				bufferside = 0;
629 				pcsndbufsiz = sndbufsiz;
630 				pcrealmodeint = 0;
631 
632 				samplediv = 1193280L / samplerate;
633 
634 				j = 0;
635 				for(i=0;i<256;i++)
636 				{
637 						 //Scale (65536 normal)
638 					k = mulscale24(j-(samplediv<<7),160000) + (samplediv>>1);
639 					if (k < 0) k = 0;
640 					if (k > samplerate) k = samplerate;
641 					pcsndlookup[i] = (char)(k+1);
642 					j += samplediv;
643 				}
644 
645 				oldtimerfreq = gettimerval();
646 				chainbackstart = oldtimerfreq/samplediv;
647 				chainbackcnt = chainbackstart;
648 				setuppctimerhandler(sndoffs+sndbufsiz,oldtimerfreq,0L,0L,0L,0L);
649 
650 				_disable();
651 				oldpctimerhandler = _dos_getvect(0x8);
652 				installbikdmhandlers();
653 				koutp(0x43,0x34); koutp(0x40,samplediv&255); koutp(0x40,(samplediv>>8)&255);
654 				koutp(0x43,0x90);
655 				koutp(97,kinp(97)|3);
656 				_enable();
657 				break;
658 		}
659 	}
660 }
661 
getsbset()662 getsbset()
663 {
664 	char *sbset;
665 	long i;
666 
667 	sbset = getenv("BLASTER");
668 
669 	i = 0;
670 	while (sbset[i] > 0)
671 	{
672 		switch(sbset[i])
673 		{
674 			case 'A': case 'a':
675 				i++;
676 				sbport = 0;
677 				while (((sbset[i] >= 48) && (sbset[i] <= 57)) ||
678 						 ((sbset[i] >= 'A') && (sbset[i] <= 'F')) ||
679 						 ((sbset[i] >= 'a') && (sbset[i] <= 'f')))
680 				{
681 					sbport *= 16;
682 					if ((sbset[i] >= 48) && (sbset[i] <= 57)) sbport += sbset[i]-48;
683 					if ((sbset[i] >= 'A') && (sbset[i] <= 'F')) sbport += sbset[i]-55;
684 					if ((sbset[i] >= 'a') && (sbset[i] <= 'f')) sbport += sbset[i]-55-32;
685 					i++;
686 				}
687 				break;
688 			case 'I': case 'i':
689 				i++;
690 				sbirq = 0;
691 				while ((sbset[i] >= 48) && (sbset[i] <= 57))
692 				{
693 					sbirq *= 10;
694 					sbirq += sbset[i]-48;
695 					i++;
696 				}
697 				break;
698 			case 'D': case 'd':
699 				i++;
700 				sbdma8 = 0;
701 				while ((sbset[i] >= 48) && (sbset[i] <= 57))
702 				{
703 					sbdma8 *= 10;
704 					sbdma8 += sbset[i]-48;
705 					i++;
706 				}
707 				break;
708 			case 'H': case 'h':
709 				i++;
710 				sbdma16 = 0;
711 				while ((sbset[i] >= 48) && (sbset[i] <= 57))
712 				{
713 					sbdma16 *= 10;
714 					sbdma16 += sbset[i]-48;
715 					i++;
716 				}
717 				break;
718 			default:
719 				i++;
720 				break;
721 		}
722 	}
723 }
724 
sbhandler()725 void __interrupt __far sbhandler()
726 {
727 	switch(digistat)
728 	{
729 		case 1:
730 			if (sbver < 0x0200)
731 			{
732 				sbout(0x14);                           //SB 1-shot mode
733 				sbout((sndbufsiz-1)&255);
734 				sbout(((sndbufsiz-1)>>8)&255);
735 				kinp(sbport+0xe);                      //Acknowledge SB
736 			}
737 			else
738 			{
739 				mixerval = sbmixin(0x82);
740 				if (mixerval&1) kinp(sbport+0xe);      //Acknowledge 8-bit DMA
741 				if (mixerval&2) kinp(sbport+0xf);      //Acknowledge 16-bit DMA
742 			}
743 			break;
744 		case 2:
745 			if ((kinp(0xb89)&8) > 0) koutp(0xb89,0);
746 			break;
747 	}
748 	if (sbirq >= 8) koutp(0xa0,0x20);
749 	koutp(0x20,0x20);
750 	_enable(); preparesndbuf();
751 }
752 
uninitsb()753 uninitsb()
754 {
755 	if ((digistat == 0) && (musistat != 1))
756 		return;
757 
758 	if (digistat != 255)
759 	{
760 		if ((digistat == 1) || (digistat == 2))  //Mask off DMA
761 		{
762 			if (sbdma < 4) koutp(0xa,sbdma+4); else koutp(0xd4,sbdma);
763 		}
764 
765 		switch(digistat)
766 		{
767 			case 1:
768 				if (sbver >= 0x0400) sbout(0xda-(bytespersample-1));
769 				resetsb();
770 				sbout(0xd3);                           //Turn speaker off
771 				break;
772 			case 2:
773 				koutp(0xb8a,32);                       //Stop interrupts
774 				koutp(0xf8a,0x9);                      //DMA stop
775 				break;
776 			case 13:
777 				koutp(97,kinp(97)&252);
778 				koutp(0x43,0x34); koutp(0x40,0); koutp(0x40,0);
779 				koutp(0x43,0xbc);
780 				uninstallbikdmhandlers();
781 				break;
782 		}
783 	}
784 
785 	if (snd != 0) free(snd), snd = 0;
786 	if (sndseg != 0) convdeallocate(sndseg), sndseg = 0;
787 
788 	switch(digistat)
789 	{
790 		case 1: case 2:
791 			if (sbirq < 8)
792 			{
793 				koutp(0x21,kinp(0x21) | (1<<(sbirq&7)));
794 				_disable(); _dos_setvect(sbirq+0x8, oldsbhandler); _enable();
795 			}
796 			else
797 			{
798 				koutp(0xa1,kinp(0xa1) | (1<<(sbirq&7)));
799 				_disable(); _dos_setvect(sbirq+0x68, oldsbhandler); _enable();
800 			}
801 			break;
802 	}
803 }
804 
startwave(long wavnum,long dafreq,long davolume1,long davolume2,long dafrqeff,long davoleff,long dapaneff)805 startwave(long wavnum, long dafreq, long davolume1, long davolume2, long dafrqeff, long davoleff, long dapaneff)
806 {
807 	long i, j, chanum;
808 
809 	if ((davolume1|davolume2) == 0) return;
810 
811 	chanum = 0;
812 	for(i=NUMCHANNELS-1;i>0;i--)
813 		if (splc[i] > splc[chanum])
814 			chanum = i;
815 
816 	splc[chanum] = 0;     //Disable channel temporarily for clean switch
817 
818 	if (numspeakers == 1)
819 		calcvolookupmono(FP_OFF(volookup)+(chanum<<(9+2)),-(davolume1+davolume2)<<6,(davolume1+davolume2)>>1);
820 	else
821 		calcvolookupstereo(FP_OFF(volookup)+(chanum<<(9+2)),-(davolume1<<7),davolume1,-(davolume2<<7),davolume2);
822 
823 	sinc[chanum] = dafreq;
824 	svol1[chanum] = davolume1;
825 	svol2[chanum] = davolume2;
826 	soff[chanum] = wavoffs[wavnum]+wavleng[wavnum];
827 	splc[chanum] = -(wavleng[wavnum]<<12);              //splc's modified last
828 	swavenum[chanum] = wavnum;
829 	frqeff[chanum] = dafrqeff; frqoff[chanum] = 0;
830 	voleff[chanum] = davoleff; voloff[chanum] = 0;
831 	paneff[chanum] = dapaneff; panoff[chanum] = 0;
832 	chanstat[chanum] = 0; sincoffs[chanum] = 0;
833 }
834 
setears(long daposx,long daposy,long daxvect,long dayvect)835 setears(long daposx, long daposy, long daxvect, long dayvect)
836 {
837 	globposx = daposx;
838 	globposy = daposy;
839 	globxvect = daxvect;
840 	globyvect = dayvect;
841 }
842 
wsayfollow(char * dafilename,long dafreq,long davol,long * daxplc,long * dayplc,char followstat)843 wsayfollow(char *dafilename, long dafreq, long davol, long *daxplc, long *dayplc, char followstat)
844 {
845 	char ch1, ch2, bad;
846 	long i, wavnum, chanum;
847 
848 	if (digistat == 0) return;
849 	if (davol <= 0) return;
850 
851 	for(wavnum=numwaves-1;wavnum>=0;wavnum--)
852 	{
853 		bad = 0;
854 
855 		i = 0;
856 		while ((dafilename[i] > 0) && (i < 16))
857 		{
858 			ch1 = dafilename[i]; if ((ch1 >= 97) && (ch1 <= 123)) ch1 -= 32;
859 			ch2 = instname[wavnum][i]; if ((ch2 >= 97) && (ch2 <= 123)) ch2 -= 32;
860 			if (ch1 != ch2) {bad = 1; break;}
861 			i++;
862 		}
863 		if (bad != 0) continue;
864 
865 		chanum = 0;
866 		for(i=NUMCHANNELS-1;i>0;i--) if (splc[i] > splc[chanum]) chanum = i;
867 
868 		splc[chanum] = 0;     //Disable channel temporarily for clean switch
869 
870 		if (followstat == 0)
871 		{
872 			xplc[chanum] = *daxplc;
873 			yplc[chanum] = *dayplc;
874 		}
875 		else
876 		{
877 			xplc[chanum] = ((long)daxplc);
878 			yplc[chanum] = ((long)dayplc);
879 		}
880 		vol[chanum] = davol;
881 		vdist[chanum] = 0;
882 		sinc[chanum] = (dafreq*11025)/samplerate;
883 		svol1[chanum] = davol;
884 		svol2[chanum] = davol;
885 		sincoffs[chanum] = 0;
886 		soff[chanum] = wavoffs[wavnum]+wavleng[wavnum];
887 		splc[chanum] = -(wavleng[wavnum]<<12);              //splc's modified last
888 		swavenum[chanum] = wavnum;
889 		chanstat[chanum] = followstat+1;
890 		frqeff[chanum] = 0; frqoff[chanum] = 0;
891 		voleff[chanum] = 0; voloff[chanum] = 0;
892 		paneff[chanum] = 0; panoff[chanum] = 0;
893 		return;
894 	}
895 }
896 
getsndbufinfo(long * dasndoffsplc,long * dasndbufsiz)897 getsndbufinfo(long *dasndoffsplc, long *dasndbufsiz)
898 {
899 	*dasndoffsplc = sndoffsplc;
900 	*dasndbufsiz = (sndbufsiz<<(bytespersample+numspeakers-2));
901 }
902 
preparesndbuf()903 preparesndbuf()
904 {
905 	long i, j, k, voloffs1, voloffs2, *stempptr;
906 	long daswave, dasinc, dacnt;
907 	long ox, oy, x, y;
908 	char *sndptr, v1, v2;
909 
910 	kdmintinprep++;
911 	if (kdminprep != 0) return;
912 
913 	if ((digistat == 1) || (digistat == 2))
914 	{
915 		i = kinp(dmacheckport); i += (kinp(dmacheckport)<<8);
916 		if (i <= dmachecksiz)
917 		{
918 			i = ((i > 32) && (i <= (dmachecksiz>>1)+32));
919 			if ((sndoffsplc<(sndoffsplc^sndoffsxor)) == i) kdmintinprep++;
920 		}
921 	}
922 
923 	kdminprep = 1;
924 	while (kdmintinprep > 0)
925 	{
926 		sndoffsplc ^= sndoffsxor;
927 
928 		for (i=NUMCHANNELS-1;i>=0;i--)
929 			if ((splc[i] < 0) && (chanstat[i] > 0))
930 			{
931 				if (chanstat[i] == 1)
932 				{
933 					ox = xplc[i];
934 					oy = yplc[i];
935 				}
936 				else
937 				{
938 					stempptr = (long *)xplc[i]; ox = *stempptr;
939 					stempptr = (long *)yplc[i]; oy = *stempptr;
940 				}
941 				ox -= globposx; oy -= globposy;
942 				x = dmulscale28(oy,globxvect,-ox,globyvect);
943 				y = dmulscale28(ox,globxvect,oy,globyvect);
944 
945 				if ((klabs(x) >= 32768) || (klabs(y) >= 32768))
946 					{ splc[i] = 0; continue; }
947 
948 				j = vdist[i];
949 				vdist[i] = msqrtasm(x*x+y*y);
950 				if (j)
951 				{
952 					j = (sinc[i]<<10)/(min(max(vdist[i]-j,-768),768)+1024)-sinc[i];
953 					sincoffs[i] = ((sincoffs[i]*7+j)>>3);
954 				}
955 
956 				voloffs1 = min((vol[i]<<22)/(((x+1536)*(x+1536)+y*y)+1),255);
957 				voloffs2 = min((vol[i]<<22)/(((x-1536)*(x-1536)+y*y)+1),255);
958 
959 				if (numspeakers == 1)
960 					calcvolookupmono(FP_OFF(volookup)+(i<<(9+2)),-(voloffs1+voloffs2)<<6,(voloffs1+voloffs2)>>1);
961 				else
962 					calcvolookupstereo(FP_OFF(volookup)+(i<<(9+2)),-(voloffs1<<7),voloffs1,-(voloffs2<<7),voloffs2);
963 			}
964 
965 		for(dacnt=0;dacnt<sndbufsiz;dacnt+=bytespertic)
966 		{
967 			if (musicstatus > 0)    //Gets here 120 times/second
968 			{
969 				while ((notecnt < numnotes) && (timecount >= nttime[notecnt]))
970 				{
971 					j = trinst[nttrack[notecnt]];
972 					k = mulscale24(frqtable[ntfreq[notecnt]],finetune[j]+748);
973 
974 					if (ntvol1[notecnt] == 0)   //Note off
975 					{
976 						for(i=NUMCHANNELS-1;i>=0;i--)
977 							if (splc[i] < 0)
978 								if (swavenum[i] == j)
979 									if (sinc[i] == k)
980 										splc[i] = 0;
981 					}
982 					else                        //Note on
983 						startwave(j,k,ntvol1[notecnt],ntvol2[notecnt],ntfrqeff[notecnt],ntvoleff[notecnt],ntpaneff[notecnt]);
984 
985 					notecnt++;
986 					if (notecnt >= numnotes)
987 						if (musicrepeat > 0)
988 							notecnt = 0, timecount = nttime[0];
989 				}
990 				timecount++;
991 			}
992 
993 			for(i=NUMCHANNELS-1;i>=0;i--)
994 			{
995 				if (splc[i] >= 0) continue;
996 
997 				dasinc = sinc[i]+sincoffs[i];
998 
999 				if (frqeff[i] != 0)
1000 				{
1001 					dasinc = mulscale16(dasinc,eff[frqeff[i]-1][frqoff[i]]);
1002 					frqoff[i]++; if (frqoff[i] >= 256) frqeff[i] = 0;
1003 				}
1004 				if ((voleff[i]) || (paneff[i]))
1005 				{
1006 					voloffs1 = svol1[i];
1007 					voloffs2 = svol2[i];
1008 					if (voleff[i])
1009 					{
1010 						voloffs1 = mulscale16(voloffs1,eff[voleff[i]-1][voloff[i]]);
1011 						voloffs2 = mulscale16(voloffs2,eff[voleff[i]-1][voloff[i]]);
1012 						voloff[i]++; if (voloff[i] >= 256) voleff[i] = 0;
1013 					}
1014 
1015 					if (numspeakers == 1)
1016 						calcvolookupmono(FP_OFF(volookup)+(i<<(9+2)),-(voloffs1+voloffs2)<<6,(voloffs1+voloffs2)>>1);
1017 					else
1018 					{
1019 						if (paneff[i])
1020 						{
1021 							voloffs1 = mulscale16(voloffs1,131072-eff[paneff[i]-1][panoff[i]]);
1022 							voloffs2 = mulscale16(voloffs2,eff[paneff[i]-1][panoff[i]]);
1023 							panoff[i]++; if (panoff[i] >= 256) paneff[i] = 0;
1024 						}
1025 						calcvolookupstereo(FP_OFF(volookup)+(i<<(9+2)),-(voloffs1<<7),voloffs1,-(voloffs2<<7),voloffs2);
1026 					}
1027 				}
1028 
1029 				daswave = swavenum[i];
1030 				voloffs1 = FP_OFF(volookup)+(i<<(9+2));
1031 
1032 				kdmasm1 = repleng[daswave];
1033 				kdmasm2 = wavoffs[daswave]+repstart[daswave]+repleng[daswave];
1034 				kdmasm3 = (repleng[daswave]<<12); //repsplcoff
1035 				kdmasm4 = soff[i];
1036 				if (numspeakers == 1)
1037 				{
1038 					if (kdmqual == 0) splc[i] = monolocomb(0L,voloffs1,bytespertic,dasinc,splc[i],FP_OFF(stemp));
1039 									 else splc[i] = monohicomb(0L,voloffs1,bytespertic,dasinc,splc[i],FP_OFF(stemp));
1040 				}
1041 				else
1042 				{
1043 					if (kdmqual == 0) splc[i] = stereolocomb(0L,voloffs1,bytespertic,dasinc,splc[i],FP_OFF(stemp));
1044 									 else splc[i] = stereohicomb(0L,voloffs1,bytespertic,dasinc,splc[i],FP_OFF(stemp));
1045 				}
1046 				soff[i] = kdmasm4;
1047 
1048 				if ((kdmqual == 0) || (splc[i] >= 0)) continue;
1049 				if (numspeakers == 1)
1050 				{
1051 					if (kdmqual == 0) monolocomb(0L,voloffs1,samplerate>>11,dasinc,splc[i],FP_OFF(stemp)+(bytespertic<<2));
1052 									 else monohicomb(0L,voloffs1,samplerate>>11,dasinc,splc[i],FP_OFF(stemp)+(bytespertic<<2));
1053 				}
1054 				else
1055 				{
1056 					if (kdmqual == 0) stereolocomb(0L,voloffs1,samplerate>>11,dasinc,splc[i],FP_OFF(stemp)+(bytespertic<<3));
1057 									 else stereohicomb(0L,voloffs1,samplerate>>11,dasinc,splc[i],FP_OFF(stemp)+(bytespertic<<3));
1058 				}
1059 			}
1060 
1061 			if (kdmqual)
1062 			{
1063 				if (numspeakers == 1)
1064 				{
1065 					for(i=(samplerate>>11)-1;i>=0;i--)
1066 						stemp[i] += mulscale16(stemp[i+1024]-stemp[i],ramplookup[i]);
1067 					j = bytespertic; k = (samplerate>>11);
1068 					copybuf(&stemp[j],&stemp[1024],k);
1069 					clearbuf(&stemp[j],k,32768);
1070 				}
1071 				else
1072 				{
1073 					for(i=(samplerate>>11)-1;i>=0;i--)
1074 					{
1075 						j = (i<<1);
1076 						stemp[j+0] += mulscale16(stemp[j+1024]-stemp[j+0],ramplookup[i]);
1077 						stemp[j+1] += mulscale16(stemp[j+1025]-stemp[j+1],ramplookup[i]);
1078 					}
1079 					j = (bytespertic<<1); k = ((samplerate>>11)<<1);
1080 					copybuf(&stemp[j],&stemp[1024],k);
1081 					clearbuf(&stemp[j],k,32768);
1082 				}
1083 			}
1084 
1085 			if (numspeakers == 1)
1086 			{
1087 				if (bytespersample == 1)
1088 				{
1089 					if (digistat == 13) pcbound2char(bytespertic>>1,FP_OFF(stemp),sndoffsplc+dacnt);
1090 										  else bound2char(bytespertic>>1,FP_OFF(stemp),sndoffsplc+dacnt);
1091 				} else bound2short(bytespertic>>1,FP_OFF(stemp),sndoffsplc+(dacnt<<1));
1092 			}
1093 			else
1094 			{
1095 				if (bytespersample == 1) bound2char(bytespertic,FP_OFF(stemp),sndoffsplc+(dacnt<<1));
1096 										 else bound2short(bytespertic,FP_OFF(stemp),sndoffsplc+(dacnt<<2));
1097 			}
1098 		}
1099 		kdmintinprep--;
1100 	}
1101 	kdminprep = 0;
1102 }
1103 
wsay(char * dafilename,long dafreq,long volume1,long volume2)1104 wsay(char *dafilename, long dafreq, long volume1, long volume2)
1105 {
1106 	unsigned char ch1, ch2;
1107 	long i, j, bad;
1108 
1109 	if (digistat == 0) return;
1110 
1111 	i = numwaves-1;
1112 	do
1113 	{
1114 		bad = 0;
1115 
1116 		j = 0;
1117 		while ((dafilename[j] > 0) && (j < 16))
1118 		{
1119 			ch1 = dafilename[j]; if ((ch1 >= 97) && (ch1 <= 123)) ch1 -= 32;
1120 			ch2 = instname[i][j]; if ((ch2 >= 97) && (ch2 <= 123)) ch2 -= 32;
1121 			if (ch1 != ch2) {bad = 1; break;}
1122 			j++;
1123 		}
1124 		if (bad == 0)
1125 		{
1126 			startwave(i,(dafreq*11025)/samplerate,volume1,volume2,0L,0L,0L);
1127 			return;
1128 		}
1129 
1130 		i--;
1131 	} while (i >= 0);
1132 }
1133 
loadwaves(char * wavename)1134 loadwaves(char *wavename)
1135 {
1136 	long fil, i, j, dawaversionum;
1137 	char filename[80];
1138 
1139 	strcpy(filename,wavename);
1140 	if (strstr(filename,".KWV") == 0) strcat(filename,".KWV");
1141 	if ((fil = kopen4load(filename,0)) == -1)
1142 		if (strcmp(filename,"WAVES.KWV") != 0)
1143 		{
1144 			strcpy(filename,"WAVES.KWV");
1145 			fil = kopen4load(filename,0);
1146 		}
1147 
1148 	totsndbytes = 0;
1149 
1150 	if (fil != -1)
1151 	{
1152 		if (strcmp(kwvname,filename) == 0) { kclose(fil); return; }
1153 		strcpy(kwvname,filename);
1154 
1155 		kread(fil,&dawaversionum,4);
1156 		if (dawaversionum != 0) { kclose(fil); return; }
1157 
1158 		kread(fil,&numwaves,4);
1159 		for(i=0;i<numwaves;i++)
1160 		{
1161 			kread(fil,&instname[i][0],16);
1162 			kread(fil,&wavleng[i],4);
1163 			kread(fil,&repstart[i],4);
1164 			kread(fil,&repleng[i],4);
1165 			kread(fil,&finetune[i],4);
1166 			wavoffs[i] = totsndbytes;
1167 			totsndbytes += wavleng[i];
1168 		}
1169 	}
1170 	else
1171 	{
1172 		dawaversionum = 0;
1173 		numwaves = 0;
1174 	}
1175 
1176 	for(i=numwaves;i<MAXWAVES;i++)
1177 	{
1178 		for(j=0;j<16;j++) instname[i][j] = 0;
1179 		wavoffs[i] = totsndbytes;
1180 		wavleng[i] = 0L;
1181 		repstart[i] = 0L;
1182 		repleng[i] = 0L;
1183 		finetune[i] = 0L;
1184 	}
1185 
1186 	if (snd == 0)
1187 	{
1188 		if ((snd = (char *)malloc(totsndbytes+2)) == 0)
1189 			{ printf("Not enough memory for digital music!\n"); exit(0); }
1190 	}
1191 	for(i=0;i<MAXWAVES;i++) wavoffs[i] += FP_OFF(snd);
1192 	if (fil != -1)
1193 	{
1194 		kread(fil,snd,totsndbytes);
1195 		kclose(fil);
1196 	}
1197 	snd[totsndbytes] = snd[totsndbytes+1] = 128;
1198 }
1199 
loadsong(char * filename)1200 loadsong(char *filename)
1201 {
1202 	long i, fil;
1203 
1204 	if (musistat != 1) return(0);
1205 	musicoff();
1206 	filename = strupr(filename);
1207 	if (strstr(filename,".KDM") == 0) strcat(filename,".KDM");
1208 	if ((fil = kopen4load(filename,0)) == -1)
1209 	{
1210 		printf("I cannot load %s.\n",filename);
1211 		uninitsb();
1212 		return(-1);
1213 	}
1214 	kread(fil,&kdmversionum,4);
1215 	if (kdmversionum != 0) return(-2);
1216 	kread(fil,&numnotes,4);
1217 	kread(fil,&numtracks,4);
1218 	kread(fil,trinst,numtracks);
1219 	kread(fil,trquant,numtracks);
1220 	kread(fil,trvol1,numtracks);
1221 	kread(fil,trvol2,numtracks);
1222 	kread(fil,nttime,numnotes<<2);
1223 	kread(fil,nttrack,numnotes);
1224 	kread(fil,ntfreq,numnotes);
1225 	kread(fil,ntvol1,numnotes);
1226 	kread(fil,ntvol2,numnotes);
1227 	kread(fil,ntfrqeff,numnotes);
1228 	kread(fil,ntvoleff,numnotes);
1229 	kread(fil,ntpaneff,numnotes);
1230 	kclose(fil);
1231 	return(0);
1232 }
1233 
musicon()1234 musicon()
1235 {
1236 	if (musistat != 1)
1237 		return;
1238 
1239 	notecnt = 0;
1240 	timecount = nttime[notecnt];
1241 	musicrepeat = 1;
1242 	musicstatus = 1;
1243 }
1244 
musicoff()1245 musicoff()
1246 {
1247 	long i;
1248 
1249 	musicstatus = 0;
1250 	for(i=0;i<NUMCHANNELS;i++)
1251 		splc[i] = 0;
1252 	musicrepeat = 0;
1253 	timecount = 0;
1254 	notecnt = 0;
1255 }
1256 
kdmconvalloc32(long size)1257 kdmconvalloc32 (long size)
1258 {
1259 	union REGS r;
1260 
1261 	r.x.eax = 0x0100;           //DPMI allocate DOS memory
1262 	r.x.ebx = ((size+15)>>4);   //Number of paragraphs requested
1263 	int386(0x31,&r,&r);
1264 
1265 	if (r.x.cflag != 0)         //Failed
1266 		return ((long)0);
1267 	return ((long)((r.x.eax&0xffff)<<4));   //Returns full 32-bit offset
1268 }
1269 
installbikdmhandlers()1270 installbikdmhandlers()
1271 {
1272 	union REGS r;
1273 	struct SREGS sr;
1274 	long lowp;
1275 	void far *fh;
1276 
1277 		//Get old protected mode handler
1278 	r.x.eax = 0x3500+kdmvect;   /* DOS get vector (INT 0Ch) */
1279 	sr.ds = sr.es = 0;
1280 	int386x(0x21,&r,&r,&sr);
1281 	kdmpsel = (unsigned short)sr.es;
1282 	kdmpoff = r.x.ebx;
1283 
1284 		//Get old real mode handler
1285 	r.x.eax = 0x0200;   /* DPMI get real mode vector */
1286 	r.h.bl = kdmvect;
1287 	int386(0x31,&r,&r);
1288 	kdmrseg = (unsigned short)r.x.ecx;
1289 	kdmroff = (unsigned short)r.x.edx;
1290 
1291 
1292 		//Allocate memory in low memory to store real mode handler
1293 	if ((lowp = kdmconvalloc32(KDMCODEBYTES)) == 0)
1294 	{
1295 		printf("Can't allocate conventional memory.\n");
1296 		exit;
1297 	}
1298 	memcpy((void *)lowp,(void *)pcrealbuffer,KDMCODEBYTES);
1299 
1300 		//Set new protected mode handler
1301 	r.x.eax = 0x2500+kdmvect;   /* DOS set vector (INT 0Ch) */
1302 	fh = (void far *)pctimerhandler;
1303 	r.x.edx = FP_OFF(fh);
1304 	sr.ds = FP_SEG(fh);      //DS:EDX == &handler
1305 	sr.es = 0;
1306 	int386x(0x21,&r,&r,&sr);
1307 
1308 		//Set new real mode handler (must be after setting protected mode)
1309 	r.x.eax = 0x0201;
1310 	r.h.bl = kdmvect;              //CX:DX == real mode &handler
1311 	r.x.ecx = ((lowp>>4)&0xffff);  //D32realseg
1312 	r.x.edx = 0L;                  //D32realoff
1313 	int386(0x31,&r,&r);
1314 }
1315 
uninstallbikdmhandlers()1316 uninstallbikdmhandlers()
1317 {
1318 	union REGS r;
1319 	struct SREGS sr;
1320 
1321 		//restore old protected mode handler
1322 	r.x.eax = 0x2500+kdmvect;   /* DOS set vector (INT 0Ch) */
1323 	r.x.edx = kdmpoff;
1324 	sr.ds = kdmpsel;    /* DS:EDX == &handler */
1325 	sr.es = 0;
1326 	int386x(0x21,&r,&r,&sr);
1327 
1328 		//restore old real mode handler
1329 	r.x.eax = 0x0201;   /* DPMI set real mode vector */
1330 	r.h.bl = kdmvect;
1331 	r.x.ecx = (unsigned long)kdmrseg;     //CX:DX == real mode &handler
1332 	r.x.edx = (unsigned long)kdmroff;
1333 	int386(0x31,&r,&r);
1334 }
1335