From 0eb5dd968892449c611e09b7263c14212b6f0b1b Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 26 Nov 2017 16:47:59 -0500 Subject: [PATCH] Introduces the fundamentals of bus routing for the MSX. --- Components/9918/9918.cpp | 7 +++ Components/9918/9918.hpp | 5 ++ Machines/MSX/MSX.cpp | 100 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 111 insertions(+), 1 deletion(-) diff --git a/Components/9918/9918.cpp b/Components/9918/9918.cpp index ab20623c4..37aa9a0b6 100644 --- a/Components/9918/9918.cpp +++ b/Components/9918/9918.cpp @@ -25,3 +25,10 @@ std::shared_ptr TMS9918::get_crt() { void TMS9918::run_for(const Cycles cycles) { } + +void TMS9918::set_register(int address, uint8_t value) { +} + +uint8_t TMS9918::get_register(int address) { + return 0; +} diff --git a/Components/9918/9918.hpp b/Components/9918/9918.hpp index ad1bc9e80..ec03a1d1c 100644 --- a/Components/9918/9918.hpp +++ b/Components/9918/9918.hpp @@ -12,6 +12,8 @@ #include "../../Outputs/CRT/CRT.hpp" #include "../../ClockReceiver/ClockReceiver.hpp" +#include + namespace TI { class TMS9918 { @@ -34,6 +36,9 @@ class TMS9918 { */ void run_for(const Cycles cycles); + void set_register(int address, uint8_t value); + uint8_t get_register(int address); + private: std::shared_ptr crt_; }; diff --git a/Machines/MSX/MSX.cpp b/Machines/MSX/MSX.cpp index 1a9f8fad5..6ac20760a 100644 --- a/Machines/MSX/MSX.cpp +++ b/Machines/MSX/MSX.cpp @@ -20,6 +20,12 @@ namespace MSX { +class i8255PortHandler: public Intel::i8255::PortHandler { +}; + +class AYPortHandler: public GI::AY38910::PortHandler { +}; + class ConcreteMachine: public Machine, public CPU::Z80::BusHandler, @@ -27,7 +33,9 @@ class ConcreteMachine: public ConfigurationTarget::Machine { public: ConcreteMachine(): - z80_(*this) { + z80_(*this), + i8255_(i8255_port_handler_) { + ay_.set_port_handler(&ay_port_handler_); set_clock_rate(3579545); } @@ -57,9 +65,99 @@ class ConcreteMachine: return true; } + HalfCycles perform_machine_cycle(const CPU::Z80::PartialMachineCycle &cycle) { + uint16_t address = cycle.address ? *cycle.address : 0x0000; + switch(cycle.operation) { + case CPU::Z80::PartialMachineCycle::ReadOpcode: + case CPU::Z80::PartialMachineCycle::Read: + *cycle.value = read_pointers_[address >> 14][address & 16383]; + break; + + case CPU::Z80::PartialMachineCycle::Write: + write_pointers_[address >> 14][address & 16383] = *cycle.value; + break; + + case CPU::Z80::PartialMachineCycle::Input: + switch(address & 0xff) { + case 0x98: case 0x99: + *cycle.value = vdp_->get_register(address); + break; + + case 0xa2: + ay_.set_control_lines(static_cast(GI::AY38910::BDIR | GI::AY38910::BC1)); + ay_.set_data_input(*cycle.value); + break; + + case 0xa8: case 0xa9: + case 0xaa: case 0xab: + *cycle.value = i8255_.get_register(address); + break; + } + break; + + case CPU::Z80::PartialMachineCycle::Output: + switch(address & 0xff) { + case 0x98: case 0x99: + vdp_->set_register(address, *cycle.value); + break; + + case 0xa0: + ay_.set_control_lines(static_cast(GI::AY38910::BDIR | GI::AY38910::BC2 | GI::AY38910::BC1)); + ay_.set_data_input(*cycle.value); + break; + + case 0xa1: + ay_.set_control_lines(static_cast(GI::AY38910::BDIR | GI::AY38910::BC2)); + ay_.set_data_input(*cycle.value); + break; + + case 0xa8: case 0xa9: + case 0xaa: case 0xab: + i8255_.set_register(address, *cycle.value); + break; + } + break; + + default: break; + } + + // Per the best information I currently have, the MSX inserts an extra cycle into each opcode read, + // but otherwise runs without pause. + return HalfCycles((cycle.operation == CPU::Z80::PartialMachineCycle::ReadOpcode) ? 2 : 0);; + } + + // Obtains the system ROMs. + bool set_rom_fetcher(const std::function>>(const std::string &machine, const std::vector &names)> &roms_with_names) override { + auto roms = roms_with_names( + "MSX", + { + "basic.rom", "main_msx1.rom" + }); + + if(!roms[0] || !roms[1]) return false; + + basic_ = std::move(*roms[0]); + basic_.resize(16384); + + main_ = std::move(*roms[1]); + main_.resize(16384); + + return true; + } + private: CPU::Z80::Processor z80_; std::unique_ptr vdp_; + Intel::i8255::i8255 i8255_; + GI::AY38910::AY38910 ay_; + + i8255PortHandler i8255_port_handler_; + AYPortHandler ay_port_handler_; + + uint8_t *read_pointers_[4]; + uint8_t *write_pointers_[4]; + uint8_t ram_[65536]; + std::vector basic_, main_; }; }