Inject SPC700 to APU, add APU and PPU observers
This commit is contained in:
@@ -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.)
|
||||
};
|
||||
|
||||
@@ -107,8 +107,6 @@ class ROMInfo {
|
||||
uint16_t checksum;
|
||||
uint16_t nmiVblVector;
|
||||
uint16_t resetVector;
|
||||
|
||||
// Additional methods and constructors
|
||||
};
|
||||
|
||||
class Observer {
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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());
|
||||
|
||||
|
||||
@@ -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_;
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user