X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fpsg.cpp;fp=src%2Fpsg.cpp;h=b4f3f47c0f59da0724ac25583c921b0265d30716;hb=009359ef732411d9d978d137f1371647abc97261;hp=0000000000000000000000000000000000000000;hpb=be67039a7ed493081dd1503f94cdfae4dd4d965e;p=thunder diff --git a/src/psg.cpp b/src/psg.cpp new file mode 100644 index 0000000..b4f3f47 --- /dev/null +++ b/src/psg.cpp @@ -0,0 +1,209 @@ +// +// PSG handler +// +// This emulates the Rolling Thunder PSG (Namco CUS30) +// +// by James Hammons +// (C) 2014 Underground Software +// +// JLH = James Hammons +// +// Who When What +// --- ---------- ----------------------------------------------------------- +// JLH 04/21/2014 Created this file. +// + +#include "psg.h" +#include +#include + + +struct Voice +{ + uint8_t leftVolume; + uint8_t rightVolume; + uint8_t waveform; + uint32_t frequency; + uint32_t counter; + bool noise; + uint32_t noiseSeed; +}; + +static Voice voice[8]; +static uint8_t memory[0x200]; +//static +static uint32_t sampleRate = 44100; + +extern FILE * psg1; +extern FILE * psg2; + + +void InitPSG(uint32_t s/*=44100*/) +{ + sampleRate = s; + + for(int i=0; i<8; i++) + voice[i].noiseSeed = 1; +} + + +void UpdatePSG(uint8_t * buffer, int count) +{ +/* +if F == 44100, then counter++ for each sample. +if F == 88200, then counter += 2 for each sample. +if F == 22050, then counter += 0.5 for each sample. +*/ +// memset(buffer, 0, count * 2); + + // Recast buffer as int16, we're doing 16-bit sound here + int16_t * p = (int16_t *)buffer; + + for(int i=0; i<8; i++) + { + if (!voice[i].noise) + { + if ((voice[i].leftVolume == 0) || (voice[i].frequency == 0)) + continue; + + for(int j=0; j> 4 + : memory[(voice[i].waveform * 16) + (pos / 2)]) & 0x0F; +// p[j] += (((memory[(voice[i].waveform * 32) + pos] & 0x0F) - 8) +// * voice[i].leftVolume) << 5; + p[j] += ((sample - 8) * voice[i].leftVolume) << 5; + voice[i].counter += voice[i].frequency; + } + } + else + { + if ((voice[i].leftVolume == 0) || ((voice[i].frequency & 0xFF) == 0)) + continue; + + int16_t sample = (7 * voice[i].leftVolume) << 4; + int16_t noiseSign = 1; + int16_t hold = 1 << 1; + + for(int j=0; j> 8) & 0xFF , psg1); +} +else if (i == 3) +{ + fputc(sample & 0xFF, psg2); + fputc((sample >> 8) & 0xFF , psg2); +} +#endif + + if (hold) + { + hold--; + continue; + } + + hold = 1 << 1; + + voice[i].counter += (voice[i].frequency & 0xFF) << 4; + int c = voice[i].counter >> 12; + voice[i].counter &= 0xFFF; + + for(; c>0; c--) + { + if ((voice[i].noiseSeed + 1) & 0x02) + noiseSign *= -1; + + if (voice[i].noiseSeed & 0x01) + voice[i].noiseSeed ^= 0x28000; + + voice[i].noiseSeed >>= 1; + } + } + } + } +} + + +void WritePSG(uint16_t address, uint8_t data) +{ + if ((address >= 0x100) && (address <= 0x13F)) + { + uint8_t channel = (address - 0x100) / 8; + uint8_t knob = (address - 0x100) - (channel * 8); + + if (channel < 8) + { + switch (knob) + { + case 0: + voice[channel].leftVolume = data & 0x0F; + break; + case 1: + voice[channel].waveform = data >> 4; + voice[channel].frequency = ((data & 0x0F) << 16) + | (voice[channel].frequency & 0x0FFFF); +#if 0 +printf("PSG: Setting waveform on channel %i to %i...\n", channel, voice[channel].waveform); +#endif + break; + case 2: + voice[channel].frequency = (data << 8) + | (voice[channel].frequency & 0xF00FF); + break; + case 3: + voice[channel].frequency = data + | (voice[channel].frequency & 0xFFF00); + break; + case 4: + voice[channel].rightVolume = data & 0x0F; + // Noise switch is channel # + 1 (wraps to zero) + voice[(channel + 1) & 0x07].noise = (data & 0x80 ? true : false); +#if 0 +if (voice[(channel + 1) & 0x07].noise) +{ + uint8_t ch = (channel + 1) & 0x07; + printf("PSG: Setting noise on channel %i, vol=%i, freq=%i...\n", ch, voice[ch].leftVolume, voice[ch].frequency); +} +#endif +#if 0 +if (data & 0x0F) +{ + printf("PSG: Setting right volume on channel %i: vol=%i...\n", channel, voice[channel].rightVolume); +} +#endif + break; + } + } + +// return; + } +#if 0 + else + printf("PSG: Write to $%03X of $%02X...\n", address, data); +#endif + +//if (address < 0x100) +// printf("PSG: Waveform byte[$%02X] = $%02X...\n", address, data); + + memory[address & 0x01FF] = data; +} + + +uint8_t ReadPSG(uint16_t address) +{ + return memory[address & 0x01FF]; +} +