OSDN Git Service

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