Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Separate APU from Memory #34

Merged
merged 5 commits into from
Sep 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ build/
cmake-build-debug/
.idea/
src/.vscode/
src/dmg_boot.gb
src/dmg_boot.gb
tests/*
24 changes: 23 additions & 1 deletion src/audio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ APU::APU()
volumeLeft = 0;
volumeRight = 0;

mMap = nullptr;

channel1 = new PulseChannel(CH1);
channel2 = new PulseChannel(CH2);
channel3 = new WaveChannel();
Expand Down Expand Up @@ -50,6 +52,26 @@ bool APU::init()
return true;
}

// Set MemoryMap pointer
void APU::setMemoryMap(MemoryMap* mMap)
{
this->mMap = mMap;
// initialize Handlers
initializeReadWriteHandlers();
}

// Initializes the read-write handlers of MemoryMap
void APU::initializeReadWriteHandlers()
v1bh475u marked this conversation as resolved.
Show resolved Hide resolved
{
if (!mMap)
{
throw std::runtime_error("MemoryMap not set in APU");
return;
}

mMap->setAudioReadHandler([this](Word address) { return this->readByte(address); });
mMap->setAudioWriteHandler([this](Word address, Byte value) { this->writeByte(address, value); });
}
void APU::test()
{
printf("APU test\n");
Expand Down Expand Up @@ -728,4 +750,4 @@ void NoiseChannel::trigger()
{
LFSR = 0x7FFF;
enabled = dacEnabled;
}
}
58 changes: 32 additions & 26 deletions src/audio.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
#include "types.h"
#include <stdio.h>
#include <SDL.h>
#include <stdexcept>
#include "mmap.h"

enum Channel
{
Expand All @@ -15,9 +17,9 @@ class PulseChannel
{
private:
Channel channel;
bool enabled;
bool dacEnabled;
int frameSequencer;
bool enabled;
bool dacEnabled;
int frameSequencer;

Byte sweepPeriod;
bool sweepNegate;
Expand All @@ -26,7 +28,7 @@ class PulseChannel
// NRx1
Byte waveDuty;
int lengthTimer;
int maxLengthTimer = 64;
int maxLengthTimer = 64;

Byte envelopeInitialVolume;
bool envelopeIncrease;
Expand All @@ -41,25 +43,24 @@ class PulseChannel
void test();
void writeByte(Word address, Byte value);
Byte readByte(Word address);
bool isEnabled();
void powerOff();
void run();
void set_NRx4(Byte value);
void setFrameSequencer(int frameSequencer);
void trigger();
bool isEnabled();
void powerOff();
void run();
void set_NRx4(Byte value);
void setFrameSequencer(int frameSequencer);
void trigger();
};

class WaveChannel
{
private:

Byte waveRAM[16];
bool dacEnabled;
bool enabled;

int lengthTimer;
int maxLengthTimer = 256;
int frameSequencer;
int frameSequencer;

Byte outputLevel;

Expand All @@ -73,22 +74,22 @@ class WaveChannel
void writeByte(Word address, Byte value);
Byte readByte(Word address);
void trigger();
bool isEnabled();
void powerOff();
void set_NRx4(Byte value);
void run();
void setFrameSequencer(int frameSequencer);
bool isEnabled();
void powerOff();
void set_NRx4(Byte value);
void run();
void setFrameSequencer(int frameSequencer);
};

class NoiseChannel
{
private:
bool enabled;
bool dacEnabled;
bool enabled;
bool dacEnabled;

int lengthTimer;
int maxLengthTimer = 64;
int frameSequencer;
int frameSequencer;

Byte envelopeInitialVolume;
bool envelopeIncrease;
Expand All @@ -112,11 +113,11 @@ class NoiseChannel
void writeByte(Word address, Byte value);
Byte readByte(Word address);
void trigger();
bool isEnabled();
void powerOff();
void set_NRx4(Byte value);
void run();
void setFrameSequencer(int frameSequencer);
bool isEnabled();
void powerOff();
void set_NRx4(Byte value);
void run();
void setFrameSequencer(int frameSequencer);
};

class APU
Expand Down Expand Up @@ -160,12 +161,17 @@ class APU
WaveChannel* channel3;
NoiseChannel* channel4;

// Pointer to MemoryMap
MemoryMap* mMap;

public:
APU();
void setMemoryMap(MemoryMap* mMap);
void test();
bool init();
bool init();
void writeByte(Word address, Byte value);
Byte readByte(Word address);
void stepAPU(int cycles);
void clearRegisters();
void initializeReadWriteHandlers();
};
11 changes: 7 additions & 4 deletions src/gameBoy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,20 @@ GBE::GBE()
gbe_graphics = new PPU();

// audio = new Audio();
// APU = new APU();
gbe_audio = new APU();

// Unify the CPU and MemoryMap
gbe_cpu->setMemory(gbe_mMap);

// Unify the CPU and PPU
gbe_cpu->setPPU(gbe_graphics);

// Unify the PPU and MmeoryMap
// Unify the PPU and MemoryMap
gbe_graphics->setMemoryMap(gbe_mMap);

// Unify the APU and MemoryMap
gbe_audio->setMemoryMap(gbe_mMap);

gbe_graphics->init();

// Open the Boot ROM
Expand All @@ -38,7 +41,7 @@ GBE::GBE()
// printf("game rom file not opened");

// Open the Game ROM
if ((gameROM = fopen("../tests/dmg_sound/rom_singles/03-trigger.gb", "rb")) == NULL)
if ((gameROM = fopen("../tests/dmg_sound/rom_singles/02-len ctr.gb", "rb")) == NULL)
printf("game rom file not opened");

// Set the Boot ROM
Expand Down Expand Up @@ -122,7 +125,7 @@ void GBE::update()
// update the DIV and TIMA timers
gbe_cpu->updateTimers(s_Cycles);
gbe_graphics->executePPU(s_Cycles);
gbe_mMap->audio->stepAPU(s_Cycles);
gbe_audio->stepAPU(s_Cycles);
s_Cycles = 0;
s_Cycles += gbe_cpu->performInterrupt();
gbe_graphics->pollEvents();
Expand Down
4 changes: 4 additions & 0 deletions src/gameBoy.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "cpu.h"
#include "mmap.h"
#include "graphics.h"
#include "audio.h"

// GBE stands for GameBoyEmulator

Expand Down Expand Up @@ -34,6 +35,9 @@ class GBE
// File pointer for game ROM
FILE* gameROM;

// Pointer to Audio
APU* gbe_audio;

// Update function of the GBE
// Will be called every frame
// GB has 59.73 frames per second
Expand Down
23 changes: 18 additions & 5 deletions src/mmap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,24 @@ MemoryMap::MemoryMap()
bootRomFile = nullptr;
romFile = nullptr;

audio = new APU();

mbcMode = 0x0;
}

// MemoryMap Destructor
MemoryMap::~MemoryMap()
{
delete romBank0;
delete romBank1;
delete videoRam;
delete externalRam;
delete workRam;
delete oamTable;
delete ioPorts;
delete highRam;
delete interruptEnableRegister;
delete joyPadState;
}

// Write to memory
// TODO: Make emulation memory secure
bool MemoryMap::writeMemory(Word address, Byte value)
Expand Down Expand Up @@ -176,8 +189,8 @@ bool MemoryMap::writeMemory(Word address, Byte value)
}
// Write to Audio Registers
else if (address >= 0xFF10 && address <= 0xFF3F)
{
audio->writeByte(address, value);
{
audioWriteHandler(address, value);
}
else
ioPorts[address - 0xFF00] = value;
Expand Down Expand Up @@ -254,7 +267,7 @@ Byte MemoryMap::readMemory(Word address)
// Read from Audio Registers
if (address >= 0xFF10 && address <= 0xFF3F)
{
return audio->readByte(address);
return audioReadHandler(address);
}
// Read from I/O Ports
else
Expand Down
18 changes: 12 additions & 6 deletions src/mmap.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#pragma once
#include "types.h"
#include <stdio.h>
#include "audio.h"
#include <functional>

// The Memory Map for GBE
// Pulled from https://gbdev.io/pandocs/Memory_Map.html
Expand Down Expand Up @@ -138,12 +138,12 @@ class MemoryMap
// Stays in the I/O Ports at 0xFF4B
Byte* reg_WX;

// Write to audio are being handled by this without passing the APU pointer to MemoryMap
std::function<void(Word, Byte)> audioWriteHandler;
// Read from audio handled by this
std::function<Byte(Word)> audioReadHandler;

public:
// Audio Unit
// I know this is not the best way to do it
// But I am not sure how to do it better
APU* audio;

Byte* joyPadState;
// Constructor
MemoryMap();
Expand Down Expand Up @@ -270,4 +270,10 @@ class MemoryMap

// sets the ROM file
void setRomFile(FILE* file) { romFile = file; }

// set audioWriteHandler
void setAudioWriteHandler(const std::function<void(Word, Byte)>& function) { audioWriteHandler = function; }

// set audioReadHandler
void setAudioReadHandler(const std::function<Byte(Word)>& function) { audioReadHandler = function; }
};
Loading