Files
yaze/src/app/emu/snes.h
2023-08-20 15:39:22 -04:00

134 lines
2.9 KiB
C++

#include <cstdint>
#include <string>
#include "app/emu/apu.h"
#include "app/emu/cpu.h"
#include "app/emu/dbg.h"
#include "app/emu/ppu.h"
#include "app/rom.h"
namespace yaze {
namespace app {
namespace emu {
// Direct Memory Address
class DMA {
public:
DMA() {
// Initialize DMA and HDMA channels
for (int i = 0; i < 8; ++i) {
channels[i].DMAPn = 0;
channels[i].BBADn = 0;
channels[i].UNUSEDn = 0;
channels[i].A1Tn = 0xFFFFFF;
channels[i].DASn = 0xFFFF;
channels[i].A2An = 0xFFFF;
channels[i].NLTRn = 0xFF;
}
}
// DMA Transfer Modes
enum class DMA_TRANSFER_TYPE {
OAM,
PPUDATA,
CGDATA,
FILL_VRAM,
CLEAR_VRAM,
RESET_VRAM
};
// Functions for handling DMA and HDMA transfers
void StartDMATransfer(uint8_t channels);
void EnableHDMATransfers(uint8_t channels);
// Structure for DMA and HDMA channel registers
struct Channel {
uint8_t DMAPn; // DMA/HDMA parameters
uint8_t BBADn; // B-bus address
uint8_t UNUSEDn; // Unused byte
uint32_t A1Tn; // DMA Current Address / HDMA Table Start Address
uint16_t DASn; // DMA Byte-Counter / HDMA indirect table address
uint16_t A2An; // HDMA Table Current Address
uint8_t NLTRn; // HDMA Line-Counter
};
Channel channels[8];
uint8_t MDMAEN = 0; // Start DMA transfer
uint8_t HDMAEN = 0; // Enable HDMA transfers
};
class SNES : public DMA {
public:
SNES() = default;
~SNES() = default;
ROMInfo ReadRomHeader(uint32_t offset);
// Initialization
void Init(ROM& rom);
// Main emulation loop
void Run();
// Enable NMI Interrupts
void EnableVBlankInterrupts();
// Wait until the VBlank routine has been processed
void WaitForVBlank();
// NMI Interrupt Service Routine
void NmiIsr();
// VBlank routine
void VBlankRoutine();
// Functions for PPU-related operations
void RenderScanline();
void DrawBackgroundLayer(int layer);
void DrawSprites();
// Controller input handling
void HandleInput();
// Save/Load game state
void SaveState(const std::string& path);
void LoadState(const std::string& path);
// Debugger
void Debug();
void Breakpoint(uint16_t address);
bool running() const { return running_; }
private:
void WriteToRegister(uint16_t address, uint8_t value) {
memory_.WriteByte(address, value);
}
// Components of the SNES
MemoryImpl memory_;
CPU cpu{memory_};
PPU ppu{memory_};
APU apu{memory_};
// Helper classes
ROMInfo rom_info_;
Debugger debugger;
std::vector<uint8_t> rom_data;
// Byte flag to indicate if the VBlank routine should be executed or not
std::atomic<bool> vBlankFlag;
// 32-bit counter to track the number of NMI interrupts (useful for clocks and
// timers)
std::atomic<uint32_t> frameCounter;
// Other private member variables
bool running_;
int scanline;
};
} // namespace emu
} // namespace app
} // namespace yaze