From 096551ab3e9248658576a46544d83cd1b98c1fd7 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 4 Jun 2017 18:32:23 -0400 Subject: [PATCH] Made a first attempt to hash out the ZX80's bus. Video output isn't yet going though. Can't seem to find clarity on whether horizontal sync is really programmatic. Let's see. --- Machines/ZX8081/ZX8081.cpp | 67 ++++++++++++++++++++++++++++++++++++-- Machines/ZX8081/ZX8081.hpp | 7 ++++ Processors/Z80/Z80.hpp | 6 ++-- 3 files changed, 76 insertions(+), 4 deletions(-) diff --git a/Machines/ZX8081/ZX8081.cpp b/Machines/ZX8081/ZX8081.cpp index 417823a55..f332b1eb1 100644 --- a/Machines/ZX8081/ZX8081.cpp +++ b/Machines/ZX8081/ZX8081.cpp @@ -10,17 +10,64 @@ using namespace ZX8081; -Machine::Machine() { +Machine::Machine() : + vertical_sync_(false), + ram_(65536) { // run at 3.25 Mhz set_clock_rate(3250000); } int Machine::perform_machine_cycle(const CPU::Z80::MachineCycle &cycle) { + cycles_since_display_update_ += cycle.length; + + uint8_t r; + switch(cycle.operation) { + case CPU::Z80::BusOperation::Output: + if(*cycle.address == 0xff) { + update_display(); + set_sync(false); + } + break; + + case CPU::Z80::BusOperation::Input: + if(*cycle.address == 0xfe) { + update_display(); + set_sync(true); + } + break; + + case CPU::Z80::BusOperation::Interrupt: + *cycle.value = 0xff; + break; + + case CPU::Z80::BusOperation::ReadOpcode: + r = (uint8_t)get_value_of_register(CPU::Z80::Register::R); + set_interrupt_line(!(r & 0x40)); + case CPU::Z80::BusOperation::Read: + if(*cycle.address < rom_.size()) *cycle.value = rom_[*cycle.address]; + else { + uint8_t value = ram_[*cycle.address]; + if(*cycle.address > 32768 && !(value & 0x40) && cycle.operation == CPU::Z80::BusOperation::ReadOpcode) { + // TODO: character lookup. + output_byte(value); + *cycle.value = 0; + } + else *cycle.value = value; + } + break; + + case CPU::Z80::BusOperation::Write: + ram_[*cycle.address] = *cycle.value; + break; + + default: break; + } + return 0; } void Machine::setup_output(float aspect_ratio) { - crt_.reset(new Outputs::CRT::CRT(207 * 8, 8, Outputs::CRT::DisplayType::PAL50, 1)); + crt_.reset(new Outputs::CRT::CRT(207, 1, Outputs::CRT::DisplayType::PAL50, 1)); crt_->set_rgb_sampling_function( "vec3 rgb_sample(usampler2D sampler, vec2 coordinate, vec2 icoordinate)" "{" @@ -29,6 +76,7 @@ void Machine::setup_output(float aspect_ratio) { } void Machine::flush() { + update_display(); } void Machine::close_output() { @@ -46,6 +94,8 @@ void Machine::run_for_cycles(int number_of_cycles) { } void Machine::configure_as_target(const StaticAnalyser::Target &target) { + // TODO: pay attention to the target + rom_ = zx80_rom_; } void Machine::set_rom(ROMType type, std::vector data) { @@ -54,3 +104,16 @@ void Machine::set_rom(ROMType type, std::vector data) { case ZX81: zx81_rom_ = data; break; } } + +#pragma mark - Video + +void Machine::update_display() { + // TODO. + cycles_since_display_update_ = 0; +} + +void Machine::set_sync(bool sync) { +} + +void Machine::output_byte(uint8_t byte) { +} diff --git a/Machines/ZX8081/ZX8081.hpp b/Machines/ZX8081/ZX8081.hpp index 41c90ef31..3edd4791c 100644 --- a/Machines/ZX8081/ZX8081.hpp +++ b/Machines/ZX8081/ZX8081.hpp @@ -49,6 +49,13 @@ class Machine: std::shared_ptr crt_; std::vector zx81_rom_, zx80_rom_, rom_; std::vector ram_; + + bool vertical_sync_; + + int cycles_since_display_update_; + void update_display(); + void set_sync(bool sync); + void output_byte(uint8_t byte); }; } diff --git a/Processors/Z80/Z80.hpp b/Processors/Z80/Z80.hpp index 396258122..a9e68c454 100644 --- a/Processors/Z80/Z80.hpp +++ b/Processors/Z80/Z80.hpp @@ -38,7 +38,7 @@ enum Register { IXh, IXl, IX, IYh, IYl, IY, - R, I, + R, I, Refresh, IFF1, IFF2, IM }; @@ -1652,10 +1652,11 @@ template class Processor { case Register::R: return r_; case Register::I: return i_; + case Register::Refresh: return (uint16_t)(r_ | (i_ << 8)); case Register::IFF1: return iff1_ ? 1 : 0; case Register::IFF2: return iff2_ ? 1 : 0; - case Register::IM: return interrupt_mode_; + case Register::IM: return (uint16_t)interrupt_mode_; default: return 0; } @@ -1710,6 +1711,7 @@ template class Processor { case Register::R: r_ = (uint8_t)value; break; case Register::I: i_ = (uint8_t)value; break; + case Register::Refresh: r_ = (uint8_t)value; i_ = (uint8_t)(value >> 8); break; case Register::IFF1: iff1_ = !!value; break; case Register::IFF2: iff2_ = !!value; break;