mirror of
https://github.com/TomHarte/CLK.git
synced 2025-08-08 14:25:05 +00:00
Merge pull request #375 from TomHarte/UndefinedBehaviour
Resolves various pieces of undefined behaviour.
This commit is contained in:
@@ -16,9 +16,9 @@ namespace Static {
|
|||||||
namespace Acorn {
|
namespace Acorn {
|
||||||
|
|
||||||
struct Target: public ::Analyser::Static::Target {
|
struct Target: public ::Analyser::Static::Target {
|
||||||
bool has_adfs;
|
bool has_adfs = false;
|
||||||
bool has_dfs;
|
bool has_dfs = false;
|
||||||
bool should_shift_restart;
|
bool should_shift_restart = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -22,7 +22,7 @@ struct Target: public ::Analyser::Static::Target {
|
|||||||
CPC6128
|
CPC6128
|
||||||
};
|
};
|
||||||
|
|
||||||
Model model;
|
Model model = Model::CPC464;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -32,8 +32,8 @@ struct Target: public ::Analyser::Static::Target {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// TODO: shouldn't these be properties of the cartridge?
|
// TODO: shouldn't these be properties of the cartridge?
|
||||||
PagingModel paging_model;
|
PagingModel paging_model = PagingModel::None;
|
||||||
bool uses_superchip;
|
bool uses_superchip = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -22,8 +22,8 @@ struct Target: public ::Analyser::Static::Target {
|
|||||||
ThirtyTwoKB
|
ThirtyTwoKB
|
||||||
};
|
};
|
||||||
|
|
||||||
MemoryModel memory_model;
|
MemoryModel memory_model = MemoryModel::Unexpanded;
|
||||||
bool has_c1540;
|
bool has_c1540 = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -14,8 +14,8 @@ namespace Static {
|
|||||||
namespace Oric {
|
namespace Oric {
|
||||||
|
|
||||||
struct Target: public ::Analyser::Static::Target {
|
struct Target: public ::Analyser::Static::Target {
|
||||||
bool use_atmos_rom;
|
bool use_atmos_rom = false;
|
||||||
bool has_microdisc;
|
bool has_microdisc = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -22,8 +22,8 @@ struct Target: public ::Analyser::Static::Target {
|
|||||||
SixtyFourKB
|
SixtyFourKB
|
||||||
};
|
};
|
||||||
|
|
||||||
MemoryModel memory_model;
|
MemoryModel memory_model = MemoryModel::Unexpanded;
|
||||||
bool isZX81;
|
bool isZX81 = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -68,6 +68,10 @@ template <class T> class MOS6560 {
|
|||||||
set_output_mode(OutputMode::NTSC);
|
set_output_mode(OutputMode::NTSC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~MOS6560() {
|
||||||
|
audio_queue_.flush();
|
||||||
|
}
|
||||||
|
|
||||||
void set_clock_rate(double clock_rate) {
|
void set_clock_rate(double clock_rate) {
|
||||||
speaker_.set_input_rate(static_cast<float>(clock_rate / 4.0));
|
speaker_.set_input_rate(static_cast<float>(clock_rate / 4.0));
|
||||||
}
|
}
|
||||||
|
@@ -45,6 +45,7 @@ AsyncTaskQueue::AsyncTaskQueue()
|
|||||||
|
|
||||||
AsyncTaskQueue::~AsyncTaskQueue() {
|
AsyncTaskQueue::~AsyncTaskQueue() {
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
|
flush();
|
||||||
dispatch_release(serial_dispatch_queue_);
|
dispatch_release(serial_dispatch_queue_);
|
||||||
serial_dispatch_queue_ = nullptr;
|
serial_dispatch_queue_ = nullptr;
|
||||||
#else
|
#else
|
||||||
@@ -82,6 +83,7 @@ void AsyncTaskQueue::flush() {
|
|||||||
|
|
||||||
DeferringAsyncTaskQueue::~DeferringAsyncTaskQueue() {
|
DeferringAsyncTaskQueue::~DeferringAsyncTaskQueue() {
|
||||||
perform();
|
perform();
|
||||||
|
flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeferringAsyncTaskQueue::defer(std::function<void(void)> function) {
|
void DeferringAsyncTaskQueue::defer(std::function<void(void)> function) {
|
||||||
|
@@ -126,6 +126,10 @@ class AYDeferrer {
|
|||||||
speaker_.set_input_rate(1000000);
|
speaker_.set_input_rate(1000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~AYDeferrer() {
|
||||||
|
audio_queue_.flush();
|
||||||
|
}
|
||||||
|
|
||||||
/// Adds @c half_cycles half cycles to the amount of time that has passed.
|
/// Adds @c half_cycles half cycles to the amount of time that has passed.
|
||||||
inline void run_for(HalfCycles half_cycles) {
|
inline void run_for(HalfCycles half_cycles) {
|
||||||
cycles_since_update_ += half_cycles;
|
cycles_since_update_ += half_cycles;
|
||||||
|
@@ -26,6 +26,10 @@ class Bus {
|
|||||||
tia_sound_(audio_queue_),
|
tia_sound_(audio_queue_),
|
||||||
speaker_(tia_sound_) {}
|
speaker_(tia_sound_) {}
|
||||||
|
|
||||||
|
virtual ~Bus() {
|
||||||
|
audio_queue_.flush();
|
||||||
|
}
|
||||||
|
|
||||||
virtual void run_for(const Cycles cycles) = 0;
|
virtual void run_for(const Cycles cycles) = 0;
|
||||||
virtual void apply_confidence(Analyser::Dynamic::ConfidenceCounter &confidence_counter) = 0;
|
virtual void apply_confidence(Analyser::Dynamic::ConfidenceCounter &confidence_counter) = 0;
|
||||||
virtual void set_reset_line(bool state) = 0;
|
virtual void set_reset_line(bool state) = 0;
|
||||||
|
@@ -125,6 +125,10 @@ class ConcreteMachine:
|
|||||||
joysticks_.emplace_back(new Joystick);
|
joysticks_.emplace_back(new Joystick);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~ConcreteMachine() {
|
||||||
|
audio_queue_.flush();
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<std::unique_ptr<Inputs::Joystick>> &get_joysticks() override {
|
std::vector<std::unique_ptr<Inputs::Joystick>> &get_joysticks() override {
|
||||||
return joysticks_;
|
return joysticks_;
|
||||||
}
|
}
|
||||||
|
@@ -61,6 +61,10 @@ class ConcreteMachine:
|
|||||||
speaker_.set_input_rate(2000000 / SoundGenerator::clock_rate_divider);
|
speaker_.set_input_rate(2000000 / SoundGenerator::clock_rate_divider);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~ConcreteMachine() {
|
||||||
|
audio_queue_.flush();
|
||||||
|
}
|
||||||
|
|
||||||
void set_rom(ROMSlot slot, const std::vector<uint8_t> &data, bool is_writeable) override final {
|
void set_rom(ROMSlot slot, const std::vector<uint8_t> &data, bool is_writeable) override final {
|
||||||
uint8_t *target = nullptr;
|
uint8_t *target = nullptr;
|
||||||
switch(slot) {
|
switch(slot) {
|
||||||
|
@@ -144,6 +144,10 @@ class ConcreteMachine:
|
|||||||
tape_player_.set_sleep_observer(this);
|
tape_player_.set_sleep_observer(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~ConcreteMachine() {
|
||||||
|
audio_queue_.flush();
|
||||||
|
}
|
||||||
|
|
||||||
void setup_output(float aspect_ratio) override {
|
void setup_output(float aspect_ratio) override {
|
||||||
vdp_.reset(new TI::TMS9918(TI::TMS9918::TMS9918A));
|
vdp_.reset(new TI::TMS9918(TI::TMS9918::TMS9918A));
|
||||||
}
|
}
|
||||||
|
@@ -215,6 +215,10 @@ class ConcreteMachine:
|
|||||||
Memory::Fuzz(ram_, sizeof(ram_));
|
Memory::Fuzz(ram_, sizeof(ram_));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~ConcreteMachine() {
|
||||||
|
audio_queue_.flush();
|
||||||
|
}
|
||||||
|
|
||||||
// Obtains the system ROMs.
|
// Obtains the system ROMs.
|
||||||
bool set_rom_fetcher(const std::function<std::vector<std::unique_ptr<std::vector<uint8_t>>>(const std::string &machine, const std::vector<std::string> &names)> &roms_with_names) override {
|
bool set_rom_fetcher(const std::function<std::vector<std::unique_ptr<std::vector<uint8_t>>>(const std::string &machine, const std::vector<std::string> &names)> &roms_with_names) override {
|
||||||
auto roms = roms_with_names(
|
auto roms = roms_with_names(
|
||||||
|
@@ -76,6 +76,10 @@ template<bool is_zx81> class ConcreteMachine:
|
|||||||
clear_all_keys();
|
clear_all_keys();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~ConcreteMachine() {
|
||||||
|
audio_queue_.flush();
|
||||||
|
}
|
||||||
|
|
||||||
forceinline HalfCycles perform_machine_cycle(const CPU::Z80::PartialMachineCycle &cycle) {
|
forceinline HalfCycles perform_machine_cycle(const CPU::Z80::PartialMachineCycle &cycle) {
|
||||||
const HalfCycles previous_counter = horizontal_counter_;
|
const HalfCycles previous_counter = horizontal_counter_;
|
||||||
horizontal_counter_ += cycle.length;
|
horizontal_counter_ += cycle.length;
|
||||||
|
@@ -134,9 +134,9 @@ class ProcessorStorage {
|
|||||||
uint8_t carry_result_; // the carry flag is set if bit 0 of carry_result_ is set
|
uint8_t carry_result_; // the carry flag is set if bit 0 of carry_result_ is set
|
||||||
uint8_t halt_mask_ = 0xff;
|
uint8_t halt_mask_ = 0xff;
|
||||||
|
|
||||||
int flag_adjustment_history_ = 0; // a shifting record of whether each opcode set any flags; it turns out
|
unsigned int flag_adjustment_history_ = 0; // a shifting record of whether each opcode set any flags; it turns out
|
||||||
// that knowledge of what the last opcode did is necessary to get bits 5 & 3
|
// that knowledge of what the last opcode did is necessary to get bits 5 & 3
|
||||||
// correct for SCF and CCF.
|
// correct for SCF and CCF.
|
||||||
|
|
||||||
HalfCycles number_of_cycles_;
|
HalfCycles number_of_cycles_;
|
||||||
|
|
||||||
|
@@ -56,7 +56,7 @@ std::map<std::size_t, Storage::Encodings::MFM::Sector> Storage::Encodings::MFM::
|
|||||||
case 2: new_sector->address.sector = shifter.get_byte(); ++position; break;
|
case 2: new_sector->address.sector = shifter.get_byte(); ++position; break;
|
||||||
case 3:
|
case 3:
|
||||||
new_sector->size = shifter.get_byte();
|
new_sector->size = shifter.get_byte();
|
||||||
size = static_cast<std::size_t>(128 << new_sector->size);
|
size = static_cast<std::size_t>(128 << (new_sector->size&7));
|
||||||
++position;
|
++position;
|
||||||
is_reading = false;
|
is_reading = false;
|
||||||
shifter.set_should_obey_syncs(true);
|
shifter.set_should_obey_syncs(true);
|
||||||
|
Reference in New Issue
Block a user