From eccf5ca043eacc19901f3d29ce1f3c4b78db4f54 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 14 Feb 2021 22:20:58 -0500 Subject: [PATCH] Makes first effort to wire up the ADB vertical blank input. However: looking at the disassembly, I'm not sure it really is wired to INTR. So work to do. --- InstructionSets/M50740/Executor.cpp | 22 ++++++++++++++++++---- InstructionSets/M50740/Executor.hpp | 5 ++++- Machines/Apple/AppleIIgs/ADB.cpp | 12 +++++++++++- Machines/Apple/AppleIIgs/ADB.hpp | 2 ++ Machines/Apple/AppleIIgs/AppleIIgs.cpp | 3 +++ Machines/Apple/AppleIIgs/Video.cpp | 2 +- 6 files changed, 39 insertions(+), 7 deletions(-) diff --git a/InstructionSets/M50740/Executor.cpp b/InstructionSets/M50740/Executor.cpp index c0b1c554b..e32077fea 100644 --- a/InstructionSets/M50740/Executor.cpp +++ b/InstructionSets/M50740/Executor.cpp @@ -62,6 +62,20 @@ void Executor::reset() { set_program_counter(uint16_t(memory_[0x1ffe] | (memory_[0x1fff] << 8))); } +void Executor::set_interrupt_line(bool line) { + // Super hack: interrupt now, if permitted. Otherwise do nothing. + // So this will fail to catch enabling of interrupts while the line + // is active, amongst other things. + if(interrupt_line_ != line) { + interrupt_line_ = line; + + // TODO: verify interrupt connection. Externally, but stubbed off here. +// if(!interrupt_disable_ && line) { +// perform_interrupt(0x1ff4); +// } + } +} + uint8_t Executor::read(uint16_t address) { address &= 0x1fff; @@ -78,7 +92,7 @@ uint8_t Executor::read(uint16_t address) { case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7: case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf: LOG("Unimplemented Port R read from " << PADHEX(4) << address); - return 0xff; + return 0x00; // Ports P0–P3. case 0xe0: case 0xe2: @@ -199,7 +213,7 @@ uint8_t Executor::flags() { carry_flag_; } -template inline void Executor::perform_interrupt() { +template inline void Executor::perform_interrupt(uint16_t vector) { // BRK has an unused operand. ++program_counter_; push(uint8_t(program_counter_ >> 8)); @@ -456,7 +470,7 @@ template void Executor::pe case AddressingMode::AbsoluteIndirect: address = next16(); - address = unsigned(memory_[address] | (memory_[(address + 1) & 0x1fff] << 8)); + address = unsigned(memory_[address & 0x1fff] | (memory_[(address + 1) & 0x1fff] << 8)); break; default: @@ -587,7 +601,7 @@ template void Executor::perform(uint8_t *operand [[maybe_u } break; case Operation::BRK: - perform_interrupt(); + perform_interrupt(0x1ff4); --program_counter_; // To undo the unavoidable increment // after exiting from here. break; diff --git a/InstructionSets/M50740/Executor.hpp b/InstructionSets/M50740/Executor.hpp index 86dc5a6cf..454e45e5f 100644 --- a/InstructionSets/M50740/Executor.hpp +++ b/InstructionSets/M50740/Executor.hpp @@ -40,7 +40,9 @@ class Executor: public CachingExecutor { public: Executor(PortHandler &); void set_rom(const std::vector &rom); + void reset(); + void set_interrupt_line(bool); /*! Runs, in discrete steps, the minimum number of instructions as it takes to complete at least @c cycles. @@ -150,6 +152,7 @@ class Executor: public CachingExecutor { // Interrupt and timer control. uint8_t interrupt_control_ = 0, timer_control_ = 0; + bool interrupt_line_ = false; // Access helpers. inline uint8_t read(uint16_t address); @@ -158,7 +161,7 @@ class Executor: public CachingExecutor { inline uint8_t pull(); inline void set_flags(uint8_t); inline uint8_t flags(); - template inline void perform_interrupt(); + template inline void perform_interrupt(uint16_t vector); inline void set_port_output(int port); // MARK: - Execution time diff --git a/Machines/Apple/AppleIIgs/ADB.cpp b/Machines/Apple/AppleIIgs/ADB.cpp index afb859a62..9a2fc2644 100644 --- a/Machines/Apple/AppleIIgs/ADB.cpp +++ b/Machines/Apple/AppleIIgs/ADB.cpp @@ -16,6 +16,9 @@ #include "../../../InstructionSets/M50740/Parser.hpp" #include "../../../InstructionSets/Disassembler.hpp" +#define LOG_PREFIX "[ADB GLU] " +#include "../../../Outputs/Log.hpp" + using namespace Apple::IIgs::ADB; namespace { @@ -199,7 +202,10 @@ void GLU::set_port_output(int port, uint8_t value) { } } break; case 3: - modifier_state_ = value; + if(modifier_state_ != (value & 0x30)) { + modifier_state_ = value & 0x30; + LOG("Modifier state: " << int(value & 0x30)); + } // Output is inverted respective to input; the microcontroller // sets a value of '1' in order to pull the ADB bus low. @@ -239,3 +245,7 @@ uint8_t GLU::get_port_input(int port) { void GLU::run_ports_for(Cycles cycles) { bus_.run_for(cycles); } + +void GLU::set_vertical_blank(bool is_blank) { + executor_.set_interrupt_line(is_blank); +} diff --git a/Machines/Apple/AppleIIgs/ADB.hpp b/Machines/Apple/AppleIIgs/ADB.hpp index 8a6bd9617..eea4a0c29 100644 --- a/Machines/Apple/AppleIIgs/ADB.hpp +++ b/Machines/Apple/AppleIIgs/ADB.hpp @@ -44,6 +44,8 @@ class GLU: public InstructionSet::M50740::PortHandler { bool get_command_button() const; bool get_option_button() const; + void set_vertical_blank(bool); + private: InstructionSet::M50740::Executor executor_; diff --git a/Machines/Apple/AppleIIgs/AppleIIgs.cpp b/Machines/Apple/AppleIIgs/AppleIIgs.cpp index 90f1aff60..d4f6da0ca 100644 --- a/Machines/Apple/AppleIIgs/AppleIIgs.cpp +++ b/Machines/Apple/AppleIIgs/AppleIIgs.cpp @@ -895,6 +895,9 @@ class ConcreteMachine: } if(video_.did_flush()) { update_interrupts(); + + const bool is_vertical_blank = video_.last_valid()->get_is_vertical_blank(video_.time_since_flush()); + adb_glu_->set_vertical_blank(is_vertical_blank); } return duration; diff --git a/Machines/Apple/AppleIIgs/Video.cpp b/Machines/Apple/AppleIIgs/Video.cpp index 8368d712c..094610c20 100644 --- a/Machines/Apple/AppleIIgs/Video.cpp +++ b/Machines/Apple/AppleIIgs/Video.cpp @@ -193,7 +193,7 @@ Cycles Video::get_next_sequence_point() const { constexpr int sequence_point_offset = (blank_ticks + left_border_ticks) * CyclesPerTick; - // Seed as the distance ot the next row 0. + // Seed as the distance to the next row 0. int result = CyclesPerLine + sequence_point_offset - cycles_into_row + (Lines - row - 1)*CyclesPerLine; // Replace with the start of the next line, if closer.