1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-02-05 21:32:55 +00:00

Merge pull request #122 from TomHarte/16bit6560

Increases VIC-I intermediate format to 16 bit and corrects output colours
This commit is contained in:
Thomas Harte 2017-05-13 22:03:08 -04:00 committed by GitHub
commit 81c5f4ab19
3 changed files with 40 additions and 28 deletions

View File

@ -43,7 +43,7 @@ class Speaker: public ::Outputs::Filter<Speaker> {
template <class T> class MOS6560 {
public:
MOS6560() :
crt_(new Outputs::CRT::CRT(65*4, 4, Outputs::CRT::NTSC60, 1)),
crt_(new Outputs::CRT::CRT(65*4, 4, Outputs::CRT::NTSC60, 2)),
speaker_(new Speaker),
horizontal_counter_(0),
vertical_counter_(0),
@ -53,13 +53,11 @@ template <class T> class MOS6560 {
crt_->set_composite_sampling_function(
"float composite_sample(usampler2D texID, vec2 coordinate, vec2 iCoordinate, float phase, float amplitude)"
"{"
"uint c = texture(texID, coordinate).r;"
"float y = float(c >> 4) / 4.0;"
"uint yC = c & 15u;"
"float phaseOffset = 6.283185308 * float(yC) / 16.0;"
"vec2 yc = texture(texID, coordinate).rg / vec2(255.0);"
"float phaseOffset = 6.283185308 * 2.0 * yc.y;"
"float chroma = cos(phase + phaseOffset);"
"return mix(y, step(yC, 14) * chroma, amplitude);"
"return mix(yc.x, step(yc.y, 0.75) * chroma, amplitude);"
"}");
// default to NTSC
@ -82,17 +80,29 @@ template <class T> class MOS6560 {
*/
void set_output_mode(OutputMode output_mode) {
output_mode_ = output_mode;
const uint8_t luminances[16] = { // range is 04
0, 4, 1, 3, 2, 2, 1, 3,
2, 1, 2, 1, 2, 3, 2, 3
// Lumunances are encoded trivially: on a 0255 scale.
const uint8_t luminances[16] = {
0, 255, 109, 189,
199, 144, 159, 161,
126, 227, 227, 207,
235, 173, 188, 196
};
const uint8_t pal_chrominances[16] = { // range is 015; 15 is a special case meaning "no chrominance"
15, 15, 5, 13, 2, 10, 0, 8,
6, 7, 5, 13, 2, 10, 0, 8,
// Chrominances are encoded such that 0128 is a complete revolution of phase;
// anything above 191 disables the colour subcarrier. Phase is relative to the
// colour burst, so 0 is green.
const uint8_t pal_chrominances[16] = {
255, 255, 40, 112,
8, 88, 120, 56,
40, 48, 40, 112,
8, 88, 120, 56,
};
const uint8_t ntsc_chrominances[16] = {
15, 15, 2, 10, 4, 12, 6, 14,
0, 8, 2, 10, 4, 12, 6, 14,
255, 255, 40, 104,
64, 120, 80, 16,
32, 32, 40, 104,
64, 120, 80, 16,
};
const uint8_t *chrominances;
Outputs::CRT::DisplayType display_type;
@ -118,7 +128,7 @@ template <class T> class MOS6560 {
}
crt_->set_new_display_type((unsigned int)(timing_.cycles_per_line*4), display_type);
// crt_->set_visible_area(Outputs::CRT::Rect(0.1f, 0.1f, 0.8f, 0.8f));
crt_->set_visible_area(Outputs::CRT::Rect(0.05f, 0.05f, 0.9f, 0.9f));
// switch(output_mode) {
// case OutputMode::PAL:
@ -130,7 +140,9 @@ template <class T> class MOS6560 {
// }
for(int c = 0; c < 16; c++) {
colours_[c] = (uint8_t)((luminances[c] << 4) | chrominances[c]);
uint8_t *colour = (uint8_t *)&colours_[c];
colour[0] = luminances[c];
colour[1] = chrominances[c];
}
}
@ -256,7 +268,7 @@ template <class T> class MOS6560 {
pixel_pointer = nullptr;
if(output_state_ == State::Pixels) {
pixel_pointer = crt_->allocate_write_area(260);
pixel_pointer = (uint16_t *)crt_->allocate_write_area(260);
}
}
cycles_in_state_++;
@ -266,9 +278,9 @@ template <class T> class MOS6560 {
character_value_ = pixel_data;
if(pixel_pointer) {
uint8_t cell_colour = colours_[character_colour_ & 0x7];
uint16_t cell_colour = colours_[character_colour_ & 0x7];
if(!(character_colour_&0x8)) {
uint8_t colours[2];
uint16_t colours[2];
if(registers_.invertedCells) {
colours[0] = cell_colour;
colours[1] = registers_.backgroundColour;
@ -285,7 +297,7 @@ template <class T> class MOS6560 {
pixel_pointer[6] = colours[(character_value_ >> 1)&1];
pixel_pointer[7] = colours[(character_value_ >> 0)&1];
} else {
uint8_t colours[4] = {registers_.backgroundColour, registers_.borderColour, cell_colour, registers_.auxiliary_colour};
uint16_t colours[4] = {registers_.backgroundColour, registers_.borderColour, cell_colour, registers_.auxiliary_colour};
pixel_pointer[0] =
pixel_pointer[1] = colours[(character_value_ >> 6)&3];
pixel_pointer[2] =
@ -295,6 +307,7 @@ template <class T> class MOS6560 {
pixel_pointer[6] =
pixel_pointer[7] = colours[(character_value_ >> 0)&3];
}
pixel_pointer += 8;
}
} else {
@ -358,7 +371,7 @@ template <class T> class MOS6560 {
break;
case 0xf: {
uint8_t new_border_colour = colours_[value & 0x07];
uint16_t new_border_colour = colours_[value & 0x07];
if(this_state_ == State::Border && new_border_colour != registers_.borderColour) {
output_border(cycles_in_state_ * 4);
cycles_in_state_ = 0;
@ -405,7 +418,7 @@ template <class T> class MOS6560 {
uint8_t first_column_location, first_row_location;
uint8_t number_of_columns, number_of_rows;
uint16_t character_cell_start_address, video_matrix_start_address;
uint8_t backgroundColour, borderColour, auxiliary_colour;
uint16_t backgroundColour, borderColour, auxiliary_colour;
bool invertedCells;
uint8_t direct_values[16];
@ -436,11 +449,11 @@ template <class T> class MOS6560 {
bool is_odd_frame_, is_odd_line_;
// lookup table from 6560 colour index to appropriate PAL/NTSC value
uint8_t colours_[16];
uint16_t colours_[16];
uint8_t *pixel_pointer;
uint16_t *pixel_pointer;
void output_border(unsigned int number_of_cycles) {
uint8_t *colour_pointer = crt_->allocate_write_area(1);
uint16_t *colour_pointer = (uint16_t *)crt_->allocate_write_area(1);
if(colour_pointer) *colour_pointer = registers_.borderColour;
crt_->output_level(number_of_cycles);
}

View File

@ -336,7 +336,7 @@ void OpenGLOutputBuilder::set_output_device(OutputDevice output_device) {
}
void OpenGLOutputBuilder::set_timing(unsigned int input_frequency, unsigned int cycles_per_line, unsigned int height_of_display, unsigned int horizontal_scan_period, unsigned int vertical_scan_period, unsigned int vertical_period_divider) {
output_mutex_.lock();
std::lock_guard<std::mutex> lock_guard(output_mutex_);
input_frequency_ = input_frequency;
cycles_per_line_ = cycles_per_line;
height_of_display_ = height_of_display;
@ -345,7 +345,6 @@ void OpenGLOutputBuilder::set_timing(unsigned int input_frequency, unsigned int
vertical_period_divider_ = vertical_period_divider;
set_timing_uniforms();
output_mutex_.unlock();
}
#pragma mark - Internal Configuration

View File

@ -99,7 +99,7 @@ std::unique_ptr<IntermediateShader> IntermediateShader::make_shader(const std::s
"phaseAndAmplitudeVarying.y = 0.33;" // TODO: reinstate connection with (phaseTimeAndAmplitude.y/256.0)
// determine output position by scaling the output position according to the texture size
"vec2 eyePosition = 2.0*(extendedOutputPosition / outputTextureSize) - vec2(1.0) + vec2(1.0)/outputTextureSize;"
"vec2 eyePosition = 2.0*(extendedOutputPosition / outputTextureSize) - vec2(1.0);"
"gl_Position = vec4(eyePosition, 0.0, 1.0);"
"}", sampler_type, input_variable);