Inject SPC700 to APU, add APU and PPU observers

This commit is contained in:
scawful
2023-08-24 22:54:52 -04:00
parent 1cc0c45e79
commit 453a2575f4
6 changed files with 100 additions and 42 deletions

View File

@@ -15,10 +15,11 @@ const int kApuClockSpeed = 1024000; // 1.024 MHz
const int apuSampleRate = 32000; // 32 KHz
const int apuClocksPerSample = 64; // 64 clocks per sample
class APU : public SPC700, public Observer {
class APU : public Observer {
public:
// Initializes the APU with the necessary resources and dependencies
APU(Memory &memory, VirtualClock &clock) : memory_(memory), clock_(clock) {}
APU(Memory &memory, VirtualAudioRAM &aram, VirtualClock &clock)
: memory_(memory), clock_(clock), aram_(aram) {}
void Init();
@@ -61,11 +62,12 @@ class APU : public SPC700, public Observer {
uint8_t ReadDSPMemory(uint16_t address);
void WriteDSPMemory(uint16_t address, uint8_t value);
// Other internal methods for handling APU functionality
// Member variables to store internal APU state and resources
Memory &memory_;
VirtualClock &clock_;
VirtualAudioRAM &aram_;
SPC700 spc700_{aram_};
std::vector<int16_t> audioSamples_;
// Other state variables (registers, counters, channel settings, etc.)
};

View File

@@ -107,8 +107,6 @@ class ROMInfo {
uint16_t checksum;
uint16_t nmiVblVector;
uint16_t resetVector;
// Additional methods and constructors
};
class Observer {

View File

@@ -30,13 +30,19 @@ class IPPU {
namespace PPURegisters {
constexpr uint16_t INIDISP = 0x2100;
// OAM Size Register ($2101): Controls the size of the object/sprite, the base
// address, and the name selection for the OAM (Object Attribute Memory).
constexpr uint16_t OBJSEL = 0x2101;
// OAM Address Register ($2102-$2103): Sets the address for accessing OAM data.
constexpr uint16_t OAMADDL = 0x2102;
constexpr uint16_t OAMADDH = 0x2103;
// OAM Data Register ($2104): Holds the data to be written to the OAM at a
// specified address.
constexpr uint16_t OAMDATA = 0x2104;
// OAM Data Read Register ($2138): Allows reading data from the OAM.
@@ -44,37 +50,26 @@ namespace PPURegisters {
// Screen Mode Register ($2105): Defines the screen mode and character size for
// each background layer.
constexpr uint16_t BGMODE = 0x2105;
// Screen Pixelation Register ($2106): Sets the pixel size and screen
// designation for the mosaic display.
// BGx VRAM Location Registers ($2107-$210A): Define the location in VRAM where
// the background screen data is stored.
// BGx & BGy VRAM Location Registers ($210B-$210C): Set the base address for BG
// character data in VRAM.
// BGx Scroll Registers ($210D-$2114): Control the horizontal and vertical
// scroll values for each background layer.
// Video Port Control Register ($2115): Designates the VRAM address increment
// value.
// Video Port Address Register ($2116-$2117): Sets the initial address for
// reading from or writing to VRAM.
constexpr uint16_t INIDISP = 0x2100;
constexpr uint16_t OBJSEL = 0x2101;
constexpr uint16_t OAMADDL = 0x2102;
constexpr uint16_t OAMADDH = 0x2103;
constexpr uint16_t OAMDATA = 0x2104;
constexpr uint16_t BGMODE = 0x2105;
constexpr uint16_t MOSAIC = 0x2106;
// BGx VRAM Location Registers ($2107-$210A)
// Define the location in VRAM where the background screen data is stored.
constexpr uint16_t BG1SC = 0x2107;
constexpr uint16_t BG2SC = 0x2108;
constexpr uint16_t BG3SC = 0x2109;
constexpr uint16_t BG4SC = 0x210A;
// BGx & BGy VRAM Location Registers ($210B-$210C):
// Set the base address for BG character data in VRAM.
constexpr uint16_t BG12NBA = 0x210B;
constexpr uint16_t BG34NBA = 0x210C;
// BGx Scroll Registers ($210D-$2114): Control the horizontal and vertical
// scroll values for each background layer.
constexpr uint16_t BG1HOFS = 0x210D;
constexpr uint16_t BG1VOFS = 0x210E;
constexpr uint16_t BG2HOFS = 0x210F;
@@ -83,9 +78,16 @@ constexpr uint16_t BG3HOFS = 0x2111;
constexpr uint16_t BG3VOFS = 0x2112;
constexpr uint16_t BG4HOFS = 0x2113;
constexpr uint16_t BG4VOFS = 0x2114;
// Video Port Control Register ($2115): Designates the VRAM address increment
// value.
constexpr uint16_t VMAIN = 0x2115;
// Video Port Address Register ($2116-$2117): Sets the initial address for
// reading from or writing to VRAM.
constexpr uint16_t VMADDL = 0x2116;
constexpr uint16_t VMADDH = 0x2117;
constexpr uint16_t VMDATAL = 0x2118;
constexpr uint16_t VMDATAH = 0x2119;
constexpr uint16_t M7SEL = 0x211A;
@@ -166,12 +168,19 @@ struct MOSAIC {
};
struct BGSC {
explicit BGSC(uint8_t value)
: horizontal_tilemap_count(value & 0x01),
vertical_tilemap_count((value >> 1) & 0x01),
vram_address((value >> 2) & 0x3F) {}
uint8_t horizontal_tilemap_count : 1;
uint8_t vertical_tilemap_count : 1;
uint8_t vram_address : 6;
};
struct BGNBA {
explicit BGNBA(uint8_t value)
: chr_base_address_2(value & 0x0F),
chr_base_address_1((value >> 4) & 0x0F) {}
uint8_t chr_base_address_2 : 4;
uint8_t chr_base_address_1 : 4;
};
@@ -427,12 +436,10 @@ enum class BackgroundMode {
Mode1, // 2 layers, 4bpp (16 colors), 1 layer, 2bpp (4 colors)
Mode2, // 2 layers, 4bpp (16 colors), 1 layer for offset-per-tile
Mode3, // 1 layer, 8bpp (256 colors), 1 layer, 4bpp (16 colors)
Mode4, // 1 layer, 8bpp (256 colors), 1 layer, 2bpp (4 colors), 1 layer for
// offset-per-tile
Mode5, // 1 layer, 4bpp (16 colors), 1 layer, 2bpp (4 colors), high
// resolution
Mode6, // 1 layer, 4bpp (16 colors), 1 layer for offset-per-tile, high
// resolution
Mode4, // 1 layer, 8bpp (256 colors), 1 layer, 2bpp (4 colors)
// 1 layer for offset-per-tile
Mode5, // 1 layer, 4bpp (16 colors), 1 layer, 2bpp (4 colors) hi-res
Mode6, // 1 layer, 4bpp (16 colors), 1 layer for offset-per-tile, hi-res
Mode7, // 1 layer, 8bpp (256 colors), rotation/scaling
};
@@ -628,7 +635,7 @@ struct BackgroundLayer {
const int kPpuClockSpeed = 5369318; // 5.369318 MHz
class PPU : public Clock {
class PPU : public Clock, public Observer {
public:
// Initializes the PPU with the necessary resources and dependencies
PPU(Memory& memory, VirtualClock& clock) : memory_(memory), clock_(clock) {}
@@ -647,6 +654,10 @@ class PPU : public Clock {
void Update();
void UpdateInternalState(int cycles);
void Notify(uint32_t address, uint8_t data) override {
// Handle communication in the PPU.
}
// Reads a byte from the specified PPU register
uint8_t ReadRegister(uint16_t address);

View File

@@ -156,6 +156,10 @@ ROMInfo SNES::ReadRomHeader(uint32_t offset) {
}
void SNES::Init(ROM& rom) {
// Setup observers for the memory space
memory_.AddObserver(&apu);
memory_.AddObserver(&ppu);
// Load the ROM into memory and set up the memory mapping
memory_.Initialize(rom.vector());

View File

@@ -6,6 +6,7 @@
#include "app/emu/cpu.h"
#include "app/emu/dbg.h"
#include "app/emu/ppu.h"
#include "app/emu/spc700.h"
#include "app/rom.h"
namespace yaze {
@@ -104,10 +105,11 @@ class SNES : public DMA {
// Components of the SNES
MemoryImpl memory_;
Clock clock_;
AudioRAM audio_ram_;
CPU cpu{memory_, clock_};
PPU ppu{memory_, clock_};
APU apu{memory_, clock_};
APU apu{memory_, audio_ram_, clock_};
// Helper classes
ROMInfo rom_info_;

View File

@@ -9,7 +9,18 @@ namespace yaze {
namespace app {
namespace emu {
class AudioRAM {
class VirtualAudioRAM {
public:
virtual ~VirtualAudioRAM() = default;
// Read a byte from ARAM at the given address
virtual uint8_t read(uint16_t address) const = 0;
// Write a byte to ARAM at the given address
virtual void write(uint16_t address, uint8_t value) = 0;
};
class AudioRAM : public VirtualAudioRAM {
static const size_t ARAM_SIZE = 64 * 1024; // 64 KB
std::vector<uint8_t> ram;
@@ -17,10 +28,12 @@ class AudioRAM {
AudioRAM() : ram(ARAM_SIZE, 0) {}
// Read a byte from ARAM at the given address
uint8_t read(uint16_t address) const { return ram[address % ARAM_SIZE]; }
uint8_t read(uint16_t address) const override {
return ram[address % ARAM_SIZE];
}
// Write a byte to ARAM at the given address
void write(uint16_t address, uint8_t value) {
void write(uint16_t address, uint8_t value) override {
ram[address % ARAM_SIZE] = value;
}
};
@@ -63,7 +76,11 @@ class SDSP {
};
class SPC700 {
AudioRAM aram;
private:
VirtualAudioRAM& aram_;
public:
explicit SPC700(VirtualAudioRAM& aram) : aram_(aram) {}
SDSP sdsp;
uint8_t test_register_;
uint8_t control_register_;
@@ -104,7 +121,7 @@ class SPC700 {
return sdsp.readGlobalReg(dsp_address_register_);
default:
if (address < 0xFFC0) {
return aram.read(address);
return aram_.read(address);
} else {
// Handle IPL ROM or RAM reads here
}
@@ -129,7 +146,7 @@ class SPC700 {
break;
default:
if (address < 0xFFC0) {
aram.write(address, value);
aram_.write(address, value);
} else {
// Handle IPL ROM or RAM writes here
}
@@ -222,7 +239,31 @@ class SPC700 {
PSW.N = (result & 0x80);
}
// AND OR EOR ASL LSR ROL XCN
// AND
void AND(uint8_t operand, bool isImmediate = false) {
uint8_t value = isImmediate ? imm() : operand;
A &= value;
PSW.Z = (A == 0);
PSW.N = (A & 0x80);
}
// OR
void OR(uint8_t operand, bool isImmediate = false) {
uint8_t value = isImmediate ? imm() : operand;
A |= value;
PSW.Z = (A == 0);
PSW.N = (A & 0x80);
}
// EOR
void EOR(uint8_t operand, bool isImmediate = false) {
uint8_t value = isImmediate ? imm() : operand;
A ^= value;
PSW.Z = (A == 0);
PSW.N = (A & 0x80);
}
// ASL LSR ROL XCN
// INC DEC
// MOVW INCW DECW ADDW SUBW CMPW MUL DIV
// DAA DAS