1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-06 01:28:57 +00:00

Merge pull request #256 from TomHarte/UniversalInput

Standardises the host-side interface for joystick and keyboard input
This commit is contained in:
Thomas Harte 2017-10-19 22:15:47 -04:00 committed by GitHub
commit 8d2b9a581a
51 changed files with 983 additions and 625 deletions

41
Inputs/Joystick.hpp Normal file
View File

@ -0,0 +1,41 @@
//
// Joystick.hpp
// Clock Signal
//
// Created by Thomas Harte on 14/10/2017.
// Copyright © 2017 Thomas Harte. All rights reserved.
//
#ifndef Joystick_hpp
#define Joystick_hpp
#include <vector>
namespace Inputs {
/*!
Provides an intermediate idealised model of a simple joystick, allowing a host
machine to toggle states, while an interested party either observes or polls.
*/
class Joystick {
public:
virtual ~Joystick() {}
enum class DigitalInput {
Up, Down, Left, Right, Fire
};
// Host interface.
virtual void set_digital_input(DigitalInput digital_input, bool is_active) = 0;
virtual void reset_all_inputs() {
set_digital_input(DigitalInput::Up, false);
set_digital_input(DigitalInput::Down, false);
set_digital_input(DigitalInput::Left, false);
set_digital_input(DigitalInput::Right, false);
set_digital_input(DigitalInput::Fire, false);
}
};
}
#endif /* Joystick_hpp */

38
Inputs/Keyboard.cpp Normal file
View File

@ -0,0 +1,38 @@
//
// Keyboard.cpp
// Clock Signal
//
// Created by Thomas Harte on 10/9/17.
// Copyright © 2017 Thomas Harte. All rights reserved.
//
#include "Keyboard.hpp"
using namespace Inputs;
Keyboard::Keyboard() {}
void Keyboard::set_key_pressed(Key key, bool is_pressed) {
size_t key_offset = static_cast<size_t>(key);
if(key_offset >= key_states_.size()) {
key_states_.resize(key_offset+1, false);
}
key_states_[key_offset] = is_pressed;
if(delegate_) delegate_->keyboard_did_change_key(this, key, is_pressed);
}
void Keyboard::reset_all_keys() {
std::fill(key_states_.begin(), key_states_.end(), false);
if(delegate_) delegate_->reset_all_keys(this);
}
void Keyboard::set_delegate(Delegate *delegate) {
delegate_ = delegate;
}
bool Keyboard::get_key_state(Key key) {
size_t key_offset = static_cast<size_t>(key);
if(key_offset >= key_states_.size()) return false;
return key_states_[key_offset];
}

61
Inputs/Keyboard.hpp Normal file
View File

@ -0,0 +1,61 @@
//
// Keyboard.hpp
// Clock Signal
//
// Created by Thomas Harte on 10/9/17.
// Copyright © 2017 Thomas Harte. All rights reserved.
//
#ifndef Keyboard_hpp
#define Keyboard_hpp
#include <vector>
namespace Inputs {
/*!
Provides an intermediate idealised model of a modern-era computer keyboard
(so, heavily indebted to the current Windows and Mac layouts), allowing a host
machine to toggle states, while an interested party either observes or polls.
*/
class Keyboard {
public:
Keyboard();
enum class Key {
Escape, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PrintScreen, ScrollLock, Pause,
BackTick, k1, k2, k3, k4, k5, k6, k7, k8, k9, k0, Hyphen, Equals, BackSpace,
Tab, Q, W, E, R, T, Y, U, I, O, P, OpenSquareBracket, CloseSquareBracket, BackSlash,
CapsLock, A, S, D, F, G, H, J, K, L, Semicolon, Quote, Hash, Enter,
LeftShift, Z, X, C, V, B, N, M, Comma, FullStop, ForwardSlash, RightShift,
LeftControl, LeftOption, LeftMeta, Space, RightMeta, RightOption, RightControl,
Left, Right, Up, Down,
Insert, Home, PageUp, Delete, End, PageDown,
NumLock, KeyPadSlash, KeyPadAsterisk, KeyPadDelete,
KeyPad7, KeyPad8, KeyPad9, KeyPadPlus,
KeyPad4, KeyPad5, KeyPad6, KeyPadMinus,
KeyPad1, KeyPad2, KeyPad3, KeyPadEnter,
KeyPad0, KeyPadDecimalPoint, KeyPadEquals,
Help
};
// Host interface.
virtual void set_key_pressed(Key key, bool is_pressed);
virtual void reset_all_keys();
// Delegate interface.
struct Delegate {
virtual void keyboard_did_change_key(Keyboard *keyboard, Key key, bool is_pressed) = 0;
virtual void reset_all_keys(Keyboard *keyboard) = 0;
};
void set_delegate(Delegate *delegate);
bool get_key_state(Key key);
private:
std::vector<bool> key_states_;
Delegate *delegate_ = nullptr;
};
}
#endif /* Keyboard_hpp */

View File

@ -9,6 +9,7 @@
#include "AmstradCPC.hpp"
#include "CharacterMapper.hpp"
#include "KeyboardMapper.hpp"
#include "../../Processors/Z80/Z80.hpp"
@ -953,6 +954,10 @@ class ConcreteMachine:
key_state_.clear_all_keys();
}
KeyboardMapper &get_keyboard_mapper() override {
return keyboard_mapper_;
}
private:
inline void write_to_gate_array(uint8_t value) {
switch(value >> 6) {
@ -1032,6 +1037,7 @@ class ConcreteMachine:
uint8_t *write_pointers_[4];
KeyboardState key_state_;
AmstradCPC::KeyboardMapper keyboard_mapper_;
};
}

View File

