~lgb/x-emulators/dev

« back to all changes in this revision

Viewing changes to targets/cx16/input_devices.c

  • Committer: GitHub
  • Author(s): LGB
  • Date: 2020-01-18 01:19:08 UTC
  • mfrom: (265.1.63)
  • Revision ID: git-v1:1dd7619788b3c1f5896dd056cc1af0d4ba0daa86
Merge pull request #83 from lgblgblgb/dev

Refresh master from dev ...

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* The Xemu project.
 
2
   Copyright (C)2016-2019 LGB (Gábor Lénárt) <lgblgblgb@gmail.com>
 
3
 
 
4
   This is the Commander X16 emulation. Note: the source is overcrowded with comments by intent :)
 
5
   That it can useful for other people as well, or someone wants to contribute, etc ...
 
6
 
 
7
This program is free software; you can redistribute it and/or modify
 
8
it under the terms of the GNU General Public License as published by
 
9
the Free Software Foundation; either version 2 of the License, or
 
10
(at your option) any later version.
 
11
 
 
12
This program is distributed in the hope that it will be useful,
 
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
GNU General Public License for more details.
 
16
 
 
17
You should have received a copy of the GNU General Public License
 
18
along with this program; if not, write to the Free Software
 
19
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
20
 
 
21
#include "xemu/emutools.h"
 
22
#include "xemu/emutools_hid.h"
 
23
#include "input_devices.h"
 
24
#include "commander_x16.h"
 
25
#include <string.h>
 
26
 
 
27
struct ps2_keymap_st {
 
28
        SDL_Scancode    key;
 
29
        int             ps2_code;       // + 0x100 for extended codes
 
30
};
 
31
 
 
32
// This table is taken from Mist's X16 emulator, but converted into a table
 
33
// >0xFF codes are extended keys (and only the low byte should be treated then as the PS/2 keycode)
 
