1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-08-09 05:25:01 +00:00
Files
CLK/Machines/Commodore/Plus4/Video.hpp
2024-12-10 22:56:14 -05:00

146 lines
4.0 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// Video.hpp
// Clock Signal
//
// Created by Thomas Harte on 10/12/2024.
// Copyright © 2024 Thomas Harte. All rights reserved.
//
#pragma once
namespace Commodore::Plus4 {
struct Video {
public:
template <uint16_t address>
void write(const uint8_t value) {
const auto load_high10 = [&](uint16_t &target) {
target = uint16_t(
(target & 0x00ff) | ((value & 0x3) << 8)
);
};
const auto load_low8 = [&](uint16_t &target) {
target = uint16_t(
(target & 0xff00) | value
);
};
switch(address) {
case 0xff06:
extended_colour_mode_ = value & 0x40;
bitmap_mode_ = value & 0x20;
display_enable_ = value & 0x10;
rows_25_ = value & 8;
y_scroll_ = value & 7;
break;
case 0xff07:
characters_256_ = value & 0x80;
is_ntsc_ = value & 0x40;
ted_off_ = value & 0x20;
multicolour_mode_ = value & 0x10;
columns_40_ = value & 8;
x_scroll_ = value & 7;
break;
case 0xff12:
character_generator_address_ = uint16_t((value & 0xfc) << 8);
break;
case 0xff14:
screen_memory_address_ = uint16_t((value & 0xf8) << 8);
break;
case 0xff0c: load_high10(cursor_address_); break;
case 0xff0d: load_low8(cursor_address_); break;
case 0xff1a: load_high10(character_row_address_); break;
case 0xff1b: load_low8(character_row_address_); break;
}
}
// Outer clock is [NTSC or PAL] colour subcarrier * 2.
//
// 65 cycles = 64µs?
// 65*262*60 = 1021800
//
// In an NTSC television system. 262 raster lines are produced (0 to 261), 312 for PAL (0311).
//
// An interrupt is generated 8 cycles before the character window. For a 25 row display, the visible
// raster lines are from 4 to 203.
//
// The horizontal position register counts 456 dots, 0 to 455.
void run_for(Cycles) {
// Timing:
//
// 456 cycles/line;
// if in PAL mode, divide input clock by 1.25 (?);
// see page 34 of plus4_tech.pdf for event times.
// Horizontal events:
//
// 3: 38-column screen start
// 288: external fetch window end, refresh single clock start, increment character position end
// 290: latch character position to reload
// 296: character window end, character window single clock end, increment refresh start
// 304: video shift register end
// 307: 38-column screen stop
// 315: 40-column screen end
// 328: refresh single clock end
// 336: increment blink, increment refresh end
// 344: horizontal blanking start
// 358: horizontal sync start
// 376: increment vertical line
// 384: burst start, end of screen — clear vertical line, vertical sub and character reload registers
// 390: horizontal sync end
// 408: burst end
// 400: external fetch window start
// 416: horizontal blanking end
// 424: increment character position reload
// 432: character window start, character window single clock start, increment character position start
// 440: video shift register start
// 451: 40-column screen start
// Vertical events:
//
// 0: attribute fetch start
// 4: vertical screen window start (25 lines)
// 8: vertical screen window start (24 lines)
// 203: attribute fetch end
// 200: vertical screen window stop (24 lines)
// 204: frame window stop, vertical screen window stop (25 lines)
// 226: NTSC vertical blank start
// 229: NTSC vsync start
// 232: NTSC vsync end
// 244: NTSC vertical blank end
// 251: PAL vertical blank start
// 254: PAL vsync start
// 257: PAL vsync end
// 261: end of screen NTSC
// 269: PAL vertical blank end
// 311: end of screen PAL
}
private:
bool extended_colour_mode_ = false;
bool bitmap_mode_ = false;
bool display_enable_ = false;
bool rows_25_ = false;
int y_scroll_ = 0;
bool characters_256_ = false;
bool is_ntsc_ = false;
bool ted_off_ = false;
bool multicolour_mode_ = false;
bool columns_40_ = false;
int x_scroll_ = 0;
uint16_t cursor_address_ = 0;
uint16_t character_row_address_ = 0;
uint16_t character_generator_address_ = 0;
uint16_t screen_memory_address_ = 0;
int horizontal_counter_ = 0;
int vertical_counter_ = 0;
};
}