2 EPSON HC-40 Emulator 'eHC-40'
4 Author : Takeda.Toshiya
12 #include "../datarec.h"
14 #include "../../fifo.h"
24 #define BUFFER_SIZE 0x40000
25 #define RECV_DELAY 100
39 static const int key_tbl[256] = {
40 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x56,0x57,0xff,0xff,0xff,0x71,0xff,0xff,
41 0xb3,0xb2,0xff,0x10,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0xff,
42 0x73,0xff,0xff,0xff,0xff,0x63,0x55,0x65,0x64,0xff,0xff,0xff,0xff,0x80,0x81,0xff,
43 0x52,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x50,0x51,0xff,0xff,0xff,0xff,0xff,0xff,
44 0xff,0x66,0x40,0x76,0x30,0x22,0x31,0x32,0x33,0x27,0x34,0x35,0x36,0x42,0x41,0x60,
45 0x61,0x20,0x23,0x67,0x24,0x26,0x77,0x21,0x75,0x25,0x74,0xff,0xff,0xff,0xff,0xff,
46 0x52,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x50,0x51,0xff,0xff,0xff,0xff,0xff,0xff,
47 0x03,0x04,0x05,0x06,0x07,0xff,0xff,0xff,0xff,0xff,0x01,0x02,0xff,0xff,0xff,0xff,
48 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
49 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
50 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
51 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x70,0x37,0x43,0x53,0x44,0x45,
52 0x62,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
53 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x46,0x72,0x47,0x54,0xff,
54 0xff,0xff,0x72,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
55 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
60 // init external ram disk
61 memset(ext, 0, 0x20000);
62 memset(ext + 0x20000, 0xff, 0x20000);
66 // load external ram disk
67 FILEIO* fio = new FILEIO();
68 if(fio->Fopen(create_local_path(_T("EXTRAM.BIN")), FILEIO_READ_BINARY)) {
69 fio->Fread(ext, 0x20000, 1);
72 if(fio->Fopen(create_local_path(_T("EXT.ROM")), FILEIO_READ_BINARY)) {
73 fio->Fread(ext + 0x20000, 0x20000, 1);
79 cmd_buf = new FIFO(16);
80 rsp_buf = new FIFO(16);
81 key_buf = new FIFO(7);
82 art_buf = new FIFO(BUFFER_SIZE);
85 pd = RGB_COLOR(48, 56, 16);
86 pb = RGB_COLOR(160, 168, 160);
89 get_host_time(&cur_time);
90 onesec_intr = alarm_intr = false;
91 onesec_intr_enb = alarm_intr_enb = kb_intr_enb = true;
92 res_7508 = kb_caps = false;
95 register_frame_event(this);
96 register_event_by_clock(this, EVENT_FRC, 0x60000, true, NULL);
97 register_event_by_clock(this, EVENT_1SEC, CPU_CLOCKS, true, ®ister_id_1sec);
102 // save external ram disk
103 FILEIO* fio = new FILEIO();
104 if(fio->Fopen(create_local_path(_T("EXTRAM.BIN")), FILEIO_WRITE_BINARY)) {
105 fio->Fwrite(ext, 0x20000, 1);
123 bcr = slbcr = isr = ier = bankr = ioctlr = 0;
133 register_id_art = -1;
139 onesec_intr = alarm_intr = false;
140 onesec_intr_enb = alarm_intr_enb = kb_intr_enb = true;
144 void IO::write_signal(int id, uint32_t data, uint32_t mask)
146 if(id == SIG_IO_DREC) {
147 // signal from data recorder
149 bool next = ((data & mask) != 0);
150 if((bcr == 2 && ear && !next) || (bcr == 4 && !ear && next) || (bcr == 6 && ear != next)) {
151 icrb = get_passed_clock(cur_clock) / 6;
157 } else if(id == SIG_IO_ART) {
159 art_buf->write(data & mask);
160 if(rxen && !art_buf->empty() && register_id_art == -1) {
161 register_event(this, EVENT_ART, RECV_DELAY, false, ®ister_id_art);
166 void IO::event_frame()
168 d_beep->write_signal(SIG_BEEP_ON, beep ? 1 : 0, 1);
172 void IO::event_callback(int event_id, int err)
174 if(event_id == EVENT_FRC) {
175 // FRC overflow event
176 cur_clock = get_current_clock();
179 } else if(event_id == EVENT_1SEC) {
181 if(cur_time.initialized) {
182 cur_time.increment();
184 get_host_time(&cur_time); // resync
185 cur_time.initialized = true;
188 if(onesec_intr_enb) {
192 } else if(event_id == EVENT_ART) {
193 // recv from art event
194 if(rxen && !(artsr & RXRDY)) {
195 if(!art_buf->empty()) {
196 artdir = art_buf->read();
198 if(art_buf->empty()) {
206 // if data is still left in buffer, register event for next data
207 if(rxen && !art_buf->empty()) {
208 register_event(this, EVENT_ART, RECV_DELAY, false, ®ister_id_art);
210 register_id_art = -1;
215 void IO::write_io8(uint32_t addr, uint32_t data)
217 switch(addr & 0xff) {
238 d_drec->write_signal(SIG_DATAREC_MIC, data, 1);
239 d_drec->write_signal(SIG_DATAREC_REMOTE, data, 2);
247 d_mem->write_signal(0, data, 0xf0);
249 // dont care EDU,ECA and CKSW now...
264 // FR: dont care, always 72Hz
272 d_tf20->write_signal(SIGNAL_TF20_SIO, data, 0xff);
281 artsr &= ~(PE | OE | FE);
283 txen = ((data & 1) != 0);
284 rxen = ((data & 4) != 0);
285 if(rxen && !art_buf->empty() && register_id_art == -1) {
286 register_event(this, EVENT_ART, RECV_DELAY, false, ®ister_id_art);
291 if((ioctlr & 0x80) != (data & 0x80)) {
298 extar = (extar & 0xffff00) | data;
302 extar = (extar & 0xff00ff) | (data << 8);
306 extar = (extar & 0x00ffff) | ((data & 7) << 16);
310 if(extar < 0x20000) {
313 extar = (extar & 0xffff00) | ((extar + 1) & 0xff);
322 uint32_t IO::read_io8(uint32_t addr)
326 switch(addr & 0xff) {
328 // ICRL.C (latch FRC value)
329 icrc = get_passed_clock(cur_clock) / 6;
333 return (icrc >> 8) & 0xff;
341 return (icrb >> 8) & 0xff;
347 return (bankr & 0xf0) | 8 | 4 | (ear ? 1 : 0); // always rdysio=rdy=true
350 return rec_from_7508();
362 return 0x40 | (artsr & RXRDY ? 8 : 0); // not hand shake mode
365 if(extar < 0x40000) {
368 extar = (extar & 0xffff00) | ((extar + 1) & 0xff);
372 return extcr & ~0x80;
377 uint32_t IO::get_intr_ack()
382 } else if(isr & BIT_ART) {
384 } else if(isr & BIT_ICF) {
386 } else if(isr & BIT_OVF) {
388 } else if(isr & BIT_EXT) {
395 void IO::update_intr()
398 bool next = ((isr & ier & 0x1f) != 0);
399 d_cpu->set_intr_line(next, true, 0);
402 // ----------------------------------------------------------------------------
404 // ----------------------------------------------------------------------------
406 void IO::send_to_7508(uint8_t val)
412 uint8_t cmd = cmd_buf->read_not_remove(0);
422 if((onesec_intr && onesec_intr_enb) || (alarm_intr && alarm_intr_enb) || res_z80 || res_7508) {
424 res |= (onesec_intr && onesec_intr_enb) ? 0x20 : 0;
425 res |= (res_z80 ? 0x10 : 0) | (res_7508 ? 8 : 0);
426 res |= (alarm_intr && alarm_intr_enb) ? 2 : 0;
428 onesec_intr = alarm_intr = res_z80 = res_7508 = false;
429 } else if(key_buf->count()) {
430 res = key_buf->read();
435 // request next interrupt
436 if(key_buf->count() && kb_intr_enb) {
445 kb_rep_spd1 = 42 | 0x80;
446 kb_rep_spd2 = 18 | 0x80;
450 // kb repeat timer 1 set
451 if(cmd_buf->count() == 2) {
453 kb_rep_spd1 = cmd_buf->read();
469 rsp_buf->write(TO_BCD_HI(cur_time.year));
470 rsp_buf->write(TO_BCD_LO(cur_time.year));
471 rsp_buf->write(TO_BCD(cur_time.month));
472 rsp_buf->write(TO_BCD(cur_time.day));
473 rsp_buf->write(TO_BCD(cur_time.hour));
474 rsp_buf->write(TO_BCD(cur_time.minute));
475 rsp_buf->write(TO_BCD(cur_time.second));
476 rsp_buf->write(cur_time.day_of_week);
486 rsp_buf->write(alarm[0]);
487 rsp_buf->write(alarm[1]);
488 rsp_buf->write(alarm[2]);
489 rsp_buf->write(alarm[3]);
490 rsp_buf->write(alarm[4]);
491 rsp_buf->write(alarm[5]);
496 res = 0; // standard keyboard = 0, item keyboard = 0x80
497 res |= 0x60; // serial = 0, cart-printer = 0x20, rs-232c = 0x40, printer = 0x60
498 // res |= 0x30; // serial = 0, cart-printer = 0x10, rs-232c = 0x20, printer = 0x30
499 res |= 0xf; // ascii keyboard
503 // stop key interrupt disable -> kb interrupt on
508 // 1 sec interrupt off
510 onesec_intr_enb = false;
523 // kb repeat timer 2 set
524 if(cmd_buf->count() == 2) {
526 kb_rep_spd2 = cmd_buf->read();
541 if(cmd_buf->count() == 9) {
543 int year10 = cmd_buf->read();
544 int year1 = cmd_buf->read();
545 int month = cmd_buf->read();
546 int day = cmd_buf->read();
547 int hour = cmd_buf->read();
548 int minute = cmd_buf->read();
549 int second = cmd_buf->read();
550 int day_of_week = cmd_buf->read();
552 if((month & 0x0f) == 0 || (day & 0x0f) == 0) {
554 get_host_time(&cur_time);
556 bool changed = false;
557 if((year10 & 0x0f) != 0x0f && (year1 & 0x0f) != 0x0f) {
558 cur_time.year = (year10 & 0x0f) * 10 + (year1 & 0x0f);
559 cur_time.update_year();
562 if((month & 0x0f) != 0x0f) {
563 cur_time.month = FROM_BCD(month & 0x1f);
566 if((day & 0x0f) != 0x0f) {
567 cur_time.day = FROM_BCD(day & 0x3f);
570 if((hour & 0x0f) != 0x0f) {
571 cur_time.hour = FROM_BCD(hour & 0x3f);
574 if((minute & 0x0f) != 0x0f) {
575 cur_time.minute = FROM_BCD(minute & 0x7f);
578 if((second & 0x0f) != 0x0f) {
579 cur_time.second = FROM_BCD(second & 0x7f);
582 // if((day_of_week & 0x0f) != 0x0f) {
583 // cur_time.day_of_week = day_of_week & 0x07;
587 cur_time.update_day_of_week();
589 cancel_event(this, register_id_1sec);
590 register_event_by_clock(this, EVENT_1SEC, CPU_CLOCKS, true, ®ister_id_1sec);
597 if(cmd_buf->count() == 7) {
599 alarm[0] = cmd_buf->read();
600 alarm[1] = cmd_buf->read();
601 alarm[2] = cmd_buf->read();
602 alarm[3] = cmd_buf->read();
603 alarm[4] = cmd_buf->read();
604 alarm[5] = cmd_buf->read();
608 // stop key interrupt enable -> kb interrupt off
613 // 1 sec interrupt on
615 onesec_intr_enb = true;
618 // kb repeat timer 1 read
620 rsp_buf->write(kb_rep_spd1);
625 alarm_intr_enb = false;
628 // kb repeat timer 2 read
630 rsp_buf->write(kb_rep_spd2);
635 alarm_intr_enb = true;
640 emu->out_debug_log(_T("unknown cmd %2x\n"), cmd);
644 uint8_t IO::rec_from_7508()
646 return rsp_buf->read();
649 void IO::key_down(int code)
654 update_key(kb_caps ? 0xb4 : 0xa4);
655 update_key(kb_caps ? 0xa4 : 0xb4);
657 update_key(key_tbl[code & 0xff]);
661 void IO::key_up(int code)
664 update_key(0xa3); // break shift
665 } else if(code == 0x11) {
666 update_key(0xa2); // break ctrl
670 void IO::update_key(int code)
677 key_buf->write(code);
679 key_buf->write(code);
683 if(kb_intr_enb || (!kb_intr_enb && code == 0x10)) {
690 // ----------------------------------------------------------------------------
692 // ----------------------------------------------------------------------------
694 void IO::draw_screen()
697 uint8_t* vram = ram + ((vadr & 0xf8) << 8);
698 for(int y = 0; y < 64; y++) {
699 scrntype_t* dest = emu->get_screen_buffer((y - (yoff & 0x3f)) & 0x3f);
700 for(int x = 0; x < 30; x++) {
701 uint8_t pat = *vram++;
702 dest[0] = (pat & 0x80) ? pd : pb;
703 dest[1] = (pat & 0x40) ? pd : pb;
704 dest[2] = (pat & 0x20) ? pd : pb;
705 dest[3] = (pat & 0x10) ? pd : pb;
706 dest[4] = (pat & 0x08) ? pd : pb;
707 dest[5] = (pat & 0x04) ? pd : pb;
708 dest[6] = (pat & 0x02) ? pd : pb;
709 dest[7] = (pat & 0x01) ? pd : pb;
715 for(int y = 0; y < 64; y++) {
716 scrntype_t* dest = emu->get_screen_buffer(y);
717 for(int x = 0; x < 240; x++) {
724 #define STATE_VERSION 1
726 void IO::save_state(FILEIO* state_fio)
728 state_fio->FputUint32(STATE_VERSION);
729 state_fio->FputInt32(this_device_id);
731 state_fio->FputUint32(cur_clock);
732 state_fio->FputUint8(bcr);
733 state_fio->FputUint8(slbcr);
734 state_fio->FputUint8(isr);
735 state_fio->FputUint8(ier);
736 state_fio->FputUint8(bankr);
737 state_fio->FputUint8(ioctlr);
738 state_fio->FputUint32(icrc);
739 state_fio->FputUint32(icrb);
740 state_fio->FputBool(ear);
741 state_fio->FputUint8(vadr);
742 state_fio->FputUint8(yoff);
743 cmd_buf->save_state((void *)state_fio);
744 rsp_buf->save_state((void *)state_fio);
745 cur_time.save_state((void *)state_fio);
746 state_fio->FputInt32(register_id_1sec);
747 state_fio->FputBool(onesec_intr);
748 state_fio->FputBool(onesec_intr_enb);
749 state_fio->FputBool(alarm_intr);
750 state_fio->FputBool(alarm_intr_enb);
751 state_fio->Fwrite(alarm, sizeof(alarm), 1);
752 key_buf->save_state((void *)state_fio);
753 state_fio->FputBool(kb_intr_enb);
754 state_fio->FputBool(kb_rep_enb);
755 state_fio->FputBool(kb_caps);
756 state_fio->FputUint8(kb_rep_spd1);
757 state_fio->FputUint8(kb_rep_spd2);
758 art_buf->save_state((void *)state_fio);
759 state_fio->FputUint8(artsr);
760 state_fio->FputUint8(artdir);
761 state_fio->FputBool(txen);
762 state_fio->FputBool(rxen);
763 state_fio->FputBool(dsr);
764 state_fio->FputInt32(register_id_art);
765 state_fio->FputBool(beep);
766 state_fio->FputBool(res_z80);
767 state_fio->FputBool(res_7508);
768 state_fio->Fwrite(ext, sizeof(ext), 1);
769 state_fio->FputUint32(extar);
770 state_fio->FputUint8(extcr);
773 bool IO::load_state(FILEIO* state_fio)
775 if(state_fio->FgetUint32() != STATE_VERSION) {
778 if(state_fio->FgetInt32() != this_device_id) {
781 cur_clock = state_fio->FgetUint32();
782 bcr = state_fio->FgetUint8();
783 slbcr = state_fio->FgetUint8();
784 isr = state_fio->FgetUint8();
785 ier = state_fio->FgetUint8();
786 bankr = state_fio->FgetUint8();
787 ioctlr = state_fio->FgetUint8();
788 icrc = state_fio->FgetUint32();
789 icrb = state_fio->FgetUint32();
790 ear = state_fio->FgetBool();
791 vadr = state_fio->FgetUint8();
792 yoff = state_fio->FgetUint8();
793 if(!cmd_buf->load_state((void *)state_fio)) {
796 if(!rsp_buf->load_state((void *)state_fio)) {
799 if(!cur_time.load_state((void *)state_fio)) {
803 register_id_1sec = state_fio->FgetInt32();
804 onesec_intr = state_fio->FgetBool();
805 onesec_intr_enb = state_fio->FgetBool();
806 alarm_intr = state_fio->FgetBool();
807 alarm_intr_enb = state_fio->FgetBool();
808 state_fio->Fread(alarm, sizeof(alarm), 1);
809 if(!key_buf->load_state((void *)state_fio)) {
812 kb_intr_enb = state_fio->FgetBool();
813 kb_rep_enb = state_fio->FgetBool();
814 kb_caps = state_fio->FgetBool();
815 kb_rep_spd1 = state_fio->FgetUint8();
816 kb_rep_spd2 = state_fio->FgetUint8();
817 if(!art_buf->load_state((void *)state_fio)) {
820 artsr = state_fio->FgetUint8();
821 artdir = state_fio->FgetUint8();
822 txen = state_fio->FgetBool();
823 rxen = state_fio->FgetBool();
824 dsr = state_fio->FgetBool();
825 register_id_art = state_fio->FgetInt32();
826 beep = state_fio->FgetBool();
827 res_z80 = state_fio->FgetBool();
828 res_7508 = state_fio->FgetBool();
829 state_fio->Fread(ext, sizeof(ext), 1);
830 extar = state_fio->FgetUint32();
831 extcr = state_fio->FgetUint8();