mirror of
https://github.com/TomHarte/CLK.git
synced 2024-10-13 06:23:59 +00:00
Merge pull request #232 from TomHarte/ElectronShift
Ensures all parts of the Electron have a fully-defined initial state.
This commit is contained in:
commit
0f85cffc78
@ -30,13 +30,7 @@ class ConcreteMachine:
|
|||||||
public Tape::Delegate,
|
public Tape::Delegate,
|
||||||
public Utility::TypeRecipient {
|
public Utility::TypeRecipient {
|
||||||
public:
|
public:
|
||||||
ConcreteMachine() :
|
ConcreteMachine() : m6502_(*this) {
|
||||||
m6502_(*this),
|
|
||||||
interrupt_control_(0),
|
|
||||||
interrupt_status_(Interrupt::PowerOnReset | Interrupt::TransmitDataEmpty | 0x80),
|
|
||||||
cycles_since_audio_update_(0),
|
|
||||||
use_fast_tape_hack_(false),
|
|
||||||
cycles_until_display_interrupt_(0) {
|
|
||||||
memset(key_states_, 0, sizeof(key_states_));
|
memset(key_states_, 0, sizeof(key_states_));
|
||||||
for(int c = 0; c < 16; c++)
|
for(int c = 0; c < 16; c++)
|
||||||
memset(roms_[c], 0xff, 16384);
|
memset(roms_[c], 0xff, 16384);
|
||||||
@ -435,39 +429,41 @@ class ConcreteMachine:
|
|||||||
|
|
||||||
// Things that directly constitute the memory map.
|
// Things that directly constitute the memory map.
|
||||||
uint8_t roms_[16][16384];
|
uint8_t roms_[16][16384];
|
||||||
bool rom_write_masks_[16];
|
bool rom_write_masks_[16] = {false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false};
|
||||||
uint8_t os_[16384], ram_[32768];
|
uint8_t os_[16384], ram_[32768];
|
||||||
std::vector<uint8_t> dfs_, adfs_;
|
std::vector<uint8_t> dfs_, adfs_;
|
||||||
|
|
||||||
// Paging
|
// Paging
|
||||||
ROMSlot active_rom_;
|
ROMSlot active_rom_ = ROMSlot::ROMSlot0;
|
||||||
bool keyboard_is_active_, basic_is_active_;
|
bool keyboard_is_active_ = false;
|
||||||
|
bool basic_is_active_ = false;
|
||||||
|
|
||||||
// Interrupt and keyboard state
|
// Interrupt and keyboard state
|
||||||
uint8_t interrupt_status_, interrupt_control_;
|
uint8_t interrupt_status_ = Interrupt::PowerOnReset | Interrupt::TransmitDataEmpty | 0x80;
|
||||||
|
uint8_t interrupt_control_ = 0;
|
||||||
uint8_t key_states_[14];
|
uint8_t key_states_[14];
|
||||||
|
|
||||||
// Counters related to simultaneous subsystems
|
// Counters related to simultaneous subsystems
|
||||||
Cycles cycles_since_display_update_;
|
Cycles cycles_since_display_update_ = 0;
|
||||||
Cycles cycles_since_audio_update_;
|
Cycles cycles_since_audio_update_ = 0;
|
||||||
int cycles_until_display_interrupt_;
|
int cycles_until_display_interrupt_ = 0;
|
||||||
Interrupt next_display_interrupt_;
|
Interrupt next_display_interrupt_ = Interrupt::RealTimeClock;
|
||||||
VideoOutput::Range video_access_range_;
|
VideoOutput::Range video_access_range_ = {0, 0xffff};
|
||||||
|
|
||||||
// Tape
|
// Tape
|
||||||
Tape tape_;
|
Tape tape_;
|
||||||
bool use_fast_tape_hack_;
|
bool use_fast_tape_hack_ = false;
|
||||||
bool fast_load_is_in_data_;
|
bool fast_load_is_in_data_ = false;
|
||||||
|
|
||||||
// Disk
|
// Disk
|
||||||
std::unique_ptr<Plus3> plus3_;
|
std::unique_ptr<Plus3> plus3_;
|
||||||
bool is_holding_shift_;
|
bool is_holding_shift_ = false;
|
||||||
int shift_restart_counter_;
|
int shift_restart_counter_ = 0;
|
||||||
|
|
||||||
// Outputs
|
// Outputs
|
||||||
std::unique_ptr<VideoOutput> video_output_;
|
std::unique_ptr<VideoOutput> video_output_;
|
||||||
std::shared_ptr<Speaker> speaker_;
|
std::shared_ptr<Speaker> speaker_;
|
||||||
bool speaker_is_enabled_;
|
bool speaker_is_enabled_ = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
using namespace Electron;
|
using namespace Electron;
|
||||||
|
|
||||||
Plus3::Plus3() : WD1770(P1770), last_control_(0) {
|
Plus3::Plus3() : WD1770(P1770) {
|
||||||
set_control_register(last_control_, 0xff);
|
set_control_register(last_control_, 0xff);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,8 +23,8 @@ class Plus3 : public WD::WD1770 {
|
|||||||
private:
|
private:
|
||||||
void set_control_register(uint8_t control, uint8_t changes);
|
void set_control_register(uint8_t control, uint8_t changes);
|
||||||
std::shared_ptr<Storage::Disk::Drive> drives_[2];
|
std::shared_ptr<Storage::Disk::Drive> drives_[2];
|
||||||
int selected_drive_;
|
int selected_drive_ = 0;
|
||||||
uint8_t last_control_;
|
uint8_t last_control_ = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -25,9 +25,9 @@ class Speaker: public ::Outputs::Filter<Speaker> {
|
|||||||
static const unsigned int clock_rate_divider = 8;
|
static const unsigned int clock_rate_divider = 8;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned int counter_;
|
unsigned int counter_ = 0;
|
||||||
unsigned int divider_;
|
unsigned int divider_ = 0;
|
||||||
bool is_enabled_;
|
bool is_enabled_ = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -10,14 +10,7 @@
|
|||||||
|
|
||||||
using namespace Electron;
|
using namespace Electron;
|
||||||
|
|
||||||
Tape::Tape() :
|
Tape::Tape() : TapePlayer(2000000) {
|
||||||
TapePlayer(2000000),
|
|
||||||
is_running_(false),
|
|
||||||
data_register_(0),
|
|
||||||
delegate_(nullptr),
|
|
||||||
output_({.bits_remaining_until_empty = 0, .cycles_into_pulse = 0}),
|
|
||||||
last_posted_interrupt_status_(0),
|
|
||||||
interrupt_status_(0) {
|
|
||||||
shifter_.set_delegate(this);
|
shifter_.set_delegate(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,21 +53,22 @@ class Tape:
|
|||||||
|
|
||||||
struct {
|
struct {
|
||||||
int minimum_bits_until_full;
|
int minimum_bits_until_full;
|
||||||
} input_;
|
} input_ = {0};
|
||||||
struct {
|
struct {
|
||||||
unsigned int cycles_into_pulse;
|
unsigned int cycles_into_pulse;
|
||||||
unsigned int bits_remaining_until_empty;
|
unsigned int bits_remaining_until_empty;
|
||||||
} output_;
|
} output_ = {.bits_remaining_until_empty = 0, .cycles_into_pulse = 0};
|
||||||
|
|
||||||
bool is_running_;
|
bool is_running_ = false;
|
||||||
bool is_enabled_;
|
bool is_enabled_ = false;
|
||||||
bool is_in_input_mode_;
|
bool is_in_input_mode_ = false;
|
||||||
|
|
||||||
inline void evaluate_interrupts();
|
inline void evaluate_interrupts();
|
||||||
uint16_t data_register_;
|
uint16_t data_register_ = 0;
|
||||||
|
|
||||||
uint8_t interrupt_status_, last_posted_interrupt_status_;
|
uint8_t interrupt_status_ = 0;
|
||||||
Delegate *delegate_;
|
uint8_t last_posted_interrupt_status_ = 0;
|
||||||
|
Delegate *delegate_ = nullptr;
|
||||||
|
|
||||||
::Storage::Tape::Acorn::Shifter shifter_;
|
::Storage::Tape::Acorn::Shifter shifter_;
|
||||||
};
|
};
|
||||||
|
@ -36,13 +36,7 @@ namespace {
|
|||||||
|
|
||||||
#pragma mark - Lifecycle
|
#pragma mark - Lifecycle
|
||||||
|
|
||||||
VideoOutput::VideoOutput(uint8_t *memory) :
|
VideoOutput::VideoOutput(uint8_t *memory) : ram_(memory) {
|
||||||
ram_(memory),
|
|
||||||
current_pixel_line_(-1),
|
|
||||||
output_position_(0),
|
|
||||||
screen_mode_(6),
|
|
||||||
screen_map_pointer_(0),
|
|
||||||
cycles_into_draw_action_(0) {
|
|
||||||
memset(palette_, 0xf, sizeof(palette_));
|
memset(palette_, 0xf, sizeof(palette_));
|
||||||
setup_screen_map();
|
setup_screen_map();
|
||||||
setup_base_address();
|
setup_base_address();
|
||||||
|
@ -80,12 +80,13 @@ class VideoOutput {
|
|||||||
inline void output_pixels(unsigned int number_of_cycles);
|
inline void output_pixels(unsigned int number_of_cycles);
|
||||||
inline void setup_base_address();
|
inline void setup_base_address();
|
||||||
|
|
||||||
int output_position_, unused_cycles_;
|
int output_position_ = 0;
|
||||||
|
int unused_cycles_ = 0;
|
||||||
|
|
||||||
uint8_t palette_[16];
|
uint8_t palette_[16];
|
||||||
uint8_t screen_mode_;
|
uint8_t screen_mode_ = 6;
|
||||||
uint16_t screen_mode_base_address_;
|
uint16_t screen_mode_base_address_ = 0;
|
||||||
uint16_t start_screen_address_;
|
uint16_t start_screen_address_ = 0;
|
||||||
|
|
||||||
uint8_t *ram_;
|
uint8_t *ram_;
|
||||||
struct {
|
struct {
|
||||||
@ -97,14 +98,18 @@ class VideoOutput {
|
|||||||
} palette_tables_;
|
} palette_tables_;
|
||||||
|
|
||||||
// Display generation.
|
// Display generation.
|
||||||
uint16_t start_line_address_, current_screen_address_;
|
uint16_t start_line_address_ = 0;
|
||||||
int current_pixel_line_, current_pixel_column_, current_character_row_;
|
uint16_t current_screen_address_ = 0;
|
||||||
uint8_t last_pixel_byte_;
|
int current_pixel_line_ = -1;
|
||||||
bool is_blank_line_;
|
int current_pixel_column_ = 0;
|
||||||
|
int current_character_row_ = 0;
|
||||||
|
uint8_t last_pixel_byte_ = 0;
|
||||||
|
bool is_blank_line_ = false;
|
||||||
|
|
||||||
// CRT output
|
// CRT output
|
||||||
uint8_t *current_output_target_, *initial_output_target_;
|
uint8_t *current_output_target_ = nullptr;
|
||||||
unsigned int current_output_divider_;
|
uint8_t *initial_output_target_ = nullptr;
|
||||||
|
unsigned int current_output_divider_ = 1;
|
||||||
|
|
||||||
std::shared_ptr<Outputs::CRT::CRT> crt_;
|
std::shared_ptr<Outputs::CRT::CRT> crt_;
|
||||||
|
|
||||||
@ -119,8 +124,8 @@ class VideoOutput {
|
|||||||
void setup_screen_map();
|
void setup_screen_map();
|
||||||
void emplace_blank_line();
|
void emplace_blank_line();
|
||||||
void emplace_pixel_line();
|
void emplace_pixel_line();
|
||||||
size_t screen_map_pointer_;
|
size_t screen_map_pointer_ = 0;
|
||||||
int cycles_into_draw_action_;
|
int cycles_into_draw_action_ = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user