diff --git a/Machines/Atari2600/TIA.cpp b/Machines/Atari2600/TIA.cpp index 15d2c36dc..0e5630e9b 100644 --- a/Machines/Atari2600/TIA.cpp +++ b/Machines/Atari2600/TIA.cpp @@ -137,7 +137,7 @@ void TIA::set_output_mode(Atari2600::TIA::OutputMode output_mode) { "uint y = c & 14u;" "uint iPhase = (c >> 4);" - "float phaseOffset = 6.283185308 * (float(iPhase) + 3.0) / 13.0 + 5.074880441076923;" + "float phaseOffset = 6.283185308 * float(iPhase) / 13.0 + 5.074880441076923;" "return mix(float(y) / 14.0, step(1, iPhase) * cos(phase + phaseOffset), amplitude);" "}"); display_type = Outputs::CRT::DisplayType::NTSC60; diff --git a/Machines/Oric/Video.cpp b/Machines/Oric/Video.cpp index bfb857782..a4107101a 100644 --- a/Machines/Oric/Video.cpp +++ b/Machines/Oric/Video.cpp @@ -42,6 +42,7 @@ VideoOutput::VideoOutput(uint8_t *memory) : "return (float(texValue) - 4.0) / 20.0;" "}" ); + crt_->set_composite_function_type(Outputs::CRT::CRT::CompositeSourceType::DiscreteFourSamplesPerCycle, 0.0f); set_output_device(Outputs::CRT::Television); crt_->set_visible_area(crt_->get_rect_for_area(50, 224, 16 * 6, 40 * 6, 4.0f / 3.0f)); diff --git a/Outputs/CRT/CRT.cpp b/Outputs/CRT/CRT.cpp index cb0aed7cd..5b4cf0cdc 100644 --- a/Outputs/CRT/CRT.cpp +++ b/Outputs/CRT/CRT.cpp @@ -62,6 +62,14 @@ void CRT::set_new_display_type(unsigned int cycles_per_line, DisplayType display } } +void CRT::set_composite_function_type(CompositeSourceType type, float offset_of_first_sample) { + if(type == DiscreteFourSamplesPerCycle) { + colour_burst_phase_adjustment_ = (uint8_t)(offset_of_first_sample * 256.0f) & 63; + } else { + colour_burst_phase_adjustment_ = 0xff; + } +} + CRT::CRT(unsigned int common_output_divisor, unsigned int buffer_depth) : sync_capacitor_charge_level_(0), is_receiving_sync_(false), @@ -272,7 +280,8 @@ void CRT::output_scan(const Scan *const scan) { colour_burst_phase_ = (position_phase + scan->phase) & 255; colour_burst_amplitude_ = scan->amplitude; - colour_burst_phase_ = (colour_burst_phase_ & ~63) + 32; + if(colour_burst_phase_adjustment_ != 0xff) + colour_burst_phase_ = (colour_burst_phase_ & ~63) + colour_burst_phase_adjustment_; } } diff --git a/Outputs/CRT/CRT.hpp b/Outputs/CRT/CRT.hpp index f9025f740..3f3847cf8 100644 --- a/Outputs/CRT/CRT.hpp +++ b/Outputs/CRT/CRT.hpp @@ -59,7 +59,7 @@ class CRT { }; void output_scan(const Scan *scan); - uint8_t colour_burst_phase_, colour_burst_amplitude_; + uint8_t colour_burst_phase_, colour_burst_amplitude_, colour_burst_phase_adjustment_; bool is_writing_composite_run_; unsigned int phase_denominator_, phase_numerator_, colour_cycle_numerator_; @@ -252,6 +252,26 @@ class CRT { }); } + enum CompositeSourceType { + /// The composite function provides continuous output. + Continuous, + /// The composite function provides discrete output with four unique values per colour cycle. + DiscreteFourSamplesPerCycle + }; + + /*! Provides information about the type of output the composite sampling function provides — discrete or continuous. + + This is necessary because the CRT implementation samples discretely and therefore can use fewer intermediate + samples if it can exactly duplicate the sampling rate and placement of the composite sampling function. + + A continuous function is assumed by default. + + @param type The type of output provided by the function supplied to `set_composite_sampling_function`. + @param offset_of_first_sample The relative position within a full cycle of the colour subcarrier at which the + first sample falls. E.g. 0.125 means "at 1/8th of the way through the complete cycle". + */ + void set_composite_function_type(CompositeSourceType type, float offset_of_first_sample = 0.0f); + /*! Sets a function that will map from whatever data the machine provided to an RGB signal. If the output mode is composite then a default mapping from RGB to the display's composite diff --git a/StaticAnalyser/Commodore/Disk.cpp b/StaticAnalyser/Commodore/Disk.cpp index 890289a07..fa54e613c 100644 --- a/StaticAnalyser/Commodore/Disk.cpp +++ b/StaticAnalyser/Commodore/Disk.cpp @@ -24,6 +24,7 @@ class CommodoreGCRParser: public Storage::Disk::Controller { CommodoreGCRParser() : Storage::Disk::Controller(4000000, 1, 300), shift_register_(0), track_(1) { drive.reset(new Storage::Disk::Drive); set_drive(drive); + set_motor_on(true); } struct Sector {