From 6cdd41e5a99b90f4d20469b76c2a21f161105814 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Fri, 9 Dec 2016 22:17:10 -0500 Subject: [PATCH] Added direct use of the colour ROM, uploading 16 bits per pixel to contain the entire ROM composite wave. --- Machines/Oric/Oric.cpp | 7 +- Machines/Oric/Oric.hpp | 4 +- Machines/Oric/Video.cpp | 66 +++++++++++-------- Machines/Oric/Video.hpp | 4 +- .../Clock Signal/Machine/Wrappers/CSOric.mm | 2 + 5 files changed, 52 insertions(+), 31 deletions(-) diff --git a/Machines/Oric/Oric.cpp b/Machines/Oric/Oric.cpp index 037519eb2..6a6a8310c 100644 --- a/Machines/Oric/Oric.cpp +++ b/Machines/Oric/Oric.cpp @@ -82,6 +82,10 @@ void Machine::set_rom(ROM rom, const std::vector &data) case BASIC11: basic11_rom_ = std::move(data); break; case BASIC10: basic10_rom_ = std::move(data); break; case Microdisc: microdisc_rom_ = std::move(data); break; + case Colour: + colour_rom_ = std::move(data); + if(video_output_) video_output_->set_colour_rom(colour_rom_); + break; } } @@ -172,9 +176,10 @@ void Machine::update_video() void Machine::setup_output(float aspect_ratio) { - video_output_.reset(new VideoOutput(ram_)); via_.ay8910.reset(new GI::AY38910()); via_.ay8910->set_clock_rate(1000000); + video_output_.reset(new VideoOutput(ram_)); + if(!colour_rom_.empty()) video_output_->set_colour_rom(colour_rom_); } void Machine::close_output() diff --git a/Machines/Oric/Oric.hpp b/Machines/Oric/Oric.hpp index a069d7edc..b7c72889c 100644 --- a/Machines/Oric/Oric.hpp +++ b/Machines/Oric/Oric.hpp @@ -53,7 +53,7 @@ enum Key: uint16_t { }; enum ROM { - BASIC10, BASIC11, Microdisc + BASIC10, BASIC11, Microdisc, Colour }; class Machine: @@ -103,7 +103,7 @@ class Machine: private: // RAM and ROM - std::vector basic11_rom_, basic10_rom_, microdisc_rom_; + std::vector basic11_rom_, basic10_rom_, microdisc_rom_, colour_rom_; uint8_t ram_[65536], rom_[16384]; int cycles_since_video_update_; inline void update_video(); diff --git a/Machines/Oric/Video.cpp b/Machines/Oric/Video.cpp index fa5054de7..3326bde69 100644 --- a/Machines/Oric/Video.cpp +++ b/Machines/Oric/Video.cpp @@ -27,7 +27,7 @@ VideoOutput::VideoOutput(uint8_t *memory) : phase_(0), v_sync_start_position_(PAL50VSyncStartPosition), v_sync_end_position_(PAL50VSyncEndPosition), counter_period_(PAL50Period), next_frame_is_sixty_hertz_(false), - crt_(new Outputs::CRT::CRT(64*6, 6, Outputs::CRT::DisplayType::PAL50, 1)) + crt_(new Outputs::CRT::CRT(64*6, 6, Outputs::CRT::DisplayType::PAL50, 2)) { // TODO: this is a copy and paste from the Electron; factor out. crt_->set_rgb_sampling_function( @@ -40,21 +40,10 @@ VideoOutput::VideoOutput(uint8_t *memory) : crt_->set_composite_sampling_function( "float composite_sample(usampler2D sampler, vec2 coordinate, vec2 icoordinate, float phase, float amplitude)" "{" - "float[] array = float[](" -"0.0000, 0.0000, 0.0000, 0.0000, " -"0.1100, 0.3250, 0.3750, 0.1600, " -"0.4100, 0.2150, 0.3250, 0.5200, " -"0.3750, 0.4100, 0.5700, 0.5200, " -"0.2650, 0.2150, 0.0500, 0.1100, " -"0.2650, 0.4100, 0.3250, 0.1600, " -"0.5200, 0.3250, 0.2650, 0.4600, " -"0.5200, 0.5200, 0.5200, 0.5200" - ");" - "uint texValue = texture(sampler, coordinate).r;" - "texValue >>= 4 - (int(icoordinate.x * 8) & 4);" + "uint texValue = uint(dot(texture(sampler, coordinate).rg, uvec2(1, 256)));" "uint iPhase = uint((phase + 3.141592654 + 0.39269908175) * 2.0 / 3.141592654) & 3u;" - "return array[((texValue & 7u) << 2) + iPhase];" // (texValue << 2) -// "return (mod(phase, 2.0 * 3.141592654) > 3.141592654) ? 0.7273 : 0.3636;" // (texValue << 2) + "texValue = (texValue >> (4u*(3u - iPhase))) & 15u;" + "return (float(texValue) - 4.0) / 20.0;" "}" ); @@ -62,6 +51,17 @@ VideoOutput::VideoOutput(uint8_t *memory) : crt_->set_visible_area(crt_->get_rect_for_area(50, 224, 16 * 6, 40 * 6, 4.0f / 3.0f)); } +void VideoOutput::set_colour_rom(const std::vector &rom) +{ + for(size_t c = 0; c < 8; c++) + { + size_t index = (c << 2); + uint16_t rom_value = (uint16_t)(((uint16_t)rom[index] << 8) | (uint16_t)rom[index+1]); + rom_value = (rom_value & 0xff00) | ((rom_value >> 4)&0x000f) | ((rom_value << 4)&0x00f0); + colour_forms_[c] = rom_value; + } +} + std::shared_ptr VideoOutput::get_crt() { return crt_; @@ -96,11 +96,11 @@ void VideoOutput::run_for_cycles(int number_of_cycles) use_alternative_character_set_ = use_double_height_characters_ = blink_text_ = false; set_character_set_base_address(); phase_ += 64; - pixel_target_ = crt_->allocate_write_area(120); + pixel_target_ = (uint16_t *)crt_->allocate_write_area(240); if(!counter_) { - phase_ += 128; // TODO: incorporate all the lines that were missed + phase_ += 3; // TODO: incorporate all the lines that were missed frame_counter_++; v_sync_start_position_ = next_frame_is_sixty_hertz_ ? PAL60VSyncStartPosition : PAL50VSyncStartPosition; @@ -138,14 +138,25 @@ void VideoOutput::run_for_cycles(int number_of_cycles) { if(pixel_target_) { - uint8_t colours[2] = { - (uint8_t)(paper_ ^ inverse_mask), - (uint8_t)(ink_ ^ inverse_mask), - }; +// uint8_t colours[2] = { +// (uint8_t)(paper_ ^ inverse_mask), +// (uint8_t)(ink_ ^ inverse_mask), +// }; +// +// pixel_target_[0] = (colours[(pixels >> 4)&1] & 0x0f) | (colours[(pixels >> 5)&1] & 0xf0); +// pixel_target_[1] = (colours[(pixels >> 2)&1] & 0x0f) | (colours[(pixels >> 3)&1] & 0xf0); +// pixel_target_[2] = (colours[(pixels >> 0)&1] & 0x0f) | (colours[(pixels >> 1)&1] & 0xf0); - pixel_target_[0] = (colours[(pixels >> 4)&1] & 0x0f) | (colours[(pixels >> 5)&1] & 0xf0); - pixel_target_[1] = (colours[(pixels >> 2)&1] & 0x0f) | (colours[(pixels >> 3)&1] & 0xf0); - pixel_target_[2] = (colours[(pixels >> 0)&1] & 0x0f) | (colours[(pixels >> 1)&1] & 0xf0); + uint16_t colours[2] = { + colour_forms_[(paper_ ^ inverse_mask)&0xf], + colour_forms_[(ink_ ^ inverse_mask)&0xf], + }; + pixel_target_[0] = colours[(pixels >> 5)&1]; + pixel_target_[1] = colours[(pixels >> 4)&1]; + pixel_target_[2] = colours[(pixels >> 3)&1]; + pixel_target_[3] = colours[(pixels >> 2)&1]; + pixel_target_[4] = colours[(pixels >> 1)&1]; + pixel_target_[5] = colours[(pixels >> 0)&1]; } } else @@ -186,15 +197,16 @@ void VideoOutput::run_for_cycles(int number_of_cycles) default: break; } - if(pixel_target_) pixel_target_[0] = pixel_target_[1] = pixel_target_[2] = (uint8_t)(paper_ ^ inverse_mask); +// if(pixel_target_) pixel_target_[0] = pixel_target_[1] = pixel_target_[2] = (uint8_t)(paper_ ^ inverse_mask); + if(pixel_target_) pixel_target_[0] = pixel_target_[1] = pixel_target_[2] = pixel_target_[3] = pixel_target_[4] = pixel_target_[5] = colour_forms_[(paper_&0xf) ^ inverse_mask]; } - if(pixel_target_) pixel_target_ += 3; + if(pixel_target_) pixel_target_ += 6; h_counter++; } if(h_counter == 40) { - crt_->output_data(40 * 6, 2); + crt_->output_data(40 * 6, 1); } } else diff --git a/Machines/Oric/Video.hpp b/Machines/Oric/Video.hpp index 2629d3ddd..b8126558e 100644 --- a/Machines/Oric/Video.hpp +++ b/Machines/Oric/Video.hpp @@ -18,6 +18,7 @@ class VideoOutput { VideoOutput(uint8_t *memory); std::shared_ptr get_crt(); void run_for_cycles(int number_of_cycles); + void set_colour_rom(const std::vector &rom); private: uint8_t *ram_; @@ -28,7 +29,8 @@ class VideoOutput { int v_sync_start_position_, v_sync_end_position_, counter_period_; // Output target - uint8_t *pixel_target_; + uint16_t *pixel_target_; + uint16_t colour_forms_[8]; // Registers uint8_t ink_, paper_; diff --git a/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSOric.mm b/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSOric.mm index 6a565abb4..efc8c6e69 100644 --- a/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSOric.mm +++ b/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSOric.mm @@ -27,10 +27,12 @@ { NSData *basic10 = [self rom:@"basic10"]; NSData *basic11 = [self rom:@"basic11"]; + NSData *colour = [self rom:@"colour"]; NSData *microdisc = [self rom:@"microdisc"]; if(basic10) _oric.set_rom(Oric::BASIC10, basic10.stdVector8); if(basic11) _oric.set_rom(Oric::BASIC11, basic11.stdVector8); + if(colour) _oric.set_rom(Oric::Colour, colour.stdVector8); if(microdisc) _oric.set_rom(Oric::Microdisc, microdisc.stdVector8); } return self;