diff --git a/CMakeLists.txt b/CMakeLists.txt index b757062f..a881bad6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -250,6 +250,13 @@ src/engine/platform/sound/nes/mmc5.c src/engine/platform/sound/vera_psg.c src/engine/platform/sound/vera_pcm.c +src/engine/platform/sound/nes_nsfplay/nes_apu.cpp +src/engine/platform/sound/nes_nsfplay/nes_dmc.cpp +src/engine/platform/sound/nes_nsfplay/nes_fds.cpp +src/engine/platform/sound/nes_nsfplay/nes_mmc5.cpp +src/engine/platform/sound/nes_nsfplay/nes_n106.cpp +src/engine/platform/sound/nes_nsfplay/nes_vrc6.cpp + src/engine/platform/sound/c64/sid.cc src/engine/platform/sound/c64/voice.cc src/engine/platform/sound/c64/wave.cc diff --git a/src/engine/platform/sound/nes_nsfplay/common.h b/src/engine/platform/sound/nes_nsfplay/common.h new file mode 100644 index 00000000..894a6973 --- /dev/null +++ b/src/engine/platform/sound/nes_nsfplay/common.h @@ -0,0 +1,4 @@ +namespace xgm { + const unsigned int DEFAULT_CLOCK=1789773; + const unsigned int DEFAULT_RATE=1789773; +}; diff --git a/src/engine/platform/sound/nes_nsfplay/nes_apu.cpp b/src/engine/platform/sound/nes_nsfplay/nes_apu.cpp index b2ebb677..f215a9aa 100644 --- a/src/engine/platform/sound/nes_nsfplay/nes_apu.cpp +++ b/src/engine/platform/sound/nes_nsfplay/nes_apu.cpp @@ -3,6 +3,7 @@ // #include #include "nes_apu.h" +#include "common.h" namespace xgm { @@ -86,9 +87,9 @@ namespace xgm } - INT32 NES_APU::calc_sqr (int i, UINT32 clocks) + int NES_APU::calc_sqr (int i, unsigned int clocks) { - static const INT16 sqrtbl[4][16] = { + static const short sqrtbl[4][16] = { {0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0}, @@ -102,7 +103,7 @@ namespace xgm scounter[i] += freq[i] + 1; } - INT32 ret = 0; + int ret = 0; if (length_counter[i] > 0 && freq[i] >= 8 && sfreq[i] < 0x800 @@ -115,7 +116,7 @@ namespace xgm return ret; } - bool NES_APU::Read (UINT32 adr, UINT32 & val, UINT32 id) + bool NES_APU::Read (unsigned int adr, unsigned int & val, unsigned int id) { if (0x4000 <= adr && adr < 0x4008) { @@ -131,26 +132,26 @@ namespace xgm return false; } - void NES_APU::Tick (UINT32 clocks) + void NES_APU::Tick (unsigned int clocks) { out[0] = calc_sqr(0, clocks); out[1] = calc_sqr(1, clocks); } // ツ青カツ青ャツつウツづェツづゥツ波ツ形ツづ個振ツ閉敖づ0-8191 - UINT32 NES_APU::Render (INT32 b[2]) + unsigned int NES_APU::Render (int b[2]) { out[0] = (mask & 1) ? 0 : out[0]; out[1] = (mask & 2) ? 0 : out[1]; - INT32 m[2]; + int m[2]; if(option[OPT_NONLINEAR_MIXER]) { - INT32 voltage = square_table[out[0] + out[1]]; + int voltage = square_table[out[0] + out[1]]; m[0] = out[0] << 6; m[1] = out[1] << 6; - INT32 ref = m[0] + m[1]; + int ref = m[0] + m[1]; if (ref > 0) { m[0] = (m[0] * voltage) / ref; @@ -191,7 +192,7 @@ namespace xgm square_table[0] = 0; for(int i=1;i<32;i++) - square_table[i]=(INT32)((8192.0*95.88)/(8128.0/i+100)); + square_table[i]=(int)((8192.0*95.88)/(8128.0/i+100)); square_linear = square_table[15]; // match linear scale to one full volume square of nonlinear @@ -200,7 +201,7 @@ namespace xgm sm[c][t] = 128; } - NES_APU::‾NES_APU () + NES_APU::~NES_APU () { } @@ -267,7 +268,7 @@ namespace xgm rate = r ? r : DEFAULT_RATE; } - void NES_APU::SetStereoMix(int trk, xgm::INT16 mixl, xgm::INT16 mixr) + void NES_APU::SetStereoMix(int trk, short mixl, short mixr) { if (trk < 0) return; if (trk > 1) return; @@ -275,32 +276,11 @@ namespace xgm sm[1][trk] = mixr; } - ITrackInfo *NES_APU::GetTrackInfo(int trk) - { - trkinfo[trk]._freq = freq[trk]; - if(freq[trk]) - trkinfo[trk].freq = clock/16/(freq[trk] + 1); - else - trkinfo[trk].freq = 0; - - trkinfo[trk].output = out[trk]; - trkinfo[trk].volume = volume[trk]+(envelope_disable[trk]?0:0x10)+(envelope_loop[trk]?0x20:0); - trkinfo[trk].key = - enable[trk] && - length_counter[trk] > 0 && - freq[trk] >= 8 && - sfreq[trk] < 0x800 && - (envelope_disable[trk] ? volume[trk] : (envelope_counter[trk] > 0)); - trkinfo[trk].tone = duty[trk]; - trkinfo[trk].max_volume = 15; - return &trkinfo[trk]; - } - - bool NES_APU::Write (UINT32 adr, UINT32 val, UINT32 id) + bool NES_APU::Write (unsigned int adr, unsigned int val, unsigned int id) { int ch; - static const UINT8 length_table[32] = { + static const unsigned char length_table[32] = { 0x0A, 0xFE, 0x14, 0x02, 0x28, 0x04, diff --git a/src/engine/platform/sound/nes_nsfplay/nes_apu.h b/src/engine/platform/sound/nes_nsfplay/nes_apu.h index a6caa282..004c9997 100644 --- a/src/engine/platform/sound/nes_nsfplay/nes_apu.h +++ b/src/engine/platform/sound/nes_nsfplay/nes_apu.h @@ -1,12 +1,11 @@ #ifndef _NES_APU_H_ #define _NES_APU_H_ -#include "../device.h" #include "nes_dmc.h" namespace xgm { /** Upper half of APU **/ - class NES_APU : public ISoundChip + class NES_APU { public: enum @@ -24,15 +23,15 @@ namespace xgm protected: int option[OPT_END]; // 各種オプション int mask; - INT32 sm[2][2]; + int sm[2][2]; - UINT32 gclock; - UINT8 reg[0x20]; - INT32 out[2]; + unsigned int gclock; + unsigned char reg[0x20]; + int out[2]; double rate, clock; - INT32 square_table[32]; // nonlinear mixer - INT32 square_linear; // linear mix approximation + int square_table[32]; // nonlinear mixer + int square_linear; // linear mix approximation int scounter[2]; // frequency divider int sphase[2]; // phase counter @@ -61,26 +60,24 @@ namespace xgm bool enable[2]; void sweep_sqr (int ch); // calculates target sweep frequency - INT32 calc_sqr (int ch, UINT32 clocks); - TrackInfoBasic trkinfo[2]; + int calc_sqr (int ch, unsigned int clocks); public: - NES_APU (); - ‾NES_APU (); + NES_APU (); + ~NES_APU (); void FrameSequence(int s); virtual void Reset (); - virtual void Tick (UINT32 clocks); - virtual UINT32 Render (INT32 b[2]); - virtual bool Read (UINT32 adr, UINT32 & val, UINT32 id=0); - virtual bool Write (UINT32 adr, UINT32 val, UINT32 id=0); + virtual void Tick (unsigned int clocks); + virtual unsigned int Render (int b[2]); + virtual bool Read (unsigned int adr, unsigned int & val, unsigned int id=0); + virtual bool Write (unsigned int adr, unsigned int val, unsigned int id=0); virtual void SetRate (double rate); virtual void SetClock (double clock); virtual void SetOption (int id, int b); virtual void SetMask(int m){ mask = m; } - virtual void SetStereoMix (int trk, xgm::INT16 mixl, xgm::INT16 mixr); - virtual ITrackInfo *GetTrackInfo(int trk); + virtual void SetStereoMix (int trk, short mixl, short mixr); }; } // namespace diff --git a/src/engine/platform/sound/nes_nsfplay/nes_dmc.cpp b/src/engine/platform/sound/nes_nsfplay/nes_dmc.cpp index 49a58eb5..a37b544d 100644 --- a/src/engine/platform/sound/nes_nsfplay/nes_dmc.cpp +++ b/src/engine/platform/sound/nes_nsfplay/nes_dmc.cpp @@ -1,10 +1,12 @@ #include "nes_dmc.h" #include "nes_apu.h" +#include "common.h" +#include #include namespace xgm { - const UINT32 NES_DMC::wavlen_table[2][16] = { + const unsigned int NES_DMC::wavlen_table[2][16] = { { // NTSC 4, 8, 16, 32, 64, 96, 128, 160, 202, 254, 380, 508, 762, 1016, 2034, 4068 }, @@ -12,7 +14,7 @@ namespace xgm 4, 8, 14, 30, 60, 88, 118, 148, 188, 236, 354, 472, 708, 944, 1890, 3778 }}; - const UINT32 NES_DMC::freq_table[2][16] = { + const unsigned int NES_DMC::freq_table[2][16] = { { // NTSC 428, 380, 340, 320, 286, 254, 226, 214, 190, 160, 142, 128, 106, 84, 72, 54 }, @@ -20,7 +22,7 @@ namespace xgm 398, 354, 316, 298, 276, 236, 210, 198, 176, 148, 132, 118, 98, 78, 66, 50 }}; - const UINT32 BITREVERSE[256] = { + const unsigned int BITREVERSE[256] = { 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, @@ -67,11 +69,11 @@ namespace xgm } - NES_DMC::‾NES_DMC () + NES_DMC::~NES_DMC () { } - void NES_DMC::SetStereoMix(int trk, xgm::INT16 mixl, xgm::INT16 mixr) + void NES_DMC::SetStereoMix(int trk, short mixl, short mixr) { if (trk < 0) return; if (trk > 2) return; @@ -79,47 +81,6 @@ namespace xgm sm[1][trk] = mixr; } - ITrackInfo *NES_DMC::GetTrackInfo(int trk) - { - switch(trk) - { - case 0: - trkinfo[trk].max_volume = 255; - trkinfo[0].key = (linear_counter>0 && length_counter[0]>0 && enable[0]); - trkinfo[0].volume = 0; - trkinfo[0]._freq = tri_freq; - if(trkinfo[0]._freq) - trkinfo[0].freq = clock/32/(trkinfo[0]._freq + 1); - else - trkinfo[0].freq = 0; - trkinfo[0].tone = -1; - trkinfo[0].output = out[0]; - break; - case 1: - trkinfo[1].max_volume = 15; - trkinfo[1].volume = noise_volume+(envelope_disable?0:0x10)+(envelope_loop?0x20:0); - trkinfo[1].key = length_counter[1]>0 && enable[1] && - (envelope_disable ? (noise_volume>0) : (envelope_counter>0)); - trkinfo[1]._freq = reg[0x400e - 0x4008]&0xF; - trkinfo[1].freq = clock/double(wavlen_table[pal][trkinfo[1]._freq] * ((noise_tap&(1<<6)) ? 93 : 1)); - trkinfo[1].tone = noise_tap & (1<<6); - trkinfo[1].output = out[1]; - break; - case 2: - trkinfo[2].max_volume = 127; - trkinfo[2].volume = reg[0x4011 - 0x4008]&0x7F; - trkinfo[2].key = dlength > 0; - trkinfo[2]._freq = reg[0x4010 - 0x4008]&0xF; - trkinfo[2].freq = clock/double(freq_table[pal][trkinfo[2]._freq]); - trkinfo[2].tone = (0xc000|(adr_reg<<6)); - trkinfo[2].output = (damp<<1)|dac_lsb; - break; - default: - return NULL; - } - return &trkinfo[trk]; - } - void NES_DMC::FrameSequence(int s) { //DEBUG_OUT("FrameSequence: %d¥n",s); @@ -134,7 +95,6 @@ namespace xgm if (s == 0 && (frame_sequence_steps == 4)) { if (frame_irq_enable) frame_irq = true; - cpu->UpdateIRQ(NES_CPU::IRQD_FRAME, frame_irq & frame_irq_enable); } // 240hz clock @@ -194,9 +154,9 @@ namespace xgm } // 三角波チャンネルの計算 戻り値は0-15 - UINT32 NES_DMC::calc_tri (UINT32 clocks) + unsigned int NES_DMC::calc_tri (unsigned int clocks) { - static UINT32 tritbl[32] = + static unsigned int tritbl[32] = { 15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, @@ -215,7 +175,7 @@ namespace xgm } } - UINT32 ret = tritbl[tphase]; + unsigned int ret = tritbl[tphase]; return ret; } @@ -223,20 +183,20 @@ namespace xgm // 低サンプリングレートで合成するとエイリアスノイズが激しいので // ノイズだけはこの関数内で高クロック合成し、簡易なサンプリングレート // 変換を行っている。 - UINT32 NES_DMC::calc_noise(UINT32 clocks) + unsigned int NES_DMC::calc_noise(unsigned int clocks) { - UINT32 env = envelope_disable ? noise_volume : envelope_counter; + unsigned int env = envelope_disable ? noise_volume : envelope_counter; if (length_counter[1] < 1) env = 0; - UINT32 last = (noise & 0x4000) ? 0 : env; + unsigned int last = (noise & 0x4000) ? 0 : env; if (clocks < 1) return last; // simple anti-aliasing (noise requires it, even when oversampling is off) - UINT32 count = 0; - UINT32 accum = counter[1] * last; // samples pending from previous calc - UINT32 accum_clocks = counter[1]; + unsigned int count = 0; + unsigned int accum = counter[1] * last; // samples pending from previous calc + unsigned int accum_clocks = counter[1]; #ifdef _DEBUG - INT32 start_clocks = counter[1]; + int start_clocks = counter[1]; #endif if (counter[1] < 0) // only happens on startup when using the randomize noise option { @@ -249,7 +209,7 @@ namespace xgm while (counter[1] < 0) { // tick the noise generator - UINT32 feedback = (noise&1) ^ ((noise&noise_tap)?1:0); + unsigned int feedback = (noise&1) ^ ((noise&noise_tap)?1:0); noise = (noise>>1) | (feedback<<14); last = (noise & 0x4000) ? 0 : env; @@ -270,13 +230,13 @@ namespace xgm if (start_clocks >= 0) assert(accum_clocks == clocks); // these should be equal #endif - UINT32 average = accum / accum_clocks; + unsigned int average = accum / accum_clocks; assert(average <= 15); // above this would indicate overflow return average; } // Tick the DMC for the number of clocks, and return output counter; - UINT32 NES_DMC::calc_dmc (UINT32 clocks) + unsigned int NES_DMC::calc_dmc (unsigned int clocks) { counter[2] -= clocks; assert (dfreq > 0); // prevent infinite loop @@ -300,8 +260,7 @@ namespace xgm { if (dlength > 0) { - memory->Read (daddress, data); - cpu->StealCycles(4); // DMC read takes 3 or 4 CPU cycles, usually 4 + memory (daddress, data); // (checking for the 3-cycle case would require sub-instruction emulation) data &= 0xFF; // read 8 bits if (option[OPT_DPCM_REVERSE]) data = BITREVERSE[data]; @@ -319,7 +278,6 @@ namespace xgm else if (mode & 2) // IRQ and not looped { irq = true; - cpu->UpdateIRQ(NES_CPU::IRQD_DMC, true); } } } @@ -334,7 +292,7 @@ namespace xgm return (damp<<1) + dac_lsb; } - void NES_DMC::TickFrameSequence (UINT32 clocks) + void NES_DMC::TickFrameSequence (unsigned int clocks) { frame_sequence_count += clocks; while (frame_sequence_count > frame_sequence_length) @@ -347,28 +305,28 @@ namespace xgm } } - void NES_DMC::Tick (UINT32 clocks) + void NES_DMC::Tick (unsigned int clocks) { out[0] = calc_tri(clocks); out[1] = calc_noise(clocks); out[2] = calc_dmc(clocks); } - UINT32 NES_DMC::Render (INT32 b[2]) + unsigned int NES_DMC::Render (int b[2]) { out[0] = (mask & 1) ? 0 : out[0]; out[1] = (mask & 2) ? 0 : out[1]; out[2] = (mask & 4) ? 0 : out[2]; - INT32 m[3]; + int m[3]; m[0] = tnd_table[0][out[0]][0][0]; m[1] = tnd_table[0][0][out[1]][0]; m[2] = tnd_table[0][0][0][out[2]]; if (option[OPT_NONLINEAR_MIXER]) { - INT32 ref = m[0] + m[1] + m[2]; - INT32 voltage = tnd_table[1][out[0]][out[1]][out[2]]; + int ref = m[0] + m[1] + m[2]; + int voltage = tnd_table[1][out[0]][out[1]][out[2]]; if (ref) { for (int i=0; i < 3; ++i) @@ -391,7 +349,7 @@ namespace xgm dmc_pop = false; // prevent overflow, keep headspace at edges - const INT32 OFFSET_MAX = (1 << 30) - (4 << 16); + const int OFFSET_MAX = (1 << 30) - (4 << 16); if (dmc_pop_offset > OFFSET_MAX) dmc_pop_offset = OFFSET_MAX; if (dmc_pop_offset < -OFFSET_MAX) dmc_pop_offset = -OFFSET_MAX; } @@ -425,7 +383,7 @@ namespace xgm void NES_DMC::SetRate (double r) { - rate = (UINT32)(r?r:DEFAULT_RATE); + rate = (unsigned int)(r?r:DEFAULT_RATE); } void NES_DMC::SetPal (bool is_pal) @@ -455,7 +413,7 @@ namespace xgm for(int t=0; t<16 ; t++) { for(int n=0; n<16; n++) { for(int d=0; d<128; d++) { - tnd_table[0][t][n][d] = (UINT32)(MASTER*(3.0*t+2.0*n+d)/208.0); + tnd_table[0][t][n][d] = (unsigned int)(MASTER*(3.0*t+2.0*n+d)/208.0); } } } @@ -466,7 +424,7 @@ namespace xgm for(int n=0; n<16; n++) { for(int d=0; d<128; d++) { if(t!=0||n!=0||d!=0) - tnd_table[1][t][n][d] = (UINT32)((MASTER*159.79)/(100.0+1.0/((double)t/wt+(double)n/wn+(double)d/wd))); + tnd_table[1][t][n][d] = (unsigned int)((MASTER*159.79)/(100.0+1.0/((double)t/wt+(double)n/wn+(double)d/wd))); } } } @@ -510,7 +468,6 @@ namespace xgm frame_sequence_count = 0; frame_sequence_steps = 4; frame_sequence_step = 0; - cpu->UpdateIRQ(NES_CPU::IRQD_FRAME, false); for (i = 0; i < 0x0F; i++) Write (0x4008 + i, 0); @@ -520,7 +477,6 @@ namespace xgm Write (0x4015, 0x00); if (option[OPT_UNMUTE_ON_RESET]) Write (0x4015, 0x0f); - cpu->UpdateIRQ(NES_CPU::IRQD_DMC, false); out[0] = out[1] = out[2] = 0; damp = 0; @@ -551,7 +507,7 @@ namespace xgm SetRate(rate); } - void NES_DMC::SetMemory (IDevice * r) + void NES_DMC::SetMemory (std::function r) { memory = r; } @@ -566,9 +522,9 @@ namespace xgm } } - bool NES_DMC::Write (UINT32 adr, UINT32 val, UINT32 id) + bool NES_DMC::Write (unsigned int adr, unsigned int val, unsigned int id) { - static const UINT8 length_table[32] = { + static const unsigned char length_table[32] = { 0x0A, 0xFE, 0x14, 0x02, 0x28, 0x04, @@ -612,7 +568,6 @@ namespace xgm } irq = false; - cpu->UpdateIRQ(NES_CPU::IRQD_DMC, false); reg[adr-0x4008] = val; return true; @@ -623,7 +578,6 @@ namespace xgm //DEBUG_OUT("4017 = %02X¥n", val); frame_irq_enable = ((val & 0x40) != 0x40); if (frame_irq_enable) frame_irq = false; - cpu->UpdateIRQ(NES_CPU::IRQD_FRAME, false); frame_sequence_count = 0; if (val & 0x80) @@ -708,7 +662,6 @@ namespace xgm if (!(mode & 2)) { irq = false; - cpu->UpdateIRQ(NES_CPU::IRQD_DMC, false); } dfreq = freq_table[pal][val&15]; break; @@ -739,7 +692,7 @@ namespace xgm return true; } - bool NES_DMC::Read (UINT32 adr, UINT32 & val, UINT32 id) + bool NES_DMC::Read (unsigned int adr, unsigned int & val, unsigned int id) { if (adr == 0x4015) { @@ -751,7 +704,6 @@ namespace xgm ; frame_irq = false; - cpu->UpdateIRQ(NES_CPU::IRQD_FRAME, false); return true; } else if (0x4008<=adr&&adr<=0x4014) @@ -762,10 +714,4 @@ namespace xgm else return false; } - - // IRQ support requires CPU read access - void NES_DMC::SetCPU(NES_CPU* cpu_) - { - cpu = cpu_; - } } // namespace diff --git a/src/engine/platform/sound/nes_nsfplay/nes_dmc.h b/src/engine/platform/sound/nes_nsfplay/nes_dmc.h index 6cc8058a..4d19617d 100644 --- a/src/engine/platform/sound/nes_nsfplay/nes_dmc.h +++ b/src/engine/platform/sound/nes_nsfplay/nes_dmc.h @@ -1,16 +1,13 @@ #ifndef _NES_DMC_H_ #define _NES_DMC_H_ - -#include "../device.h" -#include "../Audio/MedianFilter.h" -#include "../CPU/nes_cpu.h" +#include namespace xgm { class NES_APU; // forward declaration /** Bottom Half of APU **/ - class NES_DMC:public ISoundChip + class NES_DMC { public: enum @@ -28,46 +25,46 @@ namespace xgm }; protected: const int GETA_BITS; - static const UINT32 freq_table[2][16]; - static const UINT32 wavlen_table[2][16]; - UINT32 tnd_table[2][16][16][128]; + static const unsigned int freq_table[2][16]; + static const unsigned int wavlen_table[2][16]; + unsigned int tnd_table[2][16][16][128]; int option[OPT_END]; int mask; - INT32 sm[2][3]; - UINT8 reg[0x10]; - UINT32 len_reg; - UINT32 adr_reg; - IDevice *memory; - UINT32 out[3]; - UINT32 daddress; - UINT32 dlength; - UINT32 data; + int sm[2][3]; + unsigned int reg[0x10]; + unsigned int len_reg; + unsigned int adr_reg; + std::function memory; + unsigned int out[3]; + unsigned int daddress; + unsigned int dlength; + unsigned int data; bool empty; - INT16 damp; + short damp; int dac_lsb; bool dmc_pop; - INT32 dmc_pop_offset; - INT32 dmc_pop_follow; + int dmc_pop_offset; + int dmc_pop_follow; double clock; - UINT32 rate; + unsigned int rate; int pal; int mode; bool irq; - INT32 counter[3]; // frequency dividers + int counter[3]; // frequency dividers int tphase; // triangle phase - UINT32 nfreq; // noise frequency - UINT32 dfreq; // DPCM frequency + unsigned int nfreq; // noise frequency + unsigned int dfreq; // DPCM frequency - UINT32 tri_freq; + unsigned int tri_freq; int linear_counter; int linear_counter_reload; bool linear_counter_halt; bool linear_counter_control; int noise_volume; - UINT32 noise, noise_tap; + unsigned int noise, noise_tap; // noise envelope bool envelope_loop; @@ -80,8 +77,6 @@ namespace xgm bool enable[2]; // tri/noise enable int length_counter[2]; // 0=tri, 1=noise - TrackInfoBasic trkinfo[3]; - // frame sequencer NES_APU* apu; // apu is clocked by DMC's frame sequencer int frame_sequence_count; // current cycle count @@ -91,37 +86,32 @@ namespace xgm bool frame_irq; bool frame_irq_enable; - NES_CPU* cpu; // IRQ needs CPU access - - inline UINT32 calc_tri (UINT32 clocks); - inline UINT32 calc_dmc (UINT32 clocks); - inline UINT32 calc_noise (UINT32 clocks); + inline unsigned int calc_tri (unsigned int clocks); + inline unsigned int calc_dmc (unsigned int clocks); + inline unsigned int calc_noise (unsigned int clocks); public: NES_DMC (); - ‾NES_DMC (); + ~NES_DMC (); void InitializeTNDTable(double wt, double wn, double wd); void SetPal (bool is_pal); void SetAPU (NES_APU* apu_); - void SetMemory (IDevice * r); + void SetMemory (std::function r); void FrameSequence(int s); int GetDamp(){ return (damp<<1)|dac_lsb ; } - void TickFrameSequence (UINT32 clocks); + void TickFrameSequence (unsigned int clocks); virtual void Reset (); - virtual void Tick (UINT32 clocks); - virtual UINT32 Render (INT32 b[2]); - virtual bool Write (UINT32 adr, UINT32 val, UINT32 id=0); - virtual bool Read (UINT32 adr, UINT32 & val, UINT32 id=0); + virtual void Tick (unsigned int clocks); + virtual unsigned int Render (int b[2]); + virtual bool Write (unsigned int adr, unsigned int val, unsigned int id=0); + virtual bool Read (unsigned int adr, unsigned int & val, unsigned int id=0); virtual void SetRate (double rate); virtual void SetClock (double rate); virtual void SetOption (int, int); virtual void SetMask(int m){ mask = m; } - virtual void SetStereoMix (int trk, xgm::INT16 mixl, xgm::INT16 mixr); - virtual ITrackInfo *GetTrackInfo(int trk); - - void SetCPU(NES_CPU* cpu_); + virtual void SetStereoMix (int trk, short mixl, short mixr); }; } diff --git a/src/engine/platform/sound/nes_nsfplay/nes_fds.cpp b/src/engine/platform/sound/nes_nsfplay/nes_fds.cpp index 1e08100c..f3e61dec 100644 --- a/src/engine/platform/sound/nes_nsfplay/nes_fds.cpp +++ b/src/engine/platform/sound/nes_nsfplay/nes_fds.cpp @@ -1,5 +1,7 @@ #include +#include #include "nes_fds.h" +#include "common.h" namespace xgm { @@ -22,11 +24,11 @@ NES_FDS::NES_FDS () Reset(); } -NES_FDS::‾NES_FDS () +NES_FDS::~NES_FDS () { } -void NES_FDS::SetStereoMix(int trk, INT16 mixl, INT16 mixr) +void NES_FDS::SetStereoMix(int trk, short mixl, short mixr) { if (trk < 0) return; if (trk > 1) return; @@ -34,20 +36,6 @@ void NES_FDS::SetStereoMix(int trk, INT16 mixl, INT16 mixr) sm[1] = mixr; } -ITrackInfo *NES_FDS::GetTrackInfo(int trk) -{ - trkinfo.max_volume = 32; - trkinfo.volume = last_vol; - trkinfo.key = last_vol > 0; - trkinfo._freq = last_freq; - trkinfo.freq = (double(last_freq) * clock) / (65536.0 * 64.0); - trkinfo.tone = env_out[EMOD]; - for(int i=0;i<64;i++) - trkinfo.wave[i] = wave[TWAV][i]; - - return &trkinfo; -} - void NES_FDS::SetClock (double c) { clock = c; @@ -61,8 +49,8 @@ void NES_FDS::SetRate (double r) double cutoff = double(option[OPT_CUTOFF]); double leak = 0.0; if (cutoff > 0) - leak = ::exp(-2.0 * 3.14159 * cutoff / rate); - rc_k = INT32(leak * double(1<= period) { // clock the envelope @@ -158,22 +146,22 @@ void NES_FDS::Tick (UINT32 clocks) if (!mod_halt) { // advance phase, adjust for modulator - UINT32 start_pos = phase[TMOD] >> 16; + unsigned int start_pos = phase[TMOD] >> 16; phase[TMOD] += (clocks * freq[TMOD]); - UINT32 end_pos = phase[TMOD] >> 16; + unsigned int end_pos = phase[TMOD] >> 16; // wrap the phase to the 64-step table (+ 16 bit accumulator) phase[TMOD] = phase[TMOD] & 0x3FFFFF; // execute all clocked steps - for (UINT32 p = start_pos; p < end_pos; ++p) + for (unsigned int p = start_pos; p < end_pos; ++p) { - INT32 wv = wave[TMOD][p & 0x3F]; + int wv = wave[TMOD][p & 0x3F]; if (wv == 4) // 4 resets mod position mod_pos = 0; else { - const INT32 BIAS[8] = { 0, 1, 2, 4, 0, -4, -2, -1 }; + const int BIAS[8] = { 0, 1, 2, 4, 0, -4, -2, -1 }; mod_pos += BIAS[wv]; mod_pos &= 0x7F; // 7-bit clamp } @@ -184,16 +172,16 @@ void NES_FDS::Tick (UINT32 clocks) if (!wav_halt) { // complex mod calculation - INT32 mod = 0; + int mod = 0; if (env_out[EMOD] != 0) // skip if modulator off { // convert mod_pos to 7-bit signed - INT32 pos = (mod_pos < 64) ? mod_pos : (mod_pos-128); + int pos = (mod_pos < 64) ? mod_pos : (mod_pos-128); // multiply pos by gain, // shift off 4 bits but with odd "rounding" behaviour - INT32 temp = pos * env_out[EMOD]; - INT32 rem = temp & 0x0F; + int temp = pos * env_out[EMOD]; + int rem = temp & 0x0F; temp >>= 4; if ((rem > 0) && ((temp & 0x80) == 0)) { @@ -216,7 +204,7 @@ void NES_FDS::Tick (UINT32 clocks) } // advance wavetable position - INT32 f = freq[TWAV] + mod; + int f = freq[TWAV] + mod; phase[TWAV] = phase[TWAV] + (clocks * f); phase[TWAV] = phase[TWAV] & 0x3FFFFF; // wrap @@ -225,7 +213,7 @@ void NES_FDS::Tick (UINT32 clocks) } // output volume caps at 32 - INT32 vol_out = env_out[EVOL]; + int vol_out = env_out[EVOL]; if (vol_out > 32) vol_out = 32; // final output @@ -242,32 +230,32 @@ void NES_FDS::Tick (UINT32 clocks) last_vol = vol_out; } -UINT32 NES_FDS::Render (INT32 b[2]) +unsigned int NES_FDS::Render (int b[2]) { // 8 bit approximation of master volume const double MASTER_VOL = 2.4 * 1223.0; // max FDS vol vs max APU square (arbitrarily 1223) const double MAX_OUT = 32.0f * 63.0f; // value that should map to master vol - const INT32 MASTER[4] = { + const int MASTER[4] = { int((MASTER_VOL / MAX_OUT) * 256.0 * 2.0f / 2.0f), int((MASTER_VOL / MAX_OUT) * 256.0 * 2.0f / 3.0f), int((MASTER_VOL / MAX_OUT) * 256.0 * 2.0f / 4.0f), int((MASTER_VOL / MAX_OUT) * 256.0 * 2.0f / 5.0f) }; - INT32 v = fout * MASTER[master_vol] >> 8; + int v = fout * MASTER[master_vol] >> 8; // lowpass RC filter - INT32 rc_out = ((rc_accum * rc_k) + (v * rc_l)) >> RC_BITS; + int rc_out = ((rc_accum * rc_k) + (v * rc_l)) >> RC_BITS; rc_accum = rc_out; v = rc_out; // output mix - INT32 m = mask ? 0 : v; + int m = mask ? 0 : v; b[0] = (m * sm[0]) >> 7; b[1] = (m * sm[1]) >> 7; return 2; } -bool NES_FDS::Write (UINT32 adr, UINT32 val, UINT32 id) +bool NES_FDS::Write (unsigned int adr, unsigned int val, unsigned int id) { // $4023 master I/O enable/disable if (adr == 0x4023) @@ -368,7 +356,7 @@ bool NES_FDS::Write (UINT32 adr, UINT32 val, UINT32 id) return false; } -bool NES_FDS::Read (UINT32 adr, UINT32 & val, UINT32 id) +bool NES_FDS::Read (unsigned int adr, unsigned int & val, unsigned int id) { if (adr >= 0x4040 && adr <= 0x407F) { diff --git a/src/engine/platform/sound/nes_nsfplay/nes_fds.h b/src/engine/platform/sound/nes_nsfplay/nes_fds.h index 67c60fd1..180841dd 100644 --- a/src/engine/platform/sound/nes_nsfplay/nes_fds.h +++ b/src/engine/platform/sound/nes_nsfplay/nes_fds.h @@ -1,17 +1,9 @@ #ifndef _NES_FDS_H_ #define _NES_FDS_H_ -#include "../device.h" namespace xgm { -class TrackInfoFDS : public TrackInfoBasic -{ -public: - INT16 wave[64]; - virtual IDeviceInfo *Clone(){ return new TrackInfoFDS(*this); } -}; - -class NES_FDS : public ISoundChip +class NES_FDS { public: enum @@ -25,57 +17,55 @@ public: protected: double rate, clock; int mask; - INT32 sm[2]; // stereo mix - INT32 fout; // current output - TrackInfoFDS trkinfo; + int sm[2]; // stereo mix + int fout; // current output int option[OPT_END]; bool master_io; - UINT32 master_vol; - UINT32 last_freq; // for trackinfo - UINT32 last_vol; // for trackinfo + unsigned int master_vol; + unsigned int last_freq; // for trackinfo + unsigned int last_vol; // for trackinfo // two wavetables enum { TMOD=0, TWAV=1 }; - INT32 wave[2][64]; - UINT32 freq[2]; - UINT32 phase[2]; + int wave[2][64]; + unsigned int freq[2]; + unsigned int phase[2]; bool wav_write; bool wav_halt; bool env_halt; bool mod_halt; - UINT32 mod_pos; - UINT32 mod_write_pos; + unsigned int mod_pos; + unsigned int mod_write_pos; // two ramp envelopes enum { EMOD=0, EVOL=1 }; bool env_mode[2]; bool env_disable[2]; - UINT32 env_timer[2]; - UINT32 env_speed[2]; - UINT32 env_out[2]; - UINT32 master_env_speed; + unsigned int env_timer[2]; + unsigned int env_speed[2]; + unsigned int env_out[2]; + unsigned int master_env_speed; // 1-pole RC lowpass filter - INT32 rc_accum; - INT32 rc_k; - INT32 rc_l; + int rc_accum; + int rc_k; + int rc_l; public: NES_FDS (); - virtual ‾ NES_FDS (); + ~NES_FDS (); virtual void Reset (); - virtual void Tick (UINT32 clocks); - virtual UINT32 Render (INT32 b[2]); - virtual bool Write (UINT32 adr, UINT32 val, UINT32 id=0); - virtual bool Read (UINT32 adr, UINT32 & val, UINT32 id=0); + virtual void Tick (unsigned int clocks); + virtual unsigned int Render (int b[2]); + virtual bool Write (unsigned int adr, unsigned int val, unsigned int id=0); + virtual bool Read (unsigned int adr, unsigned int & val, unsigned int id=0); virtual void SetRate (double); virtual void SetClock (double); virtual void SetOption (int, int); virtual void SetMask(int m){ mask = m&1; } - virtual void SetStereoMix (int trk, INT16 mixl, INT16 mixr); - virtual ITrackInfo *GetTrackInfo(int trk); + virtual void SetStereoMix (int trk, short mixl, short mixr); }; } // namespace xgm diff --git a/src/engine/platform/sound/nes_nsfplay/nes_mmc5.cpp b/src/engine/platform/sound/nes_nsfplay/nes_mmc5.cpp index 9243f659..500be87c 100644 --- a/src/engine/platform/sound/nes_nsfplay/nes_mmc5.cpp +++ b/src/engine/platform/sound/nes_nsfplay/nes_mmc5.cpp @@ -1,11 +1,11 @@ #include "nes_mmc5.h" +#include "common.h" namespace xgm { NES_MMC5::NES_MMC5 () { - cpu = NULL; SetClock (DEFAULT_CLOCK); SetRate (DEFAULT_RATE); option[OPT_NONLINEAR_MIXER] = true; @@ -15,19 +15,19 @@ namespace xgm // square nonlinear mix, same as 2A03 square_table[0] = 0; for(int i=1;i<32;i++) - square_table[i]=(INT32)((8192.0*95.88)/(8128.0/i+100)); + square_table[i]=(int)((8192.0*95.88)/(8128.0/i+100)); // 2A03 style nonlinear pcm mix with double the bits //pcm_table[0] = 0; - //INT32 wd = 22638; + //int wd = 22638; //for(int d=1;d<256; ++d) - // pcm_table[d] = (INT32)((8192.0*159.79)/(100.0+1.0/((double)d/wd))); + // pcm_table[d] = (int)((8192.0*159.79)/(100.0+1.0/((double)d/wd))); // linear pcm mix (actual hardware seems closer to this) pcm_table[0] = 0; double pcm_scale = 32.0; for (int d=1; d<256; ++d) - pcm_table[d] = (INT32)(double(d) * pcm_scale); + pcm_table[d] = (int)(double(d) * pcm_scale); // stereo mix for(int c=0;c<2;++c) @@ -35,7 +35,7 @@ namespace xgm sm[c][t] = 128; } - NES_MMC5::‾NES_MMC5 () + NES_MMC5::~NES_MMC5 () { } @@ -124,9 +124,9 @@ namespace xgm } } - INT32 NES_MMC5::calc_sqr (int i, UINT32 clocks) + int NES_MMC5::calc_sqr (int i, unsigned int clocks) { - static const INT16 sqrtbl[4][16] = { + static const short sqrtbl[4][16] = { {0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0}, @@ -140,7 +140,7 @@ namespace xgm scounter[i] -= (freq[i] + 1); } - INT32 ret = 0; + int ret = 0; if (length_counter[i] > 0) { // note MMC5 does not silence the highest 8 frequencies like APU, @@ -153,7 +153,7 @@ namespace xgm return ret; } - void NES_MMC5::TickFrameSequence (UINT32 clocks) + void NES_MMC5::TickFrameSequence (unsigned int clocks) { frame_sequence_count += clocks; while (frame_sequence_count > 7458) @@ -163,28 +163,28 @@ namespace xgm } } - void NES_MMC5::Tick (UINT32 clocks) + void NES_MMC5::Tick (unsigned int clocks) { out[0] = calc_sqr(0, clocks); out[1] = calc_sqr(1, clocks); out[2] = pcm; } - UINT32 NES_MMC5::Render (INT32 b[2]) + unsigned int NES_MMC5::Render (int b[2]) { out[0] = (mask & 1) ? 0 : out[0]; out[1] = (mask & 2) ? 0 : out[1]; out[2] = (mask & 4) ? 0 : out[2]; - INT32 m[3]; + int m[3]; if(option[OPT_NONLINEAR_MIXER]) { // squares nonlinear - INT32 voltage = square_table[out[0] + out[1]]; + int voltage = square_table[out[0] + out[1]]; m[0] = out[0] << 6; m[1] = out[1] << 6; - INT32 ref = m[0] + m[1]; + int ref = m[0] + m[1]; if (ref > 0) { m[0] = (m[0] * voltage) / ref; @@ -224,11 +224,11 @@ namespace xgm return 2; } - bool NES_MMC5::Write (UINT32 adr, UINT32 val, UINT32 id) + bool NES_MMC5::Write (unsigned int adr, unsigned int val, unsigned int id) { int ch; - static const UINT8 length_table[32] = { + static const unsigned char length_table[32] = { 0x0A, 0xFE, 0x14, 0x02, 0x28, 0x04, @@ -329,19 +329,8 @@ namespace xgm return true; } - bool NES_MMC5::Read (UINT32 adr, UINT32 & val, UINT32 id) + bool NES_MMC5::Read (unsigned int adr, unsigned int & val, unsigned int id) { - // in PCM read mode, reads from $8000-$C000 automatically load the PCM output - if (pcm_mode && (0x8000 <= adr) && (adr < 0xC000) && cpu) - { - pcm_mode = false; // prevent recursive entry - UINT32 pcm_read; - cpu->Read(adr, pcm_read); - pcm_read &= 0xFF; - if (pcm_read != 0) - pcm = pcm_read; - pcm_mode = true; - } if ((0x5000 <= adr) && (adr < 0x5008)) { @@ -373,50 +362,11 @@ namespace xgm return false; } - void NES_MMC5::SetStereoMix(int trk, xgm::INT16 mixl, xgm::INT16 mixr) + void NES_MMC5::SetStereoMix(int trk, short mixl, short mixr) { if (trk < 0) return; if (trk > 2) return; sm[0][trk] = mixl; sm[1][trk] = mixr; } - - ITrackInfo *NES_MMC5::GetTrackInfo(int trk) - { - assert(trk<3); - - if (trk < 2) // square - { - trkinfo[trk]._freq = freq[trk]; - if(freq[trk]) - trkinfo[trk].freq = clock/16/(freq[trk] + 1); - else - trkinfo[trk].freq = 0; - - trkinfo[trk].output = out[trk]; - trkinfo[trk].max_volume = 15; - trkinfo[trk].volume = volume[trk]+(envelope_disable[trk]?0:0x10); - trkinfo[trk].key = (envelope_disable[trk]?(volume[trk]>0): (envelope_counter[trk]>0)); - trkinfo[trk].tone = duty[trk]; - } - else // pcm - { - trkinfo[trk]._freq = 0; - trkinfo[trk].freq = 0; - trkinfo[trk].output = out[2]; - trkinfo[trk].max_volume = 255; - trkinfo[trk].volume = pcm; - trkinfo[trk].key = 0; - trkinfo[trk].tone = pcm_mode ? 1 : 0; - } - - return &trkinfo[trk]; - } - - // pcm read mode requires CPU read access - void NES_MMC5::SetCPU(NES_CPU* cpu_) - { - cpu = cpu_; - } - }// namespace diff --git a/src/engine/platform/sound/nes_nsfplay/nes_mmc5.h b/src/engine/platform/sound/nes_nsfplay/nes_mmc5.h index 5747ab0d..d0ae8bd0 100644 --- a/src/engine/platform/sound/nes_nsfplay/nes_mmc5.h +++ b/src/engine/platform/sound/nes_nsfplay/nes_mmc5.h @@ -1,11 +1,9 @@ #ifndef _NES_MMC5_H_ #define _NES_MMC5_H_ -#include "../device.h" -#include "../CPU/nes_cpu.h" namespace xgm { - class NES_MMC5:public ISoundChip + class NES_MMC5 { public: enum @@ -14,21 +12,20 @@ namespace xgm protected: int option[OPT_END]; int mask; - INT32 sm[2][3]; // stereo panning - UINT8 ram[0x6000 - 0x5c00]; - UINT8 reg[8]; - UINT8 mreg[2]; - UINT8 pcm; // PCM channel + int sm[2][3]; // stereo panning + unsigned char ram[0x6000 - 0x5c00]; + unsigned char reg[8]; + unsigned char mreg[2]; + unsigned char pcm; // PCM channel bool pcm_mode; // PCM channel - NES_CPU* cpu; // PCM channel reads need CPU access - UINT32 scounter[2]; // frequency divider - UINT32 sphase[2]; // phase counter + unsigned int scounter[2]; // frequency divider + unsigned int sphase[2]; // phase counter - UINT32 duty[2]; - UINT32 volume[2]; - UINT32 freq[2]; - INT32 out[3]; + unsigned int duty[2]; + unsigned int volume[2]; + unsigned int freq[2]; + int out[3]; bool enable[2]; bool envelope_disable[2]; // エンベロープ有効フラグ @@ -43,30 +40,26 @@ namespace xgm int frame_sequence_count; double clock, rate; - INT32 calc_sqr (int i, UINT32 clocks); - INT32 square_table[32]; - INT32 pcm_table[256]; - TrackInfoBasic trkinfo[3]; + int calc_sqr (int i, unsigned int clocks); + int square_table[32]; + int pcm_table[256]; public: NES_MMC5 (); - ‾NES_MMC5 (); + ~NES_MMC5 (); void FrameSequence (); - void TickFrameSequence (UINT32 clocks); + void TickFrameSequence (unsigned int clocks); virtual void Reset (); - virtual void Tick (UINT32 clocks); - virtual UINT32 Render (INT32 b[2]); - virtual bool Write (UINT32 adr, UINT32 val, UINT32 id=0); - virtual bool Read (UINT32 adr, UINT32 & val, UINT32 id=0); + virtual void Tick (unsigned int clocks); + virtual unsigned int Render (int b[2]); + virtual bool Write (unsigned int adr, unsigned int val, unsigned int id=0); + virtual bool Read (unsigned int adr, unsigned int & val, unsigned int id=0); virtual void SetOption (int id, int b); virtual void SetClock (double); virtual void SetRate (double); virtual void SetMask (int m){ mask = m; } - virtual void SetStereoMix (int trk, xgm::INT16 mixl, xgm::INT16 mixr); - virtual ITrackInfo *GetTrackInfo(int trk); - - void SetCPU(NES_CPU* cpu_); + virtual void SetStereoMix (int trk, short mixl, short mixr); }; } diff --git a/src/engine/platform/sound/nes_nsfplay/nes_n106.cpp b/src/engine/platform/sound/nes_nsfplay/nes_n106.cpp index ae793dc0..25e80fb4 100644 --- a/src/engine/platform/sound/nes_nsfplay/nes_n106.cpp +++ b/src/engine/platform/sound/nes_nsfplay/nes_n106.cpp @@ -1,5 +1,6 @@ #include #include "nes_n106.h" +#include "common.h" namespace xgm { @@ -18,11 +19,11 @@ NES_N106::NES_N106 () Reset(); } -NES_N106::‾NES_N106 () +NES_N106::~NES_N106 () { } -void NES_N106::SetStereoMix (int trk, INT16 mixl, INT16 mixr) +void NES_N106::SetStereoMix (int trk, short mixl, short mixr) { if (trk < 0 || trk >= 8) return; trk = 7-trk; // displayed channels are inverted @@ -30,42 +31,6 @@ void NES_N106::SetStereoMix (int trk, INT16 mixl, INT16 mixr) sm[1][trk] = mixr; } -ITrackInfo *NES_N106::GetTrackInfo (int trk) -{ - int channels = get_channels(); - int channel = 7-trk; // invert the track display - - TrackInfoN106* t = &trkinfo[channel]; - - if (trk >= channels) - { - t->max_volume = 15; - t->volume = 0; - t->_freq = 0; - t->wavelen = 0; - t->tone = -1; - t->output = 0; - t->key = false; - t->freq = 0; - } - else - { - t->max_volume = 15; - t->volume = get_vol(channel); - t->_freq = get_freq(channel); - t->wavelen = get_len(channel); - t->tone = get_off(channel); - t->output = fout[channel]; - - t->key = (t->volume > 0) && (t->_freq > 0); - t->freq = (double(t->_freq) * clock) / double(15 * 65536 * channels * t->wavelen); - - for (int i=0; i < t->wavelen; ++i) - t->wave[i] = get_sample((i+t->tone)&0xFF); - } - - return t; -} void NES_N106::SetClock (double c) { @@ -120,7 +85,7 @@ void NES_N106::Reset () Write(0xF800, 0x00); // select $00 without auto-increment } -void NES_N106::Tick (UINT32 clocks) +void NES_N106::Tick (unsigned int clocks) { if (master_disable) return; @@ -132,24 +97,24 @@ void NES_N106::Tick (UINT32 clocks) { int channel = 7-tick_channel; - UINT32 phase = get_phase(channel); - UINT32 freq = get_freq(channel); - UINT32 len = get_len(channel); - UINT32 off = get_off(channel); - INT32 vol = get_vol(channel); + unsigned int phase = get_phase(channel); + unsigned int freq = get_freq(channel); + unsigned int len = get_len(channel); + unsigned int off = get_off(channel); + int vol = get_vol(channel); // accumulate 24-bit phase phase = (phase + freq) & 0x00FFFFFF; // wrap phase if wavelength exceeded - UINT32 hilen = len << 16; + unsigned int hilen = len << 16; while (phase >= hilen) phase -= hilen; // write back phase set_phase(phase, channel); // fetch sample (note: N163 output is centred at 8, and inverted w.r.t 2A03) - INT32 sample = 8 - get_sample(((phase >> 16) + off) & 0xFF); + int sample = 8 - get_sample(((phase >> 16) + off) & 0xFF); fout[channel] = sample * vol; // cycle to next channel every 15 clocks @@ -160,7 +125,7 @@ void NES_N106::Tick (UINT32 clocks) } } -UINT32 NES_N106::Render (INT32 b[2]) +unsigned int NES_N106::Render (int b[2]) { b[0] = 0; b[1] = 0; @@ -217,7 +182,7 @@ UINT32 NES_N106::Render (INT32 b[2]) } // mix together, increase output level by 8 bits, roll off 7 bits from sm - INT32 MIX[9] = { 256/1, 256/1, 256/2, 256/3, 256/4, 256/5, 256/6, 256/6, 256/6 }; + int MIX[9] = { 256/1, 256/1, 256/2, 256/3, 256/4, 256/5, 256/6, 256/6, 256/6 }; b[0] = (b[0] * MIX[channels]) >> 7; b[1] = (b[1] * MIX[channels]) >> 7; // when approximating the serial multiplex as a straight mix, once the @@ -233,14 +198,14 @@ UINT32 NES_N106::Render (INT32 b[2]) // and lower volumes on others. Using 6.0x as a rough "one size fits all". const double MASTER_VOL = 6.0 * 1223.0; const double MAX_OUT = 15.0 * 15.0 * 256.0; // max digital value - const INT32 GAIN = int((MASTER_VOL / MAX_OUT) * 256.0f); + const int GAIN = int((MASTER_VOL / MAX_OUT) * 256.0f); b[0] = (b[0] * GAIN) >> 8; b[1] = (b[1] * GAIN) >> 8; return 2; } -bool NES_N106::Write (UINT32 adr, UINT32 val, UINT32 id) +bool NES_N106::Write (unsigned int adr, unsigned int val, unsigned int id) { if (adr == 0xE000) // master disable { @@ -286,7 +251,7 @@ bool NES_N106::Write (UINT32 adr, UINT32 val, UINT32 id) return false; } -bool NES_N106::Read (UINT32 adr, UINT32 & val, UINT32 id) +bool NES_N106::Read (unsigned int adr, unsigned int & val, unsigned int id) { if (adr == 0x4800) // register read { @@ -302,7 +267,7 @@ bool NES_N106::Read (UINT32 adr, UINT32 & val, UINT32 id) // register decoding/encoding functions // -inline UINT32 NES_N106::get_phase (int channel) +inline unsigned int NES_N106::get_phase (int channel) { // 24-bit phase stored in channel regs 1/3/5 channel = channel << 3; @@ -311,7 +276,7 @@ inline UINT32 NES_N106::get_phase (int channel) + (reg[0x45 + channel] << 16); } -inline UINT32 NES_N106::get_freq (int channel) +inline unsigned int NES_N106::get_freq (int channel) { // 19-bit frequency stored in channel regs 0/2/4 channel = channel << 3; @@ -320,28 +285,28 @@ inline UINT32 NES_N106::get_freq (int channel) + ((reg[0x44 + channel] & 0x03) << 16); } -inline UINT32 NES_N106::get_off (int channel) +inline unsigned int NES_N106::get_off (int channel) { // 8-bit offset stored in channel reg 6 channel = channel << 3; return reg[0x46 + channel]; } -inline UINT32 NES_N106::get_len (int channel) +inline unsigned int NES_N106::get_len (int channel) { // 6-bit<<3 length stored obscurely in channel reg 4 channel = channel << 3; return 256 - (reg[0x44 + channel] & 0xFC); } -inline INT32 NES_N106::get_vol (int channel) +inline int NES_N106::get_vol (int channel) { // 4-bit volume stored in channel reg 7 channel = channel << 3; return reg[0x47 + channel] & 0x0F; } -inline INT32 NES_N106::get_sample (UINT32 index) +inline int NES_N106::get_sample (unsigned int index) { // every sample becomes 2 samples in regs return (index&1) ? @@ -355,7 +320,7 @@ inline int NES_N106::get_channels () return ((reg[0x7F] >> 4) & 0x07) + 1; } -inline void NES_N106::set_phase (UINT32 phase, int channel) +inline void NES_N106::set_phase (unsigned int phase, int channel) { // 24-bit phase stored in channel regs 1/3/5 channel = channel << 3; diff --git a/src/engine/platform/sound/nes_nsfplay/nes_n106.h b/src/engine/platform/sound/nes_nsfplay/nes_n106.h index aebb6cb4..5ce937e2 100644 --- a/src/engine/platform/sound/nes_nsfplay/nes_n106.h +++ b/src/engine/platform/sound/nes_nsfplay/nes_n106.h @@ -1,18 +1,10 @@ #ifndef _NES_N106_H_ #define _NES_N106_H_ -#include "../device.h" namespace xgm { -class TrackInfoN106 : public TrackInfoBasic -{ -public: - int wavelen; - INT16 wave[256]; - virtual IDeviceInfo *Clone(){ return new TrackInfoN106(*this); } -}; -class NES_N106:public ISoundChip +class NES_N106 { public: enum @@ -26,13 +18,12 @@ public: protected: double rate, clock; int mask; - INT32 sm[2][8]; // stereo mix - INT32 fout[8]; // current output - TrackInfoN106 trkinfo[8]; + int sm[2][8]; // stereo mix + int fout[8]; // current output int option[OPT_END]; bool master_disable; - UINT32 reg[0x80]; // all state is contained here + unsigned int reg[0x80]; // all state is contained here unsigned int reg_select; bool reg_advance; int tick_channel; @@ -42,31 +33,30 @@ protected: int render_subclock; // convenience functions to interact with regs - inline UINT32 get_phase (int channel); - inline UINT32 get_freq (int channel); - inline UINT32 get_off (int channel); - inline UINT32 get_len (int channel); - inline INT32 get_vol (int channel); - inline INT32 get_sample (UINT32 index); + inline unsigned int get_phase (int channel); + inline unsigned int get_freq (int channel); + inline unsigned int get_off (int channel); + inline unsigned int get_len (int channel); + inline int get_vol (int channel); + inline int get_sample (unsigned int index); inline int get_channels (); // for storing back the phase after modifying - inline void set_phase (UINT32 phase, int channel); + inline void set_phase (unsigned int phase, int channel); public: NES_N106 (); - ‾NES_N106 (); + ~NES_N106 (); virtual void Reset (); - virtual void Tick (UINT32 clocks); - virtual UINT32 Render (INT32 b[2]); - virtual bool Write (UINT32 adr, UINT32 val, UINT32 id=0); - virtual bool Read (UINT32 adr, UINT32 & val, UINT32 id=0); + virtual void Tick (unsigned int clocks); + virtual unsigned int Render (int b[2]); + virtual bool Write (unsigned int adr, unsigned int val, unsigned int id=0); + virtual bool Read (unsigned int adr, unsigned int & val, unsigned int id=0); virtual void SetRate (double); virtual void SetClock (double); virtual void SetOption (int, int); virtual void SetMask (int m); - virtual void SetStereoMix (int trk, INT16 mixl, INT16 mixr); - virtual ITrackInfo *GetTrackInfo(int trk); + virtual void SetStereoMix (int trk, short mixl, short mixr); }; } // namespace xgm diff --git a/src/engine/platform/sound/nes_nsfplay/nes_vrc6.cpp b/src/engine/platform/sound/nes_nsfplay/nes_vrc6.cpp index c4610940..754d44cf 100644 --- a/src/engine/platform/sound/nes_nsfplay/nes_vrc6.cpp +++ b/src/engine/platform/sound/nes_nsfplay/nes_vrc6.cpp @@ -1,4 +1,5 @@ #include "nes_vrc6.h" +#include "common.h" namespace xgm { @@ -16,11 +17,11 @@ namespace xgm sm[c][t] = 128; } - NES_VRC6::‾NES_VRC6 () + NES_VRC6::~NES_VRC6 () { } - void NES_VRC6::SetStereoMix(int trk, xgm::INT16 mixl, xgm::INT16 mixr) + void NES_VRC6::SetStereoMix(int trk, short mixl, short mixr) { if (trk < 0) return; if (trk > 2) return; @@ -28,32 +29,6 @@ namespace xgm sm[1][trk] = mixr; } - ITrackInfo *NES_VRC6::GetTrackInfo(int trk) - { - if(trk<2) - { - trkinfo[trk].max_volume = 15; - trkinfo[trk].volume = volume[trk]; - trkinfo[trk]._freq = freq2[trk]; - trkinfo[trk].freq = freq2[trk]?clock/16/(freq2[trk]+1):0; - trkinfo[trk].tone = duty[trk]; - trkinfo[trk].key = (volume[trk]>0)&&enable[trk]&&!gate[trk]; - return &trkinfo[trk]; - } - else if(trk==2) - { - trkinfo[2].max_volume = 255; - trkinfo[2].volume = volume[2]; - trkinfo[2]._freq = freq2[2]; - trkinfo[2].freq = freq2[2]?clock/14/(freq2[2]+1):0; - trkinfo[2].tone = -1; - trkinfo[2].key = (enable[2]>0); - return &trkinfo[2]; - } - else - return NULL; - } - void NES_VRC6::SetClock (double c) { clock = c; @@ -91,9 +66,9 @@ namespace xgm phase[0] = 2; } - INT16 NES_VRC6::calc_sqr (int i, UINT32 clocks) + short NES_VRC6::calc_sqr (int i, unsigned int clocks) { - static const INT16 sqrtbl[8][16] = { + static const short sqrtbl[8][16] = { {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1}, @@ -121,7 +96,7 @@ namespace xgm || sqrtbl[duty[i]][phase[i]])? volume[i] : 0; } - INT16 NES_VRC6::calc_saw (UINT32 clocks) + short NES_VRC6::calc_saw (unsigned int clocks) { if (!enable[2]) return 0; @@ -151,16 +126,16 @@ namespace xgm return phase[2] >> 3; } - void NES_VRC6::Tick (UINT32 clocks) + void NES_VRC6::Tick (unsigned int clocks) { out[0] = calc_sqr(0,clocks); out[1] = calc_sqr(1,clocks); out[2] = calc_saw(clocks); } - UINT32 NES_VRC6::Render (INT32 b[2]) + unsigned int NES_VRC6::Render (int b[2]) { - INT32 m[3]; + int m[3]; m[0] = out[0]; m[1] = out[1]; m[2] = out[2]; @@ -182,14 +157,14 @@ namespace xgm //b[1] >>= (7 - 7); // master volume adjustment - const INT32 MASTER = INT32(256.0 * 1223.0 / 1920.0); + const int MASTER = int(256.0 * 1223.0 / 1920.0); b[0] = (b[0] * MASTER) >> 8; b[1] = (b[1] * MASTER) >> 8; return 2; } - bool NES_VRC6::Write (UINT32 adr, UINT32 val, UINT32 id) + bool NES_VRC6::Write (unsigned int adr, unsigned int val, unsigned int id) { int ch, cmap[4] = { 0, 0, 1, 2 }; @@ -255,7 +230,7 @@ namespace xgm return true; } - bool NES_VRC6::Read (UINT32 adr, UINT32 & val, UINT32 id) + bool NES_VRC6::Read (unsigned int adr, unsigned int & val, unsigned int id) { return false; } diff --git a/src/engine/platform/sound/nes_nsfplay/nes_vrc6.h b/src/engine/platform/sound/nes_nsfplay/nes_vrc6.h index 2bb64eb8..85fed39c 100644 --- a/src/engine/platform/sound/nes_nsfplay/nes_vrc6.h +++ b/src/engine/platform/sound/nes_nsfplay/nes_vrc6.h @@ -1,11 +1,10 @@ #ifndef _NES_VRC6_H_ #define _NES_VRC6_H_ -#include "../device.h" namespace xgm { - class NES_VRC6:public ISoundChip + class NES_VRC6 { public: enum @@ -13,42 +12,40 @@ namespace xgm OPT_END }; protected: - UINT32 counter[3]; // frequency divider - UINT32 phase[3]; // phase counter - UINT32 freq2[3]; // adjusted frequency + unsigned int counter[3]; // frequency divider + unsigned int phase[3]; // phase counter + unsigned int freq2[3]; // adjusted frequency int count14; // saw 14-stage counter //int option[OPT_END]; int mask; - INT32 sm[2][3]; // stereo mix + int sm[2][3]; // stereo mix int duty[2]; int volume[3]; int enable[3]; int gate[3]; - UINT32 freq[3]; - INT16 calc_sqr (int i, UINT32 clocks); - INT16 calc_saw (UINT32 clocks); + unsigned int freq[3]; + short calc_sqr (int i, unsigned int clocks); + short calc_saw (unsigned int clocks); bool halt; int freq_shift; double clock, rate; - INT32 out[3]; - TrackInfoBasic trkinfo[3]; + int out[3]; public: NES_VRC6 (); - ‾NES_VRC6 (); + ~NES_VRC6 (); virtual void Reset (); - virtual void Tick (UINT32 clocks); - virtual UINT32 Render (INT32 b[2]); - virtual bool Read (UINT32 adr, UINT32 & val, UINT32 id=0); - virtual bool Write (UINT32 adr, UINT32 val, UINT32 id=0); + virtual void Tick (unsigned int clocks); + virtual unsigned int Render (int b[2]); + virtual bool Read (unsigned int adr, unsigned int & val, unsigned int id=0); + virtual bool Write (unsigned int adr, unsigned int val, unsigned int id=0); virtual void SetClock (double); virtual void SetRate (double); virtual void SetOption (int, int); virtual void SetMask (int m){ mask = m; } - virtual void SetStereoMix (int trk, xgm::INT16 mixl, xgm::INT16 mixr); - virtual ITrackInfo *GetTrackInfo(int trk); + virtual void SetStereoMix (int trk, short mixl, short mixr); }; } // namespace