1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-04 18:29:40 +00:00

Attempts to support the panoply of EXOS and BASIC versions.

This commit is contained in:
Thomas Harte 2021-06-19 22:59:09 -04:00
parent 42a98e1676
commit 0e1e8c7faa
4 changed files with 155 additions and 13 deletions

View File

@ -18,9 +18,21 @@ namespace Static {
namespace Enterprise {
struct Target: public Analyser::Static::Target, public Reflection::StructImpl<Target> {
Target() : Analyser::Static::Target(Machine::Enterprise) {}
ReflectableEnum(EXOSVersion, v10, v20, v21, v23, Any);
ReflectableEnum(BASICVersion, v10, v11, v21, Any, None);
// TODO: I assume there'll be relevant fields to add here.
EXOSVersion exos_version = EXOSVersion::Any;
BASICVersion basic_version = BASICVersion::None;
Target() : Analyser::Static::Target(Machine::Enterprise) {
if(needs_declare()) {
AnnounceEnum(EXOSVersion);
AnnounceEnum(BASICVersion);
DeclareField(exos_version);
DeclareField(basic_version);
}
}
};
}

View File

@ -70,17 +70,92 @@ class ConcreteMachine:
// Request a clock of 4Mhz; this'll be mapped upwards for Nick and Dave elsewhere.
set_clock_rate(4'000'000);
constexpr ROM::Name exos_name = ROM::Name::EnterpriseEXOS;
const auto request = ROM::Request(exos_name);
ROM::Request request;
using Target = Analyser::Static::Enterprise::Target;
// Pick one or more EXOS ROMs.
switch(target.exos_version) {
case Target::EXOSVersion::v10: request = request && ROM::Request(ROM::Name::EnterpriseEXOS10); break;
case Target::EXOSVersion::v20: request = request && ROM::Request(ROM::Name::EnterpriseEXOS20); break;
case Target::EXOSVersion::v21: request = request && ROM::Request(ROM::Name::EnterpriseEXOS21); break;
case Target::EXOSVersion::v23: request = request && ROM::Request(ROM::Name::EnterpriseEXOS23); break;
case Target::EXOSVersion::Any:
request =
request && (
ROM::Request(ROM::Name::EnterpriseEXOS10) || ROM::Request(ROM::Name::EnterpriseEXOS20) ||
ROM::Request(ROM::Name::EnterpriseEXOS21) || ROM::Request(ROM::Name::EnterpriseEXOS23)
);
break;
default: break;
}
// Similarly pick one or more BASIC ROMs.
switch(target.basic_version) {
case Target::BASICVersion::v10:
request = request && (
ROM::Request(ROM::Name::EnterpriseBASIC10) ||
(ROM::Request(ROM::Name::EnterpriseBASIC10Part1) && ROM::Request(ROM::Name::EnterpriseBASIC10Part2))
);
break;
case Target::BASICVersion::v11:
request = request && (
ROM::Request(ROM::Name::EnterpriseBASIC11) ||
ROM::Request(ROM::Name::EnterpriseBASIC11Suffixed)
);
case Target::BASICVersion::v21:
request = request && ROM::Request(ROM::Name::EnterpriseBASIC21);
break;
case Target::BASICVersion::Any:
request =
request && (
ROM::Request(ROM::Name::EnterpriseBASIC10) ||
(ROM::Request(ROM::Name::EnterpriseBASIC10Part1) && ROM::Request(ROM::Name::EnterpriseBASIC10Part2)) ||
ROM::Request(ROM::Name::EnterpriseBASIC11) ||
ROM::Request(ROM::Name::EnterpriseBASIC21)
);
break;
default: break;
}
// Get and validate ROMs.
auto roms = rom_fetcher(request);
if(!request.validate(roms)) {
throw ROMMachine::Error::MissingROMs;
}
const auto &exos = roms.find(exos_name)->second;
// Extract the appropriate EXOS ROM.
exos_.fill(0xff);
memcpy(exos_.data(), exos.data(), std::min(exos_.size(), exos.size()));
for(const auto rom_name: { ROM::Name::EnterpriseEXOS10, ROM::Name::EnterpriseEXOS20, ROM::Name::EnterpriseEXOS21, ROM::Name::EnterpriseEXOS23 }) {
const auto exos = roms.find(rom_name);
if(exos != roms.end()) {
memcpy(exos_.data(), exos->second.data(), std::min(exos_.size(), exos->second.size()));
break;
}
}
// Extract the appropriate BASIC ROM[s] (if any).
basic_.fill(0xff);
bool has_basic = false;
for(const auto rom_name: { ROM::Name::EnterpriseBASIC10, ROM::Name::EnterpriseBASIC11, ROM::Name::EnterpriseBASIC11Suffixed, ROM::Name::EnterpriseBASIC21 }) {
const auto basic = roms.find(rom_name);
if(basic != roms.end()) {
memcpy(basic_.data(), basic->second.data(), std::min(basic_.size(), basic->second.size()));
has_basic = true;
break;
}
}
if(!has_basic) {
const auto basic1 = roms.find(ROM::Name::EnterpriseBASIC10Part1);
const auto basic2 = roms.find(ROM::Name::EnterpriseBASIC10Part2);
if(basic1 != roms.end() && basic2 != roms.end()) {
memcpy(&basic_[0x0000], basic1->second.data(), std::min(size_t(8192), basic1->second.size()));
memcpy(&basic_[0x2000], basic2->second.data(), std::min(size_t(8192), basic2->second.size()));
}
}
// Seed key state.
clear_all_keys();
// Take a reasonable guess at the initial memory configuration:
@ -212,6 +287,7 @@ class ConcreteMachine:
// MARK: - Memory layout
std::array<uint8_t, 64 * 1024> ram_;
std::array<uint8_t, 64 * 1024> exos_;
std::array<uint8_t, 16 * 1024> basic_;
const uint8_t min_ram_slot_ = uint8_t(0x100 - (ram_.size() / 0x4000));
const uint8_t *read_pointers_[4] = {nullptr, nullptr, nullptr, nullptr};
@ -226,6 +302,11 @@ class ConcreteMachine:
return;
}
if(offset >= 16 && offset < 16 + basic_.size() / 0x4000) {
page<slot>(&basic_[(offset - 16) * 0x4000], nullptr);
return;
}
// Of whatever size of RAM I've declared above, use only the final portion.
// This correlated with Nick always having been handed the final 64kb and,
// at least while the RAM is the first thing declared above, does a little
@ -280,9 +361,6 @@ class ConcreteMachine:
}
// MARK: - Interrupts
// TODO: include an error.
enum class Interrupt: uint8_t {
Nick = 0x20
};

