OSDN Git Service

[VM] I forgot to update (and remove USE_SOUND_FILES*) defines.
[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         }
494 }
495
496 void PSUB::process_cmd()
497 {
498         uint16_t lh = 0xff;
499         
500         // preset 
501         if(0xd0 <= mode && mode < 0xf0) {
502                 datap = &databuf[mode - 0xd0][0]; // send buffer
503         }
504         datalen = 0;
505         
506         // process command
507         switch(mode) {
508         case 0x00:
509                 // reset receive/send buffer
510                 break;
511         case 0xd0:
512         case 0xd1:
513         case 0xd2:
514         case 0xd3:
515         case 0xd4:
516         case 0xd5:
517         case 0xd6:
518         case 0xd7:
519                 // timer set
520                 break;
521         case 0xd8:
522         case 0xd9:
523         case 0xda:
524         case 0xdb:
525         case 0xdc:
526         case 0xdd:
527         case 0xde:
528         case 0xdf:
529                 // timer read
530                 datap = &databuf[mode - 0xd8][0];       // data buffer for timer set
531                 datalen = 6;
532                 break;
533 #ifdef _X1TURBO_FEATURE
534         case 0xe3:
535                 // game key read (for turbo)
536                 databuf[0x13][0] = databuf[0x13][1] = databuf[0x13][2] = 0;
537                 if(config.keyboard_type != 0) {
538                         databuf[0x13][0] |= key_stat[0x51] ? 0x80 : 0;  // q
539                         databuf[0x13][0] |= key_stat[0x57] ? 0x40 : 0;  // w
540                         databuf[0x13][0] |= key_stat[0x45] ? 0x20 : 0;  // e
541                         databuf[0x13][0] |= key_stat[0x41] ? 0x10 : 0;  // a
542                         databuf[0x13][0] |= key_stat[0x44] ? 0x08 : 0;  // d
543                         databuf[0x13][0] |= key_stat[0x5a] ? 0x04 : 0;  // z
544                         databuf[0x13][0] |= key_stat[0x58] ? 0x02 : 0;  // x
545                         databuf[0x13][0] |= key_stat[0x43] ? 0x01 : 0;  // c
546                         databuf[0x13][1] |= key_stat[0x67] ? 0x80 : 0;  // 7
547                         databuf[0x13][1] |= key_stat[0x64] ? 0x40 : 0;  // 4
548                         databuf[0x13][1] |= key_stat[0x61] ? 0x20 : 0;  // 1
549                         databuf[0x13][1] |= key_stat[0x68] ? 0x10 : 0;  // 8
550                         databuf[0x13][1] |= key_stat[0x62] ? 0x08 : 0;  // 2
551                         databuf[0x13][1] |= key_stat[0x69] ? 0x04 : 0;  // 9
552                         databuf[0x13][1] |= key_stat[0x66] ? 0x02 : 0;  // 6
553                         databuf[0x13][1] |= key_stat[0x63] ? 0x01 : 0;  // 3
554                         databuf[0x13][2] |= key_stat[0x1b] ? 0x80 : 0;  // esc
555                         databuf[0x13][2] |= key_stat[0x61] ? 0x40 : 0;  // 1
556                         databuf[0x13][2] |= key_stat[0x6d] ? 0x20 : 0;  // -
557                         databuf[0x13][2] |= key_stat[0x6b] ? 0x10 : 0;  // +
558                         databuf[0x13][2] |= key_stat[0x6a] ? 0x08 : 0;  // *
559                         databuf[0x13][2] |= key_stat[0x09] ? 0x04 : 0;  // tab
560                         databuf[0x13][2] |= key_stat[0x20] ? 0x02 : 0;  // sp
561                         databuf[0x13][2] |= key_stat[0x0d] ? 0x01 : 0;  // ret
562                 }
563                 datalen = 3;
564                 break;
565 #endif
566         case 0xe4:
567                 // irq vector
568 //              if(!databuf[0x14][0]) {
569                         while(!key_buf->empty()) {
570                                 lh = key_buf->read();
571                                 // ???
572                                 databuf[0x16][0] = lh & 0xff;
573                                 databuf[0x16][1] = lh >> 8;
574                         }
575 //              }
576                 intr = false;
577                 update_intr();
578                 break;
579         case 0xe6:
580                 // keydata read
581                 if(!databuf[0x14][0]) {
582                         // interrupt disabled
583                         while(!key_buf->empty()) {
584                                 lh = key_buf->read();
585                                 databuf[0x16][0] = lh & 0xff;
586                                 databuf[0x16][1] = lh >> 8;
587                         }
588                 } else {
589                         // interrupt enabed
590                         if(!key_buf->empty()) {
591                                 lh = key_buf->read();
592                                 databuf[0x16][0] = lh & 0xff;
593                                 databuf[0x16][1] = lh >> 8;
594                         }
595                 }
596 #ifdef _X1TURBO_FEATURE
597                 databuf[0x16][0] &= ~0x1f;
598                 databuf[0x16][0] |= get_key_low() & 0x1f;
599 #endif
600 #ifdef DEBUG_COMMAND
601                 this->out_debug_log(_T("X1 PSUB: keycode %2x %2x\n"), databuf[0x16][0], databuf[0x16][1]);
602 #endif
603                 datalen = 2;
604                 break;
605         case 0xe7:
606                 // TV controll
607                 databuf[0x18][0] = databuf[0x17][0];
608                 break;
609         case 0xe8:
610                 // TV controll read
611                 datalen = 1;
612                 break;
613         case 0xe9:
614                 // CMT controll
615                 if(databuf[0x1a][0] != databuf[0x19][0]) {
616                         uint8_t new_status = databuf[0x19][0];
617                         switch(databuf[0x19][0]) {
618                         case CMT_EJECT:
619                                 emu->close_tape(0);
620                                 break;
621                         case CMT_STOP:
622                                 d_drec->set_remote(false);
623                                 break;
624                         case CMT_PLAY:
625                                 if(play) {
626                                         d_drec->set_ff_rew(0);
627                                         d_drec->set_remote(true);
628                                 } else if(rec) {
629                                         new_status = CMT_STOP;
630                                 } else {
631                                         new_status = CMT_EJECT;
632                                 }
633                                 break;
634                         case CMT_FAST_FWD:
635                                 if(play) {
636                                         d_drec->set_ff_rew(1);
637                                         d_drec->set_remote(true);
638                                 } else if(rec) {
639                                         new_status = CMT_STOP;
640                                 } else {
641                                         new_status = CMT_EJECT;
642                                 }
643                                 break;
644                         case CMT_FAST_REW:
645                                 if(play) {
646                                         d_drec->set_ff_rew(-1);
647                                         d_drec->set_remote(true);
648                                 } else if(rec) {
649                                         new_status = CMT_STOP;
650                                 } else {
651                                         new_status = CMT_EJECT;
652                                 }
653                                 break;
654                         case CMT_APSS_PLUS:
655                         case CMT_APSS_MINUS:
656                                 if(play) {
657                                         d_drec->do_apss((databuf[0x19][0] == CMT_APSS_PLUS) ? 1 : -1);
658                                         new_status = CMT_STOP;
659                                 } else if(rec) {
660                                         new_status = CMT_STOP;
661                                 } else {
662                                         new_status = CMT_EJECT;
663                                 }
664                                 break;
665                         case CMT_REC:
666                                 if(play) {
667                                         new_status = CMT_STOP;
668                                 } else if(rec) {
669                                         d_drec->set_remote(true);
670                                 } else {
671                                         new_status = CMT_EJECT;
672                                 }
673                                 break;
674 #ifdef DEBUG_COMMAND
675                         default:
676                                 this->out_debug_log(_T("X1 PSUB: unknown CMT control %2x\n"), databuf[0x19][0]);
677                                 break;
678 #endif
679                         }
680
681                         databuf[0x1a][0] = new_status;
682                 }
683                 break;
684         case 0xea:
685                 // CMT status
686                 datalen = 1;
687                 break;
688         case 0xeb:
689                 // CMT sensor (bit2=WP, bit1=SET, bit0=END)
690                 databuf[0x1b][0] = (play ? 2 : rec ? 6 : 0) | (play && eot ? 1 : 0);
691                 datalen = 1;
692                 break;
693         case 0xec:
694                 // set calender
695                 cur_time.year = FROM_BCD(databuf[0x1c][0]);
696                 if((databuf[0x1c][1] & 0xf0) != 0) {
697                         cur_time.month = databuf[0x1c][1] >> 4;
698                 }
699 //              cur_time.day_of_week = databuf[0x1c][1] & 7;
700                 if(databuf[0x1c][2] != 0) {
701                         cur_time.day = FROM_BCD(databuf[0x1c][2]);
702                 }
703                 cur_time.update_year();
704                 cur_time.update_day_of_week();
705                 break;
706         case 0xed:
707                 // get calender
708                 databuf[0x1d][0] = TO_BCD(cur_time.year);
709                 databuf[0x1d][1] = (cur_time.month << 4) | cur_time.day_of_week;
710                 databuf[0x1d][2] = TO_BCD(cur_time.day);
711                 datalen = 3;
712                 break;
713         case 0xee:
714                 // set time
715                 cur_time.hour = FROM_BCD(databuf[0x1e][0]);
716                 cur_time.minute = FROM_BCD(databuf[0x1e][1] & 0x7f);
717                 cur_time.second = FROM_BCD(databuf[0x1e][2] & 0x7f);
718                 // restart event
719                 cancel_event(this, time_register_id);
720                 register_event(this, EVENT_1SEC, 1000000, true, &time_register_id);
721                 break;
722         case 0xef:
723                 // get time
724                 databuf[0x1f][0] = TO_BCD(cur_time.hour);
725                 databuf[0x1f][1] = TO_BCD(cur_time.minute);
726                 databuf[0x1f][2] = TO_BCD(cur_time.second);
727                 datalen = 3;
728                 break;
729 #ifdef DEBUG_COMMAND
730         default:
731                 this->out_debug_log(_T("X1 PSUB: unknown cmd %2x\n"), mode);
732 #endif
733         }
734 }
735
736 void PSUB::set_ibf(bool val)
737 {
738         if(ibf != val) {
739                 d_pio->write_signal(SIG_I8255_PORT_B, val ? 0xff : 0, 0x40);
740                 ibf = val;
741         }
742 }
743
744 void PSUB::set_obf(bool val)
745 {
746         if(obf != val) {
747                 d_pio->write_signal(SIG_I8255_PORT_B, val ? 0xff : 0, 0x20);
748                 obf = val;
749         }
750 }
751
752 uint8_t PSUB::get_key_low()
753 {
754         uint8_t l = 0xff;
755         
756         if(key_ctrl) {
757                 l &= ~0x01;     // ctrl
758         }
759         if(key_shift) {
760                 l &= ~0x02;     // shift
761         }
762         if(key_kana_locked) {
763                 l &= ~0x04;     // kana
764         }
765         if(key_caps_locked) {
766                 l &= ~0x08;     // caps
767         }
768         if(key_graph) {
769                 l &= ~0x10;     // graph (alt)
770         }
771         return l;
772 }
773
774 uint16_t PSUB::get_key(int code, bool repeat)
775 {
776         uint8_t l = get_key_low();
777         uint8_t h = 0;
778         
779         if(repeat) {
780                 l &= ~0x20;     // repeat
781         }
782         if(0x60 <= code && code <= 0x74) {
783                 l &= ~0x80;     // function or numpad
784         }
785         if(key_kana_locked) {
786                 if(!(l & 0x02)) {
787 #ifdef _X1TURBO_FEATURE
788                         if(config.keyboard_type != 0) {
789                                 h = keycode_ksb[code];  // kana+shift (mode b)
790                         } else
791 #endif
792                         h = keycode_ks[code];   // kana+shift
793                 } else {
794 #ifdef _X1TURBO_FEATURE
795                         if(config.keyboard_type != 0) {
796                                 h = keycode_kb[code];   // kana (mode b)
797                         } else
798 #endif
799                         h = keycode_k[code];    // kana
800                 }
801         } else {
802                 if(!(l & 0x01)) {
803                         h = keycode_c[code];    // ctrl
804                 } else if(!(l & 0x10)) {
805                         h = keycode_g[code];    // graph
806                 } else {
807                         if(!(l & 0x02)) {
808                                 h = keycode_s[code];    // shift
809                         } else {
810                                 h = keycode[code];      // (none shifted)
811                         }
812                         if(key_caps_locked) {
813                                 if(0x41 <= code && code <= 0x5a) {
814                                         h ^= 0x20;      // alphabet
815                                 }
816                         }
817                 }
818         }
819 #ifndef _X1TURBO_FEATURE
820         if(!h) {
821                 l = 0xff;
822         }
823 #endif
824         return l | (h << 8);
825 }
826
827 #define STATE_VERSION   1
828
829 void PSUB::save_state(FILEIO* state_fio)
830 {
831         state_fio->FputUint32(STATE_VERSION);
832         state_fio->FputInt32(this_device_id);
833         
834         cur_time.save_state((void *)state_fio);
835         state_fio->FputInt32(time_register_id);
836         state_fio->Fwrite(databuf, sizeof(databuf), 1);
837         state_fio->FputInt32((int)(datap - &databuf[0][0]));
838         state_fio->FputUint8(mode);
839         state_fio->FputUint8(inbuf);
840         state_fio->FputUint8(outbuf);
841         state_fio->FputBool(ibf);
842         state_fio->FputBool(obf);
843         state_fio->FputInt32(cmdlen);
844         state_fio->FputInt32(datalen);
845         key_buf->save_state((void *)state_fio);
846         state_fio->FputInt32(key_prev);
847         state_fio->FputInt32(key_break);
848         state_fio->FputBool(key_shift);
849         state_fio->FputBool(key_ctrl);
850         state_fio->FputBool(key_graph);
851         state_fio->FputBool(key_caps_locked);
852         state_fio->FputBool(key_kana_locked);
853         state_fio->FputInt32(key_register_id);
854         state_fio->FputBool(play);
855         state_fio->FputBool(rec);
856         state_fio->FputBool(eot);
857         state_fio->FputBool(iei);
858         state_fio->FputBool(intr);
859         state_fio->FputUint32(intr_bit);
860 }
861
862 bool PSUB::load_state(FILEIO* state_fio)
863 {
864         if(state_fio->FgetUint32() != STATE_VERSION) {
865                 return false;
866         }
867         if(state_fio->FgetInt32() != this_device_id) {
868                 return false;
869         }
870         if(!cur_time.load_state((void *)state_fio)) {
871                 return false;
872         }
873         time_register_id = state_fio->FgetInt32();
874         state_fio->Fread(databuf, sizeof(databuf), 1);
875         datap = &databuf[0][0] + state_fio->FgetInt32();
876         mode = state_fio->FgetUint8();
877         inbuf = state_fio->FgetUint8();
878         outbuf = state_fio->FgetUint8();
879         ibf = state_fio->FgetBool();
880         obf = state_fio->FgetBool();
881         cmdlen = state_fio->FgetInt32();
882         datalen = state_fio->FgetInt32();
883         if(!key_buf->load_state((void *)state_fio)) {
884                 return false;
885         }
886         key_prev = state_fio->FgetInt32();
887         key_break = state_fio->FgetInt32();
888         key_shift = state_fio->FgetBool();
889         key_ctrl = state_fio->FgetBool();
890         key_graph = state_fio->FgetBool();
891         key_caps_locked = state_fio->FgetBool();
892         key_kana_locked = state_fio->FgetBool();
893         key_register_id = state_fio->FgetInt32();
894         play = state_fio->FgetBool();
895         rec = state_fio->FgetBool();
896         eot = state_fio->FgetBool();
897         iei = state_fio->FgetBool();
898         intr = state_fio->FgetBool();
899         intr_bit = state_fio->FgetUint32();
900         return true;
901 }
902