OSDN Git Service

[VM] Update emu->out_debug_log to [DEVICE]->out_debug_log .
[csp-qt/common_source_project-fm7.git] / source / src / vm / fp200 / io.cpp
1 /*
2         CASIO FP-200 Emulator 'eFP-200'
3
4         Author : Takeda.Toshiya
5         Date   : 2013.03.21-
6
7         [ io ]
8 */
9
10 #include "io.h"
11 #include "../datarec.h"
12 #include "../i8080.h"
13
14 #define EVENT_CMT_READY 0
15 #define EVENT_CMT_CLOCK 1
16
17 #define CMT_MODE_REC    1
18 #define CMT_MODE_PLAY   3
19
20 #define CMT_RECORDING   (cmt_selected && cmt_mode == CMT_MODE_REC && cmt_rec)
21 #define CMT_PLAYING     (cmt_selected && cmt_mode == CMT_MODE_PLAY)
22
23 #define CMT_SAMPLE_RATE 48000
24
25 // based on elisa font (http://hp.vector.co.jp/authors/VA002310/index.htm
26 static const uint8_t elisa_font[2048] = {
27         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
28         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
30         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
32         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
33         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
35         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
37         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
38         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
39         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
40         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
41         0x08, 0x04, 0x02, 0x7f, 0x02, 0x04, 0x08, 0x00, 0x08, 0x10, 0x20, 0x7f, 0x20, 0x10, 0x08, 0x00,
42         0x08, 0x1c, 0x2a, 0x49, 0x08, 0x08, 0x08, 0x00, 0x08, 0x08, 0x08, 0x49, 0x2a, 0x1c, 0x08, 0x00,
43         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x08,
44         0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x7f, 0x24, 0x24, 0xfe, 0x48, 0x48,
45         0x08, 0x1c, 0x2a, 0x1c, 0x0a, 0x2a, 0x1c, 0x08, 0x61, 0x92, 0x94, 0x68, 0x16, 0x29, 0x49, 0x86,
46         0x30, 0x48, 0x48, 0x32, 0x4a, 0x44, 0x3a, 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
47         0x03, 0x04, 0x08, 0x08, 0x08, 0x08, 0x04, 0x03, 0xc0, 0x20, 0x10, 0x10, 0x10, 0x10, 0x20, 0xc0,
48         0x08, 0x2a, 0x1c, 0x08, 0x1c, 0x2a, 0x08, 0x00, 0x08, 0x08, 0x08, 0x7f, 0x08, 0x08, 0x08, 0x00,
49         0x00, 0x00, 0x00, 0x00, 0x60, 0x60, 0x20, 0x40, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00,
50         0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x60, 0x00, 0x00, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x00,
51         0x3c, 0x42, 0x46, 0x5a, 0x62, 0x42, 0x3c, 0x00, 0x08, 0x18, 0x08, 0x08, 0x08, 0x08, 0x1c, 0x00,
52         0x3c, 0x42, 0x02, 0x0c, 0x10, 0x20, 0x7e, 0x00, 0x3c, 0x42, 0x02, 0x3c, 0x02, 0x42, 0x3c, 0x00,
53         0x04, 0x0c, 0x14, 0x24, 0x44, 0x7e, 0x04, 0x00, 0x7e, 0x40, 0x40, 0x7c, 0x02, 0x02, 0x7c, 0x00,
54         0x3c, 0x42, 0x40, 0x7c, 0x42, 0x42, 0x3c, 0x00, 0x7e, 0x02, 0x04, 0x08, 0x10, 0x10, 0x10, 0x00,
55         0x3c, 0x42, 0x42, 0x3c, 0x42, 0x42, 0x3c, 0x00, 0x3c, 0x42, 0x42, 0x3e, 0x02, 0x42, 0x3c, 0x00,
56         0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x08, 0x10,
57         0x03, 0x0c, 0x30, 0xc0, 0x30, 0x0c, 0x03, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x7e, 0x00, 0x00, 0x00,
58         0xc0, 0x30, 0x0c, 0x03, 0x0c, 0x30, 0xc0, 0x00, 0x1c, 0x22, 0x22, 0x04, 0x08, 0x08, 0x00, 0x08,
59         0x1c, 0x22, 0x4d, 0x55, 0x47, 0x5f, 0x20, 0x1e, 0x18, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x00,
60         0x7c, 0x42, 0x42, 0x7c, 0x42, 0x42, 0x7c, 0x00, 0x1c, 0x22, 0x40, 0x40, 0x40, 0x22, 0x1c, 0x00,
61         0x78, 0x24, 0x22, 0x22, 0x22, 0x24, 0x78, 0x00, 0x7e, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x7e, 0x00,
62         0x7e, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x40, 0x00, 0x1c, 0x22, 0x40, 0x47, 0x42, 0x26, 0x1a, 0x00,
63         0x42, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x1c, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1c, 0x00,
64         0x0e, 0x04, 0x04, 0x04, 0x44, 0x44, 0x38, 0x00, 0x42, 0x44, 0x48, 0x50, 0x68, 0x44, 0x42, 0x00,
65         0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x7e, 0x00, 0x41, 0x63, 0x55, 0x49, 0x41, 0x41, 0x41, 0x00,
66         0x42, 0x62, 0x52, 0x4a, 0x46, 0x42, 0x42, 0x00, 0x18, 0x24, 0x42, 0x42, 0x42, 0x24, 0x18, 0x00,
67         0x7c, 0x42, 0x42, 0x7c, 0x40, 0x40, 0x40, 0x00, 0x18, 0x24, 0x42, 0x42, 0x4a, 0x24, 0x1a, 0x00,
68         0x7c, 0x42, 0x42, 0x7c, 0x48, 0x44, 0x42, 0x00, 0x3c, 0x42, 0x40, 0x3c, 0x02, 0x42, 0x3c, 0x00,
69         0x7f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00,
70         0x41, 0x41, 0x22, 0x22, 0x14, 0x14, 0x08, 0x00, 0x41, 0x49, 0x49, 0x55, 0x55, 0x22, 0x22, 0x00,
71         0x41, 0x22, 0x14, 0x08, 0x14, 0x22, 0x41, 0x00, 0x41, 0x22, 0x14, 0x08, 0x08, 0x08, 0x08, 0x00,
72         0x7e, 0x02, 0x04, 0x08, 0x10, 0x20, 0x7e, 0x00, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07,
73         0x41, 0x22, 0x14, 0x7f, 0x08, 0x7f, 0x08, 0x08, 0xe0, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xe0,
74         0x08, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00,
75         0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x02, 0x1e, 0x22, 0x1e, 0x00,
76         0x20, 0x20, 0x20, 0x3c, 0x22, 0x22, 0x3c, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x20, 0x22, 0x1c, 0x00,
77         0x02, 0x02, 0x02, 0x1e, 0x22, 0x22, 0x1e, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x3e, 0x20, 0x1e, 0x00,
78         0x0c, 0x12, 0x10, 0x3c, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x22, 0x1e, 0x02, 0x3c,
79         0x20, 0x20, 0x3c, 0x22, 0x22, 0x22, 0x22, 0x00, 0x08, 0x00, 0x18, 0x08, 0x08, 0x08, 0x1c, 0x00,
80         0x08, 0x00, 0x18, 0x08, 0x08, 0x08, 0x48, 0x30, 0x20, 0x20, 0x24, 0x28, 0x30, 0x28, 0x24, 0x00,
81         0x18, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x3c, 0x2a, 0x2a, 0x2a, 0x2a, 0x00,
82         0x00, 0x00, 0x3c, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x22, 0x22, 0x1c, 0x00,
83         0x00, 0x00, 0x3c, 0x22, 0x22, 0x3c, 0x20, 0x20, 0x00, 0x00, 0x1e, 0x22, 0x22, 0x1e, 0x02, 0x02,
84         0x00, 0x00, 0x2e, 0x30, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x1e, 0x20, 0x1c, 0x02, 0x3c, 0x00,
85         0x00, 0x10, 0x3c, 0x10, 0x10, 0x10, 0x0c, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x1e, 0x00,
86         0x00, 0x00, 0x22, 0x22, 0x14, 0x14, 0x08, 0x00, 0x00, 0x00, 0x22, 0x2a, 0x2a, 0x14, 0x14, 0x00,
87         0x00, 0x00, 0x22, 0x14, 0x08, 0x14, 0x22, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x1e, 0x02, 0x3c,
88         0x00, 0x00, 0x3e, 0x04, 0x08, 0x10, 0x3e, 0x00, 0x03, 0x04, 0x04, 0x08, 0x04, 0x04, 0x04, 0x03,
89         0x08, 0x08, 0x08, 0x00, 0x08, 0x08, 0x08, 0x00, 0xc0, 0x20, 0x20, 0x10, 0x20, 0x20, 0x20, 0xc0,
90         0x00, 0x00, 0x30, 0x49, 0x06, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x22, 0x10, 0x08, 0x08, 0x00, 0x08,
91         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
92         0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
93         0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
94         0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
95         0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
96         0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
97         0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
98         0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0x08, 0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08,
99         0x08, 0x08, 0x08, 0x08, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x08, 0x08, 0x08,
100         0x08, 0x08, 0x08, 0x08, 0xf8, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08,
101         0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
102         0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
103         0x00, 0x00, 0x00, 0x00, 0x0f, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x08, 0x08, 0x08,
104         0x08, 0x08, 0x08, 0x08, 0x0f, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0xf8, 0x00, 0x00, 0x00,
105         0x00, 0x00, 0x00, 0x07, 0x08, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0xc0, 0x20, 0x10, 0x10, 0x10,
106         0x10, 0x10, 0x08, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x20, 0xc0, 0x00, 0x00, 0x00, 0x00,
107         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xa0, 0x40,
108         0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xf0,
109         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x20, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
110         0x00, 0x7e, 0x02, 0x7e, 0x02, 0x04, 0x08, 0x30, 0x00, 0x00, 0x00, 0x3e, 0x0a, 0x0c, 0x08, 0x10,
111         0x00, 0x00, 0x00, 0x04, 0x08, 0x18, 0x28, 0x08, 0x00, 0x00, 0x00, 0x08, 0x3e, 0x22, 0x02, 0x0c,
112         0x00, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x04, 0x3e, 0x0c, 0x14, 0x24,
113         0x00, 0x00, 0x00, 0x10, 0x3e, 0x12, 0x14, 0x10, 0x00, 0x00, 0x00, 0x00, 0x38, 0x08, 0x08, 0x7c,
114         0x00, 0x00, 0x00, 0x3c, 0x04, 0x3c, 0x04, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x52, 0x52, 0x04, 0x18,
115         0x00, 0x00, 0x00, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x01, 0x0a, 0x0c, 0x08, 0x08, 0x10,
116         0x00, 0x02, 0x04, 0x08, 0x18, 0x28, 0x48, 0x08, 0x08, 0x08, 0x7e, 0x42, 0x42, 0x02, 0x04, 0x18,
117         0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x7f, 0x04, 0x04, 0x7f, 0x04, 0x0c, 0x14, 0x24, 0x44,
118         0x10, 0x10, 0x7e, 0x12, 0x12, 0x22, 0x22, 0x44, 0x10, 0x10, 0x7f, 0x08, 0x7f, 0x08, 0x04, 0x04,
119         0x20, 0x3e, 0x22, 0x42, 0x02, 0x04, 0x04, 0x18, 0x20, 0x20, 0x3f, 0x24, 0x44, 0x04, 0x08, 0x30,
120         0x00, 0x00, 0x7e, 0x02, 0x02, 0x02, 0x02, 0x7e, 0x00, 0x24, 0xff, 0x24, 0x24, 0x04, 0x04, 0x18,
121         0x00, 0x40, 0x20, 0x42, 0x22, 0x04, 0x08, 0x70, 0x00, 0x7e, 0x02, 0x04, 0x08, 0x14, 0x22, 0x41,
122         0x20, 0x20, 0x7e, 0x22, 0x24, 0x28, 0x20, 0x1e, 0x00, 0x41, 0x41, 0x21, 0x02, 0x02, 0x04, 0x18,
123         0x10, 0x1e, 0x12, 0x32, 0x4e, 0x04, 0x08, 0x70, 0x06, 0x38, 0x08, 0x7f, 0x08, 0x08, 0x08, 0x30,
124         0x00, 0x52, 0x52, 0x02, 0x04, 0x04, 0x08, 0x30, 0x3e, 0x00, 0x00, 0x7f, 0x08, 0x08, 0x08, 0x30,
125         0x20, 0x20, 0x20, 0x38, 0x24, 0x22, 0x20, 0x20, 0x04, 0x04, 0x7f, 0x04, 0x04, 0x04, 0x08, 0x30,
126         0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x7e, 0x02, 0x22, 0x14, 0x0c, 0x12, 0x60,
127         0x08, 0x08, 0x7f, 0x01, 0x06, 0x1a, 0x69, 0x08, 0x00, 0x02, 0x02, 0x02, 0x04, 0x04, 0x08, 0x30,
128         0x00, 0x00, 0x24, 0x24, 0x22, 0x42, 0x81, 0x00, 0x00, 0x40, 0x40, 0x7e, 0x40, 0x40, 0x40, 0x3e,
129         0x00, 0x00, 0x7e, 0x02, 0x02, 0x04, 0x08, 0x30, 0x00, 0x00, 0x18, 0x24, 0x42, 0x01, 0x00, 0x00,
130         0x08, 0x08, 0x7f, 0x08, 0x08, 0x2a, 0x49, 0x08, 0x00, 0x7e, 0x02, 0x02, 0x24, 0x18, 0x08, 0x04,
131         0x00, 0x18, 0x06, 0x18, 0x06, 0x00, 0x30, 0x0e, 0x00, 0x08, 0x08, 0x10, 0x10, 0x24, 0x42, 0x7d,
132         0x00, 0x01, 0x01, 0x12, 0x0a, 0x04, 0x0a, 0x30, 0x00, 0x7e, 0x10, 0x10, 0x7f, 0x10, 0x10, 0x1e,
133         0x10, 0x10, 0xff, 0x11, 0x12, 0x14, 0x10, 0x10, 0x00, 0x00, 0x3c, 0x04, 0x04, 0x04, 0x04, 0x7e,
134         0x00, 0x7e, 0x02, 0x02, 0x7e, 0x02, 0x02, 0x7e, 0x00, 0x3c, 0x00, 0x7e, 0x02, 0x02, 0x04, 0x38,
135         0x00, 0x22, 0x22, 0x22, 0x22, 0x02, 0x04, 0x18, 0x00, 0x28, 0x28, 0x28, 0x28, 0x29, 0x2a, 0x4c,
136         0x00, 0x20, 0x20, 0x20, 0x22, 0x22, 0x24, 0x38, 0x00, 0x7e, 0x42, 0x42, 0x42, 0x42, 0x42, 0x7e,
137         0x00, 0x7e, 0x42, 0x42, 0x02, 0x04, 0x08, 0x30, 0x00, 0x40, 0x20, 0x02, 0x02, 0x04, 0x08, 0x70,
138         0xa0, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xa0, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
139         0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x0f, 0x08, 0x08,
140         0x08, 0x08, 0xff, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, 0xf8, 0x08, 0x08, 0xf8, 0x08, 0x08,
141         0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff,
142         0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01, 0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80,
143         0x08, 0x1c, 0x3e, 0x7f, 0x7f, 0x1c, 0x3e, 0x00, 0x36, 0x7f, 0x7f, 0x7f, 0x3e, 0x1c, 0x08, 0x00,
144         0x08, 0x1c, 0x3e, 0x7f, 0x3e, 0x1c, 0x08, 0x00, 0x1c, 0x1c, 0x6b, 0x7f, 0x6b, 0x08, 0x1c, 0x00,
145         0x1c, 0x3e, 0x7f, 0x7f, 0x7f, 0x3e, 0x1c, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, 0x22, 0x1c, 0x00,
146         0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01,
147         0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81, 0x7f, 0x49, 0x49, 0x49, 0x7f, 0x41, 0x41, 0x43,
148         0x20, 0x3e, 0x48, 0xbe, 0x28, 0xff, 0x08, 0x08, 0x3f, 0x21, 0x3f, 0x21, 0x3f, 0x21, 0x41, 0x83,
149         0x7e, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x7e, 0x04, 0xee, 0xa4, 0xff, 0xa2, 0xbf, 0xe2, 0x0a,
150         0x18, 0x04, 0x42, 0xbd, 0x14, 0x14, 0x24, 0x4c, 0x24, 0xc4, 0x4e, 0xed, 0x55, 0xe6, 0xc4, 0x58,
151         0x7f, 0x00, 0x7f, 0x08, 0x08, 0x08, 0x08, 0x00, 0x08, 0x7f, 0x08, 0x7f, 0x49, 0x49, 0x4b, 0x08,
152         0xff, 0x80, 0xa4, 0x94, 0x88, 0x94, 0xe0, 0xff, 0xf8, 0xaf, 0xfa, 0xaa, 0xaa, 0xfa, 0x02, 0x06,
153         0x22, 0xf2, 0x2f, 0x72, 0x6a, 0xa2, 0x22, 0x26, 0x08, 0x08, 0x08, 0x08, 0x08, 0x14, 0x22, 0xc1,
154         0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0x00, 0x00, 0x10, 0x08, 0x04, 0x04, 0x00, 0x00,
155 };
156
157 static const uint8_t key_table[10][8] = {
158         {0x00, 0x00, 0x00, 0x00, 0x37, 0x55, 0x4a, 0x4d},
159         {0x00, 0x00, 0x00, 0x00, 0x38, 0x49, 0x4b, 0xbf},
160         {0x00, 0x00, 0x00, 0x00, 0x39, 0x4f, 0x4c, 0xbe},
161         {0x00, 0x00, 0x00, 0x00, 0x30, 0x50, 0xbc, 0xbb},
162         {0x15, 0x2e, 0x24, 0x70, 0x31, 0x51, 0x41, 0x5a},
163         {0x13, 0xdc, 0x27, 0x71, 0x32, 0x57, 0x53, 0x58},
164         {0x20, 0xde, 0x25, 0x72, 0x33, 0x45, 0x44, 0x43},
165         {0xc0, 0xbd, 0x28, 0x73, 0x34, 0x52, 0x46, 0x56},
166         {0xdb, 0xba, 0x26, 0x74, 0x35, 0x54, 0x47, 0x42},
167         {0x0d, 0xdd, 0x14, 0xe2, 0x36, 0x59, 0x48, 0x4e}
168 };
169
170 void IO::initialize()
171 {
172         FILEIO* fio = new FILEIO();
173         if(fio->Fopen(create_local_path(_T("FONT.ROM")), FILEIO_READ_BINARY)) {
174                 fio->Fread(font, sizeof(font), 1);
175                 fio->Fclose();
176         } else {
177                 memcpy(font, elisa_font, sizeof(font));
178         }
179         delete fio;
180         
181         sod = false;
182         
183         cmt_fio = new FILEIO();
184         cmt_rec = cmt_is_wav = false;
185         cmt_bufcnt = 0;
186         
187         memset(&b16_1, 0, sizeof(b16_1));
188         memset(&b16_2, 0, sizeof(b16_2));
189         memset(&g21_1, 0, sizeof(g21_1));
190         memset(&g21_2, 0, sizeof(g21_2));
191         memset(&c15, 0, sizeof(c15));
192         memset(&c16, 0, sizeof(c16));
193         memset(&f21, 0, sizeof(f21));
194         
195         cmt_clock = 0;
196         b16_1.in_s = b16_1.in_r = true;
197         b16_2.in_s = b16_2.in_r = true;
198         g21_1.in_s = true;
199         g21_2.in_s = g21_2.in_r = true;
200         g21_1.in_d = true;      // f21:q5 and f21:q6 are low
201         c15.in_b = true;        // 300baud
202         c15.in_c = false;       // load clock
203         c15.in_s = false;
204         update_cmt();
205         
206         register_event(this, EVENT_CMT_READY, 1000000.0 / 300.0, true, NULL); // 300baud
207         register_event(this, EVENT_CMT_CLOCK, 1000000.0 / 76800.0, true, NULL);
208         
209         key_stat = emu->get_key_buffer();
210 }
211
212 void IO::release()
213 {
214         close_tape();
215         delete cmt_fio;
216 }
217
218 void IO::reset()
219 {
220         mode_basic = (config.boot_mode == 0);
221         
222         memset(lcd, 0, sizeof(lcd));
223         lcd[0].cursor = lcd[1].cursor = -1;
224         lcd_status = lcd_addr = 0;
225         lcd_text = true;
226         
227         close_tape();
228         cmt_selected = false;
229         cmt_mode = 0;
230         cmt_play_ready = cmt_play_signal = cmt_rec_ready = false;
231         
232         key_column = 0;
233         update_sid();
234 }
235
236 #define REVERSE(v) (((v) & 0x80) >> 7) | (((v) & 0x40) >> 5) | (((v) & 0x20) >> 3) | (((v) & 0x10) >> 1) | (((v) & 0x08) << 1) | (((v) & 0x04) << 3) | (((v) & 0x02) << 5) | (((v) & 0x01) << 7)
237
238 void IO::write_io8(uint32_t addr, uint32_t data)
239 {
240 #ifdef _IO_DEBUG_LOG
241         this->out_debug_log(_T("%06x\tSOD=%d\tOUT8\t%04x, %02x\n"), get_cpu_pc(0), sod ? 1 : 0, addr & 0xff, data & 0xff);
242 #endif
243         
244         if(sod) {
245                 switch(addr & 0xff) {
246                 case 0x01:
247                 case 0x02:
248                         if(lcd_status == 0xb0) {
249                                 if(data == 0x40) {
250                                         lcd_text = false;
251                                 } else if(data == 0x50) {
252                                         lcd[addr & 1].offset = lcd_addr & 0x3ff;
253                                 } else {
254                                         lcd_text = true;
255                                 }
256                         } else if(lcd_status == 0x10) {
257                                 if(lcd_text) {
258                                         for(int l = 0; l < 8; l++) {
259                                                 lcd[addr & 1].ram[(lcd_addr + 16 * l) & 0x3ff] = REVERSE(font[data * 8 + l]);
260                                         }
261                                 } else {
262                                         lcd[addr & 1].ram[lcd_addr & 0x3ff] = data;
263                                 }
264                         }
265                         break;
266                 case 0x08:
267                         if((lcd_status = data & 0xf0) == 0xb0) {
268                                 lcd_addr = (lcd_addr & 0xff) | (data << 8);
269                         }
270                         break;
271                 case 0x09:
272                         lcd_addr = (lcd_addr & 0xff00) | data;
273                         break;
274                 case 0x10:
275                         cmt_selected = ((data & 2) == 0);
276                         d_drec->write_signal(SIG_DATAREC_REMOTE, CMT_MODE_PLAY ? 1 : 0, 1);
277                         break;
278                 case 0x21:
279                         key_column = data & 0x0f;
280                         update_sid();
281                         break;
282                 case 0x40:
283                         if(CMT_RECORDING) {
284                                 if(data & 1) {
285                                         // 1: 2.4KHz * 8
286                                         for(int i = 0; i < 8; i++) {
287                                                 cmt_write_buffer(0xff, CMT_SAMPLE_RATE / 2400 / 2);
288                                                 cmt_write_buffer(0x00, CMT_SAMPLE_RATE / 2400 / 2);
289                                         }
290                                 } else {
291                                         // 0: 1.2KHz * 4
292                                         for(int i = 0; i < 4; i++) {
293                                                 cmt_write_buffer(0xff, CMT_SAMPLE_RATE / 1200 / 2);
294                                                 cmt_write_buffer(0x00, CMT_SAMPLE_RATE / 1200 / 2);
295                                         }
296                                 }
297                         }
298                         break;
299                 case 0x43:
300                         cmt_mode = data & 7;
301                         d_drec->write_signal(SIG_DATAREC_REMOTE, CMT_MODE_PLAY ? 1 : 0, 1);
302                         break;
303                 }
304         } else {
305                 switch(addr & 0xf0) {
306                 case 0x10:
307                         d_rtc->write_io8(addr, data);
308                         break;
309                 }
310         }
311 }
312
313 uint32_t IO::read_io8(uint32_t addr)
314 {
315         uint32_t value = 0xff;
316         
317         if(sod) {
318                 switch(addr & 0xff) {
319                 case 0x01:
320                 case 0x02:
321                         value = lcd[addr & 1].ram[lcd_addr & 0x3ff];
322                         break;
323                 case 0x08:
324                         value = ((lcd_addr >> 8) & 0x0f) | lcd_status;
325                         break;
326                 case 0x09:
327                         value = lcd_addr & 0xff;
328                         break;
329                 case 0x10:
330                         value = 0;
331                         break;
332                 case 0x20:
333                         value = 0;
334                         if(key_column < 10) {
335                                 for(int i = 0; i < 8; i++) {
336                                         if(key_stat[key_table[key_column][i]]) {
337                                                 value |= (1 << i);
338                                         }
339                                 }
340                         }
341                         value = value;
342                         break;
343                 case 0x40:
344                         value = (CMT_PLAYING && cmt_play_signal) ? 0x08 : 0;
345                         break;
346                 case 0x41:
347                         value = ((CMT_PLAYING && cmt_play_ready) || (CMT_RECORDING && cmt_rec_ready)) ? 0x10 : 0;
348                         cmt_play_ready = cmt_rec_ready = false;
349                         break;
350                 }
351         } else {
352                 switch(addr & 0xf0) {
353                 case 0x10:
354                         value = d_rtc->read_io8(addr);
355                         break;
356                 case 0x40:
357                         value = 0; // no floppy drives
358                         break;
359                 }
360         }
361 #ifdef _IO_DEBUG_LOG
362         this->out_debug_log(_T("%06x\tSOD=%d\tIN8\t%04x = %02x\n"), get_cpu_pc(0), sod ? 1 : 0, addr & 0xff, value);
363 #endif
364         return value;
365 }
366
367 void IO::write_io8w(uint32_t addr, uint32_t data, int* wait)
368 {
369         *wait = 2;
370         write_io8(addr, data);
371 }
372
373 uint32_t IO::read_io8w(uint32_t addr, int* wait)
374 {
375         *wait = 2;
376         return read_io8(addr);
377 }
378
379 void IO::write_signal(int id, uint32_t data, uint32_t mask)
380 {
381         if(id == SIG_IO_SOD) {
382                 sod = ((data & mask) != 0);
383         } else if(id == SIG_IO_CMT) {
384                 b16_1.in_d = g21_1.in_ck = c16.in_a = ((data & mask) != 0);
385                 update_cmt();
386         }
387 }
388
389 #define BIT_2400HZ      0x10
390 #define BIT_1200HZ      0x20
391 #define BIT_300HZ       0x80
392
393 void IO::event_callback(int event_id, int err)
394 {
395         if(event_id == EVENT_CMT_READY) {
396                 if(CMT_RECORDING) {
397                         if(!cmt_rec_ready) {
398                                 request_skip_frames();
399                         }
400                         cmt_rec_ready = true;
401                 }
402         } else if(event_id == EVENT_CMT_CLOCK) {
403                 c15.in_d4 = c15.in_d5 = ((cmt_clock & BIT_1200HZ) != 0);
404                 c15.in_d6 = c15.in_d7 = ((cmt_clock & BIT_300HZ ) != 0);
405                 
406                 // 76.8KHz: L->H
407                 b16_1.in_ck = b16_2.in_ck = g21_2.in_ck = false;
408                 f21.in_ck = !(g21_1.in_d && false);
409                 update_cmt();
410                 b16_1.in_ck = b16_2.in_ck = g21_2.in_ck = true;
411                 f21.in_ck = !(g21_1.in_d && true);
412                 update_cmt();
413                 
414                 cmt_clock++;
415         }
416 }
417
418 void IO::key_down(int code)
419 {
420         if(code >= 0x10 && code <= 0x13) {
421                 update_sid();
422         } else {
423                 d_cpu->write_signal(SIG_I8085_RST7, 1, 1);
424         }
425 }
426
427 void IO::key_up()
428 {
429         update_sid();
430 }
431
432 void IO::update_sid()
433 {
434         switch(key_column) {
435         case 5:
436                 d_cpu->write_signal(SIG_I8085_SID, mode_basic ? 1 : 0, 1);
437                 break;
438         case 6:
439                 d_cpu->write_signal(SIG_I8085_SID, key_stat[0x10] ? 0 : 1, 1);  // shift
440                 break;
441         case 7:
442                 d_cpu->write_signal(SIG_I8085_SID, key_stat[0x13] ? 0 : 1, 1);  // break
443                 break;
444         case 8:
445                 d_cpu->write_signal(SIG_I8085_SID, key_stat[0x12] ? 0 : 1, 1);  // graph
446                 break;
447         case 9:
448                 d_cpu->write_signal(SIG_I8085_SID, key_stat[0x11] ? 0 : 1, 1);  // ctrl
449                 break;
450         default:
451                 d_cpu->write_signal(SIG_I8085_SID, 1, 1);
452                 break;
453         }
454 }
455
456 void IO::cmt_write_buffer(uint8_t value, int samples)
457 {
458         if(cmt_is_wav) {
459                 for(int i = 0; i < samples; i++) {
460                         cmt_buffer[cmt_bufcnt++] = value;
461                         if(cmt_bufcnt == sizeof(cmt_buffer)) {
462                                 cmt_fio->Fwrite(cmt_buffer, sizeof(cmt_buffer), 1);
463                                 cmt_bufcnt = 0;
464                         }
465                 }
466         } else {
467                 value = (value > 128) ? 0x80 : 0;
468                 while(samples > 0) {
469                         int s = min(samples, 0x7f);
470                         samples -= s;
471                         cmt_buffer[cmt_bufcnt++] = value | s;
472                         if(cmt_bufcnt == sizeof(cmt_buffer)) {
473                                 cmt_fio->Fwrite(cmt_buffer, sizeof(cmt_buffer), 1);
474                                 cmt_bufcnt = 0;
475                         }
476                 }
477         }
478 }
479
480 void IO::rec_tape(const _TCHAR* file_path)
481 {
482         close_tape();
483         
484         if(cmt_fio->Fopen(file_path, FILEIO_READ_WRITE_NEW_BINARY)) {
485                 my_tcscpy_s(cmt_rec_file_path, _MAX_PATH, file_path);
486                 if(check_file_extension(file_path, _T(".wav"))) {
487                         uint8_t dummy[sizeof(wav_header_t) + sizeof(wav_chunk_t)];
488                         memset(dummy, 0, sizeof(dummy));
489                         cmt_fio->Fwrite(dummy, sizeof(dummy), 1);
490                         cmt_is_wav = true;
491                 }
492                 cmt_bufcnt = 0;
493                 cmt_rec = true;
494         }
495 }
496
497 void IO::close_tape()
498 {
499         // close file
500         if(cmt_fio->IsOpened()) {
501                 if(cmt_rec) {
502                         if(cmt_bufcnt) {
503                                 cmt_fio->Fwrite(cmt_buffer, cmt_bufcnt, 1);
504                         }
505                         if(cmt_is_wav) {
506                                 uint32_t length = cmt_fio->Ftell();
507                                 
508                                 wav_header_t wav_header;
509                                 wav_chunk_t wav_chunk;
510                                 
511                                 memcpy(wav_header.riff_chunk.id, "RIFF", 4);
512                                 wav_header.riff_chunk.size = length - 8;
513                                 memcpy(wav_header.wave, "WAVE", 4);
514                                 memcpy(wav_header.fmt_chunk.id, "fmt ", 4);
515                                 wav_header.fmt_chunk.size = 16;
516                                 wav_header.format_id = 1;
517                                 wav_header.channels = 1;
518                                 wav_header.sample_rate = CMT_SAMPLE_RATE;
519                                 wav_header.data_speed = CMT_SAMPLE_RATE;
520                                 wav_header.block_size = 1;
521                                 wav_header.sample_bits = 8;
522                                 
523                                 memcpy(wav_chunk.id, "data", 4);
524                                 wav_chunk.size = length - sizeof(wav_header) - sizeof(wav_chunk);
525                                 
526                                 cmt_fio->Fseek(0, FILEIO_SEEK_SET);
527                                 cmt_fio->Fwrite(&wav_header, sizeof(wav_header), 1);
528                                 cmt_fio->Fwrite(&wav_chunk, sizeof(wav_chunk), 1);
529                         }
530                 }
531                 cmt_fio->Fclose();
532         }
533         cmt_rec = cmt_is_wav = false;
534         cmt_bufcnt = 0;
535 }
536
537 void IO::update_cmt()
538 {
539         bool prev_load_clock = c15.out_y;
540         
541         b16_1.update();
542         b16_2.update();
543         f21.update();
544         g21_1.update();
545         g21_2.update();
546         c16.update();
547         
548         b16_2.in_d = b16_1.out_q;
549         f21.in_clr = (b16_1.out_q && b16_2.out_nq);
550         g21_1.in_d = g21_1.in_r = c15.in_d0 = !(f21.out_q5 && f21.out_q6);
551         g21_2.in_d = g21_1.out_q;
552         c16.in_rc1 = c16.in_rc2 = (g21_1.out_q != g21_2.out_q); // xor
553         c15.in_a = (g21_1.out_q && g21_2.out_q);
554         c16.in_b = c16.out_qa;
555         c15.in_d1 = !c16.out_qa;
556         c15.in_d2 = c16.out_qb;
557         c15.in_d3 = c16.out_qc;
558         
559         c15.update();
560         
561         if(!prev_load_clock && c15.out_y) {
562                 cmt_play_ready = true;
563                 cmt_play_signal = c15.in_a;
564         }
565 }
566
567 void IO::draw_screen()
568 {
569         // render screen
570         for(int y = 0; y < 8; y++) {
571                 for(int x = 0; x < 20; x++) {
572                         int addr = y * 0x80 + (x % 10) + lcd[x < 10].offset;
573                         for(int l = 0; l < 8; l++) {
574                                 uint8_t pat = lcd[x < 10].ram[addr & 0x3ff];
575                                 addr += 0x10;
576                                 uint8_t* d = &screen[y * 8 + l][x * 8];
577                                 
578                                 d[0] = pat & 0x01;
579                                 d[1] = pat & 0x02;
580                                 d[2] = pat & 0x04;
581                                 d[3] = pat & 0x08;
582                                 d[4] = pat & 0x10;
583                                 d[5] = pat & 0x20;
584                                 d[6] = pat & 0x40;
585                                 d[7] = pat & 0x80;
586                         }
587                 }
588         }
589         
590         // copy to real screen
591         scrntype_t cd = RGB_COLOR(48, 56, 16);
592         scrntype_t cb = RGB_COLOR(160, 168, 160);
593         for(int y = 0; y < 64; y++) {
594                 scrntype_t* dst = emu->get_screen_buffer(y);
595                 uint8_t* src = screen[y];
596                 
597                 for(int x = 0; x < 160; x++) {
598                         dst[x] = src[x] ? cd : cb;
599                 }
600         }
601 }
602
603 #define STATE_VERSION   2
604
605 void IO::save_state(FILEIO* state_fio)
606 {
607         state_fio->FputUint32(STATE_VERSION);
608         state_fio->FputInt32(this_device_id);
609         
610         state_fio->Fwrite(lcd, sizeof(lcd), 1);
611         state_fio->FputInt32(lcd_status);
612         state_fio->FputInt32(lcd_addr);
613         state_fio->FputBool(lcd_text);
614         state_fio->FputBool(cmt_selected);
615         state_fio->FputUint8(cmt_mode);
616         state_fio->FputBool(cmt_play_ready);
617         state_fio->FputBool(cmt_play_signal);
618         state_fio->FputBool(cmt_rec_ready);
619         state_fio->FputBool(cmt_rec);
620         state_fio->FputBool(cmt_is_wav);
621         state_fio->Fwrite(cmt_rec_file_path, sizeof(cmt_rec_file_path), 1);
622         if(cmt_rec && cmt_fio->IsOpened()) {
623                 int length_tmp = (int)cmt_fio->Ftell();
624                 cmt_fio->Fseek(0, FILEIO_SEEK_SET);
625                 state_fio->FputInt32(length_tmp);
626                 while(length_tmp != 0) {
627                         uint8_t buffer_tmp[1024];
628                         int length_rw = min(length_tmp, (int)sizeof(buffer_tmp));
629                         cmt_fio->Fread(buffer_tmp, length_rw, 1);
630                         state_fio->Fwrite(buffer_tmp, length_rw, 1);
631                         length_tmp -= length_rw;
632                 }
633         } else {
634                 state_fio->FputInt32(0);
635         }
636         state_fio->FputInt32(cmt_bufcnt);
637         state_fio->Fwrite(cmt_buffer, cmt_bufcnt, 1);
638         state_fio->FputUint8(cmt_clock);
639         state_fio->Fwrite(&b16_1, sizeof(b16_1), 1);
640         state_fio->Fwrite(&b16_2, sizeof(b16_2), 1);
641         state_fio->Fwrite(&g21_1, sizeof(g21_1), 1);
642         state_fio->Fwrite(&g21_2, sizeof(g21_2), 1);
643         state_fio->Fwrite(&c15, sizeof(c15), 1);
644         state_fio->Fwrite(&c16, sizeof(c16), 1);
645         state_fio->Fwrite(&f21, sizeof(f21), 1);
646         state_fio->FputUint8(key_column);
647 }
648
649 bool IO::load_state(FILEIO* state_fio)
650 {
651         close_tape();
652         
653         if(state_fio->FgetUint32() != STATE_VERSION) {
654                 return false;
655         }
656         if(state_fio->FgetInt32() != this_device_id) {
657                 return false;
658         }
659         state_fio->Fread(lcd, sizeof(lcd), 1);
660         lcd_status = state_fio->FgetInt32();
661         lcd_addr = state_fio->FgetInt32();
662         lcd_text = state_fio->FgetBool();
663         cmt_selected = state_fio->FgetBool();
664         cmt_mode = state_fio->FgetUint8();
665         cmt_play_ready = state_fio->FgetBool();
666         cmt_play_signal = state_fio->FgetBool();
667         cmt_rec_ready = state_fio->FgetBool();
668         cmt_rec = state_fio->FgetBool();
669         cmt_is_wav = state_fio->FgetBool();
670         state_fio->Fread(cmt_rec_file_path, sizeof(cmt_rec_file_path), 1);
671         int length_tmp = state_fio->FgetInt32();
672         if(cmt_rec) {
673                 cmt_fio->Fopen(cmt_rec_file_path, FILEIO_READ_WRITE_NEW_BINARY);
674                 while(length_tmp != 0) {
675                         uint8_t buffer_tmp[1024];
676                         int length_rw = min(length_tmp, (int)sizeof(buffer_tmp));
677                         state_fio->Fread(buffer_tmp, length_rw, 1);
678                         if(cmt_fio->IsOpened()) {
679                                 cmt_fio->Fwrite(buffer_tmp, length_rw, 1);
680                         }
681                         length_tmp -= length_rw;
682                 }
683         }
684         cmt_bufcnt = state_fio->FgetInt32();
685         if(cmt_bufcnt) {
686                 state_fio->Fread(cmt_buffer, cmt_bufcnt, 1);
687         }
688         cmt_clock = state_fio->FgetUint8();
689         state_fio->Fread(&b16_1, sizeof(b16_1), 1);
690         state_fio->Fread(&b16_2, sizeof(b16_2), 1);
691         state_fio->Fread(&g21_1, sizeof(g21_1), 1);
692         state_fio->Fread(&g21_2, sizeof(g21_2), 1);
693         state_fio->Fread(&c15, sizeof(c15), 1);
694         state_fio->Fread(&c16, sizeof(c16), 1);
695         state_fio->Fread(&f21, sizeof(f21), 1);
696         key_column = state_fio->FgetUint8();
697         return true;
698 }
699