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

Modularized APU #32

Open
wants to merge 15 commits into
base: demigod/audio-tests
Choose a base branch
from
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,8 @@ build/
cmake-build-debug/
.idea/
src/.vscode/
src/dmg_boot.gb
src/dmg_boot.gb
tests/*
.vscode/*
run.sh
output.txt
31 changes: 30 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,35 @@
"ios": "cpp",
"queue": "cpp",
"semaphore": "cpp",
"cinttypes": "cpp"
"cinttypes": "cpp",
"any": "cpp",
"hash_map": "cpp",
"strstream": "cpp",
"charconv": "cpp",
"codecvt": "cpp",
"complex": "cpp",
"condition_variable": "cpp",
"list": "cpp",
"map": "cpp",
"set": "cpp",
"unordered_set": "cpp",
"optional": "cpp",
"source_location": "cpp",
"format": "cpp",
"fstream": "cpp",
"future": "cpp",
"iomanip": "cpp",
"iostream": "cpp",
"istream": "cpp",
"mutex": "cpp",
"shared_mutex": "cpp",
"span": "cpp",
"sstream": "cpp",
"stdfloat": "cpp",
"text_encoding": "cpp",
"cfenv": "cpp",
"typeindex": "cpp",
"valarray": "cpp",
"variant": "cpp"
}
}
4 changes: 2 additions & 2 deletions run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ elif [[ $last_keyword == "gbemu" ]]; then
echo "making new build directory"
mkdir build
cd build
cmake ..
cmake ..
cmake --build . -j8
./gbemu
else
echo "making new build directory"
mkdir build
cd build
cmake ..
cmake -DDEBUG=on ..
cmake --build . -j8
./gbemu
fi
Expand Down
51 changes: 45 additions & 6 deletions src/audio.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#include "audio.h"
#include "types.h"

APU::APU()
{
Expand All @@ -16,7 +15,7 @@ APU::APU()
enableVINRight = false;
volumeLeft = 0;
volumeRight = 0;

mMap = nullptr;
channel1 = new PulseChannel(CH1);
channel2 = new PulseChannel(CH2);
channel3 = new WaveChannel();
Expand Down Expand Up @@ -47,6 +46,7 @@ bool APU::init()
channel2->setFrameSequencer(frameSequencer);
channel3->setFrameSequencer(frameSequencer);
channel4->setFrameSequencer(frameSequencer);

return true;
}

Expand All @@ -55,9 +55,16 @@ void APU::test()
printf("APU test\n");
}

// initialize the writehandler of memorymap
void APU::initializeWriteHandler()
{
if (mMap)
mMap->setAudioWriteHandler([this](Word address) { this->onMemoryWrite(address); });
}

void APU::writeByte(Word address, Byte value)
{
printf("APU Address: %X, Value: %X\n", address, value);
printf("APU Address: %04X, Value: %02X\n", address, value);
if (address == 0xFF26)
{
bool enable = (value & 0x80) >> 7;
Expand Down Expand Up @@ -158,7 +165,6 @@ Byte APU::readByte(Word address)

case 0xFF26:
val = (enabled ? 0x80 : 0) | (channel1->isEnabled() ? 0x01 : 0) | (channel2->isEnabled() ? 0x02 : 0) | (channel3->isEnabled() ? 0x04 : 0) | (channel4->isEnabled() ? 0x08 : 0) | 0x70;
printf("APU Read 0xFF26: %X\n", val);
return val;

default:
Expand All @@ -176,7 +182,6 @@ void APU::stepAPU(int cycles)
if (frameSequencerCounter >= 8192)
{
// update envelope clocks and length timers

channel1->run();
channel2->run();
channel3->run();
Expand All @@ -189,6 +194,13 @@ void APU::stepAPU(int cycles)
channel2->setFrameSequencer(frameSequencer);
channel3->setFrameSequencer(frameSequencer);
channel4->setFrameSequencer(frameSequencer);

// Read and write back after updating
Word address[] = { 0xFF19, 0xFF1E, 0xFF23, 0xFF26 };
v1bh475u marked this conversation as resolved.
Show resolved Hide resolved
for (auto addr : address)
{
audioRegisterUpdate(addr, AudioWrite);
}
}
}

Expand All @@ -205,6 +217,33 @@ void APU::clearRegisters()
channel2->powerOff();
channel3->powerOff();
channel4->powerOff();
// Could be done by simply writing 0s but for checking's sake done as such
for (int address = 0xFF10; address <= 0xFF3F; address++)
{
audioRegisterUpdate(address, AudioWrite);
}
}

// Updates APU registers on write in MemoryMap
void APU::onMemoryWrite(Word address)
{
// address where write has occurred
audioRegisterUpdate(address, AudioMemoryWrite);
// Update the audio channel controller register
audioRegisterUpdate(AUDIO_MASTER_CONTROL_REGISTER, AudioWrite);
}

// Write Update
void APU::audioRegisterUpdate(Word address, audioWriteFlag flag)
{
Byte value = 0xFF;
if (flag == AudioMemoryWrite)
{
value = mMap->readMemory(address);
writeByte(address, value);
}
value = readByte(address);
mMap->MemoryWriteBack(address, value);
}

// PulseChannel
Expand Down Expand Up @@ -728,4 +767,4 @@ void NoiseChannel::trigger()
{
LFSR = 0x7FFF;
enabled = dacEnabled;
}
}
74 changes: 47 additions & 27 deletions src/audio.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
#pragma once
#include "types.h"
#include "mmap.h"
#include <stdio.h>
#include <SDL.h>
#include <SDL.h> // SDL Audio

#define AUDIO_MASTER_CONTROL_REGISTER 0xFF26

enum Channel
{
Expand All @@ -11,13 +14,21 @@ enum Channel
CH4 = 3
};

// For checking whether Write is due to memory or APU itself
enum audioWriteFlag
v1bh475u marked this conversation as resolved.
Show resolved Hide resolved
{
AudioWrite = 0,
AudioMemoryWrite = 1

};

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 +37,7 @@ class PulseChannel
// NRx1
Byte waveDuty;
int lengthTimer;
int maxLengthTimer = 64;
int maxLengthTimer = 64;

Byte envelopeInitialVolume;
bool envelopeIncrease;
Expand All @@ -41,25 +52,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 +83,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 +122,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 +170,22 @@ class APU
WaveChannel* channel3;
NoiseChannel* channel4;

// Memory Map
MemoryMap* mMap;

public:
APU();
void test();
bool init();
bool init();
void writeByte(Word address, Byte value);
Byte readByte(Word address);
void stepAPU(int cycles);
void clearRegisters();
void setMemoryMap(MemoryMap* map) { mMap = map; }
// Writes back on Memory Write
void onMemoryWrite(Word address);
// Write update
void audioRegisterUpdate(Word address, audioWriteFlag flag);
// initializes the audioWriteHandler of MemoryMap
void initializeWriteHandler();
};
19 changes: 11 additions & 8 deletions src/gameBoy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,30 +16,34 @@ 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);

gbe_graphics->init();

// Unify the APU and MemoryMap
gbe_audio->setMemoryMap(gbe_mMap);
// initialize the write handler
gbe_audio->initializeWriteHandler();

// Open the Boot ROM
if ((bootROM = fopen("../src/dmg_boot.gb", "rb")) == NULL)
printf("boot rom file not opened");
printf("boot rom file not opened\n");

// // Open the Game ROM
// if ((gameROM = fopen("../tests/tetris.gb", "rb")) == NULL)
// printf("game rom file not opened");

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

// Set the Boot ROM
gbe_mMap->setBootRomFile(bootROM);
Expand Down Expand Up @@ -105,7 +109,6 @@ GBE::GBE()
gbe_mMap->debugWriteMemory(0x133, 0x3E);

executeBootROM();

update();
}

Expand All @@ -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
Loading
Loading