34
static const struct ps2_keymap_st ps2_keymap[] = {
 
35
        {SDL_SCANCODE_GRAVE,            0x0e},  {SDL_SCANCODE_BACKSPACE,        0x66},  {SDL_SCANCODE_TAB,              0xd},   {SDL_SCANCODE_CLEAR,            0},     {SDL_SCANCODE_RETURN,           0x5a},
 
36
        {SDL_SCANCODE_PAUSE,            0},     {SDL_SCANCODE_ESCAPE,           0x76},  {SDL_SCANCODE_SPACE,            0x29},  {SDL_SCANCODE_APOSTROPHE,       0x52},  {SDL_SCANCODE_COMMA,            0x41},
 
37
        {SDL_SCANCODE_MINUS,            0x4e},  {SDL_SCANCODE_PERIOD,           0x49},  {SDL_SCANCODE_SLASH,            0x4a},  {SDL_SCANCODE_0,                0x45},  {SDL_SCANCODE_1,                0x16},
 
38
        {SDL_SCANCODE_2,                0x1e},  {SDL_SCANCODE_3,                0x26},  {SDL_SCANCODE_4,                0x25},  {SDL_SCANCODE_5,                0x2e},  {SDL_SCANCODE_6,                0x36},
 
39
        {SDL_SCANCODE_7,                0x3d},  {SDL_SCANCODE_8,                0x3e},  {SDL_SCANCODE_9,                0x46},  {SDL_SCANCODE_SEMICOLON,        0x4c},  {SDL_SCANCODE_EQUALS,           0x55},
 
40
        {SDL_SCANCODE_LEFTBRACKET,      0x54},  {SDL_SCANCODE_BACKSLASH,        0x5d},  {SDL_SCANCODE_RIGHTBRACKET,     0x5b},  {SDL_SCANCODE_A,                0x1c},  {SDL_SCANCODE_B,                0x32},
 
41
        {SDL_SCANCODE_C,                0x21},  {SDL_SCANCODE_D,                0x23},  {SDL_SCANCODE_E,                0x24},  {SDL_SCANCODE_F,                0x2b},  {SDL_SCANCODE_G,                0x34},
 
42
        {SDL_SCANCODE_H,                0x33},  {SDL_SCANCODE_I,                0x43},  {SDL_SCANCODE_J,                0x3B},  {SDL_SCANCODE_K,                0x42},  {SDL_SCANCODE_L,                0x4B},
 
43
        {SDL_SCANCODE_M,                0x3A},  {SDL_SCANCODE_N,                0x31},  {SDL_SCANCODE_O,                0x44},  {SDL_SCANCODE_P,                0x4D},  {SDL_SCANCODE_Q,                0x15},
 
44
        {SDL_SCANCODE_R,                0x2D},  {SDL_SCANCODE_S,                0x1B},  {SDL_SCANCODE_T,                0x2C},  {SDL_SCANCODE_U,                0x3C},  {SDL_SCANCODE_V,                0x2A},
 
45
        {SDL_SCANCODE_W,                0x1D},  {SDL_SCANCODE_X,                0x22},  {SDL_SCANCODE_Y,                0x35},  {SDL_SCANCODE_Z,                0x1A},  {SDL_SCANCODE_DELETE,           0},
 
46
        {SDL_SCANCODE_UP,               0x175}, {SDL_SCANCODE_DOWN,             0x172}, {SDL_SCANCODE_RIGHT,            0x174}, {SDL_SCANCODE_LEFT,             0x16b}, {SDL_SCANCODE_INSERT,           0},
 
47
        {SDL_SCANCODE_HOME,             0x16c}, {SDL_SCANCODE_END,              0},     {SDL_SCANCODE_PAGEUP,           0},     {SDL_SCANCODE_PAGEDOWN,         0},     {SDL_SCANCODE_F1,               0x05},
 
48
        {SDL_SCANCODE_F2,               0x06},  {SDL_SCANCODE_F3,               0x04},  {SDL_SCANCODE_F4,               0x0c},  {SDL_SCANCODE_F5,               0x03},  {SDL_SCANCODE_F6,               0x0b},
 
49
        {SDL_SCANCODE_F7,               0x83},  {SDL_SCANCODE_F8,               0x0a},  {SDL_SCANCODE_F9,               0x01},  {SDL_SCANCODE_F10,              0x09},  {SDL_SCANCODE_F11,              0x78},
 
50
        {SDL_SCANCODE_F12,              0x07},  {SDL_SCANCODE_RSHIFT,           0x59},  {SDL_SCANCODE_LSHIFT,           0x12},  {SDL_SCANCODE_LCTRL,            0x14},  {SDL_SCANCODE_RCTRL,            0x114},
 
51
        {SDL_SCANCODE_LALT,             0x11},  {SDL_SCANCODE_RALT,             0x111}, {SDL_SCANCODE_NONUSBACKSLASH,   0x61},  {SDL_SCANCODE_KP_ENTER,         0x15a}, {SDL_SCANCODE_KP_0,             0x70},
 
52
        {SDL_SCANCODE_KP_1,             0x69},  {SDL_SCANCODE_KP_2,             0x72},  {SDL_SCANCODE_KP_3,             0x7a},  {SDL_SCANCODE_KP_4,             0x6b},  {SDL_SCANCODE_KP_5,             0x73},
 
53
        {SDL_SCANCODE_KP_6,             0x74},  {SDL_SCANCODE_KP_7,             0x6c},  {SDL_SCANCODE_KP_8,             0x75},  {SDL_SCANCODE_KP_9,             0x7d},  {SDL_SCANCODE_KP_PERIOD,        0x71},
 
54
        {SDL_SCANCODE_KP_PLUS,          0x79},  {SDL_SCANCODE_KP_MINUS,         0x7b},  {SDL_SCANCODE_KP_MULTIPLY,      0x7c},  {SDL_SCANCODE_KP_DIVIDE,        0x14a}, {0,                             -1}
 
55
};
 
56
 
 
57
void clear_emu_events ( void )
 
58
{
 
59
        hid_reset_events(1);
 
60
}
 
61
 
 
62
 
 
63
 
 
64
 
 
65
 
 
66
static Uint8  ps2_stream[128];
 
67
static int    ps2_stream_w_pos = 0;
 
68
static Uint64 virt_cycle_last_read;
 
