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
58 DLL_PREFIX_I struct cur_time_s cur_time;
63 // init external ram disk
64 memset(ext, 0, 0x20000);
65 memset(ext + 0x20000, 0xff, 0x20000);
69 // load external ram disk
70 FILEIO* fio = new FILEIO();
71 if(fio->Fopen(create_local_path(_T("EXTRAM.BIN")), FILEIO_READ_BINARY)) {
72 fio->Fread(ext, 0x20000, 1);
75 if(fio->Fopen(create_local_path(_T("EXT.ROM")), FILEIO_READ_BINARY)) {
76 fio->Fread(ext + 0x20000, 0x20000, 1);
82 cmd_buf = new FIFO(16);
83 rsp_buf = new FIFO(16);
84 key_buf = new FIFO(7);
85 art_buf = new FIFO(BUFFER_SIZE);
88 pd = RGB_COLOR(48, 56, 16);
89 pb = RGB_COLOR(160, 168, 160);
92 get_host_time(&cur_time);
93 onesec_intr = alarm_intr = false;
94 onesec_intr_enb = alarm_intr_enb = kb_intr_enb = true;
95 res_7508 = kb_caps = false;
98 register_frame_event(this);
99 register_event_by_clock(this, EVENT_FRC, 0x60000, true, NULL);
100 register_event_by_clock(this, EVENT_1SEC, CPU_CLOCKS, true, ®ister_id_1sec);
105 // save external ram disk
106 FILEIO* fio = new FILEIO();
107 if(fio->Fopen(create_local_path(_T("EXTRAM.BIN")), FILEIO_WRITE_BINARY)) {
108 fio->Fwrite(ext, 0x20000, 1);
126 bcr = slbcr = isr = ier = bankr = ioctlr = 0;
136 register_id_art = -1;
142 onesec_intr = alarm_intr = false;
143 onesec_intr_enb = alarm_intr_enb = kb_intr_enb = true;
147 void IO::write_signal(int id, uint32_t data, uint32_t mask)
149 if(id == SIG_IO_DREC) {
150 // signal from data recorder
152 bool next = ((data & mask) != 0);
153 if((bcr == 2 && ear && !next) || (bcr == 4 && !ear && next) || (bcr == 6 && ear != next)) {
154 icrb = get_passed_clock(cur_clock) / 6;
160 } else if(id == SIG_IO_ART) {
162 art_buf->write(data & mask);
163 if(rxen && !art_buf->empty() && register_id_art == -1) {
164 register_event(this, EVENT_ART, RECV_DELAY, false, ®ister_id_art);
169 void IO::event_frame()
171 d_beep->write_signal(SIG_BEEP_ON, beep ? 1 : 0, 1);
175 void IO::event_callback(int event_id, int err)
177 if(event_id == EVENT_FRC) {
178 // FRC overflow event
179 cur_clock = get_current_clock();
182 } else if(event_id == EVENT_1SEC) {
184 if(cur_time.initialized) {
185 cur_time.increment();
187 get_host_time(&cur_time); // resync
188 cur_time.initialized = true;
191 if(onesec_intr_enb) {
195 } else if(event_id == EVENT_ART) {
196 // recv from art event
197 if(rxen && !(artsr & RXRDY)) {
198 if(!art_buf->empty()) {
199 artdir = art_buf->read();
201 if(art_buf->empty()) {
209 // if data is still left in buffer, register event for next data
210 if(rxen && !art_buf->empty()) {
211 register_event(this, EVENT_ART, RECV_DELAY, false, ®ister_id_art);
213 register_id_art = -1;
218 void IO::write_io8(uint32_t addr, uint32_t data)
220 switch(addr & 0xff) {
241 d_drec->write_signal(SIG_DATAREC_MIC, data, 1);
242 d_drec->write_signal(SIG_DATAREC_REMOTE, data, 2);
250 d_mem->write_signal(0, data, 0xf0);
252 // dont care EDU,ECA and CKSW now...
267 // FR: dont care, always 72Hz
275 d_tf20->write_signal(SIGNAL_TF20_SIO, data, 0xff);
284 artsr &= ~(PE | OE | FE);
286 txen = ((data & 1) != 0);
287 rxen = ((data & 4) != 0);
288 if(rxen && !art_buf->empty() && register_id_art == -1) {
289 register_event(this, EVENT_ART, RECV_DELAY, false, ®ister_id_art);
294 if((ioctlr & 0x80) != (data & 0x80)) {
301 extar = (extar & 0xffff00) | data;
305 extar = (extar & 0xff00ff) | (data << 8);
309 extar = (extar & 0x00ffff) | ((data & 7) << 16);
313 if(extar < 0x20000) {
316 extar = (extar & 0xffff00) | ((extar + 1) & 0xff);
325 uint32_t IO::read_io8(uint32_t addr)
329 switch(addr & 0xff) {
331 // ICRL.C (latch FRC value)
332 icrc = get_passed_clock(cur_clock) / 6;
336 return (icrc >> 8) & 0xff;
344 return (icrb >> 8) & 0xff;
350 return (bankr & 0xf0) | 8 | 4 | (ear ? 1 : 0); // always rdysio=rdy=true
353 return rec_from_7508();
365 return 0x40 | (artsr & RXRDY ? 8 : 0); // not hand shake mode
368 if(extar < 0x40000) {
371 extar = (extar & 0xffff00) | ((extar + 1) & 0xff);
375 return extcr & ~0x80;
380 uint32_t IO::get_intr_ack()
385 } else if(isr & BIT_ART) {
387 } else if(isr & BIT_ICF) {
389 } else if(isr & BIT_OVF) {
391 } else if(isr & BIT_EXT) {
398 void IO::update_intr()
401 bool next = ((isr & ier & 0x1f) != 0);
402 d_cpu->set_intr_line(next, true, 0);
405 // ----------------------------------------------------------------------------
407 // ----------------------------------------------------------------------------
409 void IO::send_to_7508(uint8_t val)
415 uint8_t cmd = cmd_buf->read_not_remove(0);
425 if((onesec_intr && onesec_intr_enb) || (alarm_intr && alarm_intr_enb) || res_z80 || res_7508) {
427 res |= (onesec_intr && onesec_intr_enb) ? 0x20 : 0;
428 res |= (res_z80 ? 0x10 : 0) | (res_7508 ? 8 : 0);
429 res |= (alarm_intr && alarm_intr_enb) ? 2 : 0;
431 onesec_intr = alarm_intr = res_z80 = res_7508 = false;
432 } else if(key_buf->count()) {
433 res = key_buf->read();
438 // request next interrupt
439 if(key_buf->count() && kb_intr_enb) {
448 kb_rep_spd1 = 42 | 0x80;
449 kb_rep_spd2 = 18 | 0x80;
453 // kb repeat timer 1 set
454 if(cmd_buf->count() == 2) {
456 kb_rep_spd1 = cmd_buf->read();
472 rsp_buf->write(TO_BCD_HI(cur_time.year));
473 rsp_buf->write(TO_BCD_LO(cur_time.year));
474 rsp_buf->write(TO_BCD(cur_time.month));
475 rsp_buf->write(TO_BCD(cur_time.day));
476 rsp_buf->write(TO_BCD(cur_time.hour));
477 rsp_buf->write(TO_BCD(cur_time.minute));
478 rsp_buf->write(TO_BCD(cur_time.second));
479 rsp_buf->write(cur_time.day_of_week);
489 rsp_buf->write(alarm[0]);
490 rsp_buf->write(alarm[1]);
491 rsp_buf->write(alarm[2]);
492 rsp_buf->write(alarm[3]);
493 rsp_buf->write(alarm[4]);
494 rsp_buf->write(alarm[5]);
499 res = 0; // standard keyboard = 0, item keyboard = 0x80
500 res |= 0x60; // serial = 0, cart-printer = 0x20, rs-232c = 0x40, printer = 0x60
501 // res |= 0x30; // serial = 0, cart-printer = 0x10, rs-232c = 0x20, printer = 0x30
502 res |= 0xf; // ascii keyboard
506 // stop key interrupt disable -> kb interrupt on
511 // 1 sec interrupt off
513 onesec_intr_enb = false;
526 // kb repeat timer 2 set
527 if(cmd_buf->count() == 2) {
529 kb_rep_spd2 = cmd_buf->read();
544 if(cmd_buf->count() == 9) {
546 int year10 = cmd_buf->read();
547 int year1 = cmd_buf->read();
548 int month = cmd_buf->read();
549 int day = cmd_buf->read();
550 int hour = cmd_buf->read();
551 int minute = cmd_buf->read();
552 int second = cmd_buf->read();
553 int day_of_week = cmd_buf->read();
555 if((month & 0x0f) == 0 || (day & 0x0f) == 0) {
557 get_host_time(&cur_time);
559 bool changed = false;
560 if((year10 & 0x0f) != 0x0f && (year1 & 0x0f) != 0x0f) {
561 cur_time.year = (year10 & 0x0f) * 10 + (year1 & 0x0f);
562 cur_time.update_year();
565 if((month & 0x0f) != 0x0f) {
566 cur_time.month = FROM_BCD(month & 0x1f);
569 if((day & 0x0f) != 0x0f) {
570 cur_time.day = FROM_BCD(day & 0x3f);
573 if((hour & 0x0f) != 0x0f) {
574 cur_time.hour = FROM_BCD(hour & 0x3f);
577 if((minute & 0x0f) != 0x0f) {
578 cur_time.minute = FROM_BCD(minute & 0x7f);
581 if((second & 0x0f) != 0x0f) {
582 cur_time.second = FROM_BCD(second & 0x7f);
585 // if((day_of_week & 0x0f) != 0x0f) {
586 // cur_time.day_of_week = day_of_week & 0x07;
590 cur_time.update_day_of_week();
592 cancel_event(this, register_id_1sec);
593 register_event_by_clock(this, EVENT_1SEC, CPU_CLOCKS, true, ®ister_id_1sec);
600 if(cmd_buf->count() == 7) {
602 alarm[0] = cmd_buf->read();
603 alarm[1] = cmd_buf->read();
604 alarm[2] = cmd_buf->read();
605 alarm[3] = cmd_buf->read();
606 alarm[4] = cmd_buf->read();
607 alarm[5] = cmd_buf->read();
611 // stop key interrupt enable -> kb interrupt off
616 // 1 sec interrupt on
618 onesec_intr_enb = true;
621 // kb repeat timer 1 read
623 rsp_buf->write(kb_rep_spd1);
628 alarm_intr_enb = false;
631 // kb repeat timer 2 read
633 rsp_buf->write(kb_rep_spd2);
638 alarm_intr_enb = true;
643 this->out_debug_log(_T("unknown cmd %2x\n"), cmd);
647 uint8_t IO::rec_from_7508()
649 return rsp_buf->read();
652 void IO::key_down(int code)
657 update_key(kb_caps ? 0xb4 : 0xa4);
658 update_key(kb_caps ? 0xa4 : 0xb4);
660 update_key(key_tbl[code & 0xff]);
664 void IO::key_up(int code)
667 update_key(0xa3); // break shift
668 } else if(code == 0x11) {
669 update_key(0xa2); // break ctrl
673 void IO::update_key(int code)
680 key_buf->write(code);
682 key_buf->write(code);
686 if(kb_intr_enb || (!kb_intr_enb && code == 0x10)) {
693 // ----------------------------------------------------------------------------
695 // ----------------------------------------------------------------------------
697 void IO::draw_screen()
700 uint8_t* vram = ram + ((vadr & 0xf8) << 8);
701 for(int y = 0; y < 64; y++) {
702 scrntype_t* dest = emu->get_screen_buffer((y - (yoff & 0x3f)) & 0x3f);
703 for(int x = 0; x < 30; x++) {
704 uint8_t pat = *vram++;
705 dest[0] = (pat & 0x80) ? pd : pb;
706 dest[1] = (pat & 0x40) ? pd : pb;
707 dest[2] = (pat & 0x20) ? pd : pb;
708 dest[3] = (pat & 0x10) ? pd : pb;
709 dest[4] = (pat & 0x08) ? pd : pb;
710 dest[5] = (pat & 0x04) ? pd : pb;
711 dest[6] = (pat & 0x02) ? pd : pb;
712 dest[7] = (pat & 0x01) ? pd : pb;
718 for(int y = 0; y < 64; y++) {
719 scrntype_t* dest = emu->get_screen_buffer(y);
720 for(int x = 0; x < 240; x++) {
727 #define STATE_VERSION 1
729 #include "../../statesub.h"
731 void IO::decl_state()
733 enter_decl_state(STATE_VERSION);
735 DECL_STATE_ENTRY_UINT32(cur_clock);
736 DECL_STATE_ENTRY_UINT8(bcr);
737 DECL_STATE_ENTRY_UINT8(slbcr);
738 DECL_STATE_ENTRY_UINT8(isr);
739 DECL_STATE_ENTRY_UINT8(ier);
740 DECL_STATE_ENTRY_UINT8(bankr);
741 DECL_STATE_ENTRY_UINT8(ioctlr);
742 DECL_STATE_ENTRY_UINT32(icrc);
743 DECL_STATE_ENTRY_UINT32(icrb);
744 DECL_STATE_ENTRY_BOOL(ear);
745 DECL_STATE_ENTRY_UINT8(vadr);
746 DECL_STATE_ENTRY_UINT8(yoff);
747 DECL_STATE_ENTRY_FIFO(cmd_buf);
748 DECL_STATE_ENTRY_FIFO(rsp_buf);
749 DECL_STATE_ENTRY_CUR_TIME_T(cur_time);
751 DECL_STATE_ENTRY_INT32(register_id_1sec);
752 DECL_STATE_ENTRY_BOOL(onesec_intr);
753 DECL_STATE_ENTRY_BOOL(onesec_intr_enb);
754 DECL_STATE_ENTRY_BOOL(alarm_intr);
755 DECL_STATE_ENTRY_BOOL(alarm_intr_enb);
756 DECL_STATE_ENTRY_1D_ARRAY(alarm, sizeof(alarm));
757 DECL_STATE_ENTRY_FIFO(key_buf);
758 DECL_STATE_ENTRY_BOOL(kb_intr_enb);
759 DECL_STATE_ENTRY_BOOL(kb_rep_enb);
760 DECL_STATE_ENTRY_BOOL(kb_caps);
761 DECL_STATE_ENTRY_UINT8(kb_rep_spd1);
762 DECL_STATE_ENTRY_UINT8(kb_rep_spd2);
763 DECL_STATE_ENTRY_FIFO(art_buf);
764 DECL_STATE_ENTRY_UINT8(artsr);
765 DECL_STATE_ENTRY_UINT8(artdir);
766 DECL_STATE_ENTRY_BOOL(txen);
767 DECL_STATE_ENTRY_BOOL(rxen);
768 DECL_STATE_ENTRY_BOOL(dsr);
769 DECL_STATE_ENTRY_INT32(register_id_art);
770 DECL_STATE_ENTRY_BOOL(beep);
771 DECL_STATE_ENTRY_BOOL(res_z80);
772 DECL_STATE_ENTRY_BOOL(res_7508);
773 DECL_STATE_ENTRY_1D_ARRAY(ext, sizeof(ext));
774 DECL_STATE_ENTRY_UINT32(extar);
775 DECL_STATE_ENTRY_UINT8(extcr);
781 void IO::save_state(FILEIO* state_fio)
783 if(state_entry != NULL) {
784 state_entry->save_state(state_fio);
786 // state_fio->FputUint32(STATE_VERSION);
787 // state_fio->FputInt32(this_device_id);
789 // state_fio->FputUint32(cur_clock);
790 // state_fio->FputUint8(bcr);
791 // state_fio->FputUint8(slbcr);
792 // state_fio->FputUint8(isr);
793 // state_fio->FputUint8(ier);
794 // state_fio->FputUint8(bankr);
795 // state_fio->FputUint8(ioctlr);
796 // state_fio->FputUint32(icrc);
797 // state_fio->FputUint32(icrb);
798 // state_fio->FputBool(ear);
799 // state_fio->FputUint8(vadr);
800 // state_fio->FputUint8(yoff);
801 // cmd_buf->save_state((void *)state_fio);
802 // rsp_buf->save_state((void *)state_fio);
803 // cur_time.save_state((void *)state_fio);
804 // state_fio->FputInt32(register_id_1sec);
805 // state_fio->FputBool(onesec_intr);
806 // state_fio->FputBool(onesec_intr_enb);
807 // state_fio->FputBool(alarm_intr);
808 // state_fio->FputBool(alarm_intr_enb);
809 // state_fio->Fwrite(alarm, sizeof(alarm), 1);
810 // key_buf->save_state((void *)state_fio);
811 // state_fio->FputBool(kb_intr_enb);
812 // state_fio->FputBool(kb_rep_enb);
813 // state_fio->FputBool(kb_caps);
814 // state_fio->FputUint8(kb_rep_spd1);
815 // state_fio->FputUint8(kb_rep_spd2);
816 // art_buf->save_state((void *)state_fio);
817 // state_fio->FputUint8(artsr);
818 // state_fio->FputUint8(artdir);
819 // state_fio->FputBool(txen);
820 // state_fio->FputBool(rxen);
821 // state_fio->FputBool(dsr);
822 // state_fio->FputInt32(register_id_art);
823 // state_fio->FputBool(beep);
824 // state_fio->FputBool(res_z80);
825 // state_fio->FputBool(res_7508);
826 // state_fio->Fwrite(ext, sizeof(ext), 1);
827 // state_fio->FputUint32(extar);
828 // state_fio->FputUint8(extcr);
831 bool IO::load_state(FILEIO* state_fio)
834 if(state_entry != NULL) {
835 mb = state_entry->load_state(state_fio);
840 // if(state_fio->FgetUint32() != STATE_VERSION) {
843 // if(state_fio->FgetInt32() != this_device_id) {
846 // cur_clock = state_fio->FgetUint32();
847 // bcr = state_fio->FgetUint8();
848 // slbcr = state_fio->FgetUint8();
849 // isr = state_fio->FgetUint8();
850 // ier = state_fio->FgetUint8();
851 // bankr = state_fio->FgetUint8();
852 // ioctlr = state_fio->FgetUint8();
853 // icrc = state_fio->FgetUint32();
854 // icrb = state_fio->FgetUint32();
855 // ear = state_fio->FgetBool();
856 // vadr = state_fio->FgetUint8();
857 // yoff = state_fio->FgetUint8();
858 // if(!cmd_buf->load_state((void *)state_fio)) {
861 // if(!rsp_buf->load_state((void *)state_fio)) {
864 // if(!cur_time.load_state((void *)state_fio)) {
868 // register_id_1sec = state_fio->FgetInt32();
869 // onesec_intr = state_fio->FgetBool();
870 // onesec_intr_enb = state_fio->FgetBool();
871 // alarm_intr = state_fio->FgetBool();
872 // alarm_intr_enb = state_fio->FgetBool();
873 // state_fio->Fread(alarm, sizeof(alarm), 1);
874 // if(!key_buf->load_state((void *)state_fio)) {
877 // kb_intr_enb = state_fio->FgetBool();
878 // kb_rep_enb = state_fio->FgetBool();
879 // kb_caps = state_fio->FgetBool();
880 // kb_rep_spd1 = state_fio->FgetUint8();
881 // kb_rep_spd2 = state_fio->FgetUint8();
882 // if(!art_buf->load_state((void *)state_fio)) {
885 // artsr = state_fio->FgetUint8();
886 // artdir = state_fio->FgetUint8();
887 // txen = state_fio->FgetBool();
888 // rxen = state_fio->FgetBool();
889 // dsr = state_fio->FgetBool();
890 // register_id_art = state_fio->FgetInt32();
891 // beep = state_fio->FgetBool();
892 // res_z80 = state_fio->FgetBool();
893 // res_7508 = state_fio->FgetBool();
894 // state_fio->Fread(ext, sizeof(ext), 1);
895 // extar = state_fio->FgetUint32();
896 // extcr = state_fio->FgetUint8();
900 bool IO::process_state(FILEIO* state_fio, bool loading)
902 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
905 if(!state_fio->StateCheckInt32(this_device_id)) {
908 state_fio->StateUint32(cur_clock);
909 state_fio->StateUint8(bcr);
910 state_fio->StateUint8(slbcr);
911 state_fio->StateUint8(isr);
912 state_fio->StateUint8(ier);
913 state_fio->StateUint8(bankr);
914 state_fio->StateUint8(ioctlr);
915 state_fio->StateUint32(icrc);
916 state_fio->StateUint32(icrb);
917 state_fio->StateBool(ear);
918 state_fio->StateUint8(vadr);
919 state_fio->StateUint8(yoff);
920 if(!cmd_buf->process_state((void *)state_fio, loading)) {
923 if(!rsp_buf->process_state((void *)state_fio, loading)) {
926 if(!cur_time.process_state((void *)state_fio, loading)) {
929 state_fio->StateInt32(register_id_1sec);
930 state_fio->StateBool(onesec_intr);
931 state_fio->StateBool(onesec_intr_enb);
932 state_fio->StateBool(alarm_intr);
933 state_fio->StateBool(alarm_intr_enb);
934 state_fio->StateBuffer(alarm, sizeof(alarm), 1);
935 if(!key_buf->process_state((void *)state_fio, loading)) {
938 state_fio->StateBool(kb_intr_enb);
939 state_fio->StateBool(kb_rep_enb);
940 state_fio->StateBool(kb_caps);
941 state_fio->StateUint8(kb_rep_spd1);
942 state_fio->StateUint8(kb_rep_spd2);
943 if(!art_buf->process_state((void *)state_fio, loading)) {
946 state_fio->StateUint8(artsr);
947 state_fio->StateUint8(artdir);
948 state_fio->StateBool(txen);
949 state_fio->StateBool(rxen);
950 state_fio->StateBool(dsr);
951 state_fio->StateInt32(register_id_art);
952 state_fio->StateBool(beep);
953 state_fio->StateBool(res_z80);
954 state_fio->StateBool(res_7508);
955 state_fio->StateBuffer(ext, sizeof(ext), 1);
956 state_fio->StateUint32(extar);
957 state_fio->StateUint8(extcr);