@ -12,9 +12,9 @@
using namespace AmstradCPC;
uint16_t *CharacterMapper::sequence_for_character(char character) {
#define KEYS(...) {__VA_ARGS__, EndSequence}
#define SHIFT(...) {KeyShift, __VA_ARGS__, EndSequence}
#define X {NotMapped}
#define KEYS(...) {__VA_ARGS__, KeyboardMachine::Machine::KeyEndSequence}
#define SHIFT(...) {KeyShift, __VA_ARGS__, KeyboardMachine::Machine::KeyEndSequence}
#define X {KeyboardMachine::Machine::KeyNotMapped}
static KeySequence key_sequences[] = {
/* NUL */ X, /* SOH */ X,
/* STX */ X, /* ETX */ X,

View File

@ -0,0 +1,76 @@
//
// KeyboardMapper.cpp
// Clock Signal
//
// Created by Thomas Harte on 10/10/2017.
// Copyright © 2017 Thomas Harte. All rights reserved.
//
#include "KeyboardMapper.hpp"
#include "AmstradCPC.hpp"
using namespace AmstradCPC;
uint16_t KeyboardMapper::mapped_key_for_key(Inputs::Keyboard::Key key) {
#define BIND(source, dest) case Inputs::Keyboard::Key::source: return dest
switch(key) {
default: return KeyCopy;
BIND(k0, Key0); BIND(k1, Key1); BIND(k2, Key2); BIND(k3, Key3); BIND(k4, Key4);
BIND(k5, Key5); BIND(k6, Key6); BIND(k7, Key7); BIND(k8, Key8); BIND(k9, Key9);
BIND(Q, KeyQ); BIND(W, KeyW); BIND(E, KeyE); BIND(R, KeyR); BIND(T, KeyT);
BIND(Y, KeyY); BIND(U, KeyU); BIND(I, KeyI); BIND(O, KeyO); BIND(P, KeyP);
BIND(A, KeyA); BIND(S, KeyS); BIND(D, KeyD); BIND(F, KeyF); BIND(G, KeyG);
BIND(H, KeyH); BIND(J, KeyJ); BIND(K, KeyK); BIND(L, KeyL);
BIND(Z, KeyZ); BIND(X, KeyX); BIND(C, KeyC); BIND(V, KeyV);
BIND(B, KeyB); BIND(N, KeyN); BIND(M, KeyM);
BIND(Escape, KeyEscape);
BIND(F1, KeyF1); BIND(F2, KeyF2); BIND(F3, KeyF3); BIND(F4, KeyF4); BIND(F5, KeyF5);
BIND(F6, KeyF6); BIND(F7, KeyF7); BIND(F8, KeyF8); BIND(F9, KeyF9); BIND(F10, KeyF0);
BIND(F11, KeyRightSquareBracket);
BIND(F12, KeyClear);
BIND(Hyphen, KeyMinus); BIND(Equals, KeyCaret); BIND(BackSpace, KeyDelete);
BIND(Tab, KeyTab);
BIND(OpenSquareBracket, KeyAt);
BIND(CloseSquareBracket, KeyLeftSquareBracket);
BIND(BackSlash, KeyBackSlash);
BIND(CapsLock, KeyCapsLock);
BIND(Semicolon, KeyColon);
BIND(Quote, KeySemicolon);
BIND(Hash, KeyRightSquareBracket);
BIND(Enter, KeyReturn);
BIND(LeftShift, KeyShift);
BIND(Comma, KeyComma);
BIND(FullStop, KeyFullStop);
BIND(ForwardSlash, KeyForwardSlash);
BIND(RightShift, KeyShift);
BIND(LeftControl, KeyControl); BIND(LeftOption, KeyControl); BIND(LeftMeta, KeyControl);
BIND(Space, KeySpace);
BIND(RightMeta, KeyControl); BIND(RightOption, KeyControl); BIND(RightControl, KeyControl);
BIND(Left, KeyLeft); BIND(Right, KeyRight);
BIND(Up, KeyUp); BIND(Down, KeyDown);
BIND(KeyPad0, KeyF0);
BIND(KeyPad1, KeyF1); BIND(KeyPad2, KeyF2); BIND(KeyPad3, KeyF3);
BIND(KeyPad4, KeyF4); BIND(KeyPad5, KeyF5); BIND(KeyPad6, KeyF6);
BIND(KeyPad7, KeyF7); BIND(KeyPad8, KeyF8); BIND(KeyPad9, KeyF9);
BIND(KeyPadPlus, KeySemicolon);
BIND(KeyPadMinus, KeyMinus);
BIND(KeyPadEnter, KeyEnter);
BIND(KeyPadDecimalPoint, KeyFullStop);
BIND(KeyPadEquals, KeyMinus);
BIND(KeyPadSlash, KeyForwardSlash);
BIND(KeyPadAsterisk, KeyColon);
BIND(KeyPadDelete, KeyDelete);
}
#undef BIND
}

View File

@ -0,0 +1,22 @@
//
// KeyboardMapper.hpp
// Clock Signal
//
// Created by Thomas Harte on 10/10/2017.
// Copyright © 2017 Thomas Harte. All rights reserved.
//
#ifndef Machines_AmstradCPC_KeyboardMapper_hpp
#define Machines_AmstradCPC_KeyboardMapper_hpp
#include "../KeyboardMachine.hpp"
namespace AmstradCPC {
struct KeyboardMapper: public KeyboardMachine::Machine::KeyboardMapper {
uint16_t mapped_key_for_key(Inputs::Keyboard::Key key);
};
};
#endif /* KeyboardMapper_hpp */

View File

@ -30,6 +30,33 @@ namespace {
namespace Atari2600 {
class Joystick: public Inputs::Joystick {
public:
Joystick(Bus *bus, size_t shift, size_t fire_tia_input) :
bus_(bus), shift_(shift), fire_tia_input_(fire_tia_input) {}
void set_digital_input(DigitalInput digital_input, bool is_active) {
switch(digital_input) {
case DigitalInput::Up: bus_->mos6532_.update_port_input(0, 0x10 >> shift_, is_active); break;
case DigitalInput::Down: bus_->mos6532_.update_port_input(0, 0x20 >> shift_, is_active); break;
case DigitalInput::Left: bus_->mos6532_.update_port_input(0, 0x40 >> shift_, is_active); break;
case DigitalInput::Right: bus_->mos6532_.update_port_input(0, 0x80 >> shift_, is_active); break;
// TODO: latching
case DigitalInput::Fire:
if(is_active)
bus_->tia_input_value_[fire_tia_input_] &= ~0x80;
else
bus_->tia_input_value_[fire_tia_input_] |= 0x80;
break;
}
}
private:
size_t shift_, fire_tia_input_;
Bus *bus_;
};
class ConcreteMachine:
public Machine,
public Outputs::CRT::Delegate {
@ -44,7 +71,7 @@ class ConcreteMachine:
close_output();
}
void configure_as_target(const StaticAnalyser::Target &target) {
void configure_as_target(const StaticAnalyser::Target &target) override {
const std::vector<uint8_t> &rom = target.media.cartridges.front()->get_segments().front().data;
switch(target.atari.paging_model) {
case StaticAnalyser::Atari2600PagingModel::ActivisionStack: bus_.reset(new Cartridge::Cartridge<Cartridge::ActivisionStack>(rom)); break;
@ -79,34 +106,20 @@ class ConcreteMachine:
}
break;
}
joysticks_.emplace_back(new Joystick(bus_.get(), 0, 0));
joysticks_.emplace_back(new Joystick(bus_.get(), 4, 1));
}
bool insert_media(const StaticAnalyser::Media &media) {
bool insert_media(const StaticAnalyser::Media &media) override {
return false;
}
void set_digital_input(Atari2600DigitalInput input, bool state) {
switch (input) {
case Atari2600DigitalInputJoy1Up: bus_->mos6532_.update_port_input(0, 0x10, state); break;
case Atari2600DigitalInputJoy1Down: bus_->mos6532_.update_port_input(0, 0x20, state); break;
case Atari2600DigitalInputJoy1Left: bus_->mos6532_.update_port_input(0, 0x40, state); break;
case Atari2600DigitalInputJoy1Right: bus_->mos6532_.update_port_input(0, 0x80, state); break;
case Atari2600DigitalInputJoy2Up: bus_->mos6532_.update_port_input(0, 0x01, state); break;
case Atari2600DigitalInputJoy2Down: bus_->mos6532_.update_port_input(0, 0x02, state); break;
case Atari2600DigitalInputJoy2Left: bus_->mos6532_.update_port_input(0, 0x04, state); break;
case Atari2600DigitalInputJoy2Right: bus_->mos6532_.update_port_input(0, 0x08, state); break;
// TODO: latching
case Atari2600DigitalInputJoy1Fire: if(state) bus_->tia_input_value_[0] &= ~0x80; else bus_->tia_input_value_[0] |= 0x80; break;
case Atari2600DigitalInputJoy2Fire: if(state) bus_->tia_input_value_[1] &= ~0x80; else bus_->tia_input_value_[1] |= 0x80; break;
default: break;
}
std::vector<std::unique_ptr<Inputs::Joystick>> &get_joysticks() override {
return joysticks_;
}
void set_switch_is_enabled(Atari2600Switch input, bool state) {
void set_switch_is_enabled(Atari2600Switch input, bool state) override {
switch(input) {
case Atari2600SwitchReset: bus_->mos6532_.update_port_input(1, 0x01, state); break;
case Atari2600SwitchSelect: bus_->mos6532_.update_port_input(1, 0x02, state); break;
@ -116,36 +129,36 @@ class ConcreteMachine:
}
}
void set_reset_switch(bool state) {
void set_reset_switch(bool state) override {
bus_->set_reset_line(state);
}
// to satisfy CRTMachine::Machine
void setup_output(float aspect_ratio) {
void setup_output(float aspect_ratio) override {
bus_->tia_.reset(new TIA);
bus_->speaker_.reset(new Speaker);
bus_->speaker_->set_input_rate((float)(get_clock_rate() / (double)CPUTicksPerAudioTick));
bus_->tia_->get_crt()->set_delegate(this);
}
void close_output() {
void close_output() override {
bus_.reset();
}
std::shared_ptr<Outputs::CRT::CRT> get_crt() {
std::shared_ptr<Outputs::CRT::CRT> get_crt() override {
return bus_->tia_->get_crt();
}
std::shared_ptr<Outputs::Speaker> get_speaker() {
std::shared_ptr<Outputs::Speaker> get_speaker() override {
return bus_->speaker_;
}
void run_for(const Cycles cycles) {
void run_for(const Cycles cycles) override {
bus_->run_for(cycles);
}
// to satisfy Outputs::CRT::Delegate
void crt_did_end_batch_of_frames(Outputs::CRT::CRT *crt, unsigned int number_of_frames, unsigned int number_of_unexpected_vertical_syncs) {
void crt_did_end_batch_of_frames(Outputs::CRT::CRT *crt, unsigned int number_of_frames, unsigned int number_of_unexpected_vertical_syncs) override {
const size_t number_of_frame_records = sizeof(frame_records_) / sizeof(frame_records_[0]);
frame_records_[frame_record_pointer_ % number_of_frame_records].number_of_frames = number_of_frames;
frame_records_[frame_record_pointer_ % number_of_frame_records].number_of_unexpected_vertical_syncs = number_of_unexpected_vertical_syncs;
@ -182,7 +195,6 @@ class ConcreteMachine:
}
}
private:
// the bus
std::unique_ptr<Bus> bus_;
@ -196,6 +208,7 @@ class ConcreteMachine:
} frame_records_[4];
unsigned int frame_record_pointer_;
bool is_ntsc_;
std::vector<std::unique_ptr<Inputs::Joystick>> joysticks_;
};
}

View File

@ -11,6 +11,7 @@
#include "../ConfigurationTarget.hpp"
#include "../CRTMachine.hpp"
#include "../JoystickMachine.hpp"
#include "Atari2600Inputs.h"
@ -21,16 +22,14 @@ namespace Atari2600 {
*/
class Machine:
public CRTMachine::Machine,
public ConfigurationTarget::Machine {
public ConfigurationTarget::Machine,
public JoystickMachine::Machine {
public:
virtual ~Machine();
/// Creates and returns an Atari 2600 on the heap.
static Machine *Atari2600();
/// Sets @c input to @c state.
virtual void set_digital_input(Atari2600DigitalInput input, bool state) = 0;
/// Sets the switch @c input to @c state.
virtual void set_switch_is_enabled(Atari2600Switch input, bool state) = 0;

View File

@ -12,9 +12,9 @@
using namespace Commodore::Vic20;
uint16_t *CharacterMapper::sequence_for_character(char character) {
#define KEYS(...) {__VA_ARGS__, EndSequence}
#define SHIFT(...) {KeyLShift, __VA_ARGS__, EndSequence}
#define X {NotMapped}
#define KEYS(...) {__VA_ARGS__, KeyboardMachine::Machine::KeyEndSequence}
#define SHIFT(...) {KeyLShift, __VA_ARGS__, KeyboardMachine::Machine::KeyEndSequence}
#define X {KeyboardMachine::Machine::KeyNotMapped}
static KeySequence key_sequences[] = {
/* NUL */ X, /* SOH */ X,
/* STX */ X, /* ETX */ X,

View File

@ -0,0 +1,73 @@
//
// KeyboardMapper.cpp
// Clock Signal
//
// Created by Thomas Harte on 10/10/2017.
// Copyright © 2017 Thomas Harte. All rights reserved.
//
#include "KeyboardMapper.hpp"
#include "Vic20.hpp"
using namespace Commodore::Vic20;
uint16_t KeyboardMapper::mapped_key_for_key(Inputs::Keyboard::Key key) {
#define BIND(source, dest) case Inputs::Keyboard::Key::source: return Commodore::Vic20::dest
switch(key) {
default: break;
BIND(k0, Key0); BIND(k1, Key1); BIND(k2, Key2); BIND(k3, Key3); BIND(k4, Key4);
BIND(k5, Key5); BIND(k6, Key6); BIND(k7, Key7); BIND(k8, Key8); BIND(k9, Key9);
BIND(Q, KeyQ); BIND(W, KeyW); BIND(E, KeyE); BIND(R, KeyR); BIND(T, KeyT);
BIND(Y, KeyY); BIND(U, KeyU); BIND(I, KeyI); BIND(O, KeyO); BIND(P, KeyP);
BIND(A, KeyA); BIND(S, KeyS); BIND(D, KeyD); BIND(F, KeyF); BIND(G, KeyG);
BIND(H, KeyH); BIND(J, KeyJ); BIND(K, KeyK); BIND(L, KeyL);
BIND(Z, KeyZ); BIND(X, KeyX); BIND(C, KeyC); BIND(V, KeyV);
BIND(B, KeyB); BIND(N, KeyN); BIND(M, KeyM);
BIND(BackTick, KeyLeft);
BIND(Hyphen, KeyPlus);
BIND(Equals, KeyDash);
BIND(F11, KeyGBP);
BIND(F12, KeyHome);
BIND(Tab, KeyControl);
BIND(OpenSquareBracket, KeyAt);
BIND(CloseSquareBracket, KeyAsterisk);
BIND(BackSlash, KeyRestore);
BIND(Hash, KeyUp);
BIND(F10, KeyUp);
BIND(Semicolon, KeyColon);
BIND(Quote, KeySemicolon);
BIND(F9, KeyEquals);
BIND(LeftMeta, KeyCBM);
BIND(LeftOption, KeyCBM);
BIND(RightOption, KeyCBM);
BIND(RightMeta, KeyCBM);
BIND(LeftShift, KeyLShift);
BIND(RightShift, KeyRShift);
BIND(Comma, KeyComma);
BIND(FullStop, KeyFullStop);
BIND(ForwardSlash, KeySlash);
BIND(Right, KeyRight);
BIND(Down, KeyDown);
BIND(Enter, KeyReturn);
BIND(Space, KeySpace);
BIND(BackSpace, KeyDelete);
BIND(Escape, KeyRunStop);
BIND(F1, KeyF1);
BIND(F3, KeyF3);
BIND(F5, KeyF5);
BIND(F7, KeyF7);
}
#undef BIND
return KeyboardMachine::Machine::KeyNotMapped;
}

View File

@ -0,0 +1,24 @@
//
// KeyboardMapper.hpp
// Clock Signal
//
// Created by Thomas Harte on 10/10/2017.
// Copyright © 2017 Thomas Harte. All rights reserved.
//
#ifndef Machines_Commodore_Vic20_KeyboardMapper_hpp
#define Machines_Commodore_Vic20_KeyboardMapper_hpp
#include "../../KeyboardMachine.hpp"
namespace Commodore {
namespace Vic20 {
struct KeyboardMapper: public KeyboardMachine::Machine::KeyboardMapper {
uint16_t mapped_key_for_key(Inputs::Keyboard::Key key);
};
}
}
#endif /* KeyboardMapper_hpp */

View File

@ -9,6 +9,7 @@
#include "Vic20.hpp"
#include "CharacterMapper.hpp"
#include "KeyboardMapper.hpp"
#include "../../../Processors/6502/6502.hpp"
#include "../../../Components/6560/6560.hpp"
@ -29,6 +30,14 @@
namespace Commodore {
namespace Vic20 {
enum JoystickInput {
Up = 0x04,
Down = 0x08,
Left = 0x10,
Right = 0x80,
Fire = 0x20
};
/*!
Models the user-port VIA, which is the Vic's connection point for controlling its tape recorder
sensing the presence or absence of a tape and controlling the tape motor and reading the current
@ -209,6 +218,35 @@ class Vic6560: public MOS::MOS6560<Vic6560> {
uint8_t *colour_memory; // Colour memory must be contiguous.
};
/*!
Interfaces a joystick to the two VIAs.
*/
class Joystick: public Inputs::Joystick {
public:
Joystick(UserPortVIA &user_port_via_port_handler, KeyboardVIA &keyboard_via_port_handler) :
user_port_via_port_handler_(user_port_via_port_handler),
keyboard_via_port_handler_(keyboard_via_port_handler) {}
void set_digital_input(DigitalInput digital_input, bool is_active) override {
JoystickInput mapped_input;
switch (digital_input) {
default: return;
case DigitalInput::Up: mapped_input = Up; break;
case DigitalInput::Down: mapped_input = Down; break;
case DigitalInput::Left: mapped_input = Left; break;
case DigitalInput::Right: mapped_input = Right; break;
case DigitalInput::Fire: mapped_input = Fire; break;
}
user_port_via_port_handler_.set_joystick_state(mapped_input, is_active);
keyboard_via_port_handler_.set_joystick_state(mapped_input, is_active);
}
private:
UserPortVIA &user_port_via_port_handler_;
KeyboardVIA &keyboard_via_port_handler_;
};
class ConcreteMachine:
public CPU::MOS6502::BusHandler,
public MOS::MOS6522::IRQDelegatePortHandler::Delegate,
@ -248,6 +286,9 @@ class ConcreteMachine:
// set the NTSC clock rate
set_region(NTSC);
// install a joystick
joysticks_.emplace_back(new Joystick(*user_port_via_port_handler_, *keyboard_via_port_handler_));
}
~ConcreteMachine() {
@ -327,17 +368,19 @@ class ConcreteMachine:
return !media.tapes.empty() || (!media.disks.empty() && c1540_ != nullptr) || !media.cartridges.empty();
}
void set_key_state(uint16_t key, bool isPressed) override final {
keyboard_via_port_handler_->set_key_state(key, isPressed);
void set_key_state(uint16_t key, bool is_pressed) override final {
if(key != KeyRestore)
keyboard_via_port_handler_->set_key_state(key, is_pressed);
else
user_port_via_.set_control_line_input(MOS::MOS6522::Port::A, MOS::MOS6522::Line::One, !is_pressed);
}
void clear_all_keys() override final {
keyboard_via_port_handler_->clear_all_keys();
}
void set_joystick_state(JoystickInput input, bool isPressed) override final {
user_port_via_port_handler_->set_joystick_state(input, isPressed);
keyboard_via_port_handler_->set_joystick_state(input, isPressed);
std::vector<std::unique_ptr<Inputs::Joystick>> &get_joysticks() override {
return joysticks_;
}
void set_memory_size(MemorySize size) override final {
@ -541,6 +584,10 @@ class ConcreteMachine:
keyboard_via_.set_control_line_input(MOS::MOS6522::Port::A, MOS::MOS6522::Line::One, !tape->get_input());
}
KeyboardMapper &get_keyboard_mapper() override {
return keyboard_mapper_;
}
private:
CPU::MOS6502::Processor<ConcreteMachine, false> m6502_;
@ -570,6 +617,8 @@ class ConcreteMachine:
}
Region region_;
Commodore::Vic20::KeyboardMapper keyboard_mapper_;
std::vector<std::unique_ptr<Inputs::Joystick>> joysticks_;
std::unique_ptr<Vic6560> mos6560_;
std::shared_ptr<UserPortVIA> user_port_via_port_handler_;

View File

@ -11,6 +11,8 @@
#include "../../ConfigurationTarget.hpp"
#include "../../CRTMachine.hpp"
#include "../../KeyboardMachine.hpp"
#include "../../JoystickMachine.hpp"
#include "../../Typer.hpp"
#include <cstdint>
@ -54,21 +56,16 @@ enum Key: uint16_t {
KeyI = key(1, 0x10), KeyP = key(1, 0x20), KeyAsterisk = key(1, 0x40), KeyReturn = key(1, 0x80),
Key1 = key(0, 0x01), Key3 = key(0, 0x02), Key5 = key(0, 0x04), Key7 = key(0, 0x08),
Key9 = key(0, 0x10), KeyPlus = key(0, 0x20), KeyGBP = key(0, 0x40), KeyDelete = key(0, 0x80),
#undef key
};
enum JoystickInput {
Up = 0x04,
Down = 0x08,
Left = 0x10,
Right = 0x80,
Fire = 0x20
KeyRestore = 0xfffd
#undef key
};
class Machine:
public CRTMachine::Machine,
public ConfigurationTarget::Machine,
public KeyboardMachine::Machine {
public KeyboardMachine::Machine,
public JoystickMachine::Machine {
public:
virtual ~Machine();
@ -79,9 +76,6 @@ class Machine:
virtual void set_rom(ROMSlot slot, size_t length, const uint8_t *data) = 0;
// TODO: take a std::vector<uint8_t> to collapse length and data.
/// Sets the state of joystick input @c input.
virtual void set_joystick_state(JoystickInput input, bool isPressed) = 0;
/// Sets the memory size of this Vic-20.
virtual void set_memory_size(MemorySize size) = 0;

View File

@ -12,10 +12,10 @@
using namespace Electron;
uint16_t *CharacterMapper::sequence_for_character(char character) {
#define KEYS(...) {__VA_ARGS__, EndSequence}
#define SHIFT(...) {KeyShift, __VA_ARGS__, EndSequence}
#define CTRL(...) {KeyControl, __VA_ARGS__, EndSequence}
#define X {NotMapped}
#define KEYS(...) {__VA_ARGS__, KeyboardMachine::Machine::KeyEndSequence}
#define SHIFT(...) {KeyShift, __VA_ARGS__, KeyboardMachine::Machine::KeyEndSequence}
#define CTRL(...) {KeyControl, __VA_ARGS__, KeyboardMachine::Machine::KeyEndSequence}
#define X {KeyboardMachine::Machine::KeyNotMapped}
static KeySequence key_sequences[] = {
/* NUL */ X, /* SOH */ X,
/* STX */ X, /* ETX */ X,

View File

@ -17,6 +17,7 @@
#include "CharacterMapper.hpp"
#include "Interrupts.hpp"
#include "KeyboardMapper.hpp"
#include "Plus3.hpp"
#include "Speaker.hpp"
#include "Tape.hpp"
@ -387,6 +388,10 @@ class ConcreteMachine:
Utility::TypeRecipient::set_typer_for_string(string, std::move(mapper));
}
KeyboardMapper &get_keyboard_mapper() override {
return keyboard_mapper_;
}
private:
inline void update_display() {
if(cycles_since_display_update_ > 0) {
@ -442,6 +447,7 @@ class ConcreteMachine:
uint8_t interrupt_status_ = Interrupt::PowerOnReset | Interrupt::TransmitDataEmpty | 0x80;
uint8_t interrupt_control_ = 0;
uint8_t key_states_[14];
Electron::KeyboardMapper keyboard_mapper_;
// Counters related to simultaneous subsystems
Cycles cycles_since_display_update_ = 0;

View File

@ -0,0 +1,57 @@
//
// KeyboardMapper.cpp
// Clock Signal
//
// Created by Thomas Harte on 10/10/2017.
// Copyright © 2017 Thomas Harte. All rights reserved.
//
#include "KeyboardMapper.hpp"
#include "Electron.hpp"
using namespace Electron;
uint16_t KeyboardMapper::mapped_key_for_key(Inputs::Keyboard::Key key) {
#define BIND(source, dest) case Inputs::Keyboard::Key::source: return Electron::Key::dest
switch(key) {
default: return KeyCopy;
BIND(k0, Key0); BIND(k1, Key1); BIND(k2, Key2); BIND(k3, Key3); BIND(k4, Key4);
BIND(k5, Key5); BIND(k6, Key6); BIND(k7, Key7); BIND(k8, Key8); BIND(k9, Key9);
BIND(Q, KeyQ); BIND(W, KeyW); BIND(E, KeyE); BIND(R, KeyR); BIND(T, KeyT);
BIND(Y, KeyY); BIND(U, KeyU); BIND(I, KeyI); BIND(O, KeyO); BIND(P, KeyP);
BIND(A, KeyA); BIND(S, KeyS); BIND(D, KeyD); BIND(F, KeyF); BIND(G, KeyG);
BIND(H, KeyH); BIND(J, KeyJ); BIND(K, KeyK); BIND(L, KeyL);
BIND(Z, KeyZ); BIND(X, KeyX); BIND(C, KeyC); BIND(V, KeyV);
BIND(B, KeyB); BIND(N, KeyN); BIND(M, KeyM);
BIND(Comma, KeyComma);
BIND(FullStop, KeyFullStop);
BIND(ForwardSlash, KeySlash);
BIND(Semicolon, KeySemiColon);
BIND(Quote, KeyColon);
BIND(Escape, KeyEscape);
BIND(Equals, KeyBreak);
BIND(F12, KeyBreak);
BIND(Left, KeyLeft); BIND(Right, KeyRight); BIND(Up, KeyUp); BIND(Down, KeyDown);
BIND(Tab, KeyFunc); BIND(LeftOption, KeyFunc); BIND(RightOption, KeyFunc);
BIND(LeftMeta, KeyFunc); BIND(RightMeta, KeyFunc);
BIND(CapsLock, KeyControl); BIND(LeftControl, KeyControl); BIND(RightControl, KeyControl);
BIND(LeftShift, KeyShift); BIND(RightShift, KeyShift);
BIND(Hyphen, KeyMinus);
BIND(Delete, KeyDelete);
BIND(Enter, KeyReturn); BIND(KeyPadEnter, KeyReturn);
BIND(KeyPad0, Key0); BIND(KeyPad1, Key1); BIND(KeyPad2, Key2); BIND(KeyPad3, Key3); BIND(KeyPad4, Key4);
BIND(KeyPad5, Key5); BIND(KeyPad6, Key6); BIND(KeyPad7, Key7); BIND(KeyPad8, Key8); BIND(KeyPad9, Key9);
BIND(KeyPadMinus, KeyMinus); BIND(KeyPadPlus, KeyColon);
BIND(Space, KeySpace);
}
#undef BIND
}

View File

@ -0,0 +1,22 @@
//
// KeyboardMapper.hpp
// Clock Signal
//
// Created by Thomas Harte on 10/10/2017.
// Copyright © 2017 Thomas Harte. All rights reserved.
//
#ifndef Machines_Electron_KeyboardMapper_hpp
#define Machines_Electron_KeyboardMapper_hpp
#include "../KeyboardMachine.hpp"
namespace Electron {
struct KeyboardMapper: public KeyboardMachine::Machine::KeyboardMapper {
uint16_t mapped_key_for_key(Inputs::Keyboard::Key key);
};
};
#endif /* KeyboardMapper_hpp */

View File

@ -0,0 +1,24 @@
//
// JoystickMachine.hpp
// Clock Signal
//
// Created by Thomas Harte on 14/10/2017.
// Copyright © 2017 Thomas Harte. All rights reserved.
//
#ifndef JoystickMachine_hpp
#define JoystickMachine_hpp
#include "../Inputs/Joystick.hpp"
#include <vector>
namespace JoystickMachine {
class Machine {
public:
virtual std::vector<std::unique_ptr<Inputs::Joystick>> &get_joysticks() = 0;
};
}
#endif /* JoystickMachine_hpp */

View File

@ -0,0 +1,29 @@
//
// KeyboardMachine.cpp
// Clock Signal
//
// Created by Thomas Harte on 10/10/2017.
// Copyright © 2017 Thomas Harte. All rights reserved.
//
#include "KeyboardMachine.hpp"
using namespace KeyboardMachine;
Machine::Machine() {
keyboard_.set_delegate(this);
}
void Machine::keyboard_did_change_key(Inputs::Keyboard *keyboard, Inputs::Keyboard::Key key, bool is_pressed) {
uint16_t mapped_key = get_keyboard_mapper().mapped_key_for_key(key);
if(mapped_key != KeyNotMapped) set_key_state(mapped_key, is_pressed);
}
void Machine::reset_all_keys(Inputs::Keyboard *keyboard) {
// TODO: unify naming.
clear_all_keys();
}
Inputs::Keyboard &Machine::get_keyboard() {
return keyboard_;
}

View File

@ -9,20 +9,59 @@
#ifndef KeyboardMachine_h
#define KeyboardMachine_h
#include "../Inputs/Keyboard.hpp"
namespace KeyboardMachine {
class Machine {
class Machine: public Inputs::Keyboard::Delegate {
public:
Machine();
/*!
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 isPressed) = 0;
virtual void set_key_state(uint16_t key, bool is_pressed) = 0;
/*!
Instructs that all keys should now be treated as released.
*/
virtual void clear_all_keys() = 0;
/*!
Provides a destination for keyboard input.
*/
virtual Inputs::Keyboard &get_keyboard();
/*!
A keyboard mapper attempts to provide a physical mapping between host keys and emulated keys.
See the character mapper for logical mapping.
*/
class KeyboardMapper {
public:
virtual uint16_t mapped_key_for_key(Inputs::Keyboard::Key key) = 0;
};
/// Terminates a key sequence from the character mapper.
static const uint16_t KeyEndSequence = 0xffff;
/*!
Indicates that a key is not mapped (for the keyboard mapper) or that a
character cannot be typed (for the character mapper).
*/
static const uint16_t KeyNotMapped = 0xfffe;
protected:
/*!
Allows individual machines to provide the mapping between host keys
as per Inputs::Keyboard and their native scheme.
*/
virtual KeyboardMapper &get_keyboard_mapper() = 0;
private:
void keyboard_did_change_key(Inputs::Keyboard *keyboard, Inputs::Keyboard::Key key, bool is_pressed) override;
void reset_all_keys(Inputs::Keyboard *keyboard) override;
Inputs::Keyboard keyboard_;
};
}

View File

@ -12,9 +12,9 @@
using namespace Oric;
uint16_t *CharacterMapper::sequence_for_character(char character) {
#define KEYS(...) {__VA_ARGS__, EndSequence}
#define SHIFT(...) {KeyLeftShift, __VA_ARGS__, EndSequence}
#define X {NotMapped}
#define KEYS(...) {__VA_ARGS__, KeyboardMachine::Machine::KeyEndSequence}
#define SHIFT(...) {KeyLeftShift, __VA_ARGS__, KeyboardMachine::Machine::KeyEndSequence}
#define X {KeyboardMachine::Machine::KeyNotMapped}
static KeySequence key_sequences[] = {
/* NUL */ X, /* SOH */ X,
/* STX */ X, /* ETX */ X,

View File

@ -0,0 +1,53 @@
//
// KeyboardMapper.cpp
// Clock Signal
//
// Created by Thomas Harte on 10/10/2017.
// Copyright © 2017 Thomas Harte. All rights reserved.
//
#include "KeyboardMapper.hpp"
#include "Oric.hpp"
using namespace Oric;
uint16_t KeyboardMapper::mapped_key_for_key(Inputs::Keyboard::Key key) {
#define BIND(source, dest) case Inputs::Keyboard::Key::source: return Oric::dest
switch(key) {
default: break;
BIND(k0, Key0); BIND(k1, Key1); BIND(k2, Key2); BIND(k3, Key3); BIND(k4, Key4);
BIND(k5, Key5); BIND(k6, Key6); BIND(k7, Key7); BIND(k8, Key8); BIND(k9, Key9);
BIND(Q, KeyQ); BIND(W, KeyW); BIND(E, KeyE); BIND(R, KeyR); BIND(T, KeyT);
BIND(Y, KeyY); BIND(U, KeyU); BIND(I, KeyI); BIND(O, KeyO); BIND(P, KeyP);
BIND(A, KeyA); BIND(S, KeyS); BIND(D, KeyD); BIND(F, KeyF); BIND(G, KeyG);
BIND(H, KeyH); BIND(J, KeyJ); BIND(K, KeyK); BIND(L, KeyL);
BIND(Z, KeyZ); BIND(X, KeyX); BIND(C, KeyC); BIND(V, KeyV);
BIND(B, KeyB); BIND(N, KeyN); BIND(M, KeyM);
BIND(Left, KeyLeft); BIND(Right, KeyRight); BIND(Up, KeyUp); BIND(Down, KeyDown);
BIND(Hyphen, KeyMinus); BIND(Equals, KeyEquals); BIND(BackSlash, KeyBackSlash);
BIND(OpenSquareBracket, KeyOpenSquare); BIND(CloseSquareBracket, KeyCloseSquare);
BIND(BackSpace, KeyDelete); BIND(Delete, KeyDelete);
BIND(Semicolon, KeySemiColon); BIND(Quote, KeyQuote);
BIND(Comma, KeyComma); BIND(FullStop, KeyFullStop); BIND(ForwardSlash, KeyForwardSlash);
BIND(Escape, KeyEscape); BIND(Tab, KeyEscape);
BIND(CapsLock, KeyControl); BIND(LeftControl, KeyControl); BIND(RightControl, KeyControl);
BIND(LeftOption, KeyFunction);
BIND(RightOption, KeyFunction);
BIND(LeftMeta, KeyFunction);
BIND(RightMeta, KeyFunction);
BIND(LeftShift, KeyLeftShift);
BIND(RightShift, KeyRightShift);
BIND(Space, KeySpace);
BIND(Enter, KeyReturn);
}
#undef BIND
return KeyboardMachine::Machine::KeyNotMapped;
}

View File

@ -0,0 +1,22 @@
//
// KeyboardMapper.hpp
// Clock Signal
//
// Created by Thomas Harte on 10/10/2017.
// Copyright © 2017 Thomas Harte. All rights reserved.
//
#ifndef Machines_Oric_KeyboardMapper_hpp
#define Machines_Oric_KeyboardMapper_hpp
#include "../KeyboardMachine.hpp"
namespace Oric {
struct KeyboardMapper: public KeyboardMachine::Machine::KeyboardMapper {
uint16_t mapped_key_for_key(Inputs::Keyboard::Key key);
};
};
#endif /* KeyboardMapper_hpp */

View File

@ -8,9 +8,10 @@
#include "Oric.hpp"
#include "Video.hpp"
#include "Microdisc.hpp"
#include "CharacterMapper.hpp"
#include "KeyboardMapper.hpp"
#include "Microdisc.hpp"
#include "Video.hpp"
#include "../MemoryFuzzer.hpp"
#include "../Typer.hpp"
@ -405,6 +406,10 @@ class ConcreteMachine:
set_interrupt_line();
}
KeyboardMapper &get_keyboard_mapper() override {
return keyboard_mapper_;
}
private:
CPU::MOS6502::Processor<ConcreteMachine, false> m6502_;
@ -425,6 +430,9 @@ class ConcreteMachine:
std::unique_ptr<VideoOutput> video_output_;
std::shared_ptr<GI::AY38910::AY38910> ay8910_;
// Inputs
Oric::KeyboardMapper keyboard_mapper_;
// The tape
TapePlayer tape_player_;
bool use_fast_tape_hack_ = false;

View File

@ -44,14 +44,14 @@ void Typer::run_for(const HalfCycles duration) {
bool Typer::try_type_next_character() {
uint16_t *sequence = character_mapper_->sequence_for_character(string_[string_pointer_]);
if(!sequence || sequence[0] == CharacterMapper::NotMapped) {
if(!sequence || sequence[0] == KeyboardMachine::Machine::KeyNotMapped) {
return false;
}
if(!phase_) delegate_->clear_all_keys();
else {
delegate_->set_key_state(sequence[phase_ - 1], true);
return sequence[phase_] != CharacterMapper::EndSequence;
return sequence[phase_] != KeyboardMachine::Machine::KeyEndSequence;
}
return true;
@ -85,6 +85,6 @@ Typer::~Typer() {
uint16_t *CharacterMapper::table_lookup_sequence_for_character(KeySequence *sequences, size_t length, char character) {
size_t ucharacter = static_cast<size_t>((unsigned char)character);
if(ucharacter > (length / sizeof(KeySequence))) return nullptr;
if(sequences[ucharacter][0] == NotMapped) return nullptr;
if(sequences[ucharacter][0] == KeyboardMachine::Machine::KeyNotMapped) return nullptr;
return sequences[ucharacter];
}

View File

@ -24,15 +24,6 @@ class CharacterMapper {
/// @returns The EndSequence-terminated sequence of keys that would cause @c character to be typed.
virtual uint16_t *sequence_for_character(char character) = 0;
/// Terminates a key sequence.
static const uint16_t EndSequence = 0xffff;
/*!
If returned as the first entry in a key sequence, indicates that the requested character
cannot be mapped.
*/
static const uint16_t NotMapped = 0xfffe;
protected:
typedef uint16_t KeySequence[16];

View File

@ -14,9 +14,9 @@ using namespace ZX8081;
CharacterMapper::CharacterMapper(bool is_zx81) : is_zx81_(is_zx81) {}
uint16_t *CharacterMapper::sequence_for_character(char character) {
#define KEYS(...) {__VA_ARGS__, EndSequence}
#define SHIFT(...) {KeyShift, __VA_ARGS__, EndSequence}
#define X {NotMapped}
#define KEYS(...) {__VA_ARGS__, KeyboardMachine::Machine::KeyEndSequence}
#define SHIFT(...) {KeyShift, __VA_ARGS__, KeyboardMachine::Machine::KeyEndSequence}
#define X {KeyboardMachine::Machine::KeyNotMapped}
static KeySequence zx81_key_sequences[] = {
/* NUL */ X, /* SOH */ X,
/* STX */ X, /* ETX */ X,

View File

@ -0,0 +1,35 @@
//
// KeyboardMapper.cpp
// Clock Signal
//
// Created by Thomas Harte on 10/10/2017.
// Copyright © 2017 Thomas Harte. All rights reserved.
//
#include "KeyboardMapper.hpp"
#include "ZX8081.hpp"
using namespace ZX8081;
uint16_t KeyboardMapper::mapped_key_for_key(Inputs::Keyboard::Key key) {
#define BIND(source, dest) case Inputs::Keyboard::Key::source: return ZX8081::dest
switch(key) {
default: break;
BIND(k0, Key0); BIND(k1, Key1); BIND(k2, Key2); BIND(k3, Key3); BIND(k4, Key4);
BIND(k5, Key5); BIND(k6, Key6); BIND(k7, Key7); BIND(k8, Key8); BIND(k9, Key9);
BIND(Q, KeyQ); BIND(W, KeyW); BIND(E, KeyE); BIND(R, KeyR); BIND(T, KeyT);
BIND(Y, KeyY); BIND(U, KeyU); BIND(I, KeyI); BIND(O, KeyO); BIND(P, KeyP);
BIND(A, KeyA); BIND(S, KeyS); BIND(D, KeyD); BIND(F, KeyF); BIND(G, KeyG);
BIND(H, KeyH); BIND(J, KeyJ); BIND(K, KeyK); BIND(L, KeyL);
BIND(Z, KeyZ); BIND(X, KeyX); BIND(C, KeyC); BIND(V, KeyV);
BIND(B, KeyB); BIND(N, KeyN); BIND(M, KeyM);
BIND(LeftShift, KeyShift); BIND(RightShift, KeyShift);
BIND(FullStop, KeyDot);
BIND(Enter, KeyEnter);
BIND(Space, KeySpace);
}
#undef BIND
return KeyboardMachine::Machine::KeyNotMapped;
}

View File

@ -0,0 +1,22 @@
//
// KeyboardMapper.hpp
// Clock Signal
//
// Created by Thomas Harte on 10/10/2017.
// Copyright © 2017 Thomas Harte. All rights reserved.
//
#ifndef Machines_ZX8081_KeyboardMapper_hpp
#define Machines_ZX8081_KeyboardMapper_hpp
#include "../KeyboardMachine.hpp"
namespace ZX8081 {
struct KeyboardMapper: public KeyboardMachine::Machine::KeyboardMapper {
uint16_t mapped_key_for_key(Inputs::Keyboard::Key key);
};
};
#endif /* KeyboardMapper_hpp */

View File

@ -18,6 +18,7 @@
#include "../Typer.hpp"
#include "CharacterMapper.hpp"
#include "KeyboardMapper.hpp"
#include "Video.hpp"
#include <memory>
@ -331,6 +332,10 @@ template<bool is_zx81> class ConcreteMachine:
HalfCycles get_typer_delay() override final { return Cycles(7000000); }
HalfCycles get_typer_frequency() override final { return Cycles(390000); }
KeyboardMapper &get_keyboard_mapper() override {
return keyboard_mapper_;
}
private:
CPU::Z80::Processor<ConcreteMachine, false, is_zx81> z80_;
@ -350,6 +355,7 @@ template<bool is_zx81> class ConcreteMachine:
int line_counter_;
uint8_t key_states_[8];
ZX8081::KeyboardMapper keyboard_mapper_;
HalfClockReceiver<Storage::Tape::BinaryTapePlayer> tape_player_;
Storage::Tape::ZX8081::Parser parser_;

View File

@ -81,6 +81,12 @@
4B4DC82B1D2C27A4003C5BF8 /* SerialBus.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4DC8291D2C27A4003C5BF8 /* SerialBus.cpp */; };
4B5073071DDD3B9400C48FBD /* ArrayBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B5073051DDD3B9400C48FBD /* ArrayBuilder.cpp */; };
4B50730A1DDFCFDF00C48FBD /* ArrayBuilderTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B5073091DDFCFDF00C48FBD /* ArrayBuilderTests.mm */; };
4B54C0BC1F8D8E790050900F /* KeyboardMachine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B54C0BB1F8D8E790050900F /* KeyboardMachine.cpp */; };
4B54C0BF1F8D8F450050900F /* KeyboardMapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B54C0BD1F8D8F450050900F /* KeyboardMapper.cpp */; };
4B54C0C21F8D91CD0050900F /* KeyboardMapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B54C0C11F8D91CD0050900F /* KeyboardMapper.cpp */; };
4B54C0C51F8D91D90050900F /* KeyboardMapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B54C0C41F8D91D90050900F /* KeyboardMapper.cpp */; };
4B54C0C81F8D91E50050900F /* KeyboardMapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B54C0C61F8D91E50050900F /* KeyboardMapper.cpp */; };
4B54C0CB1F8D92590050900F /* KeyboardMapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B54C0CA1F8D92580050900F /* KeyboardMapper.cpp */; };
4B55CE5D1C3B7D6F0093A61B /* CSOpenGLView.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B55CE5C1C3B7D6F0093A61B /* CSOpenGLView.m */; };
4B55CE5F1C3B7D960093A61B /* MachineDocument.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B55CE5E1C3B7D960093A61B /* MachineDocument.swift */; };
4B58601E1F806AB200AEE2E3 /* MFMSectorDump.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B58601C1F806AB200AEE2E3 /* MFMSectorDump.cpp */; };
@ -94,6 +100,7 @@
4B69FB441C4D941400B5F0AA /* TapeUEF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B69FB421C4D941400B5F0AA /* TapeUEF.cpp */; };
4B69FB461C4D950F00B5F0AA /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B69FB451C4D950F00B5F0AA /* libz.tbd */; };
4B6A4C991F58F09E00E3F787 /* 6502Base.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B6A4C951F58F09E00E3F787 /* 6502Base.cpp */; };
4B70412B1F92C2A700735E45 /* Joystick.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B7041291F92C2A700735E45 /* Joystick.cpp */; };
4B7136861F78724F008B8ED9 /* Encoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B7136841F78724F008B8ED9 /* Encoder.cpp */; };
4B7136891F78725F008B8ED9 /* Shifter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B7136871F78725F008B8ED9 /* Shifter.cpp */; };
4B71368E1F788112008B8ED9 /* Parser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B71368C1F788112008B8ED9 /* Parser.cpp */; };
@ -115,6 +122,7 @@
4B8378DF1F33675F005CA9E4 /* CharacterMapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B8378DD1F33675F005CA9E4 /* CharacterMapper.cpp */; };
4B8378E21F336920005CA9E4 /* CharacterMapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B8378E01F336920005CA9E4 /* CharacterMapper.cpp */; };
4B8378E51F3378C4005CA9E4 /* CharacterMapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B8378E31F3378C4005CA9E4 /* CharacterMapper.cpp */; };
4B86E25B1F8C628F006FAA45 /* Keyboard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B86E2591F8C628F006FAA45 /* Keyboard.cpp */; };
4B8805F01DCFC99C003085B1 /* Acorn.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B8805EE1DCFC99C003085B1 /* Acorn.cpp */; };
4B8805F41DCFD22A003085B1 /* Commodore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B8805F21DCFD22A003085B1 /* Commodore.cpp */; };
4B8805F71DCFF6C9003085B1 /* Commodore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B8805F51DCFF6C9003085B1 /* Commodore.cpp */; };
@ -520,7 +528,6 @@
4B2A332E1DB86869002876E3 /* OricOptionsPanel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OricOptionsPanel.swift; sourceTree = "<group>"; };
4B2A53901D117D36003C6002 /* CSAudioQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSAudioQueue.h; sourceTree = "<group>"; };
4B2A53911D117D36003C6002 /* CSAudioQueue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSAudioQueue.m; sourceTree = "<group>"; };
4B2A53931D117D36003C6002 /* CSKeyboardMachine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSKeyboardMachine.h; sourceTree = "<group>"; };
4B2A53941D117D36003C6002 /* CSMachine+Subclassing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "CSMachine+Subclassing.h"; sourceTree = "<group>"; };
4B2A53951D117D36003C6002 /* CSMachine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSMachine.h; sourceTree = "<group>"; };
4B2A53961D117D36003C6002 /* CSMachine.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CSMachine.mm; sourceTree = "<group>"; };
@ -628,6 +635,17 @@
4B5073051DDD3B9400C48FBD /* ArrayBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArrayBuilder.cpp; sourceTree = "<group>"; };
4B5073061DDD3B9400C48FBD /* ArrayBuilder.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ArrayBuilder.hpp; sourceTree = "<group>"; };
4B5073091DDFCFDF00C48FBD /* ArrayBuilderTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ArrayBuilderTests.mm; sourceTree = "<group>"; };
4B54C0BB1F8D8E790050900F /* KeyboardMachine.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = KeyboardMachine.cpp; sourceTree = "<group>"; };
4B54C0BD1F8D8F450050900F /* KeyboardMapper.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = KeyboardMapper.cpp; path = Oric/KeyboardMapper.cpp; sourceTree = "<group>"; };
4B54C0BE1F8D8F450050900F /* KeyboardMapper.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = KeyboardMapper.hpp; path = Oric/KeyboardMapper.hpp; sourceTree = "<group>"; };
4B54C0C01F8D91CD0050900F /* KeyboardMapper.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = KeyboardMapper.hpp; path = AmstradCPC/KeyboardMapper.hpp; sourceTree = "<group>"; };
4B54C0C11F8D91CD0050900F /* KeyboardMapper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = KeyboardMapper.cpp; path = AmstradCPC/KeyboardMapper.cpp; sourceTree = "<group>"; };
4B54C0C31F8D91D90050900F /* KeyboardMapper.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = KeyboardMapper.hpp; sourceTree = "<group>"; };
4B54C0C41F8D91D90050900F /* KeyboardMapper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = KeyboardMapper.cpp; sourceTree = "<group>"; };
4B54C0C61F8D91E50050900F /* KeyboardMapper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = KeyboardMapper.cpp; path = Electron/KeyboardMapper.cpp; sourceTree = "<group>"; };
4B54C0C71F8D91E50050900F /* KeyboardMapper.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = KeyboardMapper.hpp; path = Electron/KeyboardMapper.hpp; sourceTree = "<group>"; };
4B54C0C91F8D92580050900F /* KeyboardMapper.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = KeyboardMapper.hpp; path = ZX8081/KeyboardMapper.hpp; sourceTree = "<group>"; };
4B54C0CA1F8D92580050900F /* KeyboardMapper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = KeyboardMapper.cpp; path = ZX8081/KeyboardMapper.cpp; sourceTree = "<group>"; };
4B55CE5B1C3B7D6F0093A61B /* CSOpenGLView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSOpenGLView.h; sourceTree = "<group>"; };
4B55CE5C1C3B7D6F0093A61B /* CSOpenGLView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSOpenGLView.m; sourceTree = "<group>"; };
4B55CE5E1C3B7D960093A61B /* MachineDocument.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MachineDocument.swift; sourceTree = "<group>"; };
@ -654,6 +672,9 @@
4B6A4C911F58F09E00E3F787 /* 6502AllRAM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = 6502AllRAM.cpp; sourceTree = "<group>"; };
4B6A4C921F58F09E00E3F787 /* 6502AllRAM.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = 6502AllRAM.hpp; sourceTree = "<group>"; };
4B6A4C951F58F09E00E3F787 /* 6502Base.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = 6502Base.cpp; sourceTree = "<group>"; };
4B7041271F92C26900735E45 /* JoystickMachine.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = JoystickMachine.hpp; sourceTree = "<group>"; };
4B7041291F92C2A700735E45 /* Joystick.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Joystick.cpp; sourceTree = "<group>"; };
4B70412A1F92C2A700735E45 /* Joystick.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Joystick.hpp; sourceTree = "<group>"; };
4B7136841F78724F008B8ED9 /* Encoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Encoder.cpp; sourceTree = "<group>"; };
4B7136851F78724F008B8ED9 /* Encoder.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Encoder.hpp; sourceTree = "<group>"; };
4B7136871F78725F008B8ED9 /* Shifter.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Shifter.cpp; sourceTree = "<group>"; };
@ -689,6 +710,8 @@
4B8378E11F336920005CA9E4 /* CharacterMapper.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = CharacterMapper.hpp; path = Oric/CharacterMapper.hpp; sourceTree = "<group>"; };
4B8378E31F3378C4005CA9E4 /* CharacterMapper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CharacterMapper.cpp; sourceTree = "<group>"; };
4B8378E41F3378C4005CA9E4 /* CharacterMapper.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CharacterMapper.hpp; sourceTree = "<group>"; };
4B86E2591F8C628F006FAA45 /* Keyboard.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Keyboard.cpp; sourceTree = "<group>"; };
4B86E25A1F8C628F006FAA45 /* Keyboard.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Keyboard.hpp; sourceTree = "<group>"; };
4B8805EE1DCFC99C003085B1 /* Acorn.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Acorn.cpp; path = Parsers/Acorn.cpp; sourceTree = "<group>"; };
4B8805EF1DCFC99C003085B1 /* Acorn.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Acorn.hpp; path = Parsers/Acorn.hpp; sourceTree = "<group>"; };
4B8805F21DCFD22A003085B1 /* Commodore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Commodore.cpp; path = Parsers/Commodore.cpp; sourceTree = "<group>"; };
@ -717,7 +740,6 @@
4B96F7201D75119A0058BB2D /* Tape.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Tape.cpp; path = ../../StaticAnalyser/Acorn/Tape.cpp; sourceTree = "<group>"; };
4B96F7211D75119A0058BB2D /* Tape.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Tape.hpp; path = ../../StaticAnalyser/Acorn/Tape.hpp; sourceTree = "<group>"; };
4B9CCDA01DA279CA0098B625 /* Vic20OptionsPanel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Vic20OptionsPanel.swift; sourceTree = "<group>"; };
4B9CCDA21DA27C3F0098B625 /* CSJoystickMachine.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CSJoystickMachine.h; sourceTree = "<group>"; };
4BA0F68C1EEA0E8400E9489E /* ZX8081.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ZX8081.cpp; path = Data/ZX8081.cpp; sourceTree = "<group>"; };
4BA0F68D1EEA0E8400E9489E /* ZX8081.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = ZX8081.hpp; path = Data/ZX8081.hpp; sourceTree = "<group>"; };
4BA22B051D8817CE0008C640 /* Disk.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Disk.cpp; path = ../../StaticAnalyser/Commodore/Disk.cpp; sourceTree = "<group>"; };
@ -1204,9 +1226,11 @@
isa = PBXGroup;
children = (
4B8378DD1F33675F005CA9E4 /* CharacterMapper.cpp */,
4B54C0CA1F8D92580050900F /* KeyboardMapper.cpp */,
4BD3A3091EE755C800B5B501 /* Video.cpp */,
4B1497901EE4B5A800CE2596 /* ZX8081.cpp */,
4B8378DE1F33675F005CA9E4 /* CharacterMapper.hpp */,
4B54C0C91F8D92580050900F /* KeyboardMapper.hpp */,
4BD3A30A1EE755C800B5B501 /* Video.hpp */,
4B1497911EE4B5A800CE2596 /* ZX8081.hpp */,
);
@ -1257,8 +1281,6 @@
isa = PBXGroup;
children = (
4BBC34241D2208B100FFC9DF /* CSFastLoading.h */,
4B9CCDA21DA27C3F0098B625 /* CSJoystickMachine.h */,
4B2A53931D117D36003C6002 /* CSKeyboardMachine.h */,
4B2A53951D117D36003C6002 /* CSMachine.h */,
4B2A53941D117D36003C6002 /* CSMachine+Subclassing.h */,
4B643F3C1D77AE5C00D431D6 /* CSMachine+Target.h */,
@ -1316,6 +1338,7 @@
children = (
4B8378DA1F336631005CA9E4 /* CharacterMapper.cpp */,
4B2E2D9B1C3A070400138695 /* Electron.cpp */,
4B54C0C61F8D91E50050900F /* KeyboardMapper.cpp */,
4B30512E1D98ACC600B4FED8 /* Plus3.cpp */,
4BEA52611DF339D7007E74F2 /* Speaker.cpp */,
4BEA525D1DF33323007E74F2 /* Tape.cpp */,
@ -1323,6 +1346,7 @@
4B8378DB1F336631005CA9E4 /* CharacterMapper.hpp */,
4B2E2D9C1C3A070400138695 /* Electron.hpp */,
4BEA52601DF3343A007E74F2 /* Interrupts.hpp */,
4B54C0C71F8D91E50050900F /* KeyboardMapper.hpp */,
4B30512F1D98ACC600B4FED8 /* Plus3.hpp */,
4BEA52621DF339D7007E74F2 /* Speaker.hpp */,
4BEA525F1DF333D8007E74F2 /* Tape.hpp */,
@ -1376,9 +1400,11 @@
isa = PBXGroup;
children = (
4B38F3461F2EC11D00D9235D /* AmstradCPC.cpp */,
4B38F3471F2EC11D00D9235D /* AmstradCPC.hpp */,
4BACC5AF1F3DFF7C0037C015 /* CharacterMapper.cpp */,
4B54C0C11F8D91CD0050900F /* KeyboardMapper.cpp */,
4B38F3471F2EC11D00D9235D /* AmstradCPC.hpp */,
4BACC5B01F3DFF7C0037C015 /* CharacterMapper.hpp */,
4B54C0C01F8D91CD0050900F /* KeyboardMapper.hpp */,
);
name = AmstradCPC;
sourceTree = "<group>";
@ -1522,8 +1548,10 @@
isa = PBXGroup;
children = (
4B8378E31F3378C4005CA9E4 /* CharacterMapper.cpp */,
4B54C0C41F8D91D90050900F /* KeyboardMapper.cpp */,
4B4DC81F1D2C2425003C5BF8 /* Vic20.cpp */,
4B8378E41F3378C4005CA9E4 /* CharacterMapper.hpp */,
4B54C0C31F8D91D90050900F /* KeyboardMapper.hpp */,
4B4DC8201D2C2425003C5BF8 /* Vic20.hpp */,
);
path = "Vic-20";
@ -1715,6 +1743,18 @@
name = Implementation;
sourceTree = "<group>";
};
4B86E2581F8C628F006FAA45 /* Inputs */ = {
isa = PBXGroup;
children = (
4B86E2591F8C628F006FAA45 /* Keyboard.cpp */,
4B86E25A1F8C628F006FAA45 /* Keyboard.hpp */,
4B7041291F92C2A700735E45 /* Joystick.cpp */,
4B70412A1F92C2A700735E45 /* Joystick.hpp */,
);
name = Inputs;
path = ../../Inputs;
sourceTree = "<group>";
};
4B8805F11DCFC9A2003085B1 /* Parsers */ = {
isa = PBXGroup;
children = (
@ -2070,6 +2110,7 @@
4BF660691F281573002CB053 /* ClockReceiver */,
4BC9DF4A1D04691600F44158 /* Components */,
4B3940E81DA83C8700427841 /* Concurrency */,
4B86E2581F8C628F006FAA45 /* Inputs */,
4BB73EDC1B587CA500552FC2 /* Machines */,
4BB697C81D4B559300248BDF /* NumberTheory */,
4B366DFD1B5C165F0026627B /* Outputs */,
@ -2159,10 +2200,12 @@
4BB73EDC1B587CA500552FC2 /* Machines */ = {
isa = PBXGroup;
children = (
4B54C0BB1F8D8E790050900F /* KeyboardMachine.cpp */,
4B2A33281DB8544D002876E3 /* MemoryFuzzer.cpp */,
4B1E85731D170228001EF87D /* Typer.cpp */,
4BA9C3CF1D8164A9002DDB61 /* ConfigurationTarget.hpp */,
4B046DC31CFE651500E9E45E /* CRTMachine.hpp */,
4B7041271F92C26900735E45 /* JoystickMachine.hpp */,
4B8E4ECD1DCE483D003716C3 /* KeyboardMachine.hpp */,
4B2A33291DB8544D002876E3 /* MemoryFuzzer.hpp */,
4B1E85741D170228001EF87D /* Typer.hpp */,
@ -2302,10 +2345,12 @@
isa = PBXGroup;
children = (
4B8378E01F336920005CA9E4 /* CharacterMapper.cpp */,
4B54C0BD1F8D8F450050900F /* KeyboardMapper.cpp */,
4B5FADBE1DE3BF2B00AEC565 /* Microdisc.cpp */,
4BCF1FA21DADC3DD0039D2E7 /* Oric.cpp */,
4B2BFDB01DAEF5FF001A68B8 /* Video.cpp */,
4B8378E11F336920005CA9E4 /* CharacterMapper.hpp */,
4B54C0BE1F8D8F450050900F /* KeyboardMapper.hpp */,
4B5FADBF1DE3BF2B00AEC565 /* Microdisc.hpp */,
4BCF1FA31DADC3DD0039D2E7 /* Oric.hpp */,
4B2BFDB11DAEF5FF001A68B8 /* Video.hpp */,
@ -2912,12 +2957,14 @@
4B4518A11F75FD1C00926311 /* D64.cpp in Sources */,
4B1558C01F844ECD006E9A97 /* BitReverse.cpp in Sources */,
4BCF1FA41DADC3DD0039D2E7 /* Oric.cpp in Sources */,
4B54C0CB1F8D92590050900F /* KeyboardMapper.cpp in Sources */,
4BEA525E1DF33323007E74F2 /* Tape.cpp in Sources */,
4B8334951F5E25B60097E338 /* C1540.cpp in Sources */,
4B1497921EE4B5A800CE2596 /* ZX8081.cpp in Sources */,
4B643F3F1D77B88000D431D6 /* DocumentController.swift in Sources */,
4B4518861F75E91A00926311 /* MFMDiskController.cpp in Sources */,
4BA799951D8B656E0045123D /* StaticAnalyser.cpp in Sources */,
4B54C0BF1F8D8F450050900F /* KeyboardMapper.cpp in Sources */,
4B3FE75E1F3CF68B00448EE4 /* CPM.cpp in Sources */,
4B2BFDB21DAEF5FF001A68B8 /* Video.cpp in Sources */,
4B4DC82B1D2C27A4003C5BF8 /* SerialBus.cpp in Sources */,
@ -2950,7 +2997,10 @@
4BEA52631DF339D7007E74F2 /* Speaker.cpp in Sources */,
4BC5E4921D7ED365008CF980 /* StaticAnalyser.cpp in Sources */,
4BC830D11D6E7C690000A26F /* Tape.cpp in Sources */,
4B54C0C51F8D91D90050900F /* KeyboardMapper.cpp in Sources */,
4B70412B1F92C2A700735E45 /* Joystick.cpp in Sources */,
4B69FB441C4D941400B5F0AA /* TapeUEF.cpp in Sources */,
4B86E25B1F8C628F006FAA45 /* Keyboard.cpp in Sources */,
4B4518851F75E91A00926311 /* DiskController.cpp in Sources */,
4B8334841F5DA0360097E338 /* Z80Storage.cpp in Sources */,
4BA61EB01D91515900B3C876 /* NSData+StdVector.mm in Sources */,
@ -2979,6 +3029,7 @@
4B8FE2291DA1EDDF0090D3CE /* ElectronOptionsPanel.swift in Sources */,
4B55CE5D1C3B7D6F0093A61B /* CSOpenGLView.m in Sources */,
4BB697CB1D4B6D3E00248BDF /* TimedEventLoop.cpp in Sources */,
4B54C0C21F8D91CD0050900F /* KeyboardMapper.cpp in Sources */,
4BBC951E1F368D83008F4C34 /* i8272.cpp in Sources */,
4BF1354C1D6D2C300054B2EA /* StaticAnalyser.cpp in Sources */,
4B4A76301DB1A3FA007AAE2E /* AY38910.cpp in Sources */,
@ -3009,6 +3060,7 @@
4BEE0A6F1D72496600532C7B /* Cartridge.cpp in Sources */,
4B8805FB1DCFF807003085B1 /* Oric.cpp in Sources */,
4B5FADC01DE3BF2B00AEC565 /* Microdisc.cpp in Sources */,
4B54C0C81F8D91E50050900F /* KeyboardMapper.cpp in Sources */,
4BEE0A701D72496600532C7B /* PRG.cpp in Sources */,
4B8334861F5DA3780097E338 /* 6502Storage.cpp in Sources */,
4B8FE2271DA1DE2D0090D3CE /* NSBundle+DataResource.m in Sources */,
@ -3019,6 +3071,7 @@
4B2A539F1D117D36003C6002 /* CSAudioQueue.m in Sources */,
4B37EE821D7345A6006A09A4 /* BinaryDump.cpp in Sources */,
4B8334821F5D9FF70097E338 /* PartialMachineCycle.cpp in Sources */,
4B54C0BC1F8D8E790050900F /* KeyboardMachine.cpp in Sources */,
4BB73EA21B587A5100552FC2 /* AppDelegate.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;

View File

@ -3,7 +3,6 @@
//
#import "CSMachine.h"
#import "CSKeyboardMachine.h"
#import "CSFastLoading.h"
#import "CSAtari2600.h"
@ -17,3 +16,5 @@
#import "CSOpenGLView.h"
#import "CSAudioQueue.h"
#import "CSBestEffortUpdater.h"
#include "KeyCodes.h"

View File

@ -187,48 +187,22 @@ class MachineDocument:
}
// MARK: Input management
fileprivate func withKeyboardMachine(_ action: (CSKeyboardMachine) -> ()) {
if let keyboardMachine = self.machine as? CSKeyboardMachine {
action(keyboardMachine)
}
}
fileprivate func withJoystickMachine(_ action: (CSJoystickMachine) -> ()) {
if let joystickMachine = self.machine as? CSJoystickMachine {
action(joystickMachine)
}
}
fileprivate func sendJoystickEvent(_ machine: CSJoystickMachine, keyCode: UInt16, isPressed: Bool) {
switch keyCode {
case 123: machine.setDirection(.left, onPad: 0, isPressed: isPressed)
case 126: machine.setDirection(.up, onPad: 0, isPressed: isPressed)
case 124: machine.setDirection(.right, onPad: 0, isPressed: isPressed)
case 125: machine.setDirection(.down, onPad: 0, isPressed: isPressed)
default: machine.setButtonAt(0, onPad: 0, isPressed: isPressed)
}
}
func windowDidResignKey(_ notification: Notification) {
self.withKeyboardMachine { $0.clearAllKeys() }
self.machine.clearAllKeys()
}
func keyDown(_ event: NSEvent) {
self.withKeyboardMachine { $0.setKey(event.keyCode, isPressed: true) }
self.withJoystickMachine { sendJoystickEvent($0, keyCode: event.keyCode, isPressed: true) }
self.machine.setKey(event.keyCode, isPressed: true)
}
func keyUp(_ event: NSEvent) {
self.withKeyboardMachine { $0.setKey(event.keyCode, isPressed: false) }
self.withJoystickMachine { sendJoystickEvent($0, keyCode: event.keyCode, isPressed: false) }
self.machine.setKey(event.keyCode, isPressed: false)
}
func flagsChanged(_ newModifiers: NSEvent) {
self.withKeyboardMachine {
$0.setKey(VK_Shift, isPressed: newModifiers.modifierFlags.contains(.shift))
$0.setKey(VK_Control, isPressed: newModifiers.modifierFlags.contains(.control))
$0.setKey(VK_Command, isPressed: newModifiers.modifierFlags.contains(.command))
$0.setKey(VK_Option, isPressed: newModifiers.modifierFlags.contains(.option))
}
self.machine.setKey(VK_Shift, isPressed: newModifiers.modifierFlags.contains(.shift))
self.machine.setKey(VK_Control, isPressed: newModifiers.modifierFlags.contains(.control))
self.machine.setKey(VK_Command, isPressed: newModifiers.modifierFlags.contains(.command))
self.machine.setKey(VK_Option, isPressed: newModifiers.modifierFlags.contains(.option))
}
}

View File

@ -1,22 +0,0 @@
//
// CSJoystickMachine.h
// Clock Signal
//
// Created by Thomas Harte on 03/10/2016.
// Copyright © 2016 Thomas Harte. All rights reserved.
//
typedef NS_ENUM(NSInteger, CSJoystickDirection)
{
CSJoystickDirectionUp,
CSJoystickDirectionDown,
CSJoystickDirectionLeft,
CSJoystickDirectionRight
};
@protocol CSJoystickMachine <NSObject>
- (void)setButtonAtIndex:(NSUInteger)button onPad:(NSUInteger)pad isPressed:(BOOL)isPressed;
- (void)setDirection:(CSJoystickDirection)direction onPad:(NSUInteger)pad isPressed:(BOOL)isPressed;
@end

View File

@ -1,16 +0,0 @@
//
// CSKeyboardMachine.h
// Clock Signal
//
// Created by Thomas Harte on 05/06/2016.
// Copyright © 2016 Thomas Harte. All rights reserved.
//
#import "KeyCodes.h"
@protocol CSKeyboardMachine <NSObject>
- (void)setKey:(uint16_t)key isPressed:(BOOL)isPressed;
- (void)clearAllKeys;
@end

View File

@ -35,6 +35,9 @@
- (void)setView:(CSOpenGLView *)view aspectRatio:(float)aspectRatio;
- (void)drawViewForPixelSize:(CGSize)pixelSize onlyIfDirty:(BOOL)onlyIfDirty;
- (void)setKey:(uint16_t)key isPressed:(BOOL)isPressed;
- (void)clearAllKeys;
@property (nonatomic, strong) CSAudioQueue *audioQueue;
@property (nonatomic, readonly) CSOpenGLView *view;
@property (nonatomic, weak) id<CSMachineDelegate> delegate;

View File

@ -10,8 +10,11 @@
#import "CSMachine+Subclassing.h"
#import "CSMachine+Target.h"
#include "KeyCodes.h"
#include "Typer.hpp"
#include "ConfigurationTarget.hpp"
#include "JoystickMachine.hpp"
#include "KeyboardMachine.hpp"
@interface CSMachine()
- (void)speaker:(Outputs::Speaker *)speaker didCompleteSamples:(const int16_t *)samples length:(int)length;
@ -183,4 +186,106 @@ struct MachineDelegate: CRTMachine::Machine::Delegate, public LockProtectedDeleg
}
}
- (void)setKey:(uint16_t)key isPressed:(BOOL)isPressed {
auto keyboard_machine = dynamic_cast<KeyboardMachine::Machine *>(_machine);
if(keyboard_machine) {
@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
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);
BIND(VK_ANSI_Q, Q); BIND(VK_ANSI_W, W); BIND(VK_ANSI_E, E); BIND(VK_ANSI_R, R); BIND(VK_ANSI_T, T);
BIND(VK_ANSI_Y, Y); BIND(VK_ANSI_U, U); BIND(VK_ANSI_I, I); BIND(VK_ANSI_O, O); BIND(VK_ANSI_P, P);
BIND(VK_ANSI_A, A); BIND(VK_ANSI_S, S); BIND(VK_ANSI_D, D); BIND(VK_ANSI_F, F); BIND(VK_ANSI_G, G);
BIND(VK_ANSI_H, H); BIND(VK_ANSI_J, J); BIND(VK_ANSI_K, K); BIND(VK_ANSI_L, L);
BIND(VK_ANSI_Z, Z); BIND(VK_ANSI_X, X); BIND(VK_ANSI_C, C); BIND(VK_ANSI_V, V);
BIND(VK_ANSI_B, B); BIND(VK_ANSI_N, N); BIND(VK_ANSI_M, M);
BIND(VK_F1, F1); BIND(VK_F2, F2); BIND(VK_F3, F3); BIND(VK_F4, F4);
BIND(VK_F5, F5); BIND(VK_F6, F6); BIND(VK_F7, F7); BIND(VK_F8, F8);
BIND(VK_F9, F9); BIND(VK_F10, F10); BIND(VK_F11, F11); BIND(VK_F12, F12);
BIND(VK_ANSI_Keypad0, KeyPad0); BIND(VK_ANSI_Keypad1, KeyPad1); BIND(VK_ANSI_Keypad2, KeyPad2);
BIND(VK_ANSI_Keypad3, KeyPad3); BIND(VK_ANSI_Keypad4, KeyPad4); BIND(VK_ANSI_Keypad5, KeyPad5);
BIND(VK_ANSI_Keypad6, KeyPad6); BIND(VK_ANSI_Keypad7, KeyPad7); BIND(VK_ANSI_Keypad8, KeyPad8);
BIND(VK_ANSI_Keypad9, KeyPad9);
BIND(VK_ANSI_Equal, Equals); BIND(VK_ANSI_Minus, Hyphen);
BIND(VK_ANSI_RightBracket, CloseSquareBracket); BIND(VK_ANSI_LeftBracket, OpenSquareBracket);
BIND(VK_ANSI_Quote, Quote); BIND(VK_ANSI_Grave, BackTick);
BIND(VK_ANSI_Semicolon, Semicolon);
BIND(VK_ANSI_Backslash, BackSlash); BIND(VK_ANSI_Slash, ForwardSlash);
BIND(VK_ANSI_Comma, Comma); BIND(VK_ANSI_Period, FullStop);
BIND(VK_ANSI_KeypadDecimal, KeyPadDecimalPoint); BIND(VK_ANSI_KeypadEquals, KeyPadEquals);
BIND(VK_ANSI_KeypadMultiply, KeyPadAsterisk); BIND(VK_ANSI_KeypadDivide, KeyPadSlash);
BIND(VK_ANSI_KeypadPlus, KeyPadPlus); BIND(VK_ANSI_KeypadMinus, KeyPadMinus);
BIND(VK_ANSI_KeypadClear, KeyPadDelete); BIND(VK_ANSI_KeypadEnter, KeyPadEnter);
BIND(VK_Return, Enter); BIND(VK_Tab, Tab);
BIND(VK_Space, Space); BIND(VK_Delete, BackSpace);
BIND(VK_Control, LeftControl); BIND(VK_Option, LeftOption);
BIND(VK_Command, LeftMeta); BIND(VK_Shift, LeftShift);
BIND(VK_RightControl, RightControl); BIND(VK_RightOption, RightOption);
BIND(VK_Escape, Escape); BIND(VK_CapsLock, CapsLock);
BIND(VK_Home, Home); BIND(VK_End, End);
BIND(VK_PageUp, PageUp); BIND(VK_PageDown, PageDown);
BIND(VK_RightShift, RightShift);
BIND(VK_Help, Help);
BIND(VK_ForwardDelete, Delete);
BIND(VK_LeftArrow, Left); BIND(VK_RightArrow, Right);
BIND(VK_DownArrow, Down); BIND(VK_UpArrow, Up);
}
#undef BIND
}
return;
}
auto joystick_machine = dynamic_cast<JoystickMachine::Machine *>(_machine);
if(joystick_machine) {
@synchronized(self) {
std::vector<std::unique_ptr<Inputs::Joystick>> &joysticks = joystick_machine->get_joysticks();
if(!joysticks.empty()) {
switch(key) {
case VK_LeftArrow: joysticks[0]->set_digital_input(Inputs::Joystick::DigitalInput::Left, isPressed); break;
case VK_RightArrow: joysticks[0]->set_digital_input(Inputs::Joystick::DigitalInput::Right, isPressed); break;
case VK_UpArrow: joysticks[0]->set_digital_input(Inputs::Joystick::DigitalInput::Up, isPressed); break;
case VK_DownArrow: joysticks[0]->set_digital_input(Inputs::Joystick::DigitalInput::Down, isPressed); break;
default:
joysticks[0]->set_digital_input(Inputs::Joystick::DigitalInput::Fire, isPressed); break;
break;
}
}
}
}
}
- (void)clearAllKeys {
auto keyboard_machine = dynamic_cast<KeyboardMachine::Machine *>(_machine);
if(keyboard_machine) {
@synchronized(self) {
keyboard_machine->get_keyboard().reset_all_keys();
}
}
auto joystick_machine = dynamic_cast<JoystickMachine::Machine *>(_machine);
if(joystick_machine) {
@synchronized(self) {
for(auto &joystick : joystick_machine->get_joysticks()) {
joystick->reset_all_inputs();
}
}
}
}
@end

View File

@ -7,9 +7,8 @@
//
#import "CSMachine.h"
#import "CSKeyboardMachine.h"
@interface CSAmstradCPC : CSMachine <CSKeyboardMachine>
@interface CSAmstradCPC : CSMachine
- (instancetype)init;

View File

@ -55,98 +55,4 @@
- (NSString *)userDefaultsPrefix { return @"amstradCPC"; }
#pragma mark - Keyboard Mapping
- (void)clearAllKeys {
@synchronized(self) {
_amstradCPC->clear_all_keys();
}
}
- (void)setKey:(uint16_t)key isPressed:(BOOL)isPressed {
@synchronized(self) {
switch(key) {
case VK_ANSI_0: _amstradCPC->set_key_state(AmstradCPC::Key::Key0, isPressed); break;
case VK_ANSI_1: _amstradCPC->set_key_state(AmstradCPC::Key::Key1, isPressed); break;
case VK_ANSI_2: _amstradCPC->set_key_state(AmstradCPC::Key::Key2, isPressed); break;
case VK_ANSI_3: _amstradCPC->set_key_state(AmstradCPC::Key::Key3, isPressed); break;
case VK_ANSI_4: _amstradCPC->set_key_state(AmstradCPC::Key::Key4, isPressed); break;
case VK_ANSI_5: _amstradCPC->set_key_state(AmstradCPC::Key::Key5, isPressed); break;
case VK_ANSI_6: _amstradCPC->set_key_state(AmstradCPC::Key::Key6, isPressed); break;
case VK_ANSI_7: _amstradCPC->set_key_state(AmstradCPC::Key::Key7, isPressed); break;
case VK_ANSI_8: _amstradCPC->set_key_state(AmstradCPC::Key::Key8, isPressed); break;
case VK_ANSI_9: _amstradCPC->set_key_state(AmstradCPC::Key::Key9, isPressed); break;
case VK_ANSI_Q: _amstradCPC->set_key_state(AmstradCPC::Key::KeyQ, isPressed); break;
case VK_ANSI_W: _amstradCPC->set_key_state(AmstradCPC::Key::KeyW, isPressed); break;
case VK_ANSI_E: _amstradCPC->set_key_state(AmstradCPC::Key::KeyE, isPressed); break;
case VK_ANSI_R: _amstradCPC->set_key_state(AmstradCPC::Key::KeyR, isPressed); break;
case VK_ANSI_T: _amstradCPC->set_key_state(AmstradCPC::Key::KeyT, isPressed); break;
case VK_ANSI_Y: _amstradCPC->set_key_state(AmstradCPC::Key::KeyY, isPressed); break;
case VK_ANSI_U: _amstradCPC->set_key_state(AmstradCPC::Key::KeyU, isPressed); break;
case VK_ANSI_I: _amstradCPC->set_key_state(AmstradCPC::Key::KeyI, isPressed); break;
case VK_ANSI_O: _amstradCPC->set_key_state(AmstradCPC::Key::KeyO, isPressed); break;
case VK_ANSI_P: _amstradCPC->set_key_state(AmstradCPC::Key::KeyP, isPressed); break;
case VK_ANSI_A: _amstradCPC->set_key_state(AmstradCPC::Key::KeyA, isPressed); break;
case VK_ANSI_S: _amstradCPC->set_key_state(AmstradCPC::Key::KeyS, isPressed); break;
case VK_ANSI_D: _amstradCPC->set_key_state(AmstradCPC::Key::KeyD, isPressed); break;
case VK_ANSI_F: _amstradCPC->set_key_state(AmstradCPC::Key::KeyF, isPressed); break;
case VK_ANSI_G: _amstradCPC->set_key_state(AmstradCPC::Key::KeyG, isPressed); break;
case VK_ANSI_H: _amstradCPC->set_key_state(AmstradCPC::Key::KeyH, isPressed); break;
case VK_ANSI_J: _amstradCPC->set_key_state(AmstradCPC::Key::KeyJ, isPressed); break;
case VK_ANSI_K: _amstradCPC->set_key_state(AmstradCPC::Key::KeyK, isPressed); break;
case VK_ANSI_L: _amstradCPC->set_key_state(AmstradCPC::Key::KeyL, isPressed); break;
case VK_ANSI_Z: _amstradCPC->set_key_state(AmstradCPC::Key::KeyZ, isPressed); break;
case VK_ANSI_X: _amstradCPC->set_key_state(AmstradCPC::Key::KeyX, isPressed); break;
case VK_ANSI_C: _amstradCPC->set_key_state(AmstradCPC::Key::KeyC, isPressed); break;
case VK_ANSI_V: _amstradCPC->set_key_state(AmstradCPC::Key::KeyV, isPressed); break;
case VK_ANSI_B: _amstradCPC->set_key_state(AmstradCPC::Key::KeyB, isPressed); break;
case VK_ANSI_N: _amstradCPC->set_key_state(AmstradCPC::Key::KeyN, isPressed); break;
case VK_ANSI_M: _amstradCPC->set_key_state(AmstradCPC::Key::KeyM, isPressed); break;
case VK_Space: _amstradCPC->set_key_state(AmstradCPC::Key::KeySpace, isPressed); break;
case VK_ANSI_Grave: _amstradCPC->set_key_state(AmstradCPC::Key::KeyCopy, isPressed); break;
case VK_Return: _amstradCPC->set_key_state(AmstradCPC::Key::KeyReturn, isPressed); break;
case VK_ANSI_Minus: _amstradCPC->set_key_state(AmstradCPC::Key::KeyMinus, isPressed); break;
case VK_RightArrow: _amstradCPC->set_key_state(AmstradCPC::Key::KeyRight, isPressed); break;
case VK_LeftArrow: _amstradCPC->set_key_state(AmstradCPC::Key::KeyLeft, isPressed); break;
case VK_DownArrow: _amstradCPC->set_key_state(AmstradCPC::Key::KeyDown, isPressed); break;
case VK_UpArrow: _amstradCPC->set_key_state(AmstradCPC::Key::KeyUp, isPressed); break;
case VK_Delete: _amstradCPC->set_key_state(AmstradCPC::Key::KeyDelete, isPressed); break;
case VK_Escape: _amstradCPC->set_key_state(AmstradCPC::Key::KeyEscape, isPressed); break;
case VK_ANSI_Comma: _amstradCPC->set_key_state(AmstradCPC::Key::KeyComma, isPressed); break;
case VK_ANSI_Period: _amstradCPC->set_key_state(AmstradCPC::Key::KeyFullStop, isPressed); break;
case VK_ANSI_Semicolon:
_amstradCPC->set_key_state(AmstradCPC::Key::KeySemicolon, isPressed); break;
case VK_ANSI_Quote: _amstradCPC->set_key_state(AmstradCPC::Key::KeyColon, isPressed); break;
case VK_ANSI_Slash: _amstradCPC->set_key_state(AmstradCPC::Key::KeyForwardSlash, isPressed); break;
case VK_ANSI_Backslash: _amstradCPC->set_key_state(AmstradCPC::Key::KeyBackSlash, isPressed); break;
case VK_Shift: _amstradCPC->set_key_state(AmstradCPC::Key::KeyShift, isPressed); break;
case VK_Control: _amstradCPC->set_key_state(AmstradCPC::Key::KeyControl, isPressed); break;
case VK_F1: _amstradCPC->set_key_state(AmstradCPC::Key::KeyF1, isPressed); break;
case VK_F2: _amstradCPC->set_key_state(AmstradCPC::Key::KeyF2, isPressed); break;
case VK_F3: _amstradCPC->set_key_state(AmstradCPC::Key::KeyF3, isPressed); break;
case VK_F4: _amstradCPC->set_key_state(AmstradCPC::Key::KeyF4, isPressed); break;
case VK_F5: _amstradCPC->set_key_state(AmstradCPC::Key::KeyF5, isPressed); break;
case VK_F6: _amstradCPC->set_key_state(AmstradCPC::Key::KeyF6, isPressed); break;
case VK_F7: _amstradCPC->set_key_state(AmstradCPC::Key::KeyF7, isPressed); break;
case VK_F8: _amstradCPC->set_key_state(AmstradCPC::Key::KeyF8, isPressed); break;
case VK_F9: _amstradCPC->set_key_state(AmstradCPC::Key::KeyF9, isPressed); break;
case VK_F10: _amstradCPC->set_key_state(AmstradCPC::Key::KeyF0, isPressed); break;
case VK_F12: _amstradCPC->set_key_state(AmstradCPC::Key::KeyFDot, isPressed); break;
default:
// printf("%02x\n", key);
break;
}
}
}
@end

View File

@ -8,9 +8,8 @@
#include "CSMachine.h"
#include "Atari2600Inputs.h"
#import "CSJoystickMachine.h"
@interface CSAtari2600 : CSMachine <CSJoystickMachine>
@interface CSAtari2600 : CSMachine
- (instancetype)init;

View File

@ -24,26 +24,6 @@
return self;
}
- (void)setDirection:(CSJoystickDirection)direction onPad:(NSUInteger)pad isPressed:(BOOL)isPressed {
Atari2600DigitalInput input;
switch(direction)
{
case CSJoystickDirectionUp: input = pad ? Atari2600DigitalInputJoy2Up : Atari2600DigitalInputJoy1Up; break;
case CSJoystickDirectionDown: input = pad ? Atari2600DigitalInputJoy2Down : Atari2600DigitalInputJoy1Down; break;
case CSJoystickDirectionLeft: input = pad ? Atari2600DigitalInputJoy2Left : Atari2600DigitalInputJoy1Left; break;
case CSJoystickDirectionRight: input = pad ? Atari2600DigitalInputJoy2Right : Atari2600DigitalInputJoy1Right; break;
}
@synchronized(self) {
_atari2600->set_digital_input(input, isPressed ? true : false);
}
}
- (void)setButtonAtIndex:(NSUInteger)button onPad:(NSUInteger)pad isPressed:(BOOL)isPressed {
@synchronized(self) {
_atari2600->set_digital_input(pad ? Atari2600DigitalInputJoy2Fire : Atari2600DigitalInputJoy1Fire, isPressed ? true : false);
}
}
- (void)setResetLineEnabled:(BOOL)enabled {
@synchronized(self) {
_atari2600->set_reset_switch(enabled ? true : false);

View File

@ -7,10 +7,9 @@
//
#import "CSMachine.h"
#import "CSKeyboardMachine.h"
#import "CSFastLoading.h"
@interface CSElectron : CSMachine <CSKeyboardMachine, CSFastLoading>
@interface CSElectron : CSMachine <CSFastLoading>
- (instancetype)init;

View File

@ -57,94 +57,6 @@
}
}
#pragma mark - Keyboard Mapping
- (void)clearAllKeys {
@synchronized(self) {
_electron->clear_all_keys();
}
}
- (void)setKey:(uint16_t)key isPressed:(BOOL)isPressed {
@synchronized(self) {
switch(key)
{
case VK_ANSI_0: _electron->set_key_state(Electron::Key::Key0, isPressed); break;
case VK_ANSI_1: _electron->set_key_state(Electron::Key::Key1, isPressed); break;
case VK_ANSI_2: _electron->set_key_state(Electron::Key::Key2, isPressed); break;
case VK_ANSI_3: _electron->set_key_state(Electron::Key::Key3, isPressed); break;
case VK_ANSI_4: _electron->set_key_state(Electron::Key::Key4, isPressed); break;
case VK_ANSI_5: _electron->set_key_state(Electron::Key::Key5, isPressed); break;
case VK_ANSI_6: _electron->set_key_state(Electron::Key::Key6, isPressed); break;
case VK_ANSI_7: _electron->set_key_state(Electron::Key::Key7, isPressed); break;
case VK_ANSI_8: _electron->set_key_state(Electron::Key::Key8, isPressed); break;
case VK_ANSI_9: _electron->set_key_state(Electron::Key::Key9, isPressed); break;
case VK_ANSI_Q: _electron->set_key_state(Electron::Key::KeyQ, isPressed); break;
case VK_ANSI_W: _electron->set_key_state(Electron::Key::KeyW, isPressed); break;
case VK_ANSI_E: _electron->set_key_state(Electron::Key::KeyE, isPressed); break;
case VK_ANSI_R: _electron->set_key_state(Electron::Key::KeyR, isPressed); break;
case VK_ANSI_T: _electron->set_key_state(Electron::Key::KeyT, isPressed); break;
case VK_ANSI_Y: _electron->set_key_state(Electron::Key::KeyY, isPressed); break;
case VK_ANSI_U: _electron->set_key_state(Electron::Key::KeyU, isPressed); break;
case VK_ANSI_I: _electron->set_key_state(Electron::Key::KeyI, isPressed); break;
case VK_ANSI_O: _electron->set_key_state(Electron::Key::KeyO, isPressed); break;
case VK_ANSI_P: _electron->set_key_state(Electron::Key::KeyP, isPressed); break;
case VK_ANSI_A: _electron->set_key_state(Electron::Key::KeyA, isPressed); break;
case VK_ANSI_S: _electron->set_key_state(Electron::Key::KeyS, isPressed); break;
case VK_ANSI_D: _electron->set_key_state(Electron::Key::KeyD, isPressed); break;
case VK_ANSI_F: _electron->set_key_state(Electron::Key::KeyF, isPressed); break;
case VK_ANSI_G: _electron->set_key_state(Electron::Key::KeyG, isPressed); break;
case VK_ANSI_H: _electron->set_key_state(Electron::Key::KeyH, isPressed); break;
case VK_ANSI_J: _electron->set_key_state(Electron::Key::KeyJ, isPressed); break;
case VK_ANSI_K: _electron->set_key_state(Electron::Key::KeyK, isPressed); break;
case VK_ANSI_L: _electron->set_key_state(Electron::Key::KeyL, isPressed); break;
case VK_ANSI_Z: _electron->set_key_state(Electron::Key::KeyZ, isPressed); break;
case VK_ANSI_X: _electron->set_key_state(Electron::Key::KeyX, isPressed); break;
case VK_ANSI_C: _electron->set_key_state(Electron::Key::KeyC, isPressed); break;
case VK_ANSI_V: _electron->set_key_state(Electron::Key::KeyV, isPressed); break;
case VK_ANSI_B: _electron->set_key_state(Electron::Key::KeyB, isPressed); break;
case VK_ANSI_N: _electron->set_key_state(Electron::Key::KeyN, isPressed); break;
case VK_ANSI_M: _electron->set_key_state(Electron::Key::KeyM, isPressed); break;
case VK_Space: _electron->set_key_state(Electron::Key::KeySpace, isPressed); break;
case VK_ANSI_Grave:
case VK_ANSI_Backslash:
_electron->set_key_state(Electron::Key::KeyCopy, isPressed); break;
case VK_Return: _electron->set_key_state(Electron::Key::KeyReturn, isPressed); break;
case VK_ANSI_Minus: _electron->set_key_state(Electron::Key::KeyMinus, isPressed); break;
case VK_RightArrow: _electron->set_key_state(Electron::Key::KeyRight, isPressed); break;
case VK_LeftArrow: _electron->set_key_state(Electron::Key::KeyLeft, isPressed); break;
case VK_DownArrow: _electron->set_key_state(Electron::Key::KeyDown, isPressed); break;
case VK_UpArrow: _electron->set_key_state(Electron::Key::KeyUp, isPressed); break;
case VK_Delete: _electron->set_key_state(Electron::Key::KeyDelete, isPressed); break;
case VK_Escape: _electron->set_key_state(Electron::Key::KeyEscape, isPressed); break;
case VK_ANSI_Comma: _electron->set_key_state(Electron::Key::KeyComma, isPressed); break;
case VK_ANSI_Period: _electron->set_key_state(Electron::Key::KeyFullStop, isPressed); break;
case VK_ANSI_Semicolon:
_electron->set_key_state(Electron::Key::KeySemiColon, isPressed); break;
case VK_ANSI_Quote: _electron->set_key_state(Electron::Key::KeyColon, isPressed); break;
case VK_ANSI_Slash: _electron->set_key_state(Electron::Key::KeySlash, isPressed); break;
case VK_Shift: _electron->set_key_state(Electron::Key::KeyShift, isPressed); break;
case VK_Control: _electron->set_key_state(Electron::Key::KeyControl, isPressed); break;
case VK_Command:
case VK_Option: _electron->set_key_state(Electron::Key::KeyFunc, isPressed); break;
case VK_F12: _electron->set_key_state(Electron::Key::KeyBreak, isPressed); break;
default:
// printf("%02x\n", key);
break;
}
}
}
- (NSString *)userDefaultsPrefix { return @"electron"; }
#pragma mark - Options

View File

@ -7,10 +7,9 @@
//
#import "CSMachine.h"
#import "CSKeyboardMachine.h"
#import "CSFastLoading.h"
@interface CSOric : CSMachine <CSKeyboardMachine, CSFastLoading>
@interface CSOric : CSMachine <CSFastLoading>
- (instancetype)init;

View File

@ -43,99 +43,6 @@
return [[NSBundle mainBundle] dataForResource:name withExtension:@"rom" subdirectory:@"ROMImages/Oric"];
}
#pragma mark - CSKeyboardMachine
- (void)setKey:(uint16_t)key isPressed:(BOOL)isPressed {
@synchronized(self) {
switch(key) {
case VK_ANSI_0: _oric->set_key_state(Oric::Key::Key0, isPressed); break;
case VK_ANSI_1: _oric->set_key_state(Oric::Key::Key1, isPressed); break;
case VK_ANSI_2: _oric->set_key_state(Oric::Key::Key2, isPressed); break;
case VK_ANSI_3: _oric->set_key_state(Oric::Key::Key3, isPressed); break;
case VK_ANSI_4: _oric->set_key_state(Oric::Key::Key4, isPressed); break;
case VK_ANSI_5: _oric->set_key_state(Oric::Key::Key5, isPressed); break;
case VK_ANSI_6: _oric->set_key_state(Oric::Key::Key6, isPressed); break;
case VK_ANSI_7: _oric->set_key_state(Oric::Key::Key7, isPressed); break;
case VK_ANSI_8: _oric->set_key_state(Oric::Key::Key8, isPressed); break;
case VK_ANSI_9: _oric->set_key_state(Oric::Key::Key9, isPressed); break;
case VK_ANSI_Q: _oric->set_key_state(Oric::Key::KeyQ, isPressed); break;
case VK_ANSI_W: _oric->set_key_state(Oric::Key::KeyW, isPressed); break;
case VK_ANSI_E: _oric->set_key_state(Oric::Key::KeyE, isPressed); break;
case VK_ANSI_R: _oric->set_key_state(Oric::Key::KeyR, isPressed); break;
case VK_ANSI_T: _oric->set_key_state(Oric::Key::KeyT, isPressed); break;
case VK_ANSI_Y: _oric->set_key_state(Oric::Key::KeyY, isPressed); break;
case VK_ANSI_U: _oric->set_key_state(Oric::Key::KeyU, isPressed); break;
case VK_ANSI_I: _oric->set_key_state(Oric::Key::KeyI, isPressed); break;
case VK_ANSI_O: _oric->set_key_state(Oric::Key::KeyO, isPressed); break;
case VK_ANSI_P: _oric->set_key_state(Oric::Key::KeyP, isPressed); break;
case VK_ANSI_A: _oric->set_key_state(Oric::Key::KeyA, isPressed); break;
case VK_ANSI_S: _oric->set_key_state(Oric::Key::KeyS, isPressed); break;
case VK_ANSI_D: _oric->set_key_state(Oric::Key::KeyD, isPressed); break;
case VK_ANSI_F: _oric->set_key_state(Oric::Key::KeyF, isPressed); break;
case VK_ANSI_G: _oric->set_key_state(Oric::Key::KeyG, isPressed); break;
case VK_ANSI_H: _oric->set_key_state(Oric::Key::KeyH, isPressed); break;
case VK_ANSI_J: _oric->set_key_state(Oric::Key::KeyJ, isPressed); break;
case VK_ANSI_K: _oric->set_key_state(Oric::Key::KeyK, isPressed); break;
case VK_ANSI_L: _oric->set_key_state(Oric::Key::KeyL, isPressed); break;
case VK_ANSI_Z: _oric->set_key_state(Oric::Key::KeyZ, isPressed); break;
case VK_ANSI_X: _oric->set_key_state(Oric::Key::KeyX, isPressed); break;
case VK_ANSI_C: _oric->set_key_state(Oric::Key::KeyC, isPressed); break;
case VK_ANSI_V: _oric->set_key_state(Oric::Key::KeyV, isPressed); break;
case VK_ANSI_B: _oric->set_key_state(Oric::Key::KeyB, isPressed); break;
case VK_ANSI_N: _oric->set_key_state(Oric::Key::KeyN, isPressed); break;
case VK_ANSI_M: _oric->set_key_state(Oric::Key::KeyM, isPressed); break;
case VK_Space: _oric->set_key_state(Oric::Key::KeySpace, isPressed); break;
case VK_Return: _oric->set_key_state(Oric::Key::KeyReturn, isPressed); break;
case VK_ANSI_Minus: _oric->set_key_state(Oric::Key::KeyMinus, isPressed); break;
case VK_ANSI_Equal: _oric->set_key_state(Oric::Key::KeyEquals, isPressed); break;
case VK_ANSI_Backslash:
_oric->set_key_state(Oric::Key::KeyBackSlash, isPressed); break;
case VK_ANSI_Slash: _oric->set_key_state(Oric::Key::KeyForwardSlash, isPressed); break;
case VK_ANSI_LeftBracket:
_oric->set_key_state(Oric::Key::KeyOpenSquare, isPressed); break;
case VK_ANSI_RightBracket:
_oric->set_key_state(Oric::Key::KeyCloseSquare, isPressed); break;
case VK_ANSI_Quote: _oric->set_key_state(Oric::Key::KeyQuote, isPressed); break;
case VK_RightArrow: _oric->set_key_state(Oric::Key::KeyRight, isPressed); break;
case VK_LeftArrow: _oric->set_key_state(Oric::Key::KeyLeft, isPressed); break;
case VK_DownArrow: _oric->set_key_state(Oric::Key::KeyDown, isPressed); break;
case VK_UpArrow: _oric->set_key_state(Oric::Key::KeyUp, isPressed); break;
case VK_Delete: _oric->set_key_state(Oric::Key::KeyDelete, isPressed); break;
case VK_Escape: _oric->set_key_state(Oric::Key::KeyEscape, isPressed); break;
case VK_ANSI_Comma: _oric->set_key_state(Oric::Key::KeyComma, isPressed); break;
case VK_ANSI_Period: _oric->set_key_state(Oric::Key::KeyFullStop, isPressed); break;
case VK_ANSI_Semicolon: _oric->set_key_state(Oric::Key::KeySemiColon, isPressed); break;
case VK_Shift:
_oric->set_key_state(Oric::Key::KeyLeftShift, isPressed);
_oric->set_key_state(Oric::Key::KeyRightShift, isPressed);
break;
case VK_RightShift: _oric->set_key_state(Oric::Key::KeyRightShift, isPressed); break;
case VK_Control: _oric->set_key_state(Oric::Key::KeyControl, isPressed); break;
case VK_ANSI_Grave:
case VK_F12: _oric->set_key_state(Oric::Key::KeyNMI, isPressed); break;
default:
printf("%02x\n", key);
break;
}
}
}
- (void)clearAllKeys {
@synchronized(self) {
_oric->clear_all_keys();
}
}
#pragma mark - Options
- (void)setUseFastLoadingHack:(BOOL)useFastLoadingHack {

View File

@ -7,7 +7,6 @@
//
#import "CSMachine.h"
#import "CSKeyboardMachine.h"
#import "CSFastLoading.h"
typedef NS_ENUM(NSInteger, CSVic20Country)
@ -26,7 +25,7 @@ typedef NS_ENUM(NSInteger, CSVic20MemorySize)
CSVic20MemorySize32Kb,
};
@interface CSVic20 : CSMachine <CSKeyboardMachine, CSFastLoading>
@interface CSVic20 : CSMachine <CSFastLoading>
- (instancetype)init;

View File

@ -68,101 +68,15 @@ using namespace Commodore::Vic20;
#pragma mark - Keyboard map
- (void)setKey:(uint16_t)key isPressed:(BOOL)isPressed {
static NSDictionary<NSNumber *, NSNumber *> *vicKeysByKeys = @{
@(VK_ANSI_1): @(Key::Key1), @(VK_ANSI_2): @(Key::Key2),
@(VK_ANSI_3): @(Key::Key3), @(VK_ANSI_4): @(Key::Key4),
@(VK_ANSI_5): @(Key::Key5), @(VK_ANSI_6): @(Key::Key6),
@(VK_ANSI_7): @(Key::Key7), @(VK_ANSI_8): @(Key::Key8),
@(VK_ANSI_9): @(Key::Key9), @(VK_ANSI_0): @(Key::Key0),
@(VK_ANSI_Q): @(Key::KeyQ), @(VK_ANSI_W): @(Key::KeyW),
@(VK_ANSI_E): @(Key::KeyE), @(VK_ANSI_R): @(Key::KeyR),
@(VK_ANSI_T): @(Key::KeyT), @(VK_ANSI_Y): @(Key::KeyY),
@(VK_ANSI_U): @(Key::KeyU), @(VK_ANSI_I): @(Key::KeyI),
@(VK_ANSI_O): @(Key::KeyO), @(VK_ANSI_P): @(Key::KeyP),
@(VK_ANSI_A): @(Key::KeyA), @(VK_ANSI_S): @(Key::KeyS),
@(VK_ANSI_D): @(Key::KeyD), @(VK_ANSI_F): @(Key::KeyF),
@(VK_ANSI_G): @(Key::KeyG), @(VK_ANSI_H): @(Key::KeyH),
@(VK_ANSI_J): @(Key::KeyJ), @(VK_ANSI_K): @(Key::KeyK),
@(VK_ANSI_L): @(Key::KeyL), @(VK_ANSI_Z): @(Key::KeyZ),
@(VK_ANSI_X): @(Key::KeyX), @(VK_ANSI_C): @(Key::KeyC),
@(VK_ANSI_V): @(Key::KeyV), @(VK_ANSI_B): @(Key::KeyB),
@(VK_ANSI_N): @(Key::KeyN), @(VK_ANSI_M): @(Key::KeyM),
@(VK_Space): @(Key::KeySpace),
@(VK_Return): @(Key::KeyReturn),
@(VK_Delete): @(Key::KeyDelete),
@(VK_ANSI_Comma): @(Key::KeyComma),
@(VK_ANSI_Period): @(Key::KeyFullStop),
@(VK_ANSI_Minus): @(Key::KeyDash),
@(VK_ANSI_Equal): @(Key::KeyEquals),
@(VK_ANSI_Semicolon): @(Key::KeyColon),
@(VK_ANSI_Quote): @(Key::KeySemicolon),
@(VK_ANSI_Slash): @(Key::KeySlash),
@(VK_Option): @(Key::KeyCBM),
@(VK_Control): @(Key::KeyControl),
@(VK_F1): @(Key::KeyF1), @(VK_F3): @(Key::KeyF3),
@(VK_F5): @(Key::KeyF5), @(VK_F7): @(Key::KeyF7),
@(VK_ANSI_Grave): @(Key::KeyLeft),
@(VK_Tab): @(Key::KeyRunStop),
@(VK_ANSI_LeftBracket): @(Key::KeyAt),
@(VK_ANSI_RightBracket): @(Key::KeyAsterisk),
@(VK_ANSI_Backslash): @(Key::KeyUp),
@(VK_RightArrow): @(Key::KeyRight),
@(VK_DownArrow): @(Key::KeyDown),
};
// Not yet mapped:
// KeyHome
// KeyPlus
// KeyGBP
if(key == VK_Tab && isPressed) {
_joystickMode ^= YES;
}
@synchronized(self) {
if(_joystickMode) {
switch(key) {
case VK_UpArrow: _vic20->set_joystick_state(JoystickInput::Up, isPressed); break;
case VK_DownArrow: _vic20->set_joystick_state(JoystickInput::Down, isPressed); break;
case VK_LeftArrow: _vic20->set_joystick_state(JoystickInput::Left, isPressed); break;
case VK_RightArrow: _vic20->set_joystick_state(JoystickInput::Right, isPressed); break;
case VK_ANSI_A: _vic20->set_joystick_state(JoystickInput::Fire, isPressed); break;
}
} else {
switch(key) {
default: {
NSNumber *targetKey = vicKeysByKeys[@(key)];
if(targetKey)
{
_vic20->set_key_state((Key)targetKey.integerValue, isPressed);
}
else
{
NSLog(@"Unmapped: %02x", key);
}
} break;
case VK_Shift:
// Yuck
_vic20->set_key_state(Key::KeyLShift, isPressed);
_vic20->set_key_state(Key::KeyRShift, isPressed);
break;
}
/*- (void)setKey:(uint16_t)key isPressed:(BOOL)isPressed {
switch(key) {
case VK_UpArrow: _vic20->set_joystick_state(JoystickInput::Up, isPressed); break;
case VK_DownArrow: _vic20->set_joystick_state(JoystickInput::Down, isPressed); break;
case VK_LeftArrow: _vic20->set_joystick_state(JoystickInput::Left, isPressed); break;
case VK_RightArrow: _vic20->set_joystick_state(JoystickInput::Right, isPressed); break;
case VK_ANSI_A: _vic20->set_joystick_state(JoystickInput::Fire, isPressed); break;
}
}
}
- (void)clearAllKeys {
@synchronized(self) {
_vic20->clear_all_keys();
}
}
}*/
#pragma mark - Public configuration options

View File

@ -7,10 +7,9 @@
//
#import "CSMachine.h"
#import "CSKeyboardMachine.h"
#import "CSFastLoading.h"
@interface CSZX8081 : CSMachine <CSKeyboardMachine, CSFastLoading>
@interface CSZX8081 : CSMachine <CSFastLoading>
@property (nonatomic, assign) BOOL useFastLoadingHack;

View File

@ -34,69 +34,6 @@
return [[NSBundle mainBundle] dataForResource:name withExtension:@"rom" subdirectory:@"ROMImages/ZX8081"];
}
#pragma mark - Keyboard Mapping
- (void)clearAllKeys {
@synchronized(self) {
_zx8081->clear_all_keys();
}
}
- (void)setKey:(uint16_t)key isPressed:(BOOL)isPressed {
@synchronized(self) {
switch(key) {
case VK_ANSI_0: _zx8081->set_key_state(ZX8081::Key::Key0, isPressed); break;
case VK_ANSI_1: _zx8081->set_key_state(ZX8081::Key::Key1, isPressed); break;
case VK_ANSI_2: _zx8081->set_key_state(ZX8081::Key::Key2, isPressed); break;
case VK_ANSI_3: _zx8081->set_key_state(ZX8081::Key::Key3, isPressed); break;
case VK_ANSI_4: _zx8081->set_key_state(ZX8081::Key::Key4, isPressed); break;
case VK_ANSI_5: _zx8081->set_key_state(ZX8081::Key::Key5, isPressed); break;
case VK_ANSI_6: _zx8081->set_key_state(ZX8081::Key::Key6, isPressed); break;
case VK_ANSI_7: _zx8081->set_key_state(ZX8081::Key::Key7, isPressed); break;
case VK_ANSI_8: _zx8081->set_key_state(ZX8081::Key::Key8, isPressed); break;
case VK_ANSI_9: _zx8081->set_key_state(ZX8081::Key::Key9, isPressed); break;
case VK_ANSI_Q: _zx8081->set_key_state(ZX8081::Key::KeyQ, isPressed); break;
case VK_ANSI_W: _zx8081->set_key_state(ZX8081::Key::KeyW, isPressed); break;
case VK_ANSI_E: _zx8081->set_key_state(ZX8081::Key::KeyE, isPressed); break;
case VK_ANSI_R: _zx8081->set_key_state(ZX8081::Key::KeyR, isPressed); break;
case VK_ANSI_T: _zx8081->set_key_state(ZX8081::Key::KeyT, isPressed); break;
case VK_ANSI_Y: _zx8081->set_key_state(ZX8081::Key::KeyY, isPressed); break;
case VK_ANSI_U: _zx8081->set_key_state(ZX8081::Key::KeyU, isPressed); break;
case VK_ANSI_I: _zx8081->set_key_state(ZX8081::Key::KeyI, isPressed); break;
case VK_ANSI_O: _zx8081->set_key_state(ZX8081::Key::KeyO, isPressed); break;
case VK_ANSI_P: _zx8081->set_key_state(ZX8081::Key::KeyP, isPressed); break;
case VK_ANSI_A: _zx8081->set_key_state(ZX8081::Key::KeyA, isPressed); break;
case VK_ANSI_S: _zx8081->set_key_state(ZX8081::Key::KeyS, isPressed); break;
case VK_ANSI_D: _zx8081->set_key_state(ZX8081::Key::KeyD, isPressed); break;
case VK_ANSI_F: _zx8081->set_key_state(ZX8081::Key::KeyF, isPressed); break;
case VK_ANSI_G: _zx8081->set_key_state(ZX8081::Key::KeyG, isPressed); break;
case VK_ANSI_H: _zx8081->set_key_state(ZX8081::Key::KeyH, isPressed); break;
case VK_ANSI_J: _zx8081->set_key_state(ZX8081::Key::KeyJ, isPressed); break;
case VK_ANSI_K: _zx8081->set_key_state(ZX8081::Key::KeyK, isPressed); break;
case VK_ANSI_L: _zx8081->set_key_state(ZX8081::Key::KeyL, isPressed); break;
case VK_ANSI_Z: _zx8081->set_key_state(ZX8081::Key::KeyZ, isPressed); break;
case VK_ANSI_X: _zx8081->set_key_state(ZX8081::Key::KeyX, isPressed); break;
case VK_ANSI_C: _zx8081->set_key_state(ZX8081::Key::KeyC, isPressed); break;
case VK_ANSI_V: _zx8081->set_key_state(ZX8081::Key::KeyV, isPressed); break;
case VK_ANSI_B: _zx8081->set_key_state(ZX8081::Key::KeyB, isPressed); break;
case VK_ANSI_N: _zx8081->set_key_state(ZX8081::Key::KeyN, isPressed); break;
case VK_ANSI_M: _zx8081->set_key_state(ZX8081::Key::KeyM, isPressed); break;
case VK_Shift:
case VK_RightShift:
_zx8081->set_key_state(ZX8081::Key::KeyShift, isPressed); break;
break;
case VK_ANSI_Period:_zx8081->set_key_state(ZX8081::Key::KeyDot, isPressed); break;
case VK_Return: _zx8081->set_key_state(ZX8081::Key::KeyEnter, isPressed); break;
case VK_Space: _zx8081->set_key_state(ZX8081::Key::KeySpace, isPressed); break;
}
}
}
- (NSString *)userDefaultsPrefix { return @"zx8081"; }
#pragma mark - Options

View File

@ -72,7 +72,7 @@ uint8_t *TextureBuilder::allocate_write_area(size_t required_length, size_t requ
size_t alignment_offset = (required_alignment - ((write_areas_start_x_ + 1) % required_alignment)) % required_alignment;
if(write_areas_start_x_ + required_length + 2 + alignment_offset > InputBufferBuilderWidth) {
write_areas_start_x_ = 0;
alignment_offset = (required_alignment - 1) % required_alignment;
alignment_offset = required_alignment - 1;
write_areas_start_y_ = (write_areas_start_y_ + 1) % InputBufferBuilderHeight;
if(write_areas_start_y_ == first_unsubmitted_y_) {