diff --git a/Machines/ZX8081/ZX8081.cpp b/Machines/ZX8081/ZX8081.cpp index 9b3b89882..f08733ce0 100644 --- a/Machines/ZX8081/ZX8081.cpp +++ b/Machines/ZX8081/ZX8081.cpp @@ -16,7 +16,8 @@ Machine::Machine() : vsync_(false), hsync_(false), ram_(1024), - line_data_(nullptr) { + line_data_(nullptr), + key_states_{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} { // run at 3.25 Mhz set_clock_rate(3250000); Memory::Fuzz(ram_); @@ -34,13 +35,20 @@ int Machine::perform_machine_cycle(const CPU::Z80::MachineCycle &cycle) { } break; - case CPU::Z80::BusOperation::Input: + case CPU::Z80::BusOperation::Input: { + uint8_t value = 0xff; if((address&7) == 6) { set_vsync(true); line_counter_ = 0; + + uint16_t mask = 0x100; + for(int c = 0; c < 8; c++) { + if(!(address & mask)) value &= key_states_[c]; + mask <<= 1; + } } - *cycle.value = 0xff; - break; + *cycle.value = value; + } break; case CPU::Z80::BusOperation::Interrupt: set_hsync(true); @@ -189,9 +197,22 @@ void Machine::output_byte(uint8_t byte) { void Machine::setup_output(float aspect_ratio) { crt_.reset(new Outputs::CRT::CRT(210 * 2, 1, Outputs::CRT::DisplayType::PAL50, 1)); - crt_->set_rgb_sampling_function( - "vec3 rgb_sample(usampler2D sampler, vec2 coordinate, vec2 icoordinate)" + crt_->set_composite_sampling_function( + "float composite_sample(usampler2D sampler, vec2 coordinate, vec2 icoordinate, float phase, float amplitude)" "{" - "return vec3(float(texture(texID, coordinate).r) / 255.0);" + "return float(texture(texID, coordinate).r) / 255.0;" "}"); } + +#pragma mark - Keyboard + +void Machine::set_key_state(uint16_t key, bool isPressed) { + if(isPressed) + key_states_[key >> 8] &= (uint8_t)(~key); + else + key_states_[key >> 8] |= (uint8_t)key; +} + +void Machine::clear_all_keys() { + memset(key_states_, 0xff, 8); +} diff --git a/Machines/ZX8081/ZX8081.hpp b/Machines/ZX8081/ZX8081.hpp index 44d9f58e1..2a873ba6f 100644 --- a/Machines/ZX8081/ZX8081.hpp +++ b/Machines/ZX8081/ZX8081.hpp @@ -23,6 +23,17 @@ enum ROMType: uint8_t { ZX80, ZX81 }; +enum Key: uint16_t { + KeyShift = 0x0000 | 0x01, KeyZ = 0x0000 | 0x02, KeyX = 0x0000 | 0x04, KeyC = 0x0000 | 0x08, KeyV = 0x0000 | 0x10, + KeyA = 0x0100 | 0x01, KeyS = 0x0100 | 0x02, KeyD = 0x0100 | 0x04, KeyF = 0x0100 | 0x08, KeyG = 0x0100 | 0x10, + KeyQ = 0x0200 | 0x01, KeyW = 0x0200 | 0x02, KeyE = 0x0200 | 0x04, KeyR = 0x0200 | 0x08, KeyT = 0x0200 | 0x10, + Key1 = 0x0300 | 0x01, Key2 = 0x0300 | 0x02, Key3 = 0x0300 | 0x04, Key4 = 0x0300 | 0x08, Key5 = 0x0300 | 0x10, + Key0 = 0x0400 | 0x01, Key9 = 0x0400 | 0x02, Key8 = 0x0400 | 0x04, Key7 = 0x0400 | 0x08, Key6 = 0x0400 | 0x10, + KeyP = 0x0500 | 0x01, KeyO = 0x0500 | 0x02, KeyI = 0x0500 | 0x04, KeyU = 0x0500 | 0x08, KeyY = 0x0500 | 0x10, + KeyEnter = 0x0600 | 0x01, KeyL = 0x0600 | 0x02, KeyK = 0x0600 | 0x04, KeyJ = 0x0600 | 0x08, KeyH = 0x0600 | 0x10, + KeySpace = 0x0700 | 0x01, KeyDot = 0x0700 | 0x02, KeyM = 0x0700 | 0x04, KeyN = 0x0700 | 0x08, KeyB = 0x0700 | 0x10, +}; + class Machine: public CPU::Z80::Processor, public CRTMachine::Machine, @@ -44,6 +55,8 @@ class Machine: void configure_as_target(const StaticAnalyser::Target &target); void set_rom(ROMType type, std::vector data); + void set_key_state(uint16_t key, bool isPressed); + void clear_all_keys(); private: std::shared_ptr crt_; @@ -55,6 +68,8 @@ class Machine: uint8_t *line_data_, *line_data_pointer_; int line_counter_; + uint8_t key_states_[8]; + unsigned int cycles_since_display_update_; void update_display(); void set_vsync(bool sync); diff --git a/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSZX8081.mm b/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSZX8081.mm index c5801d3ce..7a1248818 100644 --- a/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSZX8081.mm +++ b/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSZX8081.mm @@ -15,18 +15,18 @@ #import "NSBundle+DataResource.h" @implementation CSZX8081 { - ZX8081::Machine zx8081; + ZX8081::Machine _zx8081; } - (CRTMachine::Machine * const)machine { - return &zx8081; + return &_zx8081; } - (instancetype)init { self = [super init]; if(self) { - zx8081.set_rom(ZX8081::ROMType::ZX80, [self rom:@"zx80"].stdVector8); - zx8081.set_rom(ZX8081::ROMType::ZX81, [self rom:@"zx81"].stdVector8); + _zx8081.set_rom(ZX8081::ROMType::ZX80, [self rom:@"zx80"].stdVector8); + _zx8081.set_rom(ZX8081::ROMType::ZX81, [self rom:@"zx81"].stdVector8); } return self; } @@ -38,9 +38,65 @@ #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"; }