1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-25 16:31:42 +00:00

Reintroduces Vic-20 output.

Resolving errors in shader generation while I'm here.
This commit is contained in:
Thomas Harte 2018-11-22 22:43:42 -05:00
parent c0454ff101
commit b9aca39eb0
4 changed files with 37 additions and 51 deletions

View File

@ -64,23 +64,12 @@ template <class BusHandler> class MOS6560 {
public:
MOS6560(BusHandler &bus_handler) :
bus_handler_(bus_handler),
// crt_(new Outputs::CRT::CRT(65*4, 4, Outputs::Display::Type::NTSC60, 2)),
crt_(65*4, 4, Outputs::Display::Type::NTSC60, Outputs::Display::InputDataType::Luminance8Phase8),
audio_generator_(audio_queue_),
speaker_(audio_generator_)
{
// crt_->set_svideo_sampling_function(
// "vec2 svideo_sample(usampler2D texID, vec2 coordinate, float phase, float amplitude)"
// "{"
// "vec2 yc = texture(texID, coordinate).rg / vec2(255.0);"
//
// "float phaseOffset = 6.283185308 * 2.0 * yc.y;"
// "float chroma = step(yc.y, 0.75) * cos(phase + phaseOffset);"
//
// "return vec2(yc.x, chroma);"
// "}");
// default to s-video output
// crt_->set_video_signal(Outputs::Display::VideoSignal::SVideo);
// crt_.set_video_signal(Outputs::Display::VideoSignal::SVideo);
// default to NTSC
set_output_mode(OutputMode::NTSC);
@ -94,7 +83,7 @@ template <class BusHandler> class MOS6560 {
speaker_.set_input_rate(static_cast<float>(clock_rate / 4.0));
}
Outputs::CRT::CRT *get_crt() { return crt_.get(); }
void set_scan_target(Outputs::Display::ScanTarget *scan_target) { crt_.set_scan_target(scan_target); }
Outputs::Speaker::Speaker *get_speaker() { return &speaker_; }
void set_high_frequency_cutoff(float cutoff) {
@ -155,14 +144,14 @@ template <class BusHandler> class MOS6560 {
break;
}
crt_->set_new_display_type(timing_.cycles_per_line*4, display_type);
crt_.set_new_display_type(timing_.cycles_per_line*4, display_type);
switch(output_mode) {
case OutputMode::PAL:
crt_->set_visible_area(Outputs::Display::Rect(0.1f, 0.07f, 0.9f, 0.9f));
crt_.set_visible_area(Outputs::Display::Rect(0.1f, 0.07f, 0.9f, 0.9f));
break;
case OutputMode::NTSC:
crt_->set_visible_area(Outputs::Display::Rect(0.05f, 0.05f, 0.9f, 0.9f));
crt_.set_visible_area(Outputs::Display::Rect(0.05f, 0.05f, 0.9f, 0.9f));
break;
}
@ -284,17 +273,17 @@ template <class BusHandler> class MOS6560 {
// update the CRT
if(this_state_ != output_state_) {
switch(output_state_) {
case State::Sync: crt_->output_sync(cycles_in_state_ * 4); break;
case State::ColourBurst: crt_->output_colour_burst(cycles_in_state_ * 4, (is_odd_frame_ || is_odd_line_) ? 128 : 0); break;
case State::Border: output_border(cycles_in_state_ * 4); break;
case State::Pixels: crt_->output_data(cycles_in_state_ * 4); break;
case State::Sync: crt_.output_sync(cycles_in_state_ * 4); break;
case State::ColourBurst: crt_.output_colour_burst(cycles_in_state_ * 4, (is_odd_frame_ || is_odd_line_) ? 128 : 0); break;
case State::Border: output_border(cycles_in_state_ * 4); break;
case State::Pixels: crt_.output_data(cycles_in_state_ * 4); break;
}
output_state_ = this_state_;
cycles_in_state_ = 0;
pixel_pointer = nullptr;
if(output_state_ == State::Pixels) {
pixel_pointer = reinterpret_cast<uint16_t *>(crt_->begin_data(260));
pixel_pointer = reinterpret_cast<uint16_t *>(crt_.begin_data(260));
}
}
cycles_in_state_++;
@ -438,7 +427,7 @@ template <class BusHandler> class MOS6560 {
private:
BusHandler &bus_handler_;
std::unique_ptr<Outputs::CRT::CRT> crt_;
Outputs::CRT::CRT crt_;
Concurrency::DeferringAsyncTaskQueue audio_queue_;
AudioGenerator audio_generator_;
@ -512,9 +501,9 @@ template <class BusHandler> class MOS6560 {
uint16_t *pixel_pointer;
void output_border(int number_of_cycles) {
uint16_t *colour_pointer = reinterpret_cast<uint16_t *>(crt_->begin_data(1));
uint16_t *colour_pointer = reinterpret_cast<uint16_t *>(crt_.begin_data(1));
if(colour_pointer) *colour_pointer = registers_.borderColour;
crt_->output_level(number_of_cycles);
crt_.output_level(number_of_cycles);
}
struct {

View File

@ -294,6 +294,7 @@ class ConcreteMachine:
public:
ConcreteMachine(const Analyser::Static::Commodore::Target &target, const ROMMachine::ROMFetcher &rom_fetcher) :
m6502_(*this),
mos6560_(mos6560_bus_handler_),
user_port_via_port_handler_(new UserPortVIA),
keyboard_via_port_handler_(new KeyboardVIA),
serial_port_(new SerialPort),
@ -377,13 +378,16 @@ class ConcreteMachine:
if(target.region == Analyser::Static::Commodore::Target::Region::American || target.region == Analyser::Static::Commodore::Target::Region::Japanese) {
// NTSC
set_clock_rate(1022727);
output_mode_ = MOS::MOS6560::OutputMode::NTSC;
mos6560_.set_output_mode(MOS::MOS6560::OutputMode::NTSC);
} else {
// PAL
set_clock_rate(1108404);
output_mode_ = MOS::MOS6560::OutputMode::PAL;
mos6560_.set_output_mode(MOS::MOS6560::OutputMode::PAL);
}
mos6560_.set_high_frequency_cutoff(1600); // There is a 1.6Khz low-pass filter in the Vic-20.
mos6560_.set_clock_rate(get_clock_rate());
// Initialise the memory maps as all pointing to nothing
memset(processor_read_memory_map_, 0, sizeof(processor_read_memory_map_));
memset(processor_write_memory_map_, 0, sizeof(processor_write_memory_map_));
@ -501,7 +505,7 @@ class ConcreteMachine:
if((address&0xfc00) == 0x9000) {
if(!(address&0x100)) {
update_video();
result &= mos6560_->get_register(address);
result &= mos6560_.get_register(address);
}
if(address & 0x10) result &= user_port_via_.get_register(address);
if(address & 0x20) result &= keyboard_via_.get_register(address);
@ -588,7 +592,7 @@ class ConcreteMachine:
// The VIC is selected by bit 8 = 0
if(!(address&0x100)) {
update_video();
mos6560_->set_register(address, *value);
mos6560_.set_register(address, *value);
}
// The first VIA is selected by bit 4 = 1.
if(address & 0x10) user_port_via_.set_register(address, *value);
@ -613,7 +617,7 @@ class ConcreteMachine:
void flush() {
update_video();
mos6560_->flush();
mos6560_.flush();
}
void run_for(const Cycles cycles) override final {
@ -621,22 +625,11 @@ class ConcreteMachine:
}
void set_scan_target(Outputs::Display::ScanTarget *scan_target) override final {
mos6560_.reset(new MOS::MOS6560::MOS6560<Vic6560BusHandler>(mos6560_bus_handler_));
mos6560_->set_high_frequency_cutoff(1600); // There is a 1.6Khz low-pass filter in the Vic-20.
mos6560_->set_output_mode(output_mode_);
mos6560_->set_clock_rate(get_clock_rate());
mos6560_.set_scan_target(scan_target);
}
// void close_output() override final {
// mos6560_ = nullptr;
// }
//
// Outputs::CRT::CRT *get_crt() override final {
// return mos6560_->get_crt();
// }
Outputs::Speaker::Speaker *get_speaker() override final {
return mos6560_->get_speaker();
return mos6560_.get_speaker();
}
void mos6522_did_change_interrupt_status(void *mos6522) override final {
@ -701,7 +694,7 @@ class ConcreteMachine:
private:
void update_video() {
mos6560_->run_for(cycles_since_mos6560_update_.flush());
mos6560_.run_for(cycles_since_mos6560_update_.flush());
}
CPU::MOS6502::Processor<CPU::MOS6502::Personality::P6502, ConcreteMachine, false> m6502_;
@ -731,8 +724,7 @@ class ConcreteMachine:
Cycles cycles_since_mos6560_update_;
Vic6560BusHandler mos6560_bus_handler_;
MOS::MOS6560::OutputMode output_mode_;
std::unique_ptr<MOS::MOS6560::MOS6560<Vic6560BusHandler>> mos6560_;
MOS::MOS6560::MOS6560<Vic6560BusHandler> mos6560_;
std::shared_ptr<UserPortVIA> user_port_via_port_handler_;
std::shared_ptr<KeyboardVIA> keyboard_via_port_handler_;
std::shared_ptr<SerialPort> serial_port_;

View File

@ -190,9 +190,14 @@ std::unique_ptr<Shader> ScanTarget::input_shader(InputDataType input_data_type,
fragment_shader += "fragColour = vec4(vec3(texture(textureName, textureCoordinate).r / 255.0), 1.0);";
break;
case InputDataType::Phase8Luminance8:
case InputDataType::Luminance8Phase8:
computed_display_type = DisplayType::SVideo;
fragment_shader += "fragColour = vec4(texture(textureName, textureCoordinate).rg / vec2(255.0), 0.0, 1.0);";
fragment_shader +=
"vec2 yc = texture(textureName, textureCoordinate).rg / vec2(255.0);"
"float phaseOffset = 3.141592654 * 2.0 * 2.0 * yc.y;"
"float chroma = step(yc.y, 0.75) * cos(compositeAngle + phaseOffset);"
"fragColour = vec4(yc.x, chroma, 0.0, 1.0);";
break;
case InputDataType::Red1Green1Blue1:
@ -233,7 +238,7 @@ std::unique_ptr<Shader> ScanTarget::input_shader(InputDataType input_data_type,
}
// If the output type isn't SVideo, add an SVideo to composite step.
if(computed_display_type != DisplayType::SVideo) {
if(display_type != DisplayType::SVideo) {
fragment_shader += "fragColour = vec4(vec3(mix(fragColour.r, 2.0*(fragColour.g - 0.5), compositeAmplitudeOut)), 1.0);";
}
}

View File

@ -70,7 +70,7 @@ enum class InputDataType {
// of a colour subcarrier. So they can be used to generate a luminance signal,
// or an s-video pipeline.
Phase8Luminance8, // 2 bytes/pixel; first is phase, second is luminance.
Luminance8Phase8, // 2 bytes/pixel; first is luminance, second is phase.
// Phase is encoded on a 192-unit circle; anything
// greater than 192 implies that the colour part of
// the signal should be omitted.
@ -92,7 +92,7 @@ inline size_t size_for_data_type(InputDataType data_type) {
case InputDataType::Red2Green2Blue2:
return 1;
case InputDataType::Phase8Luminance8:
case InputDataType::Luminance8Phase8:
case InputDataType::Red4Green4Blue4:
return 2;