2 CANON X-07 Emulator 'eX-07'
5 Author : Takeda.Toshiya
11 #if defined(_MSC_VER) && (_MSC_VER >= 1400)
12 #pragma warning( disable : 4996 )
19 #include "../../fifo.h"
25 static const uint8 sub_cmd_len[0x47] = {
55 0x81, // 1d StartPgmWrite
56 0x81, // 1e SPWriteCont
71 1, // 2d KeyBufferClear
79 0x82, // 35 UdkContWrite
88 1, // 3e UnexecStartPgm
99 static const char *udk_ini[12] = {
114 static const int udk_ofs[12] = {
115 0, 42, 84, 126, 168, 210, 256, 298, 340, 382, 424, 466
118 static const int udk_size[12] = {
119 42, 42, 42, 42, 42, 46, 42, 42, 42, 42, 42, 46
122 static const int key_tbl[256] = {
123 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x0d,0x00,0x00,
124 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
125 0x20,0x00,0x00,0x00, 0x0b,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x12,0x16,0x00,
126 0x30,0x31,0x32,0x33, 0x34,0x35,0x36,0x37, 0x38,0x39,0x00,0x00, 0x00,0x00,0x00,0x00,
127 0x00,0x41,0x42,0x43, 0x44,0x45,0x46,0x47, 0x48,0x49,0x4a,0x4b, 0x4c,0x4d,0x4e,0x4f,
128 0x50,0x51,0x52,0x53, 0x54,0x55,0x56,0x57, 0x58,0x59,0x5a,0x00, 0x00,0x00,0x00,0x00,
129 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
130 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
131 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
132 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
133 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
134 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x3a,0x3b, 0x2c,0x2d,0x2e,0x2f,
135 0x40,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,0x00,0x5b, 0x5c,0x5d,0x5e,0x00,
137 0x00,0x00,0x5c,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,0x00, 0x00,0x00,0x00,0x00
141 static const int key_tbl_s[256] = {
142 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x0d,0x00,0x00,
143 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
144 0x20,0x00,0x00,0x00, 0x0c,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x12,0x16,0x00,
145 0x00,0x21,0x22,0x23, 0x24,0x25,0x26,0x27, 0x28,0x29,0x00,0x00, 0x00,0x00,0x00,0x00,
146 0x00,0x61,0x62,0x63, 0x64,0x65,0x66,0x67, 0x68,0x69,0x6a,0x6b, 0x6c,0x6d,0x6e,0x6f,
147 0x70,0x71,0x72,0x73, 0x74,0x75,0x76,0x77, 0x78,0x79,0x7a,0x00, 0x00,0x00,0x00,0x00,
148 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
149 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
150 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
151 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
152 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
153 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x2a,0x2b, 0x3c,0x3d,0x3e,0x3f,
154 0x60,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
155 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x7b, 0x7c,0x7d,0x7e,0x00,
156 0x00,0x00,0x5f,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
157 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00
160 static const int key_tbl_k[256] = {
161 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x0d,0x00,0x00,
162 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
163 0x20,0x00,0x00,0x00, 0x0b,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x12,0x16,0x00,
164 0xdc,0xc7,0xcc,0xb1, 0xb3,0xb4,0xb5,0xd4, 0xd5,0xd6,0x00,0x00, 0x00,0x00,0x00,0x00,
165 0x00,0xc1,0xba,0xbf, 0xbc,0xb2,0xca,0xb7, 0xb8,0xc6,0xcf,0xc9, 0xd8,0xd3,0xd0,0xd7,
166 0xbe,0xc0,0xbd,0xc4, 0xb6,0xc5,0xcb,0xc3, 0xbb,0xdd,0xc2,0x00, 0x00,0x00,0x00,0x00,
167 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
168 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
169 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
170 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
171 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
172 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0xb9,0xda, 0xc8,0xce,0xd9,0xd2,
173 0xde,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,0xdf, 0xb0,0xd1,0xcd,0x00,
175 0x00,0x00,0xdb,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
179 static const int key_tbl_ks[256] = {
180 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x0d,0x00,0x00,
181 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
182 0x20,0x00,0x00,0x00, 0x0c,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x12,0x16,0x00,
183 0xa6,0x00,0x00,0xa7, 0xa9,0xaa,0xab,0xac, 0xad,0xae,0x00,0x00, 0x00,0x00,0x00,0x00,
184 0x00,0x00,0x00,0x00, 0x00,0xa8,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
185 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0xaf,0x00, 0x00,0x00,0x00,0x00,
186 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
187 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
188 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
189 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
190 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
191 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0xa4,0x00,0xa1,0xa5,
192 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
193 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0xa2, 0x00,0xa3,0x00,0x00,
194 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
195 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00
198 static const int key_tbl_g[256] = {
199 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x0d,0x00,0x00,
200 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
201 0x20,0x00,0x00,0x00, 0x0c,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x12,0x16,0x00,
202 0x8a,0xe9,0x90,0x91, 0x92,0x93,0xec,0xe0, 0xf2,0xf1,0x00,0x00, 0x00,0x00,0x00,0x00,
203 0x00,0x88,0xed,0xe4, 0xef,0x99,0xfd,0x9d, 0xfe,0xf9,0xe5,0x9b, 0xf4,0xf5,0x89,0x9e,
204 0xf7,0x8b,0xf6,0x9f, 0x97,0x94,0x95,0xfb, 0x98,0x96,0xe1,0x00, 0x00,0x00,0x00,0x00,
205 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
206 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
207 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
208 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
209 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
210 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x81,0x82, 0x9c,0xf0,0x9a,0x80,
211 0xe7,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
212 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x84, 0x00,0x85,0xfc,0x00,
213 0x00,0x00,0x83,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
214 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00
217 static const int key_tbl_c[256] = {
218 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x0d,0x00,0x00,
219 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
220 0x20,0x00,0x00,0x00, 0x0b,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x12,0x16,0x00,
221 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
222 0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07, 0x08,0x09,0x0a,0x0b, 0x0c,0x0d,0x0e,0x0f,
223 0x10,0x11,0x12,0x13, 0x14,0x15,0x16,0x17, 0x18,0x19,0x1a,0x00, 0x00,0x00,0x00,0x00,
224 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
225 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
226 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
227 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
228 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
229 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
230 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
231 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
232 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
233 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00
236 //memo: how to request the display size changing
237 //emu->change_screen_size(TV_SCREEN_WIDTH, TV_SCREEN_HEIGHT, -1, -1, TV_WINDOW_WIDTH, TV_WINDOW_HEIGHT);
238 //emu->change_screen_size(SCREEN_WIDTH, SCREEN_HEIGHT, -1, -1, WINDOW_WIDTH, WINDOW_HEIGHT);
240 void IO::initialize()
243 FILEIO* fio = new FILEIO();
244 if(fio->Fopen(emu->bios_path(_T("FONT.ROM")), FILEIO_READ_BINARY)) {
245 fio->Fread(font, sizeof(font), 1);
251 emu->get_host_time(&cur_time);
252 register_event(this, EVENT_1SEC, 1000000, true, ®ister_id_1sec);
255 key_buf = new FIFO(20);
256 cmd_buf = new FIFO(256);
257 rsp_buf = new FIFO(256);
260 memset(wram, 0, 0x200);
261 for(int i = 0; i < 12; i++) {
262 strcpy((char*)wram + udk_ofs[i], udk_ini[i]);
264 for(int i = 0; i < 0x200; i++) {
269 memcpy(udc, font, sizeof(udc));
272 cmt_fio = new FILEIO();
273 cmt_play = cmt_rec = false;
276 register_frame_event(this);
277 register_vline_event(this);
296 memset(rregs, 0, sizeof(rregs));
297 memset(wregs, 0, sizeof(wregs));
306 ctrl = shift = kana = graph = brk = false;
308 strig = strig1 = 0xff;
315 memset(lcd, 0, sizeof(lcd));
316 locate_on = cursor_on = udk_on = false;
317 locate_x = locate_y = cursor_x = cursor_y = cursor_blink = 0;
322 register_id_beep = -1;
325 void IO::event_callback(int event_id, int err)
327 if(event_id == EVENT_BEEP) {
328 register_id_beep = -1;
329 d_beep->write_signal(SIG_BEEP_ON, 0, 0);
330 rregs[4] = (wregs[4] &= ~2);
331 } else if(event_id == EVENT_CMT) {
334 } else if(event_id == EVENT_1SEC) {
335 if(cur_time.initialized) {
336 cur_time.increment();
338 emu->get_host_time(&cur_time); // resync
339 cur_time.initialized = true;
344 void IO::event_frame()
349 void IO::event_vline(int v, int clock)
354 void IO::write_io8(uint32 addr, uint32 data)
356 // emu->out_debug_log("OUT\t%4x, %2x\n", addr, data);
357 switch(addr & 0xff) {
362 // d_mem->write_signal(0, data, 0xff);
368 wregs[addr & 7] = data;
371 rregs[4] = wregs[4] = data;
373 cmt_mode = ((data & 0x0c) == 8);
374 // if(cmt_mode && (wregs[5] & 4)) {
378 if((data & 0x0e) == 0x0e) {
379 double freq = 192000.0 / (wregs[2] | (wregs[3] << 8));
380 d_beep->set_frequency(freq);
381 d_beep->write_signal(SIG_BEEP_ON, 1, 1);
382 // temporary patch: register the event to stop
383 int intv = ram[0x450] * 50000;
384 if(register_id_beep != -1) {
385 cancel_event(this, register_id_beep);
387 register_event(this, EVENT_BEEP, intv, false, ®ister_id_beep);
389 d_beep->write_signal(SIG_BEEP_ON, 0, 1);
413 uint32 IO::read_io8(uint32 addr)
417 switch(addr & 0xff) {
431 val = ((addr & 0x0f) < 8) ? udc[(font_code << 3) | (addr & 7)] : 0;
434 val = vblank ? 0x80 : 0;
442 val = rregs[addr & 7];
459 // emu->out_debug_log("IN\t%4x = %2x\n", addr, val);
463 void IO::update_intr()
465 if(!key_buf->empty()) {
467 rregs[1] = key_buf->read();
469 d_cpu->write_signal(SIG_NSC800_RSTA, 1, 1);
475 d_cpu->write_signal(SIG_NSC800_RSTA, 1, 1);
476 } else if(sub_int & 1) {
479 d_cpu->write_signal(SIG_NSC800_RSTA, 1, 1);
480 } else if(sub_int & 2) {
482 d_cpu->write_signal(SIG_NSC800_RSTB, 1, 1);
486 // ----------------------------------------------------------------------------
488 // ----------------------------------------------------------------------------
490 void IO::draw_screen()
492 scrntype cd = RGB_COLOR(48, 56, 16);
493 scrntype cb = RGB_COLOR(160, 168, 160);
495 for(int y = 0; y < 4; y++) {
497 for(int x = 0; x < 20; x++) {
499 if(cursor_on && (cursor_blink & 0x20) && cursor_x == x && cursor_y == y) {
500 for(int l = 0; l < 8; l++) {
501 scrntype* dest = emu->screen_buffer(py + l);
503 dest[0] = dest[1] = dest[2] = dest[3] = dest[4] = dest[5] = (l < 7) ? cb : cd;
506 for(int l = 0; l < 8; l++) {
507 uint8* src = &lcd[py + l][px];
508 scrntype* dest = emu->screen_buffer(py + l);
510 dest[0] = src[0] ? cd : cb;
511 dest[1] = src[1] ? cd : cb;
512 dest[2] = src[2] ? cd : cb;
513 dest[3] = src[3] ? cd : cb;
514 dest[4] = src[4] ? cd : cb;
515 dest[5] = src[5] ? cd : cb;
522 void IO::draw_font(int x, int y, uint8 code)
524 if(x < 20 && y < 4) {
528 for(int l = 0; l < 8; l++) {
529 uint8 pat = udc[ofs + l];
530 lcd[py + l][px + 0] = (pat & 0x80) ? 0xff : 0;
531 lcd[py + l][px + 1] = (pat & 0x40) ? 0xff : 0;
532 lcd[py + l][px + 2] = (pat & 0x20) ? 0xff : 0;
533 lcd[py + l][px + 3] = (pat & 0x10) ? 0xff : 0;
534 lcd[py + l][px + 4] = (pat & 0x08) ? 0xff : 0;
535 lcd[py + l][px + 5] = (pat & 0x04) ? 0xff : 0;
542 for(int i = 0, x = 0; i < 5; i++) {
543 int ofs = udk_ofs[i + (shift ? 6 : 0)];
544 draw_font(x++, 3, 0x83);
545 for(int j = 0; j < 3; j++) {
546 draw_font(x++, 3, wram[ofs++]);
551 #define draw_point(x, y, c) { if((x) < 120 && (y) < 32) lcd[y][x] = c; }
553 void IO::draw_line(int sx, int sy, int ex, int ey)
555 int next_x = sx, next_y = sy;
556 int delta_x = abs(ex - sx) * 2;
557 int delta_y = abs(ey - sy) * 2;
558 int step_x = (ex < sx) ? -1 : 1;
559 int step_y = (ey < sy) ? -1 : 1;
561 if(delta_x > delta_y) {
562 int frac = delta_y - delta_x / 2;
563 while(next_x != ex) {
570 draw_point(next_x, next_y, 0xff);
573 int frac = delta_x - delta_y / 2;
574 while(next_y != ey) {
581 draw_point(next_x, next_y, 0xff);
584 draw_point(sx, sy, 0xff);
585 draw_point(ex, ey, 0xff);
588 void IO::draw_circle(int x, int y, int r)
592 double xlim = sqrt((double)(r * r) / 2);
594 for(int cx = 0, cy = r; cx <= xlim ; cx++) {
595 double d1 = (cx * cx + cy * cy) - r * r;
596 double d2 = (cx * cx + (cy - 1) * (cy - 1)) - r * r;
597 if(abs(d1) > abs(d2)) {
600 draw_point(cx + x, cy + y, 0xff);
601 draw_point(cx + x, -cy + y, 0xff);
602 draw_point(-cx + x, cy + y, 0xff);
603 draw_point(-cx + x, -cy + y, 0xff);
604 draw_point(cy + x, cx + y, 0xff);
605 draw_point(cy + x, -cx + y, 0xff);
606 draw_point(-cy + x, cx + y, 0xff);
607 draw_point(-cy + x, -cx + y, 0xff);
614 draw_point(cx + x, cy + y, 0xff);
615 draw_point(cx + x, -cy + y, 0xff);
616 draw_point(cy + x, cx + y, 0xff);
617 draw_point(-cy + x, cx + y, 0xff);
630 draw_point(cx + x, cy + y, 0xff);
631 draw_point(-cx + x, cy + y, 0xff);
632 draw_point(-cx + x, -cy + y, 0xff);
633 draw_point(cx + x, -cy + y, 0xff);
638 void IO::line_clear(int y)
641 for(int l = y * 8; l < (y + 1) * 8; l++) {
642 memset(lcd[l], 0, 120);
649 if(scroll_min <= scroll_max && scroll_max <= 4) {
650 for(int l = scroll_min * 8; l < (scroll_max - 1) * 8; l++) {
651 memcpy(lcd[l], lcd[l + 8], 120);
653 for(int l = (scroll_max - 1) * 8; l < scroll_max * 8; l++) {
654 memset(lcd[l], 0, 120);
659 // ----------------------------------------------------------------------------
661 // ----------------------------------------------------------------------------
663 void IO::key_down(int code)
679 graph = kana = false;
690 graph = kana = false;
714 if(!key_buf->full()) {
715 key_buf->write(code);
720 fctn = shift ? 6 : 0;
723 fctn = shift ? 7 : 1;
726 fctn = shift ? 8 : 2;
729 fctn = shift ? 9 : 3;
732 fctn = shift ? 10 : 4;
736 fctn = shift ? 11 : 5;
756 ptr = udk_ofs[fctn] + 3;
758 uint8 val = wram[ptr++];
762 if(!key_buf->full()) {
766 if(!key_buf->empty()) {
771 if(!key_buf->full()) {
774 val = key_tbl_c[code];
777 val = key_tbl_ks[code];
779 val = key_tbl_k[code];
782 val = key_tbl_g[code];
785 val = key_tbl_s[code];
798 void IO::key_up(int code)
801 case 0x08: // bs->left
828 // ----------------------------------------------------------------------------
830 // ----------------------------------------------------------------------------
832 void IO::play_tape(_TCHAR* file_path)
835 if(cmt_fio->Fopen(file_path, FILEIO_READ_BINARY)) {
836 cmt_fio->Fseek(0, FILEIO_SEEK_END);
837 cmt_len = min(cmt_fio->Ftell(), CMT_BUF_SIZE);
838 cmt_fio->Fseek(0, FILEIO_SEEK_SET);
839 memset(cmt_buf, 0, sizeof(cmt_buf));
840 cmt_fio->Fread(cmt_buf, cmt_len, 1);
844 // receive first byte
845 if(cmt_mode && (wregs[5] & 4)) {
851 void IO::rec_tape(_TCHAR* file_path)
854 if(cmt_fio->Fopen(file_path, FILEIO_READ_WRITE_NEW_BINARY)) {
855 _tcscpy_s(rec_file_path, _MAX_PATH, file_path);
861 void IO::close_tape()
863 if(cmt_fio->IsOpened()) {
864 if(cmt_rec && cmt_ptr) {
865 cmt_fio->Fwrite(cmt_buf, cmt_ptr, 1);
869 cmt_play = cmt_rec = false;
872 void IO::send_to_cmt()
874 if(cmt_rec && cmt_mode) {
875 cmt_buf[cmt_ptr++] = wregs[7];
876 if(!(cmt_ptr &= (CMT_BUF_SIZE - 1))) {
877 cmt_fio->Fwrite(cmt_buf, sizeof(cmt_buf), 1);
882 void IO::recv_from_cmt()
884 if(cmt_play && cmt_mode) {
886 rregs[7] = (cmt_ptr < cmt_len) ? cmt_buf[cmt_ptr++] : 0;
887 // register event for rstb
888 register_event(this, EVENT_CMT, 2000, false, NULL);
892 // ----------------------------------------------------------------------------
894 // ----------------------------------------------------------------------------
896 void IO::send_to_sub()
899 if(cmd_buf->empty()) {
900 if(locate_on && (wregs[1] & 0x7f) != 0x24 && 0x20 <= wregs[1] && wregs[1] < 0x80) {
902 draw_font(cursor_x, cursor_x, wregs[1]);
904 if((wregs[1] & 0x7f) < 0x47) {
905 cmd_buf->write(wregs[1] & 0x7f);
910 cmd_buf->write(wregs[1]);
911 if(cmd_buf->count() == 2) {
912 uint8 cmd_type = cmd_buf->read_not_remove(0);
913 if(cmd_type == 7 && wregs[1] > 4) {
915 cmd_buf->write(wregs[1] & 0x7f);
916 } else if(cmd_type == 0x0c && wregs[1] == 0xb0) {
917 memset(lcd, 0, sizeof(lcd));
919 cmd_buf->write(wregs[1] & 0x7f);
924 if(!cmd_buf->empty()) {
925 uint8 cmd_type = cmd_buf->read_not_remove(0);
926 uint8 cmd_len = sub_cmd_len[cmd_type];
928 if((cmd_len & 0x7f) < cmd_buf->count() && !wregs[1]) {
929 cmd_len = cmd_buf->count();
932 if(cmd_buf->count() == cmd_len) {
937 if(rsp_buf->count()) {
941 // emu->out_debug_log("CMD TYPE = %2x, LEN = %d RSP=%d\n", cmd_type, cmd_len, rsp_buf->count());
946 void IO::recv_from_sub()
949 rregs[1] = rsp_buf->read_not_remove(0);
953 void IO::ack_from_sub()
957 if(!rsp_buf->empty()) {
963 void IO::process_sub()
965 static const uint8 dow[8] = {128, 192, 224, 240, 248, 252, 254, 255};
968 int sx, sy, ex, ey, cr, i;
970 uint8 cmd_type = cmd_buf->read();
971 switch(cmd_type & 0x7f) {
972 case 0x00: // unknown
974 case 0x01: // TimeCall
975 rsp_buf->write((cur_time.year >> 8) & 0xff);
976 rsp_buf->write(cur_time.year & 0xff);
977 rsp_buf->write(cur_time.month);
978 rsp_buf->write(cur_time.day);
979 rsp_buf->write(dow[cur_time.day_of_week]);
980 rsp_buf->write(cur_time.hour);
981 rsp_buf->write(cur_time.minute);
982 rsp_buf->write(cur_time.second);
985 rsp_buf->write(stick);
988 rsp_buf->write(strig);
991 rsp_buf->write(strig1);
993 case 0x05: // RamRead
994 addr = cmd_buf->read();
995 addr |= cmd_buf->read() << 8;
998 } else if(addr == 0xd000) {
1000 } else if(WRAM_OFS_UDC0 <= addr && addr < WRAM_OFS_UDC1) {
1001 val = udc[FONT_OFS_UDC0 + (addr - WRAM_OFS_UDC0)];
1002 } else if(WRAM_OFS_UDC1 <= addr && addr < WRAM_OFS_KBUF) {
1003 val = udc[FONT_OFS_UDC1 + (addr - WRAM_OFS_UDC1)];
1005 val = wram[addr & 0x7ff];
1007 rsp_buf->write(val);
1009 case 0x06: // RamWrite
1010 val = cmd_buf->read();
1011 addr = cmd_buf->read();
1012 addr |= cmd_buf->read() << 8;
1013 if(WRAM_OFS_UDC0 <= addr && addr < WRAM_OFS_UDC1) {
1014 udc[FONT_OFS_UDC0 + (addr - WRAM_OFS_UDC0)] = val;
1015 } else if(WRAM_OFS_UDC1 <= addr && addr < WRAM_OFS_KBUF) {
1016 udc[FONT_OFS_UDC1 + (addr - WRAM_OFS_UDC1)] = val;
1018 wram[addr & 0x7ff] = val;
1021 case 0x07: // ScrollSet
1022 scroll_min = cmd_buf->read();
1023 scroll_max = cmd_buf->read() + 1;
1025 case 0x08: // ScrollExec
1028 case 0x09: // LineClear
1029 val = cmd_buf->read();
1032 case 0x0a: // TimeSet
1033 cur_time.second = cmd_buf->read();
1034 cur_time.minute = cmd_buf->read();
1035 cur_time.hour = cmd_buf->read();
1036 cmd_buf->read(); // day of week
1037 cur_time.day = cmd_buf->read();
1038 cur_time.month = cmd_buf->read();
1039 cur_time.year = cmd_buf->read();
1040 cur_time.year |= cmd_buf->read() << 8;
1041 cur_time.update_year();
1042 cur_time.update_day_of_week();
1044 cancel_event(this, register_id_1sec);
1045 register_event(this, EVENT_1SEC, 1000000, true, ®ister_id_1sec);
1047 case 0x0b: // CalcDay
1049 case 0x0c: // AlarmSet
1050 for(i = 0; i < 8; i++) {
1051 alarm[i] = cmd_buf->read();
1054 case 0x0d: // BuzzerOff
1055 // d_beep->write_signal(SIG_BEEP_ON, 0, 0);
1057 case 0x0e: // BuzzerOn
1058 // d_beep->write_signal(SIG_BEEP_ON, 1, 1);
1060 case 0x0f: // TrfLine
1061 sy = cmd_buf->read();
1062 for(i = 0; i < 120; i++) {
1064 rsp_buf->write(lcd[sy][i]);
1070 case 0x10: // TestPoint
1071 sx = cmd_buf->read();
1072 sy = cmd_buf->read();
1073 if(sx < 120 && sy < 32) {
1074 rsp_buf->write(lcd[sy][sx]);
1080 sx = cmd_buf->read();
1081 sy = cmd_buf->read();
1082 draw_point(sx, sy, 0xff);
1084 case 0x12: // Preset
1085 sx = cmd_buf->read();
1086 sy = cmd_buf->read();
1087 draw_point(sx, sy, 0);
1090 sx = cmd_buf->read();
1091 sy = cmd_buf->read();
1092 if(sx < 120 && sy < 32) {
1093 lcd[sy][sx] = ~lcd[sy][sx];
1097 sx = cmd_buf->read();
1098 sy = cmd_buf->read();
1099 ex = cmd_buf->read();
1100 ey = cmd_buf->read();
1101 draw_line(sx, sy, ex, ey);
1103 case 0x15: // Circle
1104 sx = cmd_buf->read();
1105 sy = cmd_buf->read();
1106 cr = cmd_buf->read();
1107 draw_circle(sx, sy, cr);
1109 case 0x16: // UDKWrite
1110 val = cmd_buf->read();
1111 for(i = 0; i < udk_size[val]; i++) {
1112 wram[udk_ofs[val] + i] = cmd_buf->read();
1115 case 0x17: // UDKRead
1116 val = cmd_buf->read();
1117 for(i = 0; i < udk_size[val]; i++) {
1118 uint8 code = wram[udk_ofs[val] + i];
1119 rsp_buf->write(code);
1126 case 0x19: // UDKOff
1128 case 0x1a: // UDCWrite
1129 addr = cmd_buf->read() << 3;
1130 for(i = 0; i < 8; i++) {
1131 udc[addr + i] = cmd_buf->read();
1134 case 0x1b: // UDCRead
1135 addr = cmd_buf->read() << 3;
1136 for(i = 0; i < 8; i++) {
1137 rsp_buf->write(udc[addr + i]);
1140 case 0x1c: // UDCInit
1141 memcpy(udc, font, sizeof(udc));
1143 case 0x1d: // StartPgmWrite
1145 case 0x1e: // SPWriteCont
1151 case 0x21: // StartPgmRead
1152 for(i = 0; i < 128; i++) {
1156 case 0x22: // OnStat
1157 rsp_buf->write(4); // 0x41 ?
1159 case 0x23: // OFFReq
1161 case 0x24: // Locate
1162 sx = cmd_buf->read();
1163 sy = cmd_buf->read();
1164 val = cmd_buf->read();
1165 locate_on = (locate_x != sx || locate_y != sy);
1166 locate_x = cursor_x = sx;
1167 locate_y = cursor_y = sy;
1169 draw_font(sx, sy, val);
1172 case 0x25: // CursOn
1175 case 0x26: // CursOff
1178 case 0x27: // TestKey
1179 case 0x28: // TestChr
1182 case 0x29: // InitSec
1183 case 0x2a: // InitDate
1184 case 0x2b: // ScrOff
1187 case 0x2d: // KeyBufferClear
1190 case 0x2e: // ClsScr
1191 memset(lcd, 0, sizeof(lcd));
1194 cursor_x = cursor_y = 0;
1200 case 0x31: // UDKOff
1204 case 0x36: // AlarmRead
1205 for(i = 0; i < 8; i++) {
1206 rsp_buf->write(alarm[i]);
1209 case 0x37: // BuzzZero
1213 memset(wram, 0, 0x200);
1214 for(i = 0; i < 12; i++) {
1215 strcpy((char*)wram + udk_ofs[i], udk_ini[i]);
1217 for(i = 0; i < 0x200; i++) {
1219 if(wram[i] == '^') {
1224 case 0x42: // ReadCar
1225 for(i = 0; i < 8; i++) {
1234 case 0x45: // TimeChk
1235 case 0x46: // AlmChk
1241 #define STATE_VERSION 1
1243 void IO::save_state(FILEIO* state_fio)
1245 state_fio->FputUint32(STATE_VERSION);
1246 state_fio->FputInt32(this_device_id);
1248 state_fio->Fwrite(rregs, sizeof(rregs), 1);
1249 state_fio->Fwrite(wregs, sizeof(wregs), 1);
1250 cur_time.save_state((void *)state_fio);
1251 state_fio->FputInt32(register_id_1sec);
1252 cmd_buf->save_state((void *)state_fio);
1253 rsp_buf->save_state((void *)state_fio);
1254 state_fio->FputUint8(sub_int);
1255 state_fio->Fwrite(wram, sizeof(wram), 1);
1256 state_fio->Fwrite(alarm, sizeof(alarm), 1);
1257 key_buf->save_state((void *)state_fio);
1258 state_fio->FputBool(ctrl);
1259 state_fio->FputBool(shift);
1260 state_fio->FputBool(kana);
1261 state_fio->FputBool(graph);
1262 state_fio->FputBool(brk);
1263 state_fio->FputUint8(stick);
1264 state_fio->FputUint8(strig);
1265 state_fio->FputUint8(strig1);
1266 state_fio->FputBool(cmt_play);
1267 state_fio->FputBool(cmt_rec);
1268 state_fio->FputBool(cmt_mode);
1269 state_fio->Fwrite(rec_file_path, sizeof(rec_file_path), 1);
1270 if(cmt_rec && cmt_fio->IsOpened()) {
1271 int length_tmp = (int)cmt_fio->Ftell();
1272 cmt_fio->Fseek(0, FILEIO_SEEK_SET);
1273 state_fio->FputInt32(length_tmp);
1274 while(length_tmp != 0) {
1275 uint8 buffer_tmp[1024];
1276 int length_rw = min(length_tmp, sizeof(buffer_tmp));
1277 cmt_fio->Fread(buffer_tmp, length_rw, 1);
1278 state_fio->Fwrite(buffer_tmp, length_rw, 1);
1279 length_tmp -= length_rw;
1282 state_fio->FputInt32(0);
1284 state_fio->FputInt32(cmt_len);
1285 state_fio->FputInt32(cmt_ptr);
1286 state_fio->Fwrite(cmt_buf, sizeof(cmt_buf), 1);
1287 state_fio->FputBool(vblank);
1288 state_fio->FputUint8(font_code);
1289 state_fio->Fwrite(udc, sizeof(udc), 1);
1290 state_fio->Fwrite(lcd, sizeof(lcd), 1);
1291 state_fio->FputBool(locate_on);
1292 state_fio->FputBool(cursor_on);
1293 state_fio->FputBool(udk_on);
1294 state_fio->FputInt32(locate_x);
1295 state_fio->FputInt32(locate_y);
1296 state_fio->FputInt32(cursor_x);
1297 state_fio->FputInt32(cursor_y);
1298 state_fio->FputInt32(cursor_blink);
1299 state_fio->FputInt32(scroll_min);
1300 state_fio->FputInt32(scroll_max);
1301 state_fio->FputInt32(register_id_beep);
1304 bool IO::load_state(FILEIO* state_fio)
1308 if(state_fio->FgetUint32() != STATE_VERSION) {
1311 if(state_fio->FgetInt32() != this_device_id) {
1314 state_fio->Fread(rregs, sizeof(rregs), 1);
1315 state_fio->Fread(wregs, sizeof(wregs), 1);
1316 if(!cur_time.load_state((void *)state_fio)) {
1319 register_id_1sec = state_fio->FgetInt32();
1320 if(!cmd_buf->load_state((void *)state_fio)) {
1323 if(!rsp_buf->load_state((void *)state_fio)) {
1326 sub_int = state_fio->FgetUint8();
1327 state_fio->Fread(wram, sizeof(wram), 1);
1328 state_fio->Fread(alarm, sizeof(alarm), 1);
1329 if(!key_buf->load_state((void *)state_fio)) {
1332 ctrl = state_fio->FgetBool();
1333 shift = state_fio->FgetBool();
1334 kana = state_fio->FgetBool();
1335 graph = state_fio->FgetBool();
1336 brk = state_fio->FgetBool();
1337 stick = state_fio->FgetUint8();
1338 strig = state_fio->FgetUint8();
1339 strig1 = state_fio->FgetUint8();
1340 cmt_play = state_fio->FgetBool();
1341 cmt_rec = state_fio->FgetBool();
1342 cmt_mode = state_fio->FgetBool();
1343 state_fio->Fread(rec_file_path, sizeof(rec_file_path), 1);
1344 int length_tmp = state_fio->FgetInt32();
1346 cmt_fio->Fopen(rec_file_path, FILEIO_READ_WRITE_NEW_BINARY);
1347 while(length_tmp != 0) {
1348 uint8 buffer_tmp[1024];
1349 int length_rw = min(length_tmp, sizeof(buffer_tmp));
1350 state_fio->Fread(buffer_tmp, length_rw, 1);
1351 if(cmt_fio->IsOpened()) {
1352 cmt_fio->Fwrite(buffer_tmp, length_rw, 1);
1354 length_tmp -= length_rw;
1357 cmt_len = state_fio->FgetInt32();
1358 cmt_ptr = state_fio->FgetInt32();
1359 state_fio->Fread(cmt_buf, sizeof(cmt_buf), 1);
1360 vblank = state_fio->FgetBool();
1361 font_code = state_fio->FgetUint8();
1362 state_fio->Fread(udc, sizeof(udc), 1);
1363 state_fio->Fread(lcd, sizeof(lcd), 1);
1364 locate_on = state_fio->FgetBool();
1365 cursor_on = state_fio->FgetBool();
1366 udk_on = state_fio->FgetBool();
1367 locate_x = state_fio->FgetInt32();
1368 locate_y = state_fio->FgetInt32();
1369 cursor_x = state_fio->FgetInt32();
1370 cursor_y = state_fio->FgetInt32();
1371 cursor_blink = state_fio->FgetInt32();
1372 scroll_min = state_fio->FgetInt32();
1373 scroll_max = state_fio->FgetInt32();
1374 register_id_beep = state_fio->FgetInt32();