From 304f0999cdfffad56566a3abb648820a5c5b8a03 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Wed, 12 Oct 2016 21:29:21 -0400 Subject: [PATCH] Made a faulty but hopefully creditable attempt to demarcate an Oric frame. --- Machines/Oric/Oric.cpp | 18 +++++---------- Machines/Oric/Oric.hpp | 5 ++-- Machines/Oric/Video.cpp | 51 +++++++++++++++++++++++++++++++++++++++-- Machines/Oric/Video.hpp | 16 ++++++++++++- 4 files changed, 72 insertions(+), 18 deletions(-) diff --git a/Machines/Oric/Oric.cpp b/Machines/Oric/Oric.cpp index c3205580d..9a1ac6494 100644 --- a/Machines/Oric/Oric.cpp +++ b/Machines/Oric/Oric.cpp @@ -45,6 +45,11 @@ unsigned int Machine::perform_bus_operation(CPU6502::BusOperation operation, uin return 1; } +void Machine::synchronise() +{ + update_video(); +} + void Machine::update_video() { _videoOutput->run_for_cycles(_cycles_since_video_update); @@ -53,21 +58,10 @@ void Machine::update_video() void Machine::setup_output(float aspect_ratio) { - // TODO: this is a copy and paste from the Electron; correct. - - _crt.reset(new Outputs::CRT::CRT(256, 8, Outputs::CRT::DisplayType::PAL50, 1)); - _crt->set_rgb_sampling_function( - "vec3 rgb_sample(usampler2D sampler, vec2 coordinate, vec2 icoordinate)" - "{" - "uint texValue = texture(sampler, coordinate).r;" - "texValue >>= 4 - (int(icoordinate.x * 8) & 4);" - "return vec3( uvec3(texValue) & uvec3(4u, 2u, 1u));" - "}"); - _videoOutput.reset(new VideoOutput(_ram)); - _videoOutput->set_crt(_crt); } void Machine::close_output() { + _videoOutput.reset(); } diff --git a/Machines/Oric/Oric.hpp b/Machines/Oric/Oric.hpp index ccf2ffca1..2fbededf9 100644 --- a/Machines/Oric/Oric.hpp +++ b/Machines/Oric/Oric.hpp @@ -38,12 +38,12 @@ class Machine: // to satisfy CPU6502::Processor unsigned int perform_bus_operation(CPU6502::BusOperation operation, uint16_t address, uint8_t *value); - void synchronise() { update_video(); } + void synchronise(); // to satisfy CRTMachine::Machine virtual void setup_output(float aspect_ratio); virtual void close_output(); - virtual std::shared_ptr get_crt() { return _crt; } + virtual std::shared_ptr get_crt() { return _videoOutput->get_crt(); } virtual std::shared_ptr get_speaker() { return nullptr; } virtual void run_for_cycles(int number_of_cycles) { CPU6502::Processor::run_for_cycles(number_of_cycles); } @@ -54,7 +54,6 @@ class Machine: inline void update_video(); // Outputs - std::shared_ptr _crt; std::unique_ptr _videoOutput; }; diff --git a/Machines/Oric/Video.cpp b/Machines/Oric/Video.cpp index 3c106a9f0..7ddd97686 100644 --- a/Machines/Oric/Video.cpp +++ b/Machines/Oric/Video.cpp @@ -10,14 +10,61 @@ using namespace Oric; -VideoOutput::VideoOutput(uint8_t *memory) : _ram(memory) +VideoOutput::VideoOutput(uint8_t *memory) : + _ram(memory), + _frame_counter(0), _counter(0), + _state(Sync), _cycles_in_state(0) { + _crt.reset(new Outputs::CRT::CRT(384, 6, Outputs::CRT::DisplayType::PAL50, 1)); + + // TODO: this is a copy and paste from the Electron; factor out. + _crt->set_rgb_sampling_function( + "vec3 rgb_sample(usampler2D sampler, vec2 coordinate, vec2 icoordinate)" + "{" + "uint texValue = texture(sampler, coordinate).r;" + "texValue >>= 4 - (int(icoordinate.x * 8) & 4);" + "return vec3( uvec3(texValue) & uvec3(4u, 2u, 1u));" + "}"); } -void VideoOutput::set_crt(std::shared_ptr crt) +std::shared_ptr VideoOutput::get_crt() { + return _crt; } void VideoOutput::run_for_cycles(int number_of_cycles) { + // Vertical: 0–39: pixels; otherwise blank; 48–53 sync + // Horizontal: 0–223: pixels; otherwise blank; 256–259 sync + + while(number_of_cycles--) + { + _counter = (_counter + 1)%(312 * 64); // TODO: NTSC + + State new_state = Blank; + if((_counter & 63) >= 48 && (_counter & 63) <= 53) new_state = Sync; + else if(_counter >= 256*312 && _counter <= 259*312) new_state = Sync; + else if(_counter < 224 && ((_counter&63) < 40)) new_state = Pixels; + + if(_state != new_state) + { + switch(_state) + { + case Sync: _crt->output_sync(_cycles_in_state * 6); break; + case Blank: _crt->output_blank(_cycles_in_state * 6); break; + case Pixels: _crt->output_data(_cycles_in_state * 6, 2); break; + } + _state = new_state; + _cycles_in_state = 0; + if(_state == Pixels) _pixel_target = _crt->allocate_write_area(120); + } + else _cycles_in_state++; + + if(new_state == Pixels) { + _pixel_target[0] = 0x70; + _pixel_target[1] = 0x14; + _pixel_target[2] = 0x23; + _pixel_target += 3; + } + } } diff --git a/Machines/Oric/Video.hpp b/Machines/Oric/Video.hpp index cf5a49564..a16ed54bc 100644 --- a/Machines/Oric/Video.hpp +++ b/Machines/Oric/Video.hpp @@ -16,11 +16,25 @@ namespace Oric { class VideoOutput { public: VideoOutput(uint8_t *memory); - void set_crt(std::shared_ptr crt); + std::shared_ptr get_crt(); void run_for_cycles(int number_of_cycles); private: uint8_t *_ram; + std::shared_ptr _crt; + + // Counters + int _counter, _frame_counter; + + // Output state + enum State { + Blank, Sync, Pixels + } _state; + unsigned int _cycles_in_state; + uint8_t *_pixel_target; + + // Registers + uint8_t _ink, _style, _paper; }; }