From 245b7baa6114a31dd4cc8629bc51d69d1142d96b Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Thu, 16 Sep 2021 21:17:23 -0400 Subject: [PATCH] Moves the Copper into its own file. --- Machines/Amiga/Chipset.cpp | 73 --------------- Machines/Amiga/Chipset.hpp | 40 +------- Machines/Amiga/Copper.cpp | 91 +++++++++++++++++++ Machines/Amiga/Copper.hpp | 55 +++++++++++ .../Clock Signal.xcodeproj/project.pbxproj | 8 ++ 5 files changed, 157 insertions(+), 110 deletions(-) create mode 100644 Machines/Amiga/Copper.cpp create mode 100644 Machines/Amiga/Copper.hpp diff --git a/Machines/Amiga/Chipset.cpp b/Machines/Amiga/Chipset.cpp index 7d98b98ce..3c2580fd1 100644 --- a/Machines/Amiga/Chipset.cpp +++ b/Machines/Amiga/Chipset.cpp @@ -62,79 +62,6 @@ void Chipset::posit_interrupt(InterruptFlag flag) { update_interrupts(); } -bool Chipset::Copper::advance(uint16_t position) { - switch(state_) { - default: return false; - - case State::Waiting: - // TODO: blitter-finished bit. - if((position & position_mask_) >= instruction_[0]) { - state_ = State::FetchFirstWord; - } - return false; - - case State::FetchFirstWord: - instruction_[0] = ram_[address_ & ram_mask_]; - ++address_; - state_ = State::FetchSecondWord; - break; - - case State::FetchSecondWord: { - const bool should_skip_move = skip_next_; - skip_next_ = false; - - instruction_[1] = ram_[address_ & ram_mask_]; - ++address_; - - if(!(instruction_[0] & 1)) { - // A MOVE. - - if(!should_skip_move) { - // Stop if this move would be a privilege violation. - instruction_[0] &= 0x1fe; - if((instruction_[0] < 0x10) || (instruction_[0] < 0x20 && !(control_&1))) { - LOG("Invalid Copper MOVE to " << PADHEX(4) << instruction_[0] << "; stopping"); - state_ = State::Stopped; - break; - } - - // Construct a 68000-esque Microcycle in order to be able to perform the access. - CPU::MC68000::Microcycle cycle; - cycle.operation = CPU::MC68000::Microcycle::SelectWord; - uint32_t full_address = instruction_[0]; - CPU::RegisterPair16 data = instruction_[1]; - cycle.address = &full_address; - cycle.value = &data; - chipset_.perform(cycle); - } - - // Roll onto the next command. - state_ = State::FetchFirstWord; - break; - } - - // Prepare for a position comparison. - position_mask_ = 0x8001 | (instruction_[1] & 0x7ffe); - instruction_[0] &= position_mask_; - - if(!(instruction_[1] & 1)) { - // A WAIT. Just note that this is now waiting; the proper test - // will be applied from the next potential `advance` onwards. - state_ = State::Waiting; - break; - } - - // Neither a WAIT nor a MOVE => a SKIP. - - // TODO: blitter-finished bit. - skip_next_ = (position & position_mask_) >= instruction_[0]; - state_ = State::FetchFirstWord; - } break; - } - - return true; -} - template void Chipset::output() { // Notes to self on guesses below: // diff --git a/Machines/Amiga/Chipset.hpp b/Machines/Amiga/Chipset.hpp index 305815db9..b7dfeec7b 100644 --- a/Machines/Amiga/Chipset.hpp +++ b/Machines/Amiga/Chipset.hpp @@ -15,8 +15,9 @@ #include "../../Processors/68000/68000.hpp" #include "../../Outputs/CRT/CRT.hpp" -#include "DMADevice.hpp" #include "Blitter.hpp" +#include "Copper.hpp" +#include "DMADevice.hpp" namespace Amiga { @@ -191,42 +192,7 @@ class Chipset { // MARK: - Copper. - class Copper: public DMADevice<2> { - public: - using DMADevice<2>::DMADevice; - - /// Offers a DMA slot to the Copper, specifying the current beam position. - /// - /// @returns @c true if the slot was used; @c false otherwise. - bool advance(uint16_t position); - - /// Forces a reload of address @c id (i.e. 0 or 1) and restarts the Copper. - template void reload() { - address_ = pointer_[id]; - state_ = State::FetchFirstWord; - } - - /// Sets the Copper control word. - void set_control(uint16_t c) { - control_ = c; - } - - /// Forces the Copper into the stopped state. - void stop() { - state_ = State::Stopped; - } - - private: - uint32_t address_ = 0; - uint16_t control_ = 0; - - enum class State { - FetchFirstWord, FetchSecondWord, Waiting, Stopped, - } state_ = State::Stopped; - bool skip_next_ = false; - uint16_t instruction_[2]{}; - uint16_t position_mask_ = 0xffff; - } copper_; + Copper copper_; // MARK: - Serial port. diff --git a/Machines/Amiga/Copper.cpp b/Machines/Amiga/Copper.cpp new file mode 100644 index 000000000..9c45797af --- /dev/null +++ b/Machines/Amiga/Copper.cpp @@ -0,0 +1,91 @@ +// +// Copper.cpp +// Clock Signal +// +// Created by Thomas Harte on 16/09/2021. +// Copyright © 2021 Thomas Harte. All rights reserved. +// + +#include + +#define NDEBUG +#define LOG_PREFIX "[Copper] " +#include "../../Outputs/Log.hpp" + +#include "Chipset.hpp" +#include "Copper.hpp" + +using namespace Amiga; + +bool Copper::advance(uint16_t position) { + switch(state_) { + default: return false; + + case State::Waiting: + // TODO: blitter-finished bit. + if((position & position_mask_) >= instruction_[0]) { + state_ = State::FetchFirstWord; + } + return false; + + case State::FetchFirstWord: + instruction_[0] = ram_[address_ & ram_mask_]; + ++address_; + state_ = State::FetchSecondWord; + break; + + case State::FetchSecondWord: { + const bool should_skip_move = skip_next_; + skip_next_ = false; + + instruction_[1] = ram_[address_ & ram_mask_]; + ++address_; + + if(!(instruction_[0] & 1)) { + // A MOVE. + + if(!should_skip_move) { + // Stop if this move would be a privilege violation. + instruction_[0] &= 0x1fe; + if((instruction_[0] < 0x10) || (instruction_[0] < 0x20 && !(control_&1))) { + LOG("Invalid MOVE to " << PADHEX(4) << instruction_[0] << "; stopping"); + state_ = State::Stopped; + break; + } + + // Construct a 68000-esque Microcycle in order to be able to perform the access. + CPU::MC68000::Microcycle cycle; + cycle.operation = CPU::MC68000::Microcycle::SelectWord; + uint32_t full_address = instruction_[0]; + CPU::RegisterPair16 data = instruction_[1]; + cycle.address = &full_address; + cycle.value = &data; + chipset_.perform(cycle); + } + + // Roll onto the next command. + state_ = State::FetchFirstWord; + break; + } + + // Prepare for a position comparison. + position_mask_ = 0x8001 | (instruction_[1] & 0x7ffe); + instruction_[0] &= position_mask_; + + if(!(instruction_[1] & 1)) { + // A WAIT. Just note that this is now waiting; the proper test + // will be applied from the next potential `advance` onwards. + state_ = State::Waiting; + break; + } + + // Neither a WAIT nor a MOVE => a SKIP. + + // TODO: blitter-finished bit. + skip_next_ = (position & position_mask_) >= instruction_[0]; + state_ = State::FetchFirstWord; + } break; + } + + return true; +} diff --git a/Machines/Amiga/Copper.hpp b/Machines/Amiga/Copper.hpp new file mode 100644 index 000000000..8afee3efa --- /dev/null +++ b/Machines/Amiga/Copper.hpp @@ -0,0 +1,55 @@ +// +// Copper.hpp +// Clock Signal +// +// Created by Thomas Harte on 16/09/2021. +// Copyright © 2021 Thomas Harte. All rights reserved. +// + +#ifndef Copper_h +#define Copper_h + +#include "DMADevice.hpp" + +namespace Amiga { + +class Copper: public DMADevice<2> { + public: + using DMADevice<2>::DMADevice; + + /// Offers a DMA slot to the Copper, specifying the current beam position. + /// + /// @returns @c true if the slot was used; @c false otherwise. + bool advance(uint16_t position); + + /// Forces a reload of address @c id (i.e. 0 or 1) and restarts the Copper. + template void reload() { + address_ = pointer_[id]; + state_ = State::FetchFirstWord; + } + + /// Sets the Copper control word. + void set_control(uint16_t c) { + control_ = c; + } + + /// Forces the Copper into the stopped state. + void stop() { + state_ = State::Stopped; + } + + private: + uint32_t address_ = 0; + uint16_t control_ = 0; + + enum class State { + FetchFirstWord, FetchSecondWord, Waiting, Stopped, + } state_ = State::Stopped; + bool skip_next_ = false; + uint16_t instruction_[2]{}; + uint16_t position_mask_ = 0xffff; +}; + +} + +#endif /* Copper_h */ diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index 29f7af521..576812570 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -915,6 +915,8 @@ 4BC57CDA2436A62900FBC404 /* State.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC57CD82436A62900FBC404 /* State.cpp */; }; 4BC5C3E022C994CD00795658 /* 68000MoveTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BC5C3DF22C994CC00795658 /* 68000MoveTests.mm */; }; 4BC5FC3020CDDDEF00410AA0 /* AppleIIOptions.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4BC5FC2E20CDDDEE00410AA0 /* AppleIIOptions.xib */; }; + 4BC6236D26F4235400F83DFE /* Copper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC6236C26F4235400F83DFE /* Copper.cpp */; }; + 4BC6236E26F4235400F83DFE /* Copper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC6236C26F4235400F83DFE /* Copper.cpp */; }; 4BC751B21D157E61006C31D9 /* 6522Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BC751B11D157E61006C31D9 /* 6522Tests.swift */; }; 4BC76E691C98E31700E6EF73 /* FIRFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC76E671C98E31700E6EF73 /* FIRFilter.cpp */; }; 4BC890D3230F86020025A55A /* DirectAccessDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC890D1230F86020025A55A /* DirectAccessDevice.cpp */; }; @@ -1962,6 +1964,8 @@ 4BC5C3DF22C994CC00795658 /* 68000MoveTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = 68000MoveTests.mm; sourceTree = ""; }; 4BC5FC2F20CDDDEE00410AA0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = "Clock Signal/Base.lproj/AppleIIOptions.xib"; sourceTree = SOURCE_ROOT; }; 4BC6236A26F178DA00F83DFE /* DMADevice.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = DMADevice.hpp; sourceTree = ""; }; + 4BC6236B26F4224300F83DFE /* Copper.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Copper.hpp; sourceTree = ""; }; + 4BC6236C26F4235400F83DFE /* Copper.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Copper.cpp; sourceTree = ""; }; 4BC751B11D157E61006C31D9 /* 6522Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = 6522Tests.swift; sourceTree = ""; }; 4BC76E671C98E31700E6EF73 /* FIRFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FIRFilter.cpp; sourceTree = ""; }; 4BC76E681C98E31700E6EF73 /* FIRFilter.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = FIRFilter.hpp; sourceTree = ""; }; @@ -4281,10 +4285,12 @@ 4BC080D826A25ADA00D03FD8 /* Amiga.cpp */, 4B9EC0E126AA27BA0060A31F /* Blitter.cpp */, 4B9EC0E426AA4A660060A31F /* Chipset.cpp */, + 4BC6236C26F4235400F83DFE /* Copper.cpp */, 4B9EC0E826B384080060A31F /* Keyboard.cpp */, 4BC080D726A25ADA00D03FD8 /* Amiga.hpp */, 4B9EC0E026AA260C0060A31F /* Blitter.hpp */, 4B9EC0E526AA4A660060A31F /* Chipset.hpp */, + 4BC6236B26F4224300F83DFE /* Copper.hpp */, 4BC6236A26F178DA00F83DFE /* DMADevice.hpp */, 4B9EC0E926B384080060A31F /* Keyboard.hpp */, ); @@ -5428,6 +5434,7 @@ 4B055AA01FAE85DA0060FFFF /* MFMSectorDump.cpp in Sources */, 4BEBFB522002DB30000708CC /* DiskROM.cpp in Sources */, 4BC23A2D2467600F001A6030 /* OPLL.cpp in Sources */, + 4BC6236E26F4235400F83DFE /* Copper.cpp in Sources */, 4B055AA11FAE85DA0060FFFF /* OricMFMDSK.cpp in Sources */, 4B1EC717255398B000A1F44B /* Sound.cpp in Sources */, 4BB8616F24E22DC500A00E03 /* BufferingScanTarget.cpp in Sources */, @@ -5575,6 +5582,7 @@ 4B0ACC2A23775819008902D0 /* Video.cpp in Sources */, 4B54C0BF1F8D8F450050900F /* Keyboard.cpp in Sources */, 4B3FE75E1F3CF68B00448EE4 /* CPM.cpp in Sources */, + 4BC6236D26F4235400F83DFE /* Copper.cpp in Sources */, 4B2BFDB21DAEF5FF001A68B8 /* Video.cpp in Sources */, 4BEDA3BF25B25563000C2DBD /* Decoder.cpp in Sources */, 4B051C95266EF50200CA44E8 /* AppleIIController.swift in Sources */,