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:
parent
c0454ff101
commit
b9aca39eb0
@ -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 {
|
||||
|
@ -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_;
|
||||
|
@ -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);";
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user