From 7cc4bf3fe7cca85d9fc6f9a53a4e578b563e8c84 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 9 Jul 2016 15:40:25 -0400 Subject: [PATCH] Hit and hope is getting me nowhere. Time to unit test this thing. --- Components/6522/6522.hpp | 6 +- Machines/Commodore/1540/Commodore1540.cpp | 4 +- Machines/Commodore/1540/Commodore1540.hpp | 7 +- Machines/Commodore/SerialBus.cpp | 1 + Machines/Commodore/SerialBus.hpp | 9 +- .../Clock Signal.xcodeproj/project.pbxproj | 6 ++ .../Clock Signal/Machine/Wrappers/CSVic20.mm | 2 +- .../Mac/Clock SignalTests/C1540Bridge.h | 20 +++++ .../Mac/Clock SignalTests/C1540Bridge.mm | 83 +++++++++++++++++++ 9 files changed, 124 insertions(+), 14 deletions(-) create mode 100644 OSBindings/Mac/Clock SignalTests/C1540Bridge.h create mode 100644 OSBindings/Mac/Clock SignalTests/C1540Bridge.mm diff --git a/Components/6522/6522.hpp b/Components/6522/6522.hpp index dd5cb5526..e7524f7e3 100644 --- a/Components/6522/6522.hpp +++ b/Components/6522/6522.hpp @@ -117,15 +117,15 @@ template class MOS6522 { _registers.peripheral_control = value; // TODO: simplify below; tryig to avoid improper logging of unimplemented warnings in input mode - if(value & 0x08) - { +// if(value & 0x08) +// { switch(value & 0x0e) { 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; } - } +// } if(value & 0x80) { switch(value & 0xe0) diff --git a/Machines/Commodore/1540/Commodore1540.cpp b/Machines/Commodore/1540/Commodore1540.cpp index 0d803fc6e..a59cfcb8d 100644 --- a/Machines/Commodore/1540/Commodore1540.cpp +++ b/Machines/Commodore/1540/Commodore1540.cpp @@ -30,14 +30,14 @@ void Machine::set_serial_bus(std::shared_ptr<::Commodore::Serial::Bus> serial_bu unsigned int Machine::perform_bus_operation(CPU6502::BusOperation operation, uint16_t address, uint8_t *value) { - static bool log = false; +/* static bool log = false; if(operation == CPU6502::BusOperation::ReadOpcode) { log = (address >= 0xE85B && address <= 0xE907) || (address >= 0xE9C9 && address <= 0xEA2D); if(log) printf("\n%04x: ", address); } - if(log) printf("[%c %04x] ", isReadOperation(operation) ? 'r' : 'w', address); + if(log) printf("[%c %04x] ", isReadOperation(operation) ? 'r' : 'w', address);*/ if(address < 0x800) { diff --git a/Machines/Commodore/1540/Commodore1540.hpp b/Machines/Commodore/1540/Commodore1540.hpp index 153dc5b8c..a6057ef35 100644 --- a/Machines/Commodore/1540/Commodore1540.hpp +++ b/Machines/Commodore/1540/Commodore1540.hpp @@ -34,7 +34,7 @@ class SerialPortVIA: public MOS::MOS6522, public MOS::MOS6522IRQD if(port) { std::shared_ptr<::Commodore::Serial::Port> serialPort = _serialPort.lock(); if(serialPort) { - printf("1540 output: %02x\n", value); +// printf("1540 output: %02x\n", value); // "ATNA (Attention Acknowledge) is an output from PB4 which is sensed on the serial data line after being exclusively "ored" by the attention line and inverted" _attention_acknowledge_level = !(value&0x10); _data_level_output = (value&0x02); @@ -79,10 +79,7 @@ class SerialPortVIA: public MOS::MOS6522, public MOS::MOS6522IRQD if(serialPort) { serialPort->set_output(::Commodore::Serial::Line::Data, (::Commodore::Serial::LineLevel)!(_data_level_output - || (_attention_level_input == _attention_acknowledge_level)) - ); - -// + || (_attention_level_input == _attention_acknowledge_level))); } } }; diff --git a/Machines/Commodore/SerialBus.cpp b/Machines/Commodore/SerialBus.cpp index 057a210f7..d3c3a5659 100644 --- a/Machines/Commodore/SerialBus.cpp +++ b/Machines/Commodore/SerialBus.cpp @@ -45,6 +45,7 @@ void Bus::set_line_output_did_change(Line line) if(locked_port) { new_line_level = (LineLevel)((bool)new_line_level & (bool)locked_port->get_output(line)); +// printf("[%s] %s is now %s\n", typeid(locked_port).name(), (bool)locked_port->get_output(line) ? "high" : "low"); } } diff --git a/Machines/Commodore/SerialBus.hpp b/Machines/Commodore/SerialBus.hpp index 7973f98ae..4b2b654f8 100644 --- a/Machines/Commodore/SerialBus.hpp +++ b/Machines/Commodore/SerialBus.hpp @@ -48,9 +48,12 @@ namespace Serial { Port() : _line_levels{High, High, High, High, High} {} void set_output(Line line, LineLevel level) { - _line_levels[line] = level; - std::shared_ptr bus = _serial_bus.lock(); - if(bus) bus->set_line_output_did_change(line); + if(_line_levels[line] != level) + { + _line_levels[line] = level; + std::shared_ptr bus = _serial_bus.lock(); + if(bus) bus->set_line_output_did_change(line); + } } LineLevel get_output(Line line) { diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index 007ef4c80..82189b583 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -25,6 +25,7 @@ 4B2E2D951C399D1200138695 /* ElectronDocument.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4B2E2D931C399D1200138695 /* ElectronDocument.xib */; }; 4B2E2D9A1C3A06EC00138695 /* Atari2600.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B2E2D971C3A06EC00138695 /* Atari2600.cpp */; }; 4B2E2D9D1C3A070400138695 /* Electron.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B2E2D9B1C3A070400138695 /* Electron.cpp */; }; + 4B3BA0C11D31882D005DD7A7 /* C1540Bridge.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B3BA0C01D31882D005DD7A7 /* C1540Bridge.mm */; }; 4B4DC8211D2C2425003C5BF8 /* Vic20.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4DC81F1D2C2425003C5BF8 /* Vic20.cpp */; }; 4B4DC8281D2C2470003C5BF8 /* Commodore1540.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4DC8261D2C2470003C5BF8 /* Commodore1540.cpp */; }; 4B4DC82B1D2C27A4003C5BF8 /* SerialBus.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4DC8291D2C27A4003C5BF8 /* SerialBus.cpp */; }; @@ -386,6 +387,8 @@ 4B2E2D991C3A06EC00138695 /* Atari2600Inputs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Atari2600Inputs.h; sourceTree = ""; }; 4B2E2D9B1C3A070400138695 /* Electron.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Electron.cpp; path = Electron/Electron.cpp; sourceTree = ""; }; 4B2E2D9C1C3A070400138695 /* Electron.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Electron.hpp; path = Electron/Electron.hpp; sourceTree = ""; }; + 4B3BA0BF1D31882D005DD7A7 /* C1540Bridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = C1540Bridge.h; sourceTree = ""; }; + 4B3BA0C01D31882D005DD7A7 /* C1540Bridge.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = C1540Bridge.mm; sourceTree = ""; }; 4B4DC81F1D2C2425003C5BF8 /* Vic20.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Vic20.cpp; sourceTree = ""; }; 4B4DC8201D2C2425003C5BF8 /* Vic20.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Vic20.hpp; sourceTree = ""; }; 4B4DC8261D2C2470003C5BF8 /* Commodore1540.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Commodore1540.cpp; sourceTree = ""; }; @@ -1285,6 +1288,8 @@ 4B14145F1B58885000E04248 /* WolfgangLorenzTests.swift */, 4B1414631B588A1100E04248 /* Test Binaries */, 4BC9E1ED1D23449A003FCEE4 /* 6502InterruptTests.swift */, + 4B3BA0BF1D31882D005DD7A7 /* C1540Bridge.h */, + 4B3BA0C01D31882D005DD7A7 /* C1540Bridge.mm */, ); path = "Clock SignalTests"; sourceTree = ""; @@ -1843,6 +1848,7 @@ files = ( 4BC751B61D157EB3006C31D9 /* MOS6522Bridge.mm in Sources */, 4B14145E1B5887AA00E04248 /* CPU6502AllRAM.cpp in Sources */, + 4B3BA0C11D31882D005DD7A7 /* C1540Bridge.mm in Sources */, 4B14145D1B5887A600E04248 /* CPU6502.cpp in Sources */, 4B1E85811D176468001EF87D /* 6532Tests.swift in Sources */, 4BC9E1EE1D23449A003FCEE4 /* 6502InterruptTests.swift in Sources */, diff --git a/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSVic20.mm b/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSVic20.mm index bb0be94d3..7d7cffc8e 100644 --- a/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSVic20.mm +++ b/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSVic20.mm @@ -126,7 +126,7 @@ using namespace Commodore::Vic20; { switch(key) { - case VK_UpArrow: _vic20.set_joystick_state(JoystickInput::Up, isPressed); break; + case VK_UpArrow: _vic20.set_joystick_state(JoystickInput::Up, isPressed); break; case VK_DownArrow: _vic20.set_joystick_state(JoystickInput::Down, isPressed); break; case VK_LeftArrow: _vic20.set_joystick_state(JoystickInput::Left, isPressed); break; case VK_RightArrow: _vic20.set_joystick_state(JoystickInput::Right, isPressed); break; diff --git a/OSBindings/Mac/Clock SignalTests/C1540Bridge.h b/OSBindings/Mac/Clock SignalTests/C1540Bridge.h new file mode 100644 index 000000000..c1e6dd963 --- /dev/null +++ b/OSBindings/Mac/Clock SignalTests/C1540Bridge.h @@ -0,0 +1,20 @@ +// +// C1540Bridge.h +// Clock Signal +// +// Created by Thomas Harte on 09/07/2016. +// Copyright © 2016 Thomas Harte. All rights reserved. +// + +#import + +@interface C1540Bridge : NSObject + +@property (nonatomic) BOOL attentionLine; +@property (nonatomic) BOOL dataLine; +@property (nonatomic) BOOL clockLine; + +- (void)runForCycles:(NSUInteger)numberOfCycles; +- (void)setROM:(NSData *)ROM; + +@end diff --git a/OSBindings/Mac/Clock SignalTests/C1540Bridge.mm b/OSBindings/Mac/Clock SignalTests/C1540Bridge.mm new file mode 100644 index 000000000..ba29751b4 --- /dev/null +++ b/OSBindings/Mac/Clock SignalTests/C1540Bridge.mm @@ -0,0 +1,83 @@ +// +// C1540Bridge.m +// Clock Signal +// +// Created by Thomas Harte on 09/07/2016. +// Copyright © 2016 Thomas Harte. All rights reserved. +// + +#import "C1540Bridge.h" +#include "Commodore1540.hpp" + +class VanillaSerialPort: public Commodore::Serial::Port { + public: + void set_input(Commodore::Serial::Line line, Commodore::Serial::LineLevel value) + { + _input_line_levels[(int)line] = value; + } + + Commodore::Serial::LineLevel _input_line_levels[5]; +}; + +@implementation C1540Bridge +{ + Commodore::C1540::Machine _c1540; + std::shared_ptr _serialBus; + std::shared_ptr _serialPort; +} + +- (instancetype)init +{ + self = [super init]; + if(self) + { + _serialBus.reset(new ::Commodore::Serial::Bus); + _serialPort.reset(new VanillaSerialPort); + + _c1540.set_serial_bus(_serialBus); + _serialBus->add_port(_serialPort); + } + return self; +} + +- (void)setROM:(NSData *)ROM +{ + _c1540.set_rom((uint8_t *)ROM.bytes); +} + +- (void)runForCycles:(NSUInteger)numberOfCycles +{ + _c1540.run_for_cycles((int)numberOfCycles); +} + +- (void)setAttentionLine:(BOOL)attentionLine +{ + _serialPort->set_input(Commodore::Serial::Line::Attention, attentionLine ? Commodore::Serial::LineLevel::High : Commodore::Serial::LineLevel::Low); +} + +- (BOOL)attentionLine +{ + return _serialPort->_input_line_levels[Commodore::Serial::Line::Attention]; +} + +- (void)setDataLine:(BOOL)dataLine +{ + _serialPort->set_input(Commodore::Serial::Line::Data, dataLine ? Commodore::Serial::LineLevel::High : Commodore::Serial::LineLevel::Low); +} + +- (BOOL)dataLine +{ + return _serialPort->_input_line_levels[Commodore::Serial::Line::Data]; +} + +- (void)setClockLine:(BOOL)clockLine +{ + _serialPort->set_input(Commodore::Serial::Line::Clock, clockLine ? Commodore::Serial::LineLevel::High : Commodore::Serial::LineLevel::Low); +} + +- (BOOL)clockLine +{ + return _serialPort->_input_line_levels[Commodore::Serial::Line::Clock]; +} + +@end