From f7750af3d00a032a2043a103ddea1e6fc5408d6a Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Wed, 11 Dec 2024 22:32:14 -0500 Subject: [PATCH] Provide bus visibility to video; mark vertical portion of display. --- Machines/Commodore/Plus4/Pager.hpp | 50 +++++++++++++++++++ Machines/Commodore/Plus4/Plus4.cpp | 41 ++------------- Machines/Commodore/Plus4/Video.hpp | 35 +++++++------ .../Clock Signal.xcodeproj/project.pbxproj | 4 +- 4 files changed, 77 insertions(+), 53 deletions(-) create mode 100644 Machines/Commodore/Plus4/Pager.hpp diff --git a/Machines/Commodore/Plus4/Pager.hpp b/Machines/Commodore/Plus4/Pager.hpp new file mode 100644 index 000000000..6a2efea7f --- /dev/null +++ b/Machines/Commodore/Plus4/Pager.hpp @@ -0,0 +1,50 @@ +// +// Pager.hpp +// Clock Signal +// +// Created by Thomas Harte on 11/12/2024. +// Copyright © 2024 Thomas Harte. All rights reserved. +// + +#pragma once + +template +class Pager { +public: + DataT read(AddressT address) { + return read_[address >> Shift][address]; + } + DataT &write(AddressT address) { + return write_[address >> Shift][address]; + } + + template + void page(const uint8_t *read, uint8_t *write) { + write_[slot] = write - (slot << Shift); + read_[slot] = read - (slot << Shift); + } + +private: + std::array write_{}; + std::array read_{}; + + static constexpr auto AddressBits = sizeof(AddressT) * 8; + static constexpr auto PageSize = (1 << AddressBits) / NumPages; + static_assert(!(PageSize & (PageSize - 1)), "Pages must be a power of two in size"); + + static constexpr int ln2(int value) { + int result = 0; + while(value != 1) { + value >>= 1; + ++result; + } + return result; + } + static constexpr auto Shift = ln2(PageSize); +}; + +namespace Commodore::Plus4 { + +using Pager = Pager; + +} diff --git a/Machines/Commodore/Plus4/Plus4.cpp b/Machines/Commodore/Plus4/Plus4.cpp index 17392510c..79e072a2e 100644 --- a/Machines/Commodore/Plus4/Plus4.cpp +++ b/Machines/Commodore/Plus4/Plus4.cpp @@ -8,6 +8,7 @@ #include "Plus4.hpp" +#include "Pager.hpp" #include "Video.hpp" #include "../../MachineTypes.hpp" @@ -18,41 +19,6 @@ using namespace Commodore::Plus4; namespace { -template -class Pager { -public: - DataT read(AddressT address) { - return read_[address >> Shift][address]; - } - DataT &write(AddressT address) { - return write_[address >> Shift][address]; - } - - template - void page(const uint8_t *read, uint8_t *write) { - write_[slot] = write - (slot << Shift); - read_[slot] = read - (slot << Shift); - } - -private: - std::array write_{}; - std::array read_{}; - - static constexpr auto AddressBits = sizeof(AddressT) * 8; - static constexpr auto PageSize = (1 << AddressBits) / NumPages; - static_assert(!(PageSize & (PageSize - 1)), "Pages must be a power of two in size"); - - static constexpr int ln2(int value) { - int result = 0; - while(value != 1) { - value >>= 1; - ++result; - } - return result; - } - static constexpr auto Shift = ln2(PageSize); -}; - class Timers { public: template @@ -128,7 +94,8 @@ class ConcreteMachine: public Machine { public: ConcreteMachine(const Analyser::Static::Commodore::Target &target, const ROMMachine::ROMFetcher &rom_fetcher) : - m6502_(*this) + m6502_(*this), + video_(map_) { // PAL: 8867240 divided by 5 or 4? // NTSC: 7159090? @@ -246,7 +213,7 @@ private: return true; } - Pager map_; + Commodore::Plus4::Pager map_; std::array ram_; std::vector kernel_; std::vector basic_; diff --git a/Machines/Commodore/Plus4/Video.hpp b/Machines/Commodore/Plus4/Video.hpp index ba3798937..b158958c0 100644 --- a/Machines/Commodore/Plus4/Video.hpp +++ b/Machines/Commodore/Plus4/Video.hpp @@ -8,6 +8,8 @@ #pragma once +#include "Pager.hpp" + #include "../../../Numeric/UpperBound.hpp" #include "../../../Outputs/CRT/CRT.hpp" @@ -15,7 +17,9 @@ namespace Commodore::Plus4 { struct Video { public: - Video() : crt_(465, 1, Outputs::Display::Type::PAL50, Outputs::Display::InputDataType::Luminance8Phase8) {} + Video(const Commodore::Plus4::Pager &pager) : + crt_(465, 1, Outputs::Display::Type::PAL50, Outputs::Display::InputDataType::Luminance8Phase8), + pager_(pager) {} template void write(const uint8_t value) { @@ -60,6 +64,8 @@ public: case 0xff1a: load_high10(character_row_address_); break; case 0xff1b: load_low8(character_row_address_); break; } + +// printf("bitmap:%d c256:%d ntsc:%d 40col:%d; base:%04x\n", bitmap_mode_, characters_256_, is_ntsc_, columns_40_, screen_memory_address_); } // Outer clock is [NTSC or PAL] colour subcarrier * 2. @@ -103,20 +109,14 @@ public: } break; - case 4: // Vertical screen window start (25 lines). - break; - - case 8: // Vertical screen window start (24 lines). - break; - - case 200: // Vertical screen window stop (24 lines). - break; - case 203: // Attribute fetch end. break; - case 204: // Vertical screen window stop (25 lines). - break; + + case 4: if(rows_25_) vertical_window_ = true; break; // Vertical screen window start (25 lines). + case 204: if(rows_25_) vertical_window_ = false; break; // Vertical screen window stop (25 lines). + case 8: if(!rows_25_) vertical_window_ = true; break; // Vertical screen window start (24 lines). + case 200: if(!rows_25_) vertical_window_ = false; break; // Vertical screen window stop (24 lines). case 226: if(is_ntsc_) vertical_blank_ = true; break; // NTSC vertical blank start. case 229: if(is_ntsc_) vertical_sync_ = true; break; // NTSC vsync start. @@ -136,7 +136,7 @@ public: // - // TODO: output. + // Output. // OutputState state; if(vertical_sync_ || horizontal_sync_) { @@ -144,8 +144,8 @@ public: } else if(vertical_blank_ || horizontal_blank_) { state = horizontal_burst_ ? OutputState::Burst : OutputState::Blank; } else { - state = OutputState::Border; - // TODO: pixels when? + state = vertical_window_ ? OutputState::Pixels : OutputState::Border; + // TODO: pixels when? Like, for real? } @@ -155,6 +155,7 @@ public: case OutputState::Sync: crt_.output_sync(time_in_state_); break; case OutputState::Burst: crt_.output_default_colour_burst(time_in_state_); break; case OutputState::Border: crt_.output_level(time_in_state_, 0x8080); break; + case OutputState::Pixels: crt_.output_level(time_in_state_, 0xff80); break; } time_in_state_ = 0; } @@ -269,6 +270,7 @@ private: // Running state. bool vertical_blank_ = false; bool vertical_sync_ = false; + bool vertical_window_ = false; bool horizontal_blank_ = false; bool horizontal_sync_ = false; bool horizontal_burst_ = false; @@ -278,8 +280,11 @@ private: Sync, Burst, Border, + Pixels, } output_state_ = OutputState::Blank; int time_in_state_ = 0; + + const Commodore::Plus4::Pager &pager_; }; } diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index c6f89df4b..354ca63ea 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -1298,6 +1298,7 @@ 4B01A6871F22F0DB001FD6E3 /* Z80MemptrTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Z80MemptrTests.swift; sourceTree = ""; }; 4B03291F2D0923E300C51EB5 /* Video.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Video.hpp; sourceTree = ""; }; 4B0329202D0A78DC00C51EB5 /* UpperBound.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = UpperBound.hpp; sourceTree = ""; }; + 4B0329212D0A8C4700C51EB5 /* Pager.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Pager.hpp; sourceTree = ""; }; 4B0333AD2094081A0050B93D /* AppleDSK.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = AppleDSK.cpp; sourceTree = ""; }; 4B0333AE2094081A0050B93D /* AppleDSK.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = AppleDSK.hpp; sourceTree = ""; }; 4B046DC31CFE651500E9E45E /* ScanProducer.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ScanProducer.hpp; sourceTree = ""; }; @@ -3393,8 +3394,9 @@ 4B596EB12D037E8800FBF4B1 /* Plus4 */ = { isa = PBXGroup; children = ( - 4B596EAF2D037E8800FBF4B1 /* Plus4.hpp */, 4B596EB02D037E8800FBF4B1 /* Plus4.cpp */, + 4B0329212D0A8C4700C51EB5 /* Pager.hpp */, + 4B596EAF2D037E8800FBF4B1 /* Plus4.hpp */, 4B03291F2D0923E300C51EB5 /* Video.hpp */, ); path = Plus4;