mirror of
https://github.com/MoleskiCoder/EightBit.git
synced 2025-01-11 17:29:57 +00:00
A different approach to audio handling. Just holding data at the moment.
Signed-off-by: Adrian.Conlon <adrian.conlon@gmail.com>
This commit is contained in:
parent
462b82add6
commit
61ae382a98
310
LR35902/inc/Audio.h
Normal file
310
LR35902/inc/Audio.h
Normal file
@ -0,0 +1,310 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
|
||||
#include <Processor.h>
|
||||
|
||||
namespace EightBit {
|
||||
namespace GameBoy {
|
||||
|
||||
class Envelope {
|
||||
public:
|
||||
Envelope() {}
|
||||
|
||||
enum Direction { Attenuate, Amplify };
|
||||
|
||||
int default() const { return m_defaultValue; }
|
||||
void setDefault(int value) { m_defaultValue = value; }
|
||||
|
||||
Direction direction() const { return (Direction)m_direction; }
|
||||
void setDirection(int value) { m_direction = value; }
|
||||
void setDirection(Direction value) { setDirection((int)value); }
|
||||
|
||||
int stepLength() const { return m_stepLength; }
|
||||
void setStepLength(int value) { m_stepLength = value; }
|
||||
|
||||
void dump() const {
|
||||
std::cout << "Envelope: default=" << default() << ",direction=" << direction() << ",step length=" << stepLength() << std::endl;
|
||||
}
|
||||
|
||||
private:
|
||||
int m_defaultValue;
|
||||
int m_direction;
|
||||
int m_stepLength;
|
||||
};
|
||||
|
||||
class Sweep {
|
||||
public:
|
||||
Sweep() {}
|
||||
|
||||
enum Direction { Addition, Subtraction };
|
||||
|
||||
int time() const { return m_time; }
|
||||
void setTime(int value) { m_time = value; }
|
||||
|
||||
Direction direction() const { return (Direction)m_direction; }
|
||||
void setDirection(int value) { m_direction = value; }
|
||||
void setDirection(Direction value) { setDirection((int)value); }
|
||||
|
||||
int shift() const { return m_shift; }
|
||||
void setShift(int value) { m_shift = value; }
|
||||
|
||||
void dump() const {
|
||||
std::cout << "Sweep: time=" << time() << ",direction=" << direction() << ",shift=" << shift() << std::endl;
|
||||
}
|
||||
|
||||
private:
|
||||
int m_time;
|
||||
int m_direction;
|
||||
int m_shift;
|
||||
};
|
||||
|
||||
class AudioVoice {
|
||||
public:
|
||||
AudioVoice() {}
|
||||
|
||||
enum Type { Continuous, Counter };
|
||||
|
||||
Type type() const { return (Type)m_counterContinuous; }
|
||||
void setType(int value) { m_counterContinuous = value; }
|
||||
void setType(Type value) { setType((int)value); }
|
||||
|
||||
bool initialise() const { return !!m_initialise; }
|
||||
void setInitialise(bool value) { m_initialise = value; }
|
||||
|
||||
virtual void dump() const {
|
||||
std::cout << "Audio Voice: type=" << type() << ",initialise=" << initialise() << std::endl;
|
||||
}
|
||||
|
||||
private:
|
||||
int m_counterContinuous;
|
||||
int m_initialise;
|
||||
};
|
||||
|
||||
class WaveVoice : public AudioVoice {
|
||||
public:
|
||||
WaveVoice() {}
|
||||
|
||||
int frequencyLowOrder() const { return m_frequencyLowOrder; }
|
||||
|
||||
void setFrequencyLowOrder(int value) {
|
||||
assert(value < Processor::Bit8);
|
||||
m_frequencyLowOrder = value;
|
||||
}
|
||||
|
||||
int frequencyHighOrder() const { return m_frequencyHighOrder; }
|
||||
|
||||
void setFrequencyHighOrder(int value) {
|
||||
assert(value < Processor::Bit3);
|
||||
m_frequencyHighOrder = value;
|
||||
}
|
||||
|
||||
int frequency() const {
|
||||
return (m_frequencyHighOrder >> 8) | m_frequencyLowOrder;
|
||||
}
|
||||
|
||||
void setFrequency(int value) {
|
||||
assert(value < Processor::Bit11);
|
||||
m_frequencyHighOrder = (value >> 8) & Processor::Mask3;
|
||||
m_frequencyLowOrder = value & Processor::Mask8;
|
||||
}
|
||||
|
||||
virtual void dump() const override {
|
||||
AudioVoice::dump();
|
||||
std::cout << "Wave Voice: frequency=" << frequency() << std::endl;
|
||||
}
|
||||
|
||||
private:
|
||||
int m_frequencyLowOrder; // 8 bits
|
||||
int m_frequencyHighOrder; // 3 bits
|
||||
};
|
||||
|
||||
class RectangularVoice : public WaveVoice {
|
||||
public:
|
||||
RectangularVoice() {}
|
||||
|
||||
int waveFormDutyCycle() const { return m_waveFormDutyCycle; }
|
||||
void setWaveFormDutyCycle(int value) { m_waveFormDutyCycle = value; }
|
||||
|
||||
int length() const { return m_soundLength; }
|
||||
void setLength(int value) { m_soundLength = value; }
|
||||
|
||||
virtual void dump() const override {
|
||||
WaveVoice::dump();
|
||||
std::cout << "Rectangular Voice: wave form duty=" << waveFormDutyCycle() << ",length=" << length() << std::endl;
|
||||
}
|
||||
|
||||
private:
|
||||
int m_waveFormDutyCycle;
|
||||
int m_soundLength;
|
||||
};
|
||||
|
||||
// NR2X
|
||||
class EnvelopedRectangularVoice : public RectangularVoice {
|
||||
public:
|
||||
EnvelopedRectangularVoice() {}
|
||||
|
||||
Envelope& envelope() { return m_envelope; }
|
||||
|
||||
virtual void dump() const override {
|
||||
RectangularVoice::dump();
|
||||
m_envelope.dump();
|
||||
}
|
||||
|
||||
private:
|
||||
Envelope m_envelope;
|
||||
};
|
||||
|
||||
// NR1X
|
||||
class SweptEnvelopedRectangularVoice : public EnvelopedRectangularVoice {
|
||||
public:
|
||||
SweptEnvelopedRectangularVoice() {}
|
||||
|
||||
Sweep& sweep() { return m_sweep; }
|
||||
|
||||
virtual void dump() const override {
|
||||
EnvelopedRectangularVoice::dump();
|
||||
m_sweep.dump();
|
||||
}
|
||||
|
||||
private:
|
||||
Sweep m_sweep;
|
||||
};
|
||||
|
||||
// NR3X
|
||||
class UserDefinedWaveVoice : public WaveVoice {
|
||||
public:
|
||||
UserDefinedWaveVoice() {}
|
||||
|
||||
bool enabled() const { return !!m_enabled; }
|
||||
void setEnabled(bool value) { m_enabled = value; }
|
||||
|
||||
int length() const { return m_soundLength; }
|
||||
void setLength(int value) { m_soundLength = value; }
|
||||
|
||||
int level() const { return m_outputLevel; }
|
||||
void setLevel(int value) { m_outputLevel = value; }
|
||||
|
||||
int packedWaveDatum(int i) const {
|
||||
assert(i < 16);
|
||||
return m_waveData[i];
|
||||
}
|
||||
|
||||
void setPackedWaveDatum(int i, uint8_t value) {
|
||||
assert(i < 16);
|
||||
m_waveData[i] = value;
|
||||
}
|
||||
|
||||
int waveDatum(int i) const {
|
||||
assert(i < 32);
|
||||
const auto packed = packedWaveDatum(i >> 1);
|
||||
return i & 1 ? Processor::lowNibble(packed) : Processor::highNibble(packed);
|
||||
}
|
||||
|
||||
private:
|
||||
int m_enabled;
|
||||
int m_soundLength;
|
||||
int m_outputLevel;
|
||||
std::array<uint8_t, 16> m_waveData;
|
||||
};
|
||||
|
||||
// NR4X
|
||||
class WhiteNoiseWaveVoice : public AudioVoice {
|
||||
public:
|
||||
WhiteNoiseWaveVoice() {}
|
||||
|
||||
Envelope& envelope() { return m_envelope; }
|
||||
|
||||
int length() const { return m_soundLength; }
|
||||
void setLength(int value) { m_soundLength = value; }
|
||||
|
||||
int polynomialShiftClockFrequency() const { return m_polynomialShiftClockFrequency; }
|
||||
void setPolynomialShiftClockFrequency(int value) { m_polynomialShiftClockFrequency = value; }
|
||||
|
||||
int polynomialCounterSteps() const { return m_polynomialCounterSteps; }
|
||||
void setPolynomialCounterSteps(int value) { m_polynomialCounterSteps = value; }
|
||||
|
||||
int frequencyDivisionRatio() const { return m_frequencyDivisionRatio; }
|
||||
void setFrequencyDivisionRatio(int value) { m_frequencyDivisionRatio = value; }
|
||||
|
||||
private:
|
||||
Envelope m_envelope;
|
||||
int m_soundLength;
|
||||
int m_polynomialShiftClockFrequency;
|
||||
int m_polynomialCounterSteps;
|
||||
int m_frequencyDivisionRatio;
|
||||
};
|
||||
|
||||
class OutputChannel {
|
||||
public:
|
||||
OutputChannel() {}
|
||||
|
||||
bool vin() const { return m_vin; }
|
||||
void setVin(bool value) { m_vin = value; }
|
||||
|
||||
int outputLevel() const { return m_outputLevel; }
|
||||
void setOutputLevel(int value) { m_outputLevel = value; }
|
||||
|
||||
bool& outputVoice(int voice) { return m_outputVoice[voice]; }
|
||||
bool& outputVoice1() { return m_outputVoice[0]; }
|
||||
bool& outputVoice2() { return m_outputVoice[1]; }
|
||||
bool& outputVoice3() { return m_outputVoice[2]; }
|
||||
bool& outputVoice4() { return m_outputVoice[3]; }
|
||||
|
||||
private:
|
||||
bool m_vin;
|
||||
int m_outputLevel;
|
||||
std::array<bool, 4> m_outputVoice;
|
||||
};
|
||||
|
||||
class Audio {
|
||||
public:
|
||||
Audio() {
|
||||
m_voices[0] = std::make_shared<SweptEnvelopedRectangularVoice>();
|
||||
m_voices[1] = std::make_shared<EnvelopedRectangularVoice>();
|
||||
m_voices[2] = std::make_shared<UserDefinedWaveVoice>();
|
||||
m_voices[3] = std::make_shared<WhiteNoiseWaveVoice>();
|
||||
}
|
||||
|
||||
std::shared_ptr<AudioVoice> voice(int i) { return m_voices[i]; }
|
||||
|
||||
SweptEnvelopedRectangularVoice* voice1() {
|
||||
return (SweptEnvelopedRectangularVoice*)voice(0).get();
|
||||
}
|
||||
|
||||
EnvelopedRectangularVoice* voice2() {
|
||||
return (EnvelopedRectangularVoice*)voice(1).get();
|
||||
}
|
||||
|
||||
UserDefinedWaveVoice* voice3() {
|
||||
return (UserDefinedWaveVoice*)voice(2).get();
|
||||
}
|
||||
|
||||
WhiteNoiseWaveVoice* voice4() {
|
||||
return (WhiteNoiseWaveVoice*)voice(3).get();
|
||||
}
|
||||
|
||||
OutputChannel& channel(int i) { return m_channels[i]; }
|
||||
OutputChannel& channel1() { return channel(0); }
|
||||
OutputChannel& channel2() { return channel(1); }
|
||||
|
||||
bool enabled() const { return m_enabled; }
|
||||
void setEnabled(bool value) { m_enabled = value; }
|
||||
|
||||
void dump() const {
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
std::cout << "** Voice " << i + 1 << std::endl;
|
||||
m_voices[i]->dump();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::array<std::shared_ptr<AudioVoice>, 4> m_voices;
|
||||
std::array<OutputChannel, 2> m_channels;
|
||||
bool m_enabled;
|
||||
};
|
||||
}
|
||||
}
|
@ -9,6 +9,8 @@
|
||||
#include <Processor.h>
|
||||
#include <Signal.h>
|
||||
|
||||
#include "Audio.h"
|
||||
|
||||
namespace EightBit {
|
||||
namespace GameBoy {
|
||||
class Bus : public EightBit::Bus {
|
||||
@ -118,29 +120,7 @@ namespace EightBit {
|
||||
|
||||
Bus();
|
||||
|
||||
Signal<std::tuple<int, int>> Audio_SweepTimeModified;
|
||||
Signal<std::tuple<int, int>> Audio_SweepDirectionModified;
|
||||
Signal<std::tuple<int, int>> Audio_SweepShiftModified;
|
||||
Signal<std::tuple<int, int>> Audio_WavePatternDutyModified;
|
||||
Signal<std::tuple<int, int>> Audio_SoundLengthModified;
|
||||
Signal<std::tuple<int, int>> Audio_DefaultEnvelopeVolumeModified;
|
||||
Signal<std::tuple<int, int>> Audio_EnvelopeDirectionModified;
|
||||
Signal<std::tuple<int, int>> Audio_EnvelopeStepLengthModified;
|
||||
Signal<std::tuple<int, int>> Audio_FrequencyLoModified;
|
||||
Signal<std::tuple<int, int>> Audio_InitialiseModified;
|
||||
Signal<std::tuple<int, int>> Audio_CounterContinuousSelectionModified;
|
||||
Signal<std::tuple<int, int>> Audio_FrequencyHiModified;
|
||||
Signal<std::tuple<int, int>> Audio_SoundOnOffModified;
|
||||
Signal<std::tuple<int, int>> Audio_OutputLevelModified;
|
||||
Signal<std::tuple<int, int>> Audio_PolynomialShiftClockFrequencyModified;
|
||||
Signal<std::tuple<int, int>> Audio_PolynomialCounterStepModified;
|
||||
Signal<std::tuple<int, int>> Audio_FrequencyDivisionRatioModified;
|
||||
Signal<std::tuple<int, int>> Audio_SO_VinOnOffModified;
|
||||
Signal<std::tuple<int, int>> Audio_SO_OutputLevelModified;
|
||||
Signal<std::tuple<int, int, int>> Audio_SO_SoundOutputModified;
|
||||
Signal<int> Audio_AllSoundOnOffModified;
|
||||
Signal<std::tuple<int, int>> Audio_ChannelOnOffModified;
|
||||
|
||||
Audio& audio() { return m_audio; }
|
||||
|
||||
void reset();
|
||||
|
||||
@ -337,6 +317,8 @@ namespace EightBit {
|
||||
bool m_p11; // left/b
|
||||
bool m_p10; // right/a
|
||||
|
||||
Audio m_audio;
|
||||
|
||||
void checkTimer(int cycles);
|
||||
|
||||
void validateCartridgeType();
|
||||
|
@ -246,120 +246,116 @@ void EightBit::GameBoy::Bus::Bus_WrittenByte(const uint16_t address) {
|
||||
break;
|
||||
|
||||
case BASE + NR10: // Sound mode 1 register: Sweep
|
||||
Audio_SweepTimeModified.fire(std::make_tuple(1, (value >> 4) & Processor::Mask3)); // Bits 4-6
|
||||
Audio_SweepDirectionModified.fire(std::make_tuple(1, (value >> 3) & Processor::Mask1)); // Bits 3
|
||||
Audio_SweepShiftModified.fire(std::make_tuple(1, value & Processor::Mask3)); // Bits 0-2
|
||||
audio().voice1()->sweep().setTime((value >> 4) & Processor::Mask3); // Bits 4-6
|
||||
audio().voice1()->sweep().setDirection((value >> 3) & Processor::Mask1); // Bit 3
|
||||
audio().voice1()->sweep().setShift(value & Processor::Mask3); // Bits 0-2
|
||||
break;
|
||||
|
||||
case BASE + NR11: // Sound mode 1 register: Sound length / Wave pattern duty
|
||||
Audio_WavePatternDutyModified.fire(std::make_tuple(1, (value >> 6) & Processor::Mask2));// Bits 6-7
|
||||
Audio_SoundLengthModified.fire(std::make_tuple(1, value & Processor::Mask6)); // Bits 0-5
|
||||
audio().voice1()->setWaveFormDutyCycle((value >> 6) & Processor::Mask2); // Bits 6-7
|
||||
audio().voice1()->setLength(value & Processor::Mask6); // Bits 0-5
|
||||
break;
|
||||
|
||||
case BASE + NR12: // Sound mode 1 register: Envelope
|
||||
Audio_DefaultEnvelopeVolumeModified.fire(std::make_tuple(1, (value >> 4) & Processor::Mask4)); // Bits 4-7
|
||||
Audio_EnvelopeDirectionModified.fire(std::make_tuple(1, (value >> 3) & Processor::Mask1)); // Bits 3
|
||||
Audio_EnvelopeStepLengthModified.fire(std::make_tuple(1, value & Processor::Mask3)); // Bits 0-2
|
||||
audio().voice1()->envelope().setDefault((value >> 4) & Processor::Mask4); // Bits 4-7
|
||||
audio().voice1()->envelope().setDirection((value >> 3) & Processor::Mask1); // Bit 3
|
||||
audio().voice1()->envelope().setStepLength(value & Processor::Mask3); // Bits 0-2
|
||||
break;
|
||||
|
||||
case BASE + NR13: // Sound mode 1 register: Frequency lo
|
||||
Audio_FrequencyLoModified.fire(std::make_tuple(1, value));
|
||||
audio().voice1()->setFrequencyLowOrder(value);
|
||||
break;
|
||||
|
||||
case BASE + NR14: // Sound mode 1 register: Frequency hi
|
||||
Audio_InitialiseModified.fire(std::make_tuple(1, (value >> 7) & Processor::Mask1)); // Bits 7
|
||||
Audio_CounterContinuousSelectionModified.fire(std::make_tuple(1, (value >> 6) & Processor::Mask1));// Bits 6
|
||||
Audio_FrequencyHiModified.fire(std::make_tuple(1, value & Processor::Mask3)); // Bits 0-2
|
||||
audio().voice1()->setInitialise((value >> 7) & Processor::Mask1); // Bits 7
|
||||
audio().voice1()->setType((value >> 6) & Processor::Mask1); // Bits 6
|
||||
audio().voice1()->setFrequencyHighOrder(value & Processor::Mask3); // Bits 0-2
|
||||
break;
|
||||
|
||||
case BASE + NR21: // Sound mode 2 register: Sound length / Wave pattern duty
|
||||
Audio_WavePatternDutyModified.fire(std::make_tuple(2, (value >> 6) & Processor::Mask2));// Bits 6-7
|
||||
Audio_SoundLengthModified.fire(std::make_tuple(2, Processor::Mask6)); // Bits 0-5
|
||||
audio().voice2()->setWaveFormDutyCycle((value >> 6) & Processor::Mask2); // Bits 6-7
|
||||
audio().voice2()->setLength(value & Processor::Mask6); // Bits 0-5
|
||||
break;
|
||||
|
||||
case BASE + NR22: // Sound mode 2 register: Envelope
|
||||
Audio_DefaultEnvelopeVolumeModified.fire(std::make_tuple(2, (value >> 4) & Processor::Mask4)); // Bits 4-7
|
||||
Audio_EnvelopeDirectionModified.fire(std::make_tuple(2, (value >> 3) & Processor::Mask1)); // Bits 3
|
||||
Audio_EnvelopeStepLengthModified.fire(std::make_tuple(2, value & Processor::Mask3)); // Bits 0-2
|
||||
audio().voice2()->envelope().setDefault((value >> 4) & Processor::Mask4); // Bits 4-7
|
||||
audio().voice2()->envelope().setDirection((value >> 3) & Processor::Mask1); // Bit 3
|
||||
audio().voice2()->envelope().setStepLength(value & Processor::Mask3); // Bits 0-2
|
||||
break;
|
||||
|
||||
case BASE + NR23: // Sound mode 2 register: Frequency lo
|
||||
Audio_FrequencyLoModified.fire(std::make_tuple(2, value));
|
||||
audio().voice2()->setFrequencyLowOrder(value);
|
||||
break;
|
||||
|
||||
case BASE + NR24: // Sound mode 2 register: Frequency hi
|
||||
Audio_InitialiseModified.fire(std::make_tuple(2, (value >> 7) & Processor::Mask1)); // Bits 7
|
||||
Audio_CounterContinuousSelectionModified.fire(std::make_tuple(2, (value >> 6) & Processor::Mask1));// Bits 6
|
||||
Audio_FrequencyHiModified.fire(std::make_tuple(2, value & Processor::Mask3)); // Bits 0-2
|
||||
audio().voice2()->setInitialise((value >> 7) & Processor::Mask1); // Bit 7
|
||||
audio().voice2()->setType((value >> 6) & Processor::Mask1); // Bit 6
|
||||
audio().voice2()->setFrequencyHighOrder(value & Processor::Mask3); // Bits 0-2
|
||||
break;
|
||||
|
||||
case BASE + NR30: // Sound mode 3 register: Sound on/off
|
||||
Audio_SoundOnOffModified.fire(std::make_tuple(3, (value >> 7) & Processor::Mask1)); // Bits 0-2
|
||||
audio().voice3()->setEnabled((value >> 7) & Processor::Mask1); // Bit 7
|
||||
break;
|
||||
|
||||
case BASE + NR31: // Sound mode 3 register: Sound length
|
||||
Audio_SoundLengthModified.fire(std::make_tuple(3, value));
|
||||
audio().voice3()->setLength(value);
|
||||
break;
|
||||
|
||||
case BASE + NR32: // Sound mode 3 register: Select output level
|
||||
Audio_OutputLevelModified.fire(std::make_tuple(3, value));
|
||||
audio().voice3()->setLevel(value);
|
||||
break;
|
||||
|
||||
case BASE + NR33: // Sound mode 3 register: Frequency lo
|
||||
Audio_FrequencyLoModified.fire(std::make_tuple(3, value));
|
||||
audio().voice3()->setFrequencyLowOrder(value);
|
||||
break;
|
||||
|
||||
case BASE + NR34: // Sound mode 3 register: Frequency hi
|
||||
Audio_InitialiseModified.fire(std::make_tuple(3, (value >> 7) & Processor::Mask1)); // Bits 7
|
||||
Audio_CounterContinuousSelectionModified.fire(std::make_tuple(3, (value >> 6) & Processor::Mask1));// Bits 6
|
||||
Audio_FrequencyHiModified.fire(std::make_tuple(3, value & Processor::Mask3)); // Bits 0-2
|
||||
audio().voice3()->setInitialise((value >> 7) & Processor::Mask1); // Bits 7
|
||||
audio().voice3()->setType((value >> 6) & Processor::Mask1); // Bits 6
|
||||
audio().voice3()->setFrequencyHighOrder(value & Processor::Mask3); // Bits 0-2
|
||||
break;
|
||||
|
||||
case BASE + NR41: // Sound mode 4 register: Sound length
|
||||
Audio_SoundLengthModified.fire(std::make_tuple(4, value & Processor::Mask6)); // Bits 0-5
|
||||
audio().voice4()->setLength(value & Processor::Mask6); // Bits 0-5
|
||||
break;
|
||||
|
||||
case BASE + NR42: // Sound mode 4 register: Envelope
|
||||
Audio_DefaultEnvelopeVolumeModified.fire(std::make_tuple(4, (value >> 4) & Processor::Mask4)); // Bits 4-7
|
||||
Audio_EnvelopeDirectionModified.fire(std::make_tuple(4, (value >> 3) & Processor::Mask1)); // Bits 3
|
||||
Audio_EnvelopeStepLengthModified.fire(std::make_tuple(4, value & Processor::Mask3)); // Bits 0-2
|
||||
audio().voice4()->envelope().setDefault((value >> 4) & Processor::Mask4); // Bits 4-7
|
||||
audio().voice4()->envelope().setDirection((value >> 3) & Processor::Mask1); // Bit 3
|
||||
audio().voice4()->envelope().setStepLength(value & Processor::Mask3); // Bits 0-2
|
||||
break;
|
||||
|
||||
case BASE + NR43: // Sound mode 4 register: Polynomial counter
|
||||
Audio_PolynomialShiftClockFrequencyModified.fire(std::make_tuple(4, (value >> 4) & Processor::Mask4)); // Bits 4-7
|
||||
Audio_PolynomialCounterStepModified.fire(std::make_tuple(4, (value >> 3) & Processor::Mask1)); // Bit 3
|
||||
Audio_FrequencyDivisionRatioModified.fire(std::make_tuple(4, value & Processor::Mask3)); // Bits 0-2
|
||||
audio().voice4()->setPolynomialShiftClockFrequency((value >> 4) & Processor::Mask4); // Bits 4-7
|
||||
audio().voice4()->setPolynomialCounterSteps((value >> 3) & Processor::Mask1); // Bit 3
|
||||
audio().voice4()->setFrequencyDivisionRatio(value & Processor::Mask3); // Bits 0-2
|
||||
break;
|
||||
|
||||
case BASE + NR44: // Sound mode 4 register: counter/consecutive; inital
|
||||
Audio_InitialiseModified.fire(std::make_tuple(4, (value >> 7) & Processor::Mask1)); // Bit 7
|
||||
Audio_CounterContinuousSelectionModified.fire(std::make_tuple(4, (value >> 6) & Processor::Mask1)); // Bits 6
|
||||
audio().voice4()->setInitialise((value >> 7) & Processor::Mask1); // Bit 7
|
||||
audio().voice4()->setType((value >> 6) & Processor::Mask1); // Bit 6
|
||||
break;
|
||||
|
||||
case BASE + NR50: // Channel control/on-off/volume
|
||||
Audio_SO_VinOnOffModified.fire(std::make_tuple(2, (value >> 7) & Processor::Mask1)); // Bit 7
|
||||
Audio_SO_OutputLevelModified.fire(std::make_tuple(2, (value >> 4) & Processor::Mask3)); // Bits 4-6
|
||||
Audio_SO_VinOnOffModified.fire(std::make_tuple(1, (value >> 3) & Processor::Mask1)); // Bit 3
|
||||
Audio_SO_OutputLevelModified.fire(std::make_tuple(1, value & Processor::Mask3)); // Bits 0-2
|
||||
case BASE + NR50: // Channel control: on-off/volume
|
||||
audio().channel2().setVin((value >> 7) & Processor::Mask1); // Bit 7
|
||||
audio().channel2().setOutputLevel((value >> 4) & Processor::Mask3); // Bits 4-6
|
||||
audio().channel1().setVin((value >> 3) & Processor::Mask1); // Bit 3
|
||||
audio().channel1().setOutputLevel(value & Processor::Mask3); // Bits 0-2
|
||||
break;
|
||||
|
||||
case BASE + NR51:
|
||||
Audio_SO_SoundOutputModified.fire(std::make_tuple(2, 4, (value >> 7) & Processor::Mask1)); // Bit 7
|
||||
Audio_SO_SoundOutputModified.fire(std::make_tuple(2, 3, (value >> 6) & Processor::Mask1)); // Bit 6
|
||||
Audio_SO_SoundOutputModified.fire(std::make_tuple(2, 2, (value >> 5) & Processor::Mask1)); // Bit 5
|
||||
Audio_SO_SoundOutputModified.fire(std::make_tuple(2, 1, (value >> 4) & Processor::Mask1)); // Bit 4
|
||||
Audio_SO_SoundOutputModified.fire(std::make_tuple(1, 4, (value >> 3) & Processor::Mask1)); // Bit 3
|
||||
Audio_SO_SoundOutputModified.fire(std::make_tuple(1, 3, (value >> 2) & Processor::Mask1)); // Bit 2
|
||||
Audio_SO_SoundOutputModified.fire(std::make_tuple(1, 2, (value >> 1) & Processor::Mask1)); // Bit 1
|
||||
Audio_SO_SoundOutputModified.fire(std::make_tuple(1, 1, value & Processor::Mask1)); // Bit 0
|
||||
audio().channel2().outputVoice4() = (value >> 7) & Processor::Mask1; // Bit 7
|
||||
audio().channel2().outputVoice3() = (value >> 6) & Processor::Mask1; // Bit 6
|
||||
audio().channel2().outputVoice2() = (value >> 5) & Processor::Mask1; // Bit 5
|
||||
audio().channel2().outputVoice1() = (value >> 4) & Processor::Mask1; // Bit 4
|
||||
audio().channel1().outputVoice4() = (value >> 3) & Processor::Mask1; // Bit 3
|
||||
audio().channel1().outputVoice3() = (value >> 2) & Processor::Mask1; // Bit 2
|
||||
audio().channel1().outputVoice2() = (value >> 1) & Processor::Mask1; // Bit 1
|
||||
audio().channel1().outputVoice1() = value & Processor::Mask1; // Bit 0
|
||||
break;
|
||||
|
||||
case BASE + NR52: // Sound on/off
|
||||
Audio_AllSoundOnOffModified.fire((value >> 7) & Processor::Mask1); // Bit 7
|
||||
Audio_ChannelOnOffModified.fire(std::make_tuple(4, (value >> 3) & Processor::Mask1)); // Bit 3
|
||||
Audio_ChannelOnOffModified.fire(std::make_tuple(3, (value >> 2) & Processor::Mask1)); // Bit 2
|
||||
Audio_ChannelOnOffModified.fire(std::make_tuple(2, (value >> 1) & Processor::Mask1)); // Bit 1
|
||||
Audio_ChannelOnOffModified.fire(std::make_tuple(1, value & Processor::Mask1)); // Bit 0
|
||||
audio().setEnabled((value >> 7) & Processor::Mask1); // Bit 7
|
||||
break;
|
||||
|
||||
case BASE + LCDC:
|
||||
|
@ -140,6 +140,7 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\inc\AbstractColourPalette.h" />
|
||||
<ClInclude Include="..\inc\Audio.h" />
|
||||
<ClInclude Include="..\inc\GameBoyBus.h" />
|
||||
<ClInclude Include="..\inc\CharacterDefinition.h" />
|
||||
<ClInclude Include="..\inc\Disassembler.h" />
|
||||
|
@ -38,6 +38,9 @@
|
||||
<ClInclude Include="..\inc\ObjectAttribute.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\inc\Audio.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
|
@ -10,8 +10,11 @@
|
||||
#include <map>
|
||||
#include <bitset>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <cassert>
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
Loading…
x
Reference in New Issue
Block a user