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

Factored out ZX80/81 video and rejigged to ensure it will keep ticking over irrespective of whether the machine is supplying data.

This commit is contained in:
Thomas Harte 2017-06-06 17:53:23 -04:00
parent b55579c348
commit 8c66e1d99d
5 changed files with 139 additions and 84 deletions

84
Machines/ZX8081/Video.cpp Normal file
View File

@ -0,0 +1,84 @@
//
// Video.cpp
// Clock Signal
//
// Created by Thomas Harte on 06/06/2017.
// Copyright © 2017 Thomas Harte. All rights reserved.
//
#include "Video.hpp"
using namespace ZX8081;
Video::Video() :
crt_(new Outputs::CRT::CRT(210 * 2, 1, Outputs::CRT::DisplayType::PAL50, 1)),
line_data_(nullptr),
line_data_pointer_(nullptr),
cycles_since_update_(0),
sync_(false) {
crt_->set_composite_sampling_function(
"float composite_sample(usampler2D sampler, vec2 coordinate, vec2 icoordinate, float phase, float amplitude)"
"{"
"return float(texture(texID, coordinate).r) / 255.0;"
"}");
}
void Video::run_for_cycles(int number_of_cycles) {
cycles_since_update_ += (unsigned int)number_of_cycles << 1;
}
void Video::flush() {
if(sync_) {
crt_->output_sync(cycles_since_update_);
} else {
if(line_data_) {
unsigned int data_length = (unsigned int)(line_data_pointer_ - line_data_);
if(data_length < cycles_since_update_) {
crt_->output_data(data_length, 1);
line_data_pointer_ = line_data_ = nullptr;
cycles_since_update_ -= data_length;
} else return;
}
uint8_t *colour_pointer = (uint8_t *)crt_->allocate_write_area(1);
if(colour_pointer) *colour_pointer = 0xff;
crt_->output_level(cycles_since_update_);
}
cycles_since_update_ = 0;
}
void Video::set_sync(bool sync) {
if(sync_ == sync) return;
flush();
sync_ = sync;
if(cycles_since_update_) flush();
}
void Video::output_byte(uint8_t byte) {
flush();
if(!line_data_) {
line_data_pointer_ = line_data_ = crt_->allocate_write_area(320);
}
if(line_data_) {
uint8_t mask = 0x80;
for(int c = 0; c < 8; c++) {
line_data_pointer_[c] = (byte & mask) ? 0xff : 0x00;
mask >>= 1;
}
line_data_pointer_ += 8;
if(line_data_pointer_ - line_data_ == 320) {
crt_->output_data(320, 1);
line_data_pointer_ = line_data_ = nullptr;
cycles_since_update_ -= 160;
}
}
}
std::shared_ptr<Outputs::CRT::CRT> Video::get_crt() {
return crt_;
}

36
Machines/ZX8081/Video.hpp Normal file
View File

@ -0,0 +1,36 @@
//
// Video.hpp
// Clock Signal
//
// Created by Thomas Harte on 06/06/2017.
// Copyright © 2017 Thomas Harte. All rights reserved.
//
#ifndef Machines_ZX8081_Video_hpp
#define Machines_ZX8081_Video_hpp
#include "../../Outputs/CRT/CRT.hpp"
namespace ZX8081 {
class Video {
public:
Video();
std::shared_ptr<Outputs::CRT::CRT> get_crt();
void run_for_cycles(int number_of_cycles);
void flush();
void set_sync(bool sync);
void output_byte(uint8_t byte);
private:
bool sync_;
uint8_t *line_data_, *line_data_pointer_;
unsigned int cycles_since_update_;
std::shared_ptr<Outputs::CRT::CRT> crt_;
};
}
#endif /* Video_hpp */

View File

@ -20,7 +20,6 @@ Machine::Machine() :
vsync_(false),
hsync_(false),
ram_(1024),
line_data_(nullptr),
key_states_{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
tape_player_(ZX8081ClockRate) {
// run at 3.25 Mhz
@ -30,7 +29,7 @@ Machine::Machine() :
}
int Machine::perform_machine_cycle(const CPU::Z80::MachineCycle &cycle) {
cycles_since_display_update_ += (unsigned int)cycle.length;
video_->run_for_cycles(cycle.length);
tape_player_.run_for_cycles(cycle.length);
uint16_t refresh = 0;
@ -80,8 +79,7 @@ int Machine::perform_machine_cycle(const CPU::Z80::MachineCycle &cycle) {
value = rom_[char_address & (rom_.size() - 1)] ^ mask;
}
// TODO: character lookup.
output_byte(value);
video_->output_byte(value);
*cycle.value = 0;
} else *cycle.value = value;
}
@ -98,14 +96,19 @@ int Machine::perform_machine_cycle(const CPU::Z80::MachineCycle &cycle) {
}
void Machine::flush() {
update_display();
video_->flush();
}
void Machine::setup_output(float aspect_ratio) {
video_.reset(new Video);
}
void Machine::close_output() {
video_.reset();
}
std::shared_ptr<Outputs::CRT::CRT> Machine::get_crt() {
return crt_;
return video_->get_crt();
}
std::shared_ptr<Outputs::Speaker> Machine::get_speaker() {
@ -134,87 +137,18 @@ void Machine::set_rom(ROMType type, std::vector<uint8_t> data) {
#pragma mark - Video
void Machine::update_display() {
// cycles_since_display_update_ = 0;
}
void Machine::set_vsync(bool sync) {
if(sync == vsync_) return;
vsync_ = sync;
update_sync();
}
void Machine::set_hsync(bool sync) {
if(sync == hsync_) return;
hsync_ = sync;
update_sync();
}
void Machine::update_sync() {
bool is_sync = hsync_ || vsync_;
if(is_sync == is_sync_) return;
if(line_data_) {
output_data();
}
if(is_sync_) {
crt_->output_sync(cycles_since_display_update_ << 1);
} else {
output_level(cycles_since_display_update_ << 1);
}
cycles_since_display_update_ = 0;
is_sync_ = is_sync;
}
void Machine::output_level(unsigned int number_of_cycles) {
uint8_t *colour_pointer = (uint8_t *)crt_->allocate_write_area(1);
if(colour_pointer) *colour_pointer = 0xff;
crt_->output_level(number_of_cycles);
}
void Machine::output_data() {
unsigned int data_length = (unsigned int)(line_data_pointer_ - line_data_);
crt_->output_data(data_length, 1);
line_data_pointer_ = line_data_ = nullptr;
cycles_since_display_update_ -= data_length >> 1;
}
void Machine::output_byte(uint8_t byte) {
if(line_data_) {
if(cycles_since_display_update_ > 4) {
output_data();
}
} else {
output_level(cycles_since_display_update_ << 1);
cycles_since_display_update_ = 0;
}
if(!line_data_) {
line_data_pointer_ = line_data_ = crt_->allocate_write_area(320);
}
if(line_data_) {
uint8_t mask = 0x80;
for(int c = 0; c < 8; c++) {
line_data_pointer_[c] = (byte & mask) ? 0xff : 0x00;
mask >>= 1;
}
line_data_pointer_ += 8;
if(line_data_pointer_ - line_data_ == 320) {
output_data();
}
}
}
void Machine::setup_output(float aspect_ratio) {
crt_.reset(new Outputs::CRT::CRT(210 * 2, 1, Outputs::CRT::DisplayType::PAL50, 1));
crt_->set_composite_sampling_function(
"float composite_sample(usampler2D sampler, vec2 coordinate, vec2 icoordinate, float phase, float amplitude)"
"{"
"return float(texture(texID, coordinate).r) / 255.0;"
"}");
video_->set_sync(vsync_ || hsync_);
}
#pragma mark - Keyboard

View File

@ -15,6 +15,8 @@
#include "../../Processors/Z80/Z80.hpp"
#include "../../Storage/Tape/Tape.hpp"
#include "Video.hpp"
#include <cstdint>
#include <vector>
@ -60,25 +62,18 @@ class Machine:
void clear_all_keys();
private:
std::shared_ptr<Outputs::CRT::CRT> crt_;
std::shared_ptr<Video> video_;
std::vector<uint8_t> zx81_rom_, zx80_rom_, rom_;
std::vector<uint8_t> ram_;
bool vsync_, hsync_;
bool is_sync_;
uint8_t *line_data_, *line_data_pointer_;
int line_counter_;
uint8_t key_states_[8];
unsigned int cycles_since_display_update_;
void update_display();
void set_vsync(bool sync);
void set_hsync(bool sync);
void update_sync();
void output_level(unsigned int number_of_cycles);
void output_byte(uint8_t byte);
void output_data();
Storage::Tape::BinaryTapePlayer tape_player_;
bool tape_level_;

View File

@ -403,6 +403,7 @@
4BCF1FA81DADC5250039D2E7 /* CSOric.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BCF1FA71DADC5250039D2E7 /* CSOric.mm */; };
4BCF1FAB1DADD41B0039D2E7 /* StaticAnalyser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BCF1FA91DADD41B0039D2E7 /* StaticAnalyser.cpp */; };
4BD14B111D74627C0088EAD6 /* StaticAnalyser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BD14B0F1D74627C0088EAD6 /* StaticAnalyser.cpp */; };
4BD3A30B1EE755C800B5B501 /* Video.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BD3A3091EE755C800B5B501 /* Video.cpp */; };
4BD468F71D8DF41D0084958B /* 1770.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BD468F51D8DF41D0084958B /* 1770.cpp */; };
4BD4A8CD1E077E8A0020D856 /* PCMSegment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B121F961E060CF000BFDA12 /* PCMSegment.cpp */; };
4BD4A8D01E077FD20020D856 /* PCMTrackTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BD4A8CF1E077FD20020D856 /* PCMTrackTests.mm */; };
@ -953,6 +954,8 @@
4BCF1FAA1DADD41B0039D2E7 /* StaticAnalyser.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = StaticAnalyser.hpp; path = ../../StaticAnalyser/Oric/StaticAnalyser.hpp; sourceTree = "<group>"; };
4BD14B0F1D74627C0088EAD6 /* StaticAnalyser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StaticAnalyser.cpp; path = ../../StaticAnalyser/Acorn/StaticAnalyser.cpp; sourceTree = "<group>"; };
4BD14B101D74627C0088EAD6 /* StaticAnalyser.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = StaticAnalyser.hpp; path = ../../StaticAnalyser/Acorn/StaticAnalyser.hpp; sourceTree = "<group>"; };
4BD3A3091EE755C800B5B501 /* Video.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Video.cpp; path = ZX8081/Video.cpp; sourceTree = "<group>"; };
4BD3A30A1EE755C800B5B501 /* Video.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Video.hpp; path = ZX8081/Video.hpp; sourceTree = "<group>"; };
4BD468F51D8DF41D0084958B /* 1770.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = 1770.cpp; path = 1770/1770.cpp; sourceTree = "<group>"; };
4BD468F61D8DF41D0084958B /* 1770.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = 1770.hpp; path = 1770/1770.hpp; sourceTree = "<group>"; };
4BD4A8CF1E077FD20020D856 /* PCMTrackTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PCMTrackTests.mm; sourceTree = "<group>"; };
@ -1092,6 +1095,8 @@
children = (
4B1497901EE4B5A800CE2596 /* ZX8081.cpp */,
4B1497911EE4B5A800CE2596 /* ZX8081.hpp */,
4BD3A3091EE755C800B5B501 /* Video.cpp */,
4BD3A30A1EE755C800B5B501 /* Video.hpp */,
);
name = ZX8081;
sourceTree = "<group>";
@ -2587,6 +2592,7 @@
4B77069D1EC904570053B588 /* Z80.cpp in Sources */,
4BAB62B51D327F7E00DF5BA0 /* G64.cpp in Sources */,
4BD468F71D8DF41D0084958B /* 1770.cpp in Sources */,
4BD3A30B1EE755C800B5B501 /* Video.cpp in Sources */,
4BBF99141C8FBA6F0075DAFB /* TextureBuilder.cpp in Sources */,
4BCF1FA81DADC5250039D2E7 /* CSOric.mm in Sources */,
4B5FADBA1DE3151600AEC565 /* FileHolder.cpp in Sources */,