DOSBox-X
|
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