Attempt further to discern MO6 meaning.
This commit is contained in:
1 parent
d2090c5b8d
commit
fe07d8c3b7
1 file changed
+55
-11
@@ -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 <something>, 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 <bool is_mo6>
|
||||
struct MemoryMap {
|
||||
public:
|
||||
@@ -50,9 +64,12 @@ public:
|
||||
}
|
||||
|
||||
void set_cartridge(const std::vector<uint8_t> &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<uint8_t> &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<uint8_t, 0x7c0> floppy_rom_;
|
||||
std::array<uint8_t, 0x1000> monitor_;
|
||||
std::vector<uint8_t> rom_;
|
||||
std::vector<uint8_t> 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;
|
||||
};
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user