1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-01-03 15:29:45 +00:00

Add SSM code capture to CPC.

This commit is contained in:
Thomas Harte 2024-06-26 21:53:11 -04:00
parent 63737c09aa
commit f742266177
4 changed files with 51 additions and 13 deletions

View File

@ -20,6 +20,9 @@ struct Target: public Analyser::Static::Target, public Reflection::StructImpl<Ta
Model model = Model::CPC464; Model model = Model::CPC464;
std::string loading_command; std::string loading_command;
// This is used internally for testing; it therefore isn't exposed reflectively.
bool catch_ssm_codes = false;
Target() : Analyser::Static::Target(Machine::AmstradCPC) { Target() : Analyser::Static::Target(Machine::AmstradCPC) {
if(needs_declare()) { if(needs_declare()) {
DeclareField(model); DeclareField(model);

View File

@ -752,7 +752,8 @@ class i8255PortHandler : public Intel::i8255::PortHandler {
/*! /*!
The actual Amstrad CPC implementation; tying the 8255, 6845 and AY to the Z80. The actual Amstrad CPC implementation; tying the 8255, 6845 and AY to the Z80.
*/ */
template <bool has_fdc> class ConcreteMachine: template <bool has_fdc, bool catches_ssm>
class ConcreteMachine:
public MachineTypes::ScanProducer, public MachineTypes::ScanProducer,
public MachineTypes::AudioProducer, public MachineTypes::AudioProducer,
public MachineTypes::TimedMachine, public MachineTypes::TimedMachine,
@ -942,6 +943,19 @@ template <bool has_fdc> class ConcreteMachine:
*cycle.value = 0xc9; *cycle.value = 0xc9;
break; break;
} }
if constexpr (catches_ssm) {
ssm_code_ = (ssm_code_ << 8) | read_pointers_[address >> 14][address & 16383];
if((ssm_code_ & 0xff00ff00) == 0xed00ed00) {
if(ssm_delegate_) {
ssm_delegate_->perform(
uint16_t(
(ssm_code_ & 0xff) | ((ssm_code_ >> 8) & 0xff00)
));
}
ssm_code_ = 0;
}
}
[[fallthrough]]; [[fallthrough]];
case CPU::Z80::PartialMachineCycle::Read: case CPU::Z80::PartialMachineCycle::Read:
@ -1115,6 +1129,10 @@ template <bool has_fdc> class ConcreteMachine:
tape_player_is_sleeping_ = tape_player_.preferred_clocking() == ClockingHint::Preference::None; tape_player_is_sleeping_ = tape_player_.preferred_clocking() == ClockingHint::Preference::None;
} }
void set_ssm_delegate(SSMDelegate *delegate) final {
ssm_delegate_ = delegate;
}
// MARK: - Keyboard // MARK: - Keyboard
void type_string(const std::string &string) final { void type_string(const std::string &string) final {
Utility::TypeRecipient<CharacterMapper>::add_typer(string); Utility::TypeRecipient<CharacterMapper>::add_typer(string);
@ -1276,6 +1294,9 @@ template <bool has_fdc> class ConcreteMachine:
KeyboardState key_state_; KeyboardState key_state_;
AmstradCPC::KeyboardMapper keyboard_mapper_; AmstradCPC::KeyboardMapper keyboard_mapper_;
SSMDelegate *ssm_delegate_ = nullptr;
uint32_t ssm_code_ = 0;
bool has_run_ = false; bool has_run_ = false;
uint8_t ram_[128 * 1024]; uint8_t ram_[128 * 1024];
}; };
@ -1284,12 +1305,26 @@ template <bool has_fdc> class ConcreteMachine:
using namespace AmstradCPC; using namespace AmstradCPC;
namespace {
template <bool catch_ssm>
std::unique_ptr<Machine> machine(const Analyser::Static::AmstradCPC::Target &target, const ROMMachine::ROMFetcher &rom_fetcher) {
using Model = Analyser::Static::AmstradCPC::Target::Model;
switch(target.model) {
default: return std::make_unique<AmstradCPC::ConcreteMachine<true, catch_ssm>>(target, rom_fetcher);
case Model::CPC464: return std::make_unique<AmstradCPC::ConcreteMachine<false, catch_ssm>>(target, rom_fetcher);
}
}
}
// See header; constructs and returns an instance of the Amstrad CPC. // See header; constructs and returns an instance of the Amstrad CPC.
std::unique_ptr<Machine> Machine::AmstradCPC(const Analyser::Static::Target *target, const ROMMachine::ROMFetcher &rom_fetcher) { std::unique_ptr<Machine> Machine::AmstradCPC(const Analyser::Static::Target *target, const ROMMachine::ROMFetcher &rom_fetcher) {
using Target = Analyser::Static::AmstradCPC::Target; using Target = Analyser::Static::AmstradCPC::Target;
const Target *const cpc_target = dynamic_cast<const Target *>(target); const Target *const cpc_target = dynamic_cast<const Target *>(target);
switch(cpc_target->model) { if(cpc_target->catch_ssm_codes) {
default: return std::make_unique<AmstradCPC::ConcreteMachine<true>>(*cpc_target, rom_fetcher); return machine<true>(*cpc_target, rom_fetcher);
case Target::Model::CPC464: return std::make_unique<AmstradCPC::ConcreteMachine<false>>(*cpc_target, rom_fetcher); } else {
return machine<false>(*cpc_target, rom_fetcher);
} }
} }

View File

@ -25,7 +25,10 @@ class Machine {
virtual ~Machine() = default; virtual ~Machine() = default;
/// Creates and returns an Amstrad CPC. /// Creates and returns an Amstrad CPC.
static std::unique_ptr<Machine> AmstradCPC(const Analyser::Static::Target *target, const ROMMachine::ROMFetcher &rom_fetcher); static std::unique_ptr<Machine> AmstradCPC(
const Analyser::Static::Target *target,
const ROMMachine::ROMFetcher &rom_fetcher
);
/// Defines the runtime options available for an Amstrad CPC. /// Defines the runtime options available for an Amstrad CPC.
class Options: class Options:
@ -47,6 +50,11 @@ class Machine {
} }
} }
}; };
struct SSMDelegate {
virtual void perform(uint16_t) = 0;
};
virtual void set_ssm_delegate(SSMDelegate *) = 0;
}; };
} }

View File

@ -20,14 +20,6 @@ using namespace Storage::Automation;
namespace { namespace {
struct CSLTest {
CSLTest() {
CSL::parse("/Users/thomasharte/Downloads/Shaker_CSL/MODULE A/SHAKE26A-4.CSL");
}
};
CSLTest test;
bool append_typed(std::vector<Storage::Automation::CSL::KeyEvent> &down, std::vector<Storage::Automation::CSL::KeyEvent> &up, std::istringstream &stream) { bool append_typed(std::vector<Storage::Automation::CSL::KeyEvent> &down, std::vector<Storage::Automation::CSL::KeyEvent> &up, std::istringstream &stream) {
const auto press = [&](uint16_t key) { const auto press = [&](uint16_t key) {
CSL::KeyEvent event; CSL::KeyEvent event;