mirror of
https://github.com/TomHarte/CLK.git
synced 2026-04-19 19:16:34 +00:00
Improve consts, indentation.
This commit is contained in:
@@ -15,7 +15,7 @@ using namespace Enterprise::Dave;
|
||||
Audio::Audio(Concurrency::AsyncTaskQueue<false> &audio_queue) :
|
||||
audio_queue_(audio_queue) {}
|
||||
|
||||
void Audio::write(uint16_t address, uint8_t value) {
|
||||
void Audio::write(uint16_t address, const uint8_t value) {
|
||||
address &= 0x1f;
|
||||
audio_queue_.enqueue([address, value, this] {
|
||||
switch(address) {
|
||||
@@ -62,13 +62,13 @@ void Audio::write(uint16_t address, uint8_t value) {
|
||||
});
|
||||
}
|
||||
|
||||
void Audio::set_sample_volume_range(int16_t range) {
|
||||
void Audio::set_sample_volume_range(const int16_t range) {
|
||||
audio_queue_.enqueue([range, this] {
|
||||
volume_ = range / (63*4);
|
||||
});
|
||||
}
|
||||
|
||||
void Audio::update_channel(int c) {
|
||||
void Audio::update_channel(const int c) {
|
||||
auto output = channels_[c].output & 1;
|
||||
channels_[c].output <<= 1;
|
||||
if(channels_[c].sync) {
|
||||
@@ -100,7 +100,7 @@ void Audio::update_channel(int c) {
|
||||
}
|
||||
|
||||
template <Outputs::Speaker::Action action>
|
||||
void Audio::apply_samples(std::size_t number_of_samples, Outputs::Speaker::StereoSample *target) {
|
||||
void Audio::apply_samples(const std::size_t number_of_samples, Outputs::Speaker::StereoSample *const target) {
|
||||
Outputs::Speaker::StereoSample output_level;
|
||||
|
||||
size_t c = 0;
|
||||
@@ -216,7 +216,7 @@ uint8_t TimedInterruptSource::get_new_interrupts() {
|
||||
return result;
|
||||
}
|
||||
|
||||
void TimedInterruptSource::write(uint16_t address, uint8_t value) {
|
||||
void TimedInterruptSource::write(uint16_t address, const uint8_t value) {
|
||||
address &= 0x1f;
|
||||
switch(address) {
|
||||
default: break;
|
||||
@@ -240,7 +240,7 @@ void TimedInterruptSource::write(uint16_t address, uint8_t value) {
|
||||
}
|
||||
}
|
||||
|
||||
void TimedInterruptSource::update_channel(int c, bool is_linked, int decrement) {
|
||||
void TimedInterruptSource::update_channel(const int c, const bool is_linked, const int decrement) {
|
||||
if(channels_[c].sync) {
|
||||
channels_[c].value = channels_[c].reload;
|
||||
} else {
|
||||
@@ -273,7 +273,7 @@ void TimedInterruptSource::update_channel(int c, bool is_linked, int decrement)
|
||||
}
|
||||
}
|
||||
|
||||
void TimedInterruptSource::run_for(Cycles duration) {
|
||||
void TimedInterruptSource::run_for(const Cycles duration) {
|
||||
// Determine total number of ticks.
|
||||
run_length_ += duration;
|
||||
const Cycles cycles = run_length_.divide(global_divider_);
|
||||
|
||||
+120
-120
@@ -27,93 +27,93 @@ enum class Interrupt: uint8_t {
|
||||
Models the audio-production subset of Dave's behaviour.
|
||||
*/
|
||||
class Audio: public Outputs::Speaker::BufferSource<Audio, true> {
|
||||
public:
|
||||
Audio(Concurrency::AsyncTaskQueue<false> &audio_queue);
|
||||
public:
|
||||
Audio(Concurrency::AsyncTaskQueue<false> &audio_queue);
|
||||
|
||||
/// Modifies an register in the audio range; only the low 4 bits are
|
||||
/// used for register decoding so it's assumed that the caller has
|
||||
/// already identified this write as being to an audio register.
|
||||
void write(uint16_t address, uint8_t value);
|
||||
/// Modifies an register in the audio range; only the low 4 bits are
|
||||
/// used for register decoding so it's assumed that the caller has
|
||||
/// already identified this write as being to an audio register.
|
||||
void write(uint16_t address, uint8_t value);
|
||||
|
||||
// MARK: - SampleSource.
|
||||
void set_sample_volume_range(int16_t range);
|
||||
template <Outputs::Speaker::Action action>
|
||||
void apply_samples(std::size_t number_of_samples, Outputs::Speaker::StereoSample *target);
|
||||
// MARK: - SampleSource.
|
||||
void set_sample_volume_range(int16_t range);
|
||||
template <Outputs::Speaker::Action action>
|
||||
void apply_samples(std::size_t number_of_samples, Outputs::Speaker::StereoSample *target);
|
||||
|
||||
private:
|
||||
Concurrency::AsyncTaskQueue<false> &audio_queue_;
|
||||
private:
|
||||
Concurrency::AsyncTaskQueue<false> &audio_queue_;
|
||||
|
||||
// Global divider (i.e. 8MHz/12Mhz switch).
|
||||
uint8_t global_divider_;
|
||||
uint8_t global_divider_reload_ = 2;
|
||||
// Global divider (i.e. 8MHz/12Mhz switch).
|
||||
uint8_t global_divider_;
|
||||
uint8_t global_divider_reload_ = 2;
|
||||
|
||||
// Tone channels.
|
||||
struct Channel {
|
||||
// User-set values.
|
||||
uint16_t reload = 0;
|
||||
bool high_pass = false;
|
||||
bool ring_modulate = false;
|
||||
enum class Distortion {
|
||||
None = 0,
|
||||
FourBit = 1,
|
||||
FiveBit = 2,
|
||||
SevenBit = 3,
|
||||
} distortion = Distortion::None;
|
||||
uint8_t amplitude[2]{};
|
||||
bool sync = false;
|
||||
// Tone channels.
|
||||
struct Channel {
|
||||
// User-set values.
|
||||
uint16_t reload = 0;
|
||||
bool high_pass = false;
|
||||
bool ring_modulate = false;
|
||||
enum class Distortion {
|
||||
None = 0,
|
||||
FourBit = 1,
|
||||
FiveBit = 2,
|
||||
SevenBit = 3,
|
||||
} distortion = Distortion::None;
|
||||
uint8_t amplitude[2]{};
|
||||
bool sync = false;
|
||||
|
||||
// Current state.
|
||||
uint16_t count = 0;
|
||||
int output = 0;
|
||||
} channels_[3];
|
||||
void update_channel(int);
|
||||
// Current state.
|
||||
uint16_t count = 0;
|
||||
int output = 0;
|
||||
} channels_[3];
|
||||
void update_channel(int);
|
||||
|
||||
// Noise channel.
|
||||
struct Noise {
|
||||
// User-set values.
|
||||
uint8_t amplitude[2]{};
|
||||
enum class Frequency {
|
||||
DivideByFour,
|
||||
ToneChannel0,
|
||||
ToneChannel1,
|
||||
ToneChannel2,
|
||||
} frequency = Frequency::DivideByFour;
|
||||
enum class Polynomial {
|
||||
SeventeenBit,
|
||||
FifteenBit,
|
||||
ElevenBit,
|
||||
NineBit
|
||||
} polynomial = Polynomial::SeventeenBit;
|
||||
bool swap_polynomial = false;
|
||||
bool low_pass = false;
|
||||
bool high_pass = false;
|
||||
bool ring_modulate = false;
|
||||
// Noise channel.
|
||||
struct Noise {
|
||||
// User-set values.
|
||||
uint8_t amplitude[2]{};
|
||||
enum class Frequency {
|
||||
DivideByFour,
|
||||
ToneChannel0,
|
||||
ToneChannel1,
|
||||
ToneChannel2,
|
||||
} frequency = Frequency::DivideByFour;
|
||||
enum class Polynomial {
|
||||
SeventeenBit,
|
||||
FifteenBit,
|
||||
ElevenBit,
|
||||
NineBit
|
||||
} polynomial = Polynomial::SeventeenBit;
|
||||
bool swap_polynomial = false;
|
||||
bool low_pass = false;
|
||||
bool high_pass = false;
|
||||
bool ring_modulate = false;
|
||||
|
||||
// Current state.
|
||||
int count = 0;
|
||||
int output = 0;
|
||||
bool final_output = false;
|
||||
} noise_;
|
||||
void update_noise();
|
||||
// Current state.
|
||||
int count = 0;
|
||||
int output = 0;
|
||||
bool final_output = false;
|
||||
} noise_;
|
||||
void update_noise();
|
||||
|
||||
bool use_direct_output_[2]{};
|
||||
bool use_direct_output_[2]{};
|
||||
|
||||
// Global volume, per SampleSource obligations.
|
||||
int16_t volume_ = 0;
|
||||
// Global volume, per SampleSource obligations.
|
||||
int16_t volume_ = 0;
|
||||
|
||||
// Polynomials that are always running.
|
||||
Numeric::LFSRv<0xc> poly4_;
|
||||
Numeric::LFSRv<0x14> poly5_;
|
||||
Numeric::LFSRv<0x60> poly7_;
|
||||
// Polynomials that are always running.
|
||||
Numeric::LFSRv<0xc> poly4_;
|
||||
Numeric::LFSRv<0x14> poly5_;
|
||||
Numeric::LFSRv<0x60> poly7_;
|
||||
|
||||
// The selectable, noise-related polynomial.
|
||||
Numeric::LFSRv<0x110> poly9_;
|
||||
Numeric::LFSRv<0x500> poly11_;
|
||||
Numeric::LFSRv<0x6000> poly15_;
|
||||
Numeric::LFSRv<0x12000> poly17_;
|
||||
// The selectable, noise-related polynomial.
|
||||
Numeric::LFSRv<0x110> poly9_;
|
||||
Numeric::LFSRv<0x500> poly11_;
|
||||
Numeric::LFSRv<0x6000> poly15_;
|
||||
Numeric::LFSRv<0x12000> poly17_;
|
||||
|
||||
// Current state of the active polynomials.
|
||||
uint8_t poly_state_[4];
|
||||
// Current state of the active polynomials.
|
||||
uint8_t poly_state_[4];
|
||||
};
|
||||
|
||||
/*!
|
||||
@@ -122,62 +122,62 @@ class Audio: public Outputs::Speaker::BufferSource<Audio, true> {
|
||||
1 Hz interrupt.
|
||||
*/
|
||||
class TimedInterruptSource {
|
||||
public:
|
||||
/// Modifies an register in the audio range; only the low 4 bits are
|
||||
/// used for register decoding so it's assumed that the caller has
|
||||
/// already identified this write as being to an audio register.
|
||||
void write(uint16_t address, uint8_t value);
|
||||
public:
|
||||
/// Modifies an register in the audio range; only the low 4 bits are
|
||||
/// used for register decoding so it's assumed that the caller has
|
||||
/// already identified this write as being to an audio register.
|
||||
void write(uint16_t address, uint8_t value);
|
||||
|
||||
/// Returns a bitmask of interrupts that have become active since
|
||||
/// the last time this method was called; flags are as defined in
|
||||
/// @c Enterprise::Dave::Interrupt
|
||||
uint8_t get_new_interrupts();
|
||||
/// Returns a bitmask of interrupts that have become active since
|
||||
/// the last time this method was called; flags are as defined in
|
||||
/// @c Enterprise::Dave::Interrupt
|
||||
uint8_t get_new_interrupts();
|
||||
|
||||
/// Returns the current high or low states of the inputs that trigger
|
||||
/// the interrupts modelled here, as a bit mask compatible with that
|
||||
/// exposed by Dave as the register at 0xb4.
|
||||
uint8_t get_divider_state();
|
||||
/// Returns the current high or low states of the inputs that trigger
|
||||
/// the interrupts modelled here, as a bit mask compatible with that
|
||||
/// exposed by Dave as the register at 0xb4.
|
||||
uint8_t get_divider_state();
|
||||
|
||||
/// Advances the interrupt source.
|
||||
void run_for(Cycles);
|
||||
/// Advances the interrupt source.
|
||||
void run_for(Cycles);
|
||||
|
||||
/// @returns The amount of time from now until the earliest that
|
||||
/// @c get_new_interrupts() _might_ have new interrupts to report.
|
||||
Cycles next_sequence_point() const;
|
||||
/// @returns The amount of time from now until the earliest that
|
||||
/// @c get_new_interrupts() _might_ have new interrupts to report.
|
||||
Cycles next_sequence_point() const;
|
||||
|
||||
private:
|
||||
static constexpr Cycles clock_rate{250000};
|
||||
static constexpr Cycles half_clock_rate{125000};
|
||||
private:
|
||||
static constexpr Cycles clock_rate{250000};
|
||||
static constexpr Cycles half_clock_rate{125000};
|
||||
|
||||
// Global divider (i.e. 8MHz/12Mhz switch).
|
||||
Cycles global_divider_ = Cycles(2);
|
||||
Cycles run_length_;
|
||||
// Global divider (i.e. 8MHz/12Mhz switch).
|
||||
Cycles global_divider_ = Cycles(2);
|
||||
Cycles run_length_;
|
||||
|
||||
// Interrupts that have fired since get_new_interrupts()
|
||||
// was last called.
|
||||
uint8_t interrupts_ = 0;
|
||||
// Interrupts that have fired since get_new_interrupts()
|
||||
// was last called.
|
||||
uint8_t interrupts_ = 0;
|
||||
|
||||
// A counter for the 1Hz interrupt.
|
||||
int two_second_counter_ = 0;
|
||||
// A counter for the 1Hz interrupt.
|
||||
int two_second_counter_ = 0;
|
||||
|
||||
// A counter specific to the 1kHz and 50Hz timers, if in use.
|
||||
enum class InterruptRate {
|
||||
OnekHz,
|
||||
FiftyHz,
|
||||
ToneGenerator0,
|
||||
ToneGenerator1,
|
||||
} rate_ = InterruptRate::OnekHz;
|
||||
bool programmable_level_ = false;
|
||||
// A counter specific to the 1kHz and 50Hz timers, if in use.
|
||||
enum class InterruptRate {
|
||||
OnekHz,
|
||||
FiftyHz,
|
||||
ToneGenerator0,
|
||||
ToneGenerator1,
|
||||
} rate_ = InterruptRate::OnekHz;
|
||||
bool programmable_level_ = false;
|
||||
|
||||
// A local duplicate of the counting state of the first two audio
|
||||
// channels, maintained in case either of those is used as an
|
||||
// interrupt source.
|
||||
struct Channel {
|
||||
int value = 100, reload = 100;
|
||||
bool sync = false;
|
||||
bool level = false;
|
||||
} channels_[2];
|
||||
void update_channel(int c, bool is_linked, int decrement);
|
||||
// A local duplicate of the counting state of the first two audio
|
||||
// channels, maintained in case either of those is used as an
|
||||
// interrupt source.
|
||||
struct Channel {
|
||||
int value = 100, reload = 100;
|
||||
bool sync = false;
|
||||
bool level = false;
|
||||
} channels_[2];
|
||||
void update_channel(int c, bool is_linked, int decrement);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ EXDos::EXDos() : WD1770(P1770) {
|
||||
set_control_register(0x00);
|
||||
}
|
||||
|
||||
void EXDos::set_disk(std::shared_ptr<Storage::Disk::Disk> disk, size_t drive) {
|
||||
void EXDos::set_disk(std::shared_ptr<Storage::Disk::Disk> disk, const size_t drive) {
|
||||
get_drive(drive).set_disk(disk);
|
||||
disk_did_change_ = true;
|
||||
}
|
||||
@@ -38,7 +38,7 @@ void EXDos::set_disk(std::shared_ptr<Storage::Disk::Disk> disk, size_t drive) {
|
||||
// b1 interrupt request from WD1770
|
||||
// b0 drive ready
|
||||
|
||||
void EXDos::set_control_register(uint8_t control) {
|
||||
void EXDos::set_control_register(const uint8_t control) {
|
||||
if(control & 0x40) disk_did_change_ = false;
|
||||
set_is_double_density(!(control & 0x20));
|
||||
|
||||
@@ -67,11 +67,11 @@ uint8_t EXDos::get_control_register() {
|
||||
return status;
|
||||
}
|
||||
|
||||
void EXDos::set_motor_on(bool on) {
|
||||
void EXDos::set_motor_on(const bool on) {
|
||||
get_drive().set_motor_on(on);
|
||||
}
|
||||
|
||||
void EXDos::set_activity_observer(Activity::Observer *observer) {
|
||||
void EXDos::set_activity_observer(Activity::Observer *const observer) {
|
||||
for_all_drives([observer] (Storage::Disk::Drive &drive, size_t index) {
|
||||
drive.set_activity_observer(observer, "Drive " + std::to_string(index+1), true);
|
||||
});
|
||||
|
||||
@@ -14,20 +14,19 @@
|
||||
namespace Enterprise {
|
||||
|
||||
class EXDos final : public WD::WD1770 {
|
||||
public:
|
||||
EXDos();
|
||||
public:
|
||||
EXDos();
|
||||
|
||||
void set_disk(std::shared_ptr<Storage::Disk::Disk> disk, size_t drive);
|
||||
void set_disk(std::shared_ptr<Storage::Disk::Disk>, const size_t drive);
|
||||
|
||||
void set_control_register(uint8_t control);
|
||||
uint8_t get_control_register();
|
||||
void set_control_register(uint8_t);
|
||||
uint8_t get_control_register();
|
||||
|
||||
void set_activity_observer(Activity::Observer *observer);
|
||||
void set_activity_observer(Activity::Observer *);
|
||||
|
||||
private:
|
||||
bool disk_did_change_ = false;
|
||||
|
||||
void set_motor_on(bool on) override;
|
||||
private:
|
||||
bool disk_did_change_ = false;
|
||||
void set_motor_on(bool) override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -261,7 +261,7 @@ public:
|
||||
}
|
||||
|
||||
// MARK: - Z80::BusHandler.
|
||||
forceinline void advance_nick(HalfCycles duration) {
|
||||
forceinline void advance_nick(const HalfCycles duration) {
|
||||
if(nick_ += duration) {
|
||||
const auto nick = nick_.last_valid();
|
||||
const bool nick_interrupt_line = nick->get_interrupt_line();
|
||||
@@ -558,7 +558,7 @@ public:
|
||||
return penalty;
|
||||
}
|
||||
|
||||
void flush_output(int outputs) final {
|
||||
void flush_output(const int outputs) final {
|
||||
if(outputs & Output::Video) {
|
||||
nick_.flush();
|
||||
}
|
||||
@@ -613,7 +613,7 @@ if(offset >= location && offset < location + source.size() / 0x4000) { \
|
||||
page<slot>(nullptr, nullptr);
|
||||
}
|
||||
|
||||
template <size_t slot> void page(const uint8_t *read, uint8_t *write) {
|
||||
template <size_t slot> void page(const uint8_t *const read, uint8_t *const write) {
|
||||
read_pointers_[slot] = read ? read - (slot * 0x4000) : nullptr;
|
||||
write_pointers_[slot] = write ? write - (slot * 0x4000) : nullptr;
|
||||
}
|
||||
@@ -629,7 +629,7 @@ if(offset >= location && offset < location + source.size() / 0x4000) { \
|
||||
bool is_video_[4]{};
|
||||
|
||||
// MARK: - ScanProducer
|
||||
void set_scan_target(Outputs::Display::ScanTarget *scan_target) override {
|
||||
void set_scan_target(Outputs::Display::ScanTarget *const scan_target) override {
|
||||
nick_.last_valid()->set_scan_target(scan_target);
|
||||
}
|
||||
|
||||
@@ -637,7 +637,7 @@ if(offset >= location && offset < location + source.size() / 0x4000) { \
|
||||
return nick_.last_valid()->get_scaled_scan_status();
|
||||
}
|
||||
|
||||
void set_display_type(Outputs::Display::DisplayType display_type) final {
|
||||
void set_display_type(const Outputs::Display::DisplayType display_type) final {
|
||||
nick_.last_valid()->set_display_type(display_type);
|
||||
}
|
||||
|
||||
@@ -664,7 +664,7 @@ if(offset >= location && offset < location + source.size() / 0x4000) { \
|
||||
|
||||
uint8_t active_key_line_ = 0;
|
||||
std::array<uint8_t, 10> key_lines_;
|
||||
void set_key_state(uint16_t key, bool is_pressed) final {
|
||||
void set_key_state(const uint16_t key, const bool is_pressed) final {
|
||||
if(is_pressed) {
|
||||
key_lines_[key >> 8] &= ~uint8_t(key);
|
||||
} else {
|
||||
@@ -689,7 +689,7 @@ if(offset >= location && offset < location + source.size() / 0x4000) { \
|
||||
}
|
||||
}
|
||||
|
||||
bool can_type(char c) const final {
|
||||
bool can_type(const char c) const final {
|
||||
return Utility::TypeRecipient<CharacterMapper>::can_type(c);
|
||||
}
|
||||
|
||||
@@ -710,11 +710,11 @@ if(offset >= location && offset < location + source.size() / 0x4000) { \
|
||||
// MARK: - Interrupts
|
||||
|
||||
uint8_t interrupt_mask_ = 0x00, interrupt_state_ = 0x00;
|
||||
void set_interrupts(uint8_t mask, HalfCycles offset = HalfCycles(0)) {
|
||||
void set_interrupts(const uint8_t mask, const HalfCycles offset = HalfCycles(0)) {
|
||||
interrupt_state_ |= uint8_t(mask);
|
||||
update_interrupts(offset);
|
||||
}
|
||||
void update_interrupts(HalfCycles offset = HalfCycles(0)) {
|
||||
void update_interrupts(const HalfCycles offset = HalfCycles(0)) {
|
||||
z80_.set_interrupt_line((interrupt_state_ >> 1) & interrupt_mask_, offset);
|
||||
}
|
||||
|
||||
@@ -743,7 +743,7 @@ if(offset >= location && offset < location + source.size() / 0x4000) { \
|
||||
EXDos exdos_;
|
||||
|
||||
// MARK: - Activity Source
|
||||
void set_activity_observer([[maybe_unused]] Activity::Observer *observer) final {
|
||||
void set_activity_observer([[maybe_unused]] Activity::Observer *const observer) final {
|
||||
if constexpr (has_disk_controller) {
|
||||
exdos_.set_activity_observer(observer);
|
||||
}
|
||||
|
||||
@@ -32,7 +32,9 @@ struct Machine {
|
||||
friend Configurable::DisplayOption<Options>;
|
||||
public:
|
||||
Options(Configurable::OptionsType type) :
|
||||
Configurable::DisplayOption<Options>(type == Configurable::OptionsType::UserFriendly ? Configurable::Display::RGB : Configurable::Display::CompositeColour) {}
|
||||
Configurable::DisplayOption<Options>(
|
||||
type == Configurable::OptionsType::UserFriendly ?
|
||||
Configurable::Display::RGB : Configurable::Display::CompositeColour) {}
|
||||
|
||||
private:
|
||||
Options() : Options(Configurable::OptionsType::UserFriendly) {}
|
||||
@@ -40,7 +42,9 @@ struct Machine {
|
||||
friend Reflection::StructImpl<Options>;
|
||||
void declare_fields() {
|
||||
declare_display_option();
|
||||
limit_enum(&output, Configurable::Display::RGB, Configurable::Display::CompositeColour, Configurable::Display::CompositeMonochrome, -1);
|
||||
limit_enum(&output,
|
||||
Configurable::Display::RGB, Configurable::Display::CompositeColour,
|
||||
Configurable::Display::CompositeMonochrome, -1);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
using namespace Enterprise;
|
||||
|
||||
uint16_t KeyboardMapper::mapped_key_for_key(Inputs::Keyboard::Key key) const {
|
||||
uint16_t KeyboardMapper::mapped_key_for_key(const Inputs::Keyboard::Key key) const {
|
||||
#define BIND(source, dest) case Inputs::Keyboard::Key::source: return uint16_t(Key::dest)
|
||||
switch(key) {
|
||||
default: break;
|
||||
@@ -73,7 +73,7 @@ uint16_t KeyboardMapper::mapped_key_for_key(Inputs::Keyboard::Key key) const {
|
||||
return MachineTypes::MappedKeyboardMachine::KeyNotMapped;
|
||||
}
|
||||
|
||||
const uint16_t *CharacterMapper::sequence_for_character(char character) const {
|
||||
const uint16_t *CharacterMapper::sequence_for_character(const char character) const {
|
||||
#define KEYS(x) {uint16_t(x), MachineTypes::MappedKeyboardMachine::KeyEndSequence}
|
||||
#define SHIFT(x) {uint16_t(Key::LeftShift), uint16_t(x), MachineTypes::MappedKeyboardMachine::KeyEndSequence}
|
||||
#define _ {MachineTypes::MappedKeyboardMachine::KeyNotMapped}
|
||||
|
||||
@@ -13,8 +13,6 @@
|
||||
|
||||
namespace Enterprise {
|
||||
|
||||
#define KeyCode(line, mask) (line << 8) | mask
|
||||
|
||||
enum class Key: uint16_t {
|
||||
N = 0x0000 | 0x01, Backslash = 0x0000 | 0x02, B = 0x0000 | 0x04, C = 0x0000 | 0x08,
|
||||
V = 0x0000 | 0x10, X = 0x0000 | 0x20, Z = 0x0000 | 0x40, LeftShift = 0x0000 | 0x80,
|
||||
@@ -50,14 +48,12 @@ enum class Key: uint16_t {
|
||||
OpenSquareBracket = 0x0900 | 0x20
|
||||
};
|
||||
|
||||
#undef KeyCode
|
||||
|
||||
struct KeyboardMapper: public MachineTypes::MappedKeyboardMachine::KeyboardMapper {
|
||||
uint16_t mapped_key_for_key(Inputs::Keyboard::Key key) const final;
|
||||
uint16_t mapped_key_for_key(Inputs::Keyboard::Key) const final;
|
||||
};
|
||||
|
||||
struct CharacterMapper: public ::Utility::CharacterMapper {
|
||||
const uint16_t *sequence_for_character(char character) const override;
|
||||
const uint16_t *sequence_for_character(char) const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace {
|
||||
|
||||
uint16_t mapped_colour(uint8_t source) {
|
||||
uint16_t mapped_colour(const uint8_t source) {
|
||||
// On the Enterprise, red and green are 3-bit quantities; blue is a 2-bit quantity.
|
||||
int red = ((source&0x01) << 2) | ((source&0x08) >> 2) | ((source&0x40) >> 6);
|
||||
int green = ((source&0x02) << 1) | ((source&0x10) >> 3) | ((source&0x80) >> 7);
|
||||
@@ -46,7 +46,7 @@ uint16_t mapped_colour(uint8_t source) {
|
||||
|
||||
using namespace Enterprise;
|
||||
|
||||
Nick::Nick(const uint8_t *ram) :
|
||||
Nick::Nick(const uint8_t *const ram) :
|
||||
crt_(57*16, 16, Outputs::Display::Type::PAL50, Outputs::Display::InputDataType::Red4Green4Blue4),
|
||||
ram_(ram) {
|
||||
|
||||
@@ -57,7 +57,7 @@ Nick::Nick(const uint8_t *ram) :
|
||||
crt_.set_visible_area(Outputs::Display::Rect(0.05f, 0.05f, 0.9f, 0.9f));
|
||||
}
|
||||
|
||||
void Nick::write(uint16_t address, uint8_t value) {
|
||||
void Nick::write(const uint16_t address, const uint8_t value) {
|
||||
switch(address & 3) {
|
||||
case 0:
|
||||
// Ignored: everything to do with external colour.
|
||||
@@ -95,7 +95,7 @@ uint8_t Nick::read() {
|
||||
return last_read_;
|
||||
}
|
||||
|
||||
Cycles Nick::get_time_until_z80_slot(Cycles after_period) const {
|
||||
Cycles Nick::get_time_until_z80_slot(const Cycles after_period) const {
|
||||
// Place Z80 accesses in the first six cycles in each sixteen-cycle window.
|
||||
// That models video accesses as being the final ten. Which has the net effect
|
||||
// of responding to the line parameter table interrupt flag as soon as it's
|
||||
@@ -111,8 +111,8 @@ Cycles Nick::get_time_until_z80_slot(Cycles after_period) const {
|
||||
}
|
||||
}
|
||||
|
||||
void Nick::run_for(Cycles duration) {
|
||||
constexpr int line_length = 912;
|
||||
void Nick::run_for(const Cycles duration) {
|
||||
static constexpr int line_length = 912;
|
||||
|
||||
#define add_window(x) \
|
||||
line_data_pointer_[0] += is_sync_or_pixels_ * line_data_per_column_increments_[0] * (x); \
|
||||
@@ -437,7 +437,7 @@ void Nick::run_for(Cycles duration) {
|
||||
|
||||
}
|
||||
|
||||
void Nick::set_output_type(OutputType type, bool force_flush) {
|
||||
void Nick::set_output_type(const OutputType type, const bool force_flush) {
|
||||
if(type == output_type_ && !force_flush) {
|
||||
return;
|
||||
}
|
||||
@@ -480,7 +480,7 @@ Cycles Nick::next_sequence_point() const {
|
||||
|
||||
// MARK: - CRT passthroughs.
|
||||
|
||||
void Nick::set_scan_target(Outputs::Display::ScanTarget *scan_target) {
|
||||
void Nick::set_scan_target(Outputs::Display::ScanTarget *const scan_target) {
|
||||
crt_.set_scan_target(scan_target);
|
||||
}
|
||||
|
||||
@@ -488,7 +488,7 @@ Outputs::Display::ScanStatus Nick::get_scaled_scan_status() const {
|
||||
return crt_.get_scaled_scan_status();
|
||||
}
|
||||
|
||||
void Nick::set_display_type(Outputs::Display::DisplayType display_type) {
|
||||
void Nick::set_display_type(const Outputs::Display::DisplayType display_type) {
|
||||
first_pixel_window_ = display_type == Outputs::Display::DisplayType::RGB ? 8 : 10;
|
||||
crt_.set_display_type(display_type);
|
||||
}
|
||||
@@ -526,7 +526,7 @@ Outputs::Display::DisplayType Nick::get_display_type() const {
|
||||
target[0] = mapped_colour(x); \
|
||||
++target
|
||||
|
||||
template <int bpp, bool is_lpixel> void Nick::output_pixel(uint16_t *target, int columns) const {
|
||||
template <int bpp, bool is_lpixel> void Nick::output_pixel(uint16_t *target, const int columns) const {
|
||||
static_assert(bpp == 1 || bpp == 2 || bpp == 4 || bpp == 8);
|
||||
|
||||
int index = 0;
|
||||
@@ -576,7 +576,7 @@ template <int bpp, bool is_lpixel> void Nick::output_pixel(uint16_t *target, int
|
||||
}
|
||||
}
|
||||
|
||||
template <int bpp, int index_bits> void Nick::output_character(uint16_t *target, int columns) const {
|
||||
template <int bpp, int index_bits> void Nick::output_character(uint16_t *target, const int columns) const {
|
||||
static_assert(bpp == 1 || bpp == 2 || bpp == 4 || bpp == 8);
|
||||
|
||||
for(int c = 0; c < columns; c++) {
|
||||
@@ -605,7 +605,7 @@ template <int bpp, int index_bits> void Nick::output_character(uint16_t *target,
|
||||
}
|
||||
}
|
||||
|
||||
template <int bpp> void Nick::output_attributed(uint16_t *target, int columns) const {
|
||||
template <int bpp> void Nick::output_attributed(uint16_t *target, const int columns) const {
|
||||
static_assert(bpp == 1 || bpp == 2 || bpp == 4 || bpp == 8);
|
||||
|
||||
for(int c = 0; c < columns; c++) {
|
||||
|
||||
@@ -15,108 +15,108 @@
|
||||
namespace Enterprise {
|
||||
|
||||
class Nick {
|
||||
public:
|
||||
Nick(const uint8_t *ram);
|
||||
public:
|
||||
Nick(const uint8_t *ram);
|
||||
|
||||
/// Writes to a Nick register; only the low two bits are decoded.
|
||||
void write(uint16_t address, uint8_t value);
|
||||
/// Writes to a Nick register; only the low two bits are decoded.
|
||||
void write(uint16_t address, uint8_t value);
|
||||
|
||||
/// Reads from the Nick range. Nobody seems to be completely clear what
|
||||
/// this should return; I've set it up to return the last fetched video or mode
|
||||
/// line byte during periods when those things are being fetched, 0xff at all
|
||||
/// other times. Including during refresh, since I don't know what addresses
|
||||
/// are generated then.
|
||||
///
|
||||
/// This likely isn't accurate, but is the most accurate guess I could make.
|
||||
uint8_t read();
|
||||
/// Reads from the Nick range. Nobody seems to be completely clear what
|
||||
/// this should return; I've set it up to return the last fetched video or mode
|
||||
/// line byte during periods when those things are being fetched, 0xff at all
|
||||
/// other times. Including during refresh, since I don't know what addresses
|
||||
/// are generated then.
|
||||
///
|
||||
/// This likely isn't accurate, but is the most accurate guess I could make.
|
||||
uint8_t read();
|
||||
|
||||
void run_for(Cycles);
|
||||
Cycles get_time_until_z80_slot(Cycles after_period) const;
|
||||
void run_for(Cycles);
|
||||
Cycles get_time_until_z80_slot(Cycles after_period) const;
|
||||
|
||||
void set_scan_target(Outputs::Display::ScanTarget *scan_target);
|
||||
Outputs::Display::ScanStatus get_scaled_scan_status() const;
|
||||
void set_scan_target(Outputs::Display::ScanTarget *);
|
||||
Outputs::Display::ScanStatus get_scaled_scan_status() const;
|
||||
|
||||
/// @returns The amount of time until the next potential change in interrupt output.
|
||||
Cycles next_sequence_point() const;
|
||||
/// @returns The amount of time until the next potential change in interrupt output.
|
||||
Cycles next_sequence_point() const;
|
||||
|
||||
/*!
|
||||
@returns The current state of the interrupt line — @c true for active;
|
||||
@c false for inactive.
|
||||
*/
|
||||
inline bool get_interrupt_line() const {
|
||||
return interrupt_line_;
|
||||
}
|
||||
/*!
|
||||
@returns The current state of the interrupt line — @c true for active;
|
||||
@c false for inactive.
|
||||
*/
|
||||
inline bool get_interrupt_line() const {
|
||||
return interrupt_line_;
|
||||
}
|
||||
|
||||
/// Sets the type of output.
|
||||
void set_display_type(Outputs::Display::DisplayType);
|
||||
/// Sets the type of output.
|
||||
void set_display_type(Outputs::Display::DisplayType);
|
||||
|
||||
/// Gets the type of output.
|
||||
Outputs::Display::DisplayType get_display_type() const;
|
||||
/// Gets the type of output.
|
||||
Outputs::Display::DisplayType get_display_type() const;
|
||||
|
||||
private:
|
||||
Outputs::CRT::CRT crt_;
|
||||
const uint8_t *const ram_;
|
||||
private:
|
||||
Outputs::CRT::CRT crt_;
|
||||
const uint8_t *const ram_;
|
||||
|
||||
// CPU-provided state.
|
||||
uint8_t line_parameter_control_ = 0xc0;
|
||||
uint16_t line_parameter_base_ = 0x0000;
|
||||
uint16_t border_colour_ = 0;
|
||||
// CPU-provided state.
|
||||
uint8_t line_parameter_control_ = 0xc0;
|
||||
uint16_t line_parameter_base_ = 0x0000;
|
||||
uint16_t border_colour_ = 0;
|
||||
|
||||
// Ephemerals, related to current video position.
|
||||
int horizontal_counter_ = 0;
|
||||
uint16_t line_parameter_pointer_ = 0x0000;
|
||||
bool should_reload_line_parameters_ = true;
|
||||
uint16_t line_data_pointer_[2];
|
||||
uint16_t start_line_data_pointer_[2];
|
||||
mutable uint8_t last_read_ = 0xff;
|
||||
// Ephemerals, related to current video position.
|
||||
int horizontal_counter_ = 0;
|
||||
uint16_t line_parameter_pointer_ = 0x0000;
|
||||
bool should_reload_line_parameters_ = true;
|
||||
uint16_t line_data_pointer_[2];
|
||||
uint16_t start_line_data_pointer_[2];
|
||||
mutable uint8_t last_read_ = 0xff;
|
||||
|
||||
// Current mode line parameters.
|
||||
uint8_t lines_remaining_ = 0x00;
|
||||
uint8_t two_colour_mask_ = 0xff;
|
||||
int left_margin_ = 0, right_margin_ = 0;
|
||||
const uint16_t *alt_ind_palettes[4] = {palette_, palette_, palette_, palette_};
|
||||
enum class Mode {
|
||||
Vsync,
|
||||
Pixel,
|
||||
Attr,
|
||||
CH256,
|
||||
CH128,
|
||||
CH64,
|
||||
Unused,
|
||||
LPixel,
|
||||
} mode_ = Mode::Vsync;
|
||||
bool is_sync_or_pixels_ = false;
|
||||
int bpp_ = 0;
|
||||
int column_size_ = 0;
|
||||
bool interrupt_line_ = true;
|
||||
int line_data_per_column_increments_[2] = {0, 0};
|
||||
bool vres_ = false;
|
||||
bool reload_line_parameter_pointer_ = false;
|
||||
// Current mode line parameters.
|
||||
uint8_t lines_remaining_ = 0x00;
|
||||
uint8_t two_colour_mask_ = 0xff;
|
||||
int left_margin_ = 0, right_margin_ = 0;
|
||||
const uint16_t *alt_ind_palettes[4] = {palette_, palette_, palette_, palette_};
|
||||
enum class Mode {
|
||||
Vsync,
|
||||
Pixel,
|
||||
Attr,
|
||||
CH256,
|
||||
CH128,
|
||||
CH64,
|
||||
Unused,
|
||||
LPixel,
|
||||
} mode_ = Mode::Vsync;
|
||||
bool is_sync_or_pixels_ = false;
|
||||
int bpp_ = 0;
|
||||
int column_size_ = 0;
|
||||
bool interrupt_line_ = true;
|
||||
int line_data_per_column_increments_[2] = {0, 0};
|
||||
bool vres_ = false;
|
||||
bool reload_line_parameter_pointer_ = false;
|
||||
|
||||
// The destination for new pixels.
|
||||
static constexpr int allocation_size = 336;
|
||||
static_assert((allocation_size % 16) == 0, "Allocation size must be a multiple of 16");
|
||||
uint16_t *pixel_pointer_ = nullptr, *allocated_pointer_ = nullptr;
|
||||
// The destination for new pixels.
|
||||
static constexpr int allocation_size = 336;
|
||||
static_assert((allocation_size % 16) == 0, "Allocation size must be a multiple of 16");
|
||||
uint16_t *pixel_pointer_ = nullptr, *allocated_pointer_ = nullptr;
|
||||
|
||||
// Output transitions.
|
||||
enum class OutputType {
|
||||
Sync, Blank, Pixels, Border, ColourBurst
|
||||
};
|
||||
void set_output_type(OutputType, bool force_flush = false);
|
||||
int output_duration_ = 0;
|
||||
OutputType output_type_ = OutputType::Sync;
|
||||
// Output transitions.
|
||||
enum class OutputType {
|
||||
Sync, Blank, Pixels, Border, ColourBurst
|
||||
};
|
||||
void set_output_type(OutputType, bool force_flush = false);
|
||||
int output_duration_ = 0;
|
||||
OutputType output_type_ = OutputType::Sync;
|
||||
|
||||
// Current palette.
|
||||
uint16_t palette_[16]{};
|
||||
// Current palette.
|
||||
uint16_t palette_[16]{};
|
||||
|
||||
// The first column with pixels on it; will be either 8 or 10 depending
|
||||
// on whether the colour burst is meaningful to the current display type.
|
||||
int first_pixel_window_ = 10;
|
||||
// The first column with pixels on it; will be either 8 or 10 depending
|
||||
// on whether the colour burst is meaningful to the current display type.
|
||||
int first_pixel_window_ = 10;
|
||||
|
||||
// Specific outputters.
|
||||
template <int bpp, bool is_lpixel> void output_pixel(uint16_t *target, int columns) const;
|
||||
template <int bpp, int index_bits> void output_character(uint16_t *target, int columns) const;
|
||||
template <int bpp> void output_attributed(uint16_t *target, int columns) const;
|
||||
// Specific outputters.
|
||||
template <int bpp, bool is_lpixel> void output_pixel(uint16_t *target, int columns) const;
|
||||
template <int bpp, int index_bits> void output_character(uint16_t *target, int columns) const;
|
||||
template <int bpp> void output_attributed(uint16_t *target, int columns) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user