mirror of
https://github.com/TomHarte/CLK.git
synced 2025-04-07 01:38:25 +00:00
Continues doing away with the attempt heavily to interleave the OPLL and OPL2, creating a new OPLL class.
This commit is contained in:
parent
e929d5d819
commit
386a7ca442
@ -11,6 +11,7 @@
|
||||
|
||||
#include <optional>
|
||||
#include <functional>
|
||||
#include "LowFrequencyOscillator.hpp"
|
||||
|
||||
namespace Yamaha {
|
||||
namespace OPL {
|
||||
|
40
Components/OPL2/Implementation/OPLBase.hpp
Normal file
40
Components/OPL2/Implementation/OPLBase.hpp
Normal file
@ -0,0 +1,40 @@
|
||||
//
|
||||
// OPLBase.hpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 03/05/2020.
|
||||
// Copyright © 2020 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef OPLBase_h
|
||||
#define OPLBase_h
|
||||
|
||||
#include "../../../Outputs/Speaker/Implementation/SampleSource.hpp"
|
||||
#include "../../../Concurrency/AsyncTaskQueue.hpp"
|
||||
|
||||
namespace Yamaha {
|
||||
namespace OPL {
|
||||
|
||||
template <typename Child> class OPLBase: public ::Outputs::Speaker::SampleSource {
|
||||
public:
|
||||
void write(uint16_t address, uint8_t value) {
|
||||
if(address & 1) {
|
||||
static_cast<Child *>(this)->write_register(selected_register_, value);
|
||||
} else {
|
||||
selected_register_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
OPLBase(Concurrency::DeferringAsyncTaskQueue &task_queue) : task_queue_(task_queue) {}
|
||||
|
||||
Concurrency::DeferringAsyncTaskQueue &task_queue_;
|
||||
|
||||
private:
|
||||
uint8_t selected_register_ = 0;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OPLBase_h */
|
@ -15,12 +15,12 @@
|
||||
namespace Yamaha {
|
||||
namespace OPL {
|
||||
|
||||
enum class Waveform {
|
||||
Sine, HalfSine, AbsSine, PulseSine
|
||||
};
|
||||
|
||||
template <int phase_precision> class WaveformGenerator {
|
||||
public:
|
||||
enum class Waveform {
|
||||
Sine, HalfSine, AbsSine, PulseSine
|
||||
};
|
||||
|
||||
/*!
|
||||
@returns The output of waveform @c form at [integral] phase @c phase.
|
||||
*/
|
||||
|
@ -18,6 +18,8 @@
|
||||
|
||||
using namespace Yamaha::OPL;
|
||||
|
||||
/*
|
||||
|
||||
template <typename Child>
|
||||
OPLBase<Child>::OPLBase(Concurrency::DeferringAsyncTaskQueue &task_queue) : task_queue_(task_queue) {}
|
||||
|
||||
@ -79,43 +81,42 @@ void OPLL::get_samples(std::size_t number_of_samples, std::int16_t *target) {
|
||||
audio_offset_ = (audio_offset_ + 1) % update_period;
|
||||
}
|
||||
|
||||
|
||||
/* // Fill in any leftover from the previous session.
|
||||
if(audio_offset_) {
|
||||
while(audio_offset_ < update_period && number_of_samples) {
|
||||
*target = int16_t(channels_[audio_offset_ / channel_output_period].level);
|
||||
++target;
|
||||
++audio_offset_;
|
||||
--number_of_samples;
|
||||
}
|
||||
audio_offset_ = 0;
|
||||
}
|
||||
|
||||
// End now if that provided everything that was asked for.
|
||||
if(!number_of_samples) return;
|
||||
|
||||
int total_updates = int(number_of_samples) / update_period;
|
||||
number_of_samples %= size_t(update_period);
|
||||
audio_offset_ = int(number_of_samples);
|
||||
|
||||
while(total_updates--) {
|
||||
update_all_chanels();
|
||||
|
||||
for(int c = 0; c < update_period; ++c) {
|
||||
*target = int16_t(channels_[c / channel_output_period].level);
|
||||
++target;
|
||||
}
|
||||
}
|
||||
|
||||
// If there are any other spots remaining, fill them.
|
||||
if(number_of_samples) {
|
||||
update_all_chanels();
|
||||
|
||||
for(int c = 0; c < int(number_of_samples); ++c) {
|
||||
*target = int16_t(channels_[c / channel_output_period].level);
|
||||
++target;
|
||||
}
|
||||
}*/
|
||||
// // Fill in any leftover from the previous session.
|
||||
// if(audio_offset_) {
|
||||
// while(audio_offset_ < update_period && number_of_samples) {
|
||||
// *target = int16_t(channels_[audio_offset_ / channel_output_period].level);
|
||||
// ++target;
|
||||
// ++audio_offset_;
|
||||
// --number_of_samples;
|
||||
// }
|
||||
// audio_offset_ = 0;
|
||||
// }
|
||||
//
|
||||
// // End now if that provided everything that was asked for.
|
||||
// if(!number_of_samples) return;
|
||||
//
|
||||
// int total_updates = int(number_of_samples) / update_period;
|
||||
// number_of_samples %= size_t(update_period);
|
||||
// audio_offset_ = int(number_of_samples);
|
||||
//
|
||||
// while(total_updates--) {
|
||||
// update_all_chanels();
|
||||
//
|
||||
// for(int c = 0; c < update_period; ++c) {
|
||||
// *target = int16_t(channels_[c / channel_output_period].level);
|
||||
// ++target;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // If there are any other spots remaining, fill them.
|
||||
// if(number_of_samples) {
|
||||
// update_all_chanels();
|
||||
//
|
||||
// for(int c = 0; c < int(number_of_samples); ++c) {
|
||||
// *target = int16_t(channels_[c / channel_output_period].level);
|
||||
// ++target;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
void OPLL::set_sample_volume_range(std::int16_t range) {
|
||||
@ -274,9 +275,9 @@ void OPLL::update_all_chanels() {
|
||||
#undef VOLUME
|
||||
}
|
||||
|
||||
/*
|
||||
template <Personality personality>
|
||||
void OPL2<personality>::get_samples(std::size_t number_of_samples, std::int16_t *target) {
|
||||
|
||||
//template <Personality personality>
|
||||
//void OPL2<personality>::get_samples(std::size_t number_of_samples, std::int16_t *target) {
|
||||
// TODO.
|
||||
// out = exp(logsin(phase2 + exp(logsin(phase1) + gain1)) + gain2)
|
||||
|
||||
@ -301,9 +302,9 @@ void OPL2<personality>::get_samples(std::size_t number_of_samples, std::int16_t
|
||||
// Tom tom, using operator 14,
|
||||
// Cymbal, using operator 17; and
|
||||
// Symbol, using operator 13.
|
||||
}
|
||||
//}
|
||||
|
||||
|
||||
*/
|
||||
|
||||
void OPL2::write_register(uint8_t address, uint8_t value) {
|
||||
|
||||
@ -393,3 +394,5 @@ uint8_t OPL2::read(uint16_t address) {
|
||||
// b5 = timer 2 flag
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
*/
|
||||
|
@ -20,24 +20,7 @@
|
||||
namespace Yamaha {
|
||||
namespace OPL {
|
||||
|
||||
template <typename Child> class OPLBase: public ::Outputs::Speaker::SampleSource {
|
||||
public:
|
||||
void write(uint16_t address, uint8_t value);
|
||||
|
||||
protected:
|
||||
OPLBase(Concurrency::DeferringAsyncTaskQueue &task_queue);
|
||||
|
||||
Concurrency::DeferringAsyncTaskQueue &task_queue_;
|
||||
LowFrequencyOscillator oscillator_;
|
||||
|
||||
uint8_t depth_rhythm_control_;
|
||||
uint8_t csm_keyboard_split_;
|
||||
bool waveform_enable_;
|
||||
|
||||
private:
|
||||
uint8_t selected_register_ = 0;
|
||||
};
|
||||
|
||||
/*
|
||||
struct OPL2: public OPLBase<OPL2> {
|
||||
public:
|
||||
// Creates a new OPL2.
|
||||
@ -132,7 +115,7 @@ struct OPLL: public OPLBase<OPLL> {
|
||||
int audio_offset_ = 0;
|
||||
|
||||
std::atomic<int> total_volume_;
|
||||
};
|
||||
};*/
|
||||
|
||||
}
|
||||
}
|
||||
|
215
Components/OPL2/OPLL.cpp
Normal file
215
Components/OPL2/OPLL.cpp
Normal file
@ -0,0 +1,215 @@
|
||||
//
|
||||
// OPLL.cpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 03/05/2020.
|
||||
// Copyright © 2020 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#include "OPLL.hpp"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
using namespace Yamaha::OPL;
|
||||
|
||||
OPLL::OPLL(Concurrency::DeferringAsyncTaskQueue &task_queue, int audio_divider, bool is_vrc7):
|
||||
OPLBase(task_queue), audio_divider_(audio_divider), is_vrc7_(is_vrc7) {
|
||||
// Due to the way that sound mixing works on the OPLL, the audio divider may not
|
||||
// be larger than 4.
|
||||
assert(audio_divider <= 4);
|
||||
|
||||
// Set up proper damping management.
|
||||
for(int c = 0; c < 9; ++c) {
|
||||
envelope_generators_[c].set_should_damp([this, c] {
|
||||
// Propagate attack mode to the modulator, and reset both phases.
|
||||
envelope_generators_[c + 9].set_key_on(true);
|
||||
phase_generators_[c + 0].reset();
|
||||
phase_generators_[c + 9].reset();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Machine-facing programmatic input.
|
||||
|
||||
void OPLL::write_register(uint8_t address, uint8_t value) {
|
||||
// The OPLL doesn't have timers or other non-audio functions, so all writes
|
||||
// go to the audio queue.
|
||||
task_queue_.defer([this, address, value] {
|
||||
// The first 8 locations are used to define the custom instrument, and have
|
||||
// exactly the same format as the patch set arrays at the head of this file.
|
||||
if(address < 8) {
|
||||
custom_instrument_[address] = value;
|
||||
|
||||
// Update all channels that refer to instrument 0.
|
||||
for(int c = 0; c < 9; ++c) {
|
||||
if(!channels_[c].instrument) {
|
||||
install_instrument(c);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Register 0xe enables or disables rhythm mode and contains the
|
||||
// percussion key-on bits.
|
||||
if(address == 0xe) {
|
||||
rhythm_mode_enabled_ = value & 0x20;
|
||||
rhythm_generators_[0].set_key_on(value & 0x01);
|
||||
rhythm_generators_[1].set_key_on(value & 0x02);
|
||||
rhythm_generators_[2].set_key_on(value & 0x04);
|
||||
rhythm_generators_[3].set_key_on(value & 0x08);
|
||||
rhythm_generators_[4].set_key_on(value & 0x10);
|
||||
return;
|
||||
}
|
||||
|
||||
// That leaves only per-channel selections, for which the addressing
|
||||
// is completely orthogonal; check that a valid channel is being requested.
|
||||
const auto index = address & 0xf;
|
||||
if(index > 8) return;
|
||||
|
||||
switch(address & 0xf0) {
|
||||
default: break;
|
||||
|
||||
// Address 1x sets the low 8 bits of the period for channel x.
|
||||
case 0x10:
|
||||
channels_[index].period = (channels_[index].period & ~0xff) | value;
|
||||
set_channel_period(index);
|
||||
return;
|
||||
|
||||
// Address 2x Sets the octave and a single bit of the frequency, as well
|
||||
// as setting key on and sustain mode.
|
||||
case 0x20:
|
||||
channels_[index].period = (channels_[index].period & 0xff) | (value & 1);
|
||||
channels_[index].octave = (value >> 1) & 7;
|
||||
set_channel_period(index);
|
||||
|
||||
// In this implementation the first 9 envelope generators are for
|
||||
// channel carriers, and their will_attack callback is used to trigger
|
||||
// key-on for modulators. But key-off needs to be set to both envelope
|
||||
// generators now.
|
||||
if(value & 0x10) {
|
||||
envelope_generators_[index].set_key_on(true);
|
||||
} else {
|
||||
envelope_generators_[index + 0].set_key_on(false);
|
||||
envelope_generators_[index + 9].set_key_on(false);
|
||||
}
|
||||
|
||||
// Set sustain bit to both the relevant operators.
|
||||
channels_[index].use_sustain = value & 0x20;
|
||||
set_use_sustain(index);
|
||||
return;
|
||||
|
||||
// Address 3x selects the instrument and attenuation for a channel;
|
||||
// in rhythm mode some of the nibbles that ordinarily identify instruments
|
||||
// instead nominate additional attenuations. This code reads those back
|
||||
// from the stored instrument values.
|
||||
case 0x30:
|
||||
channels_[index].instrument = value >> 4;
|
||||
channels_[index].attenuation = value >> 4;
|
||||
install_instrument(index);
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void OPLL::set_channel_period(int channel) {
|
||||
phase_generators_[channel + 0].set_period(channels_[channel].period, channels_[channel].octave);
|
||||
phase_generators_[channel + 9].set_period(channels_[channel].period, channels_[channel].octave);
|
||||
|
||||
key_level_scalers_[channel + 0].set_period(channels_[channel].period, channels_[channel].octave);
|
||||
key_level_scalers_[channel + 9].set_period(channels_[channel].period, channels_[channel].octave);
|
||||
}
|
||||
|
||||
const uint8_t *OPLL::instrument_definition(int instrument) {
|
||||
// Instrument 0 is the custom instrument.
|
||||
if(!instrument) return custom_instrument_;
|
||||
|
||||
// Instruments other than 0 are taken from the fixed set.
|
||||
const int index = (instrument - 1) * 8;
|
||||
return is_vrc7_ ? &vrc7_patch_set[index] : &opll_patch_set[index];
|
||||
}
|
||||
|
||||
void OPLL::install_instrument(int channel) {
|
||||
auto &carrier_envelope = envelope_generators_[channel + 0];
|
||||
auto &carrier_phase = phase_generators_[channel + 0];
|
||||
auto &carrier_scaler = key_level_scalers_[channel + 0];
|
||||
|
||||
auto &modulator_envelope = envelope_generators_[channel + 9];
|
||||
auto &modulator_phase = phase_generators_[channel + 9];
|
||||
auto &modulator_scaler = key_level_scalers_[channel + 9];
|
||||
|
||||
const uint8_t *const instrument = instrument_definition(channels_[channel].instrument);
|
||||
|
||||
// Bytes 0 (modulator) and 1 (carrier):
|
||||
//
|
||||
// b0-b3: multiplier;
|
||||
// b4: key-scale rate enable;
|
||||
// b5: sustain-level enable;
|
||||
// b6: vibrato enable;
|
||||
// b7: tremolo enable.
|
||||
modulator_phase.set_multiple(instrument[0] & 0xf);
|
||||
channels_[channel].modulator_key_rate_scale_multiplier = (instrument[0] >> 4) & 1;
|
||||
modulator_phase.set_vibrato_enabled(instrument[0] & 0x40);
|
||||
modulator_envelope.set_tremolo_enabled(instrument[0] & 0x80);
|
||||
|
||||
carrier_phase.set_multiple(instrument[1] & 0xf);
|
||||
channels_[channel].carrier_key_rate_scale_multiplier = (instrument[1] >> 4) & 1;
|
||||
carrier_phase.set_vibrato_enabled(instrument[1] & 0x40);
|
||||
carrier_envelope.set_tremolo_enabled(instrument[1] & 0x80);
|
||||
|
||||
// Pass off bit 5.
|
||||
set_use_sustain(channel);
|
||||
|
||||
// Byte 2:
|
||||
//
|
||||
// b0–b5: modulator attenuation;
|
||||
// b6–b7: modulator key-scale level.
|
||||
modulator_scaler.set_key_scaling_level(instrument[3] >> 6);
|
||||
channels_[channel].modulator_attenuation = instrument[2] & 0x3f;
|
||||
|
||||
// Byte 3:
|
||||
//
|
||||
// b0–b2: modulator feedback level;
|
||||
// b3: modulator waveform selection;
|
||||
// b4: carrier waveform selection;
|
||||
// b5: [unused]
|
||||
// b6–b7: carrier key-scale level.
|
||||
channels_[channel].modulator_feedback = instrument[3] & 7;
|
||||
channels_[channel].modulator_waveform = Waveform((instrument[3] >> 3) & 1);
|
||||
channels_[channel].carrier_waveform = Waveform((instrument[3] >> 4) & 1);
|
||||
carrier_scaler.set_key_scaling_level(instrument[3] >> 6);
|
||||
|
||||
// Bytes 4 (modulator) and 5 (carrier):
|
||||
//
|
||||
// b0–b3: decay rate;
|
||||
// b4–b7: attack rate.
|
||||
modulator_envelope.set_decay_rate(instrument[4] & 0xf);
|
||||
modulator_envelope.set_attack_rate(instrument[4] >> 4);
|
||||
carrier_envelope.set_decay_rate(instrument[5] & 0xf);
|
||||
carrier_envelope.set_attack_rate(instrument[5] >> 4);
|
||||
|
||||
// Bytes 6 (modulator) and 7 (carrier):
|
||||
//
|
||||
// b0–b3: release rate;
|
||||
// b4–b7: sustain level.
|
||||
modulator_envelope.set_release_rate(instrument[6] & 0xf);
|
||||
modulator_envelope.set_sustain_level(instrument[6] >> 4);
|
||||
carrier_envelope.set_release_rate(instrument[7] & 0xf);
|
||||
carrier_envelope.set_release_rate(instrument[7] >> 4);
|
||||
}
|
||||
|
||||
void OPLL::set_use_sustain(int channel) {
|
||||
const uint8_t *const instrument = instrument_definition(channels_[channel].instrument);
|
||||
envelope_generators_[channel + 0].set_sustain_level((instrument[1] & 0x20) || channels_[channel].use_sustain);
|
||||
envelope_generators_[channel + 9].set_sustain_level((instrument[0] & 0x20) || channels_[channel].use_sustain);
|
||||
}
|
||||
|
||||
// MARK: - Output generation.
|
||||
|
||||
void OPLL::set_sample_volume_range(std::int16_t range) {
|
||||
total_volume_ = range;
|
||||
}
|
||||
|
||||
void OPLL::get_samples(std::size_t number_of_samples, std::int16_t *target) {
|
||||
// TODO.
|
||||
}
|
102
Components/OPL2/OPLL.hpp
Normal file
102
Components/OPL2/OPLL.hpp
Normal file
@ -0,0 +1,102 @@
|
||||
//
|
||||
// OPLL.hpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 03/05/2020.
|
||||
// Copyright © 2020 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef OPLL_hpp
|
||||
#define OPLL_hpp
|
||||
|
||||
#include "Implementation/OPLBase.hpp"
|
||||
#include "Implementation/EnvelopeGenerator.hpp"
|
||||
#include "Implementation/KeyLevelScaler.hpp"
|
||||
#include "Implementation/PhaseGenerator.hpp"
|
||||
#include "Implementation/LowFrequencyOscillator.hpp"
|
||||
#include "Implementation/WaveformGenerator.hpp"
|
||||
|
||||
#include <atomic>
|
||||
|
||||
namespace Yamaha {
|
||||
namespace OPL {
|
||||
|
||||
class OPLL: public OPLBase<OPLL> {
|
||||
public:
|
||||
/// Creates a new OPLL or VRC7.
|
||||
OPLL(Concurrency::DeferringAsyncTaskQueue &task_queue, int audio_divider = 1, bool is_vrc7 = false);
|
||||
|
||||
/// As per ::SampleSource; provides audio output.
|
||||
void get_samples(std::size_t number_of_samples, std::int16_t *target);
|
||||
void set_sample_volume_range(std::int16_t range);
|
||||
|
||||
/// Reads from the OPL.
|
||||
uint8_t read(uint16_t address);
|
||||
|
||||
private:
|
||||
friend OPLBase<OPLL>;
|
||||
void write_register(uint8_t address, uint8_t value);
|
||||
|
||||
int audio_divider_ = 0;
|
||||
std::atomic<int> total_volume_;
|
||||
|
||||
static constexpr int period_precision = 9;
|
||||
static constexpr int envelope_precision = 9;
|
||||
|
||||
// Standard melodic phase and envelope generators.
|
||||
PhaseGenerator<period_precision> phase_generators_[18];
|
||||
EnvelopeGenerator<envelope_precision, period_precision> envelope_generators_[18];
|
||||
KeyLevelScaler<period_precision> key_level_scalers_[18];
|
||||
|
||||
// Dedicated rhythm envelope generators and attenuations.
|
||||
EnvelopeGenerator<envelope_precision, period_precision> rhythm_generators_[5];
|
||||
int rhythm_attenuations_[5];
|
||||
|
||||
// Channel specifications.
|
||||
struct Channel {
|
||||
int octave = 0;
|
||||
int period = 0;
|
||||
int instrument = 0;
|
||||
|
||||
int attenuation = 0;
|
||||
int modulator_attenuation = 0;
|
||||
|
||||
Waveform carrier_waveform = Waveform::Sine;
|
||||
Waveform modulator_waveform = Waveform::Sine;
|
||||
|
||||
int carrier_key_rate_scale_multiplier = 0;
|
||||
int modulator_key_rate_scale_multiplier = 0;
|
||||
|
||||
int modulator_feedback = 0;
|
||||
|
||||
bool use_sustain = false;
|
||||
} channels_[9];
|
||||
|
||||
// The low-frequency oscillator.
|
||||
LowFrequencyOscillator oscillator_;
|
||||
bool rhythm_mode_enabled_ = false;
|
||||
bool is_vrc7_ = false;
|
||||
|
||||
// Contains the current configuration of the custom instrument.
|
||||
uint8_t custom_instrument_[8];
|
||||
|
||||
// Helpers to push per-channel information.
|
||||
|
||||
/// Pushes the current octave and period to channel @c channel.
|
||||
void set_channel_period(int channel);
|
||||
|
||||
/// Installs the appropriate instrument on channel @c channel.
|
||||
void install_instrument(int channel);
|
||||
|
||||
/// Sets whether the sustain level is used for channel @c channel based on its current instrument
|
||||
/// and the user's selection.
|
||||
void set_use_sustain(int channel);
|
||||
|
||||
/// @returns The 8-byte definition of instrument @c instrument.
|
||||
const uint8_t *instrument_definition(int instrument);
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OPLL_hpp */
|
@ -12,7 +12,7 @@
|
||||
|
||||
#include "../../Components/9918/9918.hpp"
|
||||
#include "../../Components/SN76489/SN76489.hpp"
|
||||
#include "../../Components/OPL2/OPL2.hpp"
|
||||
#include "../../Components/OPL2/OPLL.hpp"
|
||||
|
||||
#include "../MachineTypes.hpp"
|
||||
#include "../../Configurable/Configurable.hpp"
|
||||
|
@ -222,6 +222,8 @@
|
||||
4B595FAE2086DFBA0083CAA8 /* AudioToggle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B595FAC2086DFBA0083CAA8 /* AudioToggle.cpp */; };
|
||||
4B5FADBA1DE3151600AEC565 /* FileHolder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B5FADB81DE3151600AEC565 /* FileHolder.cpp */; };
|
||||
4B5FADC01DE3BF2B00AEC565 /* Microdisc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B5FADBE1DE3BF2B00AEC565 /* Microdisc.cpp */; };
|
||||
4B619099245FBF7B0013F202 /* OPLL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B619097245FBF7B0013F202 /* OPLL.cpp */; };
|
||||
4B61909A245FBF7B0013F202 /* OPLL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B619097245FBF7B0013F202 /* OPLL.cpp */; };
|
||||
4B622AE5222E0AD5008B59F2 /* DisplayMetrics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B622AE3222E0AD5008B59F2 /* DisplayMetrics.cpp */; };
|
||||
4B643F3A1D77AD1900D431D6 /* CSStaticAnalyser.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B643F391D77AD1900D431D6 /* CSStaticAnalyser.mm */; };
|
||||
4B643F3F1D77B88000D431D6 /* DocumentController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B643F3E1D77B88000D431D6 /* DocumentController.swift */; };
|
||||
@ -793,8 +795,6 @@
|
||||
4BC1317B2346DF2B00E4FF3D /* MSA.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC131782346DF2B00E4FF3D /* MSA.cpp */; };
|
||||
4BC57CD92436A62900FBC404 /* State.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC57CD82436A62900FBC404 /* State.cpp */; };
|
||||
4BC57CDA2436A62900FBC404 /* State.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC57CD82436A62900FBC404 /* State.cpp */; };
|
||||
4BC57CE22436BFE000FBC404 /* OPL2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC57CE02436BFE000FBC404 /* OPL2.cpp */; };
|
||||
4BC57CE32436BFE000FBC404 /* OPL2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC57CE02436BFE000FBC404 /* OPL2.cpp */; };
|
||||
4BC5C3E022C994CD00795658 /* 68000MoveTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BC5C3DF22C994CC00795658 /* 68000MoveTests.mm */; };
|
||||
4BC5FC3020CDDDEF00410AA0 /* AppleIIOptions.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4BC5FC2E20CDDDEE00410AA0 /* AppleIIOptions.xib */; };
|
||||
4BC751B21D157E61006C31D9 /* 6522Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BC751B11D157E61006C31D9 /* 6522Tests.swift */; };
|
||||
@ -1152,6 +1152,9 @@
|
||||
4B619093245CD63E0013F202 /* EnvelopeGenerator.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = EnvelopeGenerator.hpp; sourceTree = "<group>"; };
|
||||
4B619094245E73B90013F202 /* KeyLevelScaler.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = KeyLevelScaler.hpp; sourceTree = "<group>"; };
|
||||
4B619095245FA04B0013F202 /* WaveformGenerator.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = WaveformGenerator.hpp; sourceTree = "<group>"; };
|
||||
4B619096245FBEF80013F202 /* OPLBase.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = OPLBase.hpp; path = Implementation/OPLBase.hpp; sourceTree = "<group>"; };
|
||||
4B619097245FBF7B0013F202 /* OPLL.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = OPLL.cpp; sourceTree = "<group>"; };
|
||||
4B619098245FBF7B0013F202 /* OPLL.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = OPLL.hpp; sourceTree = "<group>"; };
|
||||
4B622AE3222E0AD5008B59F2 /* DisplayMetrics.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = DisplayMetrics.cpp; path = ../../Outputs/DisplayMetrics.cpp; sourceTree = "<group>"; };
|
||||
4B622AE4222E0AD5008B59F2 /* DisplayMetrics.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = DisplayMetrics.hpp; path = ../../Outputs/DisplayMetrics.hpp; sourceTree = "<group>"; };
|
||||
4B643F381D77AD1900D431D6 /* CSStaticAnalyser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CSStaticAnalyser.h; path = StaticAnalyser/CSStaticAnalyser.h; sourceTree = "<group>"; };
|
||||
@ -3575,6 +3578,9 @@
|
||||
4BC0CB2F2447EC7C00A79DBB /* Implementation */,
|
||||
4BC57CE02436BFE000FBC404 /* OPL2.cpp */,
|
||||
4BC57CE12436BFE000FBC404 /* OPL2.hpp */,
|
||||
4B619096245FBEF80013F202 /* OPLBase.hpp */,
|
||||
4B619097245FBF7B0013F202 /* OPLL.cpp */,
|
||||
4B619098245FBF7B0013F202 /* OPLL.hpp */,
|
||||
);
|
||||
path = OPL2;
|
||||
sourceTree = "<group>";
|
||||
@ -4375,7 +4381,6 @@
|
||||
4B894521201967B4007DE474 /* StaticAnalyser.cpp in Sources */,
|
||||
4B8318B522D3E548006DB630 /* Macintosh.cpp in Sources */,
|
||||
4B7BA03123C2B19C00B98D9E /* Jasmin.cpp in Sources */,
|
||||
4BC57CE32436BFE000FBC404 /* OPL2.cpp in Sources */,
|
||||
4B7F188F2154825E00388727 /* MasterSystem.cpp in Sources */,
|
||||
4B055AA51FAE85EF0060FFFF /* Encoder.cpp in Sources */,
|
||||
4BD5D2692199148100DDF17D /* ScanTargetGLSLFragments.cpp in Sources */,
|
||||
@ -4530,6 +4535,7 @@
|
||||
4B894537201967B4007DE474 /* Z80.cpp in Sources */,
|
||||
4B055A9F1FAE85DA0060FFFF /* HFE.cpp in Sources */,
|
||||
4BD191F52191180E0042E144 /* ScanTarget.cpp in Sources */,
|
||||
4B61909A245FBF7B0013F202 /* OPLL.cpp in Sources */,
|
||||
4B055AEC1FAE9BA20060FFFF /* Z80Base.cpp in Sources */,
|
||||
4B0F94FF208C1A1600FE41D9 /* NIB.cpp in Sources */,
|
||||
4B0E04EB1FC9E78800F43484 /* CAS.cpp in Sources */,
|
||||
@ -4651,7 +4657,6 @@
|
||||
4BEA52631DF339D7007E74F2 /* SoundGenerator.cpp in Sources */,
|
||||
4BD67DD0209BF27B00AB2146 /* Encoder.cpp in Sources */,
|
||||
4BAE495920328897004BE78E /* ZX8081OptionsPanel.swift in Sources */,
|
||||
4BC57CE22436BFE000FBC404 /* OPL2.cpp in Sources */,
|
||||
4B89451A201967B4007DE474 /* ConfidenceSummary.cpp in Sources */,
|
||||
4BE0A3EE237BB170002AB46F /* ST.cpp in Sources */,
|
||||
4B54C0C51F8D91D90050900F /* Keyboard.cpp in Sources */,
|
||||
@ -4702,6 +4707,7 @@
|
||||
4BD0FBC3233706A200148981 /* CSApplication.m in Sources */,
|
||||
4BBC951E1F368D83008F4C34 /* i8272.cpp in Sources */,
|
||||
4B89449520194CB3007DE474 /* MachineForTarget.cpp in Sources */,
|
||||
4B619099245FBF7B0013F202 /* OPLL.cpp in Sources */,
|
||||
4B4A76301DB1A3FA007AAE2E /* AY38910.cpp in Sources */,
|
||||
4B7BA03423C58B1F00B98D9E /* STX.cpp in Sources */,
|
||||
4B6A4C991F58F09E00E3F787 /* 6502Base.cpp in Sources */,
|
||||
|
Loading…
x
Reference in New Issue
Block a user