View File

@ -411,9 +411,51 @@ Description::Description(Name name) {
*this = Description(name, "DiskII", "the Disk II 13-sector state machine ROM", "state-machine-13.rom", 256, 0x62e22620u);
break;
case Name::EnterpriseEXOS: {
const std::initializer_list<std::string> filenames = {"exos.bin", "Exos (198x)(Enterprise).bin"};
*this = Description(name, "Enterprise", "the Enterprise EXOS ROM", filenames, 32 * 1024, 0x30b26387u);
case Name::EnterpriseEXOS10: {
const std::initializer_list<std::string> filenames = {"exos10.bin", "Exos (198x)(Enterprise).bin"};
*this = Description(name, "Enterprise", "the Enterprise EXOS ROM v1.0", filenames, 32 * 1024, 0x30b26387u);
} break;
case Name::EnterpriseEXOS20: {
const std::initializer_list<std::string> filenames = {"exos20.bin", "Expandible OS v2.0 (1984)(Intelligent Software).bin"};
*this = Description(name, "Enterprise", "the Enterprise EXOS ROM v2.0", filenames, 32 * 1024, 0xd421795fu);
} break;
case Name::EnterpriseEXOS21: {
const std::initializer_list<std::string> filenames = {"exos21.bin", "Expandible OS v2.1 (1985)(Intelligent Software).bin"};
*this = Description(name, "Enterprise", "the Enterprise EXOS ROM v2.1", filenames, 32 * 1024, 0x982a3b44u);
} break;
case Name::EnterpriseEXOS23: {
const std::initializer_list<std::string> filenames = {"exos23.bin", "Expandible OS v2.3 (1987)(Intelligent Software).bin"};
*this = Description(name, "Enterprise", "the Enterprise EXOS ROM v2.1", filenames, 64 * 1024, 0x24838410u);
} break;
case Name::EnterpriseBASIC10: {
const std::initializer_list<std::string> filenames = {"basic10.bin"};
*this = Description(name, "Enterprise", "the Enterprise BASIC ROM v1.0", filenames, 16 * 1024, 0xd62e4fb7u);
} break;
case Name::EnterpriseBASIC10Part1: {
const std::initializer_list<std::string> filenames = {"BASIC 1.0 - EPROM 1-2 (198x)(Enterprise).bin"};
*this = Description(name, "Enterprise", "the Enterprise BASIC ROM v1.0, Part 1", filenames, 8193, 0x37bf48e1u);
} break;
case Name::EnterpriseBASIC10Part2: {
const std::initializer_list<std::string> filenames = {"BASIC 1.0 - EPROM 2-2 (198x)(Enterprise).bin"};
*this = Description(name, "Enterprise", "the Enterprise BASIC ROM v1.0, Part 2", filenames, 8193, 0xc5298c79u);
} break;
case Name::EnterpriseBASIC11: {
const std::initializer_list<std::string> filenames = {"basic11.bin"};
*this = Description(name, "Enterprise", "the Enterprise BASIC ROM v1.1", filenames, 16 * 1024, 0x683cf455u);
} break;
case Name::EnterpriseBASIC11Suffixed: {
const std::initializer_list<std::string> filenames = {"BASIC 1.1 - EPROM 1.1 (198x)(Enterprise).bin"};
*this = Description(name, "Enterprise", "the Enterprise BASIC ROM v1.1, with trailing byte", filenames, 16385, 0xc96b7602u);
} break;
case Name::EnterpriseBASIC21: {
const std::initializer_list<std::string> filenames = {
"basic21.bin",
"BASIC Interpreter v2.1 (1985)(Intelligent Software).bin",
"BASIC Interpreter v2.1 (1985)(Intelligent Software)[a].bin"
};
const std::initializer_list<uint32_t> crcs = { 0x55f96251, 0x683cf455 };
*this = Description(name, "Enterprise", "the Enterprise BASIC ROM v2.1", filenames, 16 * 1024, crcs);
} break;
case Name::Macintosh128k: *this = Description(name, "Macintosh", "the Macintosh 128k ROM", "mac128k.rom", 64*1024, 0x6d0c8a28u); break;

View File

@ -72,7 +72,17 @@ enum Name {
DiskIIBoot13Sector,
// Enterprise.
EnterpriseEXOS,
EnterpriseEXOS10,
EnterpriseEXOS20,
EnterpriseEXOS21,
EnterpriseEXOS23,
EnterpriseBASIC10,
EnterpriseBASIC10Part1,
EnterpriseBASIC10Part2,
EnterpriseBASIC11,
EnterpriseBASIC11Suffixed,
EnterpriseBASIC21,
// Macintosh.
Macintosh128k,