diff --git a/.gitignore b/.gitignore index e459dee..5287309 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ build/ cmake-build-debug/ .idea/ src/.vscode/ -CMakeSettings.json \ No newline at end of file +CMakeSettings.json +run.sh \ No newline at end of file diff --git a/src/gameBoy.cpp b/src/gameBoy.cpp old mode 100644 new mode 100755 index 45d8a91..f19499f --- a/src/gameBoy.cpp +++ b/src/gameBoy.cpp @@ -39,11 +39,11 @@ GBE::GBE() gbe_sound->test(); // Open the Boot ROM - if ((bootROM = fopen("../../../src/dmg_boot.gb", "rb")) == NULL) + if ((bootROM = fopen("../src/dmg_boot.gb", "rb")) == NULL) printf("boot rom file not opened"); // Open the Game ROM - if ((gameROM = fopen("../../../tests/pacman.gb", "rb")) == NULL) + if ((gameROM = fopen("../tests/tetris.gb", "rb")) == NULL) printf("game rom file not opened"); // Set the Boot ROM @@ -129,6 +129,7 @@ void GBE::update() // this runs at a freq of around 27 * freq(DIV) = 442368 Hz // this is probably enough to implement APU gbe_sound->executeAPU(); + gbe_sound->test(); s_Cycles = 0; s_Cycles += gbe_cpu->performInterrupt(); gbe_graphics->pollEvents(); diff --git a/src/sound.cpp b/src/sound.cpp old mode 100644 new mode 100755 index 859e26b..ad02dd5 --- a/src/sound.cpp +++ b/src/sound.cpp @@ -1,171 +1,164 @@ #include "sound.h" #include "types.h" -APU::APU() -{ - mMap = nullptr; +APU::APU() +{ + preDiv=0; + mMap = nullptr; + SDL_zero(wanted); SDL_zero(obtained); audioDeviceID = 0; - // Audio Controllers - enableOutput = 0; - channelEnable[4] = { false }; + // Audio Controllers + enableOutput = 0; + channelEnable[4] = {false}; rateDIV = 0; - soundPann = 0; + soundPann = 0; sampleRate = 32; sampleRateTimer = 0; - enableVINLeft = 0; - enableVINRight = 0; - - volumeLeft = 0; - volumeRight = 0; + enableVINLeft = 0; + enableVINRight = 0; - // Audio Channels - channel1 = new PulseChannel(); + volumeLeft = 0; + volumeRight = 0; + + //Audio Channels + channel1 = new PulseChannel(); channel2 = new PulseChannel(); - channel3 = new WaveChannel(); - channel4 = new NoiseChannel(); + channel3 = new WaveChannel(); + channel4 = new NoiseChannel(); } -bool APU::init() -{ - // Initializing SDL Audio - wanted.freq = 44100; - wanted.format = AUDIO_F32SYS; - wanted.channels = 2; /* 1 = mono, 2 = stereo */ - wanted.samples = bufferSize; - wanted.callback = NULL; - wanted.userdata = NULL; + +bool APU::init(){ + // Initializing SDL Audio + wanted.freq = 44100; + wanted.format = AUDIO_F32SYS; + wanted.channels = 2; /* 1 = mono, 2 = stereo */ + wanted.samples = bufferSize; + wanted.callback = NULL; + wanted.userdata = NULL; audioDeviceID = SDL_OpenAudioDevice(NULL, 0, &wanted, &obtained, SDL_AUDIO_ALLOW_ANY_CHANGE); - if (audioDeviceID == 0) - { + if( audioDeviceID == 0 ){ printf("SDL Audio not initialize! SDL_Error: %s\n", SDL_GetError()); SDL_Quit(); return false; } - SDL_PauseAudioDevice(audioDeviceID, 0); + SDL_PauseAudioDevice(audioDeviceID,0); SDL_Delay(3); - if (checkChannelEnable(Pulse1)) - { - channel1->setMemoryMap(mMap); - channel1->init(1); - } + + channel1->setMemoryMap(mMap); + channel2->setMemoryMap(mMap); + channel3->setMemoryMap(mMap); + + channel1->init(1); + channel2->init(2); + channel3->readEnable(); + return true; +} - if (checkChannelEnable(Pulse2)) - { - channel2->setMemoryMap(mMap); - channel2->init(2); - } - if (checkChannelEnable(Wave)) - { - channel3->setMemoryMap(mMap); - channel3->init(); - } - - if (checkChannelEnable(Noise)) - { - channel4->setMemoryMap(mMap); - channel4->init(); - } -} void APU::test() { - for (int i = 0; i < 0x20; i++) - { - printf("------------------------ at register FF%d: %d\n\n", i, mMap->readMemory(0xff10 + i)); - } + // printf("------------------------ \n"); + // for (int i = 0; i < 0x20; i++) + // { + // int temp= mMap->readMemory(0xff10 + i) ; + // if (temp){ + // printf("------------------------ at register FF%x: %d\n\n", i, temp ); + // } + + // } + + // printf("WaveRam:"); + // for (int i = 0; i < 16; i++) + // { + // printf(" %x",mMap->readMemory(0xff30 + i)); + // } + } void APU::executeAPU() -{ - if (channel1->checkEnable()) - { +{ + if(channel1->checkEnable()){ channel1->takeSample(); } - if (channel2->checkEnable()) - { + if(channel2->checkEnable()){ channel2->takeSample(); } + // if(channel3->checkTrigger()){ + // printf("channel3->checkEnable: %d\n",channel3->checkEnable() ); + // channel3->readEnable(); + // printf("channel3->checkEnable: %d\n\n",channel3->checkEnable() ); + // } + // channel3->readEnable(); + // bool yoyo=false; + if(channel3->checkEnable()){ + channel3->takeSample(); + // if(channel3->getVolume()) yoyo=true; + } + // printf("channel3->checkTrigger: %d\n",channel3->checkTrigger() ); + // if(channel3->checkEnable()){ + // channel3->takeSample(); + // } // printf("volume from channel 1: %d\n", channel1->getVolume()); - if (((mMap->getRegDIV() & 0b1000) >> 3) == 1) - { + // if(yoyo){ + // printf("\n\tStill here\n\n"); + // } + // printf("sampleRateTimer: %d\n", sampleRateTimer); + if(((mMap->getRegDIV() & 0b1000) >> 3 ) == 1){ rateDIV = (rateDIV + 1) % 8; channel1->run(rateDIV); channel2->run(rateDIV); + channel3->run(rateDIV); } - - if (sampleRateTimer == 0) - { + if( sampleRateTimer == 0 ){ + // if(yoyo) printf("this works\n"); + // printf("yo\n\n"); + // if(channel3->getVolume() ){ + // printf("volume from channel 1 in: %d\n", channel1->getVolume()); + // printf("volume from channel 2 in: %d\n", channel2->getVolume()); + // printf("volume from channel 3 in: %d\n\n", channel3->getVolume()); + // } + float vol = 0; - // check if enable float vol1 = (float)channel1->getVolume() / 100; float vol2 = (float)channel2->getVolume() / 100; - + float vol3 = (float)channel3->getVolume() / 100; + if(vol1) printf("vol1: %f\n", vol1); + if(vol2) printf("vol2: %f\n", vol2); + if(vol3) printf("vol3: %f\n", vol3); SDL_MixAudioFormat((Uint8*)&vol, (Uint8*)&vol1, AUDIO_F32SYS, sizeof(float), SDL_MIX_MAXVOLUME); SDL_MixAudioFormat((Uint8*)&vol, (Uint8*)&vol2, AUDIO_F32SYS, sizeof(float), SDL_MIX_MAXVOLUME); - + SDL_MixAudioFormat((Uint8*)&vol, (Uint8*)&vol3, AUDIO_F32SYS, sizeof(float), SDL_MIX_MAXVOLUME); buffer[bufferIndex] = vol; buffer[bufferIndex + 1] = vol; bufferIndex += 2; } sampleRateTimer = (sampleRateTimer + 1) % sampleRate; - if (bufferIndex >= bufferSize) - { + if(bufferIndex >= bufferSize){ bufferIndex = 0; - while (SDL_GetQueuedAudioSize(audioDeviceID) > bufferSize * sizeof(float)) - { + while(SDL_GetQueuedAudioSize(audioDeviceID) > bufferSize * sizeof(float)){ SDL_Delay(1); } - SDL_QueueAudio(audioDeviceID, buffer, bufferSize * sizeof(float)); + SDL_QueueAudio(audioDeviceID, buffer, bufferSize * sizeof(float) ); } } -bool APU::checkEnable() -{ - return enableOutput; -} - -bool APU::checkChannelEnable(Channel channel) -{ - return channelEnable[channel]; -} - -void APU::triggerAPU() -{ - enableOutput = !enableOutput; -} - -bool APU::checkPann(Channel channel, bool direction) -{ - int bit = direction * 4 + channel; - return (soundPann >> bit) & 1; -} - -void APU::triggerPann(Channel channel, bool direction) -{ - int bit = direction * 4 + channel; - soundPann = soundPann ^ (1 << bit); -} -Byte APU::getMasterVolume(bool direction) -{ - int bit = direction * 4 + 3; - return NR[0] & (1 << bit) -} // ------------ Pulse Channel ------------ @@ -179,37 +172,38 @@ PulseChannel::PulseChannel() sweepPace = 0; sweepPaceClock = 0; - sweepChange = 0; - sweepSlope = 0; + sweepChange = 0; + sweepSlope = 0; - waveDuty = 0; - lengthTimer = 0; - lengthTimerClock = 0; + waveDuty = 0; + lengthTimer = 0; + lengthTimerClock=0; - envelopeVolume = 0; - envelopeDirection = 0; - envelopeSweepPace = 0; + envelopeVolume = 0; + envelopeDirection = 0; + envelopeSweepPace = 0; envelopeSweepPaceClock = 0; - + periodValue = 0; - periodValueTemp = 0; - periodValueClock = 0; - + periodValueTemp = 0; + periodValueClock = 0; + trigger = 0; - soundLengthEnable = 0; + soundLengthEnable = 0; volume = 0; WaveDutyCounter = 0; + } bool PulseChannel::init(Byte channelNum) { switch (channelNum) { - // calculating address of NRx0; note NR10 esists but NR20 does not exist + // calculating address of NRx0; note NR10 esists but NR20 does not exist case 1: regAddr = 0xFF10; - sweepPresent = 1; + sweepPresent = 1; break; case 2: regAddr = 0xFF15; @@ -220,19 +214,17 @@ bool PulseChannel::init(Byte channelNum) break; } - // fill the addresses of NRxy - for (Byte i = 0; i < 5; i++) - NR[i] = regAddr + i; + // fill the addresses of NRxyenable + for(Byte i = 0; i< 5; i++) NR[i] = regAddr + i; + return 1; } void PulseChannel::run(Byte rateDIV) { // 256 Hz - // sound length - if (soundLengthEnable && rateDIV % 2 == 0) - { - if (lengthTimer >= 64) - { + // sound length + if(soundLengthEnable && rateDIV % 2 == 0){ + if(lengthTimer >= 64){ enable = 0; lengthTimer = 0; } @@ -241,32 +233,24 @@ void PulseChannel::run(Byte rateDIV) // 128 Hz // CH1 freq sweep - if (sweepPresent && sweepPace > 0 && rateDIV % 4 == 0) - { - if (sweepPaceClock == 0) - { + if( sweepPresent && sweepPace > 0 && rateDIV % 4 == 0){ + if(sweepPaceClock == 0 ){ // calculate 11 bits from (higher 3 bits) NRx4 + (lower 8 bits) NRx3 - periodValue = (mMap->readMemory(NR[4]) & 0b00000111) << 8 | (mMap->readMemory(NR[3]) & 0b11111111); - - if (sweepChange == 0) - { - periodValueTemp = periodValue + (periodValue / (1 << sweepSlope)); + periodValue = ( mMap->readMemory(NR[4]) & 0b00000111 ) << 8 | ( mMap->readMemory(NR[3]) & 0b11111111 ); + + if(sweepChange == 0){ + periodValueTemp = periodValue + (periodValue / (1<< sweepSlope)) ; + }else{ + periodValueTemp = periodValue - (periodValue / (1<< sweepSlope)) ; } - else - { - periodValueTemp = periodValue - (periodValue / (1 << sweepSlope)); - } - - if (periodValueTemp == 0 || periodValueTemp > 0x7FF) - { - enable = 0; - } - else - { + + if( periodValueTemp == 0 || periodValueTemp > 0x7FF ){ + enable = 0; + }else{ Byte tempData = mMap->readMemory(NR[4]); tempData = (tempData & 0b11111000) | (periodValueTemp >> 8 & 0b00000111); - mMap->writeMemory(NR[4], tempData); - mMap->writeMemory(NR[3], (Byte)(periodValueTemp & 0x11111111)); + mMap->writeMemory(NR[4],tempData); + mMap->writeMemory(NR[3], (Byte)(periodValueTemp & 0x11111111) ); } } sweepPaceClock = (sweepPaceClock + 1) % sweepPace; @@ -274,31 +258,24 @@ void PulseChannel::run(Byte rateDIV) // 64 Hz // Envelope sweep - if (rateDIV % 8 == 0) - { + if(rateDIV % 8 == 0){ - if (envelopeVolume == 0 && envelopeDirection == 0) - { + if(envelopeVolume == 0 && envelopeDirection == 0){ enable = 0; } - - if (envelopeSweepPace != 0) - { - if (envelopeSweepPaceClock == 0) - { - if (envelopeDirection == 0) - { - if (envelopeVolume > 0) - envelopeVolume--; + + if( envelopeSweepPace != 0 ){ + if(envelopeSweepPaceClock == 0){ + if(envelopeDirection == 0){ + if( envelopeVolume > 0) envelopeVolume--; } - else - { - if (envelopeVolume < 0xF) - envelopeVolume++; + else { + if ( envelopeVolume < 0xF) envelopeVolume++; } } envelopeSweepPaceClock = (envelopeSweepPaceClock + 1) % envelopeSweepPace; } + } } @@ -306,52 +283,47 @@ void PulseChannel::enableAndLoad() { enable = 1; - if (sweepPresent) - { - sweepPace = (mMap->readMemory(NR[0]) & 0b01110000) >> 4; // bits 6-4 - sweepChange = (mMap->readMemory(NR[0]) & 0b00001000) >> 3; // bits 3 - sweepSlope = (mMap->readMemory(NR[0]) & 0b00000111) >> 0; // bits 2-0 + if(sweepPresent){ + sweepPace = ( mMap->readMemory(NR[0]) & 0b01110000 ) >> 4; // bits 6-4 + sweepChange = ( mMap->readMemory(NR[0]) & 0b00001000 ) >> 3; // bits 3 + sweepSlope = ( mMap->readMemory(NR[0]) & 0b00000111 ) >> 0; // bits 2-0 } - waveDuty = (mMap->readMemory(NR[1]) & 0b11000000) >> 6; // bits 7-6 - lengthTimer = (mMap->readMemory(NR[1]) & 0b00111111) >> 0; // bits 5-0 + waveDuty = ( mMap->readMemory(NR[1]) & 0b11000000 ) >> 6; // bits 7-6 + lengthTimer = ( mMap->readMemory(NR[1]) & 0b00111111 ) >> 0; // bits 5-0 - envelopeVolume = (mMap->readMemory(NR[2]) & 0b11110000) >> 4; // bits 7-4 - envelopeDirection = (mMap->readMemory(NR[2]) & 0b00001000) >> 3; // bits 3 - envelopeSweepPace = (mMap->readMemory(NR[2]) & 0b00000111) >> 0; // bits 2-0 + + envelopeVolume = ( mMap->readMemory(NR[2]) & 0b11110000 ) >> 4; // bits 7-4 + envelopeDirection = ( mMap->readMemory(NR[2]) & 0b00001000 ) >> 3; // bits 3 + envelopeSweepPace = ( mMap->readMemory(NR[2]) & 0b00000111 ) >> 0; // bits 2-0 // calculate 11 bits from (higher 3 bits) NRx4 + (lower 8 bits) NRx3 - periodValue = (mMap->readMemory(NR[4]) & 0b00000111) << 8 | (mMap->readMemory(NR[3]) & 0b11111111); + periodValue = ( mMap->readMemory(NR[4]) & 0b00000111 ) << 8 | ( mMap->readMemory(NR[3]) & 0b11111111 ); + + soundLengthEnable = ( mMap->readMemory(NR[2]) & 0b01000000 ) >> 6; // bit 6 - soundLengthEnable = (mMap->readMemory(NR[2]) & 0b01000000) >> 6; // bit 6 } + Byte PulseChannel::getVolume() { - if (enable == 0) - { - if (checkTrigger()) - { - enableAndLoad(); + if(enable == 0){ + if(checkTrigger()){ + enableAndLoad(); } return 0; - } - else - { + }else{ return volume; } } void PulseChannel::takeSample() -{ - if (enable == 1) - { - if (periodValueClock == 0) - { +{ + if ( enable == 1){ + if( periodValueClock == 0){ volume = envelopeVolume; - if (waveDutyTab[waveDuty][WaveDutyCounter] == 0) - { + if(waveDutyTab[waveDuty][WaveDutyCounter] == 0 ){ volume = 0; } WaveDutyCounter = (WaveDutyCounter + 1) % 8; @@ -360,109 +332,171 @@ void PulseChannel::takeSample() // takes sample with frequency 1048576/ (2048 - periodValue) Hz // This only works for max period frequency = 400000 Hz // To be safe we only allow 1048576/4 Hz - periodValueClock = (periodValueClock + 1) % ((0x800 - periodValue) > 4 ? 0x800 - periodValue : 4); - } - else - { + periodValueClock = (periodValueClock + 1) % ( (0x800 - periodValue) > 4 ? 0x800 - periodValue : 4 ); + }else{ volume = 0; } } bool PulseChannel::checkTrigger() { - return (mMap->readMemory(NR[4]) & 0b10000000) >> 7; // bit 7 + return ( mMap->readMemory(NR[4]) & 0b10000000 ) >> 7; // bit 7 } bool PulseChannel::checkEnable() { - return enable; + return enable; } -// Wave Channel +WaveChannel::WaveChannel(){ + for (Byte i = 0; i < 5; i++) + NR[i] = registerAddress + i; -WaveChannel : WaveChannel() -{ - mMap = nullptr; + index = 0; + volume = 0; + // NRx0 + enable = 0; - enable=0; + // NRx1 + lengthTimer = 0; - lengthTimer=0; + // NRx2 + outputLevel = 0; - outputLevel=0; + // Nrx3 + // needs 11 bits - 3 bits from NRX4 + 8 bits from NRx3 + periodValue = 0; - periodValue=0; - sampleRate=0; - toneFrequency=0; + // NRx4 - trigger=0; - soundLengthEnable=0; + trigger = 0; + soundLengthEnable = 0; + + // Wave RAM + Byte waveRAM[16]; + Byte waveSamples[32]; } -void WaveChannel::init() -{ - for (Byte i = 0; i < 5; i++) - NR[i] = registerAddress + i; +bool WaveChannel::checkEnable(){ + return enable; } -void WaveChannel::run(Byte rateDIV) -{ +void WaveChannel::readWaveRam(){ + enable = 0; + for (Word i = 0; i < 16; i++) + { + waveRAM[i] = mMap->readMemory(waveRAM_Address + i); + } + for (Word i = 0; i < 32; i++) + { + waveSamples[i] = ( waveRAM[ i/2 ] >> ( ( ( i + 1 ) % 2 ) * 4 ) ) & 0b1111 ; + } + readEnable(); } -void WaveChannel::enableAndLoad() -{ +void WaveChannel::readEnable(){ + enable = mMap->readMemory(NR[0]) >> 7; +} +bool WaveChannel::checkTrigger(){ + trigger = mMap->readMemory(NR[4]) >> 7; + return trigger; } -bool WaveChannel::getEnable() -{ - return (mMap->readMemory(NR[0])) >> 7; //get 7th bit +bool WaveChannel::checkLengthEnable(){ + return soundLengthEnable; } -void WaveChannel::setEnable(bool enable) -{ - this->enable=enable; - mMap->writeMemory(NR[0], (enable) << 7); //write 7th bit +void WaveChannel::enableAndLoad(){ + // printf("\n\tyo\n\n"); + enable = 1; + + lengthTimer = mMap->readMemory(NR[1]); // bits 7-0 + + outputLevel = (mMap->readMemory(NR[2]) & 0b01100000) >> 5; //bits 6-5 + + // calculate 11 bits from (higher 3 bits) NRx4 + (lower 8 bits) NRx3 + periodValue = ( mMap->readMemory(NR[4]) & 0b00000111 ) << 8 | ( mMap->readMemory(NR[3]) & 0b11111111 ); + + soundLengthEnable = ( mMap->readMemory(NR[2]) & 0b01000000 ) >> 6; // bit 6 } -void WaveChannel::writeLengthTimer(Byte timer) -{ - lengthTimer=timer; - mMap->writeMemory(NR[1], timer); +void WaveChannel::run(Byte rateDIV){ + // 256 Hz + // sound length + if(soundLengthEnable && rateDIV % 2 == 0){ + printf("here"); + if(lengthTimer >= 256){ + enable = 0; + lengthTimer = 0; + } + lengthTimer++; + // printf("lengthTimer: %d\n", lengthTimer); + } } -bool WaveChannel::getOutputLevel() -{ - outputLevel = (mMap->readMemory(NR[2]) >> 5 ) & 0b11; - // 00 Mute (No sound) - // 01 100% volume (use samples read from Wave RAM as-is) - // 10 50% volume (shift samples read from Wave RAM right once) - // 11 25% volume (shift samples read from Wave RAM right twice) +void WaveChannel::takeSample(){ + // if(mMap->readMemory(NR[2])){ + // printf("%x\n", mMap->readMemory(NR[2])); + // } + + // for (Byte i = 0; i < 5; i++) + // { + // /* code */ + // printf("NR[%d]: %x\n", i,mMap->readMemory(NR[i])); + // } + // printf("\n"); + + if (enable){ + if(index < 32){ + if(outputLevel){ + // printf("Index: %d\n", index); + // printf("waveSamples[index]: %d\n", waveSamples[index]); + // printf("outputLevel: %d\n", outputLevel); + outVolume = waveSamples[index] >> (outputLevel - 1); + // printf("outVolume: %d\n\n", outVolume); + // getVolume(); + }else{ + // outVolume = 0; + } + index += 1; + } else { + // printf("\n\nREAD SAMPLES\n\n"); + index = 0; + readWaveRam(); + // printf("outputLevel: %d\n\n", outputLevel); + readOutputLevel(); + // printf("outputLevel: %d\n\n", outputLevel); + takeSample(); + } + } else { + // outVolume = 0; + } } -Word WaveChannel::getPeriodValue() -{ - Byte lowerBits = mMap->readMemory(NR[3]); - Byte upperBits = mMap->readMemory(NR[4]) & 0b111; - Word periodValue = (upperBits<<8) | lowerBits; +Byte WaveChannel::getVolume(){ + // printf("here"); + // if(outVolume) printf("outVolume: %d\n", outVolume); - sampleRate = 2097152.0/(2048-periodValue); - toneFrequency = sampleRate/32; - return periodValue; -} + if(enable == 0){ + if(checkTrigger()){ + enableAndLoad(); + } + return 0; + }else{ + // printf("yo: %d \n", outVolume); -void WaveChannel::readWaveRAM() -{ - for (Byte i = 0; i < 16; i++) - { - waveRAM[i] = mMap->readMemory(waveRAM_Address + i) + return outVolume; } +} - for (Byte i = 0; i < 32; i++) - { - waveSamples[i] = ( waveRAM[ i/2 ] >> ( ( ( i + 1 ) % 2 ) * 4 ) ) & 0b1111 ; - // get 32 samples; - // As CH3 plays, it reads wave RAM left to right, upper nibble first. - // That is, $FF30’s upper nibble, $FF30’s lower nibble, $FF31’s upper nibble, and so on. - } +void WaveChannel::readOutputLevel(){ + // printf("NR[2]: %x\n", mMap->readMemory(NR[2])); + outputLevel = (mMap->readMemory(NR[2]) >> 5 ) & 0b011; +} + +void WaveChannel::readSoundLengthEnable(){ + // printf("NR[2]: %x\n", mMap->readMemory(NR[2])); + soundLengthEnable = ( mMap->readMemory(NR[2]) & 0b01000000 ) >> 6; // bit 6 } \ No newline at end of file diff --git a/src/sound.h b/src/sound.h old mode 100644 new mode 100755 index 12fe55b..8b01f98 --- a/src/sound.h +++ b/src/sound.h @@ -13,7 +13,7 @@ class PulseChannel Word regAddr = 0; // NRx0, NRx1, NRx2, NRx3, NRx4 - Byte NR[5]; + Word NR[5]; MemoryMap* mMap; @@ -26,7 +26,6 @@ class PulseChannel // NRx0 Byte sweepPace; Byte sweepPaceClock; - bool swwepDirection; Byte sweepChange; Byte sweepSlope; @@ -83,50 +82,51 @@ class WaveChannel { private: - Byte NR[5]; + Word NR[5]; Word registerAddress=0xFF1A; - MemoryMap* mMap; - //FF1A — NR30: Channel 3 DAC enable + MemoryMap* mMap; + Byte index; + Byte volume; + Byte outVolume; + // NRx0 bool enable; - // FF1B — NR31: Channel 3 length timer [write-only] + // NRx1 Byte lengthTimer; - // FF1C — NR32: Channel 3 output level + // NRx2 Byte outputLevel; - // FF1D — NR33: Channel 3 period low [write-only] - // needs 11 bits - 3 lower bits from NRX4 + 8 bits from NRx3 - Word periodValue; - double sampleRate; - double toneFrequency; + // Nrx3 + // needs 11 bits - 3 bits from NRX4 + 8 bits from NRx3 + Word periodValue; + + // NRx4 - //FF1E — NR34: Channel 3 period high & control bool trigger; bool soundLengthEnable; - //FF30–FF3F — Wave pattern RAM + // Wave RAM Word waveRAM_Address = 0xFF30; Byte waveRAM[16]; Byte waveSamples[32]; public: + // bool trigger; WaveChannel(); - void init(); - void run(Byte rateDIV); + void setMemoryMap(MemoryMap* m){ mMap = m; } void enableAndLoad(); - void setMemoryMap(MemoryMap* m){ mMap = m;} - // bool checkTrigger(); - // void takeSample(); - // Byte getVolume(); - bool getEnable(); - void setEnable(bool enable); - void writeLengthTimer(Byte timer); - Byte getOutputLevel(); - Word getPeriodValue(); - void triggerChannel(); //implement this - void readWaveRAM(); + void readWaveRam(); + bool checkEnable(); + void readEnable(); + bool checkTrigger(); + bool checkLengthEnable(); + void run(Byte rateDiv); + void takeSample(); + Byte getVolume(); + void readOutputLevel(); + void readSoundLengthEnable(); }; class NoiseChannel @@ -149,24 +149,13 @@ class NoiseChannel bool trigger; bool soundLengthEnable; - - -public: - NoiseChannel(); - bool init(); - void run(Byte rateDIV); - void enableAndLoad(); - void setMemoryMap(MemoryMap* m){ mMap = m;} - bool checkTrigger(); - void takeSample(); - bool checkEnable(); - Byte getVolume(); }; class APU { private: + Byte preDiv; // SDL Audio // https://documentation.help/SDL/guideaudioexamples.html SDL_AudioSpec wanted, obtained; @@ -195,11 +184,9 @@ class APU int sampleRateTimer; // Audio Controllers - //FF26 — NR52: Audio master control bool enableOutput; bool channelEnable[4]; - Byte soundPann; bool enableVINLeft; @@ -223,10 +210,5 @@ class APU void executeAPU(); void setMemoryMap(MemoryMap* m){ mMap = m; } void test(); - bool checkEnable(); - bool checkChannelEnable(Channel channel) - bool triggerAPU(); - bool checkPann(Channel channel, bool direction) // direction:1 => left - void setPann(Channel channel, bool direction) // direction:1 => left - Byte getMasterVolume(bool direction) // direction:1 => left + }; diff --git a/src/types.h b/src/types.h old mode 100644 new mode 100755 index 26047a3..edd42d2 --- a/src/types.h +++ b/src/types.h @@ -7,5 +7,4 @@ typedef unsigned char Byte; typedef char SByte; typedef unsigned short Word; typedef signed short SWord; -typedef unsigned int color; -enum Channel { Pulse1 ,Pulse2, Wave, Noise } \ No newline at end of file +typedef unsigned int color; \ No newline at end of file