1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-25 16:31:42 +00:00

Extends the keyboard protocol and adds keyboard input to the Apple II.

This commit is contained in:
Thomas Harte 2018-04-15 21:11:30 -04:00
parent be05d51e07
commit 465c38f03c
7 changed files with 49 additions and 10 deletions

View File

@ -12,7 +12,7 @@ using namespace Inputs;
Keyboard::Keyboard() {} Keyboard::Keyboard() {}
void Keyboard::set_key_pressed(Key key, bool is_pressed) { void Keyboard::set_key_pressed(Key key, char value, bool is_pressed) {
std::size_t key_offset = static_cast<std::size_t>(key); std::size_t key_offset = static_cast<std::size_t>(key);
if(key_offset >= key_states_.size()) { if(key_offset >= key_states_.size()) {
key_states_.resize(key_offset+1, false); key_states_.resize(key_offset+1, false);

View File

@ -40,7 +40,7 @@ class Keyboard {
}; };
// Host interface. // Host interface.
virtual void set_key_pressed(Key key, bool is_pressed); virtual void set_key_pressed(Key key, char value, bool is_pressed);
virtual void reset_all_keys(); virtual void reset_all_keys();
// Delegate interface. // Delegate interface.

View File

@ -9,6 +9,7 @@
#include "AppleII.hpp" #include "AppleII.hpp"
#include "../CRTMachine.hpp" #include "../CRTMachine.hpp"
#include "../KeyboardMachine.hpp"
#include "../Utility/MemoryFuzzer.hpp" #include "../Utility/MemoryFuzzer.hpp"
#include "../../Processors/6502/6502.hpp" #include "../../Processors/6502/6502.hpp"
@ -21,7 +22,9 @@ namespace {
class ConcreteMachine: class ConcreteMachine:
public CRTMachine::Machine, public CRTMachine::Machine,
public KeyboardMachine::Machine,
public CPU::MOS6502::BusHandler, public CPU::MOS6502::BusHandler,
public Inputs::Keyboard,
public AppleII::Machine { public AppleII::Machine {
private: private:
struct VideoBusHandler : public AppleII::Video::BusHandler { struct VideoBusHandler : public AppleII::Video::BusHandler {
@ -50,6 +53,7 @@ class ConcreteMachine:
std::vector<uint8_t> rom_; std::vector<uint8_t> rom_;
std::vector<uint8_t> character_rom_; std::vector<uint8_t> character_rom_;
uint16_t rom_start_address_; uint16_t rom_start_address_;
uint8_t keyboard_input_ = 0x00;
public: public:
ConcreteMachine(): ConcreteMachine():
@ -94,8 +98,7 @@ class ConcreteMachine:
break; break;
case 0xc000: case 0xc000:
// TODO: read keyboard. // TODO: read keyboard.
// printf("Keyboard poll\n"); *value = keyboard_input_;
*value = 0x00;//0x80 | 'A';
break; break;
} }
} }
@ -116,6 +119,10 @@ class ConcreteMachine:
case 0xc055: update_video(); video_->set_video_page(1); break; case 0xc055: update_video(); video_->set_video_page(1); break;
case 0xc056: update_video(); video_->set_low_resolution(); break; case 0xc056: update_video(); video_->set_low_resolution(); break;
case 0xc057: update_video(); video_->set_high_resolution(); break; case 0xc057: update_video(); video_->set_high_resolution(); break;
case 0xc010:
keyboard_input_ &= 0x7f;
break;
} }
// The Apple II has a slightly weird timing pattern: every 65th CPU cycle is stretched // The Apple II has a slightly weird timing pattern: every 65th CPU cycle is stretched
@ -155,6 +162,16 @@ class ConcreteMachine:
void run_for(const Cycles cycles) override { void run_for(const Cycles cycles) override {
m6502_.run_for(cycles); m6502_.run_for(cycles);
} }
void set_key_pressed(Key key, char value, bool is_pressed) override {
if(is_pressed) {
keyboard_input_ = static_cast<uint8_t>(value | 0x80);
}
}
Inputs::Keyboard &get_keyboard() override {
return *this;
}
}; };
} }

View File

@ -45,7 +45,7 @@ template <class BusHandler> class Video {
// Show only the centre 75% of the TV frame. // Show only the centre 75% of the TV frame.
crt_->set_video_signal(Outputs::CRT::VideoSignal::Composite); crt_->set_video_signal(Outputs::CRT::VideoSignal::Composite);
crt_->set_visible_area(Outputs::CRT::Rect(0.115f, 0.115f, 0.77f, 0.77f)); crt_->set_visible_area(Outputs::CRT::Rect(0.115f, 0.117f, 0.77f, 0.77f));
} }
/// @returns The CRT this video feed is feeding. /// @returns The CRT this video feed is feeding.

View File

