1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-04-09 00:37:27 +00:00

Merge pull request #1207 from TomHarte/PhoneyPC

Start sketching out a PC compatible machine.
This commit is contained in:
Thomas Harte 2023-11-17 17:12:10 -05:00 committed by GitHub
commit 3843102609
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 730 additions and 136 deletions

View File

@ -1,6 +1,6 @@
name: SDL/Ubuntu
on: [push, pull_request]
on: [pull_request]
jobs:
build:
@ -10,7 +10,7 @@ jobs:
steps:
- uses: actions/checkout@v3
- name: Install dependencies
run: sudo apt-get --allow-releaseinfo-change update && sudo apt-get --fix-missing install libsdl2-dev scons
run: sudo apt-get --allow-releaseinfo-change update && sudo apt-get --fix-missing install gcc-10 libsdl2-dev scons
- name: Make
working-directory: OSBindings/SDL
run: scons -j$(nproc --all)

View File

@ -25,6 +25,7 @@ enum class Machine {
MasterSystem,
MSX,
Oric,
PCCompatible,
Vic20,
ZX8081,
ZXSpectrum,

View File

@ -15,7 +15,7 @@
using namespace InstructionSet::x86;
template <Model model>
std::pair<int, typename Decoder<model>::InstructionT> Decoder<model>::decode(const uint8_t *source, size_t length) {
std::pair<int, typename Decoder<model>::InstructionT> Decoder<model>::decode(const uint8_t *source, std::size_t length) {
// Instruction length limits:
//
// 8086/80186: none*
@ -26,8 +26,8 @@ std::pair<int, typename Decoder<model>::InstructionT> Decoder<model>::decode(con
// be back to wherever it started, so it's safe to spit out a NOP and reset parsing
// without any loss of context. This reduces the risk of the decoder tricking a caller into
// an infinite loop.
constexpr int max_instruction_length = model >= Model::i80386 ? 15 : (model == Model::i80286 ? 10 : 65536);
const uint8_t *const end = source + std::min(length, size_t(max_instruction_length - consumed_));
static constexpr std::size_t max_instruction_length = model >= Model::i80386 ? 15 : (model == Model::i80286 ? 10 : 65536);
const uint8_t *const end = source + std::min(length, max_instruction_length - consumed_);
// MARK: - Prefixes (if present) and the opcode.
@ -58,14 +58,16 @@ std::pair<int, typename Decoder<model>::InstructionT> Decoder<model>::decode(con
#define RegAddr(op, dest, op_size, addr_size) \
SetOpSrcDestSize(op, DirectAddress, dest, op_size); \
displacement_size_ = addr_size; \
phase_ = Phase::DisplacementOrOperand
phase_ = Phase::DisplacementOrOperand; \
sign_extend_displacement_ = false
/// Handles instructions of the form jjkk, Ax where the former is implicitly an address.
#define AddrReg(op, source, op_size, addr_size) \
SetOpSrcDestSize(op, source, DirectAddress, op_size); \
displacement_size_ = addr_size; \
destination_ = Source::DirectAddress; \
phase_ = Phase::DisplacementOrOperand
phase_ = Phase::DisplacementOrOperand; \
sign_extend_displacement_ = false
/// Covers both `mem/reg, reg` and `reg, mem/reg`.
#define MemRegReg(op, format, size) \
@ -1017,11 +1019,20 @@ std::pair<int, typename Decoder<model>::InstructionT> Decoder<model>::decode(con
if(bytes_to_consume == outstanding_bytes) {
phase_ = Phase::ReadyToPost;
switch(displacement_size_) {
case DataSize::None: displacement_ = 0; break;
case DataSize::Byte: displacement_ = int8_t(inward_data_); break;
case DataSize::Word: displacement_ = int16_t(inward_data_); break;
case DataSize::DWord: displacement_ = int32_t(inward_data_); break;
if(!sign_extend_displacement_) {
switch(displacement_size_) {
case DataSize::None: displacement_ = 0; break;
case DataSize::Byte: displacement_ = uint8_t(inward_data_); break;
case DataSize::Word: displacement_ = uint16_t(inward_data_); break;
case DataSize::DWord: displacement_ = int32_t(inward_data_); break;
}
} else {
switch(displacement_size_) {
case DataSize::None: displacement_ = 0; break;
case DataSize::Byte: displacement_ = int8_t(inward_data_); break;
case DataSize::Word: displacement_ = int16_t(inward_data_); break;
case DataSize::DWord: displacement_ = int32_t(inward_data_); break;
}
}
inward_data_ >>= bit_size(displacement_size_);
@ -1112,3 +1123,7 @@ template class InstructionSet::x86::Decoder<InstructionSet::x86::Model::i8086>;
template class InstructionSet::x86::Decoder<InstructionSet::x86::Model::i80186>;
template class InstructionSet::x86::Decoder<InstructionSet::x86::Model::i80286>;
template class InstructionSet::x86::Decoder<InstructionSet::x86::Model::i80386>;
std::pair<int, Instruction<false>> Decoder8086::decode(const uint8_t *source, std::size_t length) {
return decoder.decode(source, length);
}

View File

@ -38,13 +38,12 @@ template <Model model> class Decoder {
supplied cannot form a valid instruction.
@discussion although instructions also contain an indicator of their length, on chips prior
to the 80286 there is no limit to instruction length and that could in theory overflow the available
storage, which can describe instructions only up to 1kb in size.
to the 80286 there is no limit to potential instruction length.
The 80286 and 80386 have instruction length limits of 10 and 15 bytes respectively, so
cannot overflow the field.
*/
std::pair<int, InstructionT> decode(const uint8_t *source, size_t length);
std::pair<int, InstructionT> decode(const uint8_t *source, std::size_t length);
/*!
Enables or disables 32-bit protected mode. Meaningful only if the @c Model supports it.
@ -173,7 +172,7 @@ template <Model model> class Decoder {
// Ephemeral decoding state.
Operation operation_ = Operation::Invalid;
int consumed_ = 0, operand_bytes_ = 0;
uint32_t consumed_ = 0, operand_bytes_ = 0;
// Source and destination locations.
Source source_ = Source::None;
@ -193,6 +192,8 @@ template <Model model> class Decoder {
DataSize operand_size_ = DataSize::None; // i.e. size of in-stream operand, if any.
DataSize operation_size_ = DataSize::None; // i.e. size of data manipulated by the operation.
bool sign_extend_displacement_ = true; // If set then sign extend any displacement up to the address
// size; otherwise it'll be zero-padded.
bool sign_extend_operand_ = false; // If set then sign extend the operand up to the operation size;
// otherwise it'll be zero-padded.
@ -223,9 +224,23 @@ template <Model model> class Decoder {
next_inward_data_shift_ = 0;
inward_data_ = 0;
sign_extend_operand_ = false;
sign_extend_displacement_ = true;
}
};
// This is a temporary measure; for reasons as-yet unknown, GCC isn't picking up the
// explicit instantiations of the template above at link time, even though is is
// unambiguously building and linking in Decoder.cpp.
//
// So here's a thin non-templated shim to unblock initial PC Compatible development.
class Decoder8086 {
public:
std::pair<int, Instruction<false>> decode(const uint8_t *source, std::size_t length);
private:
Decoder<Model::i8086> decoder;
};
}
#endif /* InstructionSets_x86_Decoder_hpp */

View File

@ -82,8 +82,8 @@ class Flags {
using FlagT = uint32_t;
// Flag getters.
template <Flag flag> bool flag() const {
switch(flag) {
template <Flag flag_v> bool flag() const {
switch(flag_v) {
case Flag::Carry: return carry_;
case Flag::AuxiliaryCarry: return auxiliary_carry_;
case Flag::Sign: return sign_;
@ -163,7 +163,7 @@ class Flags {
set_from<Flag::Interrupt>(value & FlagValue::Interrupt);
set_from<Flag::Direction>(value & FlagValue::Direction);
set_from<uint8_t, Flag::Sign>(value);
set_from<uint8_t, Flag::Sign>(uint8_t(value));
set_from<Flag::Zero>((~value) & FlagValue::Zero);
set_from<Flag::ParityOdd>((~value) & FlagValue::Parity);

View File

@ -13,6 +13,8 @@
#include "Stack.hpp"
#include "../AccessType.hpp"
#include <type_traits>
namespace InstructionSet::x86::Primitive {
template <typename IntT, typename ContextT>
@ -34,7 +36,7 @@ void jump(
// TODO: proper behaviour in 32-bit.
if(condition) {
context.flow_controller.jump(context.registers.ip() + displacement);
context.flow_controller.jump(uint16_t(context.registers.ip() + displacement));
}
}
@ -76,7 +78,7 @@ void loopne(
template <typename IntT, typename ContextT>
void call_relative(
IntT offset,
typename std::make_signed<IntT>::type offset,
ContextT &context
) {
push<uint16_t, false>(context.registers.ip(), context);

View File

@ -175,8 +175,8 @@ template <
case Operation::ESC:
case Operation::NOP: return;
case Operation::AAM: Primitive::aam(context.registers.axp(), instruction.operand(), context); return;
case Operation::AAD: Primitive::aad(context.registers.axp(), instruction.operand(), context); return;
case Operation::AAM: Primitive::aam(context.registers.axp(), uint8_t(instruction.operand()), context); return;
case Operation::AAD: Primitive::aad(context.registers.axp(), uint8_t(instruction.operand()), context); return;
case Operation::AAA: Primitive::aaas<true>(context.registers.axp(), context); return;
case Operation::AAS: Primitive::aaas<false>(context.registers.axp(), context); return;
case Operation::DAA: Primitive::daas<true>(context.registers.al(), context); return;
@ -232,7 +232,9 @@ template <
case Operation::NEG: Primitive::neg<IntT>(source_rmw(), context); break; // TODO: should be a destination.
case Operation::NOT: Primitive::not_<IntT>(source_rmw()); break; // TODO: should be a destination.
case Operation::CALLrel: Primitive::call_relative<AddressT>(instruction.displacement(), context); return;
case Operation::CALLrel:
Primitive::call_relative<AddressT>(instruction.displacement(), context);
return;
case Operation::CALLabs: Primitive::call_absolute<IntT>(destination_r(), context); return;
case Operation::CALLfar: Primitive::call_far(instruction, context); return;

View File

@ -162,7 +162,7 @@ typename Accessor<IntT, access>::type resolve(
//
// * if this is a memory access, set target_address and break;
// * otherwise return the appropriate value.
uint32_t target_address;
uint32_t target_address = 0;
switch(source) {
// Defer all register accesses to the register-specific lookup.
case Source::eAX: return *register_<IntT, access, Source::eAX>(context);
@ -183,7 +183,7 @@ typename Accessor<IntT, access>::type resolve(
case Source::None: return *none;
case Source::Immediate:
*immediate = instruction.operand();
*immediate = IntT(instruction.operand());
return *immediate;
case Source::Indirect:

View File

@ -0,0 +1,438 @@
//
// PCCompatible.cpp
// Clock Signal
//
// Created by Thomas Harte on 15/11/2023.
// Copyright © 2023 Thomas Harte. All rights reserved.
//
#include "PCCompatible.hpp"
#include "../../InstructionSets/x86/Decoder.hpp"
#include "../../InstructionSets/x86/Flags.hpp"
#include "../../InstructionSets/x86/Instruction.hpp"
#include "../../InstructionSets/x86/Perform.hpp"
#include "../ScanProducer.hpp"
#include "../TimedMachine.hpp"
#include <array>
namespace PCCompatible {
struct Registers {
public:
static constexpr bool is_32bit = false;
uint8_t &al() { return ax_.halves.low; }
uint8_t &ah() { return ax_.halves.high; }
uint16_t &ax() { return ax_.full; }
CPU::RegisterPair16 &axp() { return ax_; }
uint8_t &cl() { return cx_.halves.low; }
uint8_t &ch() { return cx_.halves.high; }
uint16_t &cx() { return cx_.full; }
uint8_t &dl() { return dx_.halves.low; }
uint8_t &dh() { return dx_.halves.high; }
uint16_t &dx() { return dx_.full; }
uint8_t &bl() { return bx_.halves.low; }
uint8_t &bh() { return bx_.halves.high; }
uint16_t &bx() { return bx_.full; }
uint16_t &sp() { return sp_; }
uint16_t &bp() { return bp_; }
uint16_t &si() { return si_; }
uint16_t &di() { return di_; }
uint16_t &ip() { return ip_; }
uint16_t &es() { return es_; }
uint16_t &cs() { return cs_; }
uint16_t &ds() { return ds_; }
uint16_t &ss() { return ss_; }
uint16_t es() const { return es_; }
uint16_t cs() const { return cs_; }
uint16_t ds() const { return ds_; }
uint16_t ss() const { return ss_; }
void reset() {
cs_ = 0xffff;
ip_ = 0;
}
private:
CPU::RegisterPair16 ax_;
CPU::RegisterPair16 cx_;
CPU::RegisterPair16 dx_;
CPU::RegisterPair16 bx_;
uint16_t sp_;
uint16_t bp_;
uint16_t si_;
uint16_t di_;
uint16_t es_, cs_, ds_, ss_;
uint16_t ip_;
};
class Segments {
public:
Segments(const Registers &registers) : registers_(registers) {}
using Source = InstructionSet::x86::Source;
/// Posted by @c perform after any operation which *might* have affected a segment register.
void did_update(Source segment) {
switch(segment) {
default: break;
case Source::ES: es_base_ = uint32_t(registers_.es()) << 4; break;
case Source::CS: cs_base_ = uint32_t(registers_.cs()) << 4; break;
case Source::DS: ds_base_ = uint32_t(registers_.ds()) << 4; break;
case Source::SS: ss_base_ = uint32_t(registers_.ss()) << 4; break;
}
}
void reset() {
did_update(Source::ES);
did_update(Source::CS);
did_update(Source::DS);
did_update(Source::SS);
}
uint32_t es_base_, cs_base_, ds_base_, ss_base_;
bool operator ==(const Segments &rhs) const {
return
es_base_ == rhs.es_base_ &&
cs_base_ == rhs.cs_base_ &&
ds_base_ == rhs.ds_base_ &&
ss_base_ == rhs.ss_base_;
}
private:
const Registers &registers_;
};
// TODO: send writes to the ROM area off to nowhere.
struct Memory {
public:
using AccessType = InstructionSet::x86::AccessType;
// Constructor.
Memory(Registers &registers, const Segments &segments) : registers_(registers), segments_(segments) {}
//
// Preauthorisation call-ins. Since only an 8088 is currently modelled, all accesses are implicitly authorised.
//
void preauthorise_stack_write([[maybe_unused]] uint32_t length) {}
void preauthorise_stack_read([[maybe_unused]] uint32_t length) {}
void preauthorise_read([[maybe_unused]] InstructionSet::x86::Source segment, [[maybe_unused]] uint16_t start, [[maybe_unused]] uint32_t length) {}
void preauthorise_read([[maybe_unused]] uint32_t start, [[maybe_unused]] uint32_t length) {}
//
// Access call-ins.
//
// Accesses an address based on segment:offset.
template <typename IntT, AccessType type>
typename InstructionSet::x86::Accessor<IntT, type>::type access(InstructionSet::x86::Source segment, uint16_t offset) {
const uint32_t physical_address = address(segment, offset);
if constexpr (std::is_same_v<IntT, uint16_t>) {
// If this is a 16-bit access that runs past the end of the segment, it'll wrap back
// to the start. So the 16-bit value will need to be a local cache.
if(offset == 0xffff) {
return split_word<type>(physical_address, address(segment, 0));
}
}
return access<IntT, type>(physical_address);
}
// Accesses an address based on physical location.
template <typename IntT, AccessType type>
typename InstructionSet::x86::Accessor<IntT, type>::type access(uint32_t address) {
// Dispense with the single-byte case trivially.
if constexpr (std::is_same_v<IntT, uint8_t>) {
return memory[address];
} else if(address != 0xf'ffff) {
return *reinterpret_cast<IntT *>(&memory[address]);
} else {
return split_word<type>(address, 0);
}
}
template <typename IntT>
void write_back() {
if constexpr (std::is_same_v<IntT, uint16_t>) {
if(write_back_address_[0] != NoWriteBack) {
memory[write_back_address_[0]] = write_back_value_ & 0xff;
memory[write_back_address_[1]] = write_back_value_ >> 8;
write_back_address_[0] = 0;
}
}
}
//
// Direct write.
//
template <typename IntT>
void preauthorised_write(InstructionSet::x86::Source segment, uint16_t offset, IntT value) {
// Bytes can be written without further ado.
if constexpr (std::is_same_v<IntT, uint8_t>) {
memory[address(segment, offset) & 0xf'ffff] = value;
return;
}
// Words that straddle the segment end must be split in two.
if(offset == 0xffff) {
memory[address(segment, offset) & 0xf'ffff] = value & 0xff;
memory[address(segment, 0x0000) & 0xf'ffff] = value >> 8;
return;
}
const uint32_t target = address(segment, offset) & 0xf'ffff;
// Words that straddle the end of physical RAM must also be split in two.
if(target == 0xf'ffff) {
memory[0xf'ffff] = value & 0xff;
memory[0x0'0000] = value >> 8;
return;
}
// It's safe just to write then.
*reinterpret_cast<uint16_t *>(&memory[target]) = value;
}
//
// Helper for instruction fetch.
//
std::pair<const uint8_t *, size_t> next_code() {
const uint32_t start = segments_.cs_base_ + registers_.ip();
return std::make_pair(&memory[start], 0x10'000 - start);
}
std::pair<const uint8_t *, size_t> all() {
return std::make_pair(memory.data(), 0x10'000);
}
//
// Population.
//
void install(size_t address, const uint8_t *data, size_t length) {
std::copy(data, data + length, memory.begin() + std::vector<uint8_t>::difference_type(address));
}
private:
std::array<uint8_t, 1024*1024> memory{0xff};
Registers &registers_;
const Segments &segments_;
uint32_t segment_base(InstructionSet::x86::Source segment) {
using Source = InstructionSet::x86::Source;
switch(segment) {
default: return segments_.ds_base_;
case Source::ES: return segments_.es_base_;
case Source::CS: return segments_.cs_base_;
case Source::SS: return segments_.ss_base_;
}
}
uint32_t address(InstructionSet::x86::Source segment, uint16_t offset) {
return (segment_base(segment) + offset) & 0xf'ffff;
}
template <AccessType type>
typename InstructionSet::x86::Accessor<uint16_t, type>::type
split_word(uint32_t low_address, uint32_t high_address) {
if constexpr (is_writeable(type)) {
write_back_address_[0] = low_address;
write_back_address_[1] = high_address;
// Prepopulate only if this is a modify.
if constexpr (type == AccessType::ReadModifyWrite) {
write_back_value_ = uint16_t(memory[write_back_address_[0]] | (memory[write_back_address_[1]] << 8));
}
return write_back_value_;
} else {
return uint16_t(memory[low_address] | (memory[high_address] << 8));
}
}
static constexpr uint32_t NoWriteBack = 0; // A low byte address of 0 can't require write-back.
uint32_t write_back_address_[2] = {NoWriteBack, NoWriteBack};
uint16_t write_back_value_;
};
class IO {
public:
template <typename IntT> void out([[maybe_unused]] uint16_t port, [[maybe_unused]] IntT value) {
switch(port) {
default:
if constexpr (std::is_same_v<IntT, uint8_t>) {
printf("Unhandled out: %02x to %04x\n", value, port);
} else {
printf("Unhandled out: %04x to %04x\n", value, port);
}
break;
// On the XT the NMI can be masked by setting bit 7 on I/O port 0xA0.
case 0x00a0:
printf("TODO: NMIs %s\n", (value & 0x80) ? "masked" : "unmasked");
break;
}
}
template <typename IntT> IntT in([[maybe_unused]] uint16_t port) {
printf("Unhandled in: %04x\n", port);
return IntT(~0);
}
private:
};
class FlowController {
public:
FlowController(Registers &registers, Segments &segments) :
registers_(registers), segments_(segments) {}
// Requirements for perform.
void jump(uint16_t address) {
registers_.ip() = address;
}
void jump(uint16_t segment, uint16_t address) {
registers_.cs() = segment;
segments_.did_update(Segments::Source::CS);
registers_.ip() = address;
}
void halt() {}
void wait() {}
void repeat_last() {
should_repeat_ = true;
}
// Other actions.
void begin_instruction() {
should_repeat_ = false;
}
bool should_repeat() const {
return should_repeat_;
}
private:
Registers &registers_;
Segments &segments_;
bool should_repeat_ = false;
};
class ConcreteMachine:
public Machine,
public MachineTypes::TimedMachine,
public MachineTypes::ScanProducer
{
public:
ConcreteMachine(
[[maybe_unused]] const Analyser::Static::Target &target,
[[maybe_unused]] const ROMMachine::ROMFetcher &rom_fetcher
) {
// This is actually a MIPS count; try 3 million.
set_clock_rate(3'000'000);
// Fetch the BIOS. [8088 only, for now]
const auto bios = ROM::Name::PCCompatibleGLaBIOS;
ROM::Request request = ROM::Request(bios);
auto roms = rom_fetcher(request);
if(!request.validate(roms)) {
throw ROMMachine::Error::MissingROMs;
}
const auto &bios_contents = roms.find(bios)->second;
context.memory.install(0x10'0000 - bios_contents.size(), bios_contents.data(), bios_contents.size());
}
// MARK: - TimedMachine.
void run_for([[maybe_unused]] const Cycles cycles) override {
auto instructions = cycles.as_integral();
while(instructions--) {
// Get the next thing to execute into decoded.
if(!context.flow_controller.should_repeat()) {
// Decode from the current IP.
const auto remainder = context.memory.next_code();
decoded = decoder.decode(remainder.first, remainder.second);
// If that didn't yield a whole instruction then the end of memory must have been hit;
// continue from the beginning.
if(decoded.first <= 0) {
const auto all = context.memory.all();
decoded = decoder.decode(all.first, all.second);
}
context.registers.ip() += decoded.first;
} else {
context.flow_controller.begin_instruction();
}
// Execute it.
InstructionSet::x86::perform(
decoded.second,
context
);
}
}
// MARK: - ScanProducer.
void set_scan_target([[maybe_unused]] Outputs::Display::ScanTarget *scan_target) override {}
Outputs::Display::ScanStatus get_scaled_scan_status() const override {
return Outputs::Display::ScanStatus();
}
private:
struct Context {
Context() :
segments(registers),
memory(registers, segments),
flow_controller(registers, segments)
{
reset();
}
void reset() {
registers.reset();
segments.reset();
}
InstructionSet::x86::Flags flags;
Registers registers;
Segments segments;
Memory memory;
FlowController flow_controller;
IO io;
static constexpr auto model = InstructionSet::x86::Model::i8086;
} context;
// TODO: eliminate use of Decoder8086 and Decoder8086 in gneral in favour of the templated version, as soon
// as whatever error is preventing GCC from picking up Decoder's explicit instantiations becomes apparent.
InstructionSet::x86::Decoder8086 decoder;
// InstructionSet::x86::Decoder<InstructionSet::x86::Model::i8086> decoder;
std::pair<int, InstructionSet::x86::Instruction<false>> decoded;
};
}
using namespace PCCompatible;
// See header; constructs and returns an instance of the Amstrad CPC.
Machine *Machine::PCCompatible(const Analyser::Static::Target *target, const ROMMachine::ROMFetcher &rom_fetcher) {
return new PCCompatible::ConcreteMachine(*target, rom_fetcher);
}
Machine::~Machine() {}

View File

@ -0,0 +1,33 @@
//
// PCCompatible.hpp
// Clock Signal
//
// Created by Thomas Harte on 15/11/2023.
// Copyright © 2023 Thomas Harte. All rights reserved.
//
#ifndef PCCompatible_hpp
#define PCCompatible_hpp
#include "../../Analyser/Static/StaticAnalyser.hpp"
#include "../ROMMachine.hpp"
namespace PCCompatible {
/*!
Models a PC compatible.
*/
class Machine {
public:
virtual ~Machine();
/// Creates and returns a PC Compatible.
static Machine *PCCompatible(
const Analyser::Static::Target *target,
const ROMMachine::ROMFetcher &rom_fetcher
);
};
}
#endif /* PCCompatible_hpp */

View File

@ -13,7 +13,6 @@
#include "../ClockReceiver/TimeTypes.hpp"
#include "AudioProducer.hpp"
#include "ScanProducer.hpp"
#include <cmath>

View File

@ -25,6 +25,7 @@
#include "../MasterSystem/MasterSystem.hpp"
#include "../MSX/MSX.hpp"
#include "../Oric/Oric.hpp"
#include "../PCCompatible/PCCompatible.hpp"
#include "../Sinclair/ZX8081/ZX8081.hpp"
#include "../Sinclair/ZXSpectrum/ZXSpectrum.hpp"
@ -69,6 +70,7 @@ Machine::DynamicMachine *Machine::MachineForTarget(const Analyser::Static::Targe
Bind(Enterprise)
Bind(MSX)
Bind(Oric)
Bind(PCCompatible)
BindD(Sega::MasterSystem, MasterSystem)
BindD(Sinclair::ZX8081, ZX8081)
BindD(Sinclair::ZXSpectrum, ZXSpectrum)
@ -139,6 +141,7 @@ std::string Machine::ShortNameForTargetMachine(const Analyser::Machine machine)
case Analyser::Machine::MasterSystem: return "MasterSystem";
case Analyser::Machine::MSX: return "MSX";
case Analyser::Machine::Oric: return "Oric";
case Analyser::Machine::PCCompatible: return "PCCompatible";
case Analyser::Machine::Vic20: return "Vic20";
case Analyser::Machine::ZX8081: return "ZX8081";
case Analyser::Machine::ZXSpectrum: return "ZXSpectrum";
@ -162,6 +165,7 @@ std::string Machine::LongNameForTargetMachine(Analyser::Machine machine) {
case Analyser::Machine::MasterSystem: return "Sega Master System";
case Analyser::Machine::MSX: return "MSX";
case Analyser::Machine::Oric: return "Oric";
case Analyser::Machine::PCCompatible: return "PC Compatible";
case Analyser::Machine::Vic20: return "Vic 20";
case Analyser::Machine::ZX8081: return "ZX80/81";
case Analyser::Machine::ZXSpectrum: return "ZX Spectrum";
@ -244,6 +248,7 @@ std::map<std::string, std::unique_ptr<Analyser::Static::Target>> Machine::Target
Add(Macintosh);
Add(MSX);
Add(Oric);
options.emplace(std::make_pair(LongNameForTargetMachine(Analyser::Machine::PCCompatible), new Analyser::Static::Target(Analyser::Machine::PCCompatible)));
AddMapped(Vic20, Commodore);
Add(ZX8081);
Add(ZXSpectrum);

View File

@ -567,6 +567,8 @@ Description::Description(Name name) {
case Name::OricMicrodisc: *this = Description(name, "Oric", "the Oric Microdisc ROM", "microdisc.rom", 8*1024, 0xa9664a9cu); break;
case Name::Oric8DOSBoot: *this = Description(name, "Oric", "the 8DOS boot ROM", "8dos.rom", 512, 0x49a74c06u); break;
case Name::PCCompatibleGLaBIOS: *this = Description(name, "PCCompatible", "8088 GLaBIOS 0.2.5", "GLABIOS_0.2.5_8T.ROM", 8 * 1024, 0x9576944cu); break;
// TODO: CRCs below are incomplete, at best.
case Name::MSXGenericBIOS: *this = Description(name, "MSX", "a generix MSX BIOS", "msx.rom", 32*1024, 0x94ee12f3u); break;
case Name::MSXJapaneseBIOS: *this = Description(name, "MSX", "a Japanese MSX BIOS", "msx-japanese.rom", 32*1024, 0xee229390u); break;

View File

@ -132,6 +132,9 @@ enum Name {
OricMicrodisc,
Oric8DOSBoot,
// PCCompatible.
PCCompatibleGLaBIOS,
// Sinclair QL.
SinclairQLJS,

View File

@ -9,6 +9,8 @@
/* Begin PBXBuildFile section */
423BDC4A2AB24699008E37B6 /* 8088Tests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 423BDC492AB24699008E37B6 /* 8088Tests.mm */; };
42437B332AC70833006DFED1 /* HDV.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B6FD0342923061300EC4760 /* HDV.cpp */; };
425739382B051EA800B7D1E4 /* PCCompatible.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 425739372B051EA800B7D1E4 /* PCCompatible.cpp */; };
425739392B051EA800B7D1E4 /* PCCompatible.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 425739372B051EA800B7D1E4 /* PCCompatible.cpp */; };
4281683A2A37AFB4008ECD27 /* DispatcherTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 428168392A37AFB4008ECD27 /* DispatcherTests.mm */; };
42A5E80C2ABBE04600A0DD5D /* NeskellTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42A5E80B2ABBE04600A0DD5D /* NeskellTests.swift */; };
42A5E8442ABBE16F00A0DD5D /* illegal_rmw_test.bin in Resources */ = {isa = PBXBuildFile; fileRef = 42A5E8332ABBE16F00A0DD5D /* illegal_rmw_test.bin */; };
@ -1138,6 +1140,8 @@
4257392E2AFBE2BC00B7D1E4 /* Repetition.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Repetition.hpp; sourceTree = "<group>"; };
4257392F2AFBE36B00B7D1E4 /* LoadStore.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = LoadStore.hpp; sourceTree = "<group>"; };
425739302AFBE47700B7D1E4 /* InOut.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = InOut.hpp; sourceTree = "<group>"; };
425739362B051EA800B7D1E4 /* PCCompatible.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = PCCompatible.hpp; sourceTree = "<group>"; };
425739372B051EA800B7D1E4 /* PCCompatible.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PCCompatible.cpp; sourceTree = "<group>"; };
4281572E2AA0334300E16AA1 /* Carry.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Carry.hpp; sourceTree = "<group>"; };
428168372A16C25C008ECD27 /* LineLayout.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = LineLayout.hpp; sourceTree = "<group>"; };
428168392A37AFB4008ECD27 /* DispatcherTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DispatcherTests.mm; sourceTree = "<group>"; };
@ -2353,6 +2357,15 @@
path = Implementation;
sourceTree = "<group>";
};
425739352B051EA800B7D1E4 /* PCCompatible */ = {
isa = PBXGroup;
children = (
425739362B051EA800B7D1E4 /* PCCompatible.hpp */,
425739372B051EA800B7D1E4 /* PCCompatible.cpp */,
);
path = PCCompatible;
sourceTree = "<group>";
};
42A5E8322ABBE16F00A0DD5D /* Neskell Tests */ = {
isa = PBXGroup;
children = (
@ -4475,6 +4488,7 @@
4B7F188B2154825D00388727 /* MasterSystem */,
4B79A4FC1FC8FF9800EEDAD5 /* MSX */,
4BCF1FA51DADC3E10039D2E7 /* Oric */,
425739352B051EA800B7D1E4 /* PCCompatible */,
4B0F1BC92602F17B00B85C66 /* Sinclair */,
4B2B3A461F9B8FA70062DABF /* Utility */,
);
@ -5733,6 +5747,7 @@
4BD424E62193B5830097291A /* Shader.cpp in Sources */,
4BC080CB26A238CC00D03FD8 /* AmigaADF.cpp in Sources */,
4B4B1A3D200198CA00A0F866 /* KonamiSCC.cpp in Sources */,
425739392B051EA800B7D1E4 /* PCCompatible.cpp in Sources */,
4B055AC31FAE9AE80060FFFF /* AmstradCPC.cpp in Sources */,
4B055A9E1FAE85DA0060FFFF /* G64.cpp in Sources */,
4B055AB81FAE860F0060FFFF /* ZX80O81P.cpp in Sources */,
@ -5951,6 +5966,7 @@
4B643F3F1D77B88000D431D6 /* DocumentController.swift in Sources */,
4BDA00E422E663B900AC3CD0 /* NSData+CRC32.m in Sources */,
4B9EC0E626AA4A660060A31F /* Chipset.cpp in Sources */,
425739382B051EA800B7D1E4 /* PCCompatible.cpp in Sources */,
4BB8616E24E22DC500A00E03 /* BufferingScanTarget.cpp in Sources */,
4BB4BFB022A42F290069048D /* MacintoshIMG.cpp in Sources */,
4B05401E219D1618001BF69C /* ScanTarget.cpp in Sources */,

View File

@ -123,6 +123,10 @@ typedef NS_ENUM(NSInteger, CSMachineMSXRegion) {
CSMachineMSXRegionJapanese,
};
typedef NS_ENUM(NSInteger, CSPCCompatibleModel) {
CSPCCompatibleModelTurboXT,
};
typedef int Kilobytes;
@interface CSStaticAnalyser : NSObject
@ -143,6 +147,7 @@ typedef int Kilobytes;
- (instancetype)initWithVic20Region:(CSMachineVic20Region)region memorySize:(Kilobytes)memorySize hasC1540:(BOOL)hasC1540;
- (instancetype)initWithZX80MemorySize:(Kilobytes)memorySize useZX81ROM:(BOOL)useZX81ROM;
- (instancetype)initWithZX81MemorySize:(Kilobytes)memorySize;
- (instancetype)initWithPCCompatibleModel:(CSPCCompatibleModel)model;
@property(nonatomic, readonly, nullable) NSString *optionsNibName;
@property(nonatomic, readonly) NSString *displayName;

View File

@ -272,6 +272,16 @@
return self;
}
- (instancetype)initWithPCCompatibleModel:(CSPCCompatibleModel)model {
self = [super init];
if(self) {
using Target = Analyser::Static::Target;
auto target = std::make_unique<Target>(Analyser::Machine::PCCompatible);
_targets.push_back(std::move(target));
}
return self;
}
- (instancetype)initWithSpectrumModel:(CSMachineSpectrumModel)model {
self = [super init];
if(self) {

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="21701" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="22155" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="21701"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="22155"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
@ -17,10 +17,10 @@
<window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="default" titleVisibility="hidden" id="QvC-M9-y7g">
<windowStyleMask key="styleMask" titled="YES" documentModal="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="196" y="240" width="590" height="353"/>
<rect key="screenRect" x="0.0" y="0.0" width="1800" height="1131"/>
<rect key="contentRect" x="196" y="240" width="590" height="367"/>
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1440"/>
<view key="contentView" wantsLayer="YES" id="EiT-Mj-1SZ">
<rect key="frame" x="0.0" y="0.0" width="590" height="353"/>
<rect key="frame" x="0.0" y="0.0" width="590" height="367"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="hKn-1l-OSN">
@ -49,7 +49,7 @@ Gw
<action selector="cancelCreateMachine:" target="-2" id="lf8-PM-c0m"/>
</connections>
</button>
<textField horizontalHuggingPriority="1" verticalHuggingPriority="1" horizontalCompressionResistancePriority="250" setsMaxLayoutWidthAtFirstLayout="YES" translatesAutoresizingMaskIntoConstraints="NO" id="9YM-5x-pc0">
<textField focusRingType="none" horizontalHuggingPriority="1" verticalHuggingPriority="1" horizontalCompressionResistancePriority="250" setsMaxLayoutWidthAtFirstLayout="YES" translatesAutoresizingMaskIntoConstraints="NO" id="9YM-5x-pc0">
<rect key="frame" x="18" y="14" width="405" height="32"/>
<textFieldCell key="cell" allowsUndo="NO" sendsActionOnEndEditing="YES" id="xTm-Oy-oz5">
<font key="font" metaFont="system"/>
@ -59,16 +59,16 @@ Gw
</textFieldCell>
</textField>
<tabView type="noTabsBezelBorder" translatesAutoresizingMaskIntoConstraints="NO" id="VUb-QG-x7c">
<rect key="frame" x="154" y="57" width="420" height="242"/>
<rect key="frame" x="154" y="57" width="420" height="256"/>
<font key="font" metaFont="system"/>
<tabViewItems>
<tabViewItem label="Amiga" identifier="amiga" id="JmB-OF-xcM">
<view key="view" id="5zS-Nj-Ynx">
<rect key="frame" x="10" y="7" width="400" height="222"/>
<rect key="frame" x="10" y="7" width="400" height="236"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="qfH-1l-GXp">
<rect key="frame" x="110" y="178" width="80" height="25"/>
<rect key="frame" x="110" y="192" width="80" height="25"/>
<popUpButtonCell key="cell" type="push" title="512 kb" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" tag="512" imageScaling="axesIndependently" inset="2" selectedItem="Zev-ku-jDG" id="vdO-VR-mUx">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
@ -81,16 +81,16 @@ Gw
</menu>
</popUpButtonCell>
</popUpButton>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="P6K-dt-stj">
<rect key="frame" x="18" y="184" width="89" height="16"/>
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="P6K-dt-stj">
<rect key="frame" x="18" y="198" width="89" height="16"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Chip Memory:" id="FIO-ZR-rsA">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="YD0-OJ-2bY">
<rect key="frame" x="18" y="154" width="87" height="16"/>
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="YD0-OJ-2bY">
<rect key="frame" x="18" y="168" width="87" height="16"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Fast Memory:" id="Rpz-39-jyt">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
@ -98,7 +98,7 @@ Gw
</textFieldCell>
</textField>
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="af8-pF-qc9">
<rect key="frame" x="108" y="148" width="72" height="25"/>
<rect key="frame" x="108" y="162" width="72" height="25"/>
<popUpButtonCell key="cell" type="push" title="None" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="axesIndependently" inset="2" selectedItem="zV7-V8-c7s" id="39D-ms-pf9">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
@ -148,7 +148,7 @@ Gw
</menu>
</popUpButtonCell>
</popUpButton>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="c3g-96-b3x">
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="c3g-96-b3x">
<rect key="frame" x="18" y="184" width="46" height="16"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Model:" id="53v-92-jmf">
<font key="font" metaFont="system"/>
@ -172,7 +172,7 @@ Gw
<rect key="frame" x="10" y="7" width="400" height="222"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="V5Z-dX-Ns4">
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="V5Z-dX-Ns4">
<rect key="frame" x="18" y="184" width="46" height="16"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Model:" id="qV3-2P-3JW">
<font key="font" metaFont="system"/>
@ -180,7 +180,7 @@ Gw
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="WnO-ef-IC6">
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="WnO-ef-IC6">
<rect key="frame" x="18" y="154" width="96" height="16"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Disk controller:" id="kbf-rc-Y4M">
<font key="font" metaFont="system"/>
@ -235,19 +235,19 @@ Gw
</tabViewItem>
<tabViewItem label="Apple IIgs" identifier="appleiigs" id="u5E-8n-ghF">
<view key="view" id="jOM-9f-vkk">
<rect key="frame" x="10" y="7" width="400" height="223"/>
<rect key="frame" x="10" y="7" width="400" height="222"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="0d9-IG-gKU">
<rect key="frame" x="18" y="185" width="46" height="16"/>
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="0d9-IG-gKU">
<rect key="frame" x="18" y="184" width="46" height="16"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Model:" id="kiv-1P-FWc">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="LES-76-Ovz">
<rect key="frame" x="18" y="155" width="85" height="16"/>
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="LES-76-Ovz">
<rect key="frame" x="18" y="154" width="85" height="16"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Memory size:" id="OLJ-nC-yyj">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
@ -255,7 +255,7 @@ Gw
</textFieldCell>
</textField>
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="gcS-uy-mzl">
<rect key="frame" x="67" y="179" width="89" height="25"/>
<rect key="frame" x="67" y="178" width="89" height="25"/>
<popUpButtonCell key="cell" type="push" title="ROM 03" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" tag="2" imageScaling="axesIndependently" inset="2" selectedItem="0TS-DO-O9h" id="hjw-g8-e2f">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
@ -269,7 +269,7 @@ Gw
</popUpButtonCell>
</popUpButton>
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="nQa-YS-utT">
<rect key="frame" x="106" y="149" width="82" height="25"/>
<rect key="frame" x="106" y="148" width="82" height="25"/>
<popUpButtonCell key="cell" type="push" title="8 mb" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" tag="8192" imageScaling="axesIndependently" inset="2" selectedItem="UHg-gU-Xnn" id="dl3-cq-uWO">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
@ -303,7 +303,7 @@ Gw
<rect key="frame" x="10" y="7" width="400" height="222"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="dKg-qC-BBF">
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="dKg-qC-BBF">
<rect key="frame" x="18" y="184" width="58" height="16"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Memory:" id="ZBF-0r-RNK">
<font key="font" metaFont="system"/>
@ -338,32 +338,32 @@ Gw
</tabViewItem>
<tabViewItem label="Electron" identifier="electron" id="muc-z9-Vqc">
<view key="view" id="SRc-2D-95G">
<rect key="frame" x="10" y="7" width="400" height="223"/>
<rect key="frame" x="10" y="7" width="400" height="222"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="JqM-IK-FMP">
<rect key="frame" x="18" y="186" width="168" height="18"/>
<rect key="frame" x="18" y="185" width="168" height="18"/>
<buttonCell key="cell" type="check" title="With Disk Filing System" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="tpW-5C-xKp">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="945-wU-JOH">
<rect key="frame" x="18" y="164" width="232" height="18"/>
<rect key="frame" x="18" y="163" width="232" height="18"/>
<buttonCell key="cell" type="check" title="With Advanced Disk Filing System" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="S0c-Jg-7Pu">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="cG2-Ph-S3Z">
<rect key="frame" x="18" y="142" width="231" height="18"/>
<rect key="frame" x="18" y="141" width="231" height="18"/>
<buttonCell key="cell" type="check" title="With Advanced Plus 6 Utility ROM" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="yjF-XS-zx6">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="lzo-8g-o4S">
<rect key="frame" x="18" y="120" width="284" height="18"/>
<rect key="frame" x="18" y="119" width="284" height="18"/>
<buttonCell key="cell" type="check" title="Fill unused ROM banks with sideways RAM" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="JEz-eK-uWp">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
@ -389,11 +389,11 @@ Gw
</tabViewItem>
<tabViewItem label="Enterprise" identifier="enterprise" id="zhO-EO-wUe">
<view key="view" id="1cs-PX-RAH">
<rect key="frame" x="10" y="7" width="400" height="223"/>
<rect key="frame" x="10" y="7" width="400" height="222"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="PhH-bu-pb5">
<rect key="frame" x="80" y="179" width="129" height="25"/>
<rect key="frame" x="80" y="178" width="129" height="25"/>
<popUpButtonCell key="cell" type="push" title="Enterprise 128" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" tag="128" imageScaling="axesIndependently" inset="2" selectedItem="roH-nL-f8o" id="z9O-XC-XBv">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
@ -407,7 +407,7 @@ Gw
</popUpButtonCell>
</popUpButton>
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Lfl-5c-b8j">
<rect key="frame" x="67" y="149" width="77" height="25"/>
<rect key="frame" x="67" y="148" width="77" height="25"/>
<popUpButtonCell key="cell" type="push" title="4 Mhz" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" tag="4" imageScaling="axesIndependently" inset="2" selectedItem="5N6-tD-uN7" id="BU2-NJ-Kii">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
@ -420,7 +420,7 @@ Gw
</popUpButtonCell>
</popUpButton>
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="nen-Za-7zH">
<rect key="frame" x="64" y="119" width="107" height="25"/>
<rect key="frame" x="64" y="118" width="107" height="25"/>
<popUpButtonCell key="cell" type="push" title="Version 2.1" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" tag="21" imageScaling="axesIndependently" inset="2" selectedItem="Qja-xZ-wVM" id="xGG-ri-8Sb">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
@ -434,7 +434,7 @@ Gw
</popUpButtonCell>
</popUpButton>
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="hIr-GH-7xi">
<rect key="frame" x="67" y="89" width="105" height="25"/>
<rect key="frame" x="67" y="88" width="105" height="25"/>
<popUpButtonCell key="cell" type="push" title="Version 2.1" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" tag="21" imageScaling="axesIndependently" inset="2" selectedItem="TME-cv-Jh1" id="9mQ-GW-lq9">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
@ -449,7 +449,7 @@ Gw
</popUpButtonCell>
</popUpButton>
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="syE-e7-TjU">
<rect key="frame" x="57" y="59" width="83" height="25"/>
<rect key="frame" x="57" y="58" width="83" height="25"/>
<popUpButtonCell key="cell" type="push" title="EXDOS" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" tag="1" imageScaling="axesIndependently" inset="2" selectedItem="8rP-2w-PdU" id="NvO-Zm-2Rq">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
@ -461,40 +461,40 @@ Gw
</menu>
</popUpButtonCell>
</popUpButton>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="ykc-W1-YaS">
<rect key="frame" x="18" y="125" width="43" height="16"/>
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="ykc-W1-YaS">
<rect key="frame" x="18" y="124" width="43" height="16"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="EXOS:" id="gUC-PN-zVL">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="frx-nk-c3P">
<rect key="frame" x="18" y="185" width="59" height="16"/>
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="frx-nk-c3P">
<rect key="frame" x="18" y="184" width="59" height="16"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Machine:" id="uTv-hH-mIC">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="dzd-tH-BjX">
<rect key="frame" x="18" y="95" width="46" height="16"/>
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="dzd-tH-BjX">
<rect key="frame" x="18" y="94" width="46" height="16"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="BASIC:" id="ai1-oR-X6Y">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="pxr-Bq-yh0">
<rect key="frame" x="18" y="65" width="36" height="16"/>
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="pxr-Bq-yh0">
<rect key="frame" x="18" y="64" width="36" height="16"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="DOS:" id="NFk-cp-DfS">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="rHr-bh-QMV">
<rect key="frame" x="17" y="155" width="47" height="16"/>
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="rHr-bh-QMV">
<rect key="frame" x="17" y="154" width="47" height="16"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Speed:" id="sAw-C9-Sf7">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
@ -536,11 +536,11 @@ Gw
</tabViewItem>
<tabViewItem label="Macintosh" identifier="mac" id="lmR-z3-xSm">
<view key="view" id="7Yf-vi-Q0W">
<rect key="frame" x="10" y="7" width="400" height="223"/>
<rect key="frame" x="10" y="7" width="400" height="222"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="ZOY-4E-Cfl">
<rect key="frame" x="18" y="185" width="46" height="16"/>
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="ZOY-4E-Cfl">
<rect key="frame" x="18" y="184" width="46" height="16"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Model:" id="h9r-i6-66j">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
@ -548,7 +548,7 @@ Gw
</textFieldCell>
</textField>
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="xa6-NA-JY5">
<rect key="frame" x="67" y="179" width="75" height="25"/>
<rect key="frame" x="67" y="178" width="75" height="25"/>
<popUpButtonCell key="cell" type="push" title="Plus" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" tag="3" imageScaling="axesIndependently" inset="2" selectedItem="R6T-hg-rOF" id="1Kb-Q2-BGM">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
@ -599,7 +599,7 @@ Gw
</menu>
</popUpButtonCell>
</popUpButton>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="ZaD-7v-rMS">
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="ZaD-7v-rMS">
<rect key="frame" x="18" y="154" width="50" height="16"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Region:" id="x4m-eh-Nif">
<font key="font" metaFont="system"/>
@ -607,7 +607,7 @@ Gw
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="gFV-RB-7dB">
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="gFV-RB-7dB">
<rect key="frame" x="18" y="184" width="46" height="16"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Model:" id="r7C-zE-gyj">
<font key="font" metaFont="system"/>
@ -659,11 +659,11 @@ Gw
</tabViewItem>
<tabViewItem label="Oric" identifier="oric" id="NSx-DC-p4M">
<view key="view" id="sOR-e0-8iZ">
<rect key="frame" x="10" y="7" width="400" height="223"/>
<rect key="frame" x="10" y="7" width="400" height="222"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="0ct-tf-uRH">
<rect key="frame" x="18" y="185" width="46" height="16"/>
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="0ct-tf-uRH">
<rect key="frame" x="18" y="184" width="46" height="16"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Model:" id="Xm1-7x-YVl">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
@ -671,7 +671,7 @@ Gw
</textFieldCell>
</textField>
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="ENP-hI-BVZ">
<rect key="frame" x="67" y="179" width="107" height="25"/>
<rect key="frame" x="67" y="178" width="107" height="25"/>
<popUpButtonCell key="cell" type="push" title="Oric-1" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="axesIndependently" inset="2" selectedItem="jGN-1a-biF" id="Jll-EJ-cMr">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
@ -685,7 +685,7 @@ Gw
</popUpButtonCell>
</popUpButton>
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="fYL-p6-wyn">
<rect key="frame" x="113" y="149" width="130" height="25"/>
<rect key="frame" x="113" y="148" width="130" height="25"/>
<popUpButtonCell key="cell" type="push" title="None" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="axesIndependently" inset="2" selectedItem="XhK-Jh-oTW" id="aYb-m1-H9X">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
@ -700,8 +700,8 @@ Gw
</menu>
</popUpButtonCell>
</popUpButton>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="okM-ZI-NbF">
<rect key="frame" x="18" y="155" width="92" height="16"/>
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="okM-ZI-NbF">
<rect key="frame" x="18" y="154" width="92" height="16"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Disk interface:" id="SFK-hS-tFC">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
@ -724,6 +724,44 @@ Gw
</constraints>
</view>
</tabViewItem>
<tabViewItem label="PC Compatible" identifier="pc" id="8cB-MZ-g3U">
<view key="view" id="gJD-vd-WWu">
<rect key="frame" x="10" y="7" width="400" height="236"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="stw-i3-ikG">
<rect key="frame" x="108" y="192" width="116" height="25"/>
<popUpButtonCell key="cell" type="push" title="Unexpanded" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="axesIndependently" inset="2" selectedItem="oIy-If-5bQ" id="xz8-mu-ynU">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
<menu key="menu" id="dju-ZY-2DH">
<items>
<menuItem title="Unexpanded" state="on" id="oIy-If-5bQ"/>
<menuItem title="16 kb" tag="16" id="igW-oa-8YI"/>
<menuItem title="64 kb" tag="64" hidden="YES" enabled="NO" id="Tcz-UB-hbn"/>
</items>
</menu>
</popUpButtonCell>
</popUpButton>
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="uhf-1k-ibT">
<rect key="frame" x="18" y="198" width="87" height="16"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Memory Size:" id="ROV-EU-T3W">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
<constraints>
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="stw-i3-ikG" secondAttribute="trailing" constant="20" symbolic="YES" id="A0n-lr-LHf"/>
<constraint firstItem="uhf-1k-ibT" firstAttribute="leading" secondItem="gJD-vd-WWu" secondAttribute="leading" constant="20" symbolic="YES" id="JNr-Tg-gDV"/>
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="stw-i3-ikG" secondAttribute="bottom" constant="20" symbolic="YES" id="RSc-OQ-KNO"/>
<constraint firstItem="uhf-1k-ibT" firstAttribute="centerY" secondItem="stw-i3-ikG" secondAttribute="centerY" id="bfD-kx-eOc"/>
<constraint firstItem="stw-i3-ikG" firstAttribute="leading" secondItem="uhf-1k-ibT" secondAttribute="trailing" constant="8" symbolic="YES" id="f6l-B2-nBw"/>
<constraint firstItem="stw-i3-ikG" firstAttribute="top" secondItem="gJD-vd-WWu" secondAttribute="top" constant="20" symbolic="YES" id="wjD-TM-5CL"/>
</constraints>
</view>
</tabViewItem>
<tabViewItem label="Vic-20" identifier="vic20" id="cyO-PU-hSU">
<view key="view" id="fLI-XB-QCr">
<rect key="frame" x="10" y="7" width="400" height="222"/>
@ -759,7 +797,7 @@ Gw
</menu>
</popUpButtonCell>
</popUpButton>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="MTh-9p-FqC">
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="MTh-9p-FqC">
<rect key="frame" x="18" y="184" width="50" height="16"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Region:" id="F3g-Ya-ypU">
<font key="font" metaFont="system"/>
@ -767,7 +805,7 @@ Gw
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="gRS-DK-rIy">
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="gRS-DK-rIy">
<rect key="frame" x="18" y="154" width="87" height="16"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Memory Size:" id="a4I-vG-yCp">
<font key="font" metaFont="system"/>
@ -803,11 +841,11 @@ Gw
</tabViewItem>
<tabViewItem label="ZX80" identifier="zx80" id="tMH-kF-GUz">
<view key="view" id="8hL-Vn-Hg0">
<rect key="frame" x="10" y="7" width="400" height="223"/>
<rect key="frame" x="10" y="7" width="400" height="222"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="I1a-Eu-5UB">
<rect key="frame" x="108" y="179" width="116" height="25"/>
<rect key="frame" x="108" y="178" width="116" height="25"/>
<popUpButtonCell key="cell" type="push" title="Unexpanded" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="axesIndependently" inset="2" selectedItem="4Sa-jR-xOd" id="B8M-do-Yod">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
@ -820,8 +858,8 @@ Gw
</menu>
</popUpButtonCell>
</popUpButton>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="NCX-4e-lSu">
<rect key="frame" x="18" y="185" width="87" height="16"/>
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="NCX-4e-lSu">
<rect key="frame" x="18" y="184" width="87" height="16"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Memory Size:" id="e6x-TE-OC5">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
@ -829,7 +867,7 @@ Gw
</textFieldCell>
</textField>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="ReP-bV-Thu">
<rect key="frame" x="18" y="158" width="118" height="18"/>
<rect key="frame" x="18" y="157" width="118" height="18"/>
<buttonCell key="cell" type="check" title="Use ZX81 ROM" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="VQH-nv-Pfm">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
@ -851,11 +889,11 @@ Gw
</tabViewItem>
<tabViewItem label="ZX81" identifier="zx81" id="Wnn-nQ-gZ6">
<view key="view" id="bmd-gL-gzT">
<rect key="frame" x="10" y="7" width="400" height="223"/>
<rect key="frame" x="10" y="7" width="400" height="222"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="5aO-UX-HnX">
<rect key="frame" x="108" y="179" width="116" height="25"/>
<rect key="frame" x="108" y="178" width="116" height="25"/>
<popUpButtonCell key="cell" type="push" title="Unexpanded" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="axesIndependently" inset="2" selectedItem="7QC-Ij-hES" id="d3W-Gl-3Mf">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
@ -868,8 +906,8 @@ Gw
</menu>
</popUpButtonCell>
</popUpButton>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="8tU-73-XEE">
<rect key="frame" x="18" y="185" width="87" height="16"/>
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="8tU-73-XEE">
<rect key="frame" x="18" y="184" width="87" height="16"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Memory Size:" id="z4b-oR-Yl2">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
@ -889,11 +927,11 @@ Gw
</tabViewItem>
<tabViewItem label="ZX Spectrum" identifier="spectrum" id="HQv-oF-k8b">
<view key="view" id="bMx-F6-JUb">
<rect key="frame" x="10" y="7" width="400" height="223"/>
<rect key="frame" x="10" y="7" width="400" height="222"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="gFZ-d4-WFv">
<rect key="frame" x="67" y="179" width="76" height="25"/>
<rect key="frame" x="67" y="178" width="76" height="25"/>
<popUpButtonCell key="cell" type="push" title="16kb" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" tag="16" imageScaling="axesIndependently" inset="2" selectedItem="Fo7-NL-Kv5" id="tYs-sA-oek">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
@ -909,8 +947,8 @@ Gw
</menu>
</popUpButtonCell>
</popUpButton>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="fJ3-ma-Byy">
<rect key="frame" x="18" y="185" width="46" height="16"/>
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="fJ3-ma-Byy">
<rect key="frame" x="18" y="184" width="46" height="16"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Model:" id="JId-Tp-LrE">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
@ -931,14 +969,14 @@ Gw
</tabViewItems>
</tabView>
<scrollView borderType="line" autohidesScrollers="YES" horizontalLineScroll="24" horizontalPageScroll="10" verticalLineScroll="24" verticalPageScroll="10" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" id="z5Q-Bs-hJj">
<rect key="frame" x="20" y="60" width="130" height="238"/>
<rect key="frame" x="20" y="60" width="130" height="252"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" heightSizable="YES"/>
<clipView key="contentView" id="O8s-Vw-9yQ">
<rect key="frame" x="1" y="1" width="128" height="236"/>
<rect key="frame" x="1" y="1" width="128" height="250"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="none" columnReordering="NO" columnResizing="NO" multipleSelection="NO" emptySelection="NO" autosaveColumns="NO" typeSelect="NO" rowHeight="24" id="3go-Eb-GOy">
<rect key="frame" x="0.0" y="0.0" width="128" height="236"/>
<rect key="frame" x="0.0" y="0.0" width="128" height="250"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<size key="intercellSpacing" width="17" height="0.0"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
@ -974,8 +1012,8 @@ Gw
<autoresizingMask key="autoresizingMask"/>
</scroller>
</scrollView>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="VAc-6N-O7q">
<rect key="frame" x="18" y="306" width="554" height="27"/>
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="VAc-6N-O7q">
<rect key="frame" x="18" y="320" width="554" height="27"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="Choose a machine" id="32m-Vs-dPO">
<font key="font" textStyle="title2" name=".SFNS-Regular"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>

View File

@ -84,9 +84,12 @@ class MachinePicker: NSObject, NSTableViewDataSource, NSTableViewDelegate {
// Set up data soure.
// TEMPORARY: remove the Apple IIgs option. It's not yet a fully-working machine; no need to publicise it.
let appleIIgsTabIndex = machineSelector.indexOfTabViewItem(withIdentifier: "appleiigs")
machineSelector.removeTabViewItem(machineSelector.tabViewItem(at: appleIIgsTabIndex))
// TEMPORARY: remove the Apple IIgs and PC compatible options.
// Neither is yet a fully-working machine.
for hidden in ["appleiigs", "pc"] {
let tabIndex = machineSelector.indexOfTabViewItem(withIdentifier: hidden)
machineSelector.removeTabViewItem(machineSelector.tabViewItem(at: tabIndex))
}
machineNameTable.reloadData()
// Machine type
@ -396,6 +399,9 @@ class MachinePicker: NSObject, NSTableViewDataSource, NSTableViewDelegate {
return CSStaticAnalyser(oricModel: model, diskInterface: diskInterface)
case "pc":
return CSStaticAnalyser(pcCompatibleModel: .turboXT)
case "spectrum":
var model: CSMachineSpectrumModel = .plus2a
switch spectrumModelTypeButton.selectedTag() {

View File

@ -59,7 +59,6 @@ struct Registers {
uint16_t &si() { return si_; }
uint16_t &di() { return di_; }
uint16_t ip_;
uint16_t &ip() { return ip_; }
uint16_t &es() { return es_; }
@ -89,9 +88,7 @@ struct Registers {
ip_ == rhs.ip_;
}
// TODO: make the below private and use a friend class for test population, to ensure Perform
// is free of direct accesses.
// private:
private:
CPU::RegisterPair16 ax_;
CPU::RegisterPair16 cx_;
CPU::RegisterPair16 dx_;
@ -102,6 +99,7 @@ struct Registers {
uint16_t si_;
uint16_t di_;
uint16_t es_, cs_, ds_, ss_;
uint16_t ip_;
};
class Segments {
public:
@ -369,18 +367,18 @@ struct IO {
};
class FlowController {
public:
FlowController(Memory &memory, Registers &registers, Segments &segments, Flags &flags) :
memory_(memory), registers_(registers), segments_(segments), flags_(flags) {}
FlowController(Registers &registers, Segments &segments) :
registers_(registers), segments_(segments) {}
// Requirements for perform.
void jump(uint16_t address) {
registers_.ip_ = address;
registers_.ip() = address;
}
void jump(uint16_t segment, uint16_t address) {
registers_.cs_ = segment;
registers_.cs() = segment;
segments_.did_update(Segments::Source::CS);
registers_.ip_ = address;
registers_.ip() = address;
}
void halt() {}
@ -399,10 +397,8 @@ class FlowController {
}
private:
Memory &memory_;
Registers &registers_;
Segments &segments_;
Flags &flags_;
bool should_repeat_ = false;
};
@ -418,7 +414,7 @@ struct ExecutionSupport {
ExecutionSupport():
memory(registers, segments),
segments(registers),
flow_controller(memory, registers, segments, flags) {}
flow_controller(registers, segments) {}
void clear() {
memory.clear();
@ -580,20 +576,20 @@ struct FailedExecution {
}
- (void)populate:(Registers &)registers flags:(Flags &)flags value:(NSDictionary *)value {
registers.ax_.full = [value[@"ax"] intValue];
registers.bx_.full = [value[@"bx"] intValue];
registers.cx_.full = [value[@"cx"] intValue];
registers.dx_.full = [value[@"dx"] intValue];
registers.ax() = [value[@"ax"] intValue];
registers.bx() = [value[@"bx"] intValue];
registers.cx() = [value[@"cx"] intValue];
registers.dx() = [value[@"dx"] intValue];
registers.bp_ = [value[@"bp"] intValue];
registers.cs_ = [value[@"cs"] intValue];
registers.di_ = [value[@"di"] intValue];
registers.ds_ = [value[@"ds"] intValue];
registers.es_ = [value[@"es"] intValue];
registers.si_ = [value[@"si"] intValue];
registers.sp_ = [value[@"sp"] intValue];
registers.ss_ = [value[@"ss"] intValue];
registers.ip_ = [value[@"ip"] intValue];
registers.bp() = [value[@"bp"] intValue];
registers.cs() = [value[@"cs"] intValue];
registers.di() = [value[@"di"] intValue];
registers.ds() = [value[@"ds"] intValue];
registers.es() = [value[@"es"] intValue];
registers.si() = [value[@"si"] intValue];
registers.sp() = [value[@"sp"] intValue];
registers.ss() = [value[@"ss"] intValue];
registers.ip() = [value[@"ip"] intValue];
const uint16_t flags_value = [value[@"flags"] intValue];
flags.set(flags_value);
@ -646,7 +642,7 @@ struct FailedExecution {
//
// TODO: enquire of the actual mechanism of repetition; if it were stateful as below then
// would it survive interrupts? So is it just IP adjustment?
execution_support.registers.ip_ += decoded.first;
execution_support.registers.ip() += decoded.first;
do {
execution_support.flow_controller.begin_instruction();
InstructionSet::x86::perform(
@ -718,7 +714,7 @@ struct FailedExecution {
// More research required, but for now I'm not treating this as a roadblock.
if(decoded.second.operation() == Operation::IDIV_REP) {
Registers advanced_registers = intended_registers;
advanced_registers.ip_ += decoded.first;
advanced_registers.ip() += decoded.first;
if(advanced_registers == execution_support.registers && ramEqual && flagsEqual) {
failure_list = &permitted_failures;
}

View File

@ -99,6 +99,7 @@ SOURCES += \
$$SRC/Machines/MasterSystem/*.cpp \
$$SRC/Machines/MSX/*.cpp \
$$SRC/Machines/Oric/*.cpp \
$$SRC/Machines/PCCompatible/*.cpp \
$$SRC/Machines/Utility/*.cpp \
$$SRC/Machines/Sinclair/Keyboard/*.cpp \
$$SRC/Machines/Sinclair/ZX8081/*.cpp \
@ -232,6 +233,7 @@ HEADERS += \
$$SRC/Machines/MasterSystem/*.hpp \
$$SRC/Machines/MSX/*.hpp \
$$SRC/Machines/Oric/*.hpp \
$$SRC/Machines/PCCompatible/*.hpp \
$$SRC/Machines/Utility/*.hpp \
$$SRC/Machines/Sinclair/Keyboard/*.hpp \
$$SRC/Machines/Sinclair/ZX8081/*.hpp \

View File

@ -86,6 +86,7 @@ SOURCES += glob.glob('../../Machines/Enterprise/*.cpp')
SOURCES += glob.glob('../../Machines/MasterSystem/*.cpp')
SOURCES += glob.glob('../../Machines/MSX/*.cpp')
SOURCES += glob.glob('../../Machines/Oric/*.cpp')
SOURCES += glob.glob('../../Machines/PCCompatible/*.cpp')
SOURCES += glob.glob('../../Machines/Utility/*.cpp')
SOURCES += glob.glob('../../Machines/Sinclair/Keyboard/*.cpp')
SOURCES += glob.glob('../../Machines/Sinclair/ZX8081/*.cpp')

Binary file not shown.

View File

@ -0,0 +1,5 @@
Expected files:
GLABIOS_0.2.5_8T.ROM — the 8088 GlaBIOS ROM.
GlaBIOS is an open-source GPLv3 alternative BIOS for XT clones, available from https://glabios.org/