OSDN Git Service

2db5af5df17e4dc6c39d1e1c924c88bcade1d196
[csp-qt/common_source_project-fm7.git] / source / src / vm / x1 / psub.cpp
1 /*
2         SHARP X1 Emulator 'eX1'
3         SHARP X1twin Emulator 'eX1twin'
4         SHARP X1turbo Emulator 'eX1turbo'
5         SHARP X1turboZ Emulator 'eX1turboZ'
6
7         Author : Takeda.Toshiya
8         Date   : 2009.03.15-
9
10         [ pseudo sub system ]
11 */
12
13 #include "psub.h"
14 #include "../datarec.h"
15 #include "../i8255.h"
16 #include "../../fifo.h"
17 //#define DEBUG_COMMAND
18
19 #define EVENT_1SEC      0
20 #define EVENT_DRIVE     1
21 #define EVENT_REPEAT    2
22
23 #define CMT_EJECT       0x00
24 #define CMT_STOP        0x01
25 #define CMT_PLAY        0x02
26 #define CMT_FAST_FWD    0x03
27 #define CMT_FAST_REW    0x04
28 #define CMT_APSS_PLUS   0x05
29 #define CMT_APSS_MINUS  0x06
30 #define CMT_REC         0x0a
31
32 // TODO: XFER = 0xe8 ???
33
34 namespace X1 {
35
36 static const uint8_t keycode[256] = {   // normal
37         0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x08, 0x09, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00,
38         0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0xe8, 0x00, 0x00, 0x00,
39         0x20, 0x0e, 0x0f, 0x11, 0x0b, 0x1d, 0x1e, 0x1c, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x12, 0x08, 0x00,
40         0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
41         0x00, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
42         0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x00, 0x00, 0x00, 0x00, 0x00,
43         0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
44         0x71, 0x72, 0x73, 0x74, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
45         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
46         0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
47         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
48         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x3b, 0x2c, 0x2d, 0x2e, 0x2f,
49         0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
50         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x5c, 0x5d, 0x5e, 0x00,
51         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
52         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
53 };
54 static const uint8_t keycode_s[256] = { // shift
55         0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x12, 0x09, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00,
56         0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0xe8, 0x00, 0x00, 0x00,
57         0x20, 0x0e, 0x0f, 0x11, 0x0c, 0x1d, 0x1e, 0x1c, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x12, 0x08, 0x00,
58         0x30, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
59         0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
60         0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00,
61         0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2a, 0x2b, 0x3c, 0x2d, 0x2e, 0x3f,
62         0x76, 0x77, 0x78, 0x79, 0x7a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
63         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
64         0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
65         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
66         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x2b, 0x3c, 0x3d, 0x3e, 0x3f,
67         0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
68         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x60, 0x00,
69         0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
70         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
71 };
72 static const uint8_t keycode_g[256] = { // graph
73         0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
74         0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x00, 0x00, 0x00,
75         0x00, 0x0e, 0x0f, 0x11, 0x0b, 0x1d, 0x1e, 0x1c, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x12, 0x08, 0x00,
76         0xfa, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
77         0x00, 0x7f, 0x84, 0x82, 0xea, 0xe2, 0xeb, 0xec, 0xed, 0xe7, 0xee, 0xef, 0x8e, 0x86, 0x85, 0xf0,
78         0x8d, 0xe0, 0xe3, 0xe9, 0xe4, 0xe6, 0x83, 0xe1, 0x81, 0xe5, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
79         0x8f, 0x99, 0x92, 0x98, 0x95, 0x96, 0x94, 0x9a, 0x93, 0x97, 0x9b, 0x9d, 0x87, 0x9c, 0x91, 0x9e,
80         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
81         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
82         0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
83         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
84         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfd, 0x89, 0x87, 0x8c, 0x88, 0xfe,
85         0x8a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
86         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfb, 0xe8, 0x8b, 0x00,
87         0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
88         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
89 };
90 static const uint8_t keycode_c[256] = { // ctrl
91         0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x08, 0x09, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00,
92         0x1c, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0xe8, 0x00, 0x00, 0x00,
93         0x00, 0x0e, 0x0f, 0x11, 0x0b, 0x1d, 0x1e, 0x1c, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x12, 0x08, 0x00,
94         0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
95         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
96         0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00,
97         0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2a, 0x2b, 0x00, 0x2d, 0x2e, 0x2f,
98         0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0xeb, 0xe2, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
99         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
100         0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
101         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
102         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x3b, 0x00, 0x2d, 0x00, 0x00,
103         0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
104         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x1c, 0x1d, 0x1e, 0x00,
105         0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
106         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
107 };
108 static const uint8_t keycode_k[256] = { // kana
109         0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x08, 0x09, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00,
110         0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0xe8, 0x00, 0x00, 0x00,
111         0x20, 0x0e, 0x0f, 0x11, 0x0b, 0x1d, 0x1e, 0x1c, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x12, 0x08, 0x00,
112         0xdc, 0xc7, 0xcc, 0xb1, 0xb3, 0xb4, 0xb5, 0xd4, 0xd5, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
113         0x00, 0xc1, 0xba, 0xbf, 0xbc, 0xb2, 0xca, 0xb7, 0xb8, 0xc6, 0xcf, 0xc9, 0xd8, 0xd3, 0xd0, 0xd7,
114         0xbe, 0xc0, 0xbd, 0xc4, 0xb6, 0xc5, 0xcb, 0xc3, 0xbb, 0xdd, 0xc2, 0x00, 0x00, 0x00, 0x00, 0x00,
115         0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2a, 0x2b, 0xc8, 0x2d, 0x2e, 0xd2,
116         0x71, 0x72, 0x73, 0x74, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
117         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
118         0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
119         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
120         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb9, 0xda, 0xc8, 0xce, 0xd9, 0xd2,
121         0xde, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
122         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdf, 0xb0, 0xd1, 0xcd, 0x00,
123         0x00, 0x00, 0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
124         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
125 };
126 static const uint8_t keycode_ks[256] = {        // kana+shift
127         0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x12, 0x09, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00,
128         0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0xe8, 0x00, 0x00, 0x00,
129         0x20, 0x0e, 0x0f, 0x11, 0x0c, 0x1d, 0x1e, 0x1c, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x12, 0x08, 0x00,
130         0xa6, 0xc7, 0xcc, 0xa7, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
131         0x00, 0xc1, 0xba, 0xbf, 0xbc, 0xa8, 0xca, 0xb7, 0xb8, 0xc6, 0xcf, 0xc9, 0xd8, 0xd3, 0xd0, 0xd7,
132         0xbe, 0xc0, 0xbd, 0xc4, 0xb6, 0xc5, 0xcb, 0xc3, 0xbb, 0xdd, 0xaf, 0x00, 0x00, 0x00, 0x00, 0x00,
133         0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2a, 0x2b, 0xa4, 0x2d, 0x2e, 0xa5,
134         0x76, 0x77, 0x78, 0x79, 0x7a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
135         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
136         0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
137         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
138         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb9, 0xda, 0xa4, 0xce, 0xa1, 0xa5,
139         0xde, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
140         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa2, 0xb0, 0xa3, 0xcd, 0x00,
141         0x00, 0x00, 0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
142         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
143 };
144 static const uint8_t keycode_kb[256] = {        // kana (mode b)
145         0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x08, 0x09, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00,
146         0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0xe8, 0x00, 0x00, 0x00,
147         0x20, 0x0e, 0x0f, 0x11, 0x0b, 0x1d, 0x1e, 0x1c, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x12, 0x08, 0x00,
148         0xc9, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xc5, 0xc6, 0xc7, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
149         0x00, 0xbb, 0xc4, 0xc2, 0xbd, 0xb8, 0xbe, 0xbf, 0xcf, 0xcc, 0xd0, 0xd1, 0xd2, 0xd5, 0xd4, 0xcd,
150         0xce, 0xb6, 0xb9, 0xbc, 0xba, 0xcb, 0xc3, 0xb7, 0xc1, 0xca, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
151         0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2a, 0x2b, 0xc8, 0x2d, 0x2e, 0xd2,
152         0x71, 0x72, 0x73, 0x74, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
153         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
154         0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
155         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
156         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, 0xd3, 0xd6, 0xd7, 0xdc, 0xa6,
157         0xda, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
158         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0xd9, 0xdf, 0xd8, 0x00,
159         0x00, 0x00, 0xdd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
160         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
161 };
162 static const uint8_t keycode_ksb[256] = {       // kana+shift (mode b)
163         0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x12, 0x09, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00,
164         0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0xe8, 0x00, 0x00, 0x00,
165         0x20, 0x0e, 0x0f, 0x11, 0x0c, 0x1d, 0x1e, 0x1c, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x12, 0x08, 0x00,
166         0xc9, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xc5, 0xc6, 0xc7, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
167         0x00, 0xbb, 0xc4, 0xaf, 0xbd, 0xb8, 0xbe, 0xbf, 0xcf, 0xcc, 0xd0, 0xd1, 0xd2, 0xad, 0xac, 0xcd,
168         0xce, 0xb6, 0xb9, 0xbc, 0xba, 0xcb, 0xc3, 0xb7, 0xc1, 0xca, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
169         0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2a, 0x2b, 0xa4, 0x2d, 0x2e, 0xa5,
170         0x76, 0x77, 0x78, 0x79, 0x7a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
171         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
172         0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
173         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
174         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0xd3, 0xae, 0xd7, 0xa4, 0xa1,
175         0xda, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
176         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x20, 0xa3, 0xd8, 0x00,
177         0x00, 0x00, 0xa5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
178         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
179 };
180
181 void PSUB::initialize()
182 {
183         key_buf = new FIFO(8);
184         key_stat = emu->get_key_buffer();
185         
186         get_host_time(&cur_time);
187         
188         // register events
189         register_event(this, EVENT_1SEC, 1000000, true, &time_register_id);
190         register_event(this, EVENT_DRIVE, 400, true, NULL);
191 }
192
193 void PSUB::release()
194 {
195         key_buf->release();
196         delete key_buf;
197 }
198
199 void PSUB::reset()
200 {
201         memset(databuf, 0, sizeof(databuf));
202         databuf[0x16][0] = 0xff;
203         datap = &databuf[0][0]; // temporary fix
204         mode = 0;
205         cmdlen = datalen = 0;
206         
207         play = rec = eot = false;
208         
209         ibf = true;
210         set_ibf(false);
211         obf = false;
212         set_obf(true);
213         
214         // key buffer
215         key_buf->clear();
216         key_prev = key_break = 0;
217         key_shift = key_ctrl = key_graph = false;
218         key_caps_locked = key_kana_locked = false;
219         key_register_id = -1;
220         
221         // interrupt
222         iei = true;
223         intr = false;
224         
225         // break
226         d_pio->write_signal(SIG_I8255_PORT_B, 0xff, 1);
227 }
228
229 void PSUB::write_io8(uint32_t addr, uint32_t data)
230 {
231         inbuf = data;
232         set_ibf(true);
233 }
234
235 uint32_t PSUB::read_io8(uint32_t addr)
236 {
237         set_obf(true);
238         intr = false;
239         update_intr();
240         return outbuf;
241 }
242
243 void PSUB::write_signal(int id, uint32_t data, uint32_t mask)
244 {
245         if(id == SIG_PSUB_TAPE_REMOTE) {
246                 if(!(data & mask) && (play || rec)) {
247                         databuf[0x1a][0] = CMT_STOP;
248                 }
249         } else if(id == SIG_PSUB_TAPE_END) {
250                 eot = ((data & mask) != 0);
251         }
252 }
253
254 void PSUB::set_intr_iei(bool val)
255 {
256         if(iei != val) {
257                 iei = val;
258                 update_intr();
259         }
260 }
261
262 uint32_t PSUB::get_intr_ack()
263 {
264         return read_io8(0x1900);
265 }
266
267 void PSUB::notify_intr_reti()
268 {
269         // NOTE: some software uses RET, not RETI ???
270 }
271
272 void PSUB::update_intr()
273 {
274         if(intr && iei) {
275                 d_cpu->set_intr_line(true, true, intr_bit);
276         } else {
277                 d_cpu->set_intr_line(false, true, intr_bit);
278         }
279 }
280 #if defined(Q_OS_WIN)
281 DLL_PREFIX_I struct cur_time_s cur_time;
282 #endif
283
284 void PSUB::event_callback(int event_id, int err)
285 {
286         if(event_id == EVENT_1SEC) {
287                 if(cur_time.initialized) {
288                         cur_time.increment();
289                 } else {
290                         get_host_time(&cur_time);       // resync
291                         cur_time.initialized = true;
292                 }
293         } else if(event_id == EVENT_DRIVE) {
294                 // drive sub cpu
295                 static const int cmdlen_tbl[] = {
296                         0, 1, 0, 0, 1, 0, 1, 0, 0, 3, 0, 3, 0
297                 };
298                 
299 #ifdef _X1TWIN
300                 // clear key buffer
301                 if(vm->is_cart_inserted(0)) {
302                         // clear key
303                         key_buf->clear();
304                 }
305 #endif
306                 if(ibf) {
307                         // sub cpu received data from main cpu
308                         if(cmdlen) {
309                                 // this is command parameter
310                                 *datap++ = inbuf;
311 #ifdef DEBUG_COMMAND
312                                 this->out_debug_log(_T(" %2x"), inbuf);
313 #endif
314                                 cmdlen--;
315                         } else {
316                                 // this is new command
317                                 mode = inbuf;
318 #ifdef DEBUG_COMMAND
319                                 this->out_debug_log(_T("X1 PSUB: cmd %2x"), inbuf);
320 #endif
321                                 if(0xd0 <= mode && mode <= 0xd7) {
322                                         cmdlen = 6;
323                                         datap = &databuf[mode - 0xd0][0]; // receive buffer
324                                 } else if(0xe3 <= mode && mode <= 0xef) {
325                                         cmdlen = cmdlen_tbl[mode - 0xe3];
326                                         datap = &databuf[mode - 0xd0][0]; // receive buffer
327                                 }
328                         }
329                         if(cmdlen == 0) {
330                                 // this command has no parameters or all parameters are received,
331                                 // so cpu processes the command
332 #ifdef DEBUG_COMMAND
333                                 this->out_debug_log(_T("\n"));
334 #endif
335                                 process_cmd();
336                         }
337                         // sub cpu can accept new command or parameter
338                         set_ibf(false);
339                         set_obf(true);
340                         
341                         // if command is not finished, key irq is not raised
342                         if(cmdlen || datalen) {
343                                 return;
344                         }
345                 }
346                 if(obf) {
347                         // sub cpu can send data to main cpu
348                         if(datalen) {
349                                 // sub cpu sends result data
350                                 outbuf = *datap++;
351                                 set_obf(false);
352                                 datalen--;
353                         } else if(!key_buf->empty() && databuf[0x14][0] && !intr && iei) {
354                                 // key buffer is not empty and interrupt is not disabled,
355                                 // so sub cpu sends vector and raise irq
356                                 outbuf = databuf[0x14][0];
357                                 set_obf(false);
358                                 intr = true;
359                                 update_intr();
360                                 
361                                 // read key buffer
362                                 mode = 0xe6;
363                                 process_cmd();
364                         }
365                 }
366         } else if(event_id == EVENT_REPEAT) {
367                 key_register_id = -1;
368                 key_down(key_prev, true);
369         }
370 }
371
372 // shift, ctrl, graph, caps, kana
373 #define IS_LOWBYTE_KEY(c) ((c >= 0x10 && c <= 0x12) || c == 0x14 || c == 0x15)
374
375 void PSUB::key_down(int code, bool repeat)
376 {
377         // check keycode
378         switch(code) {
379         case 0x10:
380                 key_shift = true;
381                 break;
382         case 0x11:
383                 key_ctrl = true;
384                 break;
385         case 0x12:
386                 key_graph = true;
387                 break;
388         case 0x14:
389                 key_caps_locked = !key_caps_locked;
390                 break;
391         case 0x15:
392                 key_kana_locked = !key_kana_locked;
393                 break;
394         }
395         uint16_t lh = get_key(code, repeat);
396         if(lh & 0xff00) {
397                 lh &= ~0x40;
398                 if(!databuf[0x14][0]) {
399                         key_buf->clear();
400                 }
401                 key_buf->write(lh);
402                 key_prev = code;
403                 
404                 // setup key repeat event
405                 if(key_register_id != -1) {
406                         cancel_event(this, key_register_id);
407                         key_register_id = -1;
408                 }
409                 if(!(0x70 <= code && code <= 0x87)) {
410                         if(repeat) {
411                                 register_event(this, EVENT_REPEAT, 61165, false, &key_register_id);     // 61.165 msec
412                         } else {
413                                 register_event(this, EVENT_REPEAT, 557085, false, &key_register_id);    // 557.085 msec
414                         }
415                 }
416                 
417                 // break key is pressed
418                 if((lh >> 8) == 3) {
419                         d_pio->write_signal(SIG_I8255_PORT_B, 0, 1);
420                         key_break = code;
421                 }
422 #ifdef _X1TURBO_FEATURE
423         } else if(key_prev == 0 && IS_LOWBYTE_KEY(code)) {
424                 key_buf->write(0xff);
425 #endif
426         }
427 }
428
429 void PSUB::key_up(int code)
430 {
431         // check keycode
432         switch(code) {
433         case 0x10:
434                 key_shift = false;
435                 break;
436         case 0x11:
437                 key_ctrl = false;
438                 break;
439         case 0x12:
440                 key_graph = false;
441                 break;
442         }
443 #ifdef _X1TURBO_FEATURE
444         if(code == key_prev || (key_prev == 0 && IS_LOWBYTE_KEY(code))) {
445 #else
446         if(code == key_prev) {
447 #endif
448                 // last pressed key is released
449                 if(!databuf[0x14][0]) {
450                         key_buf->clear();
451                 }
452                 key_buf->write(0xff);
453                 key_prev = 0;
454                 if(key_register_id != -1) {
455                         cancel_event(this, key_register_id);
456                         key_register_id = -1;
457                 }
458         }
459         if(code == key_break) {
460                 // break key is released
461                 d_pio->write_signal(SIG_I8255_PORT_B, 0xff, 1);
462                 key_break = 0;
463         }
464 }
465
466 void PSUB::play_tape(bool value)
467 {
468         if(value) {
469                 databuf[0x1a][0] = CMT_STOP;
470         } else {
471                 databuf[0x1a][0] = CMT_EJECT;
472         }
473         play = value;
474         rec = false;
475         d_drec->set_remote(false);
476 }
477
478 void PSUB::rec_tape(bool value)
479 {
480         if(value) {
481                 databuf[0x1a][0] = CMT_STOP;
482         } else {
483                 databuf[0x1a][0] = CMT_EJECT;
484         }
485         play = false;
486         rec = value;
487         d_drec->set_remote(false);
488 }
489
490 void PSUB::close_tape()
491 {
492         if(play || rec) {
493                 databuf[0x1a][0] = CMT_EJECT;
494                 play = rec = false;
495                 d_drec->set_remote(false);
496         }
497 }
498
499 void PSUB::process_cmd()
500 {
501         uint16_t lh = 0xff;
502         
503         // preset 
504         if(0xd0 <= mode && mode < 0xf0) {
505                 datap = &databuf[mode - 0xd0][0]; // send buffer
506         }
507         datalen = 0;
508         
509         // process command
510         switch(mode) {
511         case 0x00:
512                 // reset receive/send buffer
513                 break;
514         case 0xd0:
515         case 0xd1:
516         case 0xd2:
517         case 0xd3:
518         case 0xd4:
519         case 0xd5:
520         case 0xd6:
521         case 0xd7:
522                 // timer set
523                 break;
524         case 0xd8:
525         case 0xd9:
526         case 0xda:
527         case 0xdb:
528         case 0xdc:
529         case 0xdd:
530         case 0xde:
531         case 0xdf:
532                 // timer read
533                 datap = &databuf[mode - 0xd8][0];       // data buffer for timer set
534                 datalen = 6;
535                 break;
536 #ifdef _X1TURBO_FEATURE
537         case 0xe3:
538                 // game key read (for turbo)
539                 databuf[0x13][0] = databuf[0x13][1] = databuf[0x13][2] = 0;
540                 if(config.keyboard_type != 0) {
541                         databuf[0x13][0] |= key_stat[0x51] ? 0x80 : 0;  // q
542                         databuf[0x13][0] |= key_stat[0x57] ? 0x40 : 0;  // w
543                         databuf[0x13][0] |= key_stat[0x45] ? 0x20 : 0;  // e
544                         databuf[0x13][0] |= key_stat[0x41] ? 0x10 : 0;  // a
545                         databuf[0x13][0] |= key_stat[0x44] ? 0x08 : 0;  // d
546                         databuf[0x13][0] |= key_stat[0x5a] ? 0x04 : 0;  // z
547                         databuf[0x13][0] |= key_stat[0x58] ? 0x02 : 0;  // x
548                         databuf[0x13][0] |= key_stat[0x43] ? 0x01 : 0;  // c
549                         databuf[0x13][1] |= key_stat[0x67] ? 0x80 : 0;  // 7
550                         databuf[0x13][1] |= key_stat[0x64] ? 0x40 : 0;  // 4
551                         databuf[0x13][1] |= key_stat[0x61] ? 0x20 : 0;  // 1
552                         databuf[0x13][1] |= key_stat[0x68] ? 0x10 : 0;  // 8
553                         databuf[0x13][1] |= key_stat[0x62] ? 0x08 : 0;  // 2
554                         databuf[0x13][1] |= key_stat[0x69] ? 0x04 : 0;  // 9
555                         databuf[0x13][1] |= key_stat[0x66] ? 0x02 : 0;  // 6
556                         databuf[0x13][1] |= key_stat[0x63] ? 0x01 : 0;  // 3
557                         databuf[0x13][2] |= key_stat[0x1b] ? 0x80 : 0;  // esc
558                         databuf[0x13][2] |= key_stat[0x61] ? 0x40 : 0;  // 1
559                         databuf[0x13][2] |= key_stat[0x6d] ? 0x20 : 0;  // -
560                         databuf[0x13][2] |= key_stat[0x6b] ? 0x10 : 0;  // +
561                         databuf[0x13][2] |= key_stat[0x6a] ? 0x08 : 0;  // *
562                         databuf[0x13][2] |= key_stat[0x09] ? 0x04 : 0;  // tab
563                         databuf[0x13][2] |= key_stat[0x20] ? 0x02 : 0;  // sp
564                         databuf[0x13][2] |= key_stat[0x0d] ? 0x01 : 0;  // ret
565                 }
566                 datalen = 3;
567                 break;
568 #endif
569         case 0xe4:
570                 // irq vector
571 //              if(!databuf[0x14][0]) {
572                         while(!key_buf->empty()) {
573                                 lh = key_buf->read();
574                                 // ???
575                                 databuf[0x16][0] = lh & 0xff;
576                                 databuf[0x16][1] = lh >> 8;
577                         }
578 //              }
579                 intr = false;
580                 update_intr();
581                 break;
582         case 0xe6:
583                 // keydata read
584                 if(!databuf[0x14][0]) {
585                         // interrupt disabled
586                         while(!key_buf->empty()) {
587                                 lh = key_buf->read();
588                                 databuf[0x16][0] = lh & 0xff;
589                                 databuf[0x16][1] = lh >> 8;
590                         }
591                 } else {
592                         // interrupt enabed
593                         if(!key_buf->empty()) {
594                                 lh = key_buf->read();
595                                 databuf[0x16][0] = lh & 0xff;
596                                 databuf[0x16][1] = lh >> 8;
597                         }
598                 }
599 #ifdef _X1TURBO_FEATURE
600                 databuf[0x16][0] &= ~0x1f;
601                 databuf[0x16][0] |= get_key_low() & 0x1f;
602 #endif
603 #ifdef DEBUG_COMMAND
604                 this->out_debug_log(_T("X1 PSUB: keycode %2x %2x\n"), databuf[0x16][0], databuf[0x16][1]);
605 #endif
606                 datalen = 2;
607                 break;
608         case 0xe7:
609                 // TV controll
610                 databuf[0x18][0] = databuf[0x17][0];
611                 break;
612         case 0xe8:
613                 // TV controll read
614                 datalen = 1;
615                 break;
616         case 0xe9:
617                 // CMT controll
618                 if(databuf[0x1a][0] != databuf[0x19][0]) {
619                         uint8_t new_status = databuf[0x19][0];
620                         switch(databuf[0x19][0]) {
621                         case CMT_EJECT:
622                                 emu->close_tape(0);
623                                 break;
624                         case CMT_STOP:
625                                 d_drec->set_remote(false);
626                                 break;
627                         case CMT_PLAY:
628                                 if(play) {
629                                         d_drec->set_ff_rew(0);
630                                         d_drec->set_remote(true);
631                                 } else if(rec) {
632                                         new_status = CMT_STOP;
633                                 } else {
634                                         new_status = CMT_EJECT;
635                                 }
636                                 break;
637                         case CMT_FAST_FWD:
638                                 if(play) {
639                                         d_drec->set_ff_rew(1);
640                                         d_drec->set_remote(true);
641                                 } else if(rec) {
642                                         new_status = CMT_STOP;
643                                 } else {
644                                         new_status = CMT_EJECT;
645                                 }
646                                 break;
647                         case CMT_FAST_REW:
648                                 if(play) {
649                                         d_drec->set_ff_rew(-1);
650                                         d_drec->set_remote(true);
651                                 } else if(rec) {
652                                         new_status = CMT_STOP;
653                                 } else {
654                                         new_status = CMT_EJECT;
655                                 }
656                                 break;
657                         case CMT_APSS_PLUS:
658                         case CMT_APSS_MINUS:
659                                 if(play) {
660                                         d_drec->do_apss((databuf[0x19][0] == CMT_APSS_PLUS) ? 1 : -1);
661                                         new_status = CMT_STOP;
662                                 } else if(rec) {
663                                         new_status = CMT_STOP;
664                                 } else {
665                                         new_status = CMT_EJECT;
666                                 }
667                                 break;
668                         case CMT_REC:
669                                 if(play) {
670                                         new_status = CMT_STOP;
671                                 } else if(rec) {
672                                         d_drec->set_remote(true);
673                                 } else {
674                                         new_status = CMT_EJECT;
675                                 }
676                                 break;
677 #ifdef DEBUG_COMMAND
678                         default:
679                                 this->out_debug_log(_T("X1 PSUB: unknown CMT control %2x\n"), databuf[0x19][0]);
680                                 break;
681 #endif
682                         }
683
684                         databuf[0x1a][0] = new_status;
685                 }
686                 break;
687         case 0xea:
688                 // CMT status
689                 datalen = 1;
690                 break;
691         case 0xeb:
692                 // CMT sensor (bit2=WP, bit1=SET, bit0=END)
693                 databuf[0x1b][0] = (play ? 2 : rec ? 6 : 0) | (play && eot ? 1 : 0);
694                 datalen = 1;
695                 break;
696         case 0xec:
697                 // set calender
698                 cur_time.year = FROM_BCD(databuf[0x1c][0]);
699                 if((databuf[0x1c][1] & 0xf0) != 0) {
700                         cur_time.month = databuf[0x1c][1] >> 4;
701                 }
702 //              cur_time.day_of_week = databuf[0x1c][1] & 7;
703                 if(databuf[0x1c][2] != 0) {
704                         cur_time.day = FROM_BCD(databuf[0x1c][2]);
705                 }
706                 cur_time.update_year();
707                 cur_time.update_day_of_week();
708                 break;
709         case 0xed:
710                 // get calender
711                 databuf[0x1d][0] = TO_BCD(cur_time.year);
712                 databuf[0x1d][1] = (cur_time.month << 4) | cur_time.day_of_week;
713                 databuf[0x1d][2] = TO_BCD(cur_time.day);
714                 datalen = 3;
715                 break;
716         case 0xee:
717                 // set time
718                 cur_time.hour = FROM_BCD(databuf[0x1e][0]);
719                 cur_time.minute = FROM_BCD(databuf[0x1e][1] & 0x7f);
720                 cur_time.second = FROM_BCD(databuf[0x1e][2] & 0x7f);
721                 // restart event
722                 cancel_event(this, time_register_id);
723                 register_event(this, EVENT_1SEC, 1000000, true, &time_register_id);
724                 break;
725         case 0xef:
726                 // get time
727                 databuf[0x1f][0] = TO_BCD(cur_time.hour);
728                 databuf[0x1f][1] = TO_BCD(cur_time.minute);
729                 databuf[0x1f][2] = TO_BCD(cur_time.second);
730                 datalen = 3;
731                 break;
732 #ifdef DEBUG_COMMAND
733         default:
734                 this->out_debug_log(_T("X1 PSUB: unknown cmd %2x\n"), mode);
735 #endif
736         }
737 }
738
739 void PSUB::set_ibf(bool val)
740 {
741         if(ibf != val) {
742                 d_pio->write_signal(SIG_I8255_PORT_B, val ? 0xff : 0, 0x40);
743                 ibf = val;
744         }
745 }
746
747 void PSUB::set_obf(bool val)
748 {
749         if(obf != val) {
750                 d_pio->write_signal(SIG_I8255_PORT_B, val ? 0xff : 0, 0x20);
751                 obf = val;
752         }
753 }
754
755 uint8_t PSUB::get_key_low()
756 {
757         uint8_t l = 0xff;
758         
759         if(key_ctrl) {
760                 l &= ~0x01;     // ctrl
761         }
762         if(key_shift) {
763                 l &= ~0x02;     // shift
764         }
765         if(key_kana_locked) {
766                 l &= ~0x04;     // kana
767         }
768         if(key_caps_locked) {
769                 l &= ~0x08;     // caps
770         }
771         if(key_graph) {
772                 l &= ~0x10;     // graph (alt)
773         }
774         return l;
775 }
776
777 uint16_t PSUB::get_key(int code, bool repeat)
778 {
779         uint8_t l = get_key_low();
780         uint8_t h = 0;
781         
782         if(repeat) {
783                 l &= ~0x20;     // repeat
784         }
785         if(0x60 <= code && code <= 0x74) {
786                 l &= ~0x80;     // function or numpad
787         }
788         if(key_kana_locked) {
789                 if(!(l & 0x02)) {
790 #ifdef _X1TURBO_FEATURE
791                         if(config.keyboard_type != 0) {
792                                 h = keycode_ksb[code];  // kana+shift (mode b)
793                         } else
794 #endif
795                         h = keycode_ks[code];   // kana+shift
796                 } else {
797 #ifdef _X1TURBO_FEATURE
798                         if(config.keyboard_type != 0) {
799                                 h = keycode_kb[code];   // kana (mode b)
800                         } else
801 #endif
802                         h = keycode_k[code];    // kana
803                 }
804         } else {
805                 if(!(l & 0x01)) {
806                         h = keycode_c[code];    // ctrl
807                 } else if(!(l & 0x10)) {
808                         h = keycode_g[code];    // graph
809                 } else {
810                         if(!(l & 0x02)) {
811                                 h = keycode_s[code];    // shift
812                         } else {
813                                 h = keycode[code];      // (none shifted)
814                         }
815                         if(key_caps_locked) {
816                                 if(0x41 <= code && code <= 0x5a) {
817                                         h ^= 0x20;      // alphabet
818                                 }
819                         }
820                 }
821         }
822 #ifndef _X1TURBO_FEATURE
823         if(!h) {
824                 l = 0xff;
825         }
826 #endif
827         return l | (h << 8);
828 }
829
830 #define STATE_VERSION   1
831
832 bool PSUB::process_state(FILEIO* state_fio, bool loading)
833 {
834         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
835                 return false;
836         }
837         if(!state_fio->StateCheckInt32(this_device_id)) {
838                 return false;
839         }
840         if(!cur_time.process_state((void *)state_fio, loading)) {
841                 return false;
842         }
843         state_fio->StateValue(time_register_id);
844         state_fio->StateArray(&databuf[0][0], sizeof(databuf), 1);
845         if(loading) {
846                 intptr_t _d = (intptr_t)(&databuf[0][0]);
847                 datap = (uint8_t*)(_d + state_fio->FgetInt32_LE());
848         } else {
849                 intptr_t _d = (intptr_t)(&databuf[0][0]);
850                 state_fio->FputInt32_LE((int)((intptr_t)datap - _d));
851         }
852         state_fio->StateValue(mode);
853         state_fio->StateValue(inbuf);
854         state_fio->StateValue(outbuf);
855         state_fio->StateValue(ibf);
856         state_fio->StateValue(obf);
857         state_fio->StateValue(cmdlen);
858         state_fio->StateValue(datalen);
859         if(!key_buf->process_state((void *)state_fio, loading)) {
860                 return false;
861         }
862         state_fio->StateValue(key_prev);
863         state_fio->StateValue(key_break);
864         state_fio->StateValue(key_shift);
865         state_fio->StateValue(key_ctrl);
866         state_fio->StateValue(key_graph);
867         state_fio->StateValue(key_caps_locked);
868         state_fio->StateValue(key_kana_locked);
869         state_fio->StateValue(key_register_id);
870         state_fio->StateValue(play);
871         state_fio->StateValue(rec);
872         state_fio->StateValue(eot);
873         state_fio->StateValue(iei);
874         state_fio->StateValue(intr);
875         state_fio->StateValue(intr_bit);
876         return true;
877 }
878
879 }