From 59981238681e2adba1f6aa09bf4b928e5a776685 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 6 May 2017 19:53:24 -0400 Subject: [PATCH 1/8] Added some consts, for a minor safety improvement. --- Components/6560/6560.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Components/6560/6560.hpp b/Components/6560/6560.hpp index bdf455108..cd786888c 100644 --- a/Components/6560/6560.hpp +++ b/Components/6560/6560.hpp @@ -82,19 +82,19 @@ template class MOS6560 { */ void set_output_mode(OutputMode output_mode) { output_mode_ = output_mode; - uint8_t luminances[16] = { // range is 0–4 + const uint8_t luminances[16] = { // range is 0–4 0, 4, 1, 3, 2, 2, 1, 3, 2, 1, 2, 1, 2, 3, 2, 3 }; - uint8_t pal_chrominances[16] = { // range is 0–15; 15 is a special case meaning "no chrominance" + const uint8_t pal_chrominances[16] = { // range is 0–15; 15 is a special case meaning "no chrominance" 15, 15, 5, 13, 2, 10, 0, 8, 6, 7, 5, 13, 2, 10, 0, 8, }; - uint8_t ntsc_chrominances[16] = { + const uint8_t ntsc_chrominances[16] = { 15, 15, 2, 10, 4, 12, 6, 14, 0, 8, 2, 10, 4, 12, 6, 14, }; - uint8_t *chrominances; + const uint8_t *chrominances; Outputs::CRT::DisplayType display_type; switch(output_mode) { From 6a37a02eee55644d70b7dd07b994b5676e26efa8 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 6 May 2017 19:55:42 -0400 Subject: [PATCH 2/8] Switched to `std::ostringstream` to avoid the need to make a string length count (and I was one off when loading a disk). --- StaticAnalyser/Commodore/StaticAnalyser.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/StaticAnalyser/Commodore/StaticAnalyser.cpp b/StaticAnalyser/Commodore/StaticAnalyser.cpp index 23018563a..c1d6aa472 100644 --- a/StaticAnalyser/Commodore/StaticAnalyser.cpp +++ b/StaticAnalyser/Commodore/StaticAnalyser.cpp @@ -13,6 +13,8 @@ #include "Disk.hpp" #include "../../Storage/Cartridge/Encodings/CommodoreROM.hpp" +#include + using namespace StaticAnalyser::Commodore; static std::list> @@ -75,15 +77,15 @@ void StaticAnalyser::Commodore::AddTargets( if(files.size()) { target.vic20.memory_model = Vic20MemoryModel::Unexpanded; - if(files.front().is_basic()) { - char command[16]; - snprintf(command, 16, "LOAD\"%s\",%d,0\nRUN\n", is_disk ? "*" : "", device); - target.loadingCommand = command; + std::ostringstream string_stream; + string_stream << "LOAD\"" << (is_disk ? "*" : "") << "\"," << device << ","; + if(files.front().is_basic()) { + string_stream << "0"; } else { - char command[16]; - snprintf(command, 16, "LOAD\"%s\",%d,1\nRUN\n", is_disk ? "*" : "", device); - target.loadingCommand = command; + string_stream << "1"; } + string_stream << "\nRUN\n"; + target.loadingCommand = string_stream.str(); // make a first guess based on loading address switch(files.front().starting_address) { From 2edf73908c49df6990f22dcf2833e9c0378921eb Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 6 May 2017 22:00:12 -0400 Subject: [PATCH 3/8] Temporarily disabled the existing fast loading implementation in pursuit of another, and started trying to correct the lack of connection between the userport VIA and the tape drive. --- Machines/Commodore/Vic-20/Vic20.cpp | 44 +++++++++++-------- Machines/Commodore/Vic-20/Vic20.hpp | 10 ++--- .../Clock Signal/Machine/Wrappers/CSVic20.mm | 2 +- 3 files changed, 31 insertions(+), 25 deletions(-) diff --git a/Machines/Commodore/Vic-20/Vic20.cpp b/Machines/Commodore/Vic-20/Vic20.cpp index 6251545e5..009d9c854 100644 --- a/Machines/Commodore/Vic-20/Vic20.cpp +++ b/Machines/Commodore/Vic-20/Vic20.cpp @@ -17,12 +17,13 @@ using namespace Commodore::Vic20; Machine::Machine() : rom_(nullptr), is_running_at_zero_cost_(false), - tape_(1022727) { + tape_(new Storage::Tape::BinaryTapePlayer(1022727)) { // create 6522s, serial port and bus user_port_via_.reset(new UserPortVIA); keyboard_via_.reset(new KeyboardVIA); serial_port_.reset(new SerialPort); serial_bus_.reset(new ::Commodore::Serial::Bus); + user_port_via_->set_tape(tape_); // wire up the serial bus and serial port Commodore::Serial::AttachPortAndBus(serial_port_, serial_bus_); @@ -35,7 +36,7 @@ Machine::Machine() : // wire up the 6522s, tape and machine user_port_via_->set_interrupt_delegate(this); keyboard_via_->set_interrupt_delegate(this); - tape_.set_delegate(this); + tape_->set_delegate(this); // establish the memory maps set_memory_size(MemorySize::Default); @@ -124,11 +125,11 @@ unsigned int Machine::perform_bus_operation(CPU6502::BusOperation operation, uin // PC hits the start of the loop that just waits for an interesting tape interrupt to have // occurred then skip both 6522s and the tape ahead to the next interrupt without any further // CPU or 6560 costs. - if(use_fast_tape_hack_ && tape_.has_tape() && address == 0xf92f && operation == CPU6502::BusOperation::ReadOpcode) { - while(!user_port_via_->get_interrupt_line() && !keyboard_via_->get_interrupt_line() && !tape_.get_tape()->is_at_end()) { - user_port_via_->run_for_cycles(1); - keyboard_via_->run_for_cycles(1); - tape_.run_for_cycles(1); + if(use_fast_tape_hack_ && tape_->has_tape() && operation == CPU6502::BusOperation::ReadOpcode) { + if(address == 0xf7b2) { + printf("Find header"); + } else if(address == 0xf90b) { + printf("Tape receive"); } } } else { @@ -149,7 +150,7 @@ unsigned int Machine::perform_bus_operation(CPU6502::BusOperation operation, uin typer_.reset(); } } - tape_.run_for_cycles(1); + tape_->run_for_cycles(1); if(c1540_) c1540_->run_for_cycles(1); // If using fast tape then: @@ -163,19 +164,19 @@ unsigned int Machine::perform_bus_operation(CPU6502::BusOperation operation, uin // Note the additional test above for PC hitting 0xf92f, which is a loop in the ROM that waits // for an interesting interrupt. Up there the fast tape hack goes even further in also cutting // the CPU out of the action. - if(use_fast_tape_hack_ && tape_.has_tape()) { +/* if(use_fast_tape_hack_ && tape_->has_tape()) { if(address == 0xf98e && operation == CPU6502::BusOperation::ReadOpcode) { is_running_at_zero_cost_ = true; set_clock_is_unlimited(true); } if( (address < 0xe000 && operation == CPU6502::BusOperation::ReadOpcode) || - tape_.get_tape()->is_at_end() + tape_->get_tape()->is_at_end() ) { is_running_at_zero_cost_ = false; set_clock_is_unlimited(false); } - } + }*/ return 1; } @@ -265,7 +266,7 @@ void Machine::set_rom(ROMSlot slot, size_t length, const uint8_t *data) { void Machine::configure_as_target(const StaticAnalyser::Target &target) { if(target.tapes.size()) { - tape_.set_tape(target.tapes.front()); + tape_->set_tape(target.tapes.front()); } if(target.disks.size()) { @@ -292,8 +293,8 @@ void Machine::configure_as_target(const StaticAnalyser::Target &target) { write_to_map(processor_read_memory_map_, rom_, rom_address_, 0x2000); } - if(should_automatically_load_media_) { - if(target.loadingCommand.length()) { // TODO: and automatic loading option enabled +// if(should_automatically_load_media_) { + if(target.loadingCommand.length()) { set_typer_for_string(target.loadingCommand.c_str()); } @@ -308,7 +309,7 @@ void Machine::configure_as_target(const StaticAnalyser::Target &target) { set_memory_size(ThirtyTwoKB); break; } - } +// } } void Machine::tape_did_change_input(Storage::Tape::BinaryTapePlayer *tape) { @@ -329,15 +330,16 @@ void Machine::install_disk_rom() { uint8_t UserPortVIA::get_port_input(Port port) { if(!port) { - return port_a_; // TODO: bit 6 should be high if there is no tape, low otherwise + return port_a_ | (tape_->has_tape() ? 0x00 : 0x40); } return 0xff; } void UserPortVIA::set_control_line_output(Port port, Line line, bool value) { -// if(port == Port::A && line == Line::Two) { -// printf("Tape motor %s\n", value ? "on" : "off"); -// } + if(port == Port::A && line == Line::Two) { + tape_->set_motor_control(!value); + printf("Tape motor: %d\n", value ? 1 : 0); + } } void UserPortVIA::set_serial_line_state(::Commodore::Serial::Line line, bool value) { @@ -369,6 +371,10 @@ void UserPortVIA::set_serial_port(std::shared_ptr<::Commodore::Serial::Port> ser serial_port_ = serialPort; } +void UserPortVIA::set_tape(std::shared_ptr tape) { + tape_ = tape; +} + #pragma mark - KeyboardVIA KeyboardVIA::KeyboardVIA() : port_b_(0xff) { diff --git a/Machines/Commodore/Vic-20/Vic20.hpp b/Machines/Commodore/Vic-20/Vic20.hpp index f226cd75e..c381b5441 100644 --- a/Machines/Commodore/Vic-20/Vic20.hpp +++ b/Machines/Commodore/Vic-20/Vic20.hpp @@ -87,10 +87,12 @@ class UserPortVIA: public MOS::MOS6522, public MOS::MOS6522IRQDeleg void set_port_output(Port port, uint8_t value, uint8_t mask); void set_serial_port(std::shared_ptr<::Commodore::Serial::Port> serialPort); + void set_tape(std::shared_ptr tape); private: uint8_t port_a_; std::weak_ptr<::Commodore::Serial::Port> serial_port_; + std::shared_ptr tape_; }; class KeyboardVIA: public MOS::MOS6522, public MOS::MOS6522IRQDelegate { @@ -164,7 +166,7 @@ class Machine: void set_region(Region region); inline void set_use_fast_tape_hack(bool activate) { use_fast_tape_hack_ = activate; } - inline void set_should_automatically_load_media(bool activate) { should_automatically_load_media_ = activate; } +// inline void set_should_automatically_load_media(bool activate) { should_automatically_load_media_ = activate; } // to satisfy CPU6502::Processor unsigned int perform_bus_operation(CPU6502::BusOperation operation, uint16_t address, uint8_t *value); @@ -213,15 +215,13 @@ class Machine: std::shared_ptr<::Commodore::Serial::Bus> serial_bus_; // Tape - Storage::Tape::BinaryTapePlayer tape_; - bool use_fast_tape_hack_, should_automatically_load_media_; + std::shared_ptr tape_; + bool use_fast_tape_hack_;//, should_automatically_load_media_; bool is_running_at_zero_cost_; // Disk std::shared_ptr<::Commodore::C1540::Machine> c1540_; void install_disk_rom(); - - // Autoload string }; } diff --git a/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSVic20.mm b/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSVic20.mm index bcc3866c5..46fac4973 100644 --- a/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSVic20.mm +++ b/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSVic20.mm @@ -181,7 +181,7 @@ using namespace Commodore::Vic20; - (void)setShouldLoadAutomatically:(BOOL)shouldLoadAutomatically { _shouldLoadAutomatically = shouldLoadAutomatically; @synchronized(self) { - _vic20.set_should_automatically_load_media(shouldLoadAutomatically ? true : false); +// _vic20.set_should_automatically_load_media(shouldLoadAutomatically ? true : false); } } From 1f56e85f6d4fe9ebe3a705fc2595fd48144bdf05 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 6 May 2017 22:19:08 -0400 Subject: [PATCH 4/8] Centralised resetting of tape files within the static analyser, having implemented it patchily. --- StaticAnalyser/Acorn/StaticAnalyser.cpp | 2 -- StaticAnalyser/Oric/Tape.cpp | 2 -- StaticAnalyser/StaticAnalyser.cpp | 8 ++++++++ 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/StaticAnalyser/Acorn/StaticAnalyser.cpp b/StaticAnalyser/Acorn/StaticAnalyser.cpp index 362ff74bc..98edd262d 100644 --- a/StaticAnalyser/Acorn/StaticAnalyser.cpp +++ b/StaticAnalyser/Acorn/StaticAnalyser.cpp @@ -74,9 +74,7 @@ void StaticAnalyser::Acorn::AddTargets( // if there are any tapes, attempt to get data from the first if(tapes.size() > 0) { std::shared_ptr tape = tapes.front(); - tape->reset(); std::list files = GetFiles(tape); - tape->reset(); // continue if there are any files if(files.size()) { diff --git a/StaticAnalyser/Oric/Tape.cpp b/StaticAnalyser/Oric/Tape.cpp index 0df23e064..8ba4e772c 100644 --- a/StaticAnalyser/Oric/Tape.cpp +++ b/StaticAnalyser/Oric/Tape.cpp @@ -15,7 +15,6 @@ std::list StaticAnalyser::Oric::GetFiles(const std::shared_ptr files; Storage::Tape::Oric::Parser parser; - tape->reset(); while(!tape->is_at_end()) { // sync to next lead-in, check that it's one of three 0x16s bool is_fast = parser.sync_and_get_encoding_speed(tape); @@ -81,7 +80,6 @@ std::list StaticAnalyser::Oric::GetFiles(const std::shared_ptrreset(); return files; } diff --git a/StaticAnalyser/StaticAnalyser.cpp b/StaticAnalyser/StaticAnalyser.cpp index 291187996..803890521 100644 --- a/StaticAnalyser/StaticAnalyser.cpp +++ b/StaticAnalyser/StaticAnalyser.cpp @@ -128,5 +128,13 @@ std::list StaticAnalyser::GetTargets(const char *file_name) free(lowercase_extension); } + + // Reset any tapes to their initial position + for(auto target : targets) { + for(auto tape : target.tapes) { + tape->reset(); + } + } + return targets; } From 0771363f3b43c541c953797934fe5848e3c0a18c Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 6 May 2017 22:22:03 -0400 Subject: [PATCH 5/8] Removed one piece of unnecessary logging. --- Machines/Commodore/Vic-20/Vic20.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Machines/Commodore/Vic-20/Vic20.cpp b/Machines/Commodore/Vic-20/Vic20.cpp index 009d9c854..4dd3d8d73 100644 --- a/Machines/Commodore/Vic-20/Vic20.cpp +++ b/Machines/Commodore/Vic-20/Vic20.cpp @@ -127,9 +127,9 @@ unsigned int Machine::perform_bus_operation(CPU6502::BusOperation operation, uin // CPU or 6560 costs. if(use_fast_tape_hack_ && tape_->has_tape() && operation == CPU6502::BusOperation::ReadOpcode) { if(address == 0xf7b2) { - printf("Find header"); + printf("Find header\n"); } else if(address == 0xf90b) { - printf("Tape receive"); + printf("Tape receive\n"); } } } else { @@ -338,7 +338,6 @@ uint8_t UserPortVIA::get_port_input(Port port) { void UserPortVIA::set_control_line_output(Port port, Line line, bool value) { if(port == Port::A && line == Line::Two) { tape_->set_motor_control(!value); - printf("Tape motor: %d\n", value ? 1 : 0); } } From 2807e3134f543e7d11272bf40eada9a41b313c21 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 7 May 2017 20:32:48 -0400 Subject: [PATCH 6/8] Implemented speedy header finding. So that's half of it. --- Machines/Commodore/Vic-20/Vic20.cpp | 21 ++++++++++++++++++++- Storage/Tape/Parsers/Commodore.cpp | 14 ++++++++++++++ Storage/Tape/Parsers/Commodore.hpp | 7 ++++++- 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/Machines/Commodore/Vic-20/Vic20.cpp b/Machines/Commodore/Vic-20/Vic20.cpp index 4dd3d8d73..e011d7a9b 100644 --- a/Machines/Commodore/Vic-20/Vic20.cpp +++ b/Machines/Commodore/Vic-20/Vic20.cpp @@ -10,6 +10,7 @@ #include #include "../../../Storage/Tape/Formats/TapePRG.hpp" +#include "../../../Storage/Tape/Parsers/Commodore.hpp" #include "../../../StaticAnalyser/StaticAnalyser.hpp" using namespace Commodore::Vic20; @@ -127,7 +128,25 @@ unsigned int Machine::perform_bus_operation(CPU6502::BusOperation operation, uin // CPU or 6560 costs. if(use_fast_tape_hack_ && tape_->has_tape() && operation == CPU6502::BusOperation::ReadOpcode) { if(address == 0xf7b2) { - printf("Find header\n"); + // Address 0xf7b2 contains a JSR to 0xf8c0 that will fill the tape buffer with the next header. + // So cancel that via a double NOP and fill in the next header programmatically. + Storage::Tape::Commodore::Parser parser; + std::unique_ptr header = parser.get_next_header(tape_->get_tape()); + + // serialise to wherever b2:b3 points + uint16_t tape_buffer_pointer = (uint16_t)user_basic_memory_[0xb2] | (uint16_t)(user_basic_memory_[0xb3] << 8); + if(header) { + header->serialise(&user_basic_memory_[tape_buffer_pointer], 0x8000 - tape_buffer_pointer); + } else { + // no header found, so store end-of-tape + user_basic_memory_[tape_buffer_pointer] = 0x05; // i.e. end of tape + } + + // clear status and the verify flag + user_basic_memory_[0x90] = 0; + user_basic_memory_[0x93] = 0; + + *value = 0x0c; // i.e. NOP abs } else if(address == 0xf90b) { printf("Tape receive\n"); } diff --git a/Storage/Tape/Parsers/Commodore.cpp b/Storage/Tape/Parsers/Commodore.cpp index 332550638..628ad823d 100644 --- a/Storage/Tape/Parsers/Commodore.cpp +++ b/Storage/Tape/Parsers/Commodore.cpp @@ -119,6 +119,20 @@ std::unique_ptr
Parser::get_next_header_body(const std::shared_ptr Parser::get_next_data_body(const std::shared_ptr &tape, bool is_original) { std::unique_ptr data(new Data); diff --git a/Storage/Tape/Parsers/Commodore.hpp b/Storage/Tape/Parsers/Commodore.hpp index ebde8066d..5b36a83c1 100644 --- a/Storage/Tape/Parsers/Commodore.hpp +++ b/Storage/Tape/Parsers/Commodore.hpp @@ -10,7 +10,6 @@ #define Storage_Tape_Parsers_Commodore_hpp #include "TapeParser.hpp" -//#include "Utilities.hpp" #include #include @@ -43,6 +42,12 @@ struct Header { uint16_t ending_address; bool parity_was_valid; bool duplicate_matched; + + /*! + Writes a byte serialised version of this header to @c target, writing at most + @c length bytes. + */ + void serialise(uint8_t *target, uint16_t length); }; struct Data { From 7b43ae0a92f3169be48872e245e0aa42560dd8d1 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 7 May 2017 22:22:59 -0400 Subject: [PATCH 7/8] Implemented a catch for loading the data portion of files. --- Machines/Commodore/Vic-20/Vic20.cpp | 50 ++++++++++++++--------------- 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/Machines/Commodore/Vic-20/Vic20.cpp b/Machines/Commodore/Vic-20/Vic20.cpp index e011d7a9b..4c7beeab5 100644 --- a/Machines/Commodore/Vic-20/Vic20.cpp +++ b/Machines/Commodore/Vic-20/Vic20.cpp @@ -148,7 +148,30 @@ unsigned int Machine::perform_bus_operation(CPU6502::BusOperation operation, uin *value = 0x0c; // i.e. NOP abs } else if(address == 0xf90b) { - printf("Tape receive\n"); + uint8_t x = (uint8_t)get_value_of_register(CPU6502::Register::X); + if(x == 0xe) { + Storage::Tape::Commodore::Parser parser; + std::unique_ptr data = parser.get_next_data(tape_->get_tape()); + uint16_t start_address, end_address; + start_address = (uint16_t)(user_basic_memory_[0xc1] | (user_basic_memory_[0xc2] << 8)); + end_address = (uint16_t)(user_basic_memory_[0xae] | (user_basic_memory_[0xaf] << 8)); + + uint8_t *data_ptr = data->data.data(); + while(start_address != end_address) { + processor_write_memory_map_[start_address >> 10][start_address & 0x3ff] = *data_ptr; + data_ptr++; + start_address++; + } + + user_basic_memory_[0x90] |= 0x40; + + uint8_t flags = (uint8_t)get_value_of_register(CPU6502::Register::Flags); + flags &= ~(uint8_t)(CPU6502::Flag::Carry | CPU6502::Flag::Interrupt); + set_value_of_register(CPU6502::Register::Flags, flags); + + set_value_of_register(CPU6502::Register::ProgramCounter, 0xfccf + 1); + *value = 0x08; + } } } } else { @@ -172,31 +195,6 @@ unsigned int Machine::perform_bus_operation(CPU6502::BusOperation operation, uin tape_->run_for_cycles(1); if(c1540_) c1540_->run_for_cycles(1); - // If using fast tape then: - // if the PC hits 0xf98e, the ROM's tape loading routine, then begin zero cost processing; - // if the PC heads into RAM - // - // Where 'zero cost processing' is taken to be taking the 6560 off the bus (because I know it's - // expensive, and not relevant) then running the tape, the CPU and both 6522s as usual but not - // counting cycles towards the processing budget. So the limit is the host machine. - // - // Note the additional test above for PC hitting 0xf92f, which is a loop in the ROM that waits - // for an interesting interrupt. Up there the fast tape hack goes even further in also cutting - // the CPU out of the action. -/* if(use_fast_tape_hack_ && tape_->has_tape()) { - if(address == 0xf98e && operation == CPU6502::BusOperation::ReadOpcode) { - is_running_at_zero_cost_ = true; - set_clock_is_unlimited(true); - } - if( - (address < 0xe000 && operation == CPU6502::BusOperation::ReadOpcode) || - tape_->get_tape()->is_at_end() - ) { - is_running_at_zero_cost_ = false; - set_clock_is_unlimited(false); - } - }*/ - return 1; } From 61f8f2f18c0865847bbcc38feda630ffd4e47b37 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Mon, 8 May 2017 20:58:55 -0400 Subject: [PATCH 8/8] Switched to a more straightforward way of exiting from tape data loading. --- Machines/Commodore/Vic-20/Vic20.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Machines/Commodore/Vic-20/Vic20.cpp b/Machines/Commodore/Vic-20/Vic20.cpp index 4c7beeab5..84d8bd061 100644 --- a/Machines/Commodore/Vic-20/Vic20.cpp +++ b/Machines/Commodore/Vic-20/Vic20.cpp @@ -156,6 +156,7 @@ unsigned int Machine::perform_bus_operation(CPU6502::BusOperation operation, uin start_address = (uint16_t)(user_basic_memory_[0xc1] | (user_basic_memory_[0xc2] << 8)); end_address = (uint16_t)(user_basic_memory_[0xae] | (user_basic_memory_[0xaf] << 8)); + // perform a via-processor_write_memory_map_ memcpy uint8_t *data_ptr = data->data.data(); while(start_address != end_address) { processor_write_memory_map_[start_address >> 10][start_address & 0x3ff] = *data_ptr; @@ -163,14 +164,16 @@ unsigned int Machine::perform_bus_operation(CPU6502::BusOperation operation, uin start_address++; } + // set tape status, carry and flag user_basic_memory_[0x90] |= 0x40; - uint8_t flags = (uint8_t)get_value_of_register(CPU6502::Register::Flags); flags &= ~(uint8_t)(CPU6502::Flag::Carry | CPU6502::Flag::Interrupt); set_value_of_register(CPU6502::Register::Flags, flags); - set_value_of_register(CPU6502::Register::ProgramCounter, 0xfccf + 1); - *value = 0x08; + // to ensure that execution proceeds to 0xfccf, pretend a NOP was here and + // ensure that the PC leaps to 0xfccf + set_value_of_register(CPU6502::Register::ProgramCounter, 0xfccf); + *value = 0xea; // i.e. NOP implied } } }