Workboy emulation (Cocoa only)
This commit is contained in:
parent
e35c22d405
commit
7ff3556bc3
@ -47,7 +47,7 @@ enum model {
|
||||
bool oamUpdating;
|
||||
|
||||
NSMutableData *currentPrinterImageData;
|
||||
enum {GBAccessoryNone, GBAccessoryPrinter} accessory;
|
||||
enum {GBAccessoryNone, GBAccessoryPrinter, GBAccessoryWorkboy} accessory;
|
||||
|
||||
bool rom_warning_issued;
|
||||
|
||||
@ -138,6 +138,16 @@ static void printImage(GB_gameboy_t *gb, uint32_t *image, uint8_t height,
|
||||
[self printImage:image height:height topMargin:top_margin bottomMargin:bottom_margin exposure:exposure];
|
||||
}
|
||||
|
||||
static void setWorkboyTime(GB_gameboy_t *gb, time_t t)
|
||||
{
|
||||
[[NSUserDefaults standardUserDefaults] setInteger:time(NULL) - t forKey:@"GBWorkboyTimeOffset"];
|
||||
}
|
||||
|
||||
static time_t getWorkboyTime(GB_gameboy_t *gb)
|
||||
{
|
||||
return time(NULL) - [[NSUserDefaults standardUserDefaults] integerForKey:@"GBWorkboyTimeOffset"];
|
||||
}
|
||||
|
||||
static void audioCallback(GB_gameboy_t *gb, GB_sample_t *sample)
|
||||
{
|
||||
Document *self = (__bridge Document *)GB_get_user_data(gb);
|
||||
@ -791,6 +801,9 @@ static void rumbleCallback(GB_gameboy_t *gb, double amp)
|
||||
else if ([anItem action] == @selector(connectPrinter:)) {
|
||||
[(NSMenuItem*)anItem setState:accessory == GBAccessoryPrinter];
|
||||
}
|
||||
else if ([anItem action] == @selector(connectWorkboy:)) {
|
||||
[(NSMenuItem*)anItem setState:accessory == GBAccessoryWorkboy];
|
||||
}
|
||||
else if ([anItem action] == @selector(toggleCheats:)) {
|
||||
[(NSMenuItem*)anItem setState:GB_cheats_enabled(&gb)];
|
||||
}
|
||||
@ -1701,6 +1714,14 @@ static void rumbleCallback(GB_gameboy_t *gb, double amp)
|
||||
}];
|
||||
}
|
||||
|
||||
- (IBAction)connectWorkboy:(id)sender
|
||||
{
|
||||
[self performAtomicBlock:^{
|
||||
accessory = GBAccessoryWorkboy;
|
||||
GB_connect_workboy(&gb, setWorkboyTime, getWorkboyTime);
|
||||
}];
|
||||
}
|
||||
|
||||
- (void) updateHighpassFilter
|
||||
{
|
||||
if (GB_is_inited(&gb)) {
|
||||
|
115
Cocoa/GBView.m
115
Cocoa/GBView.m
@ -1,4 +1,5 @@
|
||||
#import <IOKit/pwr_mgt/IOPMLib.h>
|
||||
#import <Carbon/Carbon.h>
|
||||
#import "GBView.h"
|
||||
#import "GBViewGL.h"
|
||||
#import "GBViewMetal.h"
|
||||
@ -8,6 +9,98 @@
|
||||
#define JOYSTICK_HIGH 0x4000
|
||||
#define JOYSTICK_LOW 0x3800
|
||||
|
||||
static const uint8_t workboy_ascii_to_key[] = {
|
||||
['0'] = GB_WORKBOY_0,
|
||||
['`'] = GB_WORKBOY_UMLAUT,
|
||||
['1'] = GB_WORKBOY_1,
|
||||
['2'] = GB_WORKBOY_2,
|
||||
['3'] = GB_WORKBOY_3,
|
||||
['4'] = GB_WORKBOY_4,
|
||||
['5'] = GB_WORKBOY_5,
|
||||
['6'] = GB_WORKBOY_6,
|
||||
['7'] = GB_WORKBOY_7,
|
||||
['8'] = GB_WORKBOY_8,
|
||||
['9'] = GB_WORKBOY_9,
|
||||
|
||||
['\r'] = GB_WORKBOY_ENTER,
|
||||
[3] = GB_WORKBOY_ENTER,
|
||||
|
||||
['!'] = GB_WORKBOY_EXCLAMATION_MARK,
|
||||
['$'] = GB_WORKBOY_DOLLAR,
|
||||
['#'] = GB_WORKBOY_HASH,
|
||||
['~'] = GB_WORKBOY_TILDE,
|
||||
['*'] = GB_WORKBOY_ASTERISK,
|
||||
['+'] = GB_WORKBOY_PLUS,
|
||||
['-'] = GB_WORKBOY_MINUS,
|
||||
['('] = GB_WORKBOY_LEFT_PARENTHESIS,
|
||||
[')'] = GB_WORKBOY_RIGHT_PARENTHESIS,
|
||||
[';'] = GB_WORKBOY_SEMICOLON,
|
||||
[':'] = GB_WORKBOY_COLON,
|
||||
['%'] = GB_WORKBOY_PERCENT,
|
||||
['='] = GB_WORKBOY_EQUAL,
|
||||
[','] = GB_WORKBOY_COMMA,
|
||||
['<'] = GB_WORKBOY_LT,
|
||||
['.'] = GB_WORKBOY_DOT,
|
||||
['>'] = GB_WORKBOY_GT,
|
||||
['/'] = GB_WORKBOY_SLASH,
|
||||
['?'] = GB_WORKBOY_QUESTION_MARK,
|
||||
[' '] = GB_WORKBOY_SPACE,
|
||||
['\''] = GB_WORKBOY_QUOTE,
|
||||
['@'] = GB_WORKBOY_AT,
|
||||
|
||||
['q'] = GB_WORKBOY_Q,
|
||||
['w'] = GB_WORKBOY_W,
|
||||
['e'] = GB_WORKBOY_E,
|
||||
['r'] = GB_WORKBOY_R,
|
||||
['t'] = GB_WORKBOY_T,
|
||||
['y'] = GB_WORKBOY_Y,
|
||||
['u'] = GB_WORKBOY_U,
|
||||
['i'] = GB_WORKBOY_I,
|
||||
['o'] = GB_WORKBOY_O,
|
||||
['p'] = GB_WORKBOY_P,
|
||||
['a'] = GB_WORKBOY_A,
|
||||
['s'] = GB_WORKBOY_S,
|
||||
['d'] = GB_WORKBOY_D,
|
||||
['f'] = GB_WORKBOY_F,
|
||||
['g'] = GB_WORKBOY_G,
|
||||
['h'] = GB_WORKBOY_H,
|
||||
['j'] = GB_WORKBOY_J,
|
||||
['k'] = GB_WORKBOY_K,
|
||||
['l'] = GB_WORKBOY_L,
|
||||
['z'] = GB_WORKBOY_Z,
|
||||
['x'] = GB_WORKBOY_X,
|
||||
['c'] = GB_WORKBOY_C,
|
||||
['v'] = GB_WORKBOY_V,
|
||||
['b'] = GB_WORKBOY_B,
|
||||
['n'] = GB_WORKBOY_N,
|
||||
['m'] = GB_WORKBOY_M,
|
||||
};
|
||||
|
||||
static const uint8_t workboy_vk_to_key[] = {
|
||||
[kVK_F1] = GB_WORKBOY_CLOCK,
|
||||
[kVK_F2] = GB_WORKBOY_TEMPERATURE,
|
||||
[kVK_F3] = GB_WORKBOY_MONEY,
|
||||
[kVK_F4] = GB_WORKBOY_CALCULATOR,
|
||||
[kVK_F5] = GB_WORKBOY_DATE,
|
||||
[kVK_F6] = GB_WORKBOY_CONVERSION,
|
||||
[kVK_F7] = GB_WORKBOY_RECORD,
|
||||
[kVK_F8] = GB_WORKBOY_WORLD,
|
||||
[kVK_F9] = GB_WORKBOY_PHONE,
|
||||
[kVK_F10] = GB_WORKBOY_UNKNOWN,
|
||||
[kVK_Delete] = GB_WORKBOY_BACKSPACE,
|
||||
[kVK_Shift] = GB_WORKBOY_SHIFT_DOWN,
|
||||
[kVK_RightShift] = GB_WORKBOY_SHIFT_DOWN,
|
||||
[kVK_UpArrow] = GB_WORKBOY_UP,
|
||||
[kVK_DownArrow] = GB_WORKBOY_DOWN,
|
||||
[kVK_LeftArrow] = GB_WORKBOY_LEFT,
|
||||
[kVK_RightArrow] = GB_WORKBOY_RIGHT,
|
||||
[kVK_Escape] = GB_WORKBOY_ESCAPE,
|
||||
[kVK_ANSI_KeypadDecimal] = GB_WORKBOY_DECIMAL_POINT,
|
||||
[kVK_ANSI_KeypadClear] = GB_WORKBOY_M,
|
||||
[kVK_ANSI_KeypadMultiply] = GB_WORKBOY_H,
|
||||
[kVK_ANSI_KeypadDivide] = GB_WORKBOY_J,
|
||||
};
|
||||
|
||||
@implementation GBView
|
||||
{
|
||||
uint32_t *image_buffers[3];
|
||||
@ -188,7 +281,20 @@
|
||||
|
||||
-(void)keyDown:(NSEvent *)theEvent
|
||||
{
|
||||
if ([theEvent type] != NSEventTypeFlagsChanged && theEvent.isARepeat) return;
|
||||
unsigned short keyCode = theEvent.keyCode;
|
||||
if (GB_workboy_is_enabled(_gb)) {
|
||||
if (theEvent.keyCode < sizeof(workboy_vk_to_key) && workboy_vk_to_key[theEvent.keyCode]) {
|
||||
GB_workboy_set_key(_gb, workboy_vk_to_key[theEvent.keyCode]);
|
||||
return;
|
||||
}
|
||||
unichar c = [theEvent type] != NSEventTypeFlagsChanged? [theEvent.charactersIgnoringModifiers.lowercaseString characterAtIndex:0] : 0;
|
||||
if (c < sizeof(workboy_ascii_to_key) && workboy_ascii_to_key[c]) {
|
||||
GB_workboy_set_key(_gb, workboy_ascii_to_key[c]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool handled = false;
|
||||
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
@ -232,6 +338,15 @@
|
||||
-(void)keyUp:(NSEvent *)theEvent
|
||||
{
|
||||
unsigned short keyCode = theEvent.keyCode;
|
||||
if (GB_workboy_is_enabled(_gb)) {
|
||||
if (keyCode == kVK_Shift || keyCode == kVK_RightShift) {
|
||||
GB_workboy_set_key(_gb, GB_WORKBOY_SHIFT_UP);
|
||||
}
|
||||
else {
|
||||
GB_workboy_set_key(_gb, GB_WORKBOY_NONE);
|
||||
}
|
||||
|
||||
}
|
||||
bool handled = false;
|
||||
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
|
@ -379,6 +379,12 @@
|
||||
<action selector="connectPrinter:" target="-1" id="tl1-CL-tAw"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Workboy" id="lo9-CX-BJj">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="connectWorkboy:" target="-1" id="6vS-bq-wAX"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
|
@ -1131,8 +1131,9 @@ void GB_disconnect_serial(GB_gameboy_t *gb)
|
||||
gb->serial_transfer_bit_start_callback = NULL;
|
||||
gb->serial_transfer_bit_end_callback = NULL;
|
||||
|
||||
/* Reset any internally-emulated device. Currently, only the printer. */
|
||||
/* Reset any internally-emulated device. */
|
||||
memset(&gb->printer, 0, sizeof(gb->printer));
|
||||
memset(&gb->workboy, 0, sizeof(gb->workboy));
|
||||
}
|
||||
|
||||
bool GB_is_inited(GB_gameboy_t *gb)
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "sgb.h"
|
||||
#include "cheats.h"
|
||||
#include "rumble.h"
|
||||
#include "workboy.h"
|
||||
|
||||
#define GB_STRUCT_VERSION 13
|
||||
|
||||
@ -372,6 +373,7 @@ struct GB_gameboy_internal_s {
|
||||
GB_printer_t printer;
|
||||
uint8_t extra_oam[0xff00 - 0xfea0];
|
||||
uint32_t ram_size; // Different between CGB and DMG
|
||||
GB_workboy_t workboy;
|
||||
);
|
||||
|
||||
/* DMA and HDMA */
|
||||
@ -608,6 +610,9 @@ struct GB_gameboy_internal_s {
|
||||
GB_read_memory_callback_t read_memory_callback;
|
||||
GB_boot_rom_load_callback_t boot_rom_load_callback;
|
||||
GB_print_image_callback_t printer_callback;
|
||||
GB_workboy_set_time_callback workboy_set_time_callback;
|
||||
GB_workboy_get_time_callback workboy_get_time_callback;
|
||||
|
||||
/* IR */
|
||||
uint64_t cycles_since_ir_change; // In 8MHz units
|
||||
uint64_t cycles_since_input_ir_change; // In 8MHz units
|
||||
|
@ -189,13 +189,13 @@ static void byte_reieve_completed(GB_gameboy_t *gb, uint8_t byte_received)
|
||||
|
||||
static void serial_start(GB_gameboy_t *gb, bool bit_received)
|
||||
{
|
||||
gb->printer.byte_being_recieved <<= 1;
|
||||
gb->printer.byte_being_recieved |= bit_received;
|
||||
gb->printer.bits_recieved++;
|
||||
if (gb->printer.bits_recieved == 8) {
|
||||
byte_reieve_completed(gb, gb->printer.byte_being_recieved);
|
||||
gb->printer.bits_recieved = 0;
|
||||
gb->printer.byte_being_recieved = 0;
|
||||
gb->printer.byte_being_received <<= 1;
|
||||
gb->printer.byte_being_received |= bit_received;
|
||||
gb->printer.bits_received++;
|
||||
if (gb->printer.bits_received == 8) {
|
||||
byte_reieve_completed(gb, gb->printer.byte_being_received);
|
||||
gb->printer.bits_received = 0;
|
||||
gb->printer.byte_being_received = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,8 +54,8 @@ typedef struct
|
||||
uint8_t compression_run_lenth;
|
||||
bool compression_run_is_compressed;
|
||||
|
||||
uint8_t bits_recieved;
|
||||
uint8_t byte_being_recieved;
|
||||
uint8_t bits_received;
|
||||
uint8_t byte_being_received;
|
||||
bool bit_to_send;
|
||||
} GB_printer_t;
|
||||
|
||||
|
169
Core/workboy.c
Normal file
169
Core/workboy.c
Normal file
@ -0,0 +1,169 @@
|
||||
#include "gb.h"
|
||||
#include <time.h>
|
||||
|
||||
static inline uint8_t int_to_bcd(uint8_t i)
|
||||
{
|
||||
return (i % 10) + ((i / 10) << 4);
|
||||
}
|
||||
|
||||
static inline uint8_t bcd_to_int(uint8_t i)
|
||||
{
|
||||
return (i & 0xF) + (i >> 4) * 10;
|
||||
}
|
||||
|
||||
/*
|
||||
Note: This peripheral was never released. This is a hacky software reimplementation of it that allows
|
||||
reaccessing all of the features present in Workboy's ROM. Some of the implementation details are
|
||||
obviously wrong, but without access to the actual hardware, this is the best I can do.
|
||||
*/
|
||||
|
||||
static void serial_start(GB_gameboy_t *gb, bool bit_received)
|
||||
{
|
||||
gb->workboy.byte_being_received <<= 1;
|
||||
gb->workboy.byte_being_received |= bit_received;
|
||||
gb->workboy.bits_received++;
|
||||
if (gb->workboy.bits_received == 8) {
|
||||
gb->workboy.byte_to_send = 0;
|
||||
if (gb->workboy.mode != 'W' && gb->workboy.byte_being_received == 'R') {
|
||||
gb->workboy.byte_to_send = 'D';
|
||||
gb->workboy.key = GB_WORKBOY_NONE;
|
||||
gb->workboy.mode = gb->workboy.byte_being_received;
|
||||
gb->workboy.buffer_index = 1;
|
||||
|
||||
time_t time = gb->workboy_get_time_callback(gb);
|
||||
struct tm tm;
|
||||
tm = *localtime(&time);
|
||||
memset(gb->workboy.buffer, 0, sizeof(gb->workboy.buffer));
|
||||
|
||||
gb->workboy.buffer[0] = 4; // Unknown, unused, but appears to be expected to be 4
|
||||
gb->workboy.buffer[2] = int_to_bcd(tm.tm_sec); // Seconds, BCD
|
||||
gb->workboy.buffer[3] = int_to_bcd(tm.tm_min); // Minutes, BCD
|
||||
gb->workboy.buffer[4] = int_to_bcd(tm.tm_hour); // Hours, BCD
|
||||
gb->workboy.buffer[5] = int_to_bcd(tm.tm_mday); // Days, BCD. Upper most 2 bits are added to Year for some reason
|
||||
gb->workboy.buffer[6] = int_to_bcd(tm.tm_mon + 1); // Months, BCD
|
||||
gb->workboy.buffer[0xF] = tm.tm_year; // Years, plain number, since 1900
|
||||
|
||||
}
|
||||
else if (gb->workboy.mode != 'W' && gb->workboy.byte_being_received == 'W') {
|
||||
gb->workboy.byte_to_send = 'D'; // It is actually unknown what this value should be
|
||||
gb->workboy.key = GB_WORKBOY_NONE;
|
||||
gb->workboy.mode = gb->workboy.byte_being_received;
|
||||
gb->workboy.buffer_index = 0;
|
||||
}
|
||||
else if (gb->workboy.mode != 'W' && (gb->workboy.byte_being_received == 'O' || gb->workboy.mode == 'O')) {
|
||||
gb->workboy.mode = 'O';
|
||||
gb->workboy.byte_to_send = gb->workboy.key;
|
||||
if (gb->workboy.key != GB_WORKBOY_NONE) {
|
||||
if (gb->workboy.key & GB_WORKBOY_REQUIRE_SHIFT) {
|
||||
gb->workboy.key &= ~GB_WORKBOY_REQUIRE_SHIFT;
|
||||
if (gb->workboy.shift_down) {
|
||||
gb->workboy.byte_to_send = gb->workboy.key;
|
||||
gb->workboy.key = GB_WORKBOY_NONE;
|
||||
}
|
||||
else {
|
||||
gb->workboy.byte_to_send = GB_WORKBOY_SHIFT_DOWN;
|
||||
gb->workboy.shift_down = true;
|
||||
}
|
||||
}
|
||||
else if (gb->workboy.key & GB_WORKBOY_FORBID_SHIFT) {
|
||||
gb->workboy.key &= ~GB_WORKBOY_FORBID_SHIFT;
|
||||
if (!gb->workboy.shift_down) {
|
||||
gb->workboy.byte_to_send = gb->workboy.key;
|
||||
gb->workboy.key = GB_WORKBOY_NONE;
|
||||
}
|
||||
else {
|
||||
gb->workboy.byte_to_send = GB_WORKBOY_SHIFT_UP;
|
||||
gb->workboy.shift_down = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (gb->workboy.key == GB_WORKBOY_SHIFT_DOWN) {
|
||||
gb->workboy.shift_down = true;
|
||||
gb->workboy.user_shift_down = true;
|
||||
}
|
||||
else if (gb->workboy.key == GB_WORKBOY_SHIFT_UP) {
|
||||
gb->workboy.shift_down = false;
|
||||
gb->workboy.user_shift_down = false;
|
||||
}
|
||||
gb->workboy.byte_to_send = gb->workboy.key;
|
||||
gb->workboy.key = GB_WORKBOY_NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (gb->workboy.mode == 'R') {
|
||||
if (gb->workboy.buffer_index / 2 >= sizeof(gb->workboy.buffer)) {
|
||||
gb->workboy.byte_to_send = 0;
|
||||
}
|
||||
else {
|
||||
if (gb->workboy.buffer_index & 1) {
|
||||
gb->workboy.byte_to_send = "0123456789ABCDEF"[gb->workboy.buffer[gb->workboy.buffer_index / 2] & 0xF];
|
||||
}
|
||||
else {
|
||||
gb->workboy.byte_to_send = "0123456789ABCDEF"[gb->workboy.buffer[gb->workboy.buffer_index / 2] >> 4];
|
||||
}
|
||||
gb->workboy.buffer_index++;
|
||||
}
|
||||
}
|
||||
else if (gb->workboy.mode == 'W') {
|
||||
gb->workboy.byte_to_send = 'D';
|
||||
if (gb->workboy.buffer_index < 2) {
|
||||
gb->workboy.buffer_index++;
|
||||
}
|
||||
else if ((gb->workboy.buffer_index - 2) < sizeof(gb->workboy.buffer)) {
|
||||
gb->workboy.buffer[gb->workboy.buffer_index - 2] = gb->workboy.byte_being_received;
|
||||
gb->workboy.buffer_index++;
|
||||
if (gb->workboy.buffer_index - 2 == sizeof(gb->workboy.buffer)) {
|
||||
struct tm tm = {0,};
|
||||
tm.tm_sec = bcd_to_int(gb->workboy.buffer[7]);
|
||||
tm.tm_min = bcd_to_int(gb->workboy.buffer[8]);
|
||||
tm.tm_hour = bcd_to_int(gb->workboy.buffer[9]);
|
||||
tm.tm_mday = bcd_to_int(gb->workboy.buffer[0xA]);
|
||||
tm.tm_mon = bcd_to_int(gb->workboy.buffer[0xB] & 0x3F) - 1;
|
||||
tm.tm_year = (uint8_t)(gb->workboy.buffer[0x14] + (gb->workboy.buffer[0xA] >> 6)); // What were they thinking?
|
||||
gb->workboy_set_time_callback(gb, mktime(&tm));
|
||||
gb->workboy.mode = 'O';
|
||||
}
|
||||
}
|
||||
}
|
||||
gb->workboy.bits_received = 0;
|
||||
gb->workboy.byte_being_received = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static bool serial_end(GB_gameboy_t *gb)
|
||||
{
|
||||
bool ret = gb->workboy.bit_to_send;
|
||||
gb->workboy.bit_to_send = gb->workboy.byte_to_send & 0x80;
|
||||
gb->workboy.byte_to_send <<= 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void GB_connect_workboy(GB_gameboy_t *gb,
|
||||
GB_workboy_set_time_callback set_time_callback,
|
||||
GB_workboy_get_time_callback get_time_callback)
|
||||
{
|
||||
memset(&gb->workboy, 0, sizeof(gb->workboy));
|
||||
GB_set_serial_transfer_bit_start_callback(gb, serial_start);
|
||||
GB_set_serial_transfer_bit_end_callback(gb, serial_end);
|
||||
gb->workboy_set_time_callback = set_time_callback;
|
||||
gb->workboy_get_time_callback = get_time_callback;
|
||||
}
|
||||
|
||||
bool GB_workboy_is_enabled(GB_gameboy_t *gb)
|
||||
{
|
||||
return gb->workboy.mode;
|
||||
}
|
||||
|
||||
void GB_workboy_set_key(GB_gameboy_t *gb, uint8_t key)
|
||||
{
|
||||
if (gb->workboy.user_shift_down != gb->workboy.shift_down &&
|
||||
(key & (GB_WORKBOY_REQUIRE_SHIFT | GB_WORKBOY_FORBID_SHIFT)) == 0) {
|
||||
if (gb->workboy.user_shift_down) {
|
||||
key |= GB_WORKBOY_REQUIRE_SHIFT;
|
||||
}
|
||||
else {
|
||||
key |= GB_WORKBOY_FORBID_SHIFT;
|
||||
}
|
||||
}
|
||||
gb->workboy.key = key;
|
||||
}
|
118
Core/workboy.h
Normal file
118
Core/workboy.h
Normal file
@ -0,0 +1,118 @@
|
||||
#ifndef workboy_h
|
||||
#define workboy_h
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <time.h>
|
||||
#include "gb_struct_def.h"
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint8_t byte_to_send;
|
||||
bool bit_to_send;
|
||||
uint8_t byte_being_received;
|
||||
uint8_t bits_received;
|
||||
uint8_t mode;
|
||||
uint8_t key;
|
||||
bool shift_down;
|
||||
bool user_shift_down;
|
||||
uint8_t buffer[0x15];
|
||||
uint8_t buffer_index; // In nibbles during read, in bytes during write
|
||||
} GB_workboy_t;
|
||||
|
||||
typedef void (*GB_workboy_set_time_callback)(GB_gameboy_t *gb, time_t time);
|
||||
typedef time_t (*GB_workboy_get_time_callback)(GB_gameboy_t *gb);
|
||||
|
||||
enum {
|
||||
GB_WORKBOY_NONE = 0xFF,
|
||||
GB_WORKBOY_REQUIRE_SHIFT = 0x40,
|
||||
GB_WORKBOY_FORBID_SHIFT = 0x80,
|
||||
|
||||
GB_WORKBOY_CLOCK = 1,
|
||||
GB_WORKBOY_TEMPERATURE = 2,
|
||||
GB_WORKBOY_MONEY = 3,
|
||||
GB_WORKBOY_CALCULATOR = 4,
|
||||
GB_WORKBOY_DATE = 5,
|
||||
GB_WORKBOY_CONVERSION = 6,
|
||||
GB_WORKBOY_RECORD = 7,
|
||||
GB_WORKBOY_WORLD = 8,
|
||||
GB_WORKBOY_PHONE = 9,
|
||||
GB_WORKBOY_ESCAPE = 10,
|
||||
GB_WORKBOY_BACKSPACE = 11,
|
||||
GB_WORKBOY_UNKNOWN = 12,
|
||||
GB_WORKBOY_LEFT = 13,
|
||||
GB_WORKBOY_Q = 17,
|
||||
GB_WORKBOY_1 = 17 | GB_WORKBOY_REQUIRE_SHIFT,
|
||||
GB_WORKBOY_W = 18,
|
||||
GB_WORKBOY_2 = 18 | GB_WORKBOY_REQUIRE_SHIFT,
|
||||
GB_WORKBOY_E = 19,
|
||||
GB_WORKBOY_3 = 19 | GB_WORKBOY_REQUIRE_SHIFT,
|
||||
GB_WORKBOY_R = 20,
|
||||
GB_WORKBOY_T = 21,
|
||||
GB_WORKBOY_Y = 22 ,
|
||||
GB_WORKBOY_U = 23 ,
|
||||
GB_WORKBOY_I = 24,
|
||||
GB_WORKBOY_EXCLAMATION_MARK = 24 | GB_WORKBOY_REQUIRE_SHIFT,
|
||||
GB_WORKBOY_O = 25,
|
||||
GB_WORKBOY_TILDE = 25 | GB_WORKBOY_REQUIRE_SHIFT,
|
||||
GB_WORKBOY_P = 26,
|
||||
GB_WORKBOY_ASTERISK = 26 | GB_WORKBOY_REQUIRE_SHIFT,
|
||||
GB_WORKBOY_DOLLAR = 27 | GB_WORKBOY_FORBID_SHIFT,
|
||||
GB_WORKBOY_HASH = 27 | GB_WORKBOY_REQUIRE_SHIFT,
|
||||
GB_WORKBOY_A = 28,
|
||||
GB_WORKBOY_4 = 28 | GB_WORKBOY_REQUIRE_SHIFT,
|
||||
GB_WORKBOY_S = 29,
|
||||
GB_WORKBOY_5 = 29 | GB_WORKBOY_REQUIRE_SHIFT,
|
||||
GB_WORKBOY_D = 30,
|
||||
GB_WORKBOY_6 = 30 | GB_WORKBOY_REQUIRE_SHIFT,
|
||||
GB_WORKBOY_F = 31,
|
||||
GB_WORKBOY_PLUS = 31 | GB_WORKBOY_REQUIRE_SHIFT,
|
||||
GB_WORKBOY_G = 32,
|
||||
GB_WORKBOY_MINUS = 32 | GB_WORKBOY_REQUIRE_SHIFT,
|
||||
GB_WORKBOY_H = 33,
|
||||
GB_WORKBOY_J = 34,
|
||||
GB_WORKBOY_K = 35,
|
||||
GB_WORKBOY_LEFT_PARENTHESIS = 35 | GB_WORKBOY_REQUIRE_SHIFT,
|
||||
GB_WORKBOY_L = 36,
|
||||
GB_WORKBOY_RIGHT_PARENTHESIS = 36 | GB_WORKBOY_REQUIRE_SHIFT,
|
||||
GB_WORKBOY_SEMICOLON = 37 | GB_WORKBOY_FORBID_SHIFT,
|
||||
GB_WORKBOY_COLON = 37,
|
||||
GB_WORKBOY_ENTER = 38,
|
||||
GB_WORKBOY_SHIFT_DOWN = 39,
|
||||
GB_WORKBOY_Z = 40,
|
||||
GB_WORKBOY_7 = 40 | GB_WORKBOY_REQUIRE_SHIFT,
|
||||
GB_WORKBOY_X = 41,
|
||||
GB_WORKBOY_8 = 41 | GB_WORKBOY_REQUIRE_SHIFT,
|
||||
GB_WORKBOY_C = 42,
|
||||
GB_WORKBOY_9 = 42 | GB_WORKBOY_REQUIRE_SHIFT,
|
||||
GB_WORKBOY_V = 43,
|
||||
GB_WORKBOY_DECIMAL_POINT = 43 | GB_WORKBOY_REQUIRE_SHIFT,
|
||||
GB_WORKBOY_B = 44,
|
||||
GB_WORKBOY_PERCENT = 44 | GB_WORKBOY_REQUIRE_SHIFT,
|
||||
GB_WORKBOY_N = 45,
|
||||
GB_WORKBOY_EQUAL = 45 | GB_WORKBOY_REQUIRE_SHIFT,
|
||||
GB_WORKBOY_M = 46,
|
||||
GB_WORKBOY_COMMA = 47 | GB_WORKBOY_FORBID_SHIFT,
|
||||
GB_WORKBOY_LT = 47 | GB_WORKBOY_REQUIRE_SHIFT,
|
||||
GB_WORKBOY_DOT = 48 | GB_WORKBOY_FORBID_SHIFT,
|
||||
GB_WORKBOY_GT = 48 | GB_WORKBOY_REQUIRE_SHIFT,
|
||||
GB_WORKBOY_SLASH = 49 | GB_WORKBOY_FORBID_SHIFT,
|
||||
GB_WORKBOY_QUESTION_MARK = 49 | GB_WORKBOY_REQUIRE_SHIFT,
|
||||
GB_WORKBOY_SHIFT_UP = 50,
|
||||
GB_WORKBOY_0 = 51 | GB_WORKBOY_REQUIRE_SHIFT,
|
||||
GB_WORKBOY_UMLAUT = 51,
|
||||
GB_WORKBOY_SPACE = 52,
|
||||
GB_WORKBOY_QUOTE = 53 | GB_WORKBOY_FORBID_SHIFT,
|
||||
GB_WORKBOY_AT = 53 | GB_WORKBOY_REQUIRE_SHIFT,
|
||||
GB_WORKBOY_UP = 54,
|
||||
GB_WORKBOY_DOWN = 55,
|
||||
GB_WORKBOY_RIGHT = 56,
|
||||
};
|
||||
|
||||
|
||||
void GB_connect_workboy(GB_gameboy_t *gb,
|
||||
GB_workboy_set_time_callback set_time_callback,
|
||||
GB_workboy_get_time_callback get_time_callback);
|
||||
bool GB_workboy_is_enabled(GB_gameboy_t *gb);
|
||||
void GB_workboy_set_key(GB_gameboy_t *gb, uint8_t key);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user