diff --git a/Machines/Oric/Oric.cpp b/Machines/Oric/Oric.cpp index be8a0f5d0..63f574d62 100644 --- a/Machines/Oric/Oric.cpp +++ b/Machines/Oric/Oric.cpp @@ -57,16 +57,18 @@ class Joystick: public Inputs::ConcreteJoystick { }) {} void did_set_input(const Input &digital_input, bool is_active) final { -#define APPLY(b) if(is_active) state_ &= ~b; else state_ |= b; + const auto apply = [&](uint8_t bit) { + if(is_active) state_ &= ~bit; else state_ |= bit; + }; + switch(digital_input.type) { default: return; - case Input::Right: APPLY(0x02); break; - case Input::Left: APPLY(0x01); break; - case Input::Down: APPLY(0x08); break; - case Input::Up: APPLY(0x10); break; - case Input::Fire: APPLY(0x20); break; + case Input::Right: apply(0x02); break; + case Input::Left: apply(0x01); break; + case Input::Down: apply(0x08); break; + case Input::Up: apply(0x10); break; + case Input::Fire: apply(0x20); break; } -#undef APPLY } uint8_t get_state() { @@ -574,7 +576,9 @@ template get_input()); + via_.set_control_line_input( + MOS::MOS6522::Port::B, MOS::MOS6522::Line::One, + tape_player_.get_motor_control() ? + !tape_player_.get_input() : + !video_->vsync() + ); } // for Utility::TypeRecipient::Delegate @@ -795,24 +808,27 @@ template std::unique_ptr machine(const Analyser::Static::Oric::Target &target, const ROMMachine::ROMFetcher &rom_fetcher) { + switch(target.disk_interface) { + default: return std::make_unique>(target, rom_fetcher); + case DiskInterface::Microdisc: return std::make_unique>(target, rom_fetcher); + case DiskInterface::Pravetz: return std::make_unique>(target, rom_fetcher); + case DiskInterface::Jasmin: return std::make_unique>(target, rom_fetcher); + case DiskInterface::BD500: return std::make_unique>(target, rom_fetcher); + } +} + +} + std::unique_ptr Machine::Oric(const Analyser::Static::Target *target_hint, const ROMMachine::ROMFetcher &rom_fetcher) { auto *const oric_target = dynamic_cast(target_hint); -#define DiskInterfaceSwitch(processor) \ - switch(oric_target->disk_interface) { \ - default: return std::make_unique>(*oric_target, rom_fetcher); \ - case DiskInterface::Microdisc: return std::make_unique>(*oric_target, rom_fetcher); \ - case DiskInterface::Pravetz: return std::make_unique>(*oric_target, rom_fetcher); \ - case DiskInterface::Jasmin: return std::make_unique>(*oric_target, rom_fetcher); \ - case DiskInterface::BD500: return std::make_unique>(*oric_target, rom_fetcher); \ - } - switch(oric_target->processor) { - case Processor::WDC65816: DiskInterfaceSwitch(CPU::MOS6502Esque::Type::TWDC65816); - case Processor::MOS6502: DiskInterfaceSwitch(CPU::MOS6502Esque::Type::T6502); + case Processor::WDC65816: return machine(*oric_target, rom_fetcher); + case Processor::MOS6502: return machine(*oric_target, rom_fetcher); } -#undef DiskInterfaceSwitch - return nullptr; } diff --git a/Machines/Oric/Video.cpp b/Machines/Oric/Video.cpp index b14aab6b1..42636c636 100644 --- a/Machines/Oric/Video.cpp +++ b/Machines/Oric/Video.cpp @@ -17,10 +17,10 @@ using namespace Oric; namespace { const unsigned int PAL50VSyncStartPosition = 256*64; const unsigned int PAL60VSyncStartPosition = 234*64; - const unsigned int PAL50VSyncEndPosition = 259*64; + const unsigned int PAL50VSyncEndPosition = 259*64; // 19966 const unsigned int PAL60VSyncEndPosition = 238*64; const unsigned int PAL50Period = 312*64; - const unsigned int PAL60Period = 262*64; + const unsigned int PAL60Period = 264*64; } VideoOutput::VideoOutput(uint8_t *memory) : @@ -111,6 +111,25 @@ void VideoOutput::set_colour_rom(const std::vector &rom) { // } } +bool VideoOutput::vsync() { + return counter_ >= v_sync_start_position_ && counter_ < v_sync_end_position_; +} + +Cycles VideoOutput::next_sequence_point() const { + if(counter_ < v_sync_start_position_) { + return Cycles(v_sync_start_position_ - counter_); + } else if(counter_ < v_sync_end_position_) { + return Cycles(v_sync_end_position_ - counter_); + } else { + // After vsync the length of the next frame is baked in, so this is safe + // (but should probably be factored out). + return Cycles( + counter_period_ + static_cast(next_frame_is_sixty_hertz_ ? PAL60VSyncStartPosition : PAL50VSyncStartPosition) + - counter_ + ); + } +} + void VideoOutput::run_for(const Cycles cycles) { // Horizontal: 0-39: pixels; otherwise blank; 48-53 sync, 54-56 colour burst. // Vertical: 0-223: pixels; otherwise blank; 256-259 (50Hz) or 234-238 (60Hz) sync. @@ -123,7 +142,7 @@ void VideoOutput::run_for(const Cycles cycles) { int h_counter = counter_ & 63; int cycles_run_for = 0; - if(counter_ >= v_sync_start_position_ && counter_ < v_sync_end_position_) { + if(vsync()) { // this is a sync line cycles_run_for = v_sync_end_position_ - counter_; clamp(crt_.output_sync((v_sync_end_position_ - v_sync_start_position_) * 6)); diff --git a/Machines/Oric/Video.hpp b/Machines/Oric/Video.hpp index 165c10e83..b3bc5a2ea 100644 --- a/Machines/Oric/Video.hpp +++ b/Machines/Oric/Video.hpp @@ -23,6 +23,9 @@ class VideoOutput { void set_colour_rom(const std::vector &colour_rom); void run_for(const Cycles cycles); + Cycles next_sequence_point() const; + + bool vsync(); void set_scan_target(Outputs::Display::ScanTarget *scan_target); void set_display_type(Outputs::Display::DisplayType display_type);