mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-26 23:52:26 +00:00
Merge pull request #266 from TomHarte/SDLScons
Introduces an SCons build file and corrects remaining Ubuntu build errors
This commit is contained in:
commit
7adc25694a
4
.gitignore
vendored
4
.gitignore
vendored
@ -22,6 +22,10 @@ DerivedData
|
|||||||
ROMImages/*
|
ROMImages/*
|
||||||
OSBindings/Mac/Clock SignalTests/Atari\ ROMs
|
OSBindings/Mac/Clock SignalTests/Atari\ ROMs
|
||||||
|
|
||||||
|
# Exclude intermediate build products
|
||||||
|
*.o
|
||||||
|
.sconsign.dblite
|
||||||
|
|
||||||
# CocoaPods
|
# CocoaPods
|
||||||
#
|
#
|
||||||
# We recommend against adding the Pods directory to your .gitignore. However
|
# We recommend against adding the Pods directory to your .gitignore. However
|
||||||
|
@ -11,28 +11,10 @@
|
|||||||
|
|
||||||
using namespace WD;
|
using namespace WD;
|
||||||
|
|
||||||
WD1770::Status::Status() :
|
|
||||||
type(Status::One),
|
|
||||||
write_protect(false),
|
|
||||||
record_type(false),
|
|
||||||
spin_up(false),
|
|
||||||
record_not_found(false),
|
|
||||||
crc_error(false),
|
|
||||||
seek_error(false),
|
|
||||||
lost_data(false),
|
|
||||||
data_request(false),
|
|
||||||
interrupt_request(false),
|
|
||||||
busy(false) {}
|
|
||||||
|
|
||||||
WD1770::WD1770(Personality p) :
|
WD1770::WD1770(Personality p) :
|
||||||
Storage::Disk::MFMController(8000000),
|
Storage::Disk::MFMController(8000000),
|
||||||
interesting_event_mask_(static_cast<int>(Event1770::Command)),
|
|
||||||
resume_point_(0),
|
|
||||||
delay_time_(0),
|
|
||||||
index_hole_count_target_(-1),
|
|
||||||
delegate_(nullptr),
|
|
||||||
personality_(p),
|
personality_(p),
|
||||||
head_is_loaded_(false) {
|
interesting_event_mask_(static_cast<int>(Event1770::Command)) {
|
||||||
set_is_double_density(false);
|
set_is_double_density(false);
|
||||||
posit_event(static_cast<int>(Event1770::Command));
|
posit_event(static_cast<int>(Event1770::Command));
|
||||||
}
|
}
|
||||||
|
@ -85,20 +85,19 @@ class WD1770: public Storage::Disk::MFMController {
|
|||||||
inline bool has_head_load_line() { return (personality_ == P1793 ); }
|
inline bool has_head_load_line() { return (personality_ == P1793 ); }
|
||||||
|
|
||||||
struct Status {
|
struct Status {
|
||||||
Status();
|
bool write_protect = false;
|
||||||
bool write_protect;
|
bool record_type = false;
|
||||||
bool record_type;
|
bool spin_up = false;
|
||||||
bool spin_up;
|
bool record_not_found = false;
|
||||||
bool record_not_found;
|
bool crc_error = false;
|
||||||
bool crc_error;
|
bool seek_error = false;
|
||||||
bool seek_error;
|
bool lost_data = false;
|
||||||
bool lost_data;
|
bool data_request = false;
|
||||||
bool data_request;
|
bool interrupt_request = false;
|
||||||
bool interrupt_request;
|
bool busy = false;
|
||||||
bool busy;
|
|
||||||
enum {
|
enum {
|
||||||
One, Two, Three
|
One, Two, Three
|
||||||
} type;
|
} type = One;
|
||||||
} status_;
|
} status_;
|
||||||
uint8_t track_;
|
uint8_t track_;
|
||||||
uint8_t sector_;
|
uint8_t sector_;
|
||||||
@ -106,7 +105,7 @@ class WD1770: public Storage::Disk::MFMController {
|
|||||||
uint8_t command_;
|
uint8_t command_;
|
||||||
|
|
||||||
int index_hole_count_;
|
int index_hole_count_;
|
||||||
int index_hole_count_target_;
|
int index_hole_count_target_ = -1;
|
||||||
int distance_into_section_;
|
int distance_into_section_;
|
||||||
|
|
||||||
int step_direction_;
|
int step_direction_;
|
||||||
@ -121,17 +120,17 @@ class WD1770: public Storage::Disk::MFMController {
|
|||||||
};
|
};
|
||||||
void posit_event(int type);
|
void posit_event(int type);
|
||||||
int interesting_event_mask_;
|
int interesting_event_mask_;
|
||||||
int resume_point_;
|
int resume_point_ = 0;
|
||||||
unsigned int delay_time_;
|
unsigned int delay_time_ = 0;
|
||||||
|
|
||||||
// ID buffer
|
// ID buffer
|
||||||
uint8_t header_[6];
|
uint8_t header_[6];
|
||||||
|
|
||||||
// 1793 head-loading logic
|
// 1793 head-loading logic
|
||||||
bool head_is_loaded_;
|
bool head_is_loaded_ = false;
|
||||||
|
|
||||||
// delegate
|
// delegate
|
||||||
Delegate *delegate_;
|
Delegate *delegate_ = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -121,12 +121,9 @@ template <class T> class MOS6532 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MOS6532() :
|
MOS6532() {
|
||||||
interrupt_status_(0),
|
timer_.value = static_cast<unsigned int>((rand() & 0xff) << 10);
|
||||||
port_{{.output_mask = 0, .output = 0}, {.output_mask = 0, .output = 0}},
|
}
|
||||||
a7_interrupt_({.last_port_value = 0, .enabled = false}),
|
|
||||||
interrupt_line_(false),
|
|
||||||
timer_{.value = static_cast<unsigned int>((rand() & 0xff) << 10), .activeShift = 10, .writtenShift = 10, .interrupt_enabled = false} {}
|
|
||||||
|
|
||||||
inline void set_port_did_change(int port) {
|
inline void set_port_did_change(int port) {
|
||||||
if(!port) {
|
if(!port) {
|
||||||
@ -154,26 +151,26 @@ template <class T> class MOS6532 {
|
|||||||
|
|
||||||
struct {
|
struct {
|
||||||
unsigned int value;
|
unsigned int value;
|
||||||
unsigned int activeShift, writtenShift;
|
unsigned int activeShift = 10, writtenShift = 10;
|
||||||
bool interrupt_enabled;
|
bool interrupt_enabled = false;
|
||||||
} timer_;
|
} timer_;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
bool enabled;
|
bool enabled = false;
|
||||||
bool active_on_positive;
|
bool active_on_positive = false;
|
||||||
uint8_t last_port_value;
|
uint8_t last_port_value = 0;
|
||||||
} a7_interrupt_;
|
} a7_interrupt_;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
uint8_t output_mask, output;
|
uint8_t output_mask = 0, output = 0;
|
||||||
} port_[2];
|
} port_[2];
|
||||||
|
|
||||||
uint8_t interrupt_status_;
|
uint8_t interrupt_status_ = 0;
|
||||||
enum InterruptFlag: uint8_t {
|
enum InterruptFlag: uint8_t {
|
||||||
Timer = 0x80,
|
Timer = 0x80,
|
||||||
PA7 = 0x40
|
PA7 = 0x40
|
||||||
};
|
};
|
||||||
bool interrupt_line_;
|
bool interrupt_line_ = false;
|
||||||
|
|
||||||
// expected to be overridden
|
// expected to be overridden
|
||||||
uint8_t get_port_input(int port) { return 0xff; }
|
uint8_t get_port_input(int port) { return 0xff; }
|
||||||
|
@ -8,13 +8,9 @@
|
|||||||
|
|
||||||
#include "6560.hpp"
|
#include "6560.hpp"
|
||||||
|
|
||||||
using namespace MOS;
|
#include <cstring>
|
||||||
|
|
||||||
Speaker::Speaker() :
|
using namespace MOS;
|
||||||
volume_(0),
|
|
||||||
control_registers_{0, 0, 0, 0},
|
|
||||||
shift_registers_{0, 0, 0, 0},
|
|
||||||
counters_{2, 1, 0, 0} {} // create a slight phase offset for the three channels
|
|
||||||
|
|
||||||
void Speaker::set_volume(uint8_t volume) {
|
void Speaker::set_volume(uint8_t volume) {
|
||||||
enqueue([=]() {
|
enqueue([=]() {
|
||||||
|
@ -18,8 +18,6 @@ namespace MOS {
|
|||||||
// audio state
|
// audio state
|
||||||
class Speaker: public ::Outputs::Filter<Speaker> {
|
class Speaker: public ::Outputs::Filter<Speaker> {
|
||||||
public:
|
public:
|
||||||
Speaker();
|
|
||||||
|
|
||||||
void set_volume(uint8_t volume);
|
void set_volume(uint8_t volume);
|
||||||
void set_control(int channel, uint8_t value);
|
void set_control(int channel, uint8_t value);
|
||||||
|
|
||||||
@ -27,10 +25,10 @@ class Speaker: public ::Outputs::Filter<Speaker> {
|
|||||||
void skip_samples(unsigned int number_of_samples);
|
void skip_samples(unsigned int number_of_samples);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned int counters_[4];
|
unsigned int counters_[4] = {2, 1, 0, 0}; // create a slight phase offset for the three channels
|
||||||
unsigned int shift_registers_[4];
|
unsigned int shift_registers_[4] = {0, 0, 0, 0};
|
||||||
uint8_t control_registers_[4];
|
uint8_t control_registers_[4] = {0, 0, 0, 0};
|
||||||
uint8_t volume_;
|
uint8_t volume_ = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -45,12 +43,7 @@ template <class T> class MOS6560 {
|
|||||||
public:
|
public:
|
||||||
MOS6560() :
|
MOS6560() :
|
||||||
crt_(new Outputs::CRT::CRT(65*4, 4, Outputs::CRT::NTSC60, 2)),
|
crt_(new Outputs::CRT::CRT(65*4, 4, Outputs::CRT::NTSC60, 2)),
|
||||||
speaker_(new Speaker),
|
speaker_(new Speaker) {
|
||||||
horizontal_counter_(0),
|
|
||||||
vertical_counter_(0),
|
|
||||||
cycles_since_speaker_update_(0),
|
|
||||||
is_odd_frame_(false),
|
|
||||||
is_odd_line_(false) {
|
|
||||||
crt_->set_composite_sampling_function(
|
crt_->set_composite_sampling_function(
|
||||||
"float composite_sample(usampler2D texID, vec2 coordinate, vec2 iCoordinate, float phase, float amplitude)"
|
"float composite_sample(usampler2D texID, vec2 coordinate, vec2 iCoordinate, float phase, float amplitude)"
|
||||||
"{"
|
"{"
|
||||||
@ -432,7 +425,7 @@ template <class T> class MOS6560 {
|
|||||||
unsigned int cycles_in_state_;
|
unsigned int cycles_in_state_;
|
||||||
|
|
||||||
// counters that cover an entire field
|
// counters that cover an entire field
|
||||||
int horizontal_counter_, vertical_counter_, full_frame_counter_;
|
int horizontal_counter_ = 0, vertical_counter_ = 0, full_frame_counter_;
|
||||||
|
|
||||||
// latches dictating start and length of drawing
|
// latches dictating start and length of drawing
|
||||||
bool vertical_drawing_latch_, horizontal_drawing_latch_;
|
bool vertical_drawing_latch_, horizontal_drawing_latch_;
|
||||||
@ -447,7 +440,7 @@ template <class T> class MOS6560 {
|
|||||||
// data latched from the bus
|
// data latched from the bus
|
||||||
uint8_t character_code_, character_colour_, character_value_;
|
uint8_t character_code_, character_colour_, character_value_;
|
||||||
|
|
||||||
bool is_odd_frame_, is_odd_line_;
|
bool is_odd_frame_ = false, is_odd_line_ = false;
|
||||||
|
|
||||||
// lookup table from 6560 colour index to appropriate PAL/NTSC value
|
// lookup table from 6560 colour index to appropriate PAL/NTSC value
|
||||||
uint16_t colours_[16];
|
uint16_t colours_[16];
|
||||||
|
@ -10,16 +10,7 @@
|
|||||||
|
|
||||||
using namespace GI::AY38910;
|
using namespace GI::AY38910;
|
||||||
|
|
||||||
AY38910::AY38910() :
|
AY38910::AY38910() {
|
||||||
selected_register_(0),
|
|
||||||
tone_counters_{0, 0, 0}, tone_periods_{0, 0, 0}, tone_outputs_{0, 0, 0},
|
|
||||||
noise_shift_register_(0xffff), noise_period_(0), noise_counter_(0), noise_output_(0),
|
|
||||||
envelope_divider_(0), envelope_period_(0), envelope_position_(0),
|
|
||||||
master_divider_(0),
|
|
||||||
output_registers_{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
|
||||||
port_handler_(nullptr) {
|
|
||||||
output_registers_[8] = output_registers_[9] = output_registers_[10] = 0;
|
|
||||||
|
|
||||||
// set up envelope lookup tables
|
// set up envelope lookup tables
|
||||||
for(int c = 0; c < 16; c++) {
|
for(int c = 0; c < 16; c++) {
|
||||||
for(int p = 0; p < 32; p++) {
|
for(int p = 0; p < 32; p++) {
|
||||||
|
@ -89,24 +89,25 @@ class AY38910: public ::Outputs::Filter<AY38910> {
|
|||||||
void get_samples(unsigned int number_of_samples, int16_t *target);
|
void get_samples(unsigned int number_of_samples, int16_t *target);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int selected_register_;
|
int selected_register_ = 0;
|
||||||
uint8_t registers_[16], output_registers_[16];
|
uint8_t registers_[16];
|
||||||
|
uint8_t output_registers_[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||||
uint8_t port_inputs_[2];
|
uint8_t port_inputs_[2];
|
||||||
|
|
||||||
int master_divider_;
|
int master_divider_ = 0;
|
||||||
|
|
||||||
int tone_periods_[3];
|
int tone_periods_[3] = {0, 0, 0};
|
||||||
int tone_counters_[3];
|
int tone_counters_[3] = {0, 0, 0};
|
||||||
int tone_outputs_[3];
|
int tone_outputs_[3] = {0, 0, 0};
|
||||||
|
|
||||||
int noise_period_;
|
int noise_period_ = 0;
|
||||||
int noise_counter_;
|
int noise_counter_ = 0;
|
||||||
int noise_shift_register_;
|
int noise_shift_register_ = 0xffff;
|
||||||
int noise_output_;
|
int noise_output_ = 0;
|
||||||
|
|
||||||
int envelope_period_;
|
int envelope_period_ = 0;
|
||||||
int envelope_divider_;
|
int envelope_divider_ = 0;
|
||||||
int envelope_position_;
|
int envelope_position_ = 0;
|
||||||
int envelope_shapes_[16][32];
|
int envelope_shapes_[16][32];
|
||||||
int envelope_overflow_masks_[16];
|
int envelope_overflow_masks_[16];
|
||||||
|
|
||||||
@ -129,7 +130,7 @@ class AY38910: public ::Outputs::Filter<AY38910> {
|
|||||||
inline void evaluate_output_volume();
|
inline void evaluate_output_volume();
|
||||||
|
|
||||||
inline void update_bus();
|
inline void update_bus();
|
||||||
PortHandler *port_handler_;
|
PortHandler *port_handler_ = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -9,10 +9,12 @@
|
|||||||
#ifndef AsyncTaskQueue_hpp
|
#ifndef AsyncTaskQueue_hpp
|
||||||
#define AsyncTaskQueue_hpp
|
#define AsyncTaskQueue_hpp
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
#include <condition_variable>
|
||||||
|
#include <functional>
|
||||||
|
#include <list>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <list>
|
|
||||||
#include <condition_variable>
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
#include <dispatch/dispatch.h>
|
#include <dispatch/dispatch.h>
|
||||||
|
@ -602,9 +602,9 @@ class i8255PortHandler : public Intel::i8255::PortHandler {
|
|||||||
const Motorola::CRTC::CRTC6845<CRTCBusHandler> &crtc,
|
const Motorola::CRTC::CRTC6845<CRTCBusHandler> &crtc,
|
||||||
AYDeferrer &ay,
|
AYDeferrer &ay,
|
||||||
Storage::Tape::BinaryTapePlayer &tape_player) :
|
Storage::Tape::BinaryTapePlayer &tape_player) :
|
||||||
key_state_(key_state),
|
|
||||||
crtc_(crtc),
|
|
||||||
ay_(ay),
|
ay_(ay),
|
||||||
|
crtc_(crtc),
|
||||||
|
key_state_(key_state),
|
||||||
tape_player_(tape_player) {}
|
tape_player_(tape_player) {}
|
||||||
|
|
||||||
/// The i8255 will call this to set a new output value of @c value for @c port.
|
/// The i8255 will call this to set a new output value of @c value for @c port.
|
||||||
@ -658,8 +658,8 @@ class i8255PortHandler : public Intel::i8255::PortHandler {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
AYDeferrer &ay_;
|
AYDeferrer &ay_;
|
||||||
KeyboardState &key_state_;
|
|
||||||
const Motorola::CRTC::CRTC6845<CRTCBusHandler> &crtc_;
|
const Motorola::CRTC::CRTC6845<CRTCBusHandler> &crtc_;
|
||||||
|
KeyboardState &key_state_;
|
||||||
Storage::Tape::BinaryTapePlayer &tape_player_;
|
Storage::Tape::BinaryTapePlayer &tape_player_;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -674,12 +674,13 @@ class ConcreteMachine:
|
|||||||
public:
|
public:
|
||||||
ConcreteMachine() :
|
ConcreteMachine() :
|
||||||
z80_(*this),
|
z80_(*this),
|
||||||
crtc_counter_(HalfCycles(4)), // This starts the CRTC exactly out of phase with the CPU's memory accesses
|
|
||||||
crtc_(Motorola::CRTC::HD6845S, crtc_bus_handler_),
|
|
||||||
crtc_bus_handler_(ram_, interrupt_timer_),
|
crtc_bus_handler_(ram_, interrupt_timer_),
|
||||||
i8255_(i8255_port_handler_),
|
crtc_(Motorola::CRTC::HD6845S, crtc_bus_handler_),
|
||||||
i8255_port_handler_(key_state_, crtc_, ay_, tape_player_),
|
i8255_port_handler_(key_state_, crtc_, ay_, tape_player_),
|
||||||
tape_player_(8000000) {
|
i8255_(i8255_port_handler_),
|
||||||
|
tape_player_(8000000),
|
||||||
|
crtc_counter_(HalfCycles(4)) // This starts the CRTC exactly out of phase with the CPU's memory accesses
|
||||||
|
{
|
||||||
// primary clock is 4Mhz
|
// primary clock is 4Mhz
|
||||||
set_clock_rate(4000000);
|
set_clock_rate(4000000);
|
||||||
|
|
||||||
|
@ -53,8 +53,8 @@ class Joystick: public Inputs::Joystick {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
size_t shift_, fire_tia_input_;
|
|
||||||
Bus *bus_;
|
Bus *bus_;
|
||||||
|
size_t shift_, fire_tia_input_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ConcreteMachine:
|
class ConcreteMachine:
|
||||||
|
@ -16,11 +16,7 @@ class Pitfall2: public BusExtender {
|
|||||||
public:
|
public:
|
||||||
Pitfall2(uint8_t *rom_base, size_t rom_size) :
|
Pitfall2(uint8_t *rom_base, size_t rom_size) :
|
||||||
BusExtender(rom_base, rom_size),
|
BusExtender(rom_base, rom_size),
|
||||||
rom_ptr_(rom_base),
|
rom_ptr_(rom_base) {}
|
||||||
random_number_generator_(0),
|
|
||||||
featcher_address_{0, 0, 0, 0, 0, 0, 0, 0},
|
|
||||||
mask_{0, 0, 0, 0, 0, 0, 0, 0},
|
|
||||||
cycles_since_audio_update_(0) {}
|
|
||||||
|
|
||||||
void advance_cycles(int cycles) {
|
void advance_cycles(int cycles) {
|
||||||
cycles_since_audio_update_ += cycles;
|
cycles_since_audio_update_ += cycles;
|
||||||
@ -119,13 +115,13 @@ class Pitfall2: public BusExtender {
|
|||||||
return level_table[table_position];
|
return level_table[table_position];
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t featcher_address_[8];
|
uint16_t featcher_address_[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||||
uint8_t top_[8], bottom_[8], mask_[8];
|
uint8_t top_[8], bottom_[8], mask_[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||||
uint8_t music_mode_[3];
|
uint8_t music_mode_[3];
|
||||||
uint8_t random_number_generator_;
|
uint8_t random_number_generator_ = 0;
|
||||||
uint8_t *rom_ptr_;
|
uint8_t *rom_ptr_;
|
||||||
uint8_t audio_channel_[3];
|
uint8_t audio_channel_[3];
|
||||||
Cycles cycles_since_audio_update_;
|
Cycles cycles_since_audio_update_ = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
#ifndef Atari2600_PIA_h
|
#ifndef Atari2600_PIA_h
|
||||||
#define Atari2600_PIA_h
|
#define Atari2600_PIA_h
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
#include "../../Components/6532/6532.hpp"
|
#include "../../Components/6532/6532.hpp"
|
||||||
|
|
||||||
namespace Atari2600 {
|
namespace Atari2600 {
|
||||||
|
@ -20,16 +20,7 @@ namespace {
|
|||||||
uint8_t reverse_table[256];
|
uint8_t reverse_table[256];
|
||||||
}
|
}
|
||||||
|
|
||||||
TIA::TIA(bool create_crt) :
|
TIA::TIA(bool create_crt) {
|
||||||
horizontal_counter_(0),
|
|
||||||
pixels_start_location_(0),
|
|
||||||
output_mode_(0),
|
|
||||||
pixel_target_(nullptr),
|
|
||||||
background_{0, 0},
|
|
||||||
background_half_mask_(0),
|
|
||||||
horizontal_blank_extend_(false),
|
|
||||||
collision_flags_(0)
|
|
||||||
{
|
|
||||||
if(create_crt) {
|
if(create_crt) {
|
||||||
crt_.reset(new Outputs::CRT::CRT(cycles_per_line * 2 - 1, 1, Outputs::CRT::DisplayType::NTSC60, 1));
|
crt_.reset(new Outputs::CRT::CRT(cycles_per_line * 2 - 1, 1, Outputs::CRT::DisplayType::NTSC60, 1));
|
||||||
crt_->set_output_device(Outputs::CRT::Television);
|
crt_->set_output_device(Outputs::CRT::Television);
|
||||||
|
@ -81,10 +81,10 @@ class TIA {
|
|||||||
std::function<void(uint8_t *output_buffer)> line_end_function_;
|
std::function<void(uint8_t *output_buffer)> line_end_function_;
|
||||||
|
|
||||||
// the master counter; counts from 0 to 228 with all visible pixels being in the final 160
|
// the master counter; counts from 0 to 228 with all visible pixels being in the final 160
|
||||||
int horizontal_counter_;
|
int horizontal_counter_ = 0;
|
||||||
|
|
||||||
// contains flags to indicate whether sync or blank are currently active
|
// contains flags to indicate whether sync or blank are currently active
|
||||||
int output_mode_;
|
int output_mode_ = 0;
|
||||||
|
|
||||||
// keeps track of the target pixel buffer for this line and when it was acquired, and a corresponding collision buffer
|
// keeps track of the target pixel buffer for this line and when it was acquired, and a corresponding collision buffer
|
||||||
alignas(alignof(uint32_t)) uint8_t collision_buffer_[160];
|
alignas(alignof(uint32_t)) uint8_t collision_buffer_[160];
|
||||||
@ -97,7 +97,7 @@ class TIA {
|
|||||||
Missile1 = (1 << 5)
|
Missile1 = (1 << 5)
|
||||||
};
|
};
|
||||||
|
|
||||||
int collision_flags_;
|
int collision_flags_ = 0;
|
||||||
int collision_flags_by_buffer_vaules_[64];
|
int collision_flags_by_buffer_vaules_[64];
|
||||||
|
|
||||||
// colour mapping tables
|
// colour mapping tables
|
||||||
@ -118,19 +118,20 @@ class TIA {
|
|||||||
uint8_t colour_palette_[4];
|
uint8_t colour_palette_[4];
|
||||||
|
|
||||||
// playfield state
|
// playfield state
|
||||||
int background_half_mask_;
|
int background_half_mask_ = 0;
|
||||||
enum class PlayfieldPriority {
|
enum class PlayfieldPriority {
|
||||||
Standard,
|
Standard,
|
||||||
Score,
|
Score,
|
||||||
OnTop
|
OnTop
|
||||||
} playfield_priority_;
|
} playfield_priority_;
|
||||||
uint32_t background_[2]; // contains two 20-bit bitfields representing the background state;
|
uint32_t background_[2] = {0, 0};
|
||||||
// at index 0 is the left-hand side of the playfield with bit 0 being
|
// contains two 20-bit bitfields representing the background state;
|
||||||
// the first bit to display, bit 1 the second, etc. Index 1 contains
|
// at index 0 is the left-hand side of the playfield with bit 0 being
|
||||||
// a mirror image of index 0. If the playfield is being displayed in
|
// the first bit to display, bit 1 the second, etc. Index 1 contains
|
||||||
// mirroring mode, background_[0] will be output on the left and
|
// a mirror image of index 0. If the playfield is being displayed in
|
||||||
// background_[1] on the right; otherwise background_[0] will be
|
// mirroring mode, background_[0] will be output on the left and
|
||||||
// output twice.
|
// background_[1] on the right; otherwise background_[0] will be
|
||||||
|
// output twice.
|
||||||
|
|
||||||
// objects
|
// objects
|
||||||
template<class T> struct Object {
|
template<class T> struct Object {
|
||||||
@ -287,7 +288,7 @@ class TIA {
|
|||||||
} ball_;
|
} ball_;
|
||||||
|
|
||||||
// motion
|
// motion
|
||||||
bool horizontal_blank_extend_;
|
bool horizontal_blank_extend_ = false;
|
||||||
template<class T> void perform_border_motion(T &object, int start, int end);
|
template<class T> void perform_border_motion(T &object, int start, int end);
|
||||||
template<class T> void perform_motion_step(T &object);
|
template<class T> void perform_motion_step(T &object);
|
||||||
|
|
||||||
@ -300,8 +301,8 @@ class TIA {
|
|||||||
inline void output_for_cycles(int number_of_cycles);
|
inline void output_for_cycles(int number_of_cycles);
|
||||||
inline void output_line();
|
inline void output_line();
|
||||||
|
|
||||||
int pixels_start_location_;
|
int pixels_start_location_ = 0;
|
||||||
uint8_t *pixel_target_;
|
uint8_t *pixel_target_ = nullptr;
|
||||||
inline void output_pixels(int start, int end);
|
inline void output_pixels(int start, int end);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -23,8 +23,6 @@ namespace CRTMachine {
|
|||||||
*/
|
*/
|
||||||
class Machine: public ROMMachine::Machine {
|
class Machine: public ROMMachine::Machine {
|
||||||
public:
|
public:
|
||||||
Machine() : clock_is_unlimited_(false), delegate_(nullptr) {}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Causes the machine to set up its CRT and, if it has one, speaker. The caller guarantees
|
Causes the machine to set up its CRT and, if it has one, speaker. The caller guarantees
|
||||||
that an OpenGL context is bound.
|
that an OpenGL context is bound.
|
||||||
@ -75,9 +73,9 @@ class Machine: public ROMMachine::Machine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Delegate *delegate_;
|
Delegate *delegate_ = nullptr;
|
||||||
double clock_rate_;
|
double clock_rate_ = 1.0;
|
||||||
bool clock_is_unlimited_;
|
bool clock_is_unlimited_ = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6,24 +6,24 @@
|
|||||||
// Copyright © 2016 Thomas Harte. All rights reserved.
|
// Copyright © 2016 Thomas Harte. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "C1540.hpp"
|
#include "../C1540.hpp"
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <cstring>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "../../../../Storage/Disk/Encodings/CommodoreGCR.hpp"
|
#include "../../../../Storage/Disk/Encodings/CommodoreGCR.hpp"
|
||||||
|
|
||||||
using namespace Commodore::C1540;
|
using namespace Commodore::C1540;
|
||||||
|
|
||||||
MachineBase::MachineBase() :
|
MachineBase::MachineBase() :
|
||||||
m6502_(*this),
|
|
||||||
shift_register_(0),
|
|
||||||
Storage::Disk::Controller(1000000),
|
Storage::Disk::Controller(1000000),
|
||||||
serial_port_(new SerialPort),
|
m6502_(*this),
|
||||||
|
drive_(new Storage::Disk::Drive(1000000, 300, 2)),
|
||||||
serial_port_VIA_port_handler_(new SerialPortVIA(serial_port_VIA_)),
|
serial_port_VIA_port_handler_(new SerialPortVIA(serial_port_VIA_)),
|
||||||
|
serial_port_(new SerialPort),
|
||||||
drive_VIA_(drive_VIA_port_handler_),
|
drive_VIA_(drive_VIA_port_handler_),
|
||||||
serial_port_VIA_(*serial_port_VIA_port_handler_),
|
serial_port_VIA_(*serial_port_VIA_port_handler_) {
|
||||||
drive_(new Storage::Disk::Drive(1000000, 300, 2)) {
|
|
||||||
// attach the serial port to its VIA and vice versa
|
// attach the serial port to its VIA and vice versa
|
||||||
serial_port_->set_serial_port_via(serial_port_VIA_port_handler_);
|
serial_port_->set_serial_port_via(serial_port_VIA_port_handler_);
|
||||||
serial_port_VIA_port_handler_->set_serial_port(serial_port_);
|
serial_port_VIA_port_handler_->set_serial_port(serial_port_);
|
||||||
|
@ -147,7 +147,7 @@ class MachineBase:
|
|||||||
MOS::MOS6522::MOS6522<DriveVIA> drive_VIA_;
|
MOS::MOS6522::MOS6522<DriveVIA> drive_VIA_;
|
||||||
MOS::MOS6522::MOS6522<SerialPortVIA> serial_port_VIA_;
|
MOS::MOS6522::MOS6522<SerialPortVIA> serial_port_VIA_;
|
||||||
|
|
||||||
int shift_register_, bit_window_offset_;
|
int shift_register_ = 0, bit_window_offset_;
|
||||||
virtual void process_input_bit(int value);
|
virtual void process_input_bit(int value);
|
||||||
virtual void process_index_hole();
|
virtual void process_index_hole();
|
||||||
};
|
};
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
|
|
||||||
#include "SerialBus.hpp"
|
#include "SerialBus.hpp"
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
using namespace Commodore::Serial;
|
using namespace Commodore::Serial;
|
||||||
|
|
||||||
const char *::Commodore::Serial::StringForLine(Line line) {
|
const char *::Commodore::Serial::StringForLine(Line line) {
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
#ifndef SerialBus_hpp
|
#ifndef SerialBus_hpp
|
||||||
#define SerialBus_hpp
|
#define SerialBus_hpp
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace Commodore {
|
namespace Commodore {
|
||||||
|
@ -267,15 +267,13 @@ class ConcreteMachine:
|
|||||||
public:
|
public:
|
||||||
ConcreteMachine() :
|
ConcreteMachine() :
|
||||||
m6502_(*this),
|
m6502_(*this),
|
||||||
rom_(nullptr),
|
|
||||||
is_running_at_zero_cost_(false),
|
|
||||||
tape_(new Storage::Tape::BinaryTapePlayer(1022727)),
|
|
||||||
user_port_via_port_handler_(new UserPortVIA),
|
user_port_via_port_handler_(new UserPortVIA),
|
||||||
keyboard_via_port_handler_(new KeyboardVIA),
|
keyboard_via_port_handler_(new KeyboardVIA),
|
||||||
serial_port_(new SerialPort),
|
serial_port_(new SerialPort),
|
||||||
serial_bus_(new ::Commodore::Serial::Bus),
|
serial_bus_(new ::Commodore::Serial::Bus),
|
||||||
user_port_via_(*user_port_via_port_handler_),
|
user_port_via_(*user_port_via_port_handler_),
|
||||||
keyboard_via_(*keyboard_via_port_handler_) {
|
keyboard_via_(*keyboard_via_port_handler_),
|
||||||
|
tape_(new Storage::Tape::BinaryTapePlayer(1022727)) {
|
||||||
// communicate the tape to the user-port VIA
|
// communicate the tape to the user-port VIA
|
||||||
user_port_via_port_handler_->set_tape(tape_);
|
user_port_via_port_handler_->set_tape(tape_);
|
||||||
|
|
||||||
@ -453,7 +451,7 @@ class ConcreteMachine:
|
|||||||
write_to_map(mos6560_->video_memory_map, screen_memory_, 0x3000, sizeof(screen_memory_));
|
write_to_map(mos6560_->video_memory_map, screen_memory_, 0x3000, sizeof(screen_memory_));
|
||||||
mos6560_->colour_memory = colour_memory_;
|
mos6560_->colour_memory = colour_memory_;
|
||||||
|
|
||||||
write_to_map(processor_read_memory_map_, basic_rom_.data(), 0xc000, basic_rom_.size());
|
write_to_map(processor_read_memory_map_, basic_rom_.data(), 0xc000, static_cast<uint16_t>(basic_rom_.size()));
|
||||||
|
|
||||||
ROM character_rom;
|
ROM character_rom;
|
||||||
ROM kernel_rom;
|
ROM kernel_rom;
|
||||||
@ -480,9 +478,9 @@ class ConcreteMachine:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
write_to_map(processor_read_memory_map_, roms_[character_rom].data(), 0x8000, roms_[character_rom].size());
|
write_to_map(processor_read_memory_map_, roms_[character_rom].data(), 0x8000, static_cast<uint16_t>(roms_[character_rom].size()));
|
||||||
write_to_map(mos6560_->video_memory_map, roms_[character_rom].data(), 0x0000, roms_[character_rom].size());
|
write_to_map(mos6560_->video_memory_map, roms_[character_rom].data(), 0x0000, static_cast<uint16_t>(roms_[character_rom].size()));
|
||||||
write_to_map(processor_read_memory_map_, roms_[kernel_rom].data(), 0xe000, roms_[kernel_rom].size());
|
write_to_map(processor_read_memory_map_, roms_[kernel_rom].data(), 0xe000, static_cast<uint16_t>(roms_[kernel_rom].size()));
|
||||||
|
|
||||||
// install the inserted ROM if there is one
|
// install the inserted ROM if there is one
|
||||||
if(rom_) {
|
if(rom_) {
|
||||||
@ -648,7 +646,7 @@ class ConcreteMachine:
|
|||||||
std::vector<uint8_t> kernel_rom_;
|
std::vector<uint8_t> kernel_rom_;
|
||||||
uint8_t expansion_ram_[0x8000];
|
uint8_t expansion_ram_[0x8000];
|
||||||
|
|
||||||
uint8_t *rom_;
|
uint8_t *rom_ = nullptr;
|
||||||
uint16_t rom_address_, rom_length_;
|
uint16_t rom_address_, rom_length_;
|
||||||
|
|
||||||
uint8_t user_basic_memory_[0x0400];
|
uint8_t user_basic_memory_[0x0400];
|
||||||
@ -688,7 +686,7 @@ class ConcreteMachine:
|
|||||||
// Tape
|
// Tape
|
||||||
std::shared_ptr<Storage::Tape::BinaryTapePlayer> tape_;
|
std::shared_ptr<Storage::Tape::BinaryTapePlayer> tape_;
|
||||||
bool use_fast_tape_hack_;
|
bool use_fast_tape_hack_;
|
||||||
bool is_running_at_zero_cost_;
|
bool is_running_at_zero_cost_ = false;
|
||||||
|
|
||||||
// Disk
|
// Disk
|
||||||
std::shared_ptr<::Commodore::C1540::Machine> c1540_;
|
std::shared_ptr<::Commodore::C1540::Machine> c1540_;
|
||||||
|
@ -52,12 +52,12 @@ class Tape:
|
|||||||
inline void get_next_tape_pulse();
|
inline void get_next_tape_pulse();
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
int minimum_bits_until_full;
|
int minimum_bits_until_full = 0;
|
||||||
} input_ = {0};
|
} input_;
|
||||||
struct {
|
struct {
|
||||||
unsigned int cycles_into_pulse;
|
unsigned int cycles_into_pulse = 0;
|
||||||
unsigned int bits_remaining_until_empty;
|
unsigned int bits_remaining_until_empty = 0;
|
||||||
} output_ = {.bits_remaining_until_empty = 0, .cycles_into_pulse = 0};
|
} output_;
|
||||||
|
|
||||||
bool is_running_ = false;
|
bool is_running_ = false;
|
||||||
bool is_enabled_ = false;
|
bool is_enabled_ = false;
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
|
|
||||||
#include "Video.hpp"
|
#include "Video.hpp"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
using namespace Electron;
|
using namespace Electron;
|
||||||
|
|
||||||
#define graphics_line(v) ((((v) >> 7) - first_graphics_line + field_divider_line) % field_divider_line)
|
#define graphics_line(v) ((((v) >> 7) - first_graphics_line + field_divider_line) % field_divider_line)
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
#ifndef KeyboardMachine_h
|
#ifndef KeyboardMachine_h
|
||||||
#define KeyboardMachine_h
|
#define KeyboardMachine_h
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
#include "../Inputs/Keyboard.hpp"
|
#include "../Inputs/Keyboard.hpp"
|
||||||
|
|
||||||
namespace KeyboardMachine {
|
namespace KeyboardMachine {
|
||||||
|
@ -18,13 +18,7 @@ namespace {
|
|||||||
const int head_load_request_counter_target = 7653333;
|
const int head_load_request_counter_target = 7653333;
|
||||||
}
|
}
|
||||||
|
|
||||||
Microdisc::Microdisc() :
|
Microdisc::Microdisc() : WD1770(P1793) {
|
||||||
irq_enable_(false),
|
|
||||||
delegate_(nullptr),
|
|
||||||
paging_flags_(BASICDisable),
|
|
||||||
head_load_request_counter_(-1),
|
|
||||||
WD1770(P1793),
|
|
||||||
last_control_(0) {
|
|
||||||
set_control_register(last_control_, 0xff);
|
set_control_register(last_control_, 0xff);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,11 +45,11 @@ class Microdisc: public WD::WD1770 {
|
|||||||
bool get_drive_is_ready();
|
bool get_drive_is_ready();
|
||||||
std::shared_ptr<Storage::Disk::Drive> drives_[4];
|
std::shared_ptr<Storage::Disk::Drive> drives_[4];
|
||||||
int selected_drive_;
|
int selected_drive_;
|
||||||
bool irq_enable_;
|
bool irq_enable_ = false;
|
||||||
int paging_flags_;
|
int paging_flags_ = BASICDisable;
|
||||||
int head_load_request_counter_;
|
int head_load_request_counter_ = -1;
|
||||||
Delegate *delegate_;
|
Delegate *delegate_ = nullptr;
|
||||||
uint8_t last_control_;
|
uint8_t last_control_ = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -182,9 +182,9 @@ class ConcreteMachine:
|
|||||||
public:
|
public:
|
||||||
ConcreteMachine() :
|
ConcreteMachine() :
|
||||||
m6502_(*this),
|
m6502_(*this),
|
||||||
paged_rom_(rom_),
|
via_port_handler_(tape_player_, keyboard_),
|
||||||
via_(via_port_handler_),
|
via_(via_port_handler_),
|
||||||
via_port_handler_(tape_player_, keyboard_) {
|
paged_rom_(rom_) {
|
||||||
set_clock_rate(1000000);
|
set_clock_rate(1000000);
|
||||||
via_port_handler_.set_interrupt_delegate(this);
|
via_port_handler_.set_interrupt_delegate(this);
|
||||||
tape_player_.set_delegate(this);
|
tape_player_.set_delegate(this);
|
||||||
|
@ -21,12 +21,9 @@ namespace {
|
|||||||
|
|
||||||
VideoOutput::VideoOutput(uint8_t *memory) :
|
VideoOutput::VideoOutput(uint8_t *memory) :
|
||||||
ram_(memory),
|
ram_(memory),
|
||||||
frame_counter_(0), counter_(0),
|
crt_(new Outputs::CRT::CRT(64*6, 6, Outputs::CRT::DisplayType::PAL50, 2)),
|
||||||
is_graphics_mode_(false),
|
|
||||||
character_set_base_address_(0xb400),
|
|
||||||
v_sync_start_position_(PAL50VSyncStartPosition), v_sync_end_position_(PAL50VSyncEndPosition),
|
v_sync_start_position_(PAL50VSyncStartPosition), v_sync_end_position_(PAL50VSyncEndPosition),
|
||||||
counter_period_(PAL50Period), next_frame_is_sixty_hertz_(false),
|
counter_period_(PAL50Period) {
|
||||||
crt_(new Outputs::CRT::CRT(64*6, 6, Outputs::CRT::DisplayType::PAL50, 2)) {
|
|
||||||
crt_->set_rgb_sampling_function(
|
crt_->set_rgb_sampling_function(
|
||||||
"vec3 rgb_sample(usampler2D sampler, vec2 coordinate, vec2 icoordinate)"
|
"vec3 rgb_sample(usampler2D sampler, vec2 coordinate, vec2 icoordinate)"
|
||||||
"{"
|
"{"
|
||||||
|
@ -27,7 +27,7 @@ class VideoOutput {
|
|||||||
std::shared_ptr<Outputs::CRT::CRT> crt_;
|
std::shared_ptr<Outputs::CRT::CRT> crt_;
|
||||||
|
|
||||||
// Counters and limits
|
// Counters and limits
|
||||||
int counter_, frame_counter_;
|
int counter_ = 0, frame_counter_ = 0;
|
||||||
int v_sync_start_position_, v_sync_end_position_, counter_period_;
|
int v_sync_start_position_, v_sync_end_position_, counter_period_;
|
||||||
|
|
||||||
// Output target and device
|
// Output target and device
|
||||||
@ -38,11 +38,11 @@ class VideoOutput {
|
|||||||
// Registers
|
// Registers
|
||||||
uint8_t ink_, paper_;
|
uint8_t ink_, paper_;
|
||||||
|
|
||||||
int character_set_base_address_;
|
int character_set_base_address_ = 0xb400;
|
||||||
inline void set_character_set_base_address();
|
inline void set_character_set_base_address();
|
||||||
|
|
||||||
bool is_graphics_mode_;
|
bool is_graphics_mode_ = false;
|
||||||
bool next_frame_is_sixty_hertz_;
|
bool next_frame_is_sixty_hertz_ = false;
|
||||||
bool use_alternative_character_set_;
|
bool use_alternative_character_set_;
|
||||||
bool use_double_height_characters_;
|
bool use_double_height_characters_;
|
||||||
bool blink_text_;
|
bool blink_text_;
|
||||||
|
@ -7,16 +7,16 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#include "Typer.hpp"
|
#include "Typer.hpp"
|
||||||
#include <stdlib.h>
|
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
using namespace Utility;
|
using namespace Utility;
|
||||||
|
|
||||||
Typer::Typer(const char *string, HalfCycles delay, HalfCycles frequency, std::unique_ptr<CharacterMapper> character_mapper, Delegate *delegate) :
|
Typer::Typer(const char *string, HalfCycles delay, HalfCycles frequency, std::unique_ptr<CharacterMapper> character_mapper, Delegate *delegate) :
|
||||||
counter_(-delay),
|
|
||||||
frequency_(frequency),
|
frequency_(frequency),
|
||||||
string_pointer_(0),
|
counter_(-delay),
|
||||||
delegate_(delegate),
|
delegate_(delegate),
|
||||||
phase_(0),
|
|
||||||
character_mapper_(std::move(character_mapper)) {
|
character_mapper_(std::move(character_mapper)) {
|
||||||
size_t string_size = strlen(string) + 3;
|
size_t string_size = strlen(string) + 3;
|
||||||
string_ = (char *)malloc(string_size);
|
string_ = (char *)malloc(string_size);
|
||||||
|
@ -63,11 +63,11 @@ class Typer {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
char *string_;
|
char *string_;
|
||||||
size_t string_pointer_;
|
size_t string_pointer_ = 0;
|
||||||
|
|
||||||
HalfCycles frequency_;
|
HalfCycles frequency_;
|
||||||
HalfCycles counter_;
|
HalfCycles counter_;
|
||||||
int phase_;
|
int phase_ = 0;
|
||||||
|
|
||||||
Delegate *delegate_;
|
Delegate *delegate_;
|
||||||
std::unique_ptr<CharacterMapper> character_mapper_;
|
std::unique_ptr<CharacterMapper> character_mapper_;
|
||||||
|
@ -11,11 +11,7 @@
|
|||||||
using namespace ZX8081;
|
using namespace ZX8081;
|
||||||
|
|
||||||
Video::Video() :
|
Video::Video() :
|
||||||
crt_(new Outputs::CRT::CRT(207 * 2, 1, Outputs::CRT::DisplayType::PAL50, 1)),
|
crt_(new Outputs::CRT::CRT(207 * 2, 1, Outputs::CRT::DisplayType::PAL50, 1)) {
|
||||||
line_data_(nullptr),
|
|
||||||
line_data_pointer_(nullptr),
|
|
||||||
cycles_since_update_(0),
|
|
||||||
sync_(false) {
|
|
||||||
|
|
||||||
// Set a composite sampling function that assumes 8bpp input grayscale.
|
// Set a composite sampling function that assumes 8bpp input grayscale.
|
||||||
// TODO: lessen this to 1bpp.
|
// TODO: lessen this to 1bpp.
|
||||||
|
@ -42,9 +42,10 @@ class Video {
|
|||||||
void output_byte(uint8_t byte);
|
void output_byte(uint8_t byte);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool sync_;
|
bool sync_ = false;
|
||||||
uint8_t *line_data_, *line_data_pointer_;
|
uint8_t *line_data_ = nullptr;
|
||||||
unsigned int cycles_since_update_;
|
uint8_t *line_data_pointer_ = nullptr;
|
||||||
|
unsigned int cycles_since_update_ = 0;
|
||||||
std::shared_ptr<Outputs::CRT::CRT> crt_;
|
std::shared_ptr<Outputs::CRT::CRT> crt_;
|
||||||
|
|
||||||
void flush(bool next_sync);
|
void flush(bool next_sync);
|
||||||
|
@ -36,13 +36,7 @@ template<bool is_zx81> class ConcreteMachine:
|
|||||||
public:
|
public:
|
||||||
ConcreteMachine() :
|
ConcreteMachine() :
|
||||||
z80_(*this),
|
z80_(*this),
|
||||||
vsync_(false),
|
tape_player_(ZX8081ClockRate) {
|
||||||
hsync_(false),
|
|
||||||
nmi_is_enabled_(false),
|
|
||||||
tape_player_(ZX8081ClockRate),
|
|
||||||
use_fast_tape_hack_(false),
|
|
||||||
tape_advance_delay_(0),
|
|
||||||
has_latched_video_byte_(false) {
|
|
||||||
set_clock_rate(ZX8081ClockRate);
|
set_clock_rate(ZX8081ClockRate);
|
||||||
clear_all_keys();
|
clear_all_keys();
|
||||||
}
|
}
|
||||||
@ -367,8 +361,8 @@ template<bool is_zx81> class ConcreteMachine:
|
|||||||
std::vector<uint8_t> rom_;
|
std::vector<uint8_t> rom_;
|
||||||
uint16_t rom_mask_;
|
uint16_t rom_mask_;
|
||||||
|
|
||||||
bool vsync_, hsync_;
|
bool vsync_ = false, hsync_ = false;
|
||||||
int line_counter_;
|
int line_counter_ = 0;
|
||||||
|
|
||||||
uint8_t key_states_[8];
|
uint8_t key_states_[8];
|
||||||
ZX8081::KeyboardMapper keyboard_mapper_;
|
ZX8081::KeyboardMapper keyboard_mapper_;
|
||||||
@ -377,17 +371,17 @@ template<bool is_zx81> class ConcreteMachine:
|
|||||||
Storage::Tape::ZX8081::Parser parser_;
|
Storage::Tape::ZX8081::Parser parser_;
|
||||||
|
|
||||||
bool is_zx81_;
|
bool is_zx81_;
|
||||||
bool nmi_is_enabled_;
|
bool nmi_is_enabled_ = false;
|
||||||
|
|
||||||
HalfCycles vsync_start_, vsync_end_;
|
HalfCycles vsync_start_, vsync_end_;
|
||||||
HalfCycles horizontal_counter_;
|
HalfCycles horizontal_counter_;
|
||||||
|
|
||||||
uint8_t latched_video_byte_;
|
uint8_t latched_video_byte_ = 0;
|
||||||
bool has_latched_video_byte_;
|
bool has_latched_video_byte_ = false;
|
||||||
|
|
||||||
bool use_fast_tape_hack_;
|
bool use_fast_tape_hack_ = false;
|
||||||
bool use_automatic_tape_motor_control_;
|
bool use_automatic_tape_motor_control_;
|
||||||
HalfCycles tape_advance_delay_;
|
HalfCycles tape_advance_delay_ = 0;
|
||||||
|
|
||||||
#pragma mark - Video
|
#pragma mark - Video
|
||||||
|
|
||||||
|
@ -3651,6 +3651,10 @@
|
|||||||
GCC_WARN_SIGN_COMPARE = YES;
|
GCC_WARN_SIGN_COMPARE = YES;
|
||||||
INFOPLIST_FILE = "Clock Signal/Info.plist";
|
INFOPLIST_FILE = "Clock Signal/Info.plist";
|
||||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
|
||||||
|
OTHER_CPLUSPLUSFLAGS = (
|
||||||
|
"$(OTHER_CFLAGS)",
|
||||||
|
"-Wreorder",
|
||||||
|
);
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "TH.Clock-Signal";
|
PRODUCT_BUNDLE_IDENTIFIER = "TH.Clock-Signal";
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Clock Signal/ClockSignal-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Clock Signal/ClockSignal-Bridging-Header.h";
|
||||||
@ -3685,6 +3689,10 @@
|
|||||||
GCC_WARN_SIGN_COMPARE = YES;
|
GCC_WARN_SIGN_COMPARE = YES;
|
||||||
INFOPLIST_FILE = "Clock Signal/Info.plist";
|
INFOPLIST_FILE = "Clock Signal/Info.plist";
|
||||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
|
||||||
|
OTHER_CPLUSPLUSFLAGS = (
|
||||||
|
"$(OTHER_CFLAGS)",
|
||||||
|
"-Wreorder",
|
||||||
|
);
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "TH.Clock-Signal";
|
PRODUCT_BUNDLE_IDENTIFIER = "TH.Clock-Signal";
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Clock Signal/ClockSignal-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Clock Signal/ClockSignal-Bridging-Header.h";
|
||||||
|
77
OSBindings/SDL/SConstruct
Normal file
77
OSBindings/SDL/SConstruct
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
import glob
|
||||||
|
|
||||||
|
# create build environment
|
||||||
|
env = Environment()
|
||||||
|
|
||||||
|
# determine compiler and linker flags for SDL
|
||||||
|
env.ParseConfig('sdl2-config --cflags')
|
||||||
|
env.ParseConfig('sdl2-config --libs')
|
||||||
|
|
||||||
|
# gather a list of source files
|
||||||
|
SOURCES = glob.glob('*.cpp')
|
||||||
|
|
||||||
|
SOURCES += glob.glob('../../Components/1770/*.cpp')
|
||||||
|
SOURCES += glob.glob('../../Components/6522/Implementation/*.cpp')
|
||||||
|
SOURCES += glob.glob('../../Components/6560/*.cpp')
|
||||||
|
SOURCES += glob.glob('../../Components/8272/*.cpp')
|
||||||
|
SOURCES += glob.glob('../../Components/AY38910/*.cpp')
|
||||||
|
|
||||||
|
SOURCES += glob.glob('../../Concurrency/*.cpp')
|
||||||
|
|
||||||
|
SOURCES += glob.glob('../../Inputs/*.cpp')
|
||||||
|
|
||||||
|
SOURCES += glob.glob('../../Machines/*.cpp')
|
||||||
|
SOURCES += glob.glob('../../Machines/AmstradCPC/*.cpp')
|
||||||
|
SOURCES += glob.glob('../../Machines/Atari2600/*.cpp')
|
||||||
|
SOURCES += glob.glob('../../Machines/Commodore/*.cpp')
|
||||||
|
SOURCES += glob.glob('../../Machines/Commodore/1540/Implementation/*.cpp')
|
||||||
|
SOURCES += glob.glob('../../Machines/Commodore/Vic-20/*.cpp')
|
||||||
|
SOURCES += glob.glob('../../Machines/Electron/*.cpp')
|
||||||
|
SOURCES += glob.glob('../../Machines/Oric/*.cpp')
|
||||||
|
SOURCES += glob.glob('../../Machines/Utility/*.cpp')
|
||||||
|
SOURCES += glob.glob('../../Machines/ZX8081/*.cpp')
|
||||||
|
|
||||||
|
SOURCES += glob.glob('../../Outputs/CRT/*.cpp')
|
||||||
|
SOURCES += glob.glob('../../Outputs/CRT/Internals/*.cpp')
|
||||||
|
SOURCES += glob.glob('../../Outputs/CRT/Internals/Shaders/*.cpp')
|
||||||
|
|
||||||
|
SOURCES += glob.glob('../../Processors/6502/Implementation/*.cpp')
|
||||||
|
SOURCES += glob.glob('../../Processors/Z80/Implementation/*.cpp')
|
||||||
|
|
||||||
|
SOURCES += glob.glob('../../SignalProcessing/*.cpp')
|
||||||
|
|
||||||
|
SOURCES += glob.glob('../../StaticAnalyser/*.cpp')
|
||||||
|
SOURCES += glob.glob('../../StaticAnalyser/Acorn/*.cpp')
|
||||||
|
SOURCES += glob.glob('../../StaticAnalyser/AmstradCPC/*.cpp')
|
||||||
|
SOURCES += glob.glob('../../StaticAnalyser/Atari/*.cpp')
|
||||||
|
SOURCES += glob.glob('../../StaticAnalyser/Commodore/*.cpp')
|
||||||
|
SOURCES += glob.glob('../../StaticAnalyser/Disassembler/*.cpp')
|
||||||
|
SOURCES += glob.glob('../../StaticAnalyser/Oric/*.cpp')
|
||||||
|
SOURCES += glob.glob('../../StaticAnalyser/ZX8081/*.cpp')
|
||||||
|
|
||||||
|
SOURCES += glob.glob('../../Storage/*.cpp')
|
||||||
|
SOURCES += glob.glob('../../Storage/Cartridge/*.cpp')
|
||||||
|
SOURCES += glob.glob('../../Storage/Cartridge/Encodings/*.cpp')
|
||||||
|
SOURCES += glob.glob('../../Storage/Cartridge/Formats/*.cpp')
|
||||||
|
SOURCES += glob.glob('../../Storage/Data/*.cpp')
|
||||||
|
SOURCES += glob.glob('../../Storage/Disk/*.cpp')
|
||||||
|
SOURCES += glob.glob('../../Storage/Disk/Controller/*.cpp')
|
||||||
|
SOURCES += glob.glob('../../Storage/Disk/DiskImage/Formats/*.cpp')
|
||||||
|
SOURCES += glob.glob('../../Storage/Disk/DiskImage/Formats/Utility/*.cpp')
|
||||||
|
SOURCES += glob.glob('../../Storage/Disk/DPLL/*.cpp')
|
||||||
|
SOURCES += glob.glob('../../Storage/Disk/Encodings/*.cpp')
|
||||||
|
SOURCES += glob.glob('../../Storage/Disk/Encodings/MFM/*.cpp')
|
||||||
|
SOURCES += glob.glob('../../Storage/Disk/Parsers/*.cpp')
|
||||||
|
SOURCES += glob.glob('../../Storage/Disk/Track/*.cpp')
|
||||||
|
SOURCES += glob.glob('../../Storage/Disk/Data/*.cpp')
|
||||||
|
SOURCES += glob.glob('../../Storage/Tape/*.cpp')
|
||||||
|
SOURCES += glob.glob('../../Storage/Tape/Formats/*.cpp')
|
||||||
|
SOURCES += glob.glob('../../Storage/Tape/Parsers/*.cpp')
|
||||||
|
|
||||||
|
# add additional compiler flags
|
||||||
|
env.Append(CCFLAGS = ['--std=c++11', '-O3'])
|
||||||
|
# add additional libraries to link against
|
||||||
|
env.Append(LIBS = ['libz', 'pthread', 'GL'])
|
||||||
|
|
||||||
|
# build target
|
||||||
|
env.Program(target = 'clksignal', source = SOURCES)
|
@ -7,7 +7,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#include "CRT.hpp"
|
#include "CRT.hpp"
|
||||||
#include "CRTOpenGL.hpp"
|
#include "Internals/CRTOpenGL.hpp"
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@ -343,37 +343,33 @@ void CRT::output_scan(const Scan *const scan) {
|
|||||||
These all merely channel into advance_cycles, supplying appropriate arguments
|
These all merely channel into advance_cycles, supplying appropriate arguments
|
||||||
*/
|
*/
|
||||||
void CRT::output_sync(unsigned int number_of_cycles) {
|
void CRT::output_sync(unsigned int number_of_cycles) {
|
||||||
Scan scan{
|
Scan scan;
|
||||||
.type = Scan::Type::Sync,
|
scan.type = Scan::Type::Sync;
|
||||||
.number_of_cycles = number_of_cycles
|
scan.number_of_cycles = number_of_cycles;
|
||||||
};
|
|
||||||
output_scan(&scan);
|
output_scan(&scan);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CRT::output_blank(unsigned int number_of_cycles) {
|
void CRT::output_blank(unsigned int number_of_cycles) {
|
||||||
Scan scan {
|
Scan scan;
|
||||||
.type = Scan::Type::Blank,
|
scan.type = Scan::Type::Blank;
|
||||||
.number_of_cycles = number_of_cycles
|
scan.number_of_cycles = number_of_cycles;
|
||||||
};
|
|
||||||
output_scan(&scan);
|
output_scan(&scan);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CRT::output_level(unsigned int number_of_cycles) {
|
void CRT::output_level(unsigned int number_of_cycles) {
|
||||||
openGL_output_builder_.texture_builder.reduce_previous_allocation_to(1);
|
openGL_output_builder_.texture_builder.reduce_previous_allocation_to(1);
|
||||||
Scan scan {
|
Scan scan;
|
||||||
.type = Scan::Type::Level,
|
scan.type = Scan::Type::Level;
|
||||||
.number_of_cycles = number_of_cycles,
|
scan.number_of_cycles = number_of_cycles;
|
||||||
};
|
|
||||||
output_scan(&scan);
|
output_scan(&scan);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CRT::output_colour_burst(unsigned int number_of_cycles, uint8_t phase, uint8_t amplitude) {
|
void CRT::output_colour_burst(unsigned int number_of_cycles, uint8_t phase, uint8_t amplitude) {
|
||||||
Scan scan {
|
Scan scan;
|
||||||
.type = Scan::Type::ColourBurst,
|
scan.type = Scan::Type::ColourBurst;
|
||||||
.number_of_cycles = number_of_cycles,
|
scan.number_of_cycles = number_of_cycles;
|
||||||
.phase = phase,
|
scan.phase = phase;
|
||||||
.amplitude = amplitude
|
scan.amplitude = amplitude;
|
||||||
};
|
|
||||||
output_scan(&scan);
|
output_scan(&scan);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -383,10 +379,9 @@ void CRT::output_default_colour_burst(unsigned int number_of_cycles) {
|
|||||||
|
|
||||||
void CRT::output_data(unsigned int number_of_cycles, unsigned int source_divider) {
|
void CRT::output_data(unsigned int number_of_cycles, unsigned int source_divider) {
|
||||||
openGL_output_builder_.texture_builder.reduce_previous_allocation_to(number_of_cycles / source_divider);
|
openGL_output_builder_.texture_builder.reduce_previous_allocation_to(number_of_cycles / source_divider);
|
||||||
Scan scan {
|
Scan scan;
|
||||||
.type = Scan::Type::Data,
|
scan.type = Scan::Type::Data;
|
||||||
.number_of_cycles = number_of_cycles,
|
scan.number_of_cycles = number_of_cycles;
|
||||||
};
|
|
||||||
output_scan(&scan);
|
output_scan(&scan);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ struct Rect {
|
|||||||
|
|
||||||
Rect() {}
|
Rect() {}
|
||||||
Rect(float x, float y, float width, float height) :
|
Rect(float x, float y, float width, float height) :
|
||||||
origin({.x = x, .y = y}), size({.width = width, .height = height}) {}
|
origin({x, y}), size({width, height}) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
enum DisplayType {
|
enum DisplayType {
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
|
|
||||||
#include "ArrayBuilder.hpp"
|
#include "ArrayBuilder.hpp"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
using namespace Outputs::CRT;
|
using namespace Outputs::CRT;
|
||||||
|
|
||||||
ArrayBuilder::ArrayBuilder(size_t input_size, size_t output_size) :
|
ArrayBuilder::ArrayBuilder(size_t input_size, size_t output_size) :
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
// Copyright © 2016 Thomas Harte. All rights reserved.
|
// Copyright © 2016 Thomas Harte. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "CRT.hpp"
|
#include "../CRT.hpp"
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
#include "CRTConstants.hpp"
|
#include "CRTConstants.hpp"
|
||||||
#include "OpenGL.hpp"
|
#include "OpenGL.hpp"
|
||||||
#include "TextureTarget.hpp"
|
#include "TextureTarget.hpp"
|
||||||
#include "Shader.hpp"
|
#include "Shaders/Shader.hpp"
|
||||||
|
|
||||||
#include "ArrayBuilder.hpp"
|
#include "ArrayBuilder.hpp"
|
||||||
#include "TextureBuilder.hpp"
|
#include "TextureBuilder.hpp"
|
||||||
|
@ -34,8 +34,8 @@ struct Flywheel {
|
|||||||
retrace_time_(retrace_time),
|
retrace_time_(retrace_time),
|
||||||
sync_error_window_(sync_error_window),
|
sync_error_window_(sync_error_window),
|
||||||
counter_(0),
|
counter_(0),
|
||||||
expected_next_sync_(standard_period),
|
|
||||||
counter_before_retrace_(standard_period - retrace_time),
|
counter_before_retrace_(standard_period - retrace_time),
|
||||||
|
expected_next_sync_(standard_period),
|
||||||
number_of_surprises_(0) {}
|
number_of_surprises_(0) {}
|
||||||
|
|
||||||
enum SyncEvent {
|
enum SyncEvent {
|
||||||
|
@ -17,6 +17,9 @@
|
|||||||
#include <OpenGL/gl3.h>
|
#include <OpenGL/gl3.h>
|
||||||
#include <OpenGL/gl3ext.h>
|
#include <OpenGL/gl3ext.h>
|
||||||
#endif
|
#endif
|
||||||
|
#else
|
||||||
|
#define GL_GLEXT_PROTOTYPES
|
||||||
|
#include <GL/gl.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* OpenGL_h */
|
#endif /* OpenGL_h */
|
||||||
|
@ -8,9 +8,11 @@
|
|||||||
|
|
||||||
#include "IntermediateShader.hpp"
|
#include "IntermediateShader.hpp"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
#include <stdlib.h>
|
#include <cstdlib>
|
||||||
#include <math.h>
|
#include <cstring>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
#include "../../../../SignalProcessing/FIRFilter.hpp"
|
#include "../../../../SignalProcessing/FIRFilter.hpp"
|
||||||
|
|
||||||
using namespace OpenGL;
|
using namespace OpenGL;
|
||||||
|
@ -8,7 +8,8 @@
|
|||||||
|
|
||||||
#include "Shader.hpp"
|
#include "Shader.hpp"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
using namespace OpenGL;
|
using namespace OpenGL;
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
#ifndef Shader_hpp
|
#ifndef Shader_hpp
|
||||||
#define Shader_hpp
|
#define Shader_hpp
|
||||||
|
|
||||||
#include "OpenGL.hpp"
|
#include "../OpenGL.hpp"
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -51,12 +51,7 @@ struct DefaultBookender: public TextureBuilder::Bookender {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TextureBuilder::TextureBuilder(size_t bytes_per_pixel, GLenum texture_unit) :
|
TextureBuilder::TextureBuilder(size_t bytes_per_pixel, GLenum texture_unit) :
|
||||||
bytes_per_pixel_(bytes_per_pixel),
|
bytes_per_pixel_(bytes_per_pixel) {
|
||||||
write_areas_start_x_(0),
|
|
||||||
write_areas_start_y_(0),
|
|
||||||
first_unsubmitted_y_(0),
|
|
||||||
is_full_(false),
|
|
||||||
number_of_write_areas_(0) {
|
|
||||||
image_.resize(bytes_per_pixel * InputBufferBuilderWidth * InputBufferBuilderHeight);
|
image_.resize(bytes_per_pixel * InputBufferBuilderWidth * InputBufferBuilderHeight);
|
||||||
glGenTextures(1, &texture_name_);
|
glGenTextures(1, &texture_name_);
|
||||||
|
|
||||||
|
@ -127,15 +127,15 @@ class TextureBuilder {
|
|||||||
|
|
||||||
// the list of write areas that have ascended to the flush queue
|
// the list of write areas that have ascended to the flush queue
|
||||||
std::vector<WriteArea> write_areas_;
|
std::vector<WriteArea> write_areas_;
|
||||||
size_t number_of_write_areas_;
|
size_t number_of_write_areas_ = 0;
|
||||||
bool is_full_, was_full_;
|
bool is_full_ = false, was_full_ = false;
|
||||||
uint16_t first_unsubmitted_y_;
|
uint16_t first_unsubmitted_y_ = 0;
|
||||||
inline uint8_t *pointer_to_location(uint16_t x, uint16_t y);
|
inline uint8_t *pointer_to_location(uint16_t x, uint16_t y);
|
||||||
|
|
||||||
// Usually: the start position for the current batch of write areas.
|
// Usually: the start position for the current batch of write areas.
|
||||||
// Caveat: reset to the origin upon a submit. So used in comparison by flush to
|
// Caveat: reset to the origin upon a submit. So used in comparison by flush to
|
||||||
// determine whether the current batch of write areas needs to be relocated.
|
// determine whether the current batch of write areas needs to be relocated.
|
||||||
uint16_t write_areas_start_x_, write_areas_start_y_;
|
uint16_t write_areas_start_x_ = 0, write_areas_start_y_ = 0;
|
||||||
|
|
||||||
std::unique_ptr<Bookender> bookender_;
|
std::unique_ptr<Bookender> bookender_;
|
||||||
};
|
};
|
||||||
|
@ -15,11 +15,8 @@ using namespace OpenGL;
|
|||||||
TextureTarget::TextureTarget(GLsizei width, GLsizei height, GLenum texture_unit, GLint mag_filter) :
|
TextureTarget::TextureTarget(GLsizei width, GLsizei height, GLenum texture_unit, GLint mag_filter) :
|
||||||
_width(width),
|
_width(width),
|
||||||
_height(height),
|
_height(height),
|
||||||
_pixel_shader(nullptr),
|
_texture_unit(texture_unit),
|
||||||
_drawing_vertex_array(0),
|
_set_aspect_ratio(0.0f) {
|
||||||
_drawing_array_buffer(0),
|
|
||||||
_set_aspect_ratio(0.0f),
|
|
||||||
_texture_unit(texture_unit) {
|
|
||||||
glGenFramebuffers(1, &_framebuffer);
|
glGenFramebuffers(1, &_framebuffer);
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, _framebuffer);
|
glBindFramebuffer(GL_FRAMEBUFFER, _framebuffer);
|
||||||
|
|
||||||
|
@ -73,7 +73,7 @@ class TextureTarget {
|
|||||||
GLenum _texture_unit;
|
GLenum _texture_unit;
|
||||||
|
|
||||||
std::unique_ptr<Shader> _pixel_shader;
|
std::unique_ptr<Shader> _pixel_shader;
|
||||||
GLuint _drawing_vertex_array, _drawing_array_buffer;
|
GLuint _drawing_vertex_array = 0, _drawing_array_buffer = 0;
|
||||||
float _set_aspect_ratio;
|
float _set_aspect_ratio;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -9,8 +9,10 @@
|
|||||||
#ifndef Speaker_hpp
|
#ifndef Speaker_hpp
|
||||||
#define Speaker_hpp
|
#define Speaker_hpp
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@ -81,7 +83,7 @@ class Speaker {
|
|||||||
set_needs_updated_filter_coefficients();
|
set_needs_updated_filter_coefficients();
|
||||||
}
|
}
|
||||||
|
|
||||||
Speaker() : buffer_in_progress_pointer_(0), requested_number_of_taps_(0), high_frequency_cut_off_(-1.0), _queue(new Concurrency::AsyncTaskQueue) {}
|
Speaker() : _queue(new Concurrency::AsyncTaskQueue) {}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Ensures any deferred processing occurs now.
|
Ensures any deferred processing occurs now.
|
||||||
@ -105,9 +107,10 @@ class Speaker {
|
|||||||
std::shared_ptr<std::list<std::function<void(void)>>> queued_functions_;
|
std::shared_ptr<std::list<std::function<void(void)>>> queued_functions_;
|
||||||
|
|
||||||
std::vector<int16_t> buffer_in_progress_;
|
std::vector<int16_t> buffer_in_progress_;
|
||||||
float high_frequency_cut_off_;
|
float high_frequency_cut_off_ = -1.0;
|
||||||
size_t buffer_in_progress_pointer_;
|
size_t buffer_in_progress_pointer_ = 0;
|
||||||
size_t number_of_taps_, requested_number_of_taps_;
|
size_t number_of_taps_;
|
||||||
|
size_t requested_number_of_taps_ = 0;
|
||||||
bool coefficients_are_dirty_;
|
bool coefficients_are_dirty_;
|
||||||
Delegate *delegate_ = nullptr;
|
Delegate *delegate_ = nullptr;
|
||||||
|
|
||||||
|
@ -244,19 +244,7 @@ const ProcessorStorage::MicroOp ProcessorStorage::operations[256][10] = {
|
|||||||
#undef Immediate
|
#undef Immediate
|
||||||
#undef Implied
|
#undef Implied
|
||||||
|
|
||||||
ProcessorStorage::ProcessorStorage() :
|
ProcessorStorage::ProcessorStorage() {
|
||||||
is_jammed_(false),
|
|
||||||
ready_line_is_enabled_(false),
|
|
||||||
ready_is_active_(false),
|
|
||||||
inverse_interrupt_flag_(0),
|
|
||||||
irq_request_history_(0),
|
|
||||||
s_(0),
|
|
||||||
next_bus_operation_(BusOperation::None),
|
|
||||||
interrupt_requests_(InterruptRequestFlags::PowerOn),
|
|
||||||
irq_line_(0),
|
|
||||||
nmi_line_is_enabled_(false),
|
|
||||||
set_overflow_line_is_enabled_(false),
|
|
||||||
scheduled_program_counter_(nullptr) {
|
|
||||||
// only the interrupt flag is defined upon reset but get_flags isn't going to
|
// only the interrupt flag is defined upon reset but get_flags isn't going to
|
||||||
// mask the other flags so we need to do that, at least
|
// mask the other flags so we need to do that, at least
|
||||||
carry_flag_ &= Flag::Carry;
|
carry_flag_ &= Flag::Carry;
|
||||||
|
@ -64,14 +64,14 @@ class ProcessorStorage {
|
|||||||
|
|
||||||
static const MicroOp operations[256][10];
|
static const MicroOp operations[256][10];
|
||||||
|
|
||||||
const MicroOp *scheduled_program_counter_;
|
const MicroOp *scheduled_program_counter_ = nullptr;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Storage for the 6502 registers; F is stored as individual flags.
|
Storage for the 6502 registers; F is stored as individual flags.
|
||||||
*/
|
*/
|
||||||
RegisterPair pc_, last_operation_pc_;
|
RegisterPair pc_, last_operation_pc_;
|
||||||
uint8_t a_, x_, y_, s_;
|
uint8_t a_, x_, y_, s_ = 0;
|
||||||
uint8_t carry_flag_, negative_result_, zero_result_, decimal_flag_, overflow_flag_, inverse_interrupt_flag_;
|
uint8_t carry_flag_, negative_result_, zero_result_, decimal_flag_, overflow_flag_, inverse_interrupt_flag_ = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Temporary state for the micro programs.
|
Temporary state for the micro programs.
|
||||||
@ -83,7 +83,7 @@ class ProcessorStorage {
|
|||||||
Temporary storage allowing a common dispatch point for calling perform_bus_operation;
|
Temporary storage allowing a common dispatch point for calling perform_bus_operation;
|
||||||
possibly deferring is no longer of value.
|
possibly deferring is no longer of value.
|
||||||
*/
|
*/
|
||||||
BusOperation next_bus_operation_;
|
BusOperation next_bus_operation_ = BusOperation::None;
|
||||||
uint16_t bus_address_;
|
uint16_t bus_address_;
|
||||||
uint8_t *bus_value_;
|
uint8_t *bus_value_;
|
||||||
|
|
||||||
@ -105,7 +105,7 @@ class ProcessorStorage {
|
|||||||
*/
|
*/
|
||||||
inline void set_flags(uint8_t flags);
|
inline void set_flags(uint8_t flags);
|
||||||
|
|
||||||
bool is_jammed_;
|
bool is_jammed_ = false;
|
||||||
Cycles cycles_left_to_run_;
|
Cycles cycles_left_to_run_;
|
||||||
|
|
||||||
enum InterruptRequestFlags: uint8_t {
|
enum InterruptRequestFlags: uint8_t {
|
||||||
@ -115,13 +115,13 @@ class ProcessorStorage {
|
|||||||
|
|
||||||
PowerOn = 0x10,
|
PowerOn = 0x10,
|
||||||
};
|
};
|
||||||
uint8_t interrupt_requests_;
|
uint8_t interrupt_requests_ = InterruptRequestFlags::PowerOn;
|
||||||
|
|
||||||
bool ready_is_active_;
|
bool ready_is_active_ = false;
|
||||||
bool ready_line_is_enabled_;
|
bool ready_line_is_enabled_ = false;
|
||||||
|
|
||||||
uint8_t irq_line_, irq_request_history_;
|
uint8_t irq_line_ = 0, irq_request_history_ = 0;
|
||||||
bool nmi_line_is_enabled_, set_overflow_line_is_enabled_;
|
bool nmi_line_is_enabled_ = false, set_overflow_line_is_enabled_ = false;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Gets the program representing an RST response.
|
Gets the program representing an RST response.
|
||||||
|
@ -849,7 +849,6 @@ template < class T,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case MicroOp::IndexedPlaceHolder:
|
case MicroOp::IndexedPlaceHolder:
|
||||||
printf("Hit placeholder!!!\n");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#undef set_parity
|
#undef set_parity
|
||||||
|
@ -7,20 +7,11 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#include "../Z80.hpp"
|
#include "../Z80.hpp"
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
using namespace CPU::Z80;
|
using namespace CPU::Z80;
|
||||||
|
|
||||||
ProcessorStorage::ProcessorStorage() :
|
ProcessorStorage::ProcessorStorage() {
|
||||||
halt_mask_(0xff),
|
|
||||||
interrupt_mode_(0),
|
|
||||||
wait_line_(false),
|
|
||||||
request_status_(Interrupt::PowerOn),
|
|
||||||
last_request_status_(Interrupt::PowerOn),
|
|
||||||
irq_line_(false),
|
|
||||||
nmi_line_(false),
|
|
||||||
bus_request_line_(false),
|
|
||||||
pc_increment_(1),
|
|
||||||
scheduled_program_counter_(nullptr) {
|
|
||||||
set_flags(0xff);
|
set_flags(0xff);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,8 +121,8 @@ class ProcessorStorage {
|
|||||||
RegisterPair ix_, iy_, pc_, sp_;
|
RegisterPair ix_, iy_, pc_, sp_;
|
||||||
RegisterPair ir_, refresh_addr_;
|
RegisterPair ir_, refresh_addr_;
|
||||||
bool iff1_, iff2_;
|
bool iff1_, iff2_;
|
||||||
int interrupt_mode_;
|
int interrupt_mode_ = 0;
|
||||||
uint16_t pc_increment_;
|
uint16_t pc_increment_ = 1;
|
||||||
uint8_t sign_result_; // the sign flag is set if the value in sign_result_ is negative
|
uint8_t sign_result_; // the sign flag is set if the value in sign_result_ is negative
|
||||||
uint8_t zero_result_; // the zero flag is set if the value in zero_result_ is zero
|
uint8_t zero_result_; // the zero flag is set if the value in zero_result_ is zero
|
||||||
uint8_t half_carry_result_; // the half-carry flag is set if bit 4 of half_carry_result_ is set
|
uint8_t half_carry_result_; // the half-carry flag is set if bit 4 of half_carry_result_ is set
|
||||||
@ -130,7 +130,7 @@ class ProcessorStorage {
|
|||||||
uint8_t parity_overflow_result_; // the parity/overflow flag is set if the corresponding bit of parity_overflow_result_ is set
|
uint8_t parity_overflow_result_; // the parity/overflow flag is set if the corresponding bit of parity_overflow_result_ is set
|
||||||
uint8_t subtract_flag_; // contains a copy of the subtract flag in isolation
|
uint8_t subtract_flag_; // contains a copy of the subtract flag in isolation
|
||||||
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_;
|
uint8_t halt_mask_ = 0xff;
|
||||||
|
|
||||||
HalfCycles number_of_cycles_;
|
HalfCycles number_of_cycles_;
|
||||||
|
|
||||||
@ -140,17 +140,17 @@ class ProcessorStorage {
|
|||||||
Reset = 0x04,
|
Reset = 0x04,
|
||||||
PowerOn = 0x08
|
PowerOn = 0x08
|
||||||
};
|
};
|
||||||
uint8_t request_status_;
|
uint8_t request_status_ = Interrupt::PowerOn;
|
||||||
uint8_t last_request_status_;
|
uint8_t last_request_status_ = Interrupt::PowerOn;
|
||||||
bool irq_line_, nmi_line_;
|
bool irq_line_ = false, nmi_line_ = false;
|
||||||
bool bus_request_line_;
|
bool bus_request_line_ = false;
|
||||||
bool wait_line_;
|
bool wait_line_ = false;
|
||||||
|
|
||||||
uint8_t operation_;
|
uint8_t operation_;
|
||||||
RegisterPair temp16_, memptr_;
|
RegisterPair temp16_, memptr_;
|
||||||
uint8_t temp8_;
|
uint8_t temp8_;
|
||||||
|
|
||||||
const MicroOp *scheduled_program_counter_;
|
const MicroOp *scheduled_program_counter_ = nullptr;
|
||||||
|
|
||||||
std::vector<MicroOp> conditional_call_untaken_program_;
|
std::vector<MicroOp> conditional_call_untaken_program_;
|
||||||
std::vector<MicroOp> reset_program_;
|
std::vector<MicroOp> reset_program_;
|
||||||
|
@ -31,11 +31,6 @@ using namespace SignalProcessing;
|
|||||||
"DIGITAL SIGNAL PROCESSING, II", IEEE Press, pages 123–126.
|
"DIGITAL SIGNAL PROCESSING, II", IEEE Press, pages 123–126.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
// our little fixed point scheme
|
|
||||||
#define kCSKaiserBesselFilterFixedMultiplier 32767.0f
|
|
||||||
#define kCSKaiserBesselFilterFixedShift 15
|
|
||||||
|
|
||||||
/*! Evaluates the 0th order Bessel function at @c a. */
|
/*! Evaluates the 0th order Bessel function at @c a. */
|
||||||
float FIRFilter::ino(float a) {
|
float FIRFilter::ino(float a) {
|
||||||
float d = 0.0f;
|
float d = 0.0f;
|
||||||
|
@ -34,6 +34,10 @@
|
|||||||
namespace SignalProcessing {
|
namespace SignalProcessing {
|
||||||
|
|
||||||
class FIRFilter {
|
class FIRFilter {
|
||||||
|
private:
|
||||||
|
static constexpr float kCSKaiserBesselFilterFixedMultiplier = 32767.0f;
|
||||||
|
static constexpr int kCSKaiserBesselFilterFixedShift = 15;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/*!
|
/*!
|
||||||
Creates an instance of @c FIRFilter.
|
Creates an instance of @c FIRFilter.
|
||||||
|
@ -87,10 +87,10 @@ class Stepper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint64_t whole_step_;
|
|
||||||
int64_t adjustment_up_, adjustment_down_;
|
|
||||||
int64_t accumulated_error_;
|
int64_t accumulated_error_;
|
||||||
uint64_t input_rate_, output_rate_;
|
uint64_t input_rate_, output_rate_;
|
||||||
|
uint64_t whole_step_;
|
||||||
|
int64_t adjustment_up_, adjustment_down_;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -8,13 +8,16 @@
|
|||||||
|
|
||||||
#include "StaticAnalyser.hpp"
|
#include "StaticAnalyser.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
#include "../../Storage/Disk/Parsers/CPM.hpp"
|
#include "../../Storage/Disk/Parsers/CPM.hpp"
|
||||||
#include "../../Storage/Disk/Encodings/MFM/Parser.hpp"
|
#include "../../Storage/Disk/Encodings/MFM/Parser.hpp"
|
||||||
|
|
||||||
static bool strcmp_insensitive(const char *a, const char *b) {
|
static bool strcmp_insensitive(const char *a, const char *b) {
|
||||||
if(strlen(a) != strlen(b)) return false;
|
if(strlen(a) != strlen(b)) return false;
|
||||||
while(*a) {
|
while(*a) {
|
||||||
if(tolower(*a) != towlower(*b)) return false;
|
if(tolower(*a) != tolower(*b)) return false;
|
||||||
a++;
|
a++;
|
||||||
b++;
|
b++;
|
||||||
}
|
}
|
||||||
|
@ -16,14 +16,12 @@ namespace StaticAnalyser {
|
|||||||
namespace Commodore {
|
namespace Commodore {
|
||||||
|
|
||||||
struct File {
|
struct File {
|
||||||
File() : is_closed(false), is_locked(false) {}
|
|
||||||
|
|
||||||
std::wstring name;
|
std::wstring name;
|
||||||
std::vector<uint8_t> raw_name;
|
std::vector<uint8_t> raw_name;
|
||||||
uint16_t starting_address;
|
uint16_t starting_address;
|
||||||
uint16_t ending_address;
|
uint16_t ending_address;
|
||||||
bool is_locked;
|
bool is_locked = false;
|
||||||
bool is_closed;
|
bool is_closed = false;
|
||||||
enum {
|
enum {
|
||||||
RelocatableProgram,
|
RelocatableProgram,
|
||||||
NonRelocatableProgram,
|
NonRelocatableProgram,
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include "StaticAnalyser.hpp"
|
#include "StaticAnalyser.hpp"
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
// Analysers
|
// Analysers
|
||||||
#include "Acorn/StaticAnalyser.hpp"
|
#include "Acorn/StaticAnalyser.hpp"
|
||||||
|
@ -9,9 +9,10 @@
|
|||||||
#ifndef Storage_Data_ZX8081_hpp
|
#ifndef Storage_Data_ZX8081_hpp
|
||||||
#define Storage_Data_ZX8081_hpp
|
#define Storage_Data_ZX8081_hpp
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
namespace Storage {
|
namespace Storage {
|
||||||
namespace Data {
|
namespace Data {
|
||||||
|
@ -14,9 +14,8 @@ using namespace Storage::Disk;
|
|||||||
|
|
||||||
MFMController::MFMController(Cycles clock_rate) :
|
MFMController::MFMController(Cycles clock_rate) :
|
||||||
Storage::Disk::Controller(clock_rate),
|
Storage::Disk::Controller(clock_rate),
|
||||||
crc_generator_(0x1021, 0xffff),
|
shifter_(&crc_generator_),
|
||||||
data_mode_(DataMode::Scanning),
|
crc_generator_(0x1021, 0xffff) {
|
||||||
shifter_(&crc_generator_) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MFMController::process_index_hole() {
|
void MFMController::process_index_hole() {
|
||||||
|
@ -157,7 +157,7 @@ class MFMController: public Controller {
|
|||||||
|
|
||||||
// input configuration
|
// input configuration
|
||||||
bool is_double_density_;
|
bool is_double_density_;
|
||||||
DataMode data_mode_;
|
DataMode data_mode_ = DataMode::Scanning;
|
||||||
|
|
||||||
// writing
|
// writing
|
||||||
int last_bit_;
|
int last_bit_;
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include "D64.hpp"
|
#include "D64.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <cstring>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#include "../../Track/PCMTrack.hpp"
|
#include "../../Track/PCMTrack.hpp"
|
||||||
|
@ -8,7 +8,9 @@
|
|||||||
|
|
||||||
#include "G64.hpp"
|
#include "G64.hpp"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "../../Track/PCMTrack.hpp"
|
#include "../../Track/PCMTrack.hpp"
|
||||||
#include "../../Encodings/CommodoreGCR.hpp"
|
#include "../../Encodings/CommodoreGCR.hpp"
|
||||||
|
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
|
|
||||||
#include "SSD.hpp"
|
#include "SSD.hpp"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
#include "Utility/ImplicitSectors.hpp"
|
#include "Utility/ImplicitSectors.hpp"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
|
|
||||||
#include "ImplicitSectors.hpp"
|
#include "ImplicitSectors.hpp"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
#include "../../../Encodings/MFM/Sector.hpp"
|
#include "../../../Encodings/MFM/Sector.hpp"
|
||||||
#include "../../../Encodings/MFM/Encoder.hpp"
|
#include "../../../Encodings/MFM/Encoder.hpp"
|
||||||
#include "../../../Encodings/MFM/Constants.hpp"
|
#include "../../../Encodings/MFM/Constants.hpp"
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
#include "Drive.hpp"
|
#include "Drive.hpp"
|
||||||
|
|
||||||
#include "UnformattedTrack.hpp"
|
#include "Track/UnformattedTrack.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
@ -10,7 +10,9 @@
|
|||||||
#define Storage_Disk_Encodings_MFM_hpp
|
#define Storage_Disk_Encodings_MFM_hpp
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "Sector.hpp"
|
#include "Sector.hpp"
|
||||||
#include "../../Track/Track.hpp"
|
#include "../../Track/Track.hpp"
|
||||||
#include "../../../../NumberTheory/CRC.hpp"
|
#include "../../../../NumberTheory/CRC.hpp"
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
using namespace Storage::Encodings::MFM;
|
using namespace Storage::Encodings::MFM;
|
||||||
|
|
||||||
Parser::Parser(bool is_mfm, const std::shared_ptr<Storage::Disk::Disk> &disk) :
|
Parser::Parser(bool is_mfm, const std::shared_ptr<Storage::Disk::Disk> &disk) :
|
||||||
is_mfm_(is_mfm), disk_(disk) {}
|
disk_(disk), is_mfm_(is_mfm) {}
|
||||||
|
|
||||||
void Parser::install_sectors_from_track(const Storage::Disk::Track::Address &address) {
|
void Parser::install_sectors_from_track(const Storage::Disk::Track::Address &address) {
|
||||||
if(sectors_by_address_by_track_.find(address) != sectors_by_address_by_track_.end()) {
|
if(sectors_by_address_by_track_.find(address) != sectors_by_address_by_track_.end()) {
|
||||||
|
@ -8,6 +8,9 @@
|
|||||||
|
|
||||||
#include "CPM.hpp"
|
#include "CPM.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
#include "../Encodings/MFM/Parser.hpp"
|
#include "../Encodings/MFM/Parser.hpp"
|
||||||
|
|
||||||
using namespace Storage::Disk::CPM;
|
using namespace Storage::Disk::CPM;
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#define PCMSegment_hpp
|
#define PCMSegment_hpp
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "../../Storage.hpp"
|
#include "../../Storage.hpp"
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include "FileHolder.hpp"
|
#include "FileHolder.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
using namespace Storage;
|
using namespace Storage;
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
using namespace Storage::Tape;
|
using namespace Storage::Tape;
|
||||||
|
|
||||||
CommodoreTAP::CommodoreTAP(const char *file_name) :
|
CommodoreTAP::CommodoreTAP(const char *file_name) :
|
||||||
is_at_end_(false),
|
|
||||||
file_(file_name)
|
file_(file_name)
|
||||||
{
|
{
|
||||||
if(!file_.check_signature("C64-TAPE-RAW"))
|
if(!file_.check_signature("C64-TAPE-RAW"))
|
||||||
|
@ -44,7 +44,7 @@ class CommodoreTAP: public Tape {
|
|||||||
uint32_t file_size_;
|
uint32_t file_size_;
|
||||||
|
|
||||||
Pulse current_pulse_;
|
Pulse current_pulse_;
|
||||||
bool is_at_end_;
|
bool is_at_end_ = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -300,12 +300,14 @@ void TZX::ignore_group_end() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TZX::ignore_jump_to_block() {
|
void TZX::ignore_jump_to_block() {
|
||||||
__unused uint16_t target = file_.get16le();
|
uint16_t target = file_.get16le();
|
||||||
|
(void)target;
|
||||||
printf("Ignoring TZX jump\n");
|
printf("Ignoring TZX jump\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void TZX::ignore_loop_start() {
|
void TZX::ignore_loop_start() {
|
||||||
__unused uint16_t number_of_repetitions = file_.get16le();
|
uint16_t number_of_repetitions = file_.get16le();
|
||||||
|
(void)number_of_repetitions;
|
||||||
printf("Ignoring TZX loop\n");
|
printf("Ignoring TZX loop\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -313,7 +315,7 @@ void TZX::ignore_loop_end() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TZX::ignore_call_sequence() {
|
void TZX::ignore_call_sequence() {
|
||||||
__unused uint16_t number_of_entries = file_.get16le();
|
uint16_t number_of_entries = file_.get16le();
|
||||||
file_.seek(number_of_entries * sizeof(uint16_t), SEEK_CUR);
|
file_.seek(number_of_entries * sizeof(uint16_t), SEEK_CUR);
|
||||||
printf("Ignoring TZX call sequence\n");
|
printf("Ignoring TZX call sequence\n");
|
||||||
}
|
}
|
||||||
@ -323,7 +325,7 @@ void TZX::ignore_return_from_sequence() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TZX::ignore_select_block() {
|
void TZX::ignore_select_block() {
|
||||||
__unused uint16_t length_of_block = file_.get16le();
|
uint16_t length_of_block = file_.get16le();
|
||||||
file_.seek(length_of_block, SEEK_CUR);
|
file_.seek(length_of_block, SEEK_CUR);
|
||||||
printf("Ignoring TZX select block\n");
|
printf("Ignoring TZX select block\n");
|
||||||
}
|
}
|
||||||
@ -337,9 +339,10 @@ void TZX::ignore_text_description() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TZX::ignore_message_block() {
|
void TZX::ignore_message_block() {
|
||||||
__unused uint8_t time_for_display = file_.get8();
|
uint8_t time_for_display = file_.get8();
|
||||||
uint8_t length = file_.get8();
|
uint8_t length = file_.get8();
|
||||||
file_.seek(length, SEEK_CUR);
|
file_.seek(length, SEEK_CUR);
|
||||||
|
(void)time_for_display;
|
||||||
printf("Ignoring TZX message\n");
|
printf("Ignoring TZX message\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,10 +49,6 @@
|
|||||||
using namespace Storage::Tape;
|
using namespace Storage::Tape;
|
||||||
|
|
||||||
PRG::PRG(const char *file_name) :
|
PRG::PRG(const char *file_name) :
|
||||||
bit_phase_(3),
|
|
||||||
file_phase_(FilePhaseLeadIn),
|
|
||||||
phase_offset_(0),
|
|
||||||
copy_mask_(0x80),
|
|
||||||
file_(file_name)
|
file_(file_name)
|
||||||
{
|
{
|
||||||
// There's really no way to validate other than that if this file is larger than 64kb,
|
// There's really no way to validate other than that if this file is larger than 64kb,
|
||||||
|
@ -50,10 +50,10 @@ class PRG: public Tape {
|
|||||||
FilePhaseHeaderDataGap,
|
FilePhaseHeaderDataGap,
|
||||||
FilePhaseData,
|
FilePhaseData,
|
||||||
FilePhaseAtEnd
|
FilePhaseAtEnd
|
||||||
} file_phase_;
|
} file_phase_ = FilePhaseLeadIn;
|
||||||
int phase_offset_;
|
int phase_offset_ = 0;
|
||||||
|
|
||||||
int bit_phase_;
|
int bit_phase_ = 3;
|
||||||
enum OutputToken {
|
enum OutputToken {
|
||||||
Leader,
|
Leader,
|
||||||
Zero,
|
Zero,
|
||||||
@ -65,7 +65,7 @@ class PRG: public Tape {
|
|||||||
void get_next_output_token();
|
void get_next_output_token();
|
||||||
uint8_t output_byte_;
|
uint8_t output_byte_;
|
||||||
uint8_t check_digit_;
|
uint8_t check_digit_;
|
||||||
uint8_t copy_mask_;
|
uint8_t copy_mask_ = 0x80;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -68,10 +68,7 @@ static int gzget32(gzFile file) {
|
|||||||
|
|
||||||
using namespace Storage::Tape;
|
using namespace Storage::Tape;
|
||||||
|
|
||||||
UEF::UEF(const char *file_name) :
|
UEF::UEF(const char *file_name) {
|
||||||
time_base_(1200),
|
|
||||||
is_300_baud_(false),
|
|
||||||
platform_type_(TargetPlatform::Acorn) {
|
|
||||||
file_ = gzopen(file_name, "rb");
|
file_ = gzopen(file_name, "rb");
|
||||||
|
|
||||||
char identifier[10];
|
char identifier[10];
|
||||||
|
@ -41,11 +41,11 @@ class UEF : public PulseQueuedTape, public TargetPlatform::TypeDistinguisher {
|
|||||||
|
|
||||||
void set_platform_type();
|
void set_platform_type();
|
||||||
TargetPlatform::Type target_platform_type();
|
TargetPlatform::Type target_platform_type();
|
||||||
TargetPlatform::Type platform_type_;
|
TargetPlatform::Type platform_type_ = TargetPlatform::Acorn;
|
||||||
|
|
||||||
gzFile file_;
|
gzFile file_;
|
||||||
unsigned int time_base_;
|
unsigned int time_base_ = 1200;
|
||||||
bool is_300_baud_;
|
bool is_300_baud_ = false;
|
||||||
|
|
||||||
struct Chunk {
|
struct Chunk {
|
||||||
uint16_t id;
|
uint16_t id;
|
||||||
|
@ -7,15 +7,14 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#include "Commodore.hpp"
|
#include "Commodore.hpp"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
#include "../../Data/Commodore.hpp"
|
#include "../../Data/Commodore.hpp"
|
||||||
|
|
||||||
using namespace Storage::Tape::Commodore;
|
using namespace Storage::Tape::Commodore;
|
||||||
|
|
||||||
Parser::Parser() :
|
Parser::Parser() :
|
||||||
Storage::Tape::PulseClassificationParser<WaveType, SymbolType>(),
|
Storage::Tape::PulseClassificationParser<WaveType, SymbolType>() {}
|
||||||
wave_period_(0.0f),
|
|
||||||
previous_was_high_(false),
|
|
||||||
parity_byte_(0) {}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Advances to the next block on the tape, treating it as a header, then consumes, parses, and returns it.
|
Advances to the next block on the tape, treating it as a header, then consumes, parses, and returns it.
|
||||||
|
@ -99,7 +99,7 @@ class Parser: public Storage::Tape::PulseClassificationParser<WaveType, SymbolTy
|
|||||||
*/
|
*/
|
||||||
void expect_byte(const std::shared_ptr<Storage::Tape::Tape> &tape, uint8_t value);
|
void expect_byte(const std::shared_ptr<Storage::Tape::Tape> &tape, uint8_t value);
|
||||||
|
|
||||||
uint8_t parity_byte_;
|
uint8_t parity_byte_ = 0;
|
||||||
void reset_parity_byte();
|
void reset_parity_byte();
|
||||||
uint8_t get_parity_byte();
|
uint8_t get_parity_byte();
|
||||||
void add_parity_byte(uint8_t byte);
|
void add_parity_byte(uint8_t byte);
|
||||||
@ -127,8 +127,8 @@ class Parser: public Storage::Tape::PulseClassificationParser<WaveType, SymbolTy
|
|||||||
a long, medium, short or unrecognised wave period.
|
a long, medium, short or unrecognised wave period.
|
||||||
*/
|
*/
|
||||||
void process_pulse(const Storage::Tape::Tape::Pulse &pulse);
|
void process_pulse(const Storage::Tape::Tape::Pulse &pulse);
|
||||||
bool previous_was_high_;
|
bool previous_was_high_ = false;
|
||||||
float wave_period_;
|
float wave_period_ = 0.0f;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Per the contract with StaticAnalyser::TapeParser; produces any of a word marker, an end-of-block marker,
|
Per the contract with StaticAnalyser::TapeParser; produces any of a word marker, an end-of-block marker,
|
||||||
|
@ -125,23 +125,23 @@ void Parser::inspect_waves(const std::vector<WaveType> &waves)
|
|||||||
// Sync is 0x16, either encoded fast or slow; i.e. 0 0110 1000 1
|
// Sync is 0x16, either encoded fast or slow; i.e. 0 0110 1000 1
|
||||||
Pattern slow_sync[] =
|
Pattern slow_sync[] =
|
||||||
{
|
{
|
||||||
{.type = WaveType::Long, 8},
|
{WaveType::Long, 8},
|
||||||
{.type = WaveType::Short, 16},
|
{WaveType::Short, 16},
|
||||||
{.type = WaveType::Long, 4},
|
{WaveType::Long, 4},
|
||||||
{.type = WaveType::Short, 8},
|
{WaveType::Short, 8},
|
||||||
{.type = WaveType::Long, 12},
|
{WaveType::Long, 12},
|
||||||
{.type = WaveType::Short, 8},
|
{WaveType::Short, 8},
|
||||||
{.type = WaveType::Unrecognised}
|
{WaveType::Unrecognised}
|
||||||
};
|
};
|
||||||
Pattern fast_sync[] =
|
Pattern fast_sync[] =
|
||||||
{
|
{
|
||||||
{.type = WaveType::Medium, 2},
|
{WaveType::Medium, 2},
|
||||||
{.type = WaveType::Short, 2},
|
{WaveType::Short, 2},
|
||||||
{.type = WaveType::Medium, 1},
|
{WaveType::Medium, 1},
|
||||||
{.type = WaveType::Short, 1},
|
{WaveType::Short, 1},
|
||||||
{.type = WaveType::Medium, 3},
|
{WaveType::Medium, 3},
|
||||||
{.type = WaveType::Short, 1},
|
{WaveType::Short, 1},
|
||||||
{.type = WaveType::Unrecognised}
|
{WaveType::Unrecognised}
|
||||||
};
|
};
|
||||||
|
|
||||||
size_t slow_sync_matching_depth = pattern_matching_depth(waves, slow_sync);
|
size_t slow_sync_matching_depth = pattern_matching_depth(waves, slow_sync);
|
||||||
|
@ -20,7 +20,6 @@ namespace Tape {
|
|||||||
|
|
||||||
template <typename SymbolType> class Parser {
|
template <typename SymbolType> class Parser {
|
||||||
public:
|
public:
|
||||||
Parser() : has_next_symbol_(false), error_flag_(false) {}
|
|
||||||
/// Resets the error flag.
|
/// Resets the error flag.
|
||||||
void reset_error_flag() { error_flag_ = false; }
|
void reset_error_flag() { error_flag_ = false; }
|
||||||
/// @returns @c true if an error has occurred since the error flag was last reset; @c false otherwise.
|
/// @returns @c true if an error has occurred since the error flag was last reset; @c false otherwise.
|
||||||
@ -81,9 +80,9 @@ template <typename SymbolType> class Parser {
|
|||||||
error_flag_ = true;
|
error_flag_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool error_flag_;
|
bool error_flag_ = false;
|
||||||
SymbolType next_symbol_;
|
SymbolType next_symbol_;
|
||||||
bool has_next_symbol_;
|
bool has_next_symbol_ = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -117,7 +117,7 @@ void TapePlayer::process_next_event() {
|
|||||||
#pragma mark - Binary Player
|
#pragma mark - Binary Player
|
||||||
|
|
||||||
BinaryTapePlayer::BinaryTapePlayer(unsigned int input_clock_rate) :
|
BinaryTapePlayer::BinaryTapePlayer(unsigned int input_clock_rate) :
|
||||||
TapePlayer(input_clock_rate), motor_is_running_(false), input_level_(false), delegate_(nullptr)
|
TapePlayer(input_clock_rate)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
bool BinaryTapePlayer::is_sleeping() {
|
bool BinaryTapePlayer::is_sleeping() {
|
||||||
|
@ -146,10 +146,10 @@ class BinaryTapePlayer: public TapePlayer {
|
|||||||
bool is_sleeping();
|
bool is_sleeping();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Delegate *delegate_;
|
Delegate *delegate_ = nullptr;
|
||||||
virtual void process_input_pulse(const Storage::Tape::Tape::Pulse &pulse);
|
virtual void process_input_pulse(const Storage::Tape::Tape::Pulse &pulse);
|
||||||
bool input_level_;
|
bool input_level_ = false;
|
||||||
bool motor_is_running_;
|
bool motor_is_running_ = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user