From 669e0caff5d0e7b2fe8a3e704a54798a2c31a181 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 19 Aug 2017 22:06:56 -0400 Subject: [PATCH 1/8] Ensured the head_unload_delay values are properly seeded, and generalised the quick escape. --- Components/8272/i8272.cpp | 4 +++- Components/8272/i8272.hpp | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Components/8272/i8272.cpp b/Components/8272/i8272.cpp index e6b79f217..5a1958dbb 100644 --- a/Components/8272/i8272.cpp +++ b/Components/8272/i8272.cpp @@ -128,6 +128,7 @@ void i8272::run_for(Cycles cycles) { // check for any head unloads if(head_timers_running_) { + int timers_left = head_timers_running_; for(int c = 0; c < 4; c++) { for(int h = 0; h < 2; h++) { if(drives_[c].head_unload_delay[c] > 0) { @@ -135,10 +136,11 @@ void i8272::run_for(Cycles cycles) { drives_[c].head_unload_delay[c] = 0; drives_[c].head_is_loaded[c] = false; head_timers_running_--; - if(!head_timers_running_) return; } else { drives_[c].head_unload_delay[c] -= cycles.as_int(); } + timers_left--; + if(!timers_left) return; } } } diff --git a/Components/8272/i8272.hpp b/Components/8272/i8272.hpp index 44dc899af..62ff35db9 100644 --- a/Components/8272/i8272.hpp +++ b/Components/8272/i8272.hpp @@ -102,7 +102,8 @@ class i8272: public Storage::Disk::MFMController { Drive() : head_position(0), phase(NotSeeking), drive(new Storage::Disk::Drive), - head_is_loaded{false, false} {}; + head_is_loaded{false, false}, + head_unload_delay{0, 0} {}; } drives_[4]; int drives_seeking_; From 57c5b38a6d8863529e61d7981acc7a6163dfedd0 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 19 Aug 2017 22:19:46 -0400 Subject: [PATCH 2/8] Step one towards cutting much of this cost: build only the table that's appropriate for the current mode, and at least declare when a more minimal change would be sufficient. --- Machines/AmstradCPC/AmstradCPC.cpp | 79 +++++++++++++++++++----------- 1 file changed, 50 insertions(+), 29 deletions(-) diff --git a/Machines/AmstradCPC/AmstradCPC.cpp b/Machines/AmstradCPC/AmstradCPC.cpp index c5afe939d..ff9b763f7 100644 --- a/Machines/AmstradCPC/AmstradCPC.cpp +++ b/Machines/AmstradCPC/AmstradCPC.cpp @@ -159,7 +159,7 @@ class CRTCBusHandler { mode_(2), next_mode_(2), cycles_into_hsync_(0) { - build_mode_tables(); + build_mode_table(); } /*! @@ -271,6 +271,7 @@ class CRTCBusHandler { case 1: pixel_divider_ = 2; break; case 2: pixel_divider_ = 1; break; } + build_mode_table(); } interrupt_timer_.signal_hsync(); @@ -339,8 +340,7 @@ class CRTCBusHandler { border_ = mapped_palette_value(colour); } else { palette_[pen_] = mapped_palette_value(colour); - // TODO: no need for a full regeneration, of every mode, every time - build_mode_tables(); + patch_mode_table(pen_); } } @@ -351,35 +351,56 @@ class CRTCBusHandler { crt_->output_level(length * 16); } - void build_mode_tables() { - for(int c = 0; c < 256; c++) { - // prepare mode 0 - uint8_t *mode0_pixels = (uint8_t *)&mode0_output_[c]; - mode0_pixels[0] = palette_[((c & 0x80) >> 7) | ((c & 0x20) >> 3) | ((c & 0x08) >> 2) | ((c & 0x02) << 2)]; - mode0_pixels[1] = palette_[((c & 0x40) >> 6) | ((c & 0x10) >> 2) | ((c & 0x04) >> 1) | ((c & 0x01) << 3)]; + void patch_mode_table(int pen) { + // TODO: patch, don't rebuild. + build_mode_table(); + } - // prepare mode 1 - uint8_t *mode1_pixels = (uint8_t *)&mode1_output_[c]; - mode1_pixels[0] = palette_[((c & 0x80) >> 7) | ((c & 0x08) >> 2)]; - mode1_pixels[1] = palette_[((c & 0x40) >> 6) | ((c & 0x04) >> 1)]; - mode1_pixels[2] = palette_[((c & 0x20) >> 5) | ((c & 0x02) >> 0)]; - mode1_pixels[3] = palette_[((c & 0x10) >> 4) | ((c & 0x01) << 1)]; + void build_mode_table() { + switch(mode_) { + case 0: + for(int c = 0; c < 256; c++) { + // prepare mode 0 + uint8_t *mode0_pixels = (uint8_t *)&mode0_output_[c]; + mode0_pixels[0] = palette_[((c & 0x80) >> 7) | ((c & 0x20) >> 3) | ((c & 0x08) >> 2) | ((c & 0x02) << 2)]; + mode0_pixels[1] = palette_[((c & 0x40) >> 6) | ((c & 0x10) >> 2) | ((c & 0x04) >> 1) | ((c & 0x01) << 3)]; + } + break; - // prepare mode 2 - uint8_t *mode2_pixels = (uint8_t *)&mode2_output_[c]; - mode2_pixels[0] = palette_[((c & 0x80) >> 7)]; - mode2_pixels[1] = palette_[((c & 0x40) >> 6)]; - mode2_pixels[2] = palette_[((c & 0x20) >> 5)]; - mode2_pixels[3] = palette_[((c & 0x10) >> 4)]; - mode2_pixels[4] = palette_[((c & 0x08) >> 3)]; - mode2_pixels[5] = palette_[((c & 0x04) >> 2)]; - mode2_pixels[6] = palette_[((c & 0x03) >> 1)]; - mode2_pixels[7] = palette_[((c & 0x01) >> 0)]; + case 1: + for(int c = 0; c < 256; c++) { + // prepare mode 1 + uint8_t *mode1_pixels = (uint8_t *)&mode1_output_[c]; + mode1_pixels[0] = palette_[((c & 0x80) >> 7) | ((c & 0x08) >> 2)]; + mode1_pixels[1] = palette_[((c & 0x40) >> 6) | ((c & 0x04) >> 1)]; + mode1_pixels[2] = palette_[((c & 0x20) >> 5) | ((c & 0x02) >> 0)]; + mode1_pixels[3] = palette_[((c & 0x10) >> 4) | ((c & 0x01) << 1)]; + } + break; - // prepare mode 3 - uint8_t *mode3_pixels = (uint8_t *)&mode3_output_[c]; - mode3_pixels[0] = palette_[((c & 0x80) >> 7) | ((c & 0x08) >> 2)]; - mode3_pixels[1] = palette_[((c & 0x40) >> 6) | ((c & 0x04) >> 1)]; + case 2: + for(int c = 0; c < 256; c++) { + // prepare mode 2 + uint8_t *mode2_pixels = (uint8_t *)&mode2_output_[c]; + mode2_pixels[0] = palette_[((c & 0x80) >> 7)]; + mode2_pixels[1] = palette_[((c & 0x40) >> 6)]; + mode2_pixels[2] = palette_[((c & 0x20) >> 5)]; + mode2_pixels[3] = palette_[((c & 0x10) >> 4)]; + mode2_pixels[4] = palette_[((c & 0x08) >> 3)]; + mode2_pixels[5] = palette_[((c & 0x04) >> 2)]; + mode2_pixels[6] = palette_[((c & 0x03) >> 1)]; + mode2_pixels[7] = palette_[((c & 0x01) >> 0)]; + } + break; + + case 3: + for(int c = 0; c < 256; c++) { + // prepare mode 3 + uint8_t *mode3_pixels = (uint8_t *)&mode3_output_[c]; + mode3_pixels[0] = palette_[((c & 0x80) >> 7) | ((c & 0x08) >> 2)]; + mode3_pixels[1] = palette_[((c & 0x40) >> 6) | ((c & 0x04) >> 1)]; + } + break; } } From 911ee5a0d3e91a87a0faed29b13971021f1f7ab2 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 19 Aug 2017 22:22:51 -0400 Subject: [PATCH 3/8] At least added a fast return. --- Machines/AmstradCPC/AmstradCPC.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Machines/AmstradCPC/AmstradCPC.cpp b/Machines/AmstradCPC/AmstradCPC.cpp index ff9b763f7..fc98cee09 100644 --- a/Machines/AmstradCPC/AmstradCPC.cpp +++ b/Machines/AmstradCPC/AmstradCPC.cpp @@ -353,6 +353,19 @@ class CRTCBusHandler { void patch_mode_table(int pen) { // TODO: patch, don't rebuild. + switch(mode_) { + case 0: + break; + case 1: + if(pen > 3) return; + break; + case 2: + if(pen > 1) return; + break; + case 3: + if(pen > 3) return; + break; + } build_mode_table(); } From 85253a5876c35a7f04dcd862e0bab08189131def Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 20 Aug 2017 10:13:23 -0400 Subject: [PATCH 4/8] Sought further to reduce the processing footprint of palette changes by updating only those table entries that are affected by a change. --- Machines/AmstradCPC/AmstradCPC.cpp | 108 +++++++++++++++++++++++------ 1 file changed, 85 insertions(+), 23 deletions(-) diff --git a/Machines/AmstradCPC/AmstradCPC.cpp b/Machines/AmstradCPC/AmstradCPC.cpp index fc98cee09..3fdded550 100644 --- a/Machines/AmstradCPC/AmstradCPC.cpp +++ b/Machines/AmstradCPC/AmstradCPC.cpp @@ -159,6 +159,7 @@ class CRTCBusHandler { mode_(2), next_mode_(2), cycles_into_hsync_(0) { + establish_palette_hits(); build_mode_table(); } @@ -351,32 +352,41 @@ class CRTCBusHandler { crt_->output_level(length * 16); } - void patch_mode_table(int pen) { - // TODO: patch, don't rebuild. - switch(mode_) { - case 0: - break; - case 1: - if(pen > 3) return; - break; - case 2: - if(pen > 1) return; - break; - case 3: - if(pen > 3) return; - break; +#define Mode0Colour0(c) ((c & 0x80) >> 7) | ((c & 0x20) >> 3) | ((c & 0x08) >> 2) | ((c & 0x02) << 2) +#define Mode0Colour1(c) ((c & 0x40) >> 6) | ((c & 0x10) >> 2) | ((c & 0x04) >> 1) | ((c & 0x01) << 3) + +#define Mode1Colour0(c) ((c & 0x80) >> 7) | ((c & 0x08) >> 2) +#define Mode1Colour1(c) ((c & 0x40) >> 6) | ((c & 0x04) >> 1) +#define Mode1Colour2(c) ((c & 0x20) >> 5) | ((c & 0x02) >> 0) +#define Mode1Colour3(c) ((c & 0x10) >> 4) | ((c & 0x01) << 1) + +#define Mode3Colour0(c) ((c & 0x80) >> 7) | ((c & 0x08) >> 2) +#define Mode3Colour1(c) ((c & 0x40) >> 6) | ((c & 0x04) >> 1) + + void establish_palette_hits() { + for(int c = 0; c < 256; c++) { + mode0_palette_hits_[Mode0Colour0(c)].push_back((uint8_t)c); + mode0_palette_hits_[Mode0Colour1(c)].push_back((uint8_t)c); + + mode1_palette_hits_[Mode1Colour0(c)].push_back((uint8_t)c); + mode1_palette_hits_[Mode1Colour1(c)].push_back((uint8_t)c); + mode1_palette_hits_[Mode1Colour2(c)].push_back((uint8_t)c); + mode1_palette_hits_[Mode1Colour3(c)].push_back((uint8_t)c); + + mode3_palette_hits_[Mode3Colour0(c)].push_back((uint8_t)c); + mode3_palette_hits_[Mode3Colour1(c)].push_back((uint8_t)c); } - build_mode_table(); } void build_mode_table() { switch(mode_) { case 0: + // Mode 0: abcdefgh -> [gcea] [hdfb] for(int c = 0; c < 256; c++) { // prepare mode 0 uint8_t *mode0_pixels = (uint8_t *)&mode0_output_[c]; - mode0_pixels[0] = palette_[((c & 0x80) >> 7) | ((c & 0x20) >> 3) | ((c & 0x08) >> 2) | ((c & 0x02) << 2)]; - mode0_pixels[1] = palette_[((c & 0x40) >> 6) | ((c & 0x10) >> 2) | ((c & 0x04) >> 1) | ((c & 0x01) << 3)]; + mode0_pixels[0] = palette_[Mode0Colour0(c)]; + mode0_pixels[1] = palette_[Mode0Colour1(c)]; } break; @@ -384,10 +394,10 @@ class CRTCBusHandler { for(int c = 0; c < 256; c++) { // prepare mode 1 uint8_t *mode1_pixels = (uint8_t *)&mode1_output_[c]; - mode1_pixels[0] = palette_[((c & 0x80) >> 7) | ((c & 0x08) >> 2)]; - mode1_pixels[1] = palette_[((c & 0x40) >> 6) | ((c & 0x04) >> 1)]; - mode1_pixels[2] = palette_[((c & 0x20) >> 5) | ((c & 0x02) >> 0)]; - mode1_pixels[3] = palette_[((c & 0x10) >> 4) | ((c & 0x01) << 1)]; + mode1_pixels[0] = palette_[Mode1Colour0(c)]; + mode1_pixels[1] = palette_[Mode1Colour1(c)]; + mode1_pixels[2] = palette_[Mode1Colour2(c)]; + mode1_pixels[3] = palette_[Mode1Colour3(c)]; } break; @@ -410,13 +420,61 @@ class CRTCBusHandler { for(int c = 0; c < 256; c++) { // prepare mode 3 uint8_t *mode3_pixels = (uint8_t *)&mode3_output_[c]; - mode3_pixels[0] = palette_[((c & 0x80) >> 7) | ((c & 0x08) >> 2)]; - mode3_pixels[1] = palette_[((c & 0x40) >> 6) | ((c & 0x04) >> 1)]; + mode3_pixels[0] = palette_[Mode3Colour0(c)]; + mode3_pixels[1] = palette_[Mode3Colour1(c)]; } break; } } + void patch_mode_table(int pen) { + switch(mode_) { + case 0: { + for(uint8_t c : mode0_palette_hits_[pen]) { + uint8_t *mode0_pixels = (uint8_t *)&mode0_output_[c]; + mode0_pixels[0] = palette_[Mode0Colour0(c)]; + mode0_pixels[1] = palette_[Mode0Colour1(c)]; + } + } break; + case 1: + if(pen > 3) return; + for(uint8_t c : mode1_palette_hits_[pen]) { + uint8_t *mode1_pixels = (uint8_t *)&mode1_output_[c]; + mode1_pixels[0] = palette_[Mode1Colour0(c)]; + mode1_pixels[1] = palette_[Mode1Colour1(c)]; + mode1_pixels[2] = palette_[Mode1Colour2(c)]; + mode1_pixels[3] = palette_[Mode1Colour3(c)]; + } + break; + case 2: + if(pen > 1) return; + // Whichever pen this is, there's only one table entry it doesn't touch, so just + // rebuild the whole thing. + build_mode_table(); + break; + case 3: + if(pen > 3) return; + // Same argument applies here as to case 1, as the unused bits aren't masked out. + for(uint8_t c : mode3_palette_hits_[pen]) { + uint8_t *mode3_pixels = (uint8_t *)&mode3_output_[c]; + mode3_pixels[0] = palette_[Mode3Colour0(c)]; + mode3_pixels[1] = palette_[Mode3Colour1(c)]; + } + break; + } + } + +#undef Mode0Colour0 +#undef Mode0Colour1 + +#undef Mode1Colour0 +#undef Mode1Colour1 +#undef Mode1Colour2 +#undef Mode1Colour3 + +#undef Mode3Colour0 +#undef Mode3Colour1 + uint8_t mapped_palette_value(uint8_t colour) { #define COL(r, g, b) (r << 4) | (g << 2) | b static const uint8_t mapping[32] = { @@ -451,6 +509,10 @@ class CRTCBusHandler { uint64_t mode2_output_[256]; uint16_t mode3_output_[256]; + std::vector mode0_palette_hits_[16]; + std::vector mode1_palette_hits_[4]; + std::vector mode3_palette_hits_[4]; + int pen_; uint8_t palette_[16]; uint8_t border_; From f2699a3f2b2f244e56be449dea008fa4cedc6bba Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 20 Aug 2017 10:24:01 -0400 Subject: [PATCH 5/8] Okay, even if releasing it is unsafe, I can at least move the typer so that it is no longer called. --- Machines/Typer.hpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Machines/Typer.hpp b/Machines/Typer.hpp index 32cb25ce9..7e85ef4b7 100644 --- a/Machines/Typer.hpp +++ b/Machines/Typer.hpp @@ -107,12 +107,21 @@ class TypeRecipient: public Typer::Delegate { */ void typer_reset(Typer *typer) { clear_all_keys(); + + // It's unsafe to deallocate typer right now, since it is the caller, but also it has a small + // memory footprint and it's desireable not to imply that the subclass need call it any more. + // So shuffle it off into a siding. + previous_typer_ = std::move(typer_); + typer_ = nullptr; } protected: virtual HalfCycles get_typer_delay() { return HalfCycles(0); } virtual HalfCycles get_typer_frequency() { return HalfCycles(0); } std::unique_ptr typer_; + + private: + std::unique_ptr previous_typer_; }; } From 8ce46b6e498d7227c947263e4d2821e2f8708fcc Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 20 Aug 2017 10:32:09 -0400 Subject: [PATCH 6/8] Having spotted that I was using my single-character loop counter names incorrectly (quelle surprise!), got a bit more explicit. Also flattened into a single loop so that I can break rather than returning. --- Components/8272/i8272.cpp | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/Components/8272/i8272.cpp b/Components/8272/i8272.cpp index 5a1958dbb..96b50e73e 100644 --- a/Components/8272/i8272.cpp +++ b/Components/8272/i8272.cpp @@ -129,19 +129,20 @@ void i8272::run_for(Cycles cycles) { // check for any head unloads if(head_timers_running_) { int timers_left = head_timers_running_; - for(int c = 0; c < 4; c++) { - for(int h = 0; h < 2; h++) { - if(drives_[c].head_unload_delay[c] > 0) { - if(cycles.as_int() >= drives_[c].head_unload_delay[c]) { - drives_[c].head_unload_delay[c] = 0; - drives_[c].head_is_loaded[c] = false; - head_timers_running_--; - } else { - drives_[c].head_unload_delay[c] -= cycles.as_int(); - } - timers_left--; - if(!timers_left) return; + for(int c = 0; c < 8; c++) { + int drive = (c >> 1); + int head = c&1; + + if(drives_[drive].head_unload_delay[head] > 0) { + if(cycles.as_int() >= drives_[drive].head_unload_delay[head]) { + drives_[drive].head_unload_delay[head] = 0; + drives_[drive].head_is_loaded[head] = false; + head_timers_running_--; + } else { + drives_[drive].head_unload_delay[head] -= cycles.as_int(); } + timers_left--; + if(!timers_left) break; } } } From 2d9efccc983968ba387f5e713683a1f44ce5cac2 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 20 Aug 2017 10:43:53 -0400 Subject: [PATCH 7/8] Introduced a master 'is sleeping' flag. I'm starting to think there's a pattern forming here. --- Components/8272/i8272.cpp | 12 +++++++++++- Components/8272/i8272.hpp | 2 ++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/Components/8272/i8272.cpp b/Components/8272/i8272.cpp index 96b50e73e..926879f1d 100644 --- a/Components/8272/i8272.cpp +++ b/Components/8272/i8272.cpp @@ -91,6 +91,8 @@ i8272::i8272(BusHandler &bus_handler, Cycles clock_rate, int clock_rate_multipli void i8272::run_for(Cycles cycles) { Storage::Disk::MFMController::run_for(cycles); + if(is_sleeping_) return; + // check for an expired timer if(delay_time_ > 0) { if(cycles.as_int() >= delay_time_) { @@ -103,6 +105,7 @@ void i8272::run_for(Cycles cycles) { // update seek status of any drives presently seeking if(drives_seeking_) { + int drives_left = drives_seeking_; for(int c = 0; c < 4; c++) { if(drives_[c].phase == Drive::Seeking) { drives_[c].step_rate_counter += cycles.as_int(); @@ -122,6 +125,9 @@ void i8272::run_for(Cycles cycles) { break; } } + + drives_left--; + if(!drives_left) break; } } } @@ -146,6 +152,8 @@ void i8272::run_for(Cycles cycles) { } } } + + is_sleeping_ = !delay_time_ && !drives_seeking_ && !head_timers_running_; } void i8272::set_register(int address, uint8_t value) { @@ -190,7 +198,7 @@ void i8272::set_disk(std::shared_ptr disk, int drive) { #define MS_TO_CYCLES(x) x * 8000 #define WAIT_FOR_EVENT(mask) resume_point_ = __LINE__; interesting_event_mask_ = (int)mask; return; case __LINE__: -#define WAIT_FOR_TIME(ms) resume_point_ = __LINE__; interesting_event_mask_ = (int)Event8272::Timer; delay_time_ = MS_TO_CYCLES(ms); case __LINE__: if(delay_time_) return; +#define WAIT_FOR_TIME(ms) resume_point_ = __LINE__; interesting_event_mask_ = (int)Event8272::Timer; delay_time_ = MS_TO_CYCLES(ms); is_sleeping_ = false; case __LINE__: if(delay_time_) return; #define PASTE(x, y) x##y #define CONCAT(x, y) PASTE(x, y) @@ -248,6 +256,7 @@ void i8272::set_disk(std::shared_ptr disk, int drive) { if(drives_[active_drive_].head_is_loaded[active_head_]) {\ if(drives_[active_drive_].head_unload_delay[active_head_] == 0) { \ head_timers_running_++; \ + is_sleeping_ = false; \ } \ drives_[active_drive_].head_unload_delay[active_head_] = MS_TO_CYCLES(head_unload_time_);\ } @@ -701,6 +710,7 @@ void i8272::posit_event(int event_type) { // Increment the seeking count if this drive wasn't already seeking. if(drives_[drive].phase != Drive::Seeking) { drives_seeking_++; + is_sleeping_ = false; } // Set currently seeking, with a step to occur right now (yes, it sounds like jamming these diff --git a/Components/8272/i8272.hpp b/Components/8272/i8272.hpp index 62ff35db9..9c216aa7c 100644 --- a/Components/8272/i8272.hpp +++ b/Components/8272/i8272.hpp @@ -128,6 +128,8 @@ class i8272: public Storage::Disk::MFMController { // Internal registers. uint8_t cylinder_, head_, sector_, size_; + // Master switch on not performing any work. + bool is_sleeping_; }; } From 5344e3098bbd6ec4ad87ae3eb1d5724990bf124c Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 20 Aug 2017 10:55:08 -0400 Subject: [PATCH 8/8] Minor: made has_disk something that is decided on insertion/deletion. --- Storage/Disk/Drive.cpp | 6 ++++-- Storage/Disk/Drive.hpp | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Storage/Disk/Drive.cpp b/Storage/Disk/Drive.cpp index b8124dc90..99e8e6d11 100644 --- a/Storage/Disk/Drive.cpp +++ b/Storage/Disk/Drive.cpp @@ -12,20 +12,22 @@ using namespace Storage::Disk; Drive::Drive() - : head_position_(0), head_(0) {} + : head_position_(0), head_(0), has_disk_(false) {} void Drive::set_disk(const std::shared_ptr &disk) { disk_ = disk; track_ = nullptr; + has_disk_ = !!disk_; } void Drive::set_disk_with_track(const std::shared_ptr &track) { disk_ = nullptr; track_ = track; + has_disk_ = !!track_; } bool Drive::has_disk() { - return (bool)disk_ || (bool)track_; + return has_disk_; } bool Drive::get_is_track_zero() { diff --git a/Storage/Disk/Drive.hpp b/Storage/Disk/Drive.hpp index d65cb5435..009b15dc9 100644 --- a/Storage/Disk/Drive.hpp +++ b/Storage/Disk/Drive.hpp @@ -73,6 +73,7 @@ class Drive { private: std::shared_ptr track_; std::shared_ptr disk_; + bool has_disk_; int head_position_; unsigned int head_; };