diff --git a/Components/6522/6522.hpp b/Components/6522/6522.hpp index 91e785aef..34bb53f74 100644 --- a/Components/6522/6522.hpp +++ b/Components/6522/6522.hpp @@ -112,17 +112,17 @@ template class MOS6522 { _registers.auxiliary_control = value; break; case 0xc: - printf("Peripheral control %02x\n", value); +// printf("Peripheral control %02x\n", value); _registers.peripheral_control = value; switch(value & 0x0e) { - default: break; + default: printf("Unimplemented control line mode %d\n", (value >> 1)&7); break; case 0x0c: static_cast(this)->set_control_line_output(Port::A, Line::Two, false); break; case 0x0e: static_cast(this)->set_control_line_output(Port::A, Line::Two, true); break; } switch(value & 0xe0) { - default: break; + default: printf("Unimplemented control line mode %d\n", (value >> 5)&7); break; case 0xc0: static_cast(this)->set_control_line_output(Port::B, Line::Two, false); break; case 0xe0: static_cast(this)->set_control_line_output(Port::B, Line::Two, true); break; } diff --git a/Machines/Vic-20/Vic20.cpp b/Machines/Vic-20/Vic20.cpp index ca19e6c70..c912908b4 100644 --- a/Machines/Vic-20/Vic20.cpp +++ b/Machines/Vic-20/Vic20.cpp @@ -15,8 +15,16 @@ using namespace Vic20; Machine::Machine() : _rom(nullptr) { - _userPortVIA.set_delegate(this); - _keyboardVIA.set_delegate(this); + _userPortVIA.reset(new UserPortVIA); + _keyboardVIA.reset(new KeyboardVIA); + _serialPort.reset(new SerialPort); + + _userPortVIA->set_serial_port(_serialPort); + _keyboardVIA->set_serial_port(_serialPort); + _serialPort->set_vias(_userPortVIA, _keyboardVIA); + + _userPortVIA->set_delegate(this); + _keyboardVIA->set_delegate(this); _tape.set_delegate(this); memset(_videoMemoryMap, 0, sizeof(_videoMemoryMap)); @@ -71,8 +79,8 @@ unsigned int Machine::perform_bus_operation(CPU6502::BusOperation operation, uin if((address&0xfc00) == 0x9000) { if((address&0xff00) == 0x9000) result &= _mos6560->get_register(address); - if((address&0xfc10) == 0x9010) result &= _userPortVIA.get_register(address); - if((address&0xfc20) == 0x9020) result &= _keyboardVIA.get_register(address); + if((address&0xfc10) == 0x9010) result &= _userPortVIA->get_register(address); + if((address&0xfc20) == 0x9020) result &= _keyboardVIA->get_register(address); } *value = result; @@ -80,10 +88,10 @@ unsigned int Machine::perform_bus_operation(CPU6502::BusOperation operation, uin if(_use_fast_tape_hack && address == 0xf92f && operation == CPU6502::BusOperation::ReadOpcode) { // advance time on the tape and the VIAs until an interrupt is signalled - while(!_userPortVIA.get_interrupt_line() && !_keyboardVIA.get_interrupt_line()) + while(!_userPortVIA->get_interrupt_line() && !_keyboardVIA->get_interrupt_line()) { - _userPortVIA.run_for_half_cycles(2); - _keyboardVIA.run_for_half_cycles(2); + _userPortVIA->run_for_half_cycles(2); + _keyboardVIA->run_for_half_cycles(2); _tape.run_for_cycles(1); } } @@ -95,13 +103,13 @@ unsigned int Machine::perform_bus_operation(CPU6502::BusOperation operation, uin if((address&0xfc00) == 0x9000) { if((address&0xff00) == 0x9000) _mos6560->set_register(address, *value); - if((address&0xfc10) == 0x9010) _userPortVIA.set_register(address, *value); - if((address&0xfc20) == 0x9020) _keyboardVIA.set_register(address, *value); + if((address&0xfc10) == 0x9010) _userPortVIA->set_register(address, *value); + if((address&0xfc20) == 0x9020) _keyboardVIA->set_register(address, *value); } } - _userPortVIA.run_for_half_cycles(2); - _keyboardVIA.run_for_half_cycles(2); + _userPortVIA->run_for_half_cycles(2); + _keyboardVIA->run_for_half_cycles(2); if(_typer) _typer->update(1); _tape.run_for_cycles(1); return 1; @@ -111,8 +119,8 @@ unsigned int Machine::perform_bus_operation(CPU6502::BusOperation operation, uin void Machine::mos6522_did_change_interrupt_status(void *mos6522) { - set_nmi_line(_userPortVIA.get_interrupt_line()); - set_irq_line(_keyboardVIA.get_interrupt_line()); + set_nmi_line(_userPortVIA->get_interrupt_line()); + set_irq_line(_keyboardVIA->get_interrupt_line()); } #pragma mark - Setup @@ -172,7 +180,7 @@ void Machine::set_tape(std::shared_ptr tape) void Machine::tape_did_change_input(Tape *tape) { - _keyboardVIA.set_control_line_input(KeyboardVIA::Port::A, KeyboardVIA::Line::One, tape->get_input()); + _keyboardVIA->set_control_line_input(KeyboardVIA::Port::A, KeyboardVIA::Line::One, tape->get_input()); } #pragma mark - Typer @@ -306,3 +314,35 @@ void Tape::process_input_pulse(Storage::Tape::Pulse pulse) if(_delegate) _delegate->tape_did_change_input(this); } } + +#pragma mark - Serial Port + +void SerialPort::set_clock_output(bool value) +{ + printf("Serial port clock output %s\n", value ? "on" : "off"); +} + +void SerialPort::set_data_output(bool value) +{ + printf("Serial port data output %s\n", value ? "on" : "off"); +} + +void SerialPort::set_attention_output(bool value) +{ + printf("Serial port attention output %s\n", value ? "on" : "off"); +} + +void SerialPort::set_clock_input(bool value) +{ + printf("Serial port clock input %s\n", value ? "on" : "off"); +} + +void SerialPort::set_data_input(bool value) +{ + printf("Serial port data input %s\n", value ? "on" : "off"); +} + +void SerialPort::set_attention_input(bool value) +{ + printf("Serial port attention input %s\n", value ? "on" : "off"); +} diff --git a/Machines/Vic-20/Vic20.hpp b/Machines/Vic-20/Vic20.hpp index a7dc1d692..4c298aa13 100644 --- a/Machines/Vic-20/Vic20.hpp +++ b/Machines/Vic-20/Vic20.hpp @@ -49,27 +49,82 @@ enum Key: uint16_t { TerminateSequence = 0, NotMapped = 0xffff }; +enum JoystickInput { + Up = 0x04, + Down = 0x08, + Left = 0x10, + Right = 0x80, + Fire = 0x20 +}; + +class UserPortVIA; +class KeyboardVIA; + +class SerialPort { + public: + void set_clock_output(bool value); + void set_data_output(bool value); + void set_attention_output(bool value); + + void set_clock_input(bool value); + void set_data_input(bool value); + void set_attention_input(bool value); + + void set_vias(std::shared_ptr userPortVIA, std::shared_ptr keyboardVIA) { + _userPortVIA = userPortVIA; + _keyboardVIA = keyboardVIA; + } + + private: + std::weak_ptr _userPortVIA; + std::weak_ptr _keyboardVIA; +}; + class UserPortVIA: public MOS::MOS6522, public MOS::MOS6522IRQDelegate { public: uint8_t get_port_input(Port port) { if(!port) { - return 0x00; // TODO: bit 6 should be high if there is no tape, low otherwise + return _portA; // TODO: bit 6 should be high if there is no tape, low otherwise } return 0xff; } void 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) { +// printf("Tape motor %s\n", value ? "on" : "off"); +// } + } + + void set_joystick_state(JoystickInput input, bool value) { + if(input != JoystickInput::Right) + { + _portA = (_portA & ~input) | (value ? 0 : input); + } + } + + void set_port_output(Port port, uint8_t value, uint8_t mask) { + if(!port) { + std::shared_ptr serialPort = _serialPort.lock(); + if(serialPort) serialPort->set_attention_output(!(value&0x80)); } } using MOS6522IRQDelegate::set_interrupt_status; + + UserPortVIA() : _portA(0xbf) {} + + void set_serial_port(std::shared_ptr serialPort) { + _serialPort = serialPort; + } + + private: + uint8_t _portA; + std::weak_ptr _serialPort; }; class KeyboardVIA: public MOS::MOS6522, public MOS::MOS6522IRQDelegate { public: - KeyboardVIA() { + KeyboardVIA() : _portB(0xff) { clear_all_keys(); } @@ -96,7 +151,7 @@ class KeyboardVIA: public MOS::MOS6522, public MOS::MOS6522IRQDeleg return result; } - return 0xff; + return _portB; } void set_port_output(Port port, uint8_t value, uint8_t mask) { @@ -105,16 +160,36 @@ class KeyboardVIA: public MOS::MOS6522, public MOS::MOS6522IRQDeleg } void set_control_line_output(Port port, Line line, bool value) { - if(port == Port::A && line == Line::Two) { - printf("Blah Tape motor %s\n", value ? "on" : "off"); + if(line == Line::Two) { + std::shared_ptr serialPort = _serialPort.lock(); + if(serialPort) { + if(port == Port::A) { + serialPort->set_clock_output(value); + } else { + serialPort->set_data_output(value); + } + } + } + } + + void set_joystick_state(JoystickInput input, bool value) { + if(input == JoystickInput::Right) + { + _portB = (_portB & ~input) | (value ? 0 : input); } } using MOS6522IRQDelegate::set_interrupt_status; + void set_serial_port(std::shared_ptr serialPort) { + _serialPort = serialPort; + } + private: + uint8_t _portB; uint8_t _columns[8]; uint8_t _activation_mask; + std::weak_ptr _serialPort; }; class Tape: public Storage::TapePlayer { @@ -156,8 +231,12 @@ class Machine: void add_prg(size_t length, const uint8_t *data); void set_tape(std::shared_ptr tape); - void set_key_state(Key key, bool isPressed) { _keyboardVIA.set_key_state(key, isPressed); } - void clear_all_keys() { _keyboardVIA.clear_all_keys(); } + void set_key_state(Key key, bool isPressed) { _keyboardVIA->set_key_state(key, isPressed); } + void clear_all_keys() { _keyboardVIA->clear_all_keys(); } + void set_joystick_state(JoystickInput input, bool isPressed) { + _userPortVIA->set_joystick_state(input, isPressed); + _keyboardVIA->set_joystick_state(input, isPressed); + } inline void set_use_fast_tape_hack(bool activate) { _use_fast_tape_hack = activate; } @@ -204,8 +283,9 @@ class Machine: void write_to_map(uint8_t **map, uint8_t *area, uint16_t address, uint16_t length); std::unique_ptr _mos6560; - UserPortVIA _userPortVIA; - KeyboardVIA _keyboardVIA; + std::shared_ptr _userPortVIA; + std::shared_ptr _keyboardVIA; + std::shared_ptr _serialPort; // Tape Tape _tape; diff --git a/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSVic20.mm b/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSVic20.mm index 3dbf8f626..434c7f197 100644 --- a/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSVic20.mm +++ b/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSVic20.mm @@ -13,6 +13,7 @@ @implementation CSVic20 { Vic20::Machine _vic20; + BOOL _joystickMode; } - (CRTMachine::Machine * const)machine { @@ -109,24 +110,43 @@ // KeyPlus // KeyGBP - @synchronized(self) { - switch(key) - { - default: { - NSNumber *targetKey = vicKeysByKeys[@(key)]; - if(targetKey) - { - _vic20.set_key_state((Vic20::Key)targetKey.integerValue, isPressed); - } - else - NSLog(@"Unmapped: %02x", key); - } break; + if(key == VK_Tab && isPressed) + { + _joystickMode ^= YES; + } - case VK_Shift: - // Yuck - _vic20.set_key_state(Vic20::Key::KeyLShift, isPressed); - _vic20.set_key_state(Vic20::Key::KeyRShift, isPressed); - break; + @synchronized(self) { + if(_joystickMode) + { + switch(key) + { + case VK_UpArrow: _vic20.set_joystick_state(Vic20::JoystickInput::Up, isPressed); break; + case VK_DownArrow: _vic20.set_joystick_state(Vic20::JoystickInput::Down, isPressed); break; + case VK_LeftArrow: _vic20.set_joystick_state(Vic20::JoystickInput::Left, isPressed); break; + case VK_RightArrow: _vic20.set_joystick_state(Vic20::JoystickInput::Right, isPressed); break; + case VK_ANSI_A: _vic20.set_joystick_state(Vic20::JoystickInput::Fire, isPressed); break; + } + } + else + { + switch(key) + { + default: { + NSNumber *targetKey = vicKeysByKeys[@(key)]; + if(targetKey) + { + _vic20.set_key_state((Vic20::Key)targetKey.integerValue, isPressed); + } + else + NSLog(@"Unmapped: %02x", key); + } break; + + case VK_Shift: + // Yuck + _vic20.set_key_state(Vic20::Key::KeyLShift, isPressed); + _vic20.set_key_state(Vic20::Key::KeyRShift, isPressed); + break; + } } } }