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