2 EPSON HC-80 Emulator 'eHC-80'
4 Author : Takeda.Toshiya
13 #include "../../fifo.h"
14 #include "../../fileio.h"
49 #define DID_FIRST 0x31
56 // intelligent ram disk
57 #define IRAMDISK_WAIT 1
59 #define IRAMDISK_OUT 1
65 static const int key_tbl[256] = {
66 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x56,0x57,0xff,0xff,0xff,0x71,0xff,0xff,
67 0xb3,0xb2,0xff,0x10,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0xff,
68 0x73,0xff,0xff,0xff,0xff,0x63,0x55,0x65,0x64,0xff,0xff,0xff,0xff,0x80,0x81,0xff,
69 0x52,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x50,0x51,0xff,0xff,0xff,0xff,0xff,0xff,
70 0xff,0x66,0x40,0x76,0x30,0x22,0x31,0x32,0x33,0x27,0x34,0x35,0x36,0x42,0x41,0x60,
71 0x61,0x20,0x23,0x67,0x24,0x26,0x77,0x21,0x75,0x25,0x74,0xff,0xff,0xff,0xff,0xff,
72 0x52,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x50,0x51,0xff,0xff,0xff,0xff,0xff,0xff,
73 0x03,0x04,0x05,0x06,0x07,0xff,0xff,0xff,0xff,0xff,0x01,0x02,0xff,0xff,0xff,0xff,
74 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
75 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
76 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
77 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x70,0x37,0x43,0x53,0x44,0x45,
78 0x62,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
79 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x46,0x72,0x47,0x54,0xff,
80 0xff,0xff,0x72,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
81 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
84 static const uint8 dot_tbl[8] = {
85 0x80, 0x40, 0x20, 0x10, 8, 4, 2, 1
91 device_type = config.device_type;
93 // init ram and external ram disk
94 memset(ram, 0, sizeof(ram));
95 memset(ext, 0, 0x20000);
96 memset(ext + 0x20000, 0xff, 0x20000);
101 FILEIO* fio = new FILEIO();
102 if(fio->Fopen(emu->bios_path(_T("BASIC.ROM")), FILEIO_READ_BINARY)) {
103 fio->Fread(basic, 0x4000, 1);
104 memcpy(basic + 0x4000, basic, 0x4000);
105 fio->Fread(basic + 0x4000, 0x4000, 1);
108 if(fio->Fopen(emu->bios_path(_T("UTIL.ROM")), FILEIO_READ_BINARY)) {
109 fio->Fread(util, 0x4000, 1);
110 memcpy(util + 0x4000, util, 0x4000);
111 fio->Fread(util + 0x4000, 0x4000, 1);
114 if(fio->Fopen(emu->bios_path(_T("VRAM.BIN")), FILEIO_READ_BINARY)) {
115 fio->Fread(ram + 0x8000, 0x1800, 1);
118 if(fio->Fopen(emu->bios_path(_T("EXTRAM.BIN")), FILEIO_READ_BINARY)) {
119 fio->Fread(ext, 0x20000, 1);
122 if(fio->Fopen(emu->bios_path(_T("INTRAM.BIN")), FILEIO_READ_BINARY)) {
123 fio->Fread(iramdisk_sectors, sizeof(iramdisk_sectors), 1);
126 if(fio->Fopen(emu->bios_path(_T("EXT.ROM")), FILEIO_READ_BINARY)) {
127 fio->Fread(ext + 0x20000, 0x20000, 1);
130 if(fio->Fopen(emu->bios_path(_T("FONT.ROM")), FILEIO_READ_BINARY)) {
131 fio->Fread(font, sizeof(font), 1);
137 cmd6303_buf = new FIFO(1024);
138 rsp6303_buf = new FIFO(1024);
139 tf20_buf = new FIFO(1024);
141 cmd7508_buf = new FIFO(16);
142 rsp7508_buf = new FIFO(16);
143 key_buf = new FIFO(7);
146 pd = RGB_COLOR(48, 56, 16);
147 pb = RGB_COLOR(160, 168, 160);
150 emu->get_host_time(&cur_time);
151 onesec_intr = alarm_intr = false;
152 onesec_intr_enb = alarm_intr_enb = kb_intr_enb = true;
153 res_7508 = kb_caps = false;
156 register_frame_event(this);
157 register_event_by_clock(this, EVENT_FRC, 0x40000, true, NULL);
158 register_event_by_clock(this, EVENT_1SEC, CPU_CLOCKS, true, ®ister_id);
159 register_event_by_clock(this, EVENT_6303, 100, true, NULL);
164 // save external ram disk
165 FILEIO* fio = new FILEIO();
166 if(fio->Fopen(emu->bios_path(_T("VRAM.BIN")), FILEIO_WRITE_BINARY)) {
167 fio->Fwrite(ram + 0x8000, 0x1800, 1);
170 if(fio->Fopen(emu->bios_path(_T("EXTRAM.BIN")), FILEIO_WRITE_BINARY)) {
171 fio->Fwrite(ext, 0x20000, 1);
174 if(fio->Fopen(emu->bios_path(_T("INTRAM.BIN")), FILEIO_WRITE_BINARY)) {
175 fio->Fwrite(iramdisk_sectors, sizeof(iramdisk_sectors), 1);
180 cmd6303_buf->release();
182 rsp6303_buf->release();
187 cmd7508_buf->release();
189 rsp7508_buf->release();
198 bcr = slbcr = isr = ier = ioctlr = 0;
212 cs_blocks = gs_blocks = 0;
213 memset(cs_block, 0, sizeof(cs_block));
214 memset(gs_block, 0, sizeof(gs_block));
215 memset(udgc, 0, sizeof(udgc));
216 wnd_ptr_x = wnd_ptr_y = 0;
219 // reset intelligent ram disk
221 iramdisk_ptr = iramdisk_buf;
227 onesec_intr = alarm_intr = false;
228 onesec_intr_enb = alarm_intr_enb = kb_intr_enb = true;
232 void IO::write_signal(int id, uint32 data, uint32 mask)
234 if(id == SIG_IO_RXRDY) {
235 // notify rxrdy is changed from i8251
242 } else if(id == SIG_IO_BARCODE) {
243 // signal from barcode reader
245 bool next = ((data & mask) != 0);
246 if((bcr == 2 && ear && !next) || (bcr == 4 && !ear && next) || (bcr == 6 && ear != next)) {
247 icrb = passed_clock(cur_clock) / 4;
253 } else if(id == SIG_IO_TF20) {
255 tf20_buf->write(data);
259 void IO::event_frame()
261 d_beep->write_signal(SIG_BEEP_ON, beep ? 1 : 0, 1);
266 void IO::event_callback(int event_id, int err)
268 if(event_id == EVENT_FRC) {
269 // FRC overflow event
270 cur_clock = current_clock();
273 } else if(event_id == EVENT_1SEC) {
275 if(cur_time.initialized) {
276 cur_time.increment();
278 emu->get_host_time(&cur_time); // resync
279 cur_time.initialized = true;
282 if(onesec_intr_enb) {
286 } else if(event_id == EVENT_6303) {
287 // communicate between z80 and 6303
292 if(!rsp6303_buf->empty()) {
298 void IO::write_io8(uint32 addr, uint32 data)
300 //emu->out_debug_log(_T("OUT %2x,%2x\n"), addr & 0xff, data);
301 switch(addr & 0xff) {
305 d_mem->write_signal(0, data, 1);
333 d_sio->write_io8(0, data);
336 // 8251 command write
337 d_sio->write_io8(1, data);
341 cmd6303_buf->write(data);
344 emu->out_debug_log(_T("%4x\tDAT %2x\n"), get_cpu_pc(0), data);
352 emu->out_debug_log(_T("\n%4x\tCMD %2x\n"), vm->get_cpu_pc(), data);
356 if(device_type == 1) {
357 iramdisk_write_data(data);
361 if(device_type == 1) {
362 iramdisk_write_cmd(data);
367 if(device_type == 2) {
368 extar = (extar & 0xffff00) | data;
373 if(device_type == 2) {
374 extar = (extar & 0xff00ff) | (data << 8);
379 if(device_type == 2) {
380 extar = (extar & 0x00ffff) | ((data & 7) << 16);
385 if(device_type == 2) {
386 if(extar < 0x20000) {
389 extar = (extar & 0xffff00) | ((extar + 1) & 0xff);
394 if(device_type == 2) {
401 uint32 IO::read_io8(uint32 addr)
404 // emu->out_debug_log(_T("IN %2x\n"), addr & 0xff);
406 switch(addr & 0xff) {
408 // ICRL.C (latch FRC value)
409 icrc = passed_clock(cur_clock) / 4;
413 return (icrc >> 8) & 0xff;
421 return (icrb >> 8) & 0xff;
427 return 8 | 4 | (ear ? 1 : 0); // always rdysio=rdy=true
430 return rec_from_7508();
435 return d_sio->read_io8(0);
438 return d_sio->read_io8(1);
444 val = rsp6303_buf->read();
446 if(!rsp6303_buf->empty()) {
450 emu->out_debug_log(_T("%4x\tRCV %2x\n"), vm->get_cpu_pc(), val);
454 if(device_type == 1) {
455 return iramdisk_read_data();
459 if(device_type == 1) {
460 return iramdisk_read_stat();
465 if(device_type == 2) {
466 if(extar < 0x40000) {
469 extar = (extar & 0xffff00) | ((extar + 1) & 0xff);
475 if(device_type == 2) {
476 return extcr & ~0x80;
483 uint32 IO::intr_ack()
488 } else if(isr & BIT_8251) {
490 } else if(isr & BIT_CD) {
492 } else if(isr & BIT_ICF) {
494 } else if(isr & BIT_OVF) {
496 } else if(isr & BIT_EXT) {
503 void IO::update_intr()
506 bool next = ((isr & ier & 0x3f) != 0);
507 d_cpu->set_intr_line(next, true, 0);
510 // ----------------------------------------------------------------------------
512 // ----------------------------------------------------------------------------
514 void IO::send_to_7508(uint8 val)
519 cmd7508_buf->write(val);
520 uint8 cmd = cmd7508_buf->read_not_remove(0);
530 if((onesec_intr && onesec_intr_enb) || (alarm_intr && alarm_intr_enb) || res_z80 || res_7508) {
532 res |= (onesec_intr && onesec_intr_enb) ? 0x20 : 0;
533 res |= (res_z80 ? 0x10 : 0) | (res_7508 ? 8 : 0);
534 res |= (alarm_intr && alarm_intr_enb) ? 2 : 0;
536 onesec_intr = alarm_intr = res_z80 = res_7508 = false;
537 } else if(key_buf->count()) {
538 res = key_buf->read();
542 rsp7508_buf->write(res);
543 // request next interrupt
544 if(key_buf->count() && kb_intr_enb) {
553 kb_rep_spd1 = 42 | 0x80;
554 kb_rep_spd2 = 18 | 0x80;
558 // kb repeat timer 1 set
559 if(cmd7508_buf->count() == 2) {
561 kb_rep_spd1 = cmd7508_buf->read();
577 rsp7508_buf->write(TO_BCD_HI(cur_time.year));
578 rsp7508_buf->write(TO_BCD_LO(cur_time.year));
579 rsp7508_buf->write(TO_BCD(cur_time.month));
580 rsp7508_buf->write(TO_BCD(cur_time.day));
581 rsp7508_buf->write(TO_BCD(cur_time.hour));
582 rsp7508_buf->write(TO_BCD(cur_time.minute));
583 rsp7508_buf->write(TO_BCD(cur_time.second));
584 rsp7508_buf->write(cur_time.day_of_week);
589 rsp7508_buf->write(1);
594 rsp7508_buf->write(alarm[0]);
595 rsp7508_buf->write(alarm[1]);
596 rsp7508_buf->write(alarm[2]);
597 rsp7508_buf->write(alarm[3]);
598 rsp7508_buf->write(alarm[4]);
599 rsp7508_buf->write(alarm[5]);
604 res = 0xf; // ascii keyboard
605 rsp7508_buf->write(res);
608 // set power failure detect voltage
609 if(cmd7508_buf->count() == 2) {
615 // read buttery voltage
617 rsp7508_buf->write(0xe0);
620 // 1 sec interrupt off
622 onesec_intr_enb = false;
635 // kb repeat timer 2 set
636 if(cmd7508_buf->count() == 2) {
638 kb_rep_spd2 = cmd7508_buf->read();
653 if(cmd7508_buf->count() == 9) {
655 int year10 = cmd7508_buf->read();
656 int year1 = cmd7508_buf->read();
657 int month = cmd7508_buf->read();
658 int day = cmd7508_buf->read();
659 int hour = cmd7508_buf->read();
660 int minute = cmd7508_buf->read();
661 int second = cmd7508_buf->read();
662 int day_of_week = cmd7508_buf->read();
664 if((month & 0x0f) == 0 || (day & 0x0f) == 0) {
666 emu->get_host_time(&cur_time);
668 bool changed = false;
669 if((year10 & 0x0f) != 0x0f && (year1 & 0x0f) != 0x0f) {
670 cur_time.year = (year10 & 0x0f) * 10 + (year1 & 0x0f);
671 cur_time.update_year();
674 if((month & 0x0f) != 0x0f) {
675 cur_time.month = FROM_BCD(month & 0x1f);
678 if((day & 0x0f) != 0x0f) {
679 cur_time.day = FROM_BCD(day & 0x3f);
682 if((hour & 0x0f) != 0x0f) {
683 cur_time.hour = FROM_BCD(hour & 0x3f);
686 if((minute & 0x0f) != 0x0f) {
687 cur_time.minute = FROM_BCD(minute & 0x7f);
690 if((second & 0x0f) != 0x0f) {
691 cur_time.second = FROM_BCD(second & 0x7f);
694 // if((day_of_week & 0x0f) != 0x0f) {
695 // cur_time.day_of_week = day_of_week & 0x07;
699 cur_time.update_day_of_week();
701 cancel_event(this, register_id);
702 register_event_by_clock(this, EVENT_1SEC, CPU_CLOCKS, true, ®ister_id);
709 if(cmd7508_buf->count() == 7) {
711 alarm[0] = cmd7508_buf->read();
712 alarm[1] = cmd7508_buf->read();
713 alarm[2] = cmd7508_buf->read();
714 alarm[3] = cmd7508_buf->read();
715 alarm[4] = cmd7508_buf->read();
716 alarm[5] = cmd7508_buf->read();
720 // set full charge voltage
721 if(cmd7508_buf->count() == 2) {
729 rsp7508_buf->write(0x90);
732 // 1 sec interrupt on
734 onesec_intr_enb = true;
737 // kb repeat timer 1 read
739 rsp7508_buf->write(kb_rep_spd1);
744 alarm_intr_enb = false;
747 // read analog jack 1
749 rsp7508_buf->write(0);
752 // kb repeat timer 2 read
754 rsp7508_buf->write(kb_rep_spd2);
759 alarm_intr_enb = true;
762 // read analog jack 2
764 rsp7508_buf->write(0);
769 emu->out_debug_log(_T("unknown cmd %2x\n"), cmd);
773 uint8 IO::rec_from_7508()
775 return rsp7508_buf->read();
778 void IO::key_down(int code)
783 update_key(kb_caps ? 0xb4 : 0xa4);
784 update_key(kb_caps ? 0xa4 : 0xb4);
786 update_key(key_tbl[code & 0xff]);
790 void IO::key_up(int code)
793 update_key(0xa3); // break shift
794 } else if(code == 0x11) {
795 update_key(0xa2); // break ctrl
799 void IO::update_key(int code)
806 key_buf->write(code);
808 key_buf->write(code);
812 if(kb_intr_enb || (!kb_intr_enb && code == 0x10)) {
819 // ----------------------------------------------------------------------------
821 // ----------------------------------------------------------------------------
823 void IO::process_6303()
828 if(cmd6303_buf->count() == 2) {
829 uint16 addr = cmd6303_buf->read() << 8;
830 addr |= cmd6303_buf->read();
831 rsp6303_buf->write(RCD00);
832 rsp6303_buf->write(ram[addr]);
838 if(cmd6303_buf->count() == 4) {
839 uint16 addr = cmd6303_buf->read() << 8;
840 addr |= cmd6303_buf->read();
841 uint8 val = cmd6303_buf->read();
842 uint8 ope = cmd6303_buf->read();
845 } else if(ope == 2) {
847 } else if(ope == 3) {
852 rsp6303_buf->write(RCD00);
858 if(cmd6303_buf->count() == 2) {
859 uint16 addr = cmd6303_buf->read() << 8;
860 addr |= cmd6303_buf->read();
862 rsp6303_buf->write(RCD00);
867 // unknown (initialize???)
868 rsp6303_buf->write(RCD00);
872 // define screen mode
873 if(cmd6303_buf->count() == 16) {
874 cs_addr = cmd6303_buf->read() << 8;
875 cs_addr |= cmd6303_buf->read();
876 gs_addr = cmd6303_buf->read() << 8;
877 gs_addr |= cmd6303_buf->read();
886 uint16 bottom = cmd6303_buf->read() << 8;
887 bottom |= cmd6303_buf->read();
890 rsp6303_buf->write(RCD00);
892 // go to character screen mode ???
894 // stop block flashing ???
896 cs_blocks = gs_blocks = 0;
898 memset(&ram[cs_addr], 0, bottom - cs_addr);
903 if(cmd6303_buf->count() == 1) {
904 lcd_on = cmd6303_buf->read();
905 rsp6303_buf->write(RCD00);
911 if(cmd6303_buf->count() == 1) {
912 scr_mode = cmd6303_buf->read();
916 rsp6303_buf->write(RCD00);
921 // read screen pointer
922 rsp6303_buf->write(RCD00);
923 rsp6303_buf->write(scr_ptr >> 8);
924 rsp6303_buf->write(scr_ptr & 0xff);
928 // set screen pointer
929 if(cmd6303_buf->count() == 2) {
930 scr_ptr = cmd6303_buf->read() << 8;
931 scr_ptr |= cmd6303_buf->read();
932 rsp6303_buf->write(RCD00);
934 // stop block flashing ???
936 cs_blocks = gs_blocks = 0;
940 // define number of lines
941 if(cmd6303_buf->count() == 1) {
942 num_lines = cmd6303_buf->read();
943 rsp6303_buf->write(RCD00);
948 // define cursor mode
949 if(cmd6303_buf->count() == 1) {
950 curs_mode = cmd6303_buf->read();
951 rsp6303_buf->write(RCD00);
956 // read cursur position
957 rsp6303_buf->write(RCD00);
958 rsp6303_buf->write(curs_x);
959 rsp6303_buf->write(curs_y);
963 // set cursor position
964 if(cmd6303_buf->count() == 2) {
965 curs_x = cmd6303_buf->read();
966 curs_y = cmd6303_buf->read();
967 rsp6303_buf->write(RCD00);
972 // start/stop control block flashing
973 if(cmd6303_buf->count() == 1) {
974 flash_block = cmd6303_buf->read();
975 rsp6303_buf->write(RCD00);
981 if(cmd6303_buf->count() == 4) {
982 uint8 scr = cmd6303_buf->read();
983 uint8 code = cmd6303_buf->read();
984 int sy = cmd6303_buf->read();
985 int num = cmd6303_buf->read();
988 for(int y = 0; y < num; y++) {
990 memset(&ram[cs_addr + (sy + y) * 80], code, 80);
995 for(int y = 0; y < num; y++) {
997 memset(&ram[gs_addr + (sy + y) * 60 * 8], code, 60 * 8);
1001 rsp6303_buf->write(RCD00);
1006 // read character font
1007 if(cmd6303_buf->count() == 1) {
1008 int ofs = cmd6303_buf->read() << 3;
1009 rsp6303_buf->write(RCD00);
1010 for(int i = 0; i < 8; i++) {
1011 rsp6303_buf->write(font[ofs + i]);
1017 // define user defined graphic character
1018 if(cmd6303_buf->count() >= 3) {
1019 int lx = cmd6303_buf->read_not_remove(1);
1020 int ly = cmd6303_buf->read_not_remove(2);
1021 if(cmd6303_buf->count() == lx * ly + 3) {
1022 uint8 code = cmd6303_buf->read();
1023 bool pre = (udgc[code][0] && udgc[code][1]);
1024 for(int i = 0; i < lx * ly + 2; i++) {
1025 uint8 d = cmd6303_buf->read();
1031 memset(udgc, 0, sizeof(udgc));
1033 rsp6303_buf->write(RCD00);
1039 // define graphic screen block flashing data
1040 if(cmd6303_buf->count() >= 1) {
1041 int cnt = cmd6303_buf->read_not_remove(0);
1042 if(cmd6303_buf->count() == cnt * 3 + 1) {
1043 gs_blocks = cmd6303_buf->read();
1044 for(int i = 0; i < gs_blocks; i++) {
1045 gs_block[i][0] = cmd6303_buf->read();
1046 gs_block[i][1] = cmd6303_buf->read();
1047 gs_block[i][2] = cmd6303_buf->read();
1049 rsp6303_buf->write(RCD00);
1055 // draw character font on graphic screen
1056 if(cmd6303_buf->count() == 4) {
1057 int x = cmd6303_buf->read() << 8;
1058 x |= cmd6303_buf->read();
1059 int y = cmd6303_buf->read();
1060 int ofs = cmd6303_buf->read() << 3;
1061 for(int l = 0; l < 8; l++) {
1062 uint8 pat = font[ofs + l];
1063 draw_point(x + 0, y + l, pat & 0x20);
1064 draw_point(x + 1, y + l, pat & 0x10);
1065 draw_point(x + 2, y + l, pat & 0x08);
1066 draw_point(x + 3, y + l, pat & 0x04);
1067 draw_point(x + 4, y + l, pat & 0x02);
1068 draw_point(x + 5, y + l, pat & 0x01);
1070 rsp6303_buf->write(RCD00);
1075 // draw user defined character on graphics screen
1076 if(cmd6303_buf->count() >= 3) {
1077 int dx = cmd6303_buf->read();
1078 int dy = cmd6303_buf->read();
1079 uint8 code = cmd6303_buf->read();
1080 int lx = udgc[code][0];
1081 int ly = udgc[code][1];
1082 uint8* pat = &udgc[code][2];
1084 for(int y = 0; y < ly; y++) {
1085 for(int x = 0; x < lx; x++) {
1086 if(dx + x < 60 && dy + y < 64) {
1087 ram[gs_addr + (dx + x + (dy + y) * 60)] = *pat++;
1092 rsp6303_buf->write(RCD00);
1097 // read graphics screen data
1098 if(cmd6303_buf->count() == 3) {
1099 int x = cmd6303_buf->read();
1100 int y = cmd6303_buf->read();
1101 uint8* src = &ram[gs_addr + (x + y * 60)];
1102 int cnt = cmd6303_buf->read();
1103 rsp6303_buf->write(RCD00);
1104 for(int i = 0; i < cnt; i++) {
1105 rsp6303_buf->write(src[i]);
1111 // display data on graphics screen
1112 if(cmd6303_buf->count() >= 4) {
1113 int lx = cmd6303_buf->read_not_remove(2);
1114 int ly = cmd6303_buf->read_not_remove(3);
1115 if(cmd6303_buf->count() == lx * ly + 5) {
1116 int dx = cmd6303_buf->read();
1117 int dy = cmd6303_buf->read();
1118 lx = cmd6303_buf->read();
1119 ly = cmd6303_buf->read();
1120 uint8 ope = cmd6303_buf->read();
1121 for(int y = 0; y < ly; y++) {
1122 for(int x = 0; x < lx; x++) {
1123 uint8 d = cmd6303_buf->read();
1124 if(dx + x < 60 && dy + y < 64) {
1126 ram[gs_addr + (dx + x + (dy + y) * 60)] &= d;
1127 } else if(ope == 2) {
1128 ram[gs_addr + (dx + x + (dy + y) * 60)] |= d;
1129 } else if(ope == 3) {
1130 ram[gs_addr + (dx + x + (dy + y) * 60)] ^= d;
1132 ram[gs_addr + (dx + x + (dy + y) * 60)] = d;
1137 rsp6303_buf->write(RCD00);
1143 // move graphics screen block
1144 if(cmd6303_buf->count() == 6) {
1145 int sx = cmd6303_buf->read();
1146 int sy = cmd6303_buf->read();
1147 int lx = cmd6303_buf->read();
1148 int ly = cmd6303_buf->read();
1149 int dx = cmd6303_buf->read();
1150 int dy = cmd6303_buf->read();
1151 for(int y = 0; y < ly; y++) {
1152 for(int x = 0; x < lx; x++) {
1153 if(sx + x < 60 && sy + y < 64) {
1154 mov[y][x] = ram[gs_addr + (sx + x + (sy + y) * 60)];
1155 ram[gs_addr + (sx + x + (sy + y) * 60)] = 0;
1159 for(int y = 0; y < ly; y++) {
1160 for(int x = 0; x < lx; x++) {
1161 if(dx + x < 60 && dy + y < 64) {
1162 ram[gs_addr + (dx + x + (dy + y) * 60)] = mov[y][x];
1166 rsp6303_buf->write(RCD00);
1172 if(cmd6303_buf->count() == 4) {
1173 int x = cmd6303_buf->read() << 8;
1174 x |= cmd6303_buf->read();
1175 int y = cmd6303_buf->read();
1176 uint8 ope = cmd6303_buf->read();
1178 draw_point(x, y, 0);
1180 draw_point(x, y, 1);
1182 rsp6303_buf->write(RCD00);
1188 if(cmd6303_buf->count() == 3) {
1189 int x = cmd6303_buf->read() << 8;
1190 x |= cmd6303_buf->read();
1191 int y = cmd6303_buf->read();
1192 rsp6303_buf->write(RCD00);
1193 rsp6303_buf->write(get_point(x, y));
1199 if(cmd6303_buf->count() == 11) {
1200 int sx = cmd6303_buf->read() << 8;
1201 sx |= cmd6303_buf->read();
1202 int sy = cmd6303_buf->read() << 8;
1203 sy |= cmd6303_buf->read();
1204 int ex = cmd6303_buf->read() << 8;
1205 ex |= cmd6303_buf->read();
1206 int ey = cmd6303_buf->read() << 8;
1207 ey |= cmd6303_buf->read();
1208 uint16 ope = cmd6303_buf->read() << 8;
1209 ope |= cmd6303_buf->read();
1210 uint8 mode = cmd6303_buf->read();
1212 draw_line(sx, sy, ex, ey, ~ope);
1214 draw_line(sx, sy, ex, ey, ope);
1216 rsp6303_buf->write(RCD00);
1221 // user defined character
1222 if(cmd6303_buf->count() == 9) {
1223 int code = cmd6303_buf->read();
1225 for(int i = 0; i < 8; i++) {
1226 cmd6303_buf->read();
1228 rsp6303_buf->write(RCD06);
1230 int ofs = code << 3;
1231 for(int i = 0; i < 8; i++) {
1232 font[ofs + i] = cmd6303_buf->read();
1234 rsp6303_buf->write(RCD00);
1240 // define character screen block flashing data
1241 if(cmd6303_buf->count() >= 1) {
1242 int cnt = cmd6303_buf->read_not_remove(0);
1243 if(cmd6303_buf->count() == cnt * 3 + 1) {
1244 cs_blocks = cmd6303_buf->read();
1245 for(int i = 0; i < cs_blocks; i++) {
1246 cs_block[i][0] = cmd6303_buf->read();
1247 cs_block[i][1] = cmd6303_buf->read();
1248 cs_block[i][2] = cmd6303_buf->read();
1250 rsp6303_buf->write(RCD00);
1256 // read window pointer
1257 rsp6303_buf->write(RCD00);
1258 rsp6303_buf->write(wnd_ptr_x);
1259 rsp6303_buf->write(wnd_ptr_y);
1263 // set window pointer
1264 if(cmd6303_buf->count() == 2) {
1265 wnd_ptr_x = cmd6303_buf->read();
1266 wnd_ptr_y = cmd6303_buf->read();
1267 rsp6303_buf->write(RCD00);
1272 // read character screen data
1273 if(cmd6303_buf->count() == 3) {
1274 int x = cmd6303_buf->read();
1275 int y = cmd6303_buf->read();
1276 uint8* src = &ram[cs_addr + (x + y * 80)];
1277 int cnt = cmd6303_buf->read();
1278 rsp6303_buf->write(RCD00);
1279 for(int i = 0; i < cnt; i++) {
1280 rsp6303_buf->write(src[i]);
1286 // display data on character screen
1287 if(cmd6303_buf->count() >= 4) {
1288 int cnt = cmd6303_buf->read_not_remove(2);
1289 if(cmd6303_buf->count() == cnt + 3) {
1290 int x = cmd6303_buf->read();
1291 int y = cmd6303_buf->read();
1292 uint8* dest = &ram[cs_addr + (x + y * 80)];
1293 cnt = cmd6303_buf->read();
1294 for(int i = 0; i < cnt; i++) {
1295 dest[i] = cmd6303_buf->read();
1297 rsp6303_buf->write(RCD00);
1303 // move character screen block
1304 if(cmd6303_buf->count() == 6) {
1305 int sx = cmd6303_buf->read();
1306 int sy = cmd6303_buf->read();
1307 int lx = cmd6303_buf->read();
1308 int ly = cmd6303_buf->read();
1309 int dx = cmd6303_buf->read();
1310 int dy = cmd6303_buf->read();
1311 for(int y = 0; y < ly; y++) {
1312 for(int x = 0; x < lx; x++) {
1313 if(sx + x < 80 && sy + y < 64) {
1314 mov[y][x] = ram[cs_addr + (sx + x + (sy + y) * 80)];
1315 // ram[cs_addr + (sx + x + (sy + y) * 80)] = 0;
1319 for(int y = 0; y < ly; y++) {
1320 for(int x = 0; x < lx; x++) {
1321 if(dx + x < 80 && dy + y < 64) {
1322 ram[cs_addr + (dx + x + (dy + y) * 80)] = mov[y][x];
1326 rsp6303_buf->write(RCD00);
1331 // read microcassette status
1332 rsp6303_buf->write(RCD00);
1333 rsp6303_buf->write(0);
1338 rsp6303_buf->write(RCD07);
1343 rsp6303_buf->write(RCD00);
1349 // fast foward n counts
1350 if(cmd6303_buf->count() == 2) {
1351 cmd6303_buf->read();
1352 cmd6303_buf->read();
1353 rsp6303_buf->write(RCD07);
1361 rsp6303_buf->write(RCD07);
1372 rsp6303_buf->write(RCD00);
1376 // read write protect pin
1377 rsp6303_buf->write(RCD00);
1378 rsp6303_buf->write(0);
1383 rsp6303_buf->write(RCD00);
1384 rsp6303_buf->write(0);
1385 rsp6303_buf->write(0);
1390 if(cmd6303_buf->count() == 2) {
1391 cmd6303_buf->read();
1392 cmd6303_buf->read();
1393 rsp6303_buf->write(RCD00);
1398 // set write protect area pointer
1399 if(cmd6303_buf->count() == 2) {
1400 cmd6303_buf->read();
1401 cmd6303_buf->read();
1402 rsp6303_buf->write(RCD00);
1407 // reset write protect area pointer
1408 rsp6303_buf->write(RCD00);
1412 // read serial i/o status
1413 rsp6303_buf->write(RCD00);
1414 rsp6303_buf->write(0x20 | (tf20_buf->count() ? 0x80 : 0));
1418 // set serial port bit rate
1419 if(cmd6303_buf->count() == 1) {
1420 cmd6303_buf->read();
1421 rsp6303_buf->write(RCD00);
1427 rsp6303_buf->write(RCD00);
1428 rsp6303_buf->write(tf20_buf->read());
1433 if(cmd6303_buf->count() == 1) {
1434 d_tf20->write_signal(SIGNAL_TF20_SIO, cmd6303_buf->read(), 0xff);
1435 rsp6303_buf->write(RCD00);
1440 // send data with header
1441 if(cmd6303_buf->count() >= 6) {
1442 int cnt = cmd6303_buf->read_not_remove(5);
1443 if(cmd6303_buf->count() == cnt + 7) {
1444 int rcv = cmd6303_buf->read();
1445 int fmt = cmd6303_buf->read();
1446 int did = cmd6303_buf->read();
1447 int sid = cmd6303_buf->read();
1448 int fnc = cmd6303_buf->read();
1449 int siz = cmd6303_buf->read();
1453 d_tf20->write_signal(SIGNAL_TF20_SIO, DID_FIRST, 0xff);
1454 d_tf20->write_signal(SIGNAL_TF20_SIO, did, 0xff);
1455 d_tf20->write_signal(SIGNAL_TF20_SIO, sid, 0xff);
1456 d_tf20->write_signal(SIGNAL_TF20_SIO, DS_SEL, 0xff);
1457 tf20_buf->read(); // recv ack
1458 d_tf20->write_signal(SIGNAL_TF20_SIO, SOH, 0xff);
1459 d_tf20->write_signal(SIGNAL_TF20_SIO, fmt, 0xff);
1460 d_tf20->write_signal(SIGNAL_TF20_SIO, did, 0xff);
1461 d_tf20->write_signal(SIGNAL_TF20_SIO, sid, 0xff);
1462 d_tf20->write_signal(SIGNAL_TF20_SIO, fnc, 0xff);
1463 d_tf20->write_signal(SIGNAL_TF20_SIO, siz, 0xff);
1464 d_tf20->write_signal(SIGNAL_TF20_SIO, 0, 0xff);
1465 tf20_buf->read(); // recv ack
1466 d_tf20->write_signal(SIGNAL_TF20_SIO, STX, 0xff);
1467 for(int i = 0; i < siz + 1; i++) {
1468 d_tf20->write_signal(SIGNAL_TF20_SIO, cmd6303_buf->read(), 0xff);
1470 d_tf20->write_signal(SIGNAL_TF20_SIO, 0, 0xff);
1471 d_tf20->write_signal(SIGNAL_TF20_SIO, 0, 0xff);
1472 tf20_buf->read(); // recv ack
1473 d_tf20->write_signal(SIGNAL_TF20_SIO, EOT, 0xff);
1475 rsp6303_buf->write(RCD00);
1477 rsp6303_buf->write(0);
1479 rsp6303_buf->write(fmt = tf20_buf->read());
1480 rsp6303_buf->write(did = tf20_buf->read());
1481 rsp6303_buf->write(sid = tf20_buf->read());
1482 rsp6303_buf->write(fnc = tf20_buf->read());
1483 rsp6303_buf->write(siz = tf20_buf->read());
1485 d_tf20->write_signal(SIGNAL_TF20_SIO, ACK, 0xff); // ack
1487 for(int i = 0; i < siz + 1; i++) {
1488 rsp6303_buf->write(tf20_buf->read());
1490 d_tf20->write_signal(SIGNAL_TF20_SIO, ACK, 0xff); // ack
1491 d_tf20->write_signal(SIGNAL_TF20_SIO, EOT, 0xff); // eot
1499 // receive data with header
1500 rsp6303_buf->write(RCD00);
1503 int fmt, did, sid, fnc, siz;
1504 rsp6303_buf->write(0);
1506 rsp6303_buf->write(fmt = tf20_buf->read());
1507 rsp6303_buf->write(did = tf20_buf->read());
1508 rsp6303_buf->write(sid = tf20_buf->read());
1509 rsp6303_buf->write(fnc = tf20_buf->read());
1510 rsp6303_buf->write(siz = tf20_buf->read());
1512 d_tf20->write_signal(SIGNAL_TF20_SIO, ACK, 0xff); // ack
1514 for(int i = 0; i < siz + 1; i++) {
1515 rsp6303_buf->write(tf20_buf->read());
1517 d_tf20->write_signal(SIGNAL_TF20_SIO, ACK, 0xff); // ack
1518 d_tf20->write_signal(SIGNAL_TF20_SIO, EOT, 0xff); // eot
1524 // turn on/off prom cupsule power
1525 if(cmd6303_buf->count() == 1) {
1526 cmd6303_buf->read();
1527 rsp6303_buf->write(RCD00);
1533 if(cmd6303_buf->count() == 4) {
1534 cmd6303_buf->read();
1535 uint16 addr = cmd6303_buf->read() << 8;
1536 addr |= cmd6303_buf->read();
1538 int cnt = cmd6303_buf->read();
1539 if(cnt == 0) cnt = 256;
1540 rsp6303_buf->write(RCD00);
1541 for(int i = 0; i < cnt; i++) {
1543 rsp6303_buf->write(util[(addr + i) & 0x7fff]);
1545 rsp6303_buf->write(basic[(addr + i) & 0x7fff]);
1552 // turn on/off speaker power
1553 if(cmd6303_buf->count() == 1) {
1554 cmd6303_buf->read();
1555 rsp6303_buf->write(RCD00);
1560 // turn on/off speaker power
1561 if(cmd6303_buf->count() == 3) {
1562 cmd6303_buf->read();
1563 cmd6303_buf->read();
1564 cmd6303_buf->read();
1565 rsp6303_buf->write(RCD00);
1571 if(cmd6303_buf->count() == 3) {
1572 cmd6303_buf->read();
1573 cmd6303_buf->read();
1574 cmd6303_buf->read();
1575 rsp6303_buf->write(RCD00);
1582 uint8 IO::get_point(int x, int y)
1584 if(0 <= x && x < 480 && 0 <= y && y < 64) {
1585 uint8 bit = dot_tbl[x & 7];
1586 int ofs = y * 60 + (x >> 3);
1587 return ram[gs_addr + ofs] & bit;
1592 void IO::draw_point(int x, int y, uint16 dot)
1594 if(0 <= x && x < 480 && 0 <= y && y < 64) {
1595 uint8 bit = dot_tbl[x & 7];
1596 int ofs = y * 60 + (x >> 3);
1598 ram[gs_addr + ofs] |= bit;
1600 ram[gs_addr + ofs] &= ~bit;
1605 void IO::draw_line(int sx, int sy, int ex, int ey, uint16 ope)
1607 int next_x = sx, next_y = sy;
1608 int delta_x = abs(ex - sx) * 2;
1609 int delta_y = abs(ey - sy) * 2;
1610 int step_x = (ex < sx) ? -1 : 1;
1611 int step_y = (ey < sy) ? -1 : 1;
1613 draw_point(sx, sy, ope & 0x8000);
1614 ope = (ope << 1) | (ope & 0x8000 ? 1 : 0);
1615 if(delta_x > delta_y) {
1616 int frac = delta_y - delta_x / 2;
1617 while(next_x != ex) {
1624 draw_point(next_x, next_y, ope & 0x8000);
1625 ope = (ope << 1) | (ope & 0x8000 ? 1 : 0);
1628 int frac = delta_x - delta_y / 2;
1629 while(next_y != ey) {
1636 draw_point(next_x, next_y, ope & 0x8000);
1637 ope = (ope << 1) | (ope & 0x8000 ? 1 : 0);
1640 draw_point(ex, ey, ope & 0x8000);
1643 // ----------------------------------------------------------------------------
1644 // intelligent ram disk by Mr.Dennis Heynlein
1645 // ----------------------------------------------------------------------------
1648 0x81 (W) CommandByte c to RAMDisk
1650 Bit 0 : Readable DataByte on 0x81 is pending
1651 Bit 1 : Receive of Data/Command is busy
1652 Bit 7 and 6 = 0 (ident the RAMdisc)
1654 0x80 (R/W) DataByte d
1656 Commands: RESET - input: c(00)
1657 output: d(SWITCHSTATE)
1659 READSECTOR - input: c(01) d(TRACK) d(SECTOR)
1660 output: d(ERRORSTATE) d(SECTORBYTE)*128
1662 READMEMDIRECT - input: c(02) d(BANK) d(HIGHBYTE) d(LOWBYTE)
1663 output: d(ERRORSTATE) d(BYTE)
1665 WRITESECTOR - input: c(03) d(TRACK) d(SECTOR) d(SECTORBYTE)*128
1666 output: d(ERRORSTATE)
1668 WRITEMEMDIRECT - input: c(04) d(HIGHBYTE) d(LOWBYTE) d(BYTE)
1669 output: d(ERRORSTATE)
1671 INIT_BITMAP - input: c(05)
1672 output: d(ERRORSTATE)
1674 ERRORSTATE: Bit 0 = Ramdiscsize
1676 Bit 2 = Writeprotect
1685 void IO::iramdisk_write_data(uint8 val)
1687 if(iramdisk_dest == IRAMDISK_IN && iramdisk_count) {
1688 *(iramdisk_ptr++) = val;
1691 if(!iramdisk_count) {
1692 iramdisk_dest = IRAMDISK_OUT;
1693 iramdisk_ptr = iramdisk_buf;
1694 int track = iramdisk_buf[0];
1695 int sector = iramdisk_buf[1];
1697 switch(iramdisk_cmd) {
1698 case 1: //READSECTOR
1699 if(track > 14 || sector > 63) {
1700 iramdisk_buf[0] = 2;
1702 iramdisk_buf[0] = 0;
1703 for(int t = 0;t < 128; t++) {
1704 iramdisk_buf[t + 1] = iramdisk_sectors[track][sector][t];
1707 iramdisk_count = 129; //ERRORCODE + 128 Bytes
1709 case 3: //WRITESECTOR
1710 if(track > 14 || sector > 63) {
1711 iramdisk_buf[0] = 2;
1713 iramdisk_buf[0] = 0;
1714 for(int t = 0; t < 128; t++) {
1715 iramdisk_sectors[track][sector][t] = iramdisk_buf[t+2];
1718 iramdisk_count = 1; //ERRORCODE
1720 case 2: //READMEMDIRECT
1721 iramdisk_count = 2; //ERRORCODE + 1 Byte
1723 case 4: //WRITEMEMDIRECT
1724 iramdisk_count = 1; //ERRORCODE
1730 void IO::iramdisk_write_cmd(uint8 val)
1734 iramdisk_ptr = iramdisk_buf;
1735 iramdisk_dest = IRAMDISK_IN;
1737 switch(iramdisk_cmd) {
1746 iramdisk_count = 130;
1749 //PROCESS-1-BYTE_CMDs
1751 iramdisk_dest = IRAMDISK_OUT;
1752 if(iramdisk_cmd == 0) {
1753 iramdisk_buf[0] = 1; // RESET
1755 iramdisk_buf[0] = 0; //INIT
1760 uint8 IO::iramdisk_read_data()
1762 if(iramdisk_dest == IRAMDISK_OUT) {
1763 if(iramdisk_count) {
1765 if(!iramdisk_count) {
1766 iramdisk_dest = IRAMDISK_IN;
1768 return *(iramdisk_ptr++);
1774 uint8 IO::iramdisk_read_stat()
1776 if(iramdisk_dest == IRAMDISK_OUT) {
1777 return IRAMDISK_WAIT;
1783 // ----------------------------------------------------------------------------
1785 // ----------------------------------------------------------------------------
1788 void IO::draw_screen()
1791 memset(lcd, 0, sizeof(lcd));
1794 uint8* vram = &ram[scr_ptr];
1795 for(int y = 0; y < (num_lines ? 7 : 8); y++) {
1796 int py = num_lines ? (y * 9 + 1) : y * 8;
1797 for(int x = 0; x < 80; x++) {
1799 int ofs = vram[y * 80 + x] << 3;
1800 for(int l = 0; l < 8; l++) {
1801 uint8 pat = font[ofs + l];
1802 lcd[py + l][px + 0] = (pat & 0x20) ? 0xff : 0;
1803 lcd[py + l][px + 1] = (pat & 0x10) ? 0xff : 0;
1804 lcd[py + l][px + 2] = (pat & 0x08) ? 0xff : 0;
1805 lcd[py + l][px + 3] = (pat & 0x04) ? 0xff : 0;
1806 lcd[py + l][px + 4] = (pat & 0x02) ? 0xff : 0;
1807 lcd[py + l][px + 5] = (pat & 0x01) ? 0xff : 0;
1813 int yofs = (scr_ptr - cs_addr) / 80;
1814 for(int i = 0; i < cs_blocks; i++) {
1815 int x = cs_block[i][0];
1816 int y = cs_block[i][1] - yofs;
1817 if(0 <= x && x < 80 && 0 <= y && y < 8) {
1820 for(int l = 0; l < 8; l++) {
1821 lcd[py + l][px + 0] = ~lcd[py + l][px + 0];
1822 lcd[py + l][px + 1] = ~lcd[py + l][px + 1];
1823 lcd[py + l][px + 2] = ~lcd[py + l][px + 2];
1824 lcd[py + l][px + 3] = ~lcd[py + l][px + 3];
1825 lcd[py + l][px + 4] = ~lcd[py + l][px + 4];
1826 lcd[py + l][px + 5] = ~lcd[py + l][px + 5];
1833 if(!(curs_mode & 2) || (blink & 32)) {
1834 int px = curs_x * 6;
1835 int py = curs_y * 8;
1836 int st = (curs_mode & 4) ? 0 : 7;
1837 if(px + 6 - 1 < SCREEN_WIDTH) {
1838 for(int l = st; l < 8 && py + l < SCREEN_HEIGHT; l++) {
1839 memset(&lcd[py + l][px], 0xff, 6);
1846 uint8* vram = &ram[gs_addr];
1847 for(int y = 0; y < 64; y++) {
1848 for(int x = 0; x < 60; x++) {
1850 uint8 pat = *vram++;
1851 lcd[y][px + 0] = (pat & 0x80) ? 0xff : 0;
1852 lcd[y][px + 1] = (pat & 0x40) ? 0xff : 0;
1853 lcd[y][px + 2] = (pat & 0x20) ? 0xff : 0;
1854 lcd[y][px + 3] = (pat & 0x10) ? 0xff : 0;
1855 lcd[y][px + 4] = (pat & 0x08) ? 0xff : 0;
1856 lcd[y][px + 5] = (pat & 0x04) ? 0xff : 0;
1857 lcd[y][px + 6] = (pat & 0x02) ? 0xff : 0;
1858 lcd[y][px + 7] = (pat & 0x01) ? 0xff : 0;
1863 for(int i = 0; i < gs_blocks; i++) {
1864 int x = gs_block[i][0];
1865 int y = gs_block[i][1];
1866 if(0 <= x && x < 60 && 0 <= y && y < 8) {
1869 for(int l = 0; l < 8; l++) {
1870 lcd[py + l][px + 0] = ~lcd[py + l][px + 0];
1871 lcd[py + l][px + 1] = ~lcd[py + l][px + 1];
1872 lcd[py + l][px + 2] = ~lcd[py + l][px + 2];
1873 lcd[py + l][px + 3] = ~lcd[py + l][px + 3];
1874 lcd[py + l][px + 4] = ~lcd[py + l][px + 4];
1875 lcd[py + l][px + 5] = ~lcd[py + l][px + 5];
1876 lcd[py + l][px + 6] = ~lcd[py + l][px + 6];
1877 lcd[py + l][px + 7] = ~lcd[py + l][px + 7];
1883 for(int y = 0; y < 64; y++) {
1884 scrntype* dest = emu->screen_buffer(y);
1885 for(int x = 0; x < 480; x++) {
1886 dest[x] = lcd[y][x] ? pd : pb;
1890 for(int y = 0; y < 64; y++) {
1891 scrntype* dest = emu->screen_buffer(y);
1892 for(int x = 0; x < 480; x++) {