mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-03 08:05:40 +00:00
Merge pull request #906 from TomHarte/LoadingImprovements
Attempts to improve ZX fast-loading compatibility
This commit is contained in:
commit
bd1ea5740a
@ -72,7 +72,7 @@ const uint16_t *CharacterMapper::sequence_for_character(char character) const {
|
|||||||
#define SHIFT(...) {KeyShift, __VA_ARGS__, MachineTypes::MappedKeyboardMachine::KeyEndSequence}
|
#define SHIFT(...) {KeyShift, __VA_ARGS__, MachineTypes::MappedKeyboardMachine::KeyEndSequence}
|
||||||
#define SYMSHIFT(...) {KeySymbolShift, __VA_ARGS__, MachineTypes::MappedKeyboardMachine::KeyEndSequence}
|
#define SYMSHIFT(...) {KeySymbolShift, __VA_ARGS__, MachineTypes::MappedKeyboardMachine::KeyEndSequence}
|
||||||
#define X {MachineTypes::MappedKeyboardMachine::KeyNotMapped}
|
#define X {MachineTypes::MappedKeyboardMachine::KeyNotMapped}
|
||||||
constexpr KeySequence spectrum_key_sequences[] = {
|
static constexpr KeySequence spectrum_key_sequences[] = {
|
||||||
/* NUL */ X, /* SOH */ X,
|
/* NUL */ X, /* SOH */ X,
|
||||||
/* STX */ X, /* ETX */ X,
|
/* STX */ X, /* ETX */ X,
|
||||||
/* EOT */ X, /* ENQ */ X,
|
/* EOT */ X, /* ENQ */ X,
|
||||||
@ -137,7 +137,7 @@ const uint16_t *CharacterMapper::sequence_for_character(char character) const {
|
|||||||
/* z */ KEYS(KeyZ),
|
/* z */ KEYS(KeyZ),
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr KeySequence zx81_key_sequences[] = {
|
static constexpr KeySequence zx81_key_sequences[] = {
|
||||||
/* NUL */ X, /* SOH */ X,
|
/* NUL */ X, /* SOH */ X,
|
||||||
/* STX */ X, /* ETX */ X,
|
/* STX */ X, /* ETX */ X,
|
||||||
/* EOT */ X, /* ENQ */ X,
|
/* EOT */ X, /* ENQ */ X,
|
||||||
@ -203,7 +203,7 @@ const uint16_t *CharacterMapper::sequence_for_character(char character) const {
|
|||||||
/* | */ X, /* } */ X,
|
/* | */ X, /* } */ X,
|
||||||
};
|
};
|
||||||
|
|
||||||
static KeySequence zx80_key_sequences[] = {
|
static constexpr KeySequence zx80_key_sequences[] = {
|
||||||
/* NUL */ X, /* SOH */ X,
|
/* NUL */ X, /* SOH */ X,
|
||||||
/* STX */ X, /* ETX */ X,
|
/* STX */ X, /* ETX */ X,
|
||||||
/* EOT */ X, /* ENQ */ X,
|
/* EOT */ X, /* ENQ */ X,
|
||||||
|
@ -39,6 +39,8 @@
|
|||||||
|
|
||||||
#include "../../../ClockReceiver/JustInTime.hpp"
|
#include "../../../ClockReceiver/JustInTime.hpp"
|
||||||
|
|
||||||
|
#include "../../../Processors/Z80/State/State.hpp"
|
||||||
|
|
||||||
#include "../Keyboard/Keyboard.hpp"
|
#include "../Keyboard/Keyboard.hpp"
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
@ -211,15 +213,15 @@ template<Model model> class ConcreteMachine:
|
|||||||
case PartialMachineCycle::ReadOpcode:
|
case PartialMachineCycle::ReadOpcode:
|
||||||
// Fast loading: ROM version.
|
// Fast loading: ROM version.
|
||||||
//
|
//
|
||||||
// The below patches over the 'LD-BYTES' routine from the 48kb ROM.
|
// The below patches over part of the 'LD-BYTES' routine from the 48kb ROM.
|
||||||
if(use_fast_tape_hack_ && address == 0x0556 && read_pointers_[0] == &rom_[0xc000]) {
|
if(use_fast_tape_hack_ && address == 0x056b && read_pointers_[0] == &rom_[0xc000]) {
|
||||||
if(perform_rom_ld_bytes()) {
|
|
||||||
// Stop pressing enter, if neccessry.
|
// Stop pressing enter, if neccessry.
|
||||||
if(duration_to_press_enter_ > Cycles(0)) {
|
if(duration_to_press_enter_ > Cycles(0)) {
|
||||||
duration_to_press_enter_ = Cycles(0);
|
duration_to_press_enter_ = Cycles(0);
|
||||||
keyboard_.set_key_state(ZX::Keyboard::KeyEnter, false);
|
keyboard_.set_key_state(ZX::Keyboard::KeyEnter, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(perform_rom_ld_bytes_56b()) {
|
||||||
*cycle.value = 0xc9; // i.e. RET.
|
*cycle.value = 0xc9; // i.e. RET.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -627,31 +629,42 @@ template<Model model> class ConcreteMachine:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Reimplements the 'LD-BYTES' routine, as documented at
|
// Reimplements the 'LD-BYTES' routine, as documented at
|
||||||
// https://skoolkid.github.io/rom/asm/0556.html i.e.
|
// https://skoolkid.github.io/rom/asm/0556.html but picking
|
||||||
|
// up from address 56b i.e.
|
||||||
//
|
//
|
||||||
// In:
|
// In:
|
||||||
// A: 0x00 or 0xff for block type;
|
// A': 0x00 or 0xff for block type;
|
||||||
// F: carry set if loading, clear if verifying;
|
// F': carry set if loading, clear if verifying;
|
||||||
// DE: block length;
|
// DE: block length;
|
||||||
// IX: start address.
|
// IX: start address.
|
||||||
//
|
//
|
||||||
// Out:
|
// Out:
|
||||||
// F: carry set for success, clear for error.
|
// F: carry set for success, clear for error.
|
||||||
bool perform_rom_ld_bytes() {
|
//
|
||||||
|
// And, empirically:
|
||||||
|
// IX: one beyond final address written;
|
||||||
|
// DE: 0;
|
||||||
|
// L: parity byte;
|
||||||
|
// H: 0 for no error, 0xff for error;
|
||||||
|
// A: same as H.
|
||||||
|
// BC: ???
|
||||||
|
bool perform_rom_ld_bytes_56b() {
|
||||||
using Parser = Storage::Tape::ZXSpectrum::Parser;
|
using Parser = Storage::Tape::ZXSpectrum::Parser;
|
||||||
Parser parser(Parser::MachineType::ZXSpectrum);
|
Parser parser(Parser::MachineType::ZXSpectrum);
|
||||||
|
|
||||||
using Register = CPU::Z80::Register;
|
using Register = CPU::Z80::Register;
|
||||||
uint8_t flags = uint8_t(z80_.get_value_of_register(Register::Flags));
|
uint8_t flags = uint8_t(z80_.get_value_of_register(Register::FlagsDash));
|
||||||
if(!(flags & 1)) return false;
|
if(!(flags & 1)) return false;
|
||||||
|
|
||||||
const uint8_t block_type = uint8_t(z80_.get_value_of_register(Register::A));
|
const uint8_t block_type = uint8_t(z80_.get_value_of_register(Register::ADash));
|
||||||
const auto block = parser.find_block(tape_player_.get_tape());
|
const auto block = parser.find_block(tape_player_.get_tape());
|
||||||
if(!block || block_type != (*block).type) return false;
|
if(!block || block_type != (*block).type) return false;
|
||||||
|
|
||||||
uint16_t length = z80_.get_value_of_register(Register::DE);
|
uint16_t length = z80_.get_value_of_register(Register::DE);
|
||||||
uint16_t target = z80_.get_value_of_register(Register::IX);
|
uint16_t target = z80_.get_value_of_register(Register::IX);
|
||||||
|
|
||||||
|
flags = 0x93;
|
||||||
|
uint8_t parity = 0x00;
|
||||||
while(length--) {
|
while(length--) {
|
||||||
auto next = parser.get_byte(tape_player_.get_tape());
|
auto next = parser.get_byte(tape_player_.get_tape());
|
||||||
if(!next) {
|
if(!next) {
|
||||||
@ -660,10 +673,25 @@ template<Model model> class ConcreteMachine:
|
|||||||
}
|
}
|
||||||
|
|
||||||
write_pointers_[target >> 14][target] = *next;
|
write_pointers_[target >> 14][target] = *next;
|
||||||
|
parity ^= *next;
|
||||||
++target;
|
++target;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto stored_parity = parser.get_byte(tape_player_.get_tape());
|
||||||
|
if(!stored_parity) {
|
||||||
|
flags &= ~1;
|
||||||
|
} else {
|
||||||
|
z80_.set_value_of_register(Register::L, *stored_parity);
|
||||||
|
}
|
||||||
|
|
||||||
z80_.set_value_of_register(Register::Flags, flags);
|
z80_.set_value_of_register(Register::Flags, flags);
|
||||||
|
z80_.set_value_of_register(Register::DE, length);
|
||||||
|
z80_.set_value_of_register(Register::IX, target);
|
||||||
|
|
||||||
|
const uint8_t h = (flags & 1) ? 0x00 : 0xff;
|
||||||
|
z80_.set_value_of_register(Register::H, h);
|
||||||
|
z80_.set_value_of_register(Register::A, h);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,6 +212,7 @@ std::string Reflection::Struct::description() const {
|
|||||||
for(const auto &key: all_keys()) {
|
for(const auto &key: all_keys()) {
|
||||||
if(!is_first) stream << ", ";
|
if(!is_first) stream << ", ";
|
||||||
is_first = false;
|
is_first = false;
|
||||||
|
|
||||||
stream << key << ": ";
|
stream << key << ": ";
|
||||||
|
|
||||||
const auto count = count_of(key);
|
const auto count = count_of(key);
|
||||||
|
Loading…
Reference in New Issue
Block a user