mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-26 09:29:45 +00:00
Extends the keyboard protocol and adds keyboard input to the Apple II.
This commit is contained in:
parent
be05d51e07
commit
465c38f03c
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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() {}
|
||||
};
|
||||
|
||||
/*!
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user