DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator
src/hardware/snd_pc98/sound/psggenc.c
00001 #include    "np2glue.h"
00002 //#include      "compiler.h"
00003 #include        <math.h>
00004 #include        "sound.h"
00005 #include        "psggen.h"
00006 #include        "keydisp.h"
00007 
00008 
00009         PSGGENCFG       psggencfg;
00010 
00011 static const UINT8 psggen_deftbl[0x10] =
00012                                 {0, 0, 0, 0, 0, 0, 0, 0xbf, 0, 0, 0, 0, 0, 0, 0xff, 0xff};
00013 
00014 static const UINT8 psgenv_pat[16] = {
00015                                         PSGENV_ONESHOT,
00016                                         PSGENV_ONESHOT,
00017                                         PSGENV_ONESHOT,
00018                                         PSGENV_ONESHOT,
00019                                         PSGENV_ONESHOT | PSGENV_INC,
00020                                         PSGENV_ONESHOT | PSGENV_INC,
00021                                         PSGENV_ONESHOT | PSGENV_INC,
00022                                         PSGENV_ONESHOT | PSGENV_INC,
00023                                         PSGENV_ONECYCLE,
00024                                         PSGENV_ONESHOT,
00025                                         0,
00026                                         PSGENV_ONESHOT | PSGENV_LASTON,
00027                                         PSGENV_ONECYCLE | PSGENV_INC,
00028                                         PSGENV_ONESHOT | PSGENV_INC | PSGENV_LASTON,
00029                                         PSGENV_INC,
00030                                         PSGENV_ONESHOT | PSGENV_INC};
00031 
00032 
00033 void psggen_initialize(UINT rate) {
00034 
00035         double  pom;
00036         UINT    i;
00037 
00038         ZeroMemory(&psggencfg, sizeof(psggencfg));
00039         psggencfg.rate = rate;
00040         pom = (double)0x0c00;
00041         for (i=15; i; i--) {
00042                 psggencfg.voltbl[i] = (SINT32)pom;
00043                 pom /= 1.41492;
00044         }
00045         psggencfg.puchidec = (UINT16)(rate / 11025) * 2;
00046         if (psggencfg.puchidec == 0) {
00047                 psggencfg.puchidec = 1;
00048         }
00049         if (rate) {
00050                 psggencfg.base = (5000 * (1 << (32 - PSGFREQPADBIT - PSGADDEDBIT)))
00051                                                                                                                         / (rate / 25);
00052         }
00053 }
00054 
00055 void psggen_setvol(UINT vol) {
00056 
00057         UINT    i;
00058 
00059         for (i=1; i<16; i++) {
00060                 psggencfg.volume[i] = (psggencfg.voltbl[i] * vol) >> 
00061                                                                                                                         (6 + PSGADDEDBIT);
00062         }
00063 }
00064 
00065 void psggen_reset(PSGGEN psg) {
00066 
00067         UINT    i;
00068 
00069         ZeroMemory(psg, sizeof(_PSGGEN));
00070         for (i=0; i<3; i++) {
00071                 psg->tone[i].pvol = psggencfg.volume + 0;
00072         }
00073         for (i=0; i<sizeof(psggen_deftbl); i++) {
00074                 psggen_setreg(psg, i, psggen_deftbl[i]);
00075         }
00076 }
00077 
00078 void psggen_restore(PSGGEN psg) {
00079 
00080         UINT    i;
00081 
00082         for (i=0; i<0x0e; i++) {
00083                 psggen_setreg(psg, i, ((UINT8 *)&psg->reg)[i]);
00084         }
00085 }
00086 
00087 void psggen_setreg(PSGGEN psg, UINT reg, REG8 value) {
00088 
00089         UINT    ch;
00090         UINT    freq;
00091 
00092         reg = reg & 15;
00093         if (reg < 14) {
00094                 sound_sync();
00095         }
00096         ((UINT8 *)&psg->reg)[reg] = value;
00097         switch(reg) {
00098                 case 0:
00099                 case 1:
00100                 case 2:
00101                 case 3:
00102                 case 4:
00103                 case 5:
00104                         ch = reg >> 1;
00105                         freq = LOADINTELWORD(psg->reg.tune[ch]) & 0xfff;
00106                         if (freq > 9) {
00107                                 psg->tone[ch].freq = (psggencfg.base / freq) << PSGFREQPADBIT;
00108                         }
00109                         else {
00110                                 psg->tone[ch].freq = 0;
00111                         }
00112                         break;
00113 
00114                 case 6:
00115                         freq = value & 0x1f;
00116                         if (freq == 0) {
00117                                 freq = 1;
00118                         }
00119                         psg->noise.freq = psggencfg.base / freq;
00120                         psg->noise.freq <<= PSGFREQPADBIT;
00121                         break;
00122 
00123                 case 7:
00124                         keydisp_psgmix(psg);
00125                         psg->mixer = ~value;
00126                         psg->puchicount = psggencfg.puchidec;
00127 //                      TRACEOUT(("psg %x 7 %d", (long)psg, value));
00128                         break;
00129 
00130                 case 8:
00131                 case 9:
00132                 case 10:
00133                         ch = reg - 8;
00134                         keydisp_psgvol(psg, (UINT8)ch);
00135                         if (value & 0x10) {
00136                                 psg->tone[ch].pvol = &psg->evol;
00137                         }
00138                         else {
00139                                 psg->tone[ch].pvol = psggencfg.volume + (value & 15);
00140                         }
00141                         psg->tone[ch].puchi = psggencfg.puchidec;
00142                         psg->puchicount = psggencfg.puchidec;
00143 //                      TRACEOUT(("psg %x %x %d", (long)psg, reg, value));
00144                         break;
00145 
00146                 case 11:
00147                 case 12:
00148                         freq = LOADINTELWORD(psg->reg.envtime);
00149                         freq = psggencfg.rate * freq / 125000;
00150                         if (freq == 0) {
00151                                 freq = 1;
00152                         }
00153                         psg->envmax = freq;
00154                         break;
00155 
00156                 case 13:
00157                         psg->envmode = psgenv_pat[value & 0x0f];
00158                         psg->envvolcnt = 16;
00159                         psg->envcnt = 1;
00160                         break;
00161         }
00162 }
00163 
00164 REG8 psggen_getreg(PSGGEN psg, UINT reg) {
00165 
00166         return(((UINT8 *)&psg->reg)[reg & 15]);
00167 }
00168 
00169 void psggen_setpan(PSGGEN psg, UINT ch, REG8 pan) {
00170 
00171         if ((psg) && (ch < 3)) {
00172                 psg->tone[ch].pan = pan;
00173         }
00174 }
00175