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
61 changes: 55 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 @@ -125,6 +132,7 @@ void APU::writeByte(Word address, Byte value)

Byte APU::readByte(Word address)
{
printf("Address: %04X\n", address);
if (address >= 0xFF10 && address <= 0xFF14)
{
return channel1->readByte(address);
Expand Down Expand Up @@ -158,7 +166,7 @@ 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);
// printf("APU Read 0xFF26: %04X\n", val);
return val;

default:
Expand All @@ -175,8 +183,8 @@ void APU::stepAPU(int cycles)

if (frameSequencerCounter >= 8192)
{
printf("FrameSquencer start\n");
// update envelope clocks and length timers

channel1->run();
channel2->run();
channel3->run();
Expand All @@ -189,6 +197,14 @@ 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);
}
printf("FramerSequencer ends\n");
}
}

Expand All @@ -205,6 +221,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)
{
value = mMap->readMemory(address);
writeByte(address, value);
}
value = readByte(address);
mMap->MemoryWriteBack(address, value);
}

// PulseChannel
Expand Down Expand Up @@ -246,6 +289,7 @@ void PulseChannel::writeByte(Word address, Byte value)
// Sound length/Wave pattern duty
waveDuty = (value & 0xC0) >> 6;
lengthTimer = maxLengthTimer - (value & 0x3F);
printf("PC: lengthTimer\n");
return;
case 0xFF12:
case 0xFF17:
Expand Down Expand Up @@ -276,6 +320,7 @@ void PulseChannel::writeByte(Word address, Byte value)
}
if (value & 0x80)
{
printf("WC triggered\n");
trigger();
}
return;
Expand Down Expand Up @@ -431,6 +476,7 @@ void WaveChannel::writeByte(Word address, Byte value)
// NR31
// Sound length
lengthTimer = maxLengthTimer - value;
printf("WC: lengthTimer\n");
return;
case 0xFF1C:
// NR32
Expand All @@ -453,6 +499,7 @@ void WaveChannel::writeByte(Word address, Byte value)
}
if (value & 0x80)
{
printf("WC triggered\n");
trigger();
}
return;
Expand Down Expand Up @@ -590,6 +637,7 @@ void NoiseChannel::writeByte(Word address, Byte value)
// NR41
// Sound length
lengthTimer = maxLengthTimer - (value & 0x3F);
printf("NC: lengthtimer\n");
return;
case 0xFF21:
// NR42
Expand Down Expand Up @@ -618,6 +666,7 @@ void NoiseChannel::writeByte(Word address, Byte value)
}
if (value & 0x80)
{
printf("NC Triggered...\n");
trigger();
}
return;
Expand Down Expand Up @@ -728,4 +777,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();
};
Loading
Loading