From e85db40b0fdcffc3af2723177b97f8303e5f8235 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Thu, 22 Jul 2021 18:43:07 -0400 Subject: [PATCH] Sketches out a blitter class. --- Machines/Amiga/Amiga.cpp | 65 ++++++++++++----- Machines/Amiga/Blitter.cpp | 69 +++++++++++++++++++ Machines/Amiga/Blitter.hpp | 55 +++++++++++++++ .../Clock Signal.xcodeproj/project.pbxproj | 8 +++ 4 files changed, 181 insertions(+), 16 deletions(-) create mode 100644 Machines/Amiga/Blitter.cpp create mode 100644 Machines/Amiga/Blitter.hpp diff --git a/Machines/Amiga/Amiga.cpp b/Machines/Amiga/Amiga.cpp index e1228459d..61c67f617 100644 --- a/Machines/Amiga/Amiga.cpp +++ b/Machines/Amiga/Amiga.cpp @@ -24,6 +24,8 @@ #define LOG_PREFIX "[Amiga] " #include "../../Outputs/Log.hpp" +#include "Blitter.hpp" + namespace Amiga { class ConcreteMachine: @@ -35,6 +37,7 @@ class ConcreteMachine: public: ConcreteMachine(const Analyser::Static::Amiga::Target &target, const ROMMachine::ROMFetcher &rom_fetcher) : mc68000_(*this), + blitter_(reinterpret_cast(memory_.chip_ram.data()), memory_.chip_ram.size()), cia_a_handler_(memory_), cia_a_(cia_a_handler_), cia_b_(cia_b_handler_) @@ -48,7 +51,7 @@ class ConcreteMachine: if(!request.validate(roms)) { throw ROMMachine::Error::MissingROMs; } - Memory::PackBigEndian16(roms.find(rom_name)->second, memory_.kickstart_.data()); + Memory::PackBigEndian16(roms.find(rom_name)->second, memory_.kickstart.data()); // NTSC clock rate: 2*3.579545 = 7.15909Mhz. // PAL clock rate: 7.09379Mhz. @@ -88,7 +91,7 @@ class ConcreteMachine: // printf("%06x\n", *cycle.address); // } - if(!memory_.regions_[address >> 18].read_write_mask) { + if(!memory_.regions[address >> 18].read_write_mask) { if((cycle.operation & (Microcycle::SelectByte | Microcycle::SelectWord))) { // Check for various potential chip accesses. @@ -155,6 +158,10 @@ class ConcreteMachine: break; // DMA management. + case Read(0x002): + LOG("DMA control and status read"); + cycle.set_value16(dma_control_ | blitter_.get_status()); + break; case Write(0x096): ApplySetClear(dma_control_); LOG("DMA control modified by " << PADHEX(4) << cycle.value16() << "; is now " << std::bitset<16>{dma_control_}); @@ -199,6 +206,34 @@ class ConcreteMachine: cycle.set_value16(0xffff); break; + // Blitter. + case Write(0x040): blitter_.set_control(0, cycle.value16()); break; + case Write(0x042): blitter_.set_control(1, cycle.value16()); break; + case Write(0x044): blitter_.set_first_word_mask(cycle.value16()); break; + case Write(0x046): blitter_.set_last_word_mask(cycle.value16()); break; + + case Write(0x048): blitter_.set_pointer(2, 16, cycle.value16()); break; + case Write(0x04a): blitter_.set_pointer(2, 0, cycle.value16()); break; + case Write(0x04c): blitter_.set_pointer(1, 16, cycle.value16()); break; + case Write(0x04e): blitter_.set_pointer(1, 0, cycle.value16()); break; + case Write(0x050): blitter_.set_pointer(0, 16, cycle.value16()); break; + case Write(0x052): blitter_.set_pointer(0, 0, cycle.value16()); break; + case Write(0x054): blitter_.set_pointer(3, 16, cycle.value16()); break; + case Write(0x056): blitter_.set_pointer(3, 0, cycle.value16()); break; + + case Write(0x058): blitter_.set_size(cycle.value16()); break; + case Write(0x05a): blitter_.set_minterms(cycle.value16()); break; + case Write(0x05c): blitter_.set_vertical_size(cycle.value16()); break; + case Write(0x05e): blitter_.set_horizontal_size(cycle.value16()); break; + + case Write(0x060): blitter_.set_modulo(2, cycle.value16()); break; + case Write(0x062): blitter_.set_modulo(1, cycle.value16()); break; + case Write(0x064): blitter_.set_modulo(0, cycle.value16()); break; + case Write(0x066): blitter_.set_modulo(3, cycle.value16()); break; + + case Write(0x070): blitter_.set_data(2, cycle.value16()); break; + case Write(0x072): blitter_.set_data(1, cycle.value16()); break; + case Write(0x074): blitter_.set_data(0, cycle.value16()); break; // Colour palette. case Write(0x180): case Write(0x182): case Write(0x184): case Write(0x186): @@ -229,8 +264,8 @@ class ConcreteMachine: } else { // A regular memory access. cycle.apply( - &memory_.regions_[address >> 18].contents[address], - memory_.regions_[address >> 18].read_write_mask + &memory_.regions[address >> 18].contents[address], + memory_.regions[address >> 18].read_write_mask ); } @@ -243,13 +278,13 @@ class ConcreteMachine: // MARK: - Memory map. struct MemoryMap { public: - std::array ram_{}; - std::array kickstart_{0xff}; + std::array chip_ram{}; + std::array kickstart{0xff}; struct MemoryRegion { uint8_t *contents = nullptr; unsigned int read_write_mask = 0; - } regions_[64]; // i.e. top six bits are used as an index. + } regions[64]; // i.e. top six bits are used as an index. MemoryMap() { // Address spaces that matter: @@ -267,7 +302,7 @@ class ConcreteMachine: // f0'0000 — : 512kb Kickstart (or possibly just an extra 512kb reserved for hypothetical 1mb Kickstart?). // f8'0000 — : 256kb Kickstart if 2.04 or higher. // fc'0000 – : 256kb Kickstart otherwise. - set_region(0xfc'0000, 0x1'00'0000, kickstart_.data(), CPU::MC68000::Microcycle::PermitRead); + set_region(0xfc'0000, 0x1'00'0000, kickstart.data(), CPU::MC68000::Microcycle::PermitRead); reset(); } @@ -282,13 +317,10 @@ class ConcreteMachine: overlay_ = enabled; if(enabled) { - set_region(0x00'0000, 0x08'0000, kickstart_.data(), CPU::MC68000::Microcycle::PermitRead); + set_region(0x00'0000, 0x08'0000, kickstart.data(), CPU::MC68000::Microcycle::PermitRead); } else { // Mirror RAM to fill out the address range up to $20'0000 (?) - set_region(0x00'0000, 0x08'0000, ram_.data(), CPU::MC68000::Microcycle::PermitRead | CPU::MC68000::Microcycle::PermitWrite); - set_region(0x08'0000, 0x10'0000, ram_.data(), CPU::MC68000::Microcycle::PermitRead | CPU::MC68000::Microcycle::PermitWrite); - set_region(0x10'0000, 0x18'0000, ram_.data(), CPU::MC68000::Microcycle::PermitRead | CPU::MC68000::Microcycle::PermitWrite); - set_region(0x18'0000, 0x20'0000, ram_.data(), CPU::MC68000::Microcycle::PermitRead | CPU::MC68000::Microcycle::PermitWrite); + set_region(0x00'0000, 0x08'0000, chip_ram.data(), CPU::MC68000::Microcycle::PermitRead | CPU::MC68000::Microcycle::PermitWrite); } } @@ -301,8 +333,8 @@ class ConcreteMachine: base -= start; for(int c = start >> 18; c < end >> 18; c++) { - regions_[c].contents = base; - regions_[c].read_write_mask = read_write_mask; + regions[c].contents = base; + regions[c].read_write_mask = read_write_mask; } } } memory_; @@ -316,9 +348,10 @@ class ConcreteMachine: // TODO. } - // MARK: - DMA control. + // MARK: - DMA control, blitter and Paula. uint16_t dma_control_ = 0; + Blitter blitter_; // MARK: - CIAs. diff --git a/Machines/Amiga/Blitter.cpp b/Machines/Amiga/Blitter.cpp new file mode 100644 index 000000000..edde5ffde --- /dev/null +++ b/Machines/Amiga/Blitter.cpp @@ -0,0 +1,69 @@ +// +// Blitter.cpp +// Clock Signal +// +// Created by Thomas Harte on 22/07/2021. +// Copyright © 2021 Thomas Harte. All rights reserved. +// + +#include "Blitter.hpp" + +//#define NDEBUG +#define LOG_PREFIX "[Blitter] " +#include "../../Outputs/Log.hpp" + +using namespace Amiga; + +Blitter::Blitter(uint16_t *ram, size_t size) : ram_(ram), ram_size_(size) {} + +void Blitter::set_control(int index, uint16_t value) { + LOG("Set control " << index << " to " << PADHEX(4) << value); +} + +void Blitter::set_first_word_mask(uint16_t value) { + LOG("Set first word mask: " << PADHEX(4) << value); +} + +void Blitter::set_last_word_mask(uint16_t value) { + LOG("Set last word mask: " << PADHEX(4) << value); +} + +void Blitter::set_pointer(int channel, int shift, uint16_t value) { + LOG("Set pointer " << channel << " shift " << shift << " to " << PADHEX(4) << value); +} + +void Blitter::set_size(uint16_t value) { + LOG("Set size " << PADHEX(4) << value); +} + +void Blitter::set_minterms(uint16_t value) { + LOG("Set minterms " << PADHEX(4) << value); +} + +void Blitter::set_vertical_size(uint16_t value) { + LOG("Set vertical size " << PADHEX(4) << value); +} + +void Blitter::set_horizontal_size(uint16_t value) { + LOG("Set horizontal size " << PADHEX(4) << value); +} + +void Blitter::set_modulo(int channel, uint16_t value) { + LOG("Set modulo size " << channel << " to " << PADHEX(4) << value); +} + +void Blitter::set_data(int channel, uint16_t value) { + LOG("Set data " << channel << " to " << PADHEX(4) << value); +} + +uint16_t Blitter::get_status() { + LOG("Returned dummy status"); + return 0; +} + +Cycles Blitter::get_remaining_cycles() { + return Cycles(0); +} + +void Blitter::run_for(Cycles) { +} diff --git a/Machines/Amiga/Blitter.hpp b/Machines/Amiga/Blitter.hpp new file mode 100644 index 000000000..a0056dc66 --- /dev/null +++ b/Machines/Amiga/Blitter.hpp @@ -0,0 +1,55 @@ +// +// Blitter.hpp +// Clock Signal +// +// Created by Thomas Harte on 22/07/2021. +// Copyright © 2021 Thomas Harte. All rights reserved. +// + +#ifndef Blitter_hpp +#define Blitter_hpp + +#include +#include + +#include "../../ClockReceiver/ClockReceiver.hpp" + +namespace Amiga { + +class Blitter { + public: + Blitter(uint16_t *ram, size_t size); + + // Various setters; it's assumed that address decoding is handled externally. + // + // In all cases where a channel is identified numerically, it's taken that + // 0 = A, 1 = B, 2 = C, 3 = D. + void set_control(int index, uint16_t value); + void set_first_word_mask(uint16_t value); + void set_last_word_mask(uint16_t value); + void set_pointer(int channel, int shift, uint16_t value); + void set_size(uint16_t value); + void set_minterms(uint16_t value); + void set_vertical_size(uint16_t value); + void set_horizontal_size(uint16_t value); + void set_modulo(int channel, uint16_t value); + void set_data(int channel, uint16_t value); + + uint16_t get_status(); + + /// @returns The number of 'cycles' required to complete the current + /// operation, if any, or Cycles(0) if no operation is pending. + Cycles get_remaining_cycles(); + + /// Advances the stated number of cycles. + void run_for(Cycles); + + private: + uint16_t *const ram_; + const size_t ram_size_; +}; + +} + + +#endif /* Blitter_hpp */ diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index 9f123cb7b..74ed062e7 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -580,6 +580,8 @@ 4B9D0C4B22C7D70A00DE1AD3 /* 68000BCDTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B9D0C4A22C7D70900DE1AD3 /* 68000BCDTests.mm */; }; 4B9D0C4D22C7DA1A00DE1AD3 /* 68000ControlFlowTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B9D0C4C22C7DA1A00DE1AD3 /* 68000ControlFlowTests.mm */; }; 4B9D0C4F22C7E0CF00DE1AD3 /* 68000RollShiftTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B9D0C4E22C7E0CF00DE1AD3 /* 68000RollShiftTests.mm */; }; + 4B9EC0E226AA27BA0060A31F /* Blitter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B9EC0E126AA27BA0060A31F /* Blitter.cpp */; }; + 4B9EC0E326AA27BA0060A31F /* Blitter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B9EC0E126AA27BA0060A31F /* Blitter.cpp */; }; 4B9F11C92272375400701480 /* qltrace.txt.gz in Resources */ = {isa = PBXBuildFile; fileRef = 4B9F11C82272375400701480 /* qltrace.txt.gz */; }; 4B9F11CA2272433900701480 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B69FB451C4D950F00B5F0AA /* libz.tbd */; }; 4B9F11CC22729B3600701480 /* OPCLOGR2.BIN in Resources */ = {isa = PBXBuildFile; fileRef = 4B9F11CB22729B3500701480 /* OPCLOGR2.BIN */; }; @@ -1584,6 +1586,8 @@ 4B9D0C4A22C7D70900DE1AD3 /* 68000BCDTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = 68000BCDTests.mm; sourceTree = ""; }; 4B9D0C4C22C7DA1A00DE1AD3 /* 68000ControlFlowTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = 68000ControlFlowTests.mm; sourceTree = ""; }; 4B9D0C4E22C7E0CF00DE1AD3 /* 68000RollShiftTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = 68000RollShiftTests.mm; sourceTree = ""; }; + 4B9EC0E026AA260C0060A31F /* Blitter.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Blitter.hpp; sourceTree = ""; }; + 4B9EC0E126AA27BA0060A31F /* Blitter.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Blitter.cpp; sourceTree = ""; }; 4B9F11C82272375400701480 /* qltrace.txt.gz */ = {isa = PBXFileReference; lastKnownFileType = archive.gzip; path = qltrace.txt.gz; sourceTree = ""; }; 4B9F11CB22729B3500701480 /* OPCLOGR2.BIN */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; name = OPCLOGR2.BIN; path = "68000 Coverage/OPCLOGR2.BIN"; sourceTree = ""; }; 4BA0F68C1EEA0E8400E9489E /* ZX8081.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ZX8081.cpp; sourceTree = ""; }; @@ -4266,6 +4270,8 @@ children = ( 4BC080D726A25ADA00D03FD8 /* Amiga.hpp */, 4BC080D826A25ADA00D03FD8 /* Amiga.cpp */, + 4B9EC0E026AA260C0060A31F /* Blitter.hpp */, + 4B9EC0E126AA27BA0060A31F /* Blitter.cpp */, ); path = Amiga; sourceTree = ""; @@ -5358,6 +5364,7 @@ 4BF437EF209D0F7E008CBD6B /* SegmentParser.cpp in Sources */, 4B055AD11FAE9B030060FFFF /* Video.cpp in Sources */, 4BB4BFBA22A4372F0069048D /* StaticAnalyser.cpp in Sources */, + 4B9EC0E326AA27BA0060A31F /* Blitter.cpp in Sources */, 4B055AA21FAE85DA0060FFFF /* SSD.cpp in Sources */, 4B2E86E325DC95150024F1E9 /* Joystick.cpp in Sources */, 4BEBFB4E2002C4BF000708CC /* FAT12.cpp in Sources */, @@ -5681,6 +5688,7 @@ 4BCA6CC81D9DD9F000C2D7B2 /* CommodoreROM.cpp in Sources */, 4BC1317A2346DF2B00E4FF3D /* MSA.cpp in Sources */, 4BEBFB4D2002C4BF000708CC /* FAT12.cpp in Sources */, + 4B9EC0E226AA27BA0060A31F /* Blitter.cpp in Sources */, 4BBFBB6C1EE8401E00C01E7A /* ZX8081.cpp in Sources */, 4B83348A1F5DB94B0097E338 /* IRQDelegatePortHandler.cpp in Sources */, 4B8DD3862634D37E00B3C866 /* SNA.cpp in Sources */,