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:
parent
8854ffddee
commit
f7750af3d0
50
Machines/Commodore/Plus4/Pager.hpp
Normal file
50
Machines/Commodore/Plus4/Pager.hpp
Normal 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>;
|
||||
|
||||
}
|
@ -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_;
|
||||
|
@ -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_;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user