OSDN Git Service

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