1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-25 18:30:07 +00:00

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.
This commit is contained in:
Thomas Harte 2021-02-14 22:20:58 -05:00
parent 24af62a3e5
commit eccf5ca043
6 changed files with 39 additions and 7 deletions

View File

@ -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<false>(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 P0P3.
case 0xe0: case 0xe2:
@ -199,7 +213,7 @@ uint8_t Executor::flags() {
carry_flag_;
}
template<bool is_brk> inline void Executor::perform_interrupt() {
template<bool is_brk> 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 <Operation operation, AddressingMode addressing_mode> 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 <Operation operation> void Executor::perform(uint8_t *operand [[maybe_u
} break;
case Operation::BRK:
perform_interrupt<true>();
perform_interrupt<true>(0x1ff4);
--program_counter_; // To undo the unavoidable increment
// after exiting from here.
break;

View File

@ -40,7 +40,9 @@ class Executor: public CachingExecutor {
public:
Executor(PortHandler &);
void set_rom(const std::vector<uint8_t> &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<bool is_brk> inline void perform_interrupt();
template<bool is_brk> inline void perform_interrupt(uint16_t vector);
inline void set_port_output(int port);
// MARK: - Execution time

View File

@ -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);
}

View File

@ -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_;

View File

@ -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;

View File

@ -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.