📄 kdmeng.c
字号:
// "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 calledlong samplerate, numspeakers, bytespersample, intspersec, kdmqual; //KWV wave variableslong numwaves;char instname[MAXWAVES][16];long wavleng[MAXWAVES];long repstart[MAXWAVES], repleng[MAXWAVES];long finetune[MAXWAVES]; //Other useful wave variableslong totsndbytes, totsndmem, wavoffs[MAXWAVES]; //Effects arraylong 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+128static long stemp[MAXBYTESPERTIC]; //Sound reading informationlong 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 256static 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 informationlong 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_DOSextern 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -