1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-04-22 09:37:21 +00:00

Provide bus visibility to video; mark vertical portion of display.

This commit is contained in:
Thomas Harte 2024-12-11 22:32:14 -05:00
parent 8854ffddee
commit f7750af3d0
4 changed files with 77 additions and 53 deletions

View File

@ -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 <typename AddressT, typename DataT, int NumPages>
class Pager {
public:
DataT read(AddressT address) {
return read_[address >> Shift][address];
}
DataT &write(AddressT address) {
return write_[address >> Shift][address];
}
template <int slot>
void page(const uint8_t *read, uint8_t *write) {
write_[slot] = write - (slot << Shift);
read_[slot] = read - (slot << Shift);
}
private:
std::array<DataT *, NumPages> write_{};
std::array<const DataT *, NumPages> 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<uint16_t, uint8_t, 4>;
}

View File

@ -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 <typename AddressT, typename DataT, int NumPages>
class Pager {
public:
DataT read(AddressT address) {
return read_[address >> Shift][address];
}
DataT &write(AddressT address) {
return write_[address >> Shift][address];
}
template <int slot>
void page(const uint8_t *read, uint8_t *write) {
write_[slot] = write - (slot << Shift);
read_[slot] = read - (slot << Shift);
}
private:
std::array<DataT *, NumPages> write_{};
std::array<const DataT *, NumPages> 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 <int offset>
@ -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<uint16_t, uint8_t, 4> map_;
Commodore::Plus4::Pager map_;
std::array<uint8_t, 65536> ram_;
std::vector<uint8_t> kernel_;
std::vector<uint8_t> basic_;

View File

@ -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 <uint16_t address>
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<uint16_t>(time_in_state_, 0x8080); break;
case OutputState::Pixels: crt_.output_level<uint16_t>(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_;
};
}

View File

@ -1298,6 +1298,7 @@
4B01A6871F22F0DB001FD6E3 /* Z80MemptrTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Z80MemptrTests.swift; sourceTree = "<group>"; };
4B03291F2D0923E300C51EB5 /* Video.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Video.hpp; sourceTree = "<group>"; };
4B0329202D0A78DC00C51EB5 /* UpperBound.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = UpperBound.hpp; sourceTree = "<group>"; };
4B0329212D0A8C4700C51EB5 /* Pager.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Pager.hpp; sourceTree = "<group>"; };
4B0333AD2094081A0050B93D /* AppleDSK.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = AppleDSK.cpp; sourceTree = "<group>"; };
4B0333AE2094081A0050B93D /* AppleDSK.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = AppleDSK.hpp; sourceTree = "<group>"; };
4B046DC31CFE651500E9E45E /* ScanProducer.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ScanProducer.hpp; sourceTree = "<group>"; };
@ -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;