From a2de3c2ffe5998b75238e1c1d7e5cc0106c8ff00 Mon Sep 17 00:00:00 2001 From: scawful Date: Sat, 26 Aug 2023 02:33:19 -0400 Subject: [PATCH] SPC700 to get notified when ports are written --- src/app/emu/audio/apu.h | 6 +++--- src/app/emu/audio/dsp.cc | 22 +++++++++++----------- src/app/emu/audio/dsp.h | 8 ++++---- src/app/emu/audio/spc700.cc | 18 ++++++++++++++++++ src/app/emu/audio/spc700.h | 2 ++ src/app/emu/snes.cc | 35 +++++++++++++++++++++++++++++++++++ src/app/emu/snes.h | 3 +++ test/cpu_test.cc | 18 ------------------ 8 files changed, 76 insertions(+), 36 deletions(-) diff --git a/src/app/emu/audio/apu.h b/src/app/emu/audio/apu.h index 73d08aa9..d1b91d0d 100644 --- a/src/app/emu/audio/apu.h +++ b/src/app/emu/audio/apu.h @@ -61,7 +61,7 @@ class APU : public Observer { void Notify(uint32_t address, uint8_t data) override { if (address >= 0x2140 && address <= 0x2143) { - // Handle communication with the APU + spc700_.Notify(address, data); } } @@ -176,12 +176,12 @@ class APU : public Observer { void WriteDSPMemory(uint16_t address, uint8_t value); // Member variables to store internal APU state and resources - Memory &memory_; AudioRam &aram_; Clock &clock_; + Memory &memory_; + DigitalSignalProcessor dsp_; SPC700 spc700_{aram_}; - Dsp dsp_; std::vector audioSamples_; }; diff --git a/src/app/emu/audio/dsp.cc b/src/app/emu/audio/dsp.cc index 833550d0..0ebb342e 100644 --- a/src/app/emu/audio/dsp.cc +++ b/src/app/emu/audio/dsp.cc @@ -6,9 +6,9 @@ namespace yaze { namespace app { namespace emu { -void Dsp::Reset() {} +void DigitalSignalProcessor::Reset() {} -uint8_t Dsp::ReadVoiceReg(uint8_t voice, uint8_t reg) const { +uint8_t DigitalSignalProcessor::ReadVoiceReg(uint8_t voice, uint8_t reg) const { voice %= kNumVoices; switch (reg % kNumVoiceRegs) { case 0: @@ -37,7 +37,7 @@ uint8_t Dsp::ReadVoiceReg(uint8_t voice, uint8_t reg) const { } } -void Dsp::WriteVoiceReg(uint8_t voice, uint8_t reg, uint8_t value) { +void DigitalSignalProcessor::WriteVoiceReg(uint8_t voice, uint8_t reg, uint8_t value) { voice %= kNumVoices; switch (reg % kNumVoiceRegs) { case 0: @@ -69,11 +69,11 @@ void Dsp::WriteVoiceReg(uint8_t voice, uint8_t reg, uint8_t value) { } // Set the callbacks -void Dsp::SetSampleFetcher(SampleFetcher fetcher) { sample_fetcher_ = fetcher; } +void DigitalSignalProcessor::SetSampleFetcher(SampleFetcher fetcher) { sample_fetcher_ = fetcher; } -void Dsp::SetSamplePusher(SamplePusher pusher) { sample_pusher_ = pusher; } +void DigitalSignalProcessor::SetSamplePusher(SamplePusher pusher) { sample_pusher_ = pusher; } -int16_t Dsp::DecodeSample(uint8_t voice_num) { +int16_t DigitalSignalProcessor::DecodeSample(uint8_t voice_num) { Voice const& voice = voices_[voice_num]; uint16_t sample_address = voice.source_number; @@ -82,7 +82,7 @@ int16_t Dsp::DecodeSample(uint8_t voice_num) { return sample; } -int16_t Dsp::ProcessSample(uint8_t voice_num, int16_t sample) { +int16_t DigitalSignalProcessor::ProcessSample(uint8_t voice_num, int16_t sample) { Voice const& voice = voices_[voice_num]; // Adjust the pitch (for simplicity, we're just adjusting the sample value) @@ -96,7 +96,7 @@ int16_t Dsp::ProcessSample(uint8_t voice_num, int16_t sample) { return (left_sample + right_sample) / 2; } -void Dsp::MixSamples() { +void DigitalSignalProcessor::MixSamples() { int16_t mixed_sample = 0; for (uint8_t i = 0; i < kNumVoices; i++) { @@ -116,7 +116,7 @@ void Dsp::MixSamples() { sample_pusher_(mixed_sample); } -void Dsp::UpdateEnvelope(uint8_t voice) { +void DigitalSignalProcessor::UpdateEnvelope(uint8_t voice) { uint8_t adsr1 = ReadVoiceReg(voice, 0x05); uint8_t adsr2 = ReadVoiceReg(voice, 0x06); uint8_t gain = ReadVoiceReg(voice, 0x07); @@ -216,7 +216,7 @@ void Dsp::UpdateEnvelope(uint8_t voice) { } } -void Dsp::update_voice_state(uint8_t voice_num) { +void DigitalSignalProcessor::update_voice_state(uint8_t voice_num) { if (voice_num >= kNumVoices) return; Voice& voice = voices_[voice_num]; @@ -261,7 +261,7 @@ void Dsp::update_voice_state(uint8_t voice_num) { } } -void Dsp::process_envelope(uint8_t voice_num) { +void DigitalSignalProcessor::process_envelope(uint8_t voice_num) { if (voice_num >= kNumVoices) return; Voice& voice = voices_[voice_num]; diff --git a/src/app/emu/audio/dsp.h b/src/app/emu/audio/dsp.h index 7dd570e6..0d9c5d40 100644 --- a/src/app/emu/audio/dsp.h +++ b/src/app/emu/audio/dsp.h @@ -51,7 +51,7 @@ using SamplePusher = std::function; * */ -class Dsp { +class DigitalSignalProcessor { private: static const size_t kNumVoices = 8; static const size_t kNumVoiceRegs = 10; @@ -130,12 +130,12 @@ class Dsp { 180, 150, 110, 92, 55, 37, 18}}; // DSP Period Table - const std::vector> DspPeriodTable = { + const std::vector> DigitalSignalProcessorPeriodTable = { // ... Your DSP period table here ... }; // DSP Period Offset - const std::vector DspPeriodOffset = { + const std::vector DigitalSignalProcessorPeriodOffset = { // ... Your DSP period offsets here ... }; @@ -156,7 +156,7 @@ class Dsp { SamplePusher sample_pusher_; public: - Dsp() = default; + DigitalSignalProcessor() = default; void Reset(); diff --git a/src/app/emu/audio/spc700.cc b/src/app/emu/audio/spc700.cc index 24f1c518..6d4f0ff4 100644 --- a/src/app/emu/audio/spc700.cc +++ b/src/app/emu/audio/spc700.cc @@ -9,6 +9,24 @@ namespace emu { void SPC700::Reset() {} +void SPC700::Notify(uint32_t address, uint8_t data) { + // Check if the address corresponds to the APU's I/O ports + if (address >= 0x2140 && address <= 0x2143) { + // Handle the IPL process based on the address and data + if (address == 0x2140) { + // ... Handle data sent to APUIO0 ... + // For instance, checking for the $CC signal to start the APU program + } else if (address == 0x2141) { + // ... Handle data sent to APUIO1 ... + // This might involve storing data for the APU or signaling the DSP, etc. + } else if (address == 0x2142) { + // ... Handle data sent to APUIO2 ... + } else if (address == 0x2143) { + // ... Handle data sent to APUIO3 ... + } + } +} + void SPC700::ExecuteInstructions(uint8_t opcode) { switch (opcode) { // 8-bit Move Memory to Register diff --git a/src/app/emu/audio/spc700.h b/src/app/emu/audio/spc700.h index c2915794..75d9f7b9 100644 --- a/src/app/emu/audio/spc700.h +++ b/src/app/emu/audio/spc700.h @@ -70,6 +70,8 @@ class SPC700 { void Reset(); + void Notify(uint32_t address, uint8_t data); + void ExecuteInstructions(uint8_t opcode); // Read a byte from the memory-mapped registers diff --git a/src/app/emu/snes.cc b/src/app/emu/snes.cc index dc0382b6..e4019de0 100644 --- a/src/app/emu/snes.cc +++ b/src/app/emu/snes.cc @@ -379,6 +379,41 @@ void SNES::VBlankRoutine() { // ... } +void SNES::BootAPUWithIPL() { + // 1. Waiting for the SPC700 to be ready + while (!apu.IsReadySignalReceived()) { + // Active waiting (this can be optimized) + } + + // 2. Setting the starting address + const uint16_t startAddress = 0x0200; + memory_.WriteByte(0x2142, startAddress & 0xFF); // Lower byte + memory_.WriteByte(0x2143, startAddress >> 8); // Upper byte + memory_.WriteByte(0x2141, 0xCC); // Any non-zero value + memory_.WriteByte(0x2140, 0xCC); // Signal to start + + const int DATA_SIZE = 0x1000; // 4 KiB + + // 3. Sending data (simplified) + // Assuming a buffer `audioData` containing the audio program/data + uint8_t audioData[DATA_SIZE]; // Define DATA_SIZE and populate audioData as + // needed + for (int i = 0; i < DATA_SIZE; ++i) { + memory_.WriteByte(0x2141, audioData[i]); + memory_.WriteByte(0x2140, i & 0xFF); + while (memory_.ReadByte(0x2140) != (i & 0xFF)) + ; // Wait for acknowledgment + } + + // 4. Running the SPC700 program + memory_.WriteByte(0x2142, startAddress & 0xFF); // Lower byte + memory_.WriteByte(0x2143, startAddress >> 8); // Upper byte + memory_.WriteByte(0x2141, 0x00); // Zero to start the program + memory_.WriteByte(0x2140, 0xCE); // Increment by 2 + while (memory_.ReadByte(0x2140) != 0xCE) + ; // Wait for acknowledgment +} + void SNES::HandleInput() { // ... } diff --git a/src/app/emu/snes.h b/src/app/emu/snes.h index da250b20..ca917830 100644 --- a/src/app/emu/snes.h +++ b/src/app/emu/snes.h @@ -84,6 +84,9 @@ class SNES : public DMA { // VBlank routine void VBlankRoutine(); + // Boot the APU with the IPL ROM + void BootAPUWithIPL(); + // Controller input handling void HandleInput(); diff --git a/test/cpu_test.cc b/test/cpu_test.cc index 94cb2300..c8db4f0d 100644 --- a/test/cpu_test.cc +++ b/test/cpu_test.cc @@ -150,24 +150,6 @@ class CPUTest : public ::testing::Test { using ::testing::_; using ::testing::Return; -TEST_F(CPUTest, CPURunTest) { - // Arrange - EXPECT_CALL(mock_clock, UpdateClock(_)).Times(1); - EXPECT_CALL(mock_clock, GetCycleCount()).WillOnce(Return(1)); - EXPECT_CALL(mock_clock, ResetAccumulatedTime()).Times(1); - - mock_memory.InsertMemory(0x00, {0x69, 0x01, 0xEA, 0xEA}); - - // Act - mock_clock.UpdateClock(1.0); - cpu.Update(); - mock_clock.ResetAccumulatedTime(); - - // Assert - // Google Mock will automatically check the expectations - ASSERT_THAT(cpu.A, ::testing::Eq(0x01)); -} - // ============================================================================ // Infrastructure // ============================================================================