From caf3ac06458c572b641ffb45426c11792e1b3432 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 5 Aug 2017 19:20:38 -0400 Subject: [PATCH] Sought: (i) to instruct the CPC that it should be a 664, not a 464, if given a disk image (at least until I have RAM paging implemented for a 6128); (ii) to support ROM selection within the CPC and allow paging in of AMSDOS. --- Machines/AmstradCPC/AmstradCPC.cpp | 52 +++++++++++++++----- Machines/AmstradCPC/AmstradCPC.hpp | 7 +-- StaticAnalyser/AmstradCPC/StaticAnalyser.cpp | 3 ++ StaticAnalyser/StaticAnalyser.hpp | 12 +++++ 4 files changed, 58 insertions(+), 16 deletions(-) diff --git a/Machines/AmstradCPC/AmstradCPC.cpp b/Machines/AmstradCPC/AmstradCPC.cpp index f3c36b523..6e718af6d 100644 --- a/Machines/AmstradCPC/AmstradCPC.cpp +++ b/Machines/AmstradCPC/AmstradCPC.cpp @@ -567,8 +567,10 @@ class ConcreteMachine: case 1: crtc_bus_handler_.set_colour(*cycle.value & 0x1f); break; case 2: // Perform ROM paging. - read_pointers_[0] = (*cycle.value & 4) ? &ram_[0] : os_.data(); - read_pointers_[3] = (*cycle.value & 8) ? &ram_[49152] : basic_.data(); + read_pointers_[0] = (*cycle.value & 4) ? &ram_[0] : roms_[rom_model_].data(); + + upper_rom_is_paged_ = !(*cycle.value & 8); + read_pointers_[3] = upper_rom_is_paged_ ? roms_[upper_rom_].data() : &ram_[49152]; // Reset the interrupt timer if requested. if(*cycle.value & 0x10) interrupt_timer_.reset_count(); @@ -580,6 +582,12 @@ class ConcreteMachine: } } + // Check for an upper ROM selection + if(has_fdc_ && address == 0xdf00) { + upper_rom_ = (*cycle.value == 7) ? ROMType::AMSDOS : rom_model_ + 1; + if(upper_rom_is_paged_) read_pointers_[3] = roms_[upper_rom_].data(); + } + // Check for a CRTC access if(!(address & 0x4000)) { switch((address >> 8) & 3) { @@ -666,11 +674,28 @@ class ConcreteMachine: /// The ConfigurationTarget entry point; should configure this meachine as described by @c target. void configure_as_target(const StaticAnalyser::Target &target) { - // Establish reset memory map as per machine model (or, for now, as a hard-wired 464) - read_pointers_[0] = os_.data(); + switch(target.amstradcpc.model) { + case StaticAnalyser::AmstradCPCModel::CPC464: + rom_model_ = ROMType::OS464; + has_fdc_ = false; + break; + case StaticAnalyser::AmstradCPCModel::CPC664: + rom_model_ = ROMType::OS664; + has_fdc_ = true; + break; + case StaticAnalyser::AmstradCPCModel::CPC6128: + rom_model_ = ROMType::OS6128; + has_fdc_ = true; + break; + } + + // Establish default memory map + upper_rom_is_paged_ = true; + upper_rom_ = rom_model_ + 1; + read_pointers_[0] = roms_[rom_model_].data(); read_pointers_[1] = &ram_[16384]; read_pointers_[2] = &ram_[32768]; - read_pointers_[3] = basic_.data(); + read_pointers_[3] = roms_[upper_rom_].data(); write_pointers_[0] = &ram_[0]; write_pointers_[1] = &ram_[16384]; @@ -681,16 +706,13 @@ class ConcreteMachine: if(!target.tapes.empty()) { tape_player_.set_tape(target.tapes.front()); } + + // TODO: disks. } // See header; provides the system ROMs. void set_rom(ROMType type, std::vector data) { - // Keep only the two ROMs that are currently of interest. - switch(type) { - case ROMType::OS464: os_ = data; break; - case ROMType::BASIC464: basic_ = data; break; - default: break; - } + roms_[(int)type] = data; } // See header; sets a key as either pressed or released. @@ -722,8 +744,12 @@ class ConcreteMachine: HalfCycles crtc_counter_; HalfCycles half_cycles_since_ay_update_; - uint8_t ram_[65536]; - std::vector os_, basic_; + uint8_t ram_[128 * 1024]; + std::vector roms_[7]; + int rom_model_; + bool has_fdc_; + bool upper_rom_is_paged_; + int upper_rom_; uint8_t *read_pointers_[4]; uint8_t *write_pointers_[4]; diff --git a/Machines/AmstradCPC/AmstradCPC.hpp b/Machines/AmstradCPC/AmstradCPC.hpp index b3afc8e52..50ddeeda3 100644 --- a/Machines/AmstradCPC/AmstradCPC.hpp +++ b/Machines/AmstradCPC/AmstradCPC.hpp @@ -18,9 +18,10 @@ namespace AmstradCPC { -enum ROMType: uint8_t { - OS464, OS664, OS6128, - BASIC464, BASIC664, BASIC6128, +enum ROMType: int { + OS464 = 0, BASIC464, + OS664, BASIC664, + OS6128, BASIC6128, AMSDOS }; diff --git a/StaticAnalyser/AmstradCPC/StaticAnalyser.cpp b/StaticAnalyser/AmstradCPC/StaticAnalyser.cpp index b66621960..1c176b332 100644 --- a/StaticAnalyser/AmstradCPC/StaticAnalyser.cpp +++ b/StaticAnalyser/AmstradCPC/StaticAnalyser.cpp @@ -19,5 +19,8 @@ void StaticAnalyser::AmstradCPC::AddTargets( target.disks = disks; target.tapes = tapes; target.cartridges = cartridges; + + target.amstradcpc.model = target.disks.empty() ? AmstradCPCModel::CPC464 : AmstradCPCModel::CPC664; + destination.push_back(target); } diff --git a/StaticAnalyser/StaticAnalyser.hpp b/StaticAnalyser/StaticAnalyser.hpp index ac1aca5ee..df63a43fa 100644 --- a/StaticAnalyser/StaticAnalyser.hpp +++ b/StaticAnalyser/StaticAnalyser.hpp @@ -46,6 +46,12 @@ enum class ZX8081MemoryModel { SixtyFourKB }; +enum class AmstradCPCModel { + CPC464, + CPC664, + CPC6128 +}; + /*! A list of disks, tapes and cartridges plus information about the machine to which to attach them and its configuration, and instructions on how to launch the software attached, plus a measure of confidence in this target's correctness. @@ -61,6 +67,8 @@ struct Target { } machine; float probability; + // TODO: this is too C-like a solution; make Target a base class and + // turn the following into information held by more specific subclasses. union { struct { bool has_adfs; @@ -87,6 +95,10 @@ struct Target { ZX8081MemoryModel memory_model; bool isZX81; } zx8081; + + struct { + AmstradCPCModel model; + } amstradcpc; }; std::string loadingCommand;