From 859804d1796fac45b4e8aafc5d7784a985b7c318 Mon Sep 17 00:00:00 2001 From: Adrian Conlon Date: Sun, 18 Nov 2018 22:15:49 +0000 Subject: [PATCH] Refactor MC6809 core to use lambdas in preference to std::bind methods. Signed-off-by: Adrian Conlon --- MC6809/test/Board.cpp | 124 +++++++++++++++++------------------- MC6809/test/Board.h | 27 ++------ MC6809/test/Configuration.h | 3 +- 3 files changed, 62 insertions(+), 92 deletions(-) diff --git a/MC6809/test/Board.cpp b/MC6809/test/Board.cpp index 35af48b..0dd7635 100644 --- a/MC6809/test/Board.cpp +++ b/MC6809/test/Board.cpp @@ -2,10 +2,7 @@ #include "Board.h" Board::Board(const Configuration& configuration) -: m_configuration(configuration), - m_cpu(EightBit::mc6809(*this)), - m_disassembler(*this, m_cpu) { -} +: m_configuration(configuration) {} void Board::powerOn() { @@ -20,7 +17,7 @@ void Board::powerOn() { // Get the ACIA ready for action ADDRESS() = 0b1010000000000000; ACIA().DATA() = EightBit::mc6850::CR0 | EightBit::mc6850::CR1; // Master reset - updateAciaPins(EightBit::Chip::PinLevel::Low); + updateAciaPinsWrite(); ACIA().lower(ACIA().CTS()); ACIA().powerOn(); accessAcia(); @@ -38,59 +35,76 @@ void Board::initialise() { const auto directory = m_configuration.getRomDirectory() + "\\"; loadHexFile(directory + "ExBasROM.hex"); - // Once the reset has completed, we can wire the ACIA event handlers... - ACIA().Transmitting.connect(std::bind(&Board::Acia_Transmitting, this, std::placeholders::_1)); + // Catch a byte being transmitted + ACIA().Transmitting.connect([this] (EightBit::EventArgs&) { + std::cout << ACIA().TDR(); + ACIA().markTransmitComplete(); + }); - // Wire bus events... - WrittenByte.connect(std::bind(&Board::Bus_WrittenByte_Acia, this, std::placeholders::_1)); - ReadingByte.connect(std::bind(&Board::Bus_ReadingByte_Acia, this, std::placeholders::_1)); + // Marshal data from memory -> ACIA + WrittenByte.connect([this] (EightBit::EventArgs&) { + updateAciaPinsWrite(); + if (accessAcia()) { + ACIA().DATA() = DATA(); + accessAcia(); + } + }); + + // Marshal data from ACIA -> memory + ReadingByte.connect([this] (EightBit::EventArgs&) { + updateAciaPinsRead(); + if (accessAcia()) + poke(ACIA().DATA()); + }); + + // Keyboard wiring, check for input once per frame + CPU().ExecutedInstruction.connect([this] (EightBit::mc6809& cpu) { + assert(cpu.cycles() > 0); + m_frameCycleCount -= cpu.cycles(); + if (m_frameCycleCount < 0) { + if (_kbhit()) { + ACIA().RDR() = _getch(); + ACIA().markReceiveStarting(); + } + m_frameCycleCount = Configuration::FrameCycleInterval; + } + }); - // Wire CPU events - CPU().ExecutedInstruction.connect(std::bind(&Board::Cpu_ExecutedInstruction_Acia, this, std::placeholders::_1)); if (m_configuration.isDebugMode()) { - CPU().ExecutingInstruction.connect(std::bind(&Board::Cpu_ExecutingInstruction_Debug, this, std::placeholders::_1)); - CPU().ExecutedInstruction.connect(std::bind(&Board::Cpu_ExecutedInstruction_Debug, this, std::placeholders::_1)); + // MC6809 disassembly wiring + CPU().ExecutingInstruction.connect([this] (EightBit::mc6809& cpu) { + m_disassembleAt = cpu.PC(); + m_ignoreDisassembly = m_disassembler.ignore(); + }); + CPU().ExecutedInstruction.connect([this] (EightBit::mc6809&) { + if (!m_ignoreDisassembly) + std::cout << m_disassembler.trace(m_disassembleAt) << " " << ACIA().dumpStatus() << std::endl; + }); } - if (m_configuration.terminatesEarly()) - CPU().ExecutedInstruction.connect(std::bind(&Board::Cpu_ExecutedInstruction_Terminator, this, std::placeholders::_1)); -} -void Board::Cpu_ExecutingInstruction_Debug(EightBit::mc6809&) { - m_disassembleAt = CPU().PC(); - m_ignoreDisassembly = m_disassembler.ignore(); -} - -void Board::Cpu_ExecutedInstruction_Debug(EightBit::mc6809&) { - if (!m_ignoreDisassembly) - std::cout << m_disassembler.trace(m_disassembleAt) << " " << ACIA().dumpStatus() << std::endl; + if (m_configuration.terminatesEarly()) { + // Early termination condition for CPU timing code + CPU().ExecutedInstruction.connect([this] (EightBit::mc6809& cpu) { + assert(cpu.cycles() > 0); + m_totalCycleCount += cpu.cycles(); + if (m_totalCycleCount > Configuration::TerminationCycles) + powerOff(); + }); + } } EightBit::MemoryMapping Board::mapping(uint16_t address) { if (address < 0x8000) - return { m_ram, 0x0000, 0xffff, EightBit::MemoryMapping::ReadWrite }; + return { m_ram, 0x0000, EightBit::Chip::Mask16, EightBit::MemoryMapping::ReadWrite }; if (address < 0xa000) - return { m_unused2000, 0x8000, 0xffff, EightBit::MemoryMapping::ReadOnly }; + return { m_unused2000, 0x8000, EightBit::Chip::Mask16, EightBit::MemoryMapping::ReadOnly }; if (address < 0xc000) - return { m_io, 0xa000, 0xffff, EightBit::MemoryMapping::ReadWrite }; + return { m_io, 0xa000, EightBit::Chip::Mask16, EightBit::MemoryMapping::ReadWrite }; - return { m_rom, 0xc000, 0xffff, EightBit::MemoryMapping::ReadOnly }; -} - -void Board::Bus_WrittenByte_Acia(EightBit::EventArgs&) { - updateAciaPins(EightBit::Chip::Low); - if (ACIA().selected()) { - ACIA().DATA() = peek(ADDRESS()); - accessAcia(); - } -} - -void Board::Bus_ReadingByte_Acia(EightBit::EventArgs&) { - updateAciaPins(EightBit::Chip::High); - if (accessAcia()) - poke(ADDRESS(), ACIA().DATA()); + return { m_rom, 0xc000, EightBit::Chip::Mask16, EightBit::MemoryMapping::ReadOnly }; } void Board::updateAciaPins(const EightBit::Chip::PinLevel rw) { @@ -102,30 +116,6 @@ void Board::updateAciaPins(const EightBit::Chip::PinLevel rw) { ACIA().match(ACIA().CS2(), ADDRESS().word & EightBit::Chip::Bit14); } -void Board::Cpu_ExecutedInstruction_Terminator(EightBit::mc6809&) { - assert(CPU().cycles() > 0); - m_totalCycleCount += CPU().cycles(); - if (m_totalCycleCount > Configuration::TerminationCycles) - powerOff(); -} - -void Board::Cpu_ExecutedInstruction_Acia(EightBit::mc6809&) { - assert(CPU().cycles() > 0); - m_frameCycleCount -= CPU().cycles(); - if (m_frameCycleCount < 0) { - if (_kbhit()) { - ACIA().RDR() = _getch(); - ACIA().markReceiveStarting(); - } - m_frameCycleCount = Configuration::FrameCycleInterval; - } -} - -void Board::Acia_Transmitting(EightBit::EventArgs&) { - std::cout << ACIA().TDR(); - ACIA().markTransmitComplete(); -} - bool Board::accessAcia() { ACIA().raise(ACIA().E()); const bool accessed = ACIA().tick(); diff --git a/MC6809/test/Board.h b/MC6809/test/Board.h index f07f9e7..0d3e6dd 100644 --- a/MC6809/test/Board.h +++ b/MC6809/test/Board.h @@ -35,8 +35,8 @@ private: EightBit::mc6850 m_acia; - EightBit::mc6809 m_cpu; - EightBit::Disassembly m_disassembler; + EightBit::mc6809 m_cpu = *this; + EightBit::Disassembly m_disassembler = { *this, m_cpu }; uint64_t m_totalCycleCount = 0UL; int64_t m_frameCycleCount = 0L; @@ -45,28 +45,9 @@ private: EightBit::register16_t m_disassembleAt = 0x0000; bool m_ignoreDisassembly = false; - // CPU events - - void Cpu_ExecutingInstruction_Debug(EightBit::mc6809&); - void Cpu_ExecutedInstruction_Debug(EightBit::mc6809&); - - void Cpu_ExecutedInstruction_Terminator(EightBit::mc6809&); - void Cpu_ExecutedInstruction_Acia(EightBit::mc6809&); - - // Bus events - - // Allows us to marshal data from memory -> ACIA - void Bus_WrittenByte_Acia(EightBit::EventArgs&); - - // Allows us to marshal data from ACIA -> memory - void Bus_ReadingByte_Acia(EightBit::EventArgs&); - - // ACIA events - - // Allows us to catch a byte being transmitted - void Acia_Transmitting(EightBit::EventArgs&); - // Use the bus data to update the ACIA access/address pins + void updateAciaPinsRead() { updateAciaPins(EightBit::Chip::PinLevel::High); } + void updateAciaPinsWrite() { updateAciaPins(EightBit::Chip::PinLevel::Low); } void updateAciaPins(EightBit::Chip::PinLevel rw); bool accessAcia(); diff --git a/MC6809/test/Configuration.h b/MC6809/test/Configuration.h index eda5d47..2613a4d 100644 --- a/MC6809/test/Configuration.h +++ b/MC6809/test/Configuration.h @@ -2,9 +2,8 @@ #include #include -#include -class Configuration { +class Configuration final { public: static constexpr uint64_t CyclesPerSecond = 2 * 1024 * 1024; static constexpr uint64_t FrameCycleInterval = CyclesPerSecond / 60;