69
 
 
70
 
 
71
int read_ps2_port ( void )
 
72
{
 
73
        static int clk = 2;
 
74
        static int data = 1;
 
75
        if (ps2_stream_w_pos) {
 
76
                Uint64 since = all_virt_cycles - virt_cycle_last_read;
 
77
                // This is BAD, since actually the keyboard sends data the CPU takes care or not, it won't "pause" just because PS/2 lines are not checked ...
 
78
                if (since > 333) {
 
79
                        virt_cycle_last_read = all_virt_cycles;
 
80
                        //while (since > 333 && ps2_stream_w_pos) {
 
81
                                clk ^= 2;
 
82
                                if (!clk) {
 
83
                                        data = ps2_stream[0];
 
84
                                        memmove(ps2_stream, ps2_stream + 1, --ps2_stream_w_pos);
 
85
                                }
 
86
                        //      since -= 333;
 
87
                        //}
 
88
                }
 
89
        } else {
 
90
                clk = 2;
 
91
                data = 1;
 
92
        }
 
93
        return clk | data;
 
94
}
 
95
 
 
96
 
 
97
static void queue_ps2_device_packet ( Uint8 data )
 
98
{
 
99
        //DEBUGPRINT("PS2: queuing protocol byte $%02X" NL, data);
 
100
        ps2_stream[ps2_stream_w_pos++] = 0;     // start bit, always zero
 
101
        int parity = 1;                         // odd parity, we start with '1'.
 
102
        for (int a = 0; a < 8; a++, data >>=1 ) {
 
103
                ps2_stream[ps2_stream_w_pos++] = (data & 1);
 
104
                if ((data & 1))
 
105
                        parity ^= 1;
 
106
        }
 
107
        ps2_stream[ps2_stream_w_pos++] = parity;
 
108
        ps2_stream[ps2_stream_w_pos++] = 1;     // stop bit, always one
 
109
}
 
110
 
 
111
 
 
112
static XEMU_INLINE void emit_ps2_event ( SDL_Scancode key, int pressed )
 
113
{
 
114
        const struct ps2_keymap_st *p = ps2_keymap;
 
115
        while (p->ps2_code >= 0)
 
116
                if (key == p->key) {
 
117
                        if (ps2_stream_w_pos < sizeof(ps2_stream) - 12 * 3) {
 
118
                                int ps2 = p->ps2_code;
 
119
                                //fprintf(stderr, "FOUND KEY: SDL=%d PS2=%d PRESSED=%s\n", p->key, ps2, pressed ? "pressed" : "released");
 
120
                                if (ps2 >= 0x100)
 
121
                                        queue_ps2_device_packet(0xE0);  // extended key, emit E0
 
122
                                if (!pressed)
 
123
                                        queue_ps2_device_packet(0xF0);  // "break" code, ie, release of a key
 
124
                                queue_ps2_device_packet(ps2 & 0xFF);
 
125
                        } else
 
126
                                DEBUGPRINT("PS2: protocol stream is full :-(" NL);
 
127
                        return;
 
128
                } else
 
129
                        p++;
 
130
        //DEBUGPRINT("PS2: KEY NOT FOUND SDL=%d PRESSED=%s" NL, key, pressed ? "pressed" : "released");
 
131
}
 
132
 
 
133
 
 
134
// HID needs this to be defined, it's up to the emulator if it uses or not ...
 
135
// NOTE: Commander X16 is a special case, as it's not matrix based with keyboard implementation.
 
136
// Thus, we skip the matrix stuff more or less, and use the callback of the HID subsystem to
 
137
// inject the emulated PS/2 sequences then. We want to use some queue anyway ...
 
138
int emu_callback_key ( int pos, SDL_Scancode key, int pressed, int handled )
 
139
{
 
140
/*      DEBUGPRINT("KEY EVENT: pos=%d scancode=%d pressed=%d handled=%d" NL,
 
141
                        pos, key, pressed, handled
 
142
        );*/
 
143
        if (pos == -1 && handled == 0)
 
144
                emit_ps2_event(key, pressed);
 
145
        return 0;
 
146
}