1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-26 10:29:31 +00:00

Adds capture and forwarding of border colour.

This commit is contained in:
Thomas Harte 2021-04-25 14:00:12 -04:00
parent 2bbf8bc9fa
commit fd271d920b
4 changed files with 32 additions and 16 deletions

View File

@ -11,6 +11,7 @@
#include "../../../Reflection/Struct.hpp"
#include "../../../Processors/Z80/State/State.hpp"
#include "Video.hpp"
namespace Sinclair {
namespace ZXSpectrum {
@ -18,11 +19,13 @@ namespace ZXSpectrum {
struct State: public Reflection::StructImpl<State> {
CPU::Z80::State z80;
Video::State video;
std::vector<uint8_t> ram;
State() {
if(needs_declare()) {
DeclareField(z80);
DeclareField(video);
DeclareField(ram);
}
}

View File

@ -12,12 +12,15 @@
#include "../../../Outputs/CRT/CRT.hpp"
#include "../../../ClockReceiver/ClockReceiver.hpp"
#include "../../../Reflection/Struct.hpp"
#include <algorithm>
namespace Sinclair {
namespace ZXSpectrum {
namespace Video {
enum class VideoTiming {
enum class Timing {
FortyEightK,
OneTwoEightK,
Plus3,
@ -47,7 +50,7 @@ enum class VideoTiming {
*/
template <VideoTiming timing> class Video {
template <Timing timing> class Video {
private:
struct Timings {
// Number of cycles per line. Will be 224 or 228.
@ -78,17 +81,17 @@ template <VideoTiming timing> class Video {
};
static constexpr Timings get_timings() {
if constexpr (timing == VideoTiming::Plus3) {
if constexpr (timing == Timing::Plus3) {
constexpr int delays[] = {1, 0, 7, 6, 5, 4, 3, 2};
return Timings(228, 311, 6, 129, 14361, delays);
}
if constexpr (timing == VideoTiming::OneTwoEightK) {
if constexpr (timing == Timing::OneTwoEightK) {
constexpr int delays[] = {6, 5, 4, 3, 2, 1, 0, 0};
return Timings(228, 311, 4, 128, 14361, delays);
}
if constexpr (timing == VideoTiming::FortyEightK) {
if constexpr (timing == Timing::FortyEightK) {
constexpr int delays[] = {6, 5, 4, 3, 2, 1, 0, 0};
return Timings(224, 312, 4, 128, 14335, delays);
}
@ -103,7 +106,7 @@ template <VideoTiming timing> class Video {
constexpr int sync_line = (timings.interrupt_time / timings.cycles_per_line) + 1;
constexpr int sync_position = (timing == VideoTiming::FortyEightK) ? 164 * 2 : 166 * 2;
constexpr int sync_position = (timing == Timing::FortyEightK) ? 164 * 2 : 166 * 2;
constexpr int sync_length = 17 * 2;
constexpr int burst_position = sync_position + 40;
constexpr int burst_length = 17;
@ -220,7 +223,7 @@ template <VideoTiming timing> class Video {
if(offset >= burst_position && offset < burst_position+burst_length && end_offset > offset) {
const int burst_duration = std::min(burst_position + burst_length, end_offset) - offset;
if constexpr (timing >= VideoTiming::OneTwoEightK) {
if constexpr (timing >= Timing::OneTwoEightK) {
crt_.output_colour_burst(burst_duration, 116, is_alternate_line_);
// The colour burst phase above is an empirical guess. I need to research further.
} else {
@ -248,7 +251,7 @@ template <VideoTiming timing> class Video {
}
static constexpr int half_cycles_per_line() {
if constexpr (timing == VideoTiming::FortyEightK) {
if constexpr (timing == Timing::FortyEightK) {
// TODO: determine real figure here, if one exists.
// The source I'm looking at now suggests that the theoretical
// ideal of 224*2 ignores the real-life effects of separate
@ -328,7 +331,7 @@ template <VideoTiming timing> class Video {
*/
uint8_t get_floating_value() const {
constexpr auto timings = get_timings();
const uint8_t out_of_bounds = (timing == VideoTiming::Plus3) ? last_contended_access_ : 0xff;
const uint8_t out_of_bounds = (timing == Timing::Plus3) ? last_contended_access_ : 0xff;
const int line = time_into_frame_ / timings.cycles_per_line;
if(line >= 192) {
@ -342,7 +345,7 @@ template <VideoTiming timing> class Video {
// The +2a and +3 always return the low bit as set.
const uint8_t value = last_fetches_[(time_into_line >> 1) & 3];
if constexpr (timing == VideoTiming::Plus3) {
if constexpr (timing == Timing::Plus3) {
return value | 1;
}
return value;
@ -354,7 +357,7 @@ template <VideoTiming timing> class Video {
bus is accessed when the gate array isn't currently reading.
*/
void set_last_contended_area_access([[maybe_unused]] uint8_t value) {
if constexpr (timing == VideoTiming::Plus3) {
if constexpr (timing == Timing::Plus3) {
last_contended_access_ = value | 1;
}
}
@ -408,6 +411,17 @@ template <VideoTiming timing> class Video {
#undef RGB
};
struct State: public Reflection::StructImpl<State> {
uint8_t border_colour;
State() {
if(needs_declare()) {
DeclareField(border_colour);
}
}
};
}
}
}

View File

@ -775,10 +775,10 @@ template<Model model> class ConcreteMachine:
// MARK: - Video.
using VideoType =
std::conditional_t<
model <= Model::FortyEightK, Video<VideoTiming::FortyEightK>,
model <= Model::FortyEightK, Video::Video<Video::Timing::FortyEightK>,
std::conditional_t<
model <= Model::Plus2, Video<VideoTiming::OneTwoEightK>,
Video<VideoTiming::Plus3>
model <= Model::Plus2, Video::Video<Video::Timing::OneTwoEightK>,
Video::Video<Video::Timing::Plus3>
>
>;
JustInTimeActor<VideoType> video_;

View File

@ -64,8 +64,7 @@ std::unique_ptr<Analyser::Static::Target> SNA::load(const std::string &file_name
state->z80.registers.interrupt_mode = file.get8();
// 1A border colour
const uint8_t border_colour = file.get8();
(void)border_colour; // TODO.
state->video.border_colour = file.get8();
// 1B 48kb RAM contents
state->ram = file.read(48*1024);