1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-29 00:29:34 +00:00

Rejigs the typing relationship so that use of a typer is not strongly implied by the interface.

Simultaneously implements typing on the MSX by direct insertion into the key buffer.
This commit is contained in:
Thomas Harte 2017-12-29 18:30:46 -05:00
parent d5b1a9d918
commit e349161a53
7 changed files with 53 additions and 14 deletions

View File

@ -27,3 +27,6 @@ void Machine::reset_all_keys(Inputs::Keyboard *keyboard) {
Inputs::Keyboard &Machine::get_keyboard() {
return keyboard_;
}
void Machine::type_string(const std::string &) {
}

View File

@ -30,6 +30,13 @@ class Machine: public Inputs::Keyboard::Delegate {
*/
virtual void clear_all_keys() = 0;
/*!
Causes the machine to attempt to type the supplied string.
This is best effort. Success or failure is permitted to be a function of machine and current state.
*/
virtual void type_string(const std::string &);
/*!
Provides a destination for keyboard input.
*/

View File

@ -139,6 +139,10 @@ class ConcreteMachine:
void configure_as_target(const StaticAnalyser::Target &target) override {
insert_media(target.media);
if(target.loading_command.length()) {
type_string(target.loading_command);
}
}
bool insert_media(const StaticAnalyser::Media &media) override {
@ -160,6 +164,10 @@ class ConcreteMachine:
return true;
}
void type_string(const std::string &string) override final {
input_text_ += string;
}
void page_memory(uint8_t value) {
for(size_t c = 0; c < 4; ++c) {
read_pointers_[c] = memory_slots_[value & 3].read_pointers[c];
@ -296,6 +304,32 @@ class ConcreteMachine:
case CPU::Z80::PartialMachineCycle::Interrupt:
*cycle.value = 0xff;
// Take this as a convenient moment to jump into the keyboard buffer, if desired.
if(!input_text_.empty()) {
// TODO: is it safe to assume these addresses?
const int buffer_start = 0xfbf0;
const int buffer_end = 0xfb18;
int read_address = ram_[0xf3fa] | (ram_[0xf3fb] << 8);
int write_address = ram_[0xf3f8] | (ram_[0xf3f9] << 8);
const int buffer_size = buffer_end - buffer_start;
int available_space = write_address + buffer_size - read_address - 1;
const std::size_t characters_to_write = std::min(static_cast<std::size_t>(available_space), input_text_.size());
write_address -= buffer_start;
for(std::size_t c = 0; c < characters_to_write; ++c) {
char character = input_text_[c];
ram_[write_address + buffer_start] = static_cast<uint8_t>(character);
write_address = (write_address + 1) % buffer_size;
}
write_address += buffer_start;
input_text_.erase(input_text_.begin(), input_text_.begin() + static_cast<std::string::difference_type>(characters_to_write));
ram_[0xf3f8] = static_cast<uint8_t>(write_address);
ram_[0xf3f9] = static_cast<uint8_t>(write_address >> 8);
}
break;
default: break;
@ -457,6 +491,7 @@ class ConcreteMachine:
uint8_t key_states_[16];
int selected_key_line_ = 0;
std::string input_text_;
MSX::KeyboardMapper keyboard_mapper_;
};

View File

@ -87,12 +87,6 @@ class TypeRecipient: public Typer::Delegate {
typer_.reset(new Typer(string, get_typer_delay(), get_typer_frequency(), std::move(character_mapper), this));
}
/*!
Provided as a hook for subclasses to implement so that external callers can install a typer
without needing inside knowledge as to where the character mapper comes from.
*/
virtual void type_string(const std::string &) = 0;
/*!
Provided in order to conform to that part of the Typer::Delegate interface that goes above and
beyond KeyboardMachine::Machine; responds to the end of typing by clearing all keys.

View File

@ -188,9 +188,9 @@ struct MachineDelegate: CRTMachine::Machine::Delegate, public LockProtectedDeleg
}
- (void)paste:(NSString *)paste {
Utility::TypeRecipient *typeRecipient = _machine->type_recipient();
if(typeRecipient)
typeRecipient->type_string([paste UTF8String]);
KeyboardMachine::Machine *keyboardMachine = _machine->type_recipient();
if(keyboardMachine)
keyboardMachine->type_string([paste UTF8String]);
}
- (void)applyTarget:(const StaticAnalyser::Target &)target {

View File

@ -439,9 +439,9 @@ int main(int argc, char *argv[]) {
case SDL_KEYDOWN:
// Syphon off the key-press if it's control+shift+V (paste).
if(event.key.keysym.sym == SDLK_v && (SDL_GetModState()&KMOD_CTRL) && (SDL_GetModState()&KMOD_SHIFT)) {
Utility::TypeRecipient *type_recipient = machine->type_recipient();
KeyboardMachine::Machine *keyboard_machine = machine->keyboard_machine()();
if(type_recipient) {
type_recipient->type_string(SDL_GetClipboardText());
keyboard_machine->type_string(SDL_GetClipboardText());
break;
}
}

View File

@ -61,9 +61,9 @@ void StaticAnalyser::MSX::AddTargets(const Media &media, std::list<Target> &dest
std::vector<File> files_on_tape = GetFiles(tape);
if(!files_on_tape.empty()) {
switch(files_on_tape.front().type) {
case File::Type::ASCII: target.loading_command = "RUN\"CAS:\n"; break;
case File::Type::TokenisedBASIC: target.loading_command = "CLOAD\nRUN\n"; break;
case File::Type::Binary: target.loading_command = "BLOAD\"CAS:\",R\n"; break;
case File::Type::ASCII: target.loading_command = "RUN\"CAS:\r"; break;
case File::Type::TokenisedBASIC: target.loading_command = "CLOAD\rRUN\r"; break;
case File::Type::Binary: target.loading_command = "BLOAD\"CAS:\",R\r"; break;
default: break;
}
target.media.tapes.push_back(tape);