From fe07d8c3b7248d5affce93beded75ca24837efe7 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Thu, 9 Apr 2026 10:12:01 -0400 Subject: [PATCH] Attempt further to discern MO6 meaning. --- Machines/Thomson/MO5/MemoryMap.hpp | 66 +++++++++++++++++++++++++----- 1 file changed, 55 insertions(+), 11 deletions(-) diff --git a/Machines/Thomson/MO5/MemoryMap.hpp b/Machines/Thomson/MO5/MemoryMap.hpp index af9da4c8f..36bdf4605 100644 --- a/Machines/Thomson/MO5/MemoryMap.hpp +++ b/Machines/Thomson/MO5/MemoryMap.hpp @@ -19,6 +19,20 @@ namespace Thomson::MO5 { +// +// Notes on the layout of the standard MO ROM images: +// +// The MO5 images are 16kb in total, representing what should go into the +// final 16kb of the memory map. +// +// The MO6 images are 64kb in total: +// +// * the first 12kb is the BASIC 1 portion; +// * the next 12 kb is , possibly the GUI? +// * what is possibly a 4kb gap then follows — it's less than 300 bytes of content, then filler — though it ends in C000 which could be a vector?; +// * there are then probably two meaningful pages of a full 16kb each (the first of which is definitely to do with BASIC 128, presumably the second also); and +// * the final 4kb is the monitor, which resides permanently at $f000–; + template struct MemoryMap { public: @@ -50,9 +64,12 @@ public: } void set_cartridge(const std::vector &cartridge) { + cartridge_ = cartridge; if constexpr (!is_mo6) { - set_rom(cartridge.begin(), cartridge.end()); + cartridge_is_paged_ = true; + rom_.clear(); } + update_commutable_rom(); } void set_floppy_rom(const std::vector &rom) { @@ -109,17 +126,33 @@ private: const uint8_t *read_[0x10]{}; void update_commutable_rom() { - // TODO: this should be pageable. - - // Commutable ROM: 0xb000 to 0xf000; if it's smaller than that then - // align it to end at 0xf000. - const size_t start = 0xf - (rom_.size() >> 12); - for(size_t c = 0xb; c < 0xf; c++) { - if(c >= start) { - set_read(c, rom_.data() + ((c - start) << 12)); - } else { - set_read(c, nullptr); + const auto set_range = [&](const size_t start, const size_t length, const uint8_t *source) { + for(size_t c = 0x0; c < length; c++) { + set_read(c + start, source + (c << 12)); } + }; + + if(cartridge_is_paged_) { + // TODO: there's some sort of paging here, too. + set_range(0xb, 0x4, cartridge_.data()); + return; + } + + switch(paged_rom_) { + case PagedROM::FirstBank12kb: + set_read(0xb, nullptr); + set_range(0xc, 0x3, rom_.data()); + break; + case PagedROM::SecondBank12kb: + set_read(0xb, nullptr); + set_range(0xc, 0x3, rom_.data() + 12*1024); + break; + case PagedROM::ThirdBank16kb: + set_range(0xb, 0x4, rom_.data() + 28*1024); + break; + case PagedROM::FourthBank16kb: + set_range(0xb, 0x4, rom_.data() + 44*1024); + break; } } @@ -136,6 +169,17 @@ private: std::array floppy_rom_; std::array monitor_; std::vector rom_; + std::vector cartridge_; + + // TODO: the following are entirely invented by me. Probably will need adjusting to + // whatever the hardware registers model, if I ever figure it out. + enum class PagedROM { + FirstBank12kb = 0, + SecondBank12kb = 1, + ThirdBank16kb = 2, + FourthBank16kb = 3, + } paged_rom_ = is_mo6 ? PagedROM::SecondBank12kb : PagedROM::FirstBank12kb; + bool cartridge_is_paged_ = false; }; }