OSDN Git Service

[General][Qt] Merge upstream, datarecorder with sound.
[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 #include "../../fileio.h"
14
15 #define EVENT_CMT_READY 0
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 && cmt_play)
22
23 // based on elisa font (http://hp.vector.co.jp/authors/VA002310/index.htm
24 static const uint8 elisa_font[2048] = {
25         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
26         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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         0x08, 0x04, 0x02, 0x7f, 0x02, 0x04, 0x08, 0x00, 0x08, 0x10, 0x20, 0x7f, 0x20, 0x10, 0x08, 0x00,
40         0x08, 0x1c, 0x2a, 0x49, 0x08, 0x08, 0x08, 0x00, 0x08, 0x08, 0x08, 0x49, 0x2a, 0x1c, 0x08, 0x00,
41         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x08,
42         0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x7f, 0x24, 0x24, 0xfe, 0x48, 0x48,
43         0x08, 0x1c, 0x2a, 0x1c, 0x0a, 0x2a, 0x1c, 0x08, 0x61, 0x92, 0x94, 0x68, 0x16, 0x29, 0x49, 0x86,
44         0x30, 0x48, 0x48, 0x32, 0x4a, 0x44, 0x3a, 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
45         0x03, 0x04, 0x08, 0x08, 0x08, 0x08, 0x04, 0x03, 0xc0, 0x20, 0x10, 0x10, 0x10, 0x10, 0x20, 0xc0,
46         0x08, 0x2a, 0x1c, 0x08, 0x1c, 0x2a, 0x08, 0x00, 0x08, 0x08, 0x08, 0x7f, 0x08, 0x08, 0x08, 0x00,
47         0x00, 0x00, 0x00, 0x00, 0x60, 0x60, 0x20, 0x40, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00,
48         0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x60, 0x00, 0x00, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x00,
49         0x3c, 0x42, 0x46, 0x5a, 0x62, 0x42, 0x3c, 0x00, 0x08, 0x18, 0x08, 0x08, 0x08, 0x08, 0x1c, 0x00,
50         0x3c, 0x42, 0x02, 0x0c, 0x10, 0x20, 0x7e, 0x00, 0x3c, 0x42, 0x02, 0x3c, 0x02, 0x42, 0x3c, 0x00,
51         0x04, 0x0c, 0x14, 0x24, 0x44, 0x7e, 0x04, 0x00, 0x7e, 0x40, 0x40, 0x7c, 0x02, 0x02, 0x7c, 0x00,
52         0x3c, 0x42, 0x40, 0x7c, 0x42, 0x42, 0x3c, 0x00, 0x7e, 0x02, 0x04, 0x08, 0x10, 0x10, 0x10, 0x00,
53         0x3c, 0x42, 0x42, 0x3c, 0x42, 0x42, 0x3c, 0x00, 0x3c, 0x42, 0x42, 0x3e, 0x02, 0x42, 0x3c, 0x00,
54         0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x08, 0x10,
55         0x03, 0x0c, 0x30, 0xc0, 0x30, 0x0c, 0x03, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x7e, 0x00, 0x00, 0x00,
56         0xc0, 0x30, 0x0c, 0x03, 0x0c, 0x30, 0xc0, 0x00, 0x1c, 0x22, 0x22, 0x04, 0x08, 0x08, 0x00, 0x08,
57         0x1c, 0x22, 0x4d, 0x55, 0x47, 0x5f, 0x20, 0x1e, 0x18, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x00,
58         0x7c, 0x42, 0x42, 0x7c, 0x42, 0x42, 0x7c, 0x00, 0x1c, 0x22, 0x40, 0x40, 0x40, 0x22, 0x1c, 0x00,
59         0x78, 0x24, 0x22, 0x22, 0x22, 0x24, 0x78, 0x00, 0x7e, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x7e, 0x00,
60         0x7e, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x40, 0x00, 0x1c, 0x22, 0x40, 0x47, 0x42, 0x26, 0x1a, 0x00,
61         0x42, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x1c, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1c, 0x00,
62         0x0e, 0x04, 0x04, 0x04, 0x44, 0x44, 0x38, 0x00, 0x42, 0x44, 0x48, 0x50, 0x68, 0x44, 0x42, 0x00,
63         0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x7e, 0x00, 0x41, 0x63, 0x55, 0x49, 0x41, 0x41, 0x41, 0x00,
64         0x42, 0x62, 0x52, 0x4a, 0x46, 0x42, 0x42, 0x00, 0x18, 0x24, 0x42, 0x42, 0x42, 0x24, 0x18, 0x00,
65         0x7c, 0x42, 0x42, 0x7c, 0x40, 0x40, 0x40, 0x00, 0x18, 0x24, 0x42, 0x42, 0x4a, 0x24, 0x1a, 0x00,
66         0x7c, 0x42, 0x42, 0x7c, 0x48, 0x44, 0x42, 0x00, 0x3c, 0x42, 0x40, 0x3c, 0x02, 0x42, 0x3c, 0x00,
67         0x7f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00,
68         0x41, 0x41, 0x22, 0x22, 0x14, 0x14, 0x08, 0x00, 0x41, 0x49, 0x49, 0x55, 0x55, 0x22, 0x22, 0x00,
69         0x41, 0x22, 0x14, 0x08, 0x14, 0x22, 0x41, 0x00, 0x41, 0x22, 0x14, 0x08, 0x08, 0x08, 0x08, 0x00,
70         0x7e, 0x02, 0x04, 0x08, 0x10, 0x20, 0x7e, 0x00, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07,
71         0x41, 0x22, 0x14, 0x7f, 0x08, 0x7f, 0x08, 0x08, 0xe0, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xe0,
72         0x08, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00,
73         0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x02, 0x1e, 0x22, 0x1e, 0x00,
74         0x20, 0x20, 0x20, 0x3c, 0x22, 0x22, 0x3c, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x20, 0x22, 0x1c, 0x00,
75         0x02, 0x02, 0x02, 0x1e, 0x22, 0x22, 0x1e, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x3e, 0x20, 0x1e, 0x00,
76         0x0c, 0x12, 0x10, 0x3c, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x22, 0x1e, 0x02, 0x3c,
77         0x20, 0x20, 0x3c, 0x22, 0x22, 0x22, 0x22, 0x00, 0x08, 0x00, 0x18, 0x08, 0x08, 0x08, 0x1c, 0x00,
78         0x08, 0x00, 0x18, 0x08, 0x08, 0x08, 0x48, 0x30, 0x20, 0x20, 0x24, 0x28, 0x30, 0x28, 0x24, 0x00,
79         0x18, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x3c, 0x2a, 0x2a, 0x2a, 0x2a, 0x00,
80         0x00, 0x00, 0x3c, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x22, 0x22, 0x1c, 0x00,
81         0x00, 0x00, 0x3c, 0x22, 0x22, 0x3c, 0x20, 0x20, 0x00, 0x00, 0x1e, 0x22, 0x22, 0x1e, 0x02, 0x02,
82         0x00, 0x00, 0x2e, 0x30, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x1e, 0x20, 0x1c, 0x02, 0x3c, 0x00,
83         0x00, 0x10, 0x3c, 0x10, 0x10, 0x10, 0x0c, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x1e, 0x00,
84         0x00, 0x00, 0x22, 0x22, 0x14, 0x14, 0x08, 0x00, 0x00, 0x00, 0x22, 0x2a, 0x2a, 0x14, 0x14, 0x00,
85         0x00, 0x00, 0x22, 0x14, 0x08, 0x14, 0x22, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x1e, 0x02, 0x3c,
86         0x00, 0x00, 0x3e, 0x04, 0x08, 0x10, 0x3e, 0x00, 0x03, 0x04, 0x04, 0x08, 0x04, 0x04, 0x04, 0x03,
87         0x08, 0x08, 0x08, 0x00, 0x08, 0x08, 0x08, 0x00, 0xc0, 0x20, 0x20, 0x10, 0x20, 0x20, 0x20, 0xc0,
88         0x00, 0x00, 0x30, 0x49, 0x06, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x22, 0x10, 0x08, 0x08, 0x00, 0x08,
89         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
90         0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
91         0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
92         0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
93         0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
94         0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
95         0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
96         0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0x08, 0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08,
97         0x08, 0x08, 0x08, 0x08, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x08, 0x08, 0x08,
98         0x08, 0x08, 0x08, 0x08, 0xf8, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08,
99         0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
100         0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
101         0x00, 0x00, 0x00, 0x00, 0x0f, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x08, 0x08, 0x08,
102         0x08, 0x08, 0x08, 0x08, 0x0f, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0xf8, 0x00, 0x00, 0x00,
103         0x00, 0x00, 0x00, 0x07, 0x08, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0xc0, 0x20, 0x10, 0x10, 0x10,
104         0x10, 0x10, 0x08, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x20, 0xc0, 0x00, 0x00, 0x00, 0x00,
105         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xa0, 0x40,
106         0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xf0,
107         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x20, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
108         0x00, 0x7e, 0x02, 0x7e, 0x02, 0x04, 0x08, 0x30, 0x00, 0x00, 0x00, 0x3e, 0x0a, 0x0c, 0x08, 0x10,
109         0x00, 0x00, 0x00, 0x04, 0x08, 0x18, 0x28, 0x08, 0x00, 0x00, 0x00, 0x08, 0x3e, 0x22, 0x02, 0x0c,
110         0x00, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x04, 0x3e, 0x0c, 0x14, 0x24,
111         0x00, 0x00, 0x00, 0x10, 0x3e, 0x12, 0x14, 0x10, 0x00, 0x00, 0x00, 0x00, 0x38, 0x08, 0x08, 0x7c,
112         0x00, 0x00, 0x00, 0x3c, 0x04, 0x3c, 0x04, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x52, 0x52, 0x04, 0x18,
113         0x00, 0x00, 0x00, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x01, 0x0a, 0x0c, 0x08, 0x08, 0x10,
114         0x00, 0x02, 0x04, 0x08, 0x18, 0x28, 0x48, 0x08, 0x08, 0x08, 0x7e, 0x42, 0x42, 0x02, 0x04, 0x18,
115         0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x7f, 0x04, 0x04, 0x7f, 0x04, 0x0c, 0x14, 0x24, 0x44,
116         0x10, 0x10, 0x7e, 0x12, 0x12, 0x22, 0x22, 0x44, 0x10, 0x10, 0x7f, 0x08, 0x7f, 0x08, 0x04, 0x04,
117         0x20, 0x3e, 0x22, 0x42, 0x02, 0x04, 0x04, 0x18, 0x20, 0x20, 0x3f, 0x24, 0x44, 0x04, 0x08, 0x30,
118         0x00, 0x00, 0x7e, 0x02, 0x02, 0x02, 0x02, 0x7e, 0x00, 0x24, 0xff, 0x24, 0x24, 0x04, 0x04, 0x18,
119         0x00, 0x40, 0x20, 0x42, 0x22, 0x04, 0x08, 0x70, 0x00, 0x7e, 0x02, 0x04, 0x08, 0x14, 0x22, 0x41,
120         0x20, 0x20, 0x7e, 0x22, 0x24, 0x28, 0x20, 0x1e, 0x00, 0x41, 0x41, 0x21, 0x02, 0x02, 0x04, 0x18,
121         0x10, 0x1e, 0x12, 0x32, 0x4e, 0x04, 0x08, 0x70, 0x06, 0x38, 0x08, 0x7f, 0x08, 0x08, 0x08, 0x30,
122         0x00, 0x52, 0x52, 0x02, 0x04, 0x04, 0x08, 0x30, 0x3e, 0x00, 0x00, 0x7f, 0x08, 0x08, 0x08, 0x30,
123         0x20, 0x20, 0x20, 0x38, 0x24, 0x22, 0x20, 0x20, 0x04, 0x04, 0x7f, 0x04, 0x04, 0x04, 0x08, 0x30,
124         0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x7e, 0x02, 0x22, 0x14, 0x0c, 0x12, 0x60,
125         0x08, 0x08, 0x7f, 0x01, 0x06, 0x1a, 0x69, 0x08, 0x00, 0x02, 0x02, 0x02, 0x04, 0x04, 0x08, 0x30,
126         0x00, 0x00, 0x24, 0x24, 0x22, 0x42, 0x81, 0x00, 0x00, 0x40, 0x40, 0x7e, 0x40, 0x40, 0x40, 0x3e,
127         0x00, 0x00, 0x7e, 0x02, 0x02, 0x04, 0x08, 0x30, 0x00, 0x00, 0x18, 0x24, 0x42, 0x01, 0x00, 0x00,
128         0x08, 0x08, 0x7f, 0x08, 0x08, 0x2a, 0x49, 0x08, 0x00, 0x7e, 0x02, 0x02, 0x24, 0x18, 0x08, 0x04,
129         0x00, 0x18, 0x06, 0x18, 0x06, 0x00, 0x30, 0x0e, 0x00, 0x08, 0x08, 0x10, 0x10, 0x24, 0x42, 0x7d,
130         0x00, 0x01, 0x01, 0x12, 0x0a, 0x04, 0x0a, 0x30, 0x00, 0x7e, 0x10, 0x10, 0x7f, 0x10, 0x10, 0x1e,
131         0x10, 0x10, 0xff, 0x11, 0x12, 0x14, 0x10, 0x10, 0x00, 0x00, 0x3c, 0x04, 0x04, 0x04, 0x04, 0x7e,
132         0x00, 0x7e, 0x02, 0x02, 0x7e, 0x02, 0x02, 0x7e, 0x00, 0x3c, 0x00, 0x7e, 0x02, 0x02, 0x04, 0x38,
133         0x00, 0x22, 0x22, 0x22, 0x22, 0x02, 0x04, 0x18, 0x00, 0x28, 0x28, 0x28, 0x28, 0x29, 0x2a, 0x4c,
134         0x00, 0x20, 0x20, 0x20, 0x22, 0x22, 0x24, 0x38, 0x00, 0x7e, 0x42, 0x42, 0x42, 0x42, 0x42, 0x7e,
135         0x00, 0x7e, 0x42, 0x42, 0x02, 0x04, 0x08, 0x30, 0x00, 0x40, 0x20, 0x02, 0x02, 0x04, 0x08, 0x70,
136         0xa0, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xa0, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
137         0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x0f, 0x08, 0x08,
138         0x08, 0x08, 0xff, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, 0xf8, 0x08, 0x08, 0xf8, 0x08, 0x08,
139         0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff,
140         0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01, 0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80,
141         0x08, 0x1c, 0x3e, 0x7f, 0x7f, 0x1c, 0x3e, 0x00, 0x36, 0x7f, 0x7f, 0x7f, 0x3e, 0x1c, 0x08, 0x00,
142         0x08, 0x1c, 0x3e, 0x7f, 0x3e, 0x1c, 0x08, 0x00, 0x1c, 0x1c, 0x6b, 0x7f, 0x6b, 0x08, 0x1c, 0x00,
143         0x1c, 0x3e, 0x7f, 0x7f, 0x7f, 0x3e, 0x1c, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, 0x22, 0x1c, 0x00,
144         0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01,
145         0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81, 0x7f, 0x49, 0x49, 0x49, 0x7f, 0x41, 0x41, 0x43,
146         0x20, 0x3e, 0x48, 0xbe, 0x28, 0xff, 0x08, 0x08, 0x3f, 0x21, 0x3f, 0x21, 0x3f, 0x21, 0x41, 0x83,
147         0x7e, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x7e, 0x04, 0xee, 0xa4, 0xff, 0xa2, 0xbf, 0xe2, 0x0a,
148         0x18, 0x04, 0x42, 0xbd, 0x14, 0x14, 0x24, 0x4c, 0x24, 0xc4, 0x4e, 0xed, 0x55, 0xe6, 0xc4, 0x58,
149         0x7f, 0x00, 0x7f, 0x08, 0x08, 0x08, 0x08, 0x00, 0x08, 0x7f, 0x08, 0x7f, 0x49, 0x49, 0x4b, 0x08,
150         0xff, 0x80, 0xa4, 0x94, 0x88, 0x94, 0xe0, 0xff, 0xf8, 0xaf, 0xfa, 0xaa, 0xaa, 0xfa, 0x02, 0x06,
151         0x22, 0xf2, 0x2f, 0x72, 0x6a, 0xa2, 0x22, 0x26, 0x08, 0x08, 0x08, 0x08, 0x08, 0x14, 0x22, 0xc1,
152         0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0x00, 0x00, 0x10, 0x08, 0x04, 0x04, 0x00, 0x00,
153 };
154
155 static const uint8 key_table[10][8] = {
156         {0x00, 0x00, 0x00, 0x00, 0x37, 0x55, 0x4a, 0x4d},
157         {0x00, 0x00, 0x00, 0x00, 0x38, 0x49, 0x4b, 0xbf},
158         {0x00, 0x00, 0x00, 0x00, 0x39, 0x4f, 0x4c, 0xbe},
159         {0x00, 0x00, 0x00, 0x00, 0x30, 0x50, 0xbc, 0xbb},
160         {0x15, 0x2e, 0x24, 0x70, 0x31, 0x51, 0x41, 0x5a},
161         {0x13, 0xdc, 0x27, 0x71, 0x32, 0x57, 0x53, 0x58},
162         {0x20, 0xde, 0x25, 0x72, 0x33, 0x45, 0x44, 0x43},
163         {0xc0, 0xbd, 0x28, 0x73, 0x34, 0x52, 0x46, 0x56},
164         {0xdb, 0xba, 0x26, 0x74, 0x35, 0x54, 0x47, 0x42},
165         {0x0d, 0xdd, 0x14, 0xe2, 0x36, 0x59, 0x48, 0x4e}
166 };
167
168 void IO::initialize()
169 {
170         FILEIO* fio = new FILEIO();
171         if(fio->Fopen(emu->bios_path(_T("FONT.ROM")), FILEIO_READ_BINARY)) {
172                 fio->Fread(font, sizeof(font), 1);
173                 fio->Fclose();
174         } else {
175                 memcpy(font, elisa_font, sizeof(font));
176         }
177         delete fio;
178         
179         sod = false;
180         
181         cmt_fio = new FILEIO();
182         cmt_play = cmt_rec = false;
183         cmt_buffer = NULL;
184         cmt_bufcnt = cmt_buflen = 0;
185 //      register_event(this, EVENT_CMT_READY, 1000000.0 / 8900.36, true, NULL);
186 //      register_event_by_clock(this, EVENT_CMT_READY, 1580, true, NULL);
187         register_event(this, EVENT_CMT_READY, 1000000.0 / 2400.0 * 8, true, NULL);
188         
189         key_stat = emu->key_buffer();
190 }
191
192 void IO::release()
193 {
194         close_tape();
195         delete cmt_fio;
196 }
197
198 void IO::reset()
199 {
200         mode_basic = (config.boot_mode == 0);
201         
202         memset(lcd, 0, sizeof(lcd));
203         lcd[0].cursor = lcd[1].cursor = -1;
204         lcd_status = lcd_addr = 0;
205         lcd_text = true;
206         
207         close_tape();
208         cmt_selected = cmt_ready = false;
209         cmt_mode = 0;
210         
211         key_column = 0;
212         update_sid();
213 }
214
215 void IO::write_io8(uint32 addr, uint32 data)
216 {
217         if(sod) {
218                 switch(addr & 0xff) {
219                 case 0x01:
220                 case 0x02:
221                         if(lcd_status == 0xb0) {
222                                 if(data == 0) {
223                                         lcd[ addr & 1].cursor = lcd_addr & 0x3ff;
224                                         lcd[~addr & 1].cursor = -1;
225                                 } else if(data == 0x40) {
226                                         lcd_text = false;
227                                 } else if(data == 0x50) {
228                                         lcd[addr & 1].offset = lcd_addr & 0x3ff;
229                                 } else if(data == 0x60) {
230                                         lcd_text = true;
231                                 }
232                         } else {
233                                 lcd[addr & 1].ram[lcd_addr & 0x3ff].data = data;
234                                 // 0x38f means the first raster of this character
235                                 lcd[addr & 1].ram[lcd_addr & 0x38f].is_text = lcd_text;
236                         }
237                         break;
238                 case 0x08:
239                         if((lcd_status = data & 0xf0) == 0xb0) {
240                                 lcd_addr = (lcd_addr & 0xff) | (data << 8);
241                         }
242                         break;
243                 case 0x09:
244                         lcd_addr = (lcd_addr & 0xff00) | data;
245                         break;
246                 case 0x10:
247                         cmt_selected = ((data & 2) == 0);
248                         break;
249                 case 0x21:
250                         key_column = data & 0x0f;
251                         update_sid();
252                         break;
253                 case 0x40:
254                         if(CMT_RECORDING) {
255                                 cmt_write_buffer((data & 1) != 0, 1);
256                         }
257                         break;
258                 case 0x43:
259                         cmt_mode = data & 7;
260                         break;
261                 }
262         } else {
263                 switch(addr & 0xf0) {
264                 case 0x10:
265                         d_rtc->write_io8(addr, data);
266                         break;
267                 }
268         }
269 }
270
271 uint32 IO::read_io8(uint32 addr)
272 {
273         uint32 value = 0;
274         
275         if(sod) {
276                 switch(addr & 0xff) {
277                 case 0x01:
278                 case 0x02:
279                         return lcd[addr & 1].ram[lcd_addr & 0x3ff].data;
280                 case 0x08:
281                         return ((lcd_addr >> 8) & 0x0f) | lcd_status;
282                 case 0x09:
283                         return lcd_addr & 0xff;
284                 case 0x10:
285                         return 0;
286                 case 0x20:
287                         if(key_column < 10) {
288                                 for(int i = 0; i < 8; i++) {
289                                         if(key_stat[key_table[key_column][i]]) {
290                                                 value |= (1 << i);
291                                         }
292                                 }
293                         }
294                         return value;
295                 case 0x40:
296                         return cmt_read_buffer() ? 0x08 : 0;
297                 case 0x41:
298                         value = ((CMT_PLAYING || CMT_RECORDING) && cmt_ready) ? 0x10 : 0;
299                         cmt_ready = false;
300                         return value;
301                 }
302         } else {
303                 switch(addr & 0xf0) {
304                 case 0x10:
305                         return d_rtc->read_io8(addr);
306                 case 0x40:
307                         return 0; // no floppy drives
308                 }
309         }
310         return 0xff;
311 }
312
313 void IO::write_io8w(uint32 addr, uint32 data, int* wait)
314 {
315         *wait = 2;
316         write_io8(addr, data);
317 }
318
319 uint32 IO::read_io8w(uint32 addr, int* wait)
320 {
321         *wait = 2;
322         return read_io8(addr);
323 }
324
325 void IO::write_signal(int id, uint32 data, uint32 mask)
326 {
327         if(id == SIG_IO_SOD) {
328                 sod = ((data & mask) != 0);
329         }
330 }
331
332 void IO::event_callback(int event_id, int err)
333 {
334 //      if(event_id == EVENT_CMT_READY) {
335                 if((CMT_PLAYING && cmt_bufcnt < cmt_buflen) || CMT_RECORDING) {
336                         if(!cmt_ready) {
337                                 request_skip_frames();
338                         }
339                         cmt_ready = true;
340                 }
341 //      }
342 }
343
344 void IO::key_down(int code)
345 {
346         if(code >= 0x10 && code <= 0x13) {
347                 update_sid();
348         } else {
349                 d_cpu->write_signal(SIG_I8085_RST7, 1, 1);
350         }
351 }
352
353 void IO::key_up()
354 {
355         update_sid();
356 }
357
358 void IO::update_sid()
359 {
360         switch(key_column) {
361         case 5:
362                 d_cpu->write_signal(SIG_I8085_SID, mode_basic ? 1 : 0, 1);
363                 break;
364         case 6:
365                 d_cpu->write_signal(SIG_I8085_SID, key_stat[0x10] ? 0 : 1, 1);  // shift
366                 break;
367         case 7:
368                 d_cpu->write_signal(SIG_I8085_SID, key_stat[0x13] ? 0 : 1, 1);  // break
369                 break;
370         case 8:
371                 d_cpu->write_signal(SIG_I8085_SID, key_stat[0x12] ? 0 : 1, 1);  // graph
372                 break;
373         case 9:
374                 d_cpu->write_signal(SIG_I8085_SID, key_stat[0x11] ? 0 : 1, 1);  // ctrl
375                 break;
376         default:
377                 d_cpu->write_signal(SIG_I8085_SID, 1, 1);
378                 break;
379         }
380 }
381
382 bool IO::cmt_read_buffer()
383 {
384         while(CMT_PLAYING && cmt_bufcnt < cmt_buflen) {
385                 uint8 num = cmt_buffer[cmt_bufcnt] & 0x7f;
386                 if(num != 0) {
387                         cmt_buffer[cmt_bufcnt] &= 0x80;
388                         cmt_buffer[cmt_bufcnt] |= num - 1;
389                         return ((cmt_buffer[cmt_bufcnt] & 0x80) != 0);
390                 }
391                 cmt_bufcnt++;
392         }
393         return false;
394 }
395
396 void IO::cmt_write_buffer(bool value, int count)
397 {
398         while(CMT_RECORDING && count > 0) {
399                 uint8 bit = value ? 0x80 : 0;
400                 uint8 num = cmt_buffer[cmt_bufcnt] & 0x7f;
401                 if(num != 0) {
402                         if(num == 0x7f || (cmt_buffer[cmt_bufcnt] & 0x80) != bit) {
403                                 if(++cmt_bufcnt == cmt_buflen) {
404                                         cmt_fio->Fwrite(cmt_buffer, cmt_buflen, 1);
405                                         cmt_bufcnt = 0;
406                                 }
407                                 num = 0;
408                         }
409                 }
410                 cmt_buffer[cmt_bufcnt] = bit | (num + 1);
411                 count--;
412         }
413 }
414
415 void IO::play_tape(_TCHAR* file_path)
416 {
417         close_tape();
418         
419         if(cmt_fio->Fopen(file_path, FILEIO_READ_BINARY)) {
420                 cmt_fio->Fseek(0, FILEIO_SEEK_END);
421                 cmt_buflen = (int)cmt_fio->Ftell();
422                 if(cmt_buflen > 0) {
423                         cmt_buffer = (uint8 *)malloc(cmt_buflen);
424                         cmt_fio->Fseek(0, FILEIO_SEEK_SET);
425                         cmt_fio->Fread(cmt_buffer, cmt_buflen, 1);
426                         cmt_bufcnt = 0;
427                         cmt_play = true;
428                 }
429                 cmt_fio->Fclose();
430         }
431 }
432
433 void IO::rec_tape(_TCHAR* file_path)
434 {
435         close_tape();
436         
437         if(cmt_fio->Fopen(file_path, FILEIO_READ_WRITE_NEW_BINARY)) {
438                 _tcscpy_s(cmt_rec_file_path, _MAX_PATH, file_path);
439                 cmt_buflen = 0x10000;
440                 cmt_buffer = (uint8 *)calloc(cmt_buflen, sizeof(uint8));
441                 cmt_bufcnt = 0;
442                 cmt_rec = true;
443         }
444 }
445
446 void IO::close_tape()
447 {
448         // close file
449         if(cmt_fio->IsOpened()) {
450                 if(cmt_rec && cmt_bufcnt) {
451                         cmt_fio->Fwrite(cmt_buffer, cmt_bufcnt, 1);
452                 }
453                 cmt_fio->Fclose();
454         }
455         cmt_play = cmt_rec = false;
456         cmt_buffer = NULL;
457         cmt_bufcnt = cmt_buflen = 0;
458 }
459
460 void IO::draw_screen()
461 {
462         // render screen
463         for(int y = 0; y < 8; y++) {
464                 for(int x = 0; x < 20; x++) {
465                         int addr = (y * 0x80 + (x % 10) + lcd[x < 10].offset) & 0x3ff;
466                         if(lcd[x < 10].ram[addr].is_text) {
467                                 uint8 code = lcd[x < 10].ram[addr].data;
468                                 for(int l = 0; l < 8; l++) {
469                                         uint8 pat = (lcd[x < 10].cursor == addr) ? 0xff : font[(code << 3) + l];
470                                         addr += 0x10;
471                                         uint8* d = &screen[y * 8 + l][x * 8];
472                                         
473                                         d[0] = pat & 0x80;
474                                         d[1] = pat & 0x40;
475                                         d[2] = pat & 0x20;
476                                         d[3] = pat & 0x10;
477                                         d[4] = pat & 0x08;
478                                         d[5] = pat & 0x04;
479                                         d[6] = pat & 0x02;
480                                         d[7] = pat & 0x01;
481                                 }
482                         } else {
483                                 for(int l = 0; l < 8; l++) {
484                                         uint8 pat = lcd[x < 10].ram[addr].data;
485                                         addr += 0x10;
486                                         uint8* d = &screen[y * 8 + l][x * 8];
487                                         
488                                         d[0] = pat & 0x01;
489                                         d[1] = pat & 0x02;
490                                         d[2] = pat & 0x04;
491                                         d[3] = pat & 0x08;
492                                         d[4] = pat & 0x10;
493                                         d[5] = pat & 0x20;
494                                         d[6] = pat & 0x40;
495                                         d[7] = pat & 0x80;
496                                 }
497                         }
498                 }
499         }
500         
501         // copy to real screen
502         scrntype cd = RGB_COLOR(48, 56, 16);
503         scrntype cb = RGB_COLOR(160, 168, 160);
504         for(int y = 0; y < 64; y++) {
505                 scrntype* dst = emu->screen_buffer(y);
506                 uint8* src = screen[y];
507                 
508                 for(int x = 0; x < 160; x++) {
509                         dst[x] = src[x] ? cd : cb;
510                 }
511         }
512 }
513
514 #define STATE_VERSION   1
515
516 void IO::save_state(FILEIO* state_fio)
517 {
518         state_fio->FputUint32(STATE_VERSION);
519         state_fio->FputInt32(this_device_id);
520         
521         state_fio->Fwrite(lcd, sizeof(lcd), 1);
522         state_fio->FputInt32(lcd_status);
523         state_fio->FputInt32(lcd_addr);
524         state_fio->FputBool(lcd_text);
525         state_fio->FputBool(cmt_selected);
526         state_fio->FputBool(cmt_ready);
527         state_fio->FputUint8(cmt_mode);
528         state_fio->FputBool(cmt_play);
529         state_fio->FputBool(cmt_rec);
530         state_fio->Fwrite(cmt_rec_file_path, sizeof(cmt_rec_file_path), 1);
531         if(cmt_rec && cmt_fio->IsOpened()) {
532                 int length_tmp = (int)cmt_fio->Ftell();
533                 cmt_fio->Fseek(0, FILEIO_SEEK_SET);
534                 state_fio->FputInt32(length_tmp);
535                 while(length_tmp != 0) {
536                         uint8 buffer_tmp[1024];
537                         int length_rw = min(length_tmp, sizeof(buffer_tmp));
538                         cmt_fio->Fread(buffer_tmp, length_rw, 1);
539                         state_fio->Fwrite(buffer_tmp, length_rw, 1);
540                         length_tmp -= length_rw;
541                 }
542         } else {
543                 state_fio->FputInt32(0);
544         }
545         if(cmt_buflen && cmt_buffer) {
546                 state_fio->FputInt32(cmt_bufcnt);
547                 state_fio->FputInt32(cmt_buflen);
548                 state_fio->Fwrite(cmt_buffer, cmt_buflen, 1);
549         } else {
550                 state_fio->FputInt32(0);
551                 state_fio->FputInt32(0);
552         }
553         state_fio->FputUint8(key_column);
554 }
555
556 bool IO::load_state(FILEIO* state_fio)
557 {
558         close_tape();
559         
560         if(state_fio->FgetUint32() != STATE_VERSION) {
561                 return false;
562         }
563         if(state_fio->FgetInt32() != this_device_id) {
564                 return false;
565         }
566         state_fio->Fread(lcd, sizeof(lcd), 1);
567         lcd_status = state_fio->FgetInt32();
568         lcd_addr = state_fio->FgetInt32();
569         lcd_text = state_fio->FgetBool();
570         cmt_selected = state_fio->FgetBool();
571         cmt_ready = state_fio->FgetBool();
572         cmt_mode = state_fio->FgetUint8();
573         cmt_play = state_fio->FgetBool();
574         cmt_rec = state_fio->FgetBool();
575         state_fio->Fread(cmt_rec_file_path, sizeof(cmt_rec_file_path), 1);
576         int length_tmp = state_fio->FgetInt32();
577         if(cmt_rec) {
578                 cmt_fio->Fopen(cmt_rec_file_path, FILEIO_READ_WRITE_NEW_BINARY);
579                 while(length_tmp != 0) {
580                         uint8 buffer_tmp[1024];
581                         int length_rw = min(length_tmp, sizeof(buffer_tmp));
582                         state_fio->Fread(buffer_tmp, length_rw, 1);
583                         if(cmt_fio->IsOpened()) {
584                                 cmt_fio->Fwrite(buffer_tmp, length_rw, 1);
585                         }
586                         length_tmp -= length_rw;
587                 }
588         }
589         cmt_bufcnt = state_fio->FgetInt32();
590         cmt_buflen = state_fio->FgetInt32();
591         if(cmt_buflen) {
592                 cmt_buffer = (uint8 *)malloc(cmt_buflen);
593                 state_fio->Fread(cmt_buffer, cmt_buflen, 1);
594         }
595         key_column = state_fio->FgetUint8();
596         return true;
597 }
598