@ -24,12 +24,12 @@ struct KeyActions {
Indicates that the key @c key has been either pressed or released, according to Indicates that the key @c key has been either pressed or released, according to
the state of @c isPressed. the state of @c isPressed.
*/ */
virtual void set_key_state(uint16_t key, bool is_pressed) = 0; virtual void set_key_state(uint16_t key, bool is_pressed) {}
/*! /*!
Instructs that all keys should now be treated as released. Instructs that all keys should now be treated as released.
*/ */
virtual void clear_all_keys() = 0; virtual void clear_all_keys() {}
}; };
/*! /*!

View File

@ -23,6 +23,8 @@
#import "NSBundle+DataResource.h" #import "NSBundle+DataResource.h"
#import "NSData+StdVector.h" #import "NSData+StdVector.h"
#include <bitset>
@interface CSMachine() <CSFastLoading> @interface CSMachine() <CSFastLoading>
- (void)speaker:(Outputs::Speaker::Speaker *)speaker didCompleteSamples:(const int16_t *)samples length:(int)length; - (void)speaker:(Outputs::Speaker::Speaker *)speaker didCompleteSamples:(const int16_t *)samples length:(int)length;
- (void)speakerDidChangeInputClock:(Outputs::Speaker::Speaker *)speaker; - (void)speakerDidChangeInputClock:(Outputs::Speaker::Speaker *)speaker;
@ -54,6 +56,8 @@ struct SpeakerDelegate: public Outputs::Speaker::Speaker::Delegate, public LockP
CSStaticAnalyser *_analyser; CSStaticAnalyser *_analyser;
std::unique_ptr<Machine::DynamicMachine> _machine; std::unique_ptr<Machine::DynamicMachine> _machine;
std::bitset<65536> _depressedKeys;
} }
- (instancetype)initWithAnalyser:(CSStaticAnalyser *)result { - (instancetype)initWithAnalyser:(CSStaticAnalyser *)result {
@ -168,12 +172,25 @@ struct SpeakerDelegate: public Outputs::Speaker::Speaker::Delegate, public LockP
- (void)setKey:(uint16_t)key characters:(NSString *)characters isPressed:(BOOL)isPressed { - (void)setKey:(uint16_t)key characters:(NSString *)characters isPressed:(BOOL)isPressed {
auto keyboard_machine = _machine->keyboard_machine(); auto keyboard_machine = _machine->keyboard_machine();
if(keyboard_machine) { if(keyboard_machine) {
// Don't pass anything on if this is not new information.
if(_depressedKeys[key] == !!isPressed) return;
_depressedKeys[key] = !!isPressed;
// Pick an ASCII code, if any.
char pressedKey = '\0';
if(characters.length) {
unichar firstCharacter = [characters characterAtIndex:0];
if(firstCharacter < 128) {
pressedKey = (char)firstCharacter;
}
}
@synchronized(self) { @synchronized(self) {
Inputs::Keyboard &keyboard = keyboard_machine->get_keyboard(); Inputs::Keyboard &keyboard = keyboard_machine->get_keyboard();
// Connect the Carbon-era Mac keyboard scancodes to Clock Signal's 'universal' enumeration in order // Connect the Carbon-era Mac keyboard scancodes to Clock Signal's 'universal' enumeration in order
// to pass into the platform-neutral realm. // to pass into the platform-neutral realm.
#define BIND(source, dest) case source: keyboard.set_key_pressed(Inputs::Keyboard::Key::dest, isPressed); break #define BIND(source, dest) case source: keyboard.set_key_pressed(Inputs::Keyboard::Key::dest, pressedKey, isPressed); break
switch(key) { switch(key) {
BIND(VK_ANSI_0, k0); BIND(VK_ANSI_1, k1); BIND(VK_ANSI_2, k2); BIND(VK_ANSI_3, k3); BIND(VK_ANSI_4, k4); BIND(VK_ANSI_0, k0); BIND(VK_ANSI_1, k1); BIND(VK_ANSI_2, k2); BIND(VK_ANSI_3, k3); BIND(VK_ANSI_4, k4);
BIND(VK_ANSI_5, k5); BIND(VK_ANSI_6, k6); BIND(VK_ANSI_7, k7); BIND(VK_ANSI_8, k8); BIND(VK_ANSI_9, k9); BIND(VK_ANSI_5, k5); BIND(VK_ANSI_6, k6); BIND(VK_ANSI_7, k7); BIND(VK_ANSI_8, k8); BIND(VK_ANSI_9, k9);

View File

@ -239,7 +239,7 @@ int main(int argc, char *argv[]) {
} }
// Determine the machine for the supplied file. // Determine the machine for the supplied file.
TargetList targets = Analyser::Static::GetTargets(arguments.file_name); Analyser::Static::TargetList targets = Analyser::Static::GetTargets(arguments.file_name);
if(targets.empty()) { if(targets.empty()) {
std::cerr << "Cannot open " << arguments.file_name << "; no target machine found" << std::endl; std::cerr << "Cannot open " << arguments.file_name << "; no target machine found" << std::endl;
return -1; return -1;
@ -450,7 +450,12 @@ int main(int argc, char *argv[]) {
if(keyboard_machine) { if(keyboard_machine) {
Inputs::Keyboard::Key key = Inputs::Keyboard::Key::Space; Inputs::Keyboard::Key key = Inputs::Keyboard::Key::Space;
if(!KeyboardKeyForSDLScancode(event.key.keysym.scancode, key)) break; if(!KeyboardKeyForSDLScancode(event.key.keysym.scancode, key)) break;
keyboard_machine->get_keyboard().set_key_pressed(key, is_pressed);
char key_value = '\0';
const char *key_name = SDL_GetKeyName(event.key.keysym.sym);
if(key_name[0] >= 0) key_value = key_name[0];
keyboard_machine->get_keyboard().set_key_pressed(key, key_value, is_pressed);
break; break;
} }