2 SONY SMC-777 Emulator 'eSMC-777'
4 Author : Takeda.Toshiya
11 #include "../datarec.h"
12 #include "../mb8877.h"
13 #include "../pcm1bit.h"
15 #define EVENT_KEY_REPEAT 0
17 #define SET_BANK(s, e, w, r) { \
18 int sb = (s) >> 14, eb = (e) >> 14; \
19 for(int i = sb; i <= eb; i++) { \
23 wbank[i] = (w) + 0x4000 * (i - sb); \
28 rbank[i] = (r) + 0x4000 * (i - sb); \
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
104 void IO::initialize()
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));
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);
122 if(fio->Fopen(emu->bios_path(_T("KANJIROM.DAT")), FILEIO_READ_BINARY)) {
123 fio->Fread(kanji, sizeof(kanji), 1);
131 key_stat = emu->key_buffer();
132 joy_stat = emu->joy_buffer();
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},
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}
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]);
144 use_palette_text = use_palette_graph = false;
145 memset(pal, 0, sizeof(pal));
148 register_frame_event(this);
153 SET_BANK(0x0000, 0x3fff, wdmy, rom);
154 SET_BANK(0x4000, 0xffff, ram + 0x4000, ram + 0x4000);
156 rom_switch_wait = ram_switch_wait = 0;
158 key_code = key_status = key_cmd = 0;
159 key_repeat_event = -1;
162 vsync = disp = false;
165 ief_key = ief_vsync = false;//true;
166 fdc_irq = fdc_drq = false;
170 void IO::initialize_key()
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));
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];
186 key_repeat_start = 1000;
187 key_repeat_interval = 100;
190 void IO::write_data8(uint32 addr, uint32 data)
192 wbank[(addr >> 14) & 3][addr & 0x3fff] = data;
195 uint32 IO::read_data8(uint32 addr)
197 return rbank[(addr >> 14) & 3][addr & 0x3fff];
200 uint32 IO::fetch_op(uint32 addr, int *wait)
202 if(rom_switch_wait) {
203 if(--rom_switch_wait == 0) {
204 SET_BANK(0x0000, 0x3fff, wdmy, rom);
207 } else if(ram_switch_wait) {
208 if(--ram_switch_wait == 0) {
209 SET_BANK(0x0000, 0x3fff, ram, ram);
210 rom_selected = false;
214 return read_data8(addr);
217 void IO::write_io8(uint32 addr, uint32 data)
220 emu->out_debug_log(_T("%6x\tOUT8\t%04x,%02x\n"), d_cpu->get_pc(), addr, data);
222 uint8 laddr = addr & 0xff;
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) {
235 case 0x18: // HD46505S-1 register number
236 case 0x19: // HD46505S-1 register
237 d_crtc->write_io8(addr, data);
239 case 0x1a: // 8041 key encoder data
243 // clear keyboard irq
246 // go to setting mode
249 ief_key = ((data & 1) != 0);
250 } else if(key_cmd == 0xa0) {
252 int index = funckey_index++;
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;
267 case 0x1b: // 8041 key encoder control
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
273 // clear keyboard irq
276 // go to setting mode
279 ief_key = ((data & 1) != 0);
281 // bit6-7: command type
282 key_cmd = data & 0xe0;
283 switch(data & 0xc0) {
284 case 0xc0: // initialize key setting and exit setting mode
287 case 0x00: // exit setting mode
291 case 0x40: // set key repeat interval time
293 key_repeat_interval = 20 + 20 * (data & 0x0f);
295 case 0x60: // set key repeat start time
296 key_repeat_start = 500 + 100 * (data & 0x0f);
298 case 0x80: // read function key code
299 case 0xa0: // write function key code
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;
318 // bit4: OD output data
319 // bit0-2: PA pin selection
322 // RAM/~ROM ram/rom switching will be done after next instruction
330 // ~V.SUP 1 = screen is black
331 vsup = ((data & 0x10) != 0);
341 d_drec->write_signal(SIG_DATAREC_REMOTE, data, 0x10);
345 d_pcm->write_signal(SIG_PCM1BIT_SIGNAL, data, 0x10);
352 d_drec->write_signal(SIG_DATAREC_MIC, data, 0x10);
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
364 // bit0: IEF 1 = enable 60hz (vsync?) irq
365 ief_vsync = ((data & 1) != 0);
368 // bit0-3: border color
369 // border = data & 0x0f;
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);
378 // bit0: drive num 0 = drive A, 1 = drive B
379 d_fdc->write_signal(SIG_MB8877_DRIVEREG, data, 1);
382 // bit4: OD output data
383 // bit0-2: PA pin selection
385 case 6: // character screen
386 // bit4: 0 = color generator, 1 = color palette board
387 use_palette_text = ((data & 0x10) != 0);
389 case 7: // graphic screen
390 // bit4: 0 = color generator, 1 = color palette board
391 use_palette_graph = ((data & 0x10) != 0);
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
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;
406 palette_pc[n + 16] = RGB_COLOR(pal[n].r * 255 / 15, pal[n].g * 255 / 15, pal[n].b * 255 / 15);
409 case 0x53: // SN76489AN
410 d_psg->write_io8(addr, data);
412 case 0x7e: // KANJI ROM jis code (hi)
413 kanji_hi = data & 0x7f;
415 case 0x7f: // KANJI ROM jis code (lo)
416 kanji_lo = data & 0x7f;
420 addr = ((addr & 0xff00) >> 8) | (laddr << 8);
421 gram[addr & 0x7fff] = data;
425 uint32 IO::read_io8(uint32 addr)
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);
433 uint32 IO::read_io8_debug(uint32 addr)
436 uint8 laddr = addr & 0xff;
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) {
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
457 } else if(key_cmd == 0x80) {
459 int index = funckey_index++;
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];
474 case 0x1b: // 8041 key encoder status
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)
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) {
487 } else if(key_cmd != -1) {
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
498 return (warm_start ? 0x80 : 0) | 4;
500 return (warm_start ? 0x80 : 0);
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
508 return (drec_in ? 0x80 : 0) | 4;
510 return (drec_in ? 0x80 : 0);
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);
527 return (fdc_irq ? 0x80: 0) | (fdc_drq ? 0 : 0x40);
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
538 uint32 stat = joy_stat[(addr & 0x100) ? 0 : 1];
539 return (~stat & 0x0f) | ((stat & 0x30) ? 0 : 0x10) | (disp ? 0x80 : 0);
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)];
551 addr = ((addr & 0xff00) >> 8) | (laddr << 8);
552 return gram[addr & 0x7fff];
557 void IO::write_signal(int id, uint32 data, uint32 mask)
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);
570 } else if(id == SIG_IO_DATAREC_IN) {
571 drec_in = ((data & mask) != 0);
575 void IO::key_down_up(int code, bool down)
577 if(code == 0x14 && down) {
580 } else if(code == 0x15 && down) {
584 bool shift = (key_stat[0x10] != 0);
585 bool ctrl = (key_stat[0x11] != 0);
586 bool kana_tmp = kana;
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 *
593 shift = true; ctrl = kana_tmp = false;
594 } else if(code == 0x6b) { // numpad +
596 shift = true; ctrl = kana_tmp = false;
597 } else if(code == 0x6c) { // numpad ,
599 shift = ctrl = kana_tmp = false;
600 } else if(code == 0x6d) { // numpad -
602 shift = ctrl = kana_tmp = false;
603 } else if(code == 0x6e) { // numpad .
605 shift = ctrl = kana_tmp = false;
606 } else if(code == 0x6f) { // numpad /
608 shift = ctrl = kana_tmp = false;
609 } else if(code >= 0x75 && code <= 0x79) { // F6-F10 -> Shift + F1-F5
610 code = code - 0x75 + 0x70;
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];
620 code = keytable_shift[code];
622 code = keytable[code];
625 if(caps && ((code >= 'a' && code <= 'z') || (code >= 'A' && code <= 'Z'))) {
628 if(down && key_code != code) {
630 d_cpu->write_signal(SIG_CPU_IRQ, 1, 1);
632 if(key_repeat_event != -1) {
633 cancel_event(this, key_repeat_event);
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;
649 void IO::event_callback(int event_id, int err)
651 if(event_id == EVENT_KEY_REPEAT) {
653 d_cpu->write_signal(SIG_CPU_IRQ, 1, 1);
656 register_event(this, EVENT_KEY_REPEAT, key_repeat_interval * 1000, false, &key_repeat_event);
660 void IO::event_frame()
662 cblink = (cblink + 1) & 0x1f;
665 void IO::draw_screen()
667 emu->screen_skip_line(true);
670 for(int y = 0; y < 400; y++) {
671 scrntype* dest = emu->screen_buffer(y);
672 memset(dest, 0, 640 * sizeof(scrntype));
677 // render text/graph screens
678 memset(text, 0, sizeof(text));
679 memset(graph, 0, sizeof(graph));
687 draw_graph_640x200();
689 draw_graph_320x200();
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];
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];
702 for(int x = 0; x < 640; x++) {
704 dest0[x] = t ? palette_pc_text[t & 15] : palette_pc_graph[src_g[x]];
706 if(config.scan_line) {
707 memset(dest1, 0, 640 * sizeof(scrntype));
709 memcpy(dest1, dest0, 640 * sizeof(scrntype));
714 void IO::draw_text_80x25()
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];
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];
734 bool blink = ((attr & 0x40) && (cblink & 0x20));
735 bool reverse = (((attr & 0x20) != 0) != blink);
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;
746 for(int l = 0; l < ht; l++) {
747 uint8 pat = (l < 8) ? pcg[(code << 3) + l] : 0;
748 if(reverse) pat = ~pat;
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;
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++) {
773 memset(&text[yy][x << 3], 7, 8);
778 src = (src + 1) & 0x7ff;
783 void IO::draw_text_40x25()
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];
792 int page = (gcw >> 6) & 1;
793 src = (src & 0x7fe) | page;
794 cursor = (cursor & 0x7fe) | page;
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];
804 bool blink = ((attr & 0x40) && (cblink & 0x20));
805 bool reverse = (((attr & 0x20) != 0) != blink);
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;
816 for(int l = 0; l < ht; l++) {
817 uint8 pat = (l < 8) ? pcg[(code << 3) + l] : 0;
818 if(reverse) pat = ~pat;
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;
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++) {
843 memset(&text[yy][x << 3], 7, 16);
848 src = (src + 2) & 0x7ff;
853 void IO::draw_graph_640x200()
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];
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];
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];
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];
887 void IO::draw_graph_320x200()
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];
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];
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;
914 #define STATE_VERSION 1
916 void IO::save_state(FILEIO* state_fio)
918 state_fio->FputUint32(STATE_VERSION);
919 state_fio->FputInt32(this_device_id);
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);
962 bool IO::load_state(FILEIO* state_fio)
964 if(state_fio->FgetUint32() != STATE_VERSION) {
967 if(state_fio->FgetInt32() != this_device_id) {
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();
1012 SET_BANK(0x0000, 0x3fff, wdmy, rom);
1014 SET_BANK(0x0000, 0x3fff, ram, ram);