DOSBox-X
|
00001 #include "np2glue.h" 00002 //#include "compiler.h" 00003 #include "parts.h" 00004 #include "sound.h" 00005 #include "psggen.h" 00006 00007 00008 extern PSGGENCFG psggencfg; 00009 00010 00011 void SOUNDCALL psggen_getpcm(PSGGEN psg, SINT32 *pcm, UINT count) { 00012 00013 // SINT32 noisevol; 00014 UINT noisetbl = 0; 00015 PSGTONE *tone; 00016 SINT32 samp; 00017 // UINT psgvol; 00018 SINT32 vol; 00019 UINT i; 00020 UINT noise; 00021 00022 if ((psg->mixer & 0x3f) == 0) { 00023 count = min(count, psg->puchicount); 00024 psg->puchicount -= count; 00025 } 00026 if (count == 0) { 00027 return; 00028 } 00029 do { 00030 // noisevol = 0; 00031 if (psg->envcnt) { 00032 psg->envcnt--; 00033 if (psg->envcnt == 0) { 00034 psg->envvolcnt--; 00035 if (psg->envvolcnt < 0) { 00036 if (psg->envmode & PSGENV_ONESHOT) { 00037 psg->envvol = (psg->envmode & PSGENV_LASTON)?15:0; 00038 } 00039 else { 00040 psg->envvolcnt = 15; 00041 if (!(psg->envmode & PSGENV_ONECYCLE)) { 00042 psg->envmode ^= PSGENV_INC; 00043 } 00044 psg->envcnt = psg->envmax; 00045 psg->envvol = (psg->envvolcnt ^ psg->envmode) & 0x0f; 00046 } 00047 } 00048 else { 00049 psg->envcnt = psg->envmax; 00050 psg->envvol = (psg->envvolcnt ^ psg->envmode) & 0x0f; 00051 } 00052 psg->evol = psggencfg.volume[psg->envvol]; 00053 } 00054 } 00055 UINT8 mixer = psg->mixer; 00056 if (mixer & 0x38) { 00057 /* NTS: This code relies on signed integer underflow to determine when to advance 00058 the pseudo-random noise generation sequence. It assumes that it can detect 00059 SINT32 carry by copying the value, subtracting the original, and then 00060 testing to see if the result is larger than the original. 00061 00062 Unfortunately, Clang/LLVM break this code by promoting both to long (64-bit) 00063 before comparing, which turns the noise into DC bias popping noises. 00064 00065 This hack, with long type masks, emulates the original behavior even if the 00066 compare is promoted to signed long (64-bit) and allows the noise generation 00067 to work even with Clang/LLVM --J.C */ 00068 const long sint32sign = 1L << (((long)(CHAR_BIT * sizeof(long))) - 1L); 00069 const long sint32mask = sint32sign + 0x7FFFFFFFL; 00070 00071 for (i=0; i<(1 << PSGADDEDBIT); i++) { 00072 SINT32 countbak; 00073 countbak = psg->noise.count; 00074 psg->noise.count -= psg->noise.freq; 00075 if (((long)psg->noise.count & sint32mask) > ((long)countbak & sint32mask)) { 00076 // psg->noise.base = GETRAND() & (1 << (1 << PSGADDEDBIT)); 00077 psg->noise.base = rand_get() & (1 << (1 << PSGADDEDBIT)); 00078 } 00079 noisetbl += psg->noise.base; 00080 noisetbl >>= 1; 00081 } 00082 } 00083 tone = psg->tone; 00084 PSGTONE *toneterm = tone + 3; 00085 do { 00086 vol = *(tone->pvol); 00087 if (vol) { 00088 samp = 0; 00089 switch(mixer & 9) { 00090 case 0: // no mix 00091 if (tone->puchi) { 00092 tone->puchi--; 00093 samp += vol << PSGADDEDBIT; 00094 } 00095 break; 00096 00097 case 1: // tone only 00098 for (i=0; i<(1 << PSGADDEDBIT); i++) { 00099 tone->count += tone->freq; 00100 samp += vol * ((tone->count>=0)?1:-1); 00101 } 00102 break; 00103 00104 case 8: // noise only 00105 noise = noisetbl; 00106 for (i=0; i<(1 << PSGADDEDBIT); i++) { 00107 samp += vol * ((noise & 1)?1:-1); 00108 noise >>= 1; 00109 } 00110 break; 00111 00112 case 9: 00113 noise = noisetbl; 00114 for (i=0; i<(1 << PSGADDEDBIT); i++) { 00115 tone->count += tone->freq; 00116 if ((tone->count >= 0) || (noise & 1)) { 00117 samp += vol; 00118 } 00119 else { 00120 samp -= vol; 00121 } 00122 noise >>= 1; 00123 } 00124 break; 00125 } 00126 if (!(tone->pan & 1)) { 00127 pcm[0] += samp; 00128 } 00129 if (!(tone->pan & 2)) { 00130 pcm[1] += samp; 00131 } 00132 } 00133 mixer >>= 1; 00134 } while(++tone < toneterm); 00135 pcm += 2; 00136 } while(--count); 00137 } 00138