1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-08 10:52:58 +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() {}
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);
if(key_offset >= key_states_.size()) {
key_states_.resize(key_offset+1, false);

View File

@ -40,7 +40,7 @@ class Keyboard {
};
// 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();
// Delegate interface.

View File

@ -9,6 +9,7 @@
#include "AppleII.hpp"
#include "../CRTMachine.hpp"
#include "../KeyboardMachine.hpp"
#include "../Utility/MemoryFuzzer.hpp"
#include "../../Processors/6502/6502.hpp"
@ -21,7 +22,9 @@ namespace {
class ConcreteMachine:
public CRTMachine::Machine,
public KeyboardMachine::Machine,
public CPU::MOS6502::BusHandler,
public Inputs::Keyboard,
public AppleII::Machine {
private:
struct VideoBusHandler : public AppleII::Video::BusHandler {
@ -50,6 +53,7 @@ class ConcreteMachine:
std::vector<uint8_t> rom_;
std::vector<uint8_t> character_rom_;
uint16_t rom_start_address_;
uint8_t keyboard_input_ = 0x00;
public:
ConcreteMachine():
@ -94,8 +98,7 @@ class ConcreteMachine:
break;
case 0xc000:
// TODO: read keyboard.
// printf("Keyboard poll\n");
*value = 0x00;//0x80 | 'A';
*value = keyboard_input_;
break;
}
}
@ -116,6 +119,10 @@ class ConcreteMachine:
case 0xc055: update_video(); video_->set_video_page(1); break;
case 0xc056: update_video(); video_->set_low_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
@ -155,6 +162,16 @@ class ConcreteMachine:
void run_for(const Cycles cycles) override {
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.
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.

View File

@ -24,12 +24,12 @@ struct KeyActions {
Indicates that the key @c key has been either pressed or released, according to
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.
*/
virtual void clear_all_keys() = 0;
virtual void clear_all_keys() {}
};
/*!

View File

@ -23,6 +23,8 @@
#import "NSBundle+DataResource.h"
#import "NSData+StdVector.h"
#include <bitset>
@interface CSMachine() <CSFastLoading>
- (void)speaker:(Outputs::Speaker::Speaker *)speaker didCompleteSamples:(const int16_t *)samples length:(int)length;
- (void)speakerDidChangeInputClock:(Outputs::Speaker::Speaker *)speaker;
@ -54,6 +56,8 @@ struct SpeakerDelegate: public Outputs::Speaker::Speaker::Delegate, public LockP
CSStaticAnalyser *_analyser;
std::unique_ptr<Machine::DynamicMachine> _machine;
std::bitset<65536> _depressedKeys;
}
- (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 {
auto keyboard_machine = _machine->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) {
Inputs::Keyboard &keyboard = keyboard_machine->get_keyboard();
// Connect the Carbon-era Mac keyboard scancodes to Clock Signal's 'universal' enumeration in order
// 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) {
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);

View File

@ -239,7 +239,7 @@ int main(int argc, char *argv[]) {
}
// 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()) {
std::cerr << "Cannot open " << arguments.file_name << "; no target machine found" << std::endl;
return -1;
@ -450,7 +450,12 @@ int main(int argc, char *argv[]) {
if(keyboard_machine) {
Inputs::Keyboard::Key key = Inputs::Keyboard::Key::Space;
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;
}