mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-25 16:31:42 +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:
parent
b55579c348
commit
8c66e1d99d
84
Machines/ZX8081/Video.cpp
Normal file
84
Machines/ZX8081/Video.cpp
Normal 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
36
Machines/ZX8081/Video.hpp
Normal 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 */
|
@ -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
|
||||
|
@ -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_;
|
||||
|
@ -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 */,
|
||||
|
Loading…
Reference in New Issue
Block a user