1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-02-21 05:29:13 +00:00

Reduce repetitive dynamic work in 6522 usages.

This commit is contained in:
Thomas Harte 2025-01-22 14:28:28 -05:00
parent b67bb50f4a
commit f8e4023307
9 changed files with 132 additions and 101 deletions

View File

@ -33,15 +33,18 @@ enum Line {
class PortHandler {
public:
/// Requests the current input value of the named port from the port handler.
uint8_t get_port_input(Port) {
template<Port port>
uint8_t get_port_input() const {
return 0xff;
}
/// Sets the current output value of the named oprt and provides @c direction_mask, indicating which pins are marked as output.
void set_port_output(Port, [[maybe_unused]] uint8_t value, [[maybe_unused]] uint8_t direction_mask) {}
template<Port port>
void set_port_output([[maybe_unused]] uint8_t value, [[maybe_unused]] uint8_t direction_mask) {}
/// Sets the current logical output level for the named line on the specified port.
void set_control_line_output(Port, Line, [[maybe_unused]] bool value) {}
template<Port port, Line line>
void set_control_line_output([[maybe_unused]] bool value) {}
/// Sets the current logical value of the interrupt line.
void set_interrupt_status([[maybe_unused]] bool status) {}
@ -101,7 +104,8 @@ public:
BusHandlerT &bus_handler();
/// Sets the input value of the named line and port.
void set_control_line_input(Port, Line, bool value);
template<Port, Line>
void set_control_line_input(bool value);
/// Runs for a specified number of half cycles.
void run_for(const HalfCycles);
@ -126,12 +130,13 @@ private:
void access(int address);
uint8_t get_port_input(Port port, uint8_t output_mask, uint8_t output, uint8_t timer_mask);
template <Port> uint8_t get_port_input(uint8_t output_mask, uint8_t output, uint8_t timer_mask);
template <Port port, int shift> void update_pcr(const uint8_t);
inline void reevaluate_interrupts();
/// Sets the current intended output value for the port and line;
/// if this affects the visible output, it will be passed to the handler.
void set_control_line_output(Port port, Line line, LineState value);
template <Port, Line> void set_control_line_output(LineState);
void evaluate_cb2_output();
void evaluate_port_b_output();
};

View File

@ -19,7 +19,7 @@ template <typename T> void MOS6522<T>::access(const int address) {
case 0x0:
// In both handshake and pulse modes, CB2 goes low on any read or write of Port B.
if(handshake_modes_[1] != HandshakeMode::None) {
set_control_line_output(Port::B, Line::Two, LineState::Off);
set_control_line_output<Port::B, Line::Two>(LineState::Off);
}
break;
@ -27,7 +27,7 @@ template <typename T> void MOS6522<T>::access(const int address) {
case 0x1:
// In both handshake and pulse modes, CA2 goes low on any read or write of Port A.
if(handshake_modes_[0] != HandshakeMode::None) {
set_control_line_output(Port::A, Line::Two, LineState::Off);
set_control_line_output<Port::A, Line::Two>(LineState::Off);
}
break;
}
@ -55,10 +55,10 @@ template <typename T> void MOS6522<T>::write(int address, const uint8_t value) {
registers_.output[0] = value;
bus_handler_.run_for(time_since_bus_handler_call_.flush<HalfCycles>());
bus_handler_.set_port_output(Port::A, value, registers_.data_direction[0]);
bus_handler_.template set_port_output<Port::A>(value, registers_.data_direction[0]);
if(handshake_modes_[1] != HandshakeMode::None) {
set_control_line_output(Port::A, Line::Two, LineState::Off);
set_control_line_output<Port::A, Line::Two>(LineState::Off);
}
registers_.interrupt_flags &= ~(
@ -136,40 +136,8 @@ template <typename T> void MOS6522<T>::write(int address, const uint8_t value) {
// const auto old_peripheral_control = registers_.peripheral_control;
registers_.peripheral_control = value;
int shift = 0;
for(int port = 0; port < 2; ++port) {
handshake_modes_[port] = HandshakeMode::None;
switch((value >> shift) & 0x0e) {
default: break;
case 0x00: // Negative interrupt input; set Cx2 interrupt on negative Cx2 transition, clear on access to Port x register.
case 0x02: // Independent negative interrupt input; set Cx2 interrupt on negative transition, don't clear automatically.
case 0x04: // Positive interrupt input; set Cx2 interrupt on positive Cx2 transition, clear on access to Port x register.
case 0x06: // Independent positive interrupt input; set Cx2 interrupt on positive transition, don't clear automatically.
set_control_line_output(Port(port), Line::Two, LineState::Input);
break;
case 0x08: // Handshake: set Cx2 to low on any read or write of Port x; set to high on an active transition of Cx1.
handshake_modes_[port] = HandshakeMode::Handshake;
set_control_line_output(Port(port), Line::Two, LineState::Off); // At a guess.
break;
case 0x0a: // Pulse output: Cx2 is low for one cycle following a read or write of Port x.
handshake_modes_[port] = HandshakeMode::Pulse;
set_control_line_output(Port(port), Line::Two, LineState::On);
break;
case 0x0c: // Manual output: Cx2 low.
set_control_line_output(Port(port), Line::Two, LineState::Off);
break;
case 0x0e: // Manual output: Cx2 high.
set_control_line_output(Port(port), Line::Two, LineState::On);
break;
}
shift += 4;
}
update_pcr<Port::A, 0>(value);
update_pcr<Port::B, 4>(value);
} break;
// Interrupt control
@ -187,6 +155,40 @@ template <typename T> void MOS6522<T>::write(int address, const uint8_t value) {
}
}
template <typename T>
template <Port port, int shift>
void MOS6522<T>::update_pcr(const uint8_t value) {
handshake_modes_[port] = HandshakeMode::None;
switch((value >> shift) & 0x0e) {
default: break;
case 0x00: // Negative interrupt input; set Cx2 interrupt on negative Cx2 transition, clear on access to Port x register.
case 0x02: // Independent negative interrupt input; set Cx2 interrupt on negative transition, don't clear automatically.
case 0x04: // Positive interrupt input; set Cx2 interrupt on positive Cx2 transition, clear on access to Port x register.
case 0x06: // Independent positive interrupt input; set Cx2 interrupt on positive transition, don't clear automatically.
set_control_line_output<port, Line::Two>(LineState::Input);
break;
case 0x08: // Handshake: set Cx2 to low on any read or write of Port x; set to high on an active transition of Cx1.
handshake_modes_[port] = HandshakeMode::Handshake;
set_control_line_output<port, Line::Two>(LineState::Off); // At a guess.
break;
case 0x0a: // Pulse output: Cx2 is low for one cycle following a read or write of Port x.
handshake_modes_[port] = HandshakeMode::Pulse;
set_control_line_output<port, Line::Two>(LineState::On);
break;
case 0x0c: // Manual output: Cx2 low.
set_control_line_output<port, Line::Two>(LineState::Off);
break;
case 0x0e: // Manual output: Cx2 high.
set_control_line_output<port, Line::Two>(LineState::On);
break;
}
}
template <typename T> uint8_t MOS6522<T>::read(int address) {
address &= 0xf;
access(address);
@ -194,12 +196,12 @@ template <typename T> uint8_t MOS6522<T>::read(int address) {
case 0x0: // Read Port B ('IRB').
registers_.interrupt_flags &= ~(InterruptFlag::CB1ActiveEdge | InterruptFlag::CB2ActiveEdge);
reevaluate_interrupts();
return get_port_input(Port::B, registers_.data_direction[1], registers_.output[1], registers_.auxiliary_control & 0x80);
return get_port_input<Port::B>(registers_.data_direction[1], registers_.output[1], registers_.auxiliary_control & 0x80);
case 0xf:
case 0x1: // Read Port A ('IRA').
registers_.interrupt_flags &= ~(InterruptFlag::CA1ActiveEdge | InterruptFlag::CA2ActiveEdge);
reevaluate_interrupts();
return get_port_input(Port::A, registers_.data_direction[0], registers_.output[0], 0);
return get_port_input<Port::A>(registers_.data_direction[0], registers_.output[0], 0);
case 0x2: return registers_.data_direction[1]; // Port B direction ('DDRB').
case 0x3: return registers_.data_direction[0]; // Port A direction ('DDRA').
@ -236,14 +238,15 @@ template <typename T> uint8_t MOS6522<T>::read(int address) {
return 0xff;
}
template <typename T> uint8_t MOS6522<T>::get_port_input(
const Port port,
template <typename T>
template <Port port>
uint8_t MOS6522<T>::get_port_input(
const uint8_t output_mask,
uint8_t output,
const uint8_t timer_mask
) {
bus_handler_.run_for(time_since_bus_handler_call_.flush<HalfCycles>());
const uint8_t input = bus_handler_.get_port_input(port);
const uint8_t input = bus_handler_.template get_port_input<port>();
output = (output & ~timer_mask) | (registers_.timer_port_b_output & timer_mask);
return (input & ~output_mask) | (output & output_mask);
}
@ -263,13 +266,15 @@ template <typename T> void MOS6522<T>::reevaluate_interrupts() {
}
}
template <typename T> void MOS6522<T>::set_control_line_input(const Port port, const Line line, const bool value) {
template <typename T>
template <Port port, Line line>
void MOS6522<T>::set_control_line_input(const bool value) {
switch(line) {
case Line::One:
if(value != control_inputs_[port].lines[line]) {
// In handshake mode, any transition on C[A/B]1 sets output high on C[A/B]2.
if(handshake_modes_[port] == HandshakeMode::Handshake) {
set_control_line_output(port, Line::Two, LineState::On);
set_control_line_output<port, Line::Two>(LineState::On);
}
// Set the proper transition interrupt bit if enabled.
@ -332,10 +337,10 @@ template <typename T> void MOS6522<T>::do_phase2() {
// In pulse modes, CA2 and CB2 go high again on the next clock edge.
if(handshake_modes_[1] == HandshakeMode::Pulse) {
set_control_line_output(Port::B, Line::Two, LineState::On);
set_control_line_output<Port::B, Line::Two>(LineState::On);
}
if(handshake_modes_[0] == HandshakeMode::Pulse) {
set_control_line_output(Port::A, Line::Two, LineState::On);
set_control_line_output<Port::A, Line::Two>(LineState::On);
}
// If the shift register is shifting according to the input clock, do a shift.
@ -388,8 +393,7 @@ template <typename T> void MOS6522<T>::do_phase1() {
template <typename T> void MOS6522<T>::evaluate_port_b_output() {
// Apply current timer-linked PB7 output if any atop the stated output.
const uint8_t timer_control_bit = registers_.auxiliary_control & 0x80;
bus_handler_.set_port_output(
Port::B,
bus_handler_.template set_port_output<Port::B>(
(registers_.output[1] & (0xff ^ timer_control_bit)) | timer_control_bit,
registers_.data_direction[1] | timer_control_bit);
}
@ -448,19 +452,20 @@ template <typename T> void MOS6522<T>::evaluate_cb2_output() {
// Shift register is enabled, one way or the other; but announce only output.
if(is_shifting_out()) {
// Output mode; set the level according to the current top of the shift register.
bus_handler_.set_control_line_output(Port::B, Line::Two, !!(registers_.shift & 0x80));
bus_handler_.template set_control_line_output<Port::B, Line::Two>(registers_.shift & 0x80);
} else {
// Input mode.
bus_handler_.set_control_line_output(Port::B, Line::Two, true);
bus_handler_.template set_control_line_output<Port::B, Line::Two>(true);
}
} else {
// Shift register is disabled.
bus_handler_.set_control_line_output(Port::B, Line::Two, control_outputs_[1].lines[1] != LineState::Off);
bus_handler_.template set_control_line_output<Port::B, Line::Two>(control_outputs_[1].lines[1] != LineState::Off);
}
}
template <typename T>
void MOS6522<T>::set_control_line_output(const Port port, const Line line, const LineState value) {
template <Port port, Line line>
void MOS6522<T>::set_control_line_output(const LineState value) {
if(port == Port::B && line == Line::Two) {
control_outputs_[port].lines[line] = value;
evaluate_cb2_output();
@ -474,7 +479,7 @@ void MOS6522<T>::set_control_line_output(const Port port, const Line line, const
if(value != LineState::Input) {
bus_handler_.run_for(time_since_bus_handler_call_.flush<HalfCycles>());
bus_handler_.set_control_line_output(port, line, value != LineState::Off);
bus_handler_.template set_control_line_output<port, line>(value != LineState::Off);
}
}
}

View File

@ -99,7 +99,8 @@ private:
card.did_change_interrupt_flags();
}
void set_port_output(MOS::MOS6522::Port port, uint8_t value, uint8_t) {
template <MOS::MOS6522::Port port>
void set_port_output(const uint8_t value, uint8_t) {
if(port) {
using ControlLines = GI::AY38910::ControlLines;
ay.set_control_lines(
@ -116,7 +117,8 @@ private:
}
}
uint8_t get_port_input(MOS::MOS6522::Port port) {
template <MOS::MOS6522::Port port>
uint8_t get_port_input() const {
if(!port) {
return ay.get_data_output();
}

View File

@ -579,7 +579,7 @@ private:
time_since_video_update_ -= time_until_video_event_;
time_until_video_event_ = video_.next_sequence_point();
via_.set_control_line_input(MOS::MOS6522::Port::A, MOS::MOS6522::Line::One, !video_.vsync());
via_.template set_control_line_input<MOS::MOS6522::Port::A, MOS::MOS6522::Line::One>(!video_.vsync());
}
via_clock_ += via_cycles_outstanding;
@ -592,8 +592,8 @@ private:
if(keyboard_clock_ >= KEYBOARD_CLOCK_RATE) {
const auto keyboard_ticks = keyboard_clock_.divide(KEYBOARD_CLOCK_RATE);
keyboard_.run_for(keyboard_ticks);
via_.set_control_line_input(MOS::MOS6522::Port::B, MOS::MOS6522::Line::Two, keyboard_.get_data());
via_.set_control_line_input(MOS::MOS6522::Port::B, MOS::MOS6522::Line::One, keyboard_.get_clock());
via_.template set_control_line_input<MOS::MOS6522::Port::B, MOS::MOS6522::Line::Two>(keyboard_.get_data());
via_.template set_control_line_input<MOS::MOS6522::Port::B, MOS::MOS6522::Line::One>(keyboard_.get_clock());
}
// Feed mouse inputs within at most 1250 cycles of each other.
@ -616,8 +616,8 @@ private:
while(ticks--) {
clock_.update();
// TODO: leave a delay between toggling the input rather than using this coupled hack.
via_.set_control_line_input(MOS::MOS6522::Port::A, MOS::MOS6522::Line::Two, true);
via_.set_control_line_input(MOS::MOS6522::Port::A, MOS::MOS6522::Line::Two, false);
via_.template set_control_line_input<MOS::MOS6522::Port::A, MOS::MOS6522::Line::Two>(true);
via_.template set_control_line_input<MOS::MOS6522::Port::A, MOS::MOS6522::Line::Two>(false);
}
// Update the SCSI if currently active.
@ -645,7 +645,7 @@ private:
using Port = MOS::MOS6522::Port;
using Line = MOS::MOS6522::Line;
void set_port_output(Port port, uint8_t value, uint8_t) {
template <Port port> void set_port_output(const uint8_t value, uint8_t) {
/*
Peripheral lines: keyboard data, interrupt configuration.
(See p176 [/215])
@ -691,7 +691,7 @@ private:
}
}
uint8_t get_port_input(Port port) {
template <Port port> uint8_t get_port_input() const {
switch(port) {
case Port::A:
// printf("6522 r A\n");
@ -711,7 +711,7 @@ private:
return 0xff;
}
void set_control_line_output(Port port, Line line, bool value) {
template <Port port, Line line> void set_control_line_output(const bool value) {
/*
Keyboard wiring (I believe):
CB2 = data (input/output)

View File

@ -162,12 +162,14 @@ void MachineBase::drive_via_did_set_data_density(void *, const int density) {
// MARK: - SerialPortVIA
uint8_t SerialPortVIA::get_port_input(MOS::MOS6522::Port port) {
template <MOS::MOS6522::Port port>
uint8_t SerialPortVIA::get_port_input() const {
if(port) return port_b_;
return 0xff;
}
void SerialPortVIA::set_port_output(MOS::MOS6522::Port port, uint8_t value, uint8_t) {
template <MOS::MOS6522::Port port>
void SerialPortVIA::set_port_output(const uint8_t value, uint8_t) {
if(port) {
attention_acknowledge_level_ = !(value&0x10);
data_level_output_ = (value&0x02);
@ -178,8 +180,8 @@ void SerialPortVIA::set_port_output(MOS::MOS6522::Port port, uint8_t value, uint
}
void SerialPortVIA::set_serial_line_state(
::Commodore::Serial::Line line,
bool value,
const Commodore::Serial::Line line,
const bool value,
MOS::MOS6522::MOS6522<SerialPortVIA> &via
) {
switch(line) {
@ -189,7 +191,7 @@ void SerialPortVIA::set_serial_line_state(
case ::Commodore::Serial::Line::Attention:
attention_level_input_ = !value;
port_b_ = (port_b_ & ~0x80) | (value ? 0x00 : 0x80);
via.set_control_line_input(MOS::MOS6522::Port::A, MOS::MOS6522::Line::One, !value);
via.set_control_line_input<MOS::MOS6522::Port::A, MOS::MOS6522::Line::One>(!value);
update_data_line();
break;
}
@ -212,11 +214,12 @@ void DriveVIA::set_delegate(Delegate *delegate) {
}
// write protect tab uncovered
uint8_t DriveVIA::get_port_input(MOS::MOS6522::Port port) {
template <MOS::MOS6522::Port port>
uint8_t DriveVIA::get_port_input() const {
return port ? port_b_ : port_a_;
}
void DriveVIA::set_sync_detected(bool sync_detected) {
void DriveVIA::set_sync_detected(const bool sync_detected) {
port_b_ = (port_b_ & 0x7f) | (sync_detected ? 0x00 : 0x80);
}
@ -232,13 +235,15 @@ bool DriveVIA::get_motor_enabled() {
return drive_motor_;
}
void DriveVIA::set_control_line_output(MOS::MOS6522::Port port, MOS::MOS6522::Line line, bool value) {
template <MOS::MOS6522::Port port, MOS::MOS6522::Line line>
void DriveVIA::set_control_line_output(const bool value) {
if(port == MOS::MOS6522::Port::A && line == MOS::MOS6522::Line::Two) {
should_set_overflow_ = value;
}
}
void DriveVIA::set_port_output(MOS::MOS6522::Port port, uint8_t value, uint8_t) {
template <MOS::MOS6522::Port port>
void DriveVIA::set_port_output(const uint8_t value, uint8_t) {
if(port) {
if(previous_port_b_output_ != value) {
// Record drive motor state.
@ -275,6 +280,7 @@ void DriveVIA::set_activity_observer(Activity::Observer *observer) {
// MARK: - SerialPort
void SerialPort::set_input(Serial::Line line, Serial::LineLevel level) {
// TODO: add dynamic.
serial_port_via_->set_serial_line_state(line, bool(level), *via_);
}

View File

@ -39,10 +39,13 @@ namespace Commodore::C1540 {
*/
class SerialPortVIA: public MOS::MOS6522::IRQDelegatePortHandler {
public:
uint8_t get_port_input(MOS::MOS6522::Port);
template <MOS::MOS6522::Port>
uint8_t get_port_input() const;
void set_port_output(MOS::MOS6522::Port, uint8_t value, uint8_t mask);
void set_serial_line_state(::Commodore::Serial::Line, bool, MOS::MOS6522::MOS6522<SerialPortVIA> &);
template <MOS::MOS6522::Port>
void set_port_output(uint8_t value, uint8_t mask);
void set_serial_line_state(Commodore::Serial::Line, bool, MOS::MOS6522::MOS6522<SerialPortVIA> &);
void set_serial_port(Commodore::Serial::Port &);
@ -56,6 +59,13 @@ private:
void update_data_line();
};
//inline void set_serial_line_state(Commodore::Serial::Line line bool value, MOS::MOS6522::MOS6522<SerialPortVIA> &via) {
// switch(line){
// case Commodore::Serial::Line::One:
// via.set_serial_line_state<Commodore::Serial::Line::One>(value, via);
// }
//}
/*!
An implementation of the drive VIA in a Commodore 1540: the VIA that is used to interface with the disk.
@ -81,16 +91,19 @@ public:
};
void set_delegate(Delegate *);
uint8_t get_port_input(MOS::MOS6522::Port);
template <MOS::MOS6522::Port>
uint8_t get_port_input() const;
void set_sync_detected(bool);
void set_data_input(uint8_t);
bool get_should_set_overflow();
bool get_motor_enabled();
void set_control_line_output(MOS::MOS6522::Port, MOS::MOS6522::Line, bool value);
template <MOS::MOS6522::Port, MOS::MOS6522::Line>
void set_control_line_output(bool value);
void set_port_output(MOS::MOS6522::Port, uint8_t value, uint8_t direction_mask);
template <MOS::MOS6522::Port>
void set_port_output(uint8_t value, uint8_t direction_mask);
void set_activity_observer(Activity::Observer *);

View File

@ -104,7 +104,7 @@ public:
/*!
Called by the bus to signal a change in any input line level. Subclasses should implement this.
*/
virtual void set_input(Line line, LineLevel value) = 0;
virtual void set_input(Line, LineLevel) = 0;
/*!
Sets the supplied serial bus as that to which line levels will be communicated.

View File

@ -68,7 +68,7 @@ public:
UserPortVIA() : port_a_(0xbf) {}
/// Reports the current input to the 6522 port @c port.
uint8_t get_port_input(const MOS::MOS6522::Port port) {
template <MOS::MOS6522::Port port> uint8_t get_port_input() const {
// Port A provides information about the presence or absence of a tape, and parts of
// the joystick and serial port state, both of which have been statefully collected
// into port_a_.
@ -79,7 +79,7 @@ public:
}
/// Receives announcements of control line output change from the 6522.
void set_control_line_output(const MOS::MOS6522::Port port, const MOS::MOS6522::Line line, const bool value) {
template <MOS::MOS6522::Port port, MOS::MOS6522::Line line> void set_control_line_output(const bool value) {
// The CA2 output is used to control the tape motor.
if(port == MOS::MOS6522::Port::A && line == MOS::MOS6522::Line::Two) {
tape_->set_motor_control(!value);
@ -87,7 +87,7 @@ public:
}
/// Receives announcements of changes in the serial bus connected to the serial port and propagates them into Port A.
void set_serial_line_state(const ::Commodore::Serial::Line line, const bool value) {
void set_serial_line_state(Commodore::Serial::Line line, const bool value) {
switch(line) {
default: break;
case ::Commodore::Serial::Line::Data: port_a_ = (port_a_ & ~0x02) | (value ? 0x02 : 0x00); break;
@ -103,7 +103,7 @@ public:
}
/// Receives announcements from the 6522 of user-port output, which might affect what's currently being presented onto the serial bus.
void set_port_output(const MOS::MOS6522::Port port, const uint8_t value, uint8_t) {
template <MOS::MOS6522::Port port> void set_port_output(const uint8_t value, uint8_t) {
// Line 7 of port A is inverted and output as serial ATN.
if(!port) {
serial_port_->set_output(Serial::Line::Attention, Serial::LineLevel(!(value&0x80)));
@ -150,7 +150,7 @@ public:
}
/// Called by the 6522 to get input. Reads the keyboard on Port A, returns a small amount of joystick state on Port B.
uint8_t get_port_input(const MOS::MOS6522::Port port) {
template <MOS::MOS6522::Port port> uint8_t get_port_input() const {
if(!port) {
uint8_t result = 0xff;
for(int c = 0; c < 8; c++) {
@ -164,12 +164,12 @@ public:
}
/// Called by the 6522 to set output. The value of Port B selects which part of the keyboard to read.
void set_port_output(const MOS::MOS6522::Port port, const uint8_t value, const uint8_t mask) {
template <MOS::MOS6522::Port port> void set_port_output(const uint8_t value, const uint8_t mask) {
if(port) activation_mask_ = (value & mask) | (~mask);
}
/// Called by the 6522 to set control line output. Which affects the serial port.
void set_control_line_output(const MOS::MOS6522::Port port, const MOS::MOS6522::Line line, const bool value) {
template <MOS::MOS6522::Port port, MOS::MOS6522::Line line> void set_control_line_output(const bool value) {
if(line == MOS::MOS6522::Line::Two) {
// CB2 is inverted to become serial data; CA2 is inverted to become serial clock
if(port == MOS::MOS6522::Port::A)
@ -469,7 +469,7 @@ public:
} else {
switch(key) {
case KeyRestore:
user_port_via_.set_control_line_input(MOS::MOS6522::Port::A, MOS::MOS6522::Line::One, !is_pressed);
user_port_via_.set_control_line_input<MOS::MOS6522::Port::A, MOS::MOS6522::Line::One>(!is_pressed);
break;
#define ShiftedMap(source, target) \
case source: \
@ -694,7 +694,7 @@ public:
}
void tape_did_change_input(Storage::Tape::BinaryTapePlayer *const tape) final {
keyboard_via_.set_control_line_input(MOS::MOS6522::Port::A, MOS::MOS6522::Line::One, !tape->input());
keyboard_via_.set_control_line_input<MOS::MOS6522::Port::A, MOS::MOS6522::Line::One>(!tape->input());
}
KeyboardMapper *get_keyboard_mapper() final {

View File

@ -193,7 +193,7 @@ class VIAPortHandler: public MOS::MOS6522::IRQDelegatePortHandler {
Reponds to the 6522's control line output change signal; on an Oric A2 is connected to
the AY's BDIR, and B2 is connected to the AY's A2.
*/
void set_control_line_output(MOS::MOS6522::Port port, MOS::MOS6522::Line line, bool value) {
template <MOS::MOS6522::Port port, MOS::MOS6522::Line line> void set_control_line_output(const bool value) {
if(line) {
if(port) ay_bdir_ = value; else ay_bc1_ = value;
update_ay();
@ -205,7 +205,7 @@ class VIAPortHandler: public MOS::MOS6522::IRQDelegatePortHandler {
Reponds to changes in the 6522's port output. On an Oric port B sets the tape motor control
and the keyboard's active row. Port A is connected to the AY's data bus.
*/
void set_port_output(MOS::MOS6522::Port port, uint8_t value, uint8_t) {
template <MOS::MOS6522::Port port> void set_port_output(uint8_t value, uint8_t) {
if(port) {
keyboard_.set_active_row(value);
tape_player_.set_motor_control(value & 0x40);
@ -219,7 +219,7 @@ class VIAPortHandler: public MOS::MOS6522::IRQDelegatePortHandler {
/*!
Provides input data for the 6522. Port B reads the keyboard, and port A reads from the AY.
*/
uint8_t get_port_input(MOS::MOS6522::Port port) {
template <MOS::MOS6522::Port port> uint8_t get_port_input() const {
if(port) {
uint8_t column = ay8910_.get_port_output(false) ^ 0xff;
return keyboard_.query_column(column) ? 0x08 : 0x00;
@ -630,8 +630,7 @@ template <Analyser::Static::Oric::Target::DiskInterface disk_interface, CPU::MOS
void set_via_port_b_input() {
// set CB1
via_.set_control_line_input(
MOS::MOS6522::Port::B, MOS::MOS6522::Line::One,
via_.set_control_line_input<MOS::MOS6522::Port::B, MOS::MOS6522::Line::One>(
tape_player_.motor_control() ?
!tape_player_.input() :
!video_->vsync()
@ -811,7 +810,8 @@ using namespace Oric;
namespace {
template <CPU::MOS6502Esque::Type processor> std::unique_ptr<Machine> machine(const Analyser::Static::Oric::Target &target, const ROMMachine::ROMFetcher &rom_fetcher) {
template <CPU::MOS6502Esque::Type processor>
std::unique_ptr<Machine> machine(const Analyser::Static::Oric::Target &target, const ROMMachine::ROMFetcher &rom_fetcher) {
switch(target.disk_interface) {
default: return std::make_unique<ConcreteMachine<DiskInterface::None, processor>>(target, rom_fetcher);
case DiskInterface::Microdisc: return std::make_unique<ConcreteMachine<DiskInterface::Microdisc, processor>>(target, rom_fetcher);