OSDN Git Service

b9b9dc142284d3f2b64b3e00a51db9939cba7e1e
[csp-qt/common_source_project-fm7.git] / source / src / vm / smc777 / io.cpp
1 /*
2         SONY SMC-777 Emulator 'eSMC-777'
3
4         Author : Takeda.Toshiya
5         Date   : 2015.08.13-
6
7         [ i/o and memory bus ]
8 */
9
10 #include "io.h"
11 #include "../datarec.h"
12 #include "../mb8877.h"
13 #include "../pcm1bit.h"
14
15 #define EVENT_KEY_REPEAT        0
16
17 #define SET_BANK(s, e, w, r) { \
18         int sb = (s) >> 14, eb = (e) >> 14; \
19         for(int i = sb; i <= eb; i++) { \
20                 if((w) == wdmy) { \
21                         wbank[i] = wdmy; \
22                 } else { \
23                         wbank[i] = (w) + 0x4000 * (i - sb); \
24                 } \
25                 if((r) == rdmy) { \
26                         rbank[i] = rdmy; \
27                 } else { \
28                         rbank[i] = (r) + 0x4000 * (i - sb); \
29                 } \
30         } \
31 }
32
33 static const uint8 keytable_base[68][6] = {
34         {0x70, 0x01, 0x15, 0x1a, 0x01, 0x15},   // F1
35         {0x71, 0x02, 0x18, 0x10, 0x02, 0x18},   // F2
36         {0x72, 0x04, 0x12, 0x13, 0x04, 0x12},   // F3
37         {0x73, 0x06, 0x05, 0x07, 0x06, 0x05},   // F4
38         {0x74, 0x0b, 0x03, 0x0c, 0x0b, 0x03},   // F5
39         {0x23, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e},   // CLR -> END
40         {0x2e, 0x11, 0x11, 0x11, 0x11, 0x11},   // DEL
41         {0x2d, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f},   // INS
42         {0x24, 0x14, 0x14, 0x14, 0x14, 0x14},   // HOME
43         {0x25, 0x16, 0x16, 0x16, 0x16, 0x16},   // LEFT
44         {0x26, 0x17, 0x17, 0x17, 0x17, 0x17},   // UP
45         {0x28, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},   // DOWN
46         {0x27, 0x19, 0x19, 0x19, 0x19, 0x19},   // RIGHT
47         {0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b},   // ESC
48         {0x31, 0x31, 0x21, 0x00, 0xb1, 0xa7},   // '1'
49         {0x32, 0x32, 0x40, 0x00, 0xb2, 0xa8},   // '2'
50         {0x33, 0x33, 0x23, 0x00, 0xb3, 0xa9},   // '3'
51         {0x34, 0x34, 0x24, 0x00, 0xb4, 0xaa},   // '4'
52         {0x35, 0x35, 0x25, 0x00, 0xb5, 0xab},   // '5'
53         {0x36, 0x36, 0x5e, 0x00, 0xc5, 0xc5},   // '6'
54         {0x37, 0x37, 0x26, 0x00, 0xc6, 0xc6},   // '7'
55         {0x38, 0x38, 0x2a, 0x00, 0xc7, 0xc7},   // '8'
56         {0x39, 0x39, 0x28, 0x00, 0xc8, 0xc8},   // '9'
57         {0x30, 0x30, 0x29, 0x00, 0xc9, 0xc9},   // '0'
58         {0xbd, 0x2d, 0x5f, 0x00, 0xd7, 0xd7},   // '-'
59         {0xde, 0x3d, 0x2b, 0x00, 0xd8, 0xd8},   // '='
60         {0xdc, 0x7f, 0x7f, 0x7f, 0xd9, 0xd9},   // RUB OUT -> '\'
61         {0x08, 0x08, 0x08, 0x08, 0x08, 0x08},   // BS
62         {0x51, 0x71, 0x51, 0x11, 0xb6, 0xb6},   // 'Q'
63         {0x57, 0x77, 0x57, 0x17, 0xb7, 0xb7},   // 'W'
64         {0x45, 0x65, 0x45, 0x05, 0xb8, 0xb8},   // 'E'
65         {0x52, 0x72, 0x52, 0x12, 0xb9, 0xb9},   // 'R'
66         {0x54, 0x74, 0x54, 0x14, 0xba, 0xba},   // 'T'
67         {0x59, 0x79, 0x59, 0x19, 0xca, 0xca},   // 'Y'
68         {0x55, 0x75, 0x55, 0x15, 0xcb, 0xcb},   // 'U'
69         {0x49, 0x69, 0x49, 0x09, 0xcc, 0xcc},   // 'I'
70         {0x4f, 0x6f, 0x4f, 0x0f, 0xcd, 0xcd},   // 'O'
71         {0x50, 0x70, 0x50, 0x10, 0xce, 0xce},   // 'P'
72         {0xc0, 0x5b, 0x7b, 0x1b, 0xda, 0xda},   // '['
73         {0xdb, 0x5d, 0x7d, 0x1d, 0xdb, 0xb0},   // ']'
74         {0x7b, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a},   // LF -> F12
75         {0x41, 0x61, 0x41, 0x01, 0xbb, 0xbb},   // 'A'
76         {0x53, 0x73, 0x53, 0x13, 0xbc, 0xbc},   // 'S'
77         {0x44, 0x64, 0x44, 0x04, 0xbd, 0xbd},   // 'D'
78         {0x46, 0x66, 0x46, 0x06, 0xbe, 0xbe},   // 'F'
79         {0x47, 0x67, 0x47, 0x07, 0xbf, 0xbf},   // 'G'
80         {0x48, 0x68, 0x48, 0x08, 0xcf, 0xcf},   // 'H'
81         {0x4a, 0x6a, 0x4a, 0x0a, 0xd0, 0xd0},   // 'J'
82         {0x4b, 0x6b, 0x4b, 0x0b, 0xd1, 0xd1},   // 'K'
83         {0x4c, 0x6c, 0x4c, 0x0c, 0xd2, 0xd2},   // 'L'
84         {0xbb, 0x3b, 0x3a, 0x00, 0xd3, 0xd3},   // ';'
85         {0xba, 0x27, 0x22, 0x00, 0xde, 0xa2},   // ','
86         {0xdd, 0x60, 0x7e, 0x00, 0xdf, 0xa3},   // '`'
87         {0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d},   // RETURN
88         {0x5a, 0x7a, 0x5a, 0x1a, 0xc0, 0xc0},   // 'Z'
89         {0x58, 0x78, 0x58, 0x18, 0xc1, 0xc1},   // 'X'
90         {0x43, 0x63, 0x43, 0x03, 0xc2, 0xaf},   // 'C'
91         {0x56, 0x76, 0x56, 0x16, 0xc3, 0xc3},   // 'V'
92         {0x42, 0x62, 0x42, 0x02, 0xc4, 0xc4},   // 'B'
93         {0x4e, 0x6e, 0x4e, 0x0e, 0xd4, 0xac},   // 'N'
94         {0x4d, 0x6d, 0x4d, 0x0d, 0xd5, 0xad},   // 'M'
95         {0xbc, 0x2c, 0x3c, 0x00, 0xd6, 0xae},   // ','
96         {0xbe, 0x2e, 0x3e, 0x1e, 0xdc, 0xa4},   // '.'
97         {0xbf, 0x2f, 0x3f, 0x1f, 0xa6, 0xa1},   // '/'
98         {0xe2, 0x5c, 0x7c, 0x1c, 0xdd, 0xa5},   // '\'
99         {0x09, 0x09, 0x09, 0x09, 0x09, 0x09},   // TAB
100         {0x20, 0x20, 0x20, 0x20, 0x20, 0x20},   // SPACE
101         {0x7a, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d}    // H -> F11
102 };
103
104 void IO::initialize()
105 {
106         // initialize memory
107         memset(ram, 0, sizeof(ram));
108         memset(rom, 0xff, sizeof(rom));
109         memset(cram, 0, sizeof(cram));
110         memset(aram, 0, sizeof(aram));
111         memset(pcg, 0, sizeof(pcg));
112         memset(gram, 0, sizeof(gram));
113         memset(rdmy, 0xff, sizeof(rdmy));
114         memset(kanji, 0xff, sizeof(kanji));
115         
116         // load WinSMC rom images
117         FILEIO* fio = new FILEIO();
118         if(fio->Fopen(emu->bios_path(_T("SMCROM.DAT")), FILEIO_READ_BINARY)) {
119                 fio->Fread(rom, sizeof(rom), 1);
120                 fio->Fclose();
121         }
122         if(fio->Fopen(emu->bios_path(_T("KANJIROM.DAT")), FILEIO_READ_BINARY)) {
123                 fio->Fread(kanji, sizeof(kanji), 1);
124                 fio->Fclose();
125         }
126         delete fio;
127         
128         // initialize inputs
129         initialize_key();
130         caps = kana = false;
131         key_stat = emu->key_buffer();
132         joy_stat = emu->joy_buffer();
133         
134         // initialize display
135         static const uint8 color_table[16][3] = {
136                 {  0,  0,  0}, {  0,  0,255}, {  0,255,  0}, {  0,255,255}, {255,  0,  0}, {255,  0,255}, {255,255,  0}, {255,255,255},
137                 // from WinSMC
138                 { 16, 64, 16}, { 16,112, 32}, {208, 80, 32}, {224,144, 32}, { 16, 80,128}, { 16,144,224}, {240,112,144}, {128,128,128}
139         };
140         for(int i = 0; i < 16 + 16; i++) {
141                 palette_pc[i] = RGB_COLOR(color_table[i & 15][0], color_table[i & 15][1], color_table[i & 15][2]);
142         }
143         vsup = false;
144         use_palette_text = use_palette_graph = false;
145         memset(pal, 0, sizeof(pal));
146         
147         // register event
148         register_frame_event(this);
149 }
150
151 void IO::reset()
152 {
153         SET_BANK(0x0000, 0x3fff, wdmy, rom);
154         SET_BANK(0x4000, 0xffff, ram + 0x4000, ram + 0x4000);
155         rom_selected = true;
156         rom_switch_wait = ram_switch_wait = 0;
157         
158         key_code = key_status = key_cmd = 0;
159         key_repeat_event = -1;
160         
161         gcw = 0x80;
162         vsync = disp = false;
163         cblink = 0;
164         
165         ief_key = ief_vsync = false;//true;
166         fdc_irq = fdc_drq = false;
167         drec_in = false;
168 }
169
170 void IO::initialize_key()
171 {
172         memset(keytable, 0, sizeof(keytable));
173         memset(keytable_shift, 0, sizeof(keytable_shift));
174         memset(keytable_ctrl, 0, sizeof(keytable_ctrl));
175         memset(keytable_kana, 0, sizeof(keytable_kana));
176         memset(keytable_kana_shift, 0, sizeof(keytable_kana_shift));
177         
178         for(int i = 0; i < 68; i++) {
179                 uint8 code = keytable_base[i][0];
180                 keytable[code] = keytable_base[i][1];
181                 keytable_shift[code] = keytable_base[i][2];
182                 keytable_ctrl[code] = keytable_base[i][3];
183                 keytable_kana[code] = keytable_base[i][4];
184                 keytable_kana_shift[code] = keytable_base[i][5];
185         }
186         key_repeat_start = 1000;
187         key_repeat_interval = 100;
188 }
189
190 void IO::write_data8(uint32 addr, uint32 data)
191 {
192         wbank[(addr >> 14) & 3][addr & 0x3fff] = data;
193 }
194
195 uint32 IO::read_data8(uint32 addr)
196 {
197         return rbank[(addr >> 14) & 3][addr & 0x3fff];
198 }
199
200 uint32 IO::fetch_op(uint32 addr, int *wait)
201 {
202         if(rom_switch_wait) {
203                 if(--rom_switch_wait == 0) {
204                         SET_BANK(0x0000, 0x3fff, wdmy, rom);
205                         rom_selected = true;
206                 }
207         } else if(ram_switch_wait) {
208                 if(--ram_switch_wait == 0) {
209                         SET_BANK(0x0000, 0x3fff, ram, ram);
210                         rom_selected = false;
211                 }
212         }
213         *wait = 0;
214         return read_data8(addr);
215 }
216
217 void IO::write_io8(uint32 addr, uint32 data)
218 {
219 #ifdef _IO_DEBUG_LOG
220         emu->out_debug_log(_T("%6x\tOUT8\t%04x,%02x\n"), d_cpu->get_pc(), addr, data);
221 #endif
222         uint8 laddr = addr & 0xff;
223         
224         if(laddr < 0x08) {
225                 addr = ((addr & 0xff00) >> 8) | (laddr << 8);
226                 cram[addr & 0x7ff] = data;
227         } else if(laddr < 0x10) {
228                 addr = ((addr & 0xff00) >> 8) | (laddr << 8);
229                 aram[addr & 0x7ff] = data;
230         } else if(laddr < 0x18) {
231                 addr = ((addr & 0xff00) >> 8) | (laddr << 8);
232                 pcg[addr & 0x7ff] = data;
233         } else if(laddr < 0x80) {
234                 switch(laddr) {
235                 case 0x18: // HD46505S-1 register number
236                 case 0x19: // HD46505S-1 register
237                         d_crtc->write_io8(addr, data);
238                         break;
239                 case 0x1a: // 8041 key encoder data
240                         if(key_cmd == 0) {
241                                 // is this okay???
242                                 if(data & 0x80) {
243                                         // clear keyboard irq
244                                 }
245                                 if(data & 0x10) {
246                                         // go to setting mode
247                                         key_cmd = -1;
248                                 }
249                                 ief_key = ((data & 1) != 0);
250                         } else if(key_cmd == 0xa0) {
251                                 // function key code
252                                 int index = funckey_index++;
253                                 if(index == 0) {
254                                         // key code
255                                         keytable[funckey_code] = keytable_kana[funckey_code] = data;
256                                 } else if(index == 1) {
257                                         // key  code with shift key
258                                         keytable_shift[funckey_code] = keytable_kana_shift[funckey_code] = data;
259                                 } else if(index == 2) {
260                                         // key code with ctrl key
261                                         keytable_ctrl[funckey_code] = data;
262                                 } else {
263                                         key_cmd = -1;
264                                 }
265                         }
266                         break;
267                 case 0x1b: // 8041 key encoder control
268                         if(key_cmd == 0) {
269                                 // bit7: ICF            1 = clear keyboard irq
270                                 // bit4: FEF            1 = go to setting mode, 0 = scan mode
271                                 // bit0: IEF            1 = enable keyboard irq
272                                 if(data & 0x80) {
273                                         // clear keyboard irq
274                                 }
275                                 if(data & 0x10) {
276                                         // go to setting mode
277                                         key_cmd = -1;
278                                 }
279                                 ief_key = ((data & 1) != 0);
280                         } else {
281                                 // bit6-7: command type
282                                 key_cmd = data & 0xe0;
283                                 switch(data & 0xc0) {
284                                 case 0xc0: // initialize key setting and exit setting mode
285                                 case 0xe0:
286                                         initialize_key();
287                                 case 0x00: // exit setting mode
288                                 case 0x20:
289                                         key_cmd = 0;
290                                         break;
291                                 case 0x40: // set key repeat interval time
292                                         // bit0-3: time
293                                         key_repeat_interval = 20 + 20 * (data & 0x0f);
294                                         break;
295                                 case 0x60: // set key repeat start time
296                                         key_repeat_start = 500 + 100 * (data & 0x0f);
297                                         break;
298                                 case 0x80: // read function key code
299                                 case 0xa0: // write function key code
300                                         // bit5: ~R/W
301                                         // bit0-3: key address flag
302                                         switch(data & 0x0f) {
303                                         case 1:  funckey_code = 0x70; break; // F1
304                                         case 2:  funckey_code = 0x71; break; // F2
305                                         case 3:  funckey_code = 0x72; break; // F3
306                                         case 4:  funckey_code = 0x73; break; // F4
307                                         case 5:  funckey_code = 0x74; break; // F5
308                                         case 6:  funckey_code = 0x7a; break; // H -> F11
309                                         default: funckey_code = 0x00; break;
310                                         }
311                                         funckey_index = 0;
312                                         break;
313                                 }
314                         }
315                         break;
316                 case 0x1c:
317                 case 0x1d:
318                         // bit4: OD             output data
319                         // bit0-2: PA           pin selection
320                         switch(data & 7) {
321                         case 0:
322                                 // RAM/~ROM     ram/rom switching will be done after next instruction
323                                 if(data & 0x10) {
324                                         ram_switch_wait = 2;
325                                 } else {
326                                         rom_switch_wait = 2;
327                                 }
328                                 break;
329                         case 1:
330                                 // ~V.SUP       1 = screen is black
331                                 vsup = ((data & 0x10) != 0);
332                                 break;
333                         case 2:
334                                 // ~525/625
335                                 break;
336                         case 3:
337                                 // RGB/~COMP
338                                 break;
339                         case 4:
340                                 // MOTOR ON/OFF
341                                 d_drec->write_signal(SIG_DATAREC_REMOTE, data, 0x10);
342                                 break;
343                         case 5:
344                                 // SOUND OUT
345                                 d_pcm->write_signal(SIG_PCM1BIT_SIGNAL, data, 0x10);
346                                 break;
347                         case 6:
348                                 // ~PRINTER STRB
349                                 break;
350                         case 7:
351                                 // CASSETE OUT
352                                 d_drec->write_signal(SIG_DATAREC_MIC, data, 0x10);
353                                 break;
354                         }
355                         break;
356                 case 0x20:
357                         // bit7: CM             0 = 80x25, 1 = 40x25
358                         // bit6: P              0 = 40x25 page 0 (even addr), 1 = page 1 (odd addr)
359                         // bit5: T              0 = 640x200 type 1, 1 = 640x200 type 2
360                         // bit3: GM             0 = 320x200, 1 = 640x200
361                         gcw = data;
362                         break;
363                 case 0x21:
364                         // bit0: IEF            1 = enable 60hz (vsync?) irq
365                         ief_vsync = ((data & 1) != 0);
366                         break;
367                 case 0x23:
368                         // bit0-3: border color
369 //                      border = data & 0x0f;
370                         break;
371                 case 0x30: // MB8877 command register
372                 case 0x31: // MB8877 track register
373                 case 0x32: // MB8877 sector register
374                 case 0x33: // MB8877 data register
375                         d_fdc->write_io8(addr, data);
376                         break;
377                 case 0x34:
378                         // bit0: drive num      0 = drive A, 1 = drive B
379                         d_fdc->write_signal(SIG_MB8877_DRIVEREG, data, 1);
380                         break;
381                 case 0x51:
382                         // bit4: OD             output data
383                         // bit0-2: PA           pin selection
384                         switch(data & 7) {
385                         case 6: // character screen
386                                 // bit4: 0 = color generator, 1 = color palette board
387                                 use_palette_text = ((data & 0x10) != 0);
388                                 break;
389                         case 7: // graphic screen
390                                 // bit4: 0 = color generator, 1 = color palette board
391                                 use_palette_graph = ((data & 0x10) != 0);
392                                 break;
393                         }
394                         break;
395                 case 0x52:
396                         // addr bit12-13: AD    0 = red, 1 = green, 2 = blue
397                         // addr bit8-11: BD     color code
398                         // bit4-7: CD           0 = dark, 7 = blight
399                         {
400                                 int n = (addr >> 8) & 15;
401                                 switch((addr >> 12) & 3) {
402                                 case 0: pal[n].r = data >> 4; break;
403                                 case 1: pal[n].g = data >> 4; break;
404                                 case 2: pal[n].b = data >> 4; break;
405                                 }
406                                 palette_pc[n + 16] = RGB_COLOR(pal[n].r * 255 / 15, pal[n].g * 255 / 15, pal[n].b * 255 / 15);
407                         }
408                         break;
409                 case 0x53: // SN76489AN
410                         d_psg->write_io8(addr, data);
411                         break;
412                 case 0x7e: // KANJI ROM jis code (hi)
413                         kanji_hi = data & 0x7f;
414                         break;
415                 case 0x7f: // KANJI ROM jis code (lo)
416                         kanji_lo = data & 0x7f;
417                         break;
418                 }
419         } else {
420                 addr = ((addr & 0xff00) >> 8) | (laddr << 8);
421                 gram[addr & 0x7fff] = data;
422         }
423 }
424
425 uint32 IO::read_io8(uint32 addr)
426 #ifdef _IO_DEBUG_LOG
427 {
428         uint32 val = read_io8_debug(addr);
429         emu->out_debug_log(_T("%06x\tIN8\t%04x = %02x\n"), d_cpu->get_pc(), addr, val);
430         return val;
431 }
432
433 uint32 IO::read_io8_debug(uint32 addr)
434 #endif
435 {
436         uint8 laddr = addr & 0xff;
437         
438         if(laddr < 0x08) {
439                 addr = ((addr & 0xff00) >> 8) | (laddr << 8);
440                 return cram[addr & 0x7ff];
441         } else if(laddr < 0x10) {
442                 addr = ((addr & 0xff00) >> 8) | (laddr << 8);
443                 return aram[addr & 0x7ff];
444         } else if(laddr < 0x18) {
445                 addr = ((addr & 0xff00) >> 8) | (laddr << 8);
446                 return pcg[addr & 0x7ff];
447         } else if(laddr < 0x80) {
448                 switch(laddr) {
449                 case 0x18: // HD46505S-1 register number
450                 case 0x19: // HD46505S-1 register
451                         return d_crtc->read_io8(addr);
452                 case 0x1a: // 8041 key encoder data
453                         if(key_cmd == 0) {
454                                 // key code
455                                 key_status &= ~1;
456                                 return key_code;
457                         } else if(key_cmd == 0x80) {
458                                 // function key code
459                                 int index = funckey_index++;
460                                 if(index == 0) {
461                                         // key code
462                                         return keytable[funckey_code];
463                                 } else if(index == 1) {
464                                         // key  code with shift key
465                                         return keytable_shift[funckey_code];
466                                 } else if(index == 2) {
467                                         // key  code with ctrl key
468                                         return keytable_ctrl[funckey_code];
469                                 } else {
470                                         key_cmd = -1;
471                                 }
472                         }
473                         break;
474                 case 0x1b: // 8041 key encoder status
475                         if(key_cmd == 0) {
476                                 // bit7: CF             1 = ctrl key is pressed
477                                 // bit6: SF             1 = shift key is pressed
478                                 // bit2: ASF            1 = key is pressed pressed now
479                                 // bit0: BSF            1 = key was pressed (will be cleared when key code is read)
480                                 return key_status;
481                         } else {
482                                 // bit2: ~BUSY          0 = command processing, 1 = command done
483                                 // bit1: ~CS            0 = command accepted, 1 = command not accepted
484                                 // bit0: DR             0 = data not ready, 1 = data ready
485                                 if(key_cmd == 0x80) {
486                                         return 5;
487                                 } else if(key_cmd != -1) {
488                                         return 4;
489                                 }
490                                 return 4;//6;
491                         }
492                         break;
493                 case 0x1c:
494                         // bit7: RES            0 = cold start (power-on), 1 = warm start (reset)
495                         // bit4: ~CP            0 = color palette board is attached
496                         // bit2: ID             0 = SMC-777, 1 = SMC-70
497 #if defined(_SMC70)
498                         return (warm_start ? 0x80 : 0) | 4;
499 #else
500                         return (warm_start ? 0x80 : 0);
501 #endif
502                 case 0x1d:
503                         // bit7: TC IN          input signal from cassette data recorder
504                         // bit4: PR BUSY        printer busy
505                         // bit3: PR ACK         printer ack
506                         // bit2: ID             0 = SMC-777, 1 = SMC-70
507 #if defined(_SMC70)
508                         return (drec_in ? 0x80 : 0) | 4;
509 #else
510                         return (drec_in ? 0x80 : 0);
511 #endif
512                 case 0x20:
513                         // is this okay???
514                         return gcw;
515                 case 0x21:
516                         // is this okay???
517                         return ief_vsync ? 1 : 0;
518                 case 0x30: // MB8877 status register
519                 case 0x31: // MB8877 track register
520                 case 0x32: // MB8877 sector register
521                 case 0x33: // MB8877 data register
522                         return d_fdc->read_io8(addr);
523                 case 0x34:
524                         // bit7: IRQ
525                         // bit6: ~DRQ
526                         // bit0-5: 0
527                         return (fdc_irq ? 0x80: 0) | (fdc_drq ? 0 : 0x40);
528                 case 0x51:
529                         // addr bit8:           0 = joystick #2, 1 = joystick #1
530                         // bit7: ~BL            0 = h/v blanking, 1 = not blanking
531                         // bit6: ~CS            0 = joystick #2 is enabled
532                         // bit4: ~T             0 = joystick trigger on
533                         // bit3: ~R             0 = joystick right on
534                         // bit2: ~L             0 = joystick left on
535                         // bit1: ~B             0 = joystick back on
536                         // bit0: ~F             0 = joystick forward on
537                         {
538                                 uint32 stat = joy_stat[(addr & 0x100) ? 0 : 1];
539                                 return (~stat & 0x0f) | ((stat & 0x30) ? 0 : 0x10) | (disp ? 0x80 : 0);
540                         }
541                 case 0x7e: // KANJI ROM data
542                         // addr bit8-12: l/r and raster
543                         if(kanji_hi >= 0x21 && kanji_hi <= 0x4f && kanji_lo >= 0x20 && kanji_lo <= 0x7f) {
544                                 int ofs = (kanji_hi - 0x21) * 96 + (kanji_lo - 0x20);
545                                 return kanji[ofs * 32 + ((addr >> 8) & 0x1f)];
546                         }
547                         break;
548                 }
549                 return 0;//0xff;
550         } else {
551                 addr = ((addr & 0xff00) >> 8) | (laddr << 8);
552                 return gram[addr & 0x7fff];
553         }
554 }
555
556
557 void IO::write_signal(int id, uint32 data, uint32 mask)
558 {
559         if(id == SIG_IO_FDC_IRQ) {
560                 fdc_irq = ((data & mask) != 0);
561         } else if(id == SIG_IO_FDC_DRQ) {
562                 fdc_drq = ((data & mask) != 0);
563         } else if(id == SIG_IO_CRTC_DISP) {
564                 disp = ((data & mask) != 0);
565         } else if(id == SIG_IO_CRTC_VSYNC) {
566                 vsync = ((data & mask) != 0);
567                 if((data & mask) && ief_vsync) {
568                         d_cpu->write_signal(SIG_CPU_IRQ, 1, 1);
569                 }
570         } else if(id == SIG_IO_DATAREC_IN) {
571                 drec_in = ((data & mask) != 0);
572         }
573 }
574
575 void IO::key_down_up(int code, bool down)
576 {
577         if(code == 0x14 && down) {
578                 caps = !caps;
579                 return;
580         } else if(code == 0x15 && down) {
581                 kana = !kana;
582                 return;
583         }
584         bool shift = (key_stat[0x10] != 0);
585         bool ctrl = (key_stat[0x11] != 0);
586         bool kana_tmp = kana;
587         
588         if(code >= 0x60 && code <= 0x69) { // numpad 0-9
589                 code = code - 0x60 + 0x30;
590                 shift = ctrl = kana_tmp = false;
591         } else if(code == 0x6a) { // numpad *
592                 code = 0x38;
593                 shift = true; ctrl = kana_tmp = false;
594         } else if(code == 0x6b) { // numpad +
595                 code = 0xde;
596                 shift = true; ctrl = kana_tmp = false;
597         } else if(code == 0x6c) { // numpad ,
598                 code = 0xbc;
599                 shift = ctrl = kana_tmp = false;
600         } else if(code == 0x6d) { // numpad -
601                 code = 0xbd;
602                 shift = ctrl = kana_tmp = false;
603         } else if(code == 0x6e) { // numpad .
604                 code = 0xbe;
605                 shift = ctrl = kana_tmp = false;
606         } else if(code == 0x6f) { // numpad /
607                 code = 0xbf;
608                 shift = ctrl = kana_tmp = false;
609         } else if(code >= 0x75 && code <= 0x79) { // F6-F10 -> Shift + F1-F5
610                 code = code - 0x75 + 0x70;
611                 shift = true;
612         }
613         if(ctrl) {
614                 code = keytable_ctrl[code];
615         } else if(kana_tmp && shift) {
616                 code = keytable_kana_shift[code];
617         } else if(kana_tmp) {
618                 code = keytable_kana[code];
619         } else if(shift) {
620                 code = keytable_shift[code];
621         } else {
622                 code = keytable[code];
623         }
624         if(code != 0) {
625                 if(caps && ((code >= 'a' && code <= 'z') || (code >= 'A' && code <= 'Z'))) {
626                         code ^= 0x20;
627                 }
628                 if(down && key_code != code) {
629                         if(ief_key) {
630                                 d_cpu->write_signal(SIG_CPU_IRQ, 1, 1);
631                         }
632                         if(key_repeat_event != -1) {
633                                 cancel_event(this, key_repeat_event);
634                         }
635                         key_code = code;
636                         key_status = ctrl ? 0x85 : shift ? 0x45 : 5;
637                         register_event(this, EVENT_KEY_REPEAT, key_repeat_start * 1000, false, &key_repeat_event);
638                 } else if(!down && key_code == code) {
639                         if(key_repeat_event != -1) {
640                                 cancel_event(this, key_repeat_event);
641                                 key_repeat_event = -1;
642                         }
643                         key_code = 0;
644                         key_status &= ~4;
645                 }
646         }
647 }
648
649 void IO::event_callback(int event_id, int err)
650 {
651         if(event_id == EVENT_KEY_REPEAT) {
652                 if(ief_key) {
653                         d_cpu->write_signal(SIG_CPU_IRQ, 1, 1);
654                 }
655                 key_status |= 5;
656                 register_event(this, EVENT_KEY_REPEAT, key_repeat_interval * 1000, false, &key_repeat_event);
657         }
658 }
659
660 void IO::event_frame()
661 {
662         cblink = (cblink + 1) & 0x1f;
663 }
664
665 void IO::draw_screen()
666 {
667         emu->screen_skip_line(true);
668         
669         if(vsup) {
670                 for(int y = 0; y < 400; y++) {
671                         scrntype* dest = emu->screen_buffer(y);
672                         memset(dest, 0, 640 * sizeof(scrntype));
673                 }
674                 return;
675         }
676         
677         // render text/graph screens
678         memset(text, 0, sizeof(text));
679         memset(graph, 0, sizeof(graph));
680         
681         if(gcw & 0x80) {
682                 draw_text_40x25();
683         } else {
684                 draw_text_80x25();
685         }
686         if(gcw & 0x08) {
687                 draw_graph_640x200();
688         } else {
689                 draw_graph_320x200();
690         }
691         
692         // copy to screen buffer
693         scrntype *palette_pc_text = &palette_pc[use_palette_text ? 16 : 0];
694         scrntype *palette_pc_graph = &palette_pc[use_palette_graph ? 16 : 0];
695         
696         for(int y = 0; y < 200; y++) {
697                 scrntype* dest0 = emu->screen_buffer(y * 2);
698                 scrntype* dest1 = emu->screen_buffer(y * 2 + 1);
699                 uint8* src_t = text[y];
700                 uint8* src_g = graph[y];
701                 
702                 for(int x = 0; x < 640; x++) {
703                         uint8 t = src_t[x];
704                         dest0[x] = t ? palette_pc_text[t & 15] : palette_pc_graph[src_g[x]];
705                 }
706                 if(config.scan_line) {
707                         memset(dest1, 0, 640 * sizeof(scrntype));
708                 } else {
709                         memcpy(dest1, dest0, 640 * sizeof(scrntype));
710                 }
711         }
712 }
713
714 void IO::draw_text_80x25()
715 {
716         int hz = crtc_regs[1];
717         int vt = crtc_regs[6] & 0x7f;
718         int ht = (crtc_regs[9] & 0x1f) + 1;
719         uint8 bp = crtc_regs[10] & 0x60;
720         uint16 src = (crtc_regs[12] << 8) | crtc_regs[13];
721         uint16 cursor = (crtc_regs[14] << 8) | crtc_regs[15];
722         
723         src &= 0x7ff;
724         cursor &= 0x7ff;
725         
726         for(int y = 0; y < vt && y < 25; y++) {
727                 for(int x = 0; x < hz && x < 80; x++) {
728                         uint8 code = cram[src];
729                         uint8 attr = aram[src];
730                         
731                         if(attr & 0x80) {
732                                 attr = 7;
733                         }
734                         bool blink = ((attr & 0x40) && (cblink & 0x20));
735                         bool reverse = (((attr & 0x20) != 0) != blink);
736                         
737                         uint8 front = (attr & 7) | 16, back;
738                         switch((attr >> 3) & 3) {
739                         case 0: back =  0; break; // transparent
740                         case 1: back =  7; break; // white
741                         case 2: back = 16; break; // black
742                         case 3: back = ~front; break;
743                         }
744                         
745                         // draw pattern
746                         for(int l = 0; l < ht; l++) {
747                                 uint8 pat = (l < 8) ? pcg[(code << 3) + l] : 0;
748                                 if(reverse) pat = ~pat;
749                                 int yy = y * ht + l;
750                                 if(yy >= 200) {
751                                         break;
752                                 }
753                                 uint8* d = &text[yy][x << 3];
754                                 d[0] = (pat & 0x80) ? front : back;
755                                 d[1] = (pat & 0x40) ? front : back;
756                                 d[2] = (pat & 0x20) ? front : back;
757                                 d[3] = (pat & 0x10) ? front : back;
758                                 d[4] = (pat & 0x08) ? front : back;
759                                 d[5] = (pat & 0x04) ? front : back;
760                                 d[6] = (pat & 0x02) ? front : back;
761                                 d[7] = (pat & 0x01) ? front : back;
762                         
763                         }
764                         
765                         // draw cursor
766                         if(src == cursor) {
767                                 int s = crtc_regs[10] & 0x1f;
768                                 int e = crtc_regs[11] & 0x1f;
769                                 if(bp == 0 || (bp == 0x40 && (cblink & 8)) || (bp == 0x60 && (cblink & 0x10))) {
770                                         for(int l = s; l <= e && l < ht; l++) {
771                                                 int yy = y * ht + l;
772                                                 if(yy < 200) {
773                                                         memset(&text[yy][x << 3], 7, 8);
774                                                 }
775                                         }
776                                 }
777                         }
778                         src = (src + 1) & 0x7ff;
779                 }
780         }
781 }
782
783 void IO::draw_text_40x25()
784 {
785         int hz = crtc_regs[1];
786         int vt = crtc_regs[6] & 0x7f;
787         int ht = (crtc_regs[9] & 0x1f) + 1;
788         uint8 bp = crtc_regs[10] & 0x60;
789         uint16 src = (crtc_regs[12] << 8) | crtc_regs[13];
790         uint16 cursor = (crtc_regs[14] << 8) | crtc_regs[15];
791         
792         int page = (gcw >> 6) & 1;
793         src = (src & 0x7fe) | page;
794         cursor = (cursor & 0x7fe) | page;
795         
796         for(int y = 0; y < vt && y < 25; y++) {
797                 for(int x = 0; x < hz && x < 80; x += 2) {
798                         uint8 code = cram[src];
799                         uint8 attr = aram[src];
800                         
801                         if(attr & 0x80) {
802                                 attr = 7;
803                         }
804                         bool blink = ((attr & 0x40) && (cblink & 0x20));
805                         bool reverse = (((attr & 0x20) != 0) != blink);
806                         
807                         uint8 front = (attr & 7) | 16, back;
808                         switch((attr >> 3) & 3) {
809                         case 0: back =  0; break; // transparent
810                         case 1: back =  7; break; // white
811                         case 2: back = 16; break; // black
812                         case 3: back = ~front; break;
813                         }
814                         
815                         // draw pattern
816                         for(int l = 0; l < ht; l++) {
817                                 uint8 pat = (l < 8) ? pcg[(code << 3) + l] : 0;
818                                 if(reverse) pat = ~pat;
819                                 int yy = y * ht + l;
820                                 if(yy >= 200) {
821                                         break;
822                                 }
823                                 uint8* d = &text[yy][x << 3];
824                                 d[ 0] = d[ 1] = (pat & 0x80) ? front : back;
825                                 d[ 2] = d[ 3] = (pat & 0x40) ? front : back;
826                                 d[ 4] = d[ 5] = (pat & 0x20) ? front : back;
827                                 d[ 6] = d[ 7] = (pat & 0x10) ? front : back;
828                                 d[ 8] = d[ 9] = (pat & 0x08) ? front : back;
829                                 d[10] = d[11] = (pat & 0x04) ? front : back;
830                                 d[12] = d[13] = (pat & 0x02) ? front : back;
831                                 d[14] = d[15] = (pat & 0x01) ? front : back;
832                         
833                         }
834                         
835                         // draw cursor
836                         if(src == cursor) {
837                                 int s = crtc_regs[10] & 0x1f;
838                                 int e = crtc_regs[11] & 0x1f;
839                                 if(bp == 0 || (bp == 0x40 && (cblink & 8)) || (bp == 0x60 && (cblink & 0x10))) {
840                                         for(int l = s; l <= e && l < ht; l++) {
841                                                 int yy = y * ht + l;
842                                                 if(yy < 200) {
843                                                         memset(&text[yy][x << 3], 7, 16);
844                                                 }
845                                         }
846                                 }
847                         }
848                         src = (src + 2) & 0x7ff;
849                 }
850         }
851 }
852
853 void IO::draw_graph_640x200()
854 {
855         static const uint8 color_table[2][4] = {{0, 4, 2, 1}, {0, 4, 2, 7}};
856         static const uint8* color_ptr = color_table[(gcw >> 5) & 1];
857         
858         int hz = crtc_regs[1];
859         int vt = crtc_regs[6] & 0x7f;
860         int ht = (crtc_regs[9] & 0x1f) + 1;
861         uint16 src = (crtc_regs[12] << 8) | crtc_regs[13];
862         
863         for(int y = 0; y < vt && y < 25; y++) {
864                 for(int x = 0; x < hz && x < 80; x++) {
865                         for(int l = 0; l < ht; l++) {
866                                 uint8 pat0 = gram[(src + 0x1000 * l    ) & 0x7fff];
867                                 uint8 pat1 = gram[(src + 0x1000 * l + 1) & 0x7fff];
868                                 int yy = y * ht + l;
869                                 if(yy >= 200) {
870                                         break;
871                                 }
872                                 uint8* d = &graph[yy][x << 3];
873                                 d[0] = color_ptr[(pat0 >> 6)    ];
874                                 d[1] = color_ptr[(pat0 >> 4) & 3];
875                                 d[2] = color_ptr[(pat0 >> 2) & 3];
876                                 d[3] = color_ptr[(pat0     ) & 3];
877                                 d[4] = color_ptr[(pat1 >> 6)    ];
878                                 d[5] = color_ptr[(pat1 >> 4) & 3];
879                                 d[6] = color_ptr[(pat1 >> 2) & 3];
880                                 d[7] = color_ptr[(pat1     ) & 3];
881                         }
882                         src += 2;
883                 }
884         }
885 }
886
887 void IO::draw_graph_320x200()
888 {
889         int hz = crtc_regs[1];
890         int vt = crtc_regs[6] & 0x7f;
891         int ht = (crtc_regs[9] & 0x1f) + 1;
892         uint16 src = (crtc_regs[12] << 8) | crtc_regs[13];
893         
894         for(int y = 0; y < vt && y < 25; y++) {
895                 for(int x = 0; x < hz && x < 80; x++) {
896                         for(int l = 0; l < ht; l++) {
897                                 uint8 pat0 = gram[(src + 0x1000 * l    ) & 0x7fff];
898                                 uint8 pat1 = gram[(src + 0x1000 * l + 1) & 0x7fff];
899                                 int yy = y * ht + l;
900                                 if(yy >= 200) {
901                                         break;
902                                 }
903                                 uint8* d = &graph[yy][x << 3];
904                                 d[0] = d[1] = pat0 >> 4;
905                                 d[2] = d[3] = pat0 & 15;
906                                 d[4] = d[5] = pat1 >> 4;
907                                 d[6] = d[7] = pat1 & 15;
908                         }
909                         src += 2;
910                 }
911         }
912 }
913
914 #define STATE_VERSION   1
915
916 void IO::save_state(FILEIO* state_fio)
917 {
918         state_fio->FputUint32(STATE_VERSION);
919         state_fio->FputInt32(this_device_id);
920         
921         state_fio->Fwrite(ram, sizeof(ram), 1);
922         state_fio->Fwrite(cram, sizeof(cram), 1);
923         state_fio->Fwrite(aram, sizeof(aram), 1);
924         state_fio->Fwrite(pcg, sizeof(pcg), 1);
925         state_fio->Fwrite(gram, sizeof(gram), 1);
926         state_fio->FputBool(rom_selected);
927         state_fio->FputInt32(rom_switch_wait);
928         state_fio->FputInt32(ram_switch_wait);
929         state_fio->Fwrite(keytable, sizeof(keytable), 1);
930         state_fio->Fwrite(keytable_shift, sizeof(keytable_shift), 1);
931         state_fio->Fwrite(keytable_ctrl, sizeof(keytable_ctrl), 1);
932         state_fio->Fwrite(keytable_kana, sizeof(keytable_kana), 1);
933         state_fio->Fwrite(keytable_kana_shift, sizeof(keytable_kana_shift), 1);
934         state_fio->FputUint8(key_code);
935         state_fio->FputUint8(key_status);
936         state_fio->FputUint8(key_cmd);
937         state_fio->FputInt32(key_repeat_start);
938         state_fio->FputInt32(key_repeat_interval);
939         state_fio->FputInt32(key_repeat_event);
940         state_fio->FputUint8(funckey_code);
941         state_fio->FputInt32(funckey_index);
942         state_fio->FputBool(caps);
943         state_fio->FputBool(kana);
944         state_fio->FputUint8(gcw);
945         state_fio->FputBool(vsup);
946         state_fio->FputBool(vsync);
947         state_fio->FputBool(disp);
948         state_fio->FputInt32(cblink);
949         state_fio->FputBool(use_palette_text);
950         state_fio->FputBool(use_palette_graph);
951         state_fio->Fwrite(pal, sizeof(pal), 1);
952         state_fio->Fwrite(palette_pc, sizeof(palette_pc), 1);
953         state_fio->FputInt32(kanji_hi);
954         state_fio->FputInt32(kanji_lo);
955         state_fio->FputBool(ief_key);
956         state_fio->FputBool(ief_vsync);
957         state_fio->FputBool(fdc_irq);
958         state_fio->FputBool(fdc_drq);
959         state_fio->FputBool(drec_in);
960 }
961
962 bool IO::load_state(FILEIO* state_fio)
963 {
964         if(state_fio->FgetUint32() != STATE_VERSION) {
965                 return false;
966         }
967         if(state_fio->FgetInt32() != this_device_id) {
968                 return false;
969         }
970         state_fio->Fread(ram, sizeof(ram), 1);
971         state_fio->Fread(cram, sizeof(cram), 1);
972         state_fio->Fread(aram, sizeof(aram), 1);
973         state_fio->Fread(pcg, sizeof(pcg), 1);
974         state_fio->Fread(gram, sizeof(gram), 1);
975         rom_selected = state_fio->FgetBool();
976         rom_switch_wait = state_fio->FgetInt32();
977         ram_switch_wait = state_fio->FgetInt32();
978         state_fio->Fread(keytable, sizeof(keytable), 1);
979         state_fio->Fread(keytable_shift, sizeof(keytable_shift), 1);
980         state_fio->Fread(keytable_ctrl, sizeof(keytable_ctrl), 1);
981         state_fio->Fread(keytable_kana, sizeof(keytable_kana), 1);
982         state_fio->Fread(keytable_kana_shift, sizeof(keytable_kana_shift), 1);
983         key_code = state_fio->FgetUint8();
984         key_status = state_fio->FgetUint8();
985         key_cmd = state_fio->FgetUint8();
986         key_repeat_start = state_fio->FgetInt32();
987         key_repeat_interval = state_fio->FgetInt32();
988         key_repeat_event = state_fio->FgetInt32();
989         funckey_code = state_fio->FgetUint8();
990         funckey_index = state_fio->FgetInt32();
991         caps = state_fio->FgetBool();
992         kana = state_fio->FgetBool();
993         gcw = state_fio->FgetUint8();
994         vsup = state_fio->FgetBool();
995         vsync = state_fio->FgetBool();
996         disp = state_fio->FgetBool();
997         cblink = state_fio->FgetInt32();
998         use_palette_text = state_fio->FgetBool();
999         use_palette_graph = state_fio->FgetBool();
1000         state_fio->Fread(pal, sizeof(pal), 1);
1001         state_fio->Fread(palette_pc, sizeof(palette_pc), 1);
1002         kanji_hi = state_fio->FgetInt32();
1003         kanji_lo = state_fio->FgetInt32();
1004         ief_key = state_fio->FgetBool();
1005         ief_vsync = state_fio->FgetBool();
1006         fdc_irq = state_fio->FgetBool();
1007         fdc_drq = state_fio->FgetBool();
1008         drec_in = state_fio->FgetBool();
1009         
1010         // post process
1011         if(rom_selected) {
1012                 SET_BANK(0x0000, 0x3fff, wdmy, rom);
1013         } else {
1014                 SET_BANK(0x0000, 0x3fff, ram, ram);
1015         }
1016         return true;
1017 }
1018