--- /dev/null
+/*\r
+ EPSON HC-80 Emulator 'eHC-80'\r
+\r
+ Author : Takeda.Toshiya\r
+ Date : 2008.03.14 -\r
+\r
+ [ i/o ]\r
+*/\r
+\r
+#include "io.h"\r
+#include "../beep.h"\r
+#include "../tf20.h"\r
+#include "../../fifo.h"\r
+#include "../../fileio.h"\r
+\r
+//#define OUT_CMD_LOG\r
+\r
+// interrupt bits\r
+#define BIT_7508 0x01\r
+#define BIT_8251 0x02\r
+#define BIT_CD 0x04\r
+#define BIT_ICF 0x08\r
+#define BIT_OVF 0x10\r
+#define BIT_EXT 0x20\r
+\r
+// 6303\r
+#define BIT_OBF 0x01\r
+#define BIT_IBF 0x02\r
+#define BIT_F1 0x08\r
+#define RCD00 0\r
+#define RCD01 1\r
+#define RCD02 2\r
+#define RCD03 3\r
+#define RCD04 11\r
+#define RCD05 12\r
+#define RCD06 13\r
+#define RCD07 41\r
+#define RCD08 42\r
+#define RCD09 43\r
+#define RCD10 44\r
+#define RCD11 45\r
+#define RCD11_1 46\r
+#define RCD12 61\r
+#define RCD13 62\r
+#define RCD14 63\r
+#define RCD15 71\r
+\r
+// TF-20\r
+#define DID_FIRST 0x31\r
+#define DS_SEL 0x05\r
+#define SOH 0x01\r
+#define STX 0x02\r
+#define EOT 0x04\r
+#define ACK 0x06\r
+\r
+// intelligent ram disk\r
+#define IRAMDISK_WAIT 1\r
+#define IRAMDISK_IN 0\r
+#define IRAMDISK_OUT 1\r
+\r
+#define EVENT_FRC 0\r
+#define EVENT_1SEC 1\r
+#define EVENT_6303 2\r
+\r
+static const int key_tbl[256] = {\r
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x56,0x57,0xff,0xff,0xff,0x71,0xff,0xff,\r
+ 0xb3,0xb2,0xff,0x10,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0xff,\r
+ 0x73,0xff,0xff,0xff,0xff,0x63,0x55,0x65,0x64,0xff,0xff,0xff,0xff,0x80,0x81,0xff,\r
+ 0x52,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x50,0x51,0xff,0xff,0xff,0xff,0xff,0xff,\r
+ 0xff,0x66,0x40,0x76,0x30,0x22,0x31,0x32,0x33,0x27,0x34,0x35,0x36,0x42,0x41,0x60,\r
+ 0x61,0x20,0x23,0x67,0x24,0x26,0x77,0x21,0x75,0x25,0x74,0xff,0xff,0xff,0xff,0xff,\r
+ 0x52,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x50,0x51,0xff,0xff,0xff,0xff,0xff,0xff,\r
+ 0x03,0x04,0x05,0x06,0x07,0xff,0xff,0xff,0xff,0xff,0x01,0x02,0xff,0xff,0xff,0xff,\r
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,\r
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,\r
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,\r
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x70,0x37,0x43,0x53,0x44,0x45,\r
+ 0x62,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,\r
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x46,0x72,0x47,0x54,0xff,\r
+ 0xff,0xff,0x72,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,\r
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff\r
+};\r
+\r
+static const uint8 dot_tbl[8] = {\r
+ 0x80, 0x40, 0x20, 0x10, 8, 4, 2, 1\r
+};\r
+\r
+void IO::initialize()\r
+{\r
+ // config\r
+ device_type = config.device_type;\r
+ \r
+ // init ram and external ram disk\r
+ memset(ram, 0, sizeof(ram));\r
+ memset(ext, 0, 0x20000);\r
+ memset(ext + 0x20000, 0xff, 0x20000);\r
+ extar = 0;\r
+ extcr = 0;\r
+ \r
+ // load images\r
+ FILEIO* fio = new FILEIO();\r
+ if(fio->Fopen(emu->bios_path(_T("BASIC.ROM")), FILEIO_READ_BINARY)) {\r
+ fio->Fread(basic, 0x4000, 1);\r
+ memcpy(basic + 0x4000, basic, 0x4000);\r
+ fio->Fread(basic + 0x4000, 0x4000, 1);\r
+ fio->Fclose();\r
+ }\r
+ if(fio->Fopen(emu->bios_path(_T("UTIL.ROM")), FILEIO_READ_BINARY)) {\r
+ fio->Fread(util, 0x4000, 1);\r
+ memcpy(util + 0x4000, util, 0x4000);\r
+ fio->Fread(util + 0x4000, 0x4000, 1);\r
+ fio->Fclose();\r
+ }\r
+ if(fio->Fopen(emu->bios_path(_T("VRAM.BIN")), FILEIO_READ_BINARY)) {\r
+ fio->Fread(ram + 0x8000, 0x1800, 1);\r
+ fio->Fclose();\r
+ }\r
+ if(fio->Fopen(emu->bios_path(_T("EXTRAM.BIN")), FILEIO_READ_BINARY)) {\r
+ fio->Fread(ext, 0x20000, 1);\r
+ fio->Fclose();\r
+ }\r
+ if(fio->Fopen(emu->bios_path(_T("INTRAM.BIN")), FILEIO_READ_BINARY)) {\r
+ fio->Fread(iramdisk_sectors, sizeof(iramdisk_sectors), 1);\r
+ fio->Fclose();\r
+ }\r
+ if(fio->Fopen(emu->bios_path(_T("EXT.ROM")), FILEIO_READ_BINARY)) {\r
+ fio->Fread(ext + 0x20000, 0x20000, 1);\r
+ fio->Fclose();\r
+ }\r
+ if(fio->Fopen(emu->bios_path(_T("FONT.ROM")), FILEIO_READ_BINARY)) {\r
+ fio->Fread(font, sizeof(font), 1);\r
+ fio->Fclose();\r
+ }\r
+ delete fio;\r
+ \r
+ // init sub cpu\r
+ cmd6303_buf = new FIFO(1024);\r
+ rsp6303_buf = new FIFO(1024);\r
+ tf20_buf = new FIFO(1024);\r
+ \r
+ cmd7508_buf = new FIFO(16);\r
+ rsp7508_buf = new FIFO(16);\r
+ key_buf = new FIFO(7);\r
+ \r
+ // set pallete\r
+ pd = RGB_COLOR(48, 56, 16);\r
+ pb = RGB_COLOR(160, 168, 160);\r
+ \r
+ // init 7508\r
+ emu->get_host_time(&cur_time);\r
+ onesec_intr = alarm_intr = false;\r
+ onesec_intr_enb = alarm_intr_enb = kb_intr_enb = true;\r
+ res_7508 = kb_caps = false;\r
+ \r
+ // register events\r
+ register_frame_event(this);\r
+ register_event_by_clock(this, EVENT_FRC, 0x40000, true, NULL);\r
+ register_event_by_clock(this, EVENT_1SEC, CPU_CLOCKS, true, ®ister_id);\r
+ register_event_by_clock(this, EVENT_6303, 100, true, NULL);\r
+}\r
+\r
+void IO::release()\r
+{\r
+ // save external ram disk\r
+ FILEIO* fio = new FILEIO();\r
+ if(fio->Fopen(emu->bios_path(_T("VRAM.BIN")), FILEIO_WRITE_BINARY)) {\r
+ fio->Fwrite(ram + 0x8000, 0x1800, 1);\r
+ fio->Fclose();\r
+ }\r
+ if(fio->Fopen(emu->bios_path(_T("EXTRAM.BIN")), FILEIO_WRITE_BINARY)) {\r
+ fio->Fwrite(ext, 0x20000, 1);\r
+ fio->Fclose();\r
+ }\r
+ if(fio->Fopen(emu->bios_path(_T("INTRAM.BIN")), FILEIO_WRITE_BINARY)) {\r
+ fio->Fwrite(iramdisk_sectors, sizeof(iramdisk_sectors), 1);\r
+ fio->Fclose();\r
+ }\r
+ delete fio;\r
+ \r
+ cmd6303_buf->release();\r
+ delete cmd6303_buf;\r
+ rsp6303_buf->release();\r
+ delete rsp6303_buf;\r
+ tf20_buf->release();\r
+ delete tf20_buf;\r
+ \r
+ cmd7508_buf->release();\r
+ delete cmd7508_buf;\r
+ rsp7508_buf->release();\r
+ delete rsp7508_buf;\r
+ key_buf->release();\r
+ delete key_buf;\r
+}\r
+\r
+void IO::reset()\r
+{\r
+ // reset gapnit\r
+ bcr = slbcr = isr = ier = ioctlr = 0;\r
+ icrc = icrb = 0;\r
+ ear = beep = false;\r
+ res_z80 = true;\r
+ key_buf->clear();\r
+ \r
+ // reset 6303\r
+ psr = 0;\r
+ cs_addr = 0x8100;\r
+ gs_addr = 0x9500;\r
+ lcd_on = true;\r
+ scr_mode = 1;\r
+ num_lines = 0;\r
+ flash_block = 0;\r
+ cs_blocks = gs_blocks = 0;\r
+ memset(cs_block, 0, sizeof(cs_block));\r
+ memset(gs_block, 0, sizeof(gs_block));\r
+ memset(udgc, 0, sizeof(udgc));\r
+ wnd_ptr_x = wnd_ptr_y = 0;\r
+ blink = 0;\r
+ \r
+ // reset intelligent ram disk\r
+ iramdisk_count = 0;\r
+ iramdisk_ptr = iramdisk_buf;\r
+}\r
+\r
+void IO::sysreset()\r
+{\r
+ // reset 7508\r
+ onesec_intr = alarm_intr = false;\r
+ onesec_intr_enb = alarm_intr_enb = kb_intr_enb = true;\r
+ res_7508 = true;\r
+}\r
+\r
+void IO::write_signal(int id, uint32 data, uint32 mask)\r
+{\r
+ if(id == SIG_IO_RXRDY) {\r
+ // notify rxrdy is changed from i8251\r
+ if(data & mask) {\r
+ isr |= BIT_8251;\r
+ } else {\r
+ isr &= ~BIT_8251;\r
+ }\r
+ update_intr();\r
+ } else if(id == SIG_IO_BARCODE) {\r
+ // signal from barcode reader\r
+ if(!slbcr) {\r
+ bool next = ((data & mask) != 0);\r
+ if((bcr == 2 && ear && !next) || (bcr == 4 && !ear && next) || (bcr == 6 && ear != next)) {\r
+ icrb = passed_clock(cur_clock) / 4;\r
+ isr |= BIT_ICF;\r
+ update_intr();\r
+ }\r
+ ear = next;\r
+ }\r
+ } else if(id == SIG_IO_TF20) {\r
+ // recv from tf20\r
+ tf20_buf->write(data);\r
+ }\r
+}\r
+\r
+void IO::event_frame()\r
+{\r
+ d_beep->write_signal(SIG_BEEP_ON, beep ? 1 : 0, 1);\r
+ beep = false;\r
+ blink++;\r
+}\r
+\r
+void IO::event_callback(int event_id, int err)\r
+{\r
+ if(event_id == EVENT_FRC) {\r
+ // FRC overflow event\r
+ cur_clock = current_clock();\r
+ isr |= BIT_OVF;\r
+ update_intr();\r
+ } else if(event_id == EVENT_1SEC) {\r
+ // update rtc\r
+ if(cur_time.initialized) {\r
+ cur_time.increment();\r
+ } else {\r
+ emu->get_host_time(&cur_time); // resync\r
+ cur_time.initialized = true;\r
+ }\r
+ onesec_intr = true;\r
+ if(onesec_intr_enb) {\r
+ isr |= BIT_7508;\r
+ update_intr();\r
+ }\r
+ } else if(event_id == EVENT_6303) {\r
+ // communicate between z80 and 6303\r
+ if(psr & BIT_OBF) {\r
+ psr &= ~BIT_OBF;\r
+ process_6303();\r
+ }\r
+ if(!rsp6303_buf->empty()) {\r
+ psr |= BIT_IBF;\r
+ }\r
+ }\r
+}\r
+\r
+void IO::write_io8(uint32 addr, uint32 data)\r
+{\r
+ //emu->out_debug_log(_T("OUT %2x,%2x\n"), addr & 0xff, data);\r
+ switch(addr & 0xff) {\r
+ case 0x00:\r
+ // CTLR1\r
+ bcr = data & 6;\r
+ d_mem->write_signal(0, data, 1);\r
+ break;\r
+ case 0x01:\r
+ // CMDR\r
+ if(data & 4) {\r
+ isr &= ~BIT_OVF;\r
+ update_intr();\r
+ }\r
+ //if(data & 2) {\r
+ // rdysio = false;\r
+ //}\r
+ //if(data & 1) {\r
+ // rdysio = true;\r
+ //}\r
+ break;\r
+ case 0x02:\r
+ // CTLR2\r
+ break;\r
+ case 0x04:\r
+ // IER\r
+ ier = data;\r
+ break;\r
+ case 0x06:\r
+ // SIOR\r
+ send_to_7508(data);\r
+ break;\r
+ case 0x0c:\r
+ // 8251 data write\r
+ d_sio->write_io8(0, data);\r
+ break;\r
+ case 0x0d:\r
+ // 8251 command write\r
+ d_sio->write_io8(1, data);\r
+ break;\r
+ case 0x0e:\r
+ // 6303 send data\r
+ cmd6303_buf->write(data);\r
+ psr |= BIT_OBF;\r
+#ifdef OUT_CMD_LOG\r
+ emu->out_debug_log(_T("%4x\tDAT %2x\n"), get_cpu_pc(0), data);\r
+#endif\r
+ break;\r
+ case 0x0f:\r
+ // 6303 send command\r
+ cmd6303 = data;\r
+ psr |= BIT_OBF;\r
+#ifdef OUT_CMD_LOG\r
+ emu->out_debug_log(_T("\n%4x\tCMD %2x\n"), vm->get_cpu_pc(), data);\r
+#endif\r
+ break;\r
+ case 0x80:\r
+ if(device_type == 1) {\r
+ iramdisk_write_data(data);\r
+ }\r
+ break;\r
+ case 0x81:\r
+ if(device_type == 1) {\r
+ iramdisk_write_cmd(data);\r
+ }\r
+ break;\r
+ case 0x90:\r
+ // EXTAR\r
+ if(device_type == 2) {\r
+ extar = (extar & 0xffff00) | data;\r
+ }\r
+ break;\r
+ case 0x91:\r
+ // EXTAR\r
+ if(device_type == 2) {\r
+ extar = (extar & 0xff00ff) | (data << 8);\r
+ }\r
+ break;\r
+ case 0x92:\r
+ // EXTAR\r
+ if(device_type == 2) {\r
+ extar = (extar & 0x00ffff) | ((data & 7) << 16);\r
+ }\r
+ break;\r
+ case 0x93:\r
+ // EXTOR\r
+ if(device_type == 2) {\r
+ if(extar < 0x20000) {\r
+ ext[extar] = data;\r
+ }\r
+ extar = (extar & 0xffff00) | ((extar + 1) & 0xff);\r
+ }\r
+ break;\r
+ case 0x94:\r
+ // EXTCR\r
+ if(device_type == 2) {\r
+ extcr = data;\r
+ }\r
+ break;\r
+ }\r
+}\r
+\r
+uint32 IO::read_io8(uint32 addr)\r
+{\r
+ uint32 val = 0xff;\r
+// emu->out_debug_log(_T("IN %2x\n"), addr & 0xff);\r
+ \r
+ switch(addr & 0xff) {\r
+ case 0x00:\r
+ // ICRL.C (latch FRC value)\r
+ icrc = passed_clock(cur_clock) / 4;\r
+ return icrc & 0xff;\r
+ case 0x01:\r
+ // ICRH.C\r
+ return (icrc >> 8) & 0xff;\r
+ case 0x02:\r
+ // ICRL.B\r
+ return icrb & 0xff;\r
+ case 0x03:\r
+ // ICRH.B\r
+ isr &= ~BIT_ICF;\r
+ update_intr();\r
+ return (icrb >> 8) & 0xff;\r
+ case 0x04:\r
+ // ISR\r
+ return isr;\r
+ case 0x05:\r
+ // STR\r
+ return 8 | 4 | (ear ? 1 : 0); // always rdysio=rdy=true\r
+ case 0x06:\r
+ // SIOR\r
+ return rec_from_7508();\r
+ case 0x0c:\r
+ // 8251 data read\r
+ isr &= ~BIT_8251;\r
+ update_intr();\r
+ return d_sio->read_io8(0);\r
+ case 0x0d:\r
+ // 8251 status read\r
+ return d_sio->read_io8(1);\r
+ case 0x0e:\r
+ // 6303 status\r
+ return psr;\r
+ case 0x0f:\r
+ // 6303 recv data\r
+ val = rsp6303_buf->read();\r
+ psr &= ~BIT_IBF;\r
+ if(!rsp6303_buf->empty()) {\r
+ psr &= ~BIT_F1;\r
+ }\r
+#ifdef OUT_CMD_LOG\r
+ emu->out_debug_log(_T("%4x\tRCV %2x\n"), vm->get_cpu_pc(), val);\r
+#endif\r
+ return val;\r
+ case 0x80:\r
+ if(device_type == 1) {\r
+ return iramdisk_read_data();\r
+ }\r
+ return 0xff;\r
+ case 0x81:\r
+ if(device_type == 1) {\r
+ return iramdisk_read_stat();\r
+ }\r
+ return 0xff;\r
+ case 0x93:\r
+ // EXTIR\r
+ if(device_type == 2) {\r
+ if(extar < 0x40000) {\r
+ val = ext[extar];\r
+ }\r
+ extar = (extar & 0xffff00) | ((extar + 1) & 0xff);\r
+ return val;\r
+ }\r
+ return 0xff;\r
+ case 0x94:\r
+ // EXTSR\r
+ if(device_type == 2) {\r
+ return extcr & ~0x80;\r
+ }\r
+ return 0xff;\r
+ }\r
+ return 0xff;\r
+}\r
+\r
+uint32 IO::intr_ack()\r
+{\r
+ if(isr & BIT_7508) {\r
+ isr &= ~BIT_7508;\r
+ return 0xf0;\r
+ } else if(isr & BIT_8251) {\r
+ return 0xf2;\r
+ } else if(isr & BIT_CD) {\r
+ return 0xf4;\r
+ } else if(isr & BIT_ICF) {\r
+ return 0xf6;\r
+ } else if(isr & BIT_OVF) {\r
+ return 0xf8;\r
+ } else if(isr & BIT_EXT) {\r
+ return 0xfa;\r
+ }\r
+ // unknown\r
+ return 0xff;\r
+}\r
+\r
+void IO::update_intr()\r
+{\r
+ // set int signal\r
+ bool next = ((isr & ier & 0x3f) != 0);\r
+ d_cpu->set_intr_line(next, true, 0);\r
+}\r
+\r
+// ----------------------------------------------------------------------------\r
+// 7508\r
+// ----------------------------------------------------------------------------\r
+\r
+void IO::send_to_7508(uint8 val)\r
+{\r
+ int res;\r
+ \r
+ // process command\r
+ cmd7508_buf->write(val);\r
+ uint8 cmd = cmd7508_buf->read_not_remove(0);\r
+ \r
+ switch(cmd) {\r
+ case 0x01:\r
+ // power off\r
+ cmd7508_buf->read();\r
+ break;\r
+ case 0x02:\r
+ // status / key\r
+ cmd7508_buf->read();\r
+ if((onesec_intr && onesec_intr_enb) || (alarm_intr && alarm_intr_enb) || res_z80 || res_7508) {\r
+ res = 0xc1;\r
+ res |= (onesec_intr && onesec_intr_enb) ? 0x20 : 0;\r
+ res |= (res_z80 ? 0x10 : 0) | (res_7508 ? 8 : 0);\r
+ res |= (alarm_intr && alarm_intr_enb) ? 2 : 0;\r
+ // clear interrupt\r
+ onesec_intr = alarm_intr = res_z80 = res_7508 = false;\r
+ } else if(key_buf->count()) {\r
+ res = key_buf->read();\r
+ } else {\r
+ res = 0xbf;\r
+ }\r
+ rsp7508_buf->write(res);\r
+ // request next interrupt\r
+ if(key_buf->count() && kb_intr_enb) {\r
+ isr |= BIT_7508;\r
+ update_intr();\r
+ }\r
+ break;\r
+ case 0x03:\r
+ // kb reset\r
+ cmd7508_buf->read();\r
+ key_buf->clear();\r
+ kb_rep_spd1 = 42 | 0x80;\r
+ kb_rep_spd2 = 18 | 0x80;\r
+ kb_intr_enb = true;\r
+ break;\r
+ case 0x04:\r
+ // kb repeat timer 1 set\r
+ if(cmd7508_buf->count() == 2) {\r
+ cmd7508_buf->read();\r
+ kb_rep_spd1 = cmd7508_buf->read();\r
+ }\r
+ break;\r
+ case 0x05:\r
+ // kb repeat off\r
+ cmd7508_buf->read();\r
+ kb_rep_enb = false;\r
+ break;\r
+ case 0x06:\r
+ // kb interrupt off\r
+ cmd7508_buf->read();\r
+ kb_intr_enb = false;\r
+ break;\r
+ case 0x07:\r
+ // clock read\r
+ cmd7508_buf->read();\r
+ rsp7508_buf->write(TO_BCD_HI(cur_time.year));\r
+ rsp7508_buf->write(TO_BCD_LO(cur_time.year));\r
+ rsp7508_buf->write(TO_BCD(cur_time.month));\r
+ rsp7508_buf->write(TO_BCD(cur_time.day));\r
+ rsp7508_buf->write(TO_BCD(cur_time.hour));\r
+ rsp7508_buf->write(TO_BCD(cur_time.minute));\r
+ rsp7508_buf->write(TO_BCD(cur_time.second));\r
+ rsp7508_buf->write(cur_time.day_of_week);\r
+ break;\r
+ case 0x08:\r
+ // power switch read\r
+ cmd7508_buf->read();\r
+ rsp7508_buf->write(1);\r
+ break;\r
+ case 0x09:\r
+ // alarm read\r
+ cmd7508_buf->read();\r
+ rsp7508_buf->write(alarm[0]);\r
+ rsp7508_buf->write(alarm[1]);\r
+ rsp7508_buf->write(alarm[2]);\r
+ rsp7508_buf->write(alarm[3]);\r
+ rsp7508_buf->write(alarm[4]);\r
+ rsp7508_buf->write(alarm[5]);\r
+ break;\r
+ case 0x0a:\r
+ // dip switch read\r
+ cmd7508_buf->read();\r
+ res = 0xf; // ascii keyboard\r
+ rsp7508_buf->write(res);\r
+ break;\r
+ case 0x0b:\r
+ // set power failure detect voltage\r
+ if(cmd7508_buf->count() == 2) {\r
+ cmd7508_buf->read();\r
+ cmd7508_buf->read();\r
+ }\r
+ break;\r
+ case 0x0c:\r
+ // read buttery voltage\r
+ cmd7508_buf->read();\r
+ rsp7508_buf->write(0xe0);\r
+ break;\r
+ case 0x0d:\r
+ // 1 sec interrupt off\r
+ cmd7508_buf->read();\r
+ onesec_intr_enb = false;\r
+ break;\r
+ case 0x0e:\r
+ // kb clear\r
+ cmd7508_buf->read();\r
+ key_buf->clear();\r
+ break;\r
+ case 0x0f:\r
+ // system reset\r
+ cmd7508_buf->read();\r
+ res_7508 = true;\r
+ break;\r
+ case 0x14:\r
+ // kb repeat timer 2 set\r
+ if(cmd7508_buf->count() == 2) {\r
+ cmd7508_buf->read();\r
+ kb_rep_spd2 = cmd7508_buf->read();\r
+ }\r
+ break;\r
+ case 0x15:\r
+ // kb repeat on\r
+ cmd7508_buf->read();\r
+ kb_rep_enb = true;\r
+ break;\r
+ case 0x16:\r
+ // kb interrupt on\r
+ cmd7508_buf->read();\r
+ kb_intr_enb = true;\r
+ break;\r
+ case 0x17:\r
+ // clock write\r
+ if(cmd7508_buf->count() == 9) {\r
+ cmd7508_buf->read();\r
+ int year10 = cmd7508_buf->read();\r
+ int year1 = cmd7508_buf->read();\r
+ int month = cmd7508_buf->read();\r
+ int day = cmd7508_buf->read();\r
+ int hour = cmd7508_buf->read();\r
+ int minute = cmd7508_buf->read();\r
+ int second = cmd7508_buf->read();\r
+ int day_of_week = cmd7508_buf->read();\r
+ \r
+ if((month & 0x0f) == 0 || (day & 0x0f) == 0) {\r
+ // invalid date\r
+ emu->get_host_time(&cur_time);\r
+ } else {\r
+ bool changed = false;\r
+ if((year10 & 0x0f) != 0x0f && (year1 & 0x0f) != 0x0f) {\r
+ cur_time.year = (year10 & 0x0f) * 10 + (year1 & 0x0f);\r
+ cur_time.update_year();\r
+ changed = true;\r
+ }\r
+ if((month & 0x0f) != 0x0f) {\r
+ cur_time.month = FROM_BCD(month & 0x1f);\r
+ changed = true;\r
+ }\r
+ if((day & 0x0f) != 0x0f) {\r
+ cur_time.day = FROM_BCD(day & 0x3f);\r
+ changed = true;\r
+ }\r
+ if((hour & 0x0f) != 0x0f) {\r
+ cur_time.hour = FROM_BCD(hour & 0x3f);\r
+ changed = true;\r
+ }\r
+ if((minute & 0x0f) != 0x0f) {\r
+ cur_time.minute = FROM_BCD(minute & 0x7f);\r
+ changed = true;\r
+ }\r
+ if((second & 0x0f) != 0x0f) {\r
+ cur_time.second = FROM_BCD(second & 0x7f);\r
+ changed = true;\r
+ }\r
+// if((day_of_week & 0x0f) != 0x0f) {\r
+// cur_time.day_of_week = day_of_week & 0x07;\r
+// changed = true;\r
+// }\r
+ if(changed) {\r
+ cur_time.update_day_of_week();\r
+ // restart event\r
+ cancel_event(this, register_id);\r
+ register_event_by_clock(this, EVENT_1SEC, CPU_CLOCKS, true, ®ister_id);\r
+ }\r
+ }\r
+ }\r
+ break;\r
+ case 0x19:\r
+ // alarm set\r
+ if(cmd7508_buf->count() == 7) {\r
+ cmd7508_buf->read();\r
+ alarm[0] = cmd7508_buf->read();\r
+ alarm[1] = cmd7508_buf->read();\r
+ alarm[2] = cmd7508_buf->read();\r
+ alarm[3] = cmd7508_buf->read();\r
+ alarm[4] = cmd7508_buf->read();\r
+ alarm[5] = cmd7508_buf->read();\r
+ }\r
+ break;\r
+ case 0x1b:\r
+ // set full charge voltage\r
+ if(cmd7508_buf->count() == 2) {\r
+ cmd7508_buf->read();\r
+ cmd7508_buf->read();\r
+ }\r
+ break;\r
+ case 0x1c:\r
+ // read temperature\r
+ cmd7508_buf->read();\r
+ rsp7508_buf->write(0x90);\r
+ break;\r
+ case 0x1d:\r
+ // 1 sec interrupt on\r
+ cmd7508_buf->read();\r
+ onesec_intr_enb = true;\r
+ break;\r
+ case 0x24:\r
+ // kb repeat timer 1 read\r
+ cmd7508_buf->read();\r
+ rsp7508_buf->write(kb_rep_spd1);\r
+ break;\r
+ case 0x29:\r
+ // alarm off\r
+ cmd7508_buf->read();\r
+ alarm_intr_enb = false;\r
+ break;\r
+ case 0x2c:\r
+ // read analog jack 1\r
+ cmd7508_buf->read();\r
+ rsp7508_buf->write(0);\r
+ break;\r
+ case 0x34:\r
+ // kb repeat timer 2 read\r
+ cmd7508_buf->read();\r
+ rsp7508_buf->write(kb_rep_spd2);\r
+ break;\r
+ case 0x39:\r
+ // alarm on\r
+ cmd7508_buf->read();\r
+ alarm_intr_enb = true;\r
+ break;\r
+ case 0x3c:\r
+ // read analog jack 2\r
+ cmd7508_buf->read();\r
+ rsp7508_buf->write(0);\r
+ break;\r
+ default:\r
+ // unknown cmd\r
+ cmd7508_buf->read();\r
+ emu->out_debug_log(_T("unknown cmd %2x\n"), cmd);\r
+ }\r
+}\r
+\r
+uint8 IO::rec_from_7508()\r
+{\r
+ return rsp7508_buf->read();\r
+}\r
+\r
+void IO::key_down(int code)\r
+{\r
+ if(code == 0x14) {\r
+ // toggle caps lock\r
+ kb_caps = !kb_caps;\r
+ update_key(kb_caps ? 0xb4 : 0xa4);\r
+ update_key(kb_caps ? 0xa4 : 0xb4);\r
+ } else {\r
+ update_key(key_tbl[code & 0xff]);\r
+ }\r
+}\r
+\r
+void IO::key_up(int code)\r
+{\r
+ if(code == 0x10) {\r
+ update_key(0xa3); // break shift\r
+ } else if(code == 0x11) {\r
+ update_key(0xa2); // break ctrl\r
+ }\r
+}\r
+\r
+void IO::update_key(int code)\r
+{\r
+ if(code != 0xff) {\r
+ // add to buffer\r
+ if(code == 0x10) {\r
+ // stop key\r
+ key_buf->clear();\r
+ key_buf->write(code);\r
+ } else {\r
+ key_buf->write(code);\r
+ }\r
+ \r
+ // key interrupt\r
+ if(kb_intr_enb || (!kb_intr_enb && code == 0x10)) {\r
+ isr |= BIT_7508;\r
+ update_intr();\r
+ }\r
+ }\r
+}\r
+\r
+// ----------------------------------------------------------------------------\r
+// 6303\r
+// ----------------------------------------------------------------------------\r
+\r
+void IO::process_6303()\r
+{\r
+ switch(cmd6303) {\r
+ case 0x00:\r
+ // read data\r
+ if(cmd6303_buf->count() == 2) {\r
+ uint16 addr = cmd6303_buf->read() << 8;\r
+ addr |= cmd6303_buf->read();\r
+ rsp6303_buf->write(RCD00);\r
+ rsp6303_buf->write(ram[addr]);\r
+ psr |= BIT_F1;\r
+ }\r
+ break;\r
+ case 0x01:\r
+ // write data\r
+ if(cmd6303_buf->count() == 4) {\r
+ uint16 addr = cmd6303_buf->read() << 8;\r
+ addr |= cmd6303_buf->read();\r
+ uint8 val = cmd6303_buf->read();\r
+ uint8 ope = cmd6303_buf->read();\r
+ if(ope == 1) {\r
+ ram[addr] &= val;\r
+ } else if(ope == 2) {\r
+ ram[addr] |= val;\r
+ } else if(ope == 3) {\r
+ ram[addr] ^= val;\r
+ } else {\r
+ ram[addr] = val;\r
+ }\r
+ rsp6303_buf->write(RCD00);\r
+ psr |= BIT_F1;\r
+ }\r
+ break;\r
+ case 0x02:\r
+ // execute routine\r
+ if(cmd6303_buf->count() == 2) {\r
+ uint16 addr = cmd6303_buf->read() << 8;\r
+ addr |= cmd6303_buf->read();\r
+ // unknown\r
+ rsp6303_buf->write(RCD00);\r
+ psr |= BIT_F1;\r
+ }\r
+ break;\r
+ case 0x0b:\r
+ // unknown (initialize???)\r
+ rsp6303_buf->write(RCD00);\r
+ psr |= BIT_F1;\r
+ break;\r
+ case 0x10:\r
+ // define screen mode\r
+ if(cmd6303_buf->count() == 16) {\r
+ cs_addr = cmd6303_buf->read() << 8;\r
+ cs_addr |= cmd6303_buf->read();\r
+ gs_addr = cmd6303_buf->read() << 8;\r
+ gs_addr |= cmd6303_buf->read();\r
+ cmd6303_buf->read();\r
+ cmd6303_buf->read();\r
+ cmd6303_buf->read();\r
+ cmd6303_buf->read();\r
+ cmd6303_buf->read();\r
+ cmd6303_buf->read();\r
+ cmd6303_buf->read();\r
+ cmd6303_buf->read();\r
+ uint16 bottom = cmd6303_buf->read() << 8;\r
+ bottom |= cmd6303_buf->read();\r
+ cmd6303_buf->read();\r
+ cmd6303_buf->read();\r
+ rsp6303_buf->write(RCD00);\r
+ psr |= BIT_F1;\r
+ // go to character screen mode ???\r
+ scr_mode = 0xff;\r
+ // stop block flashing ???\r
+ flash_block = 0;\r
+ cs_blocks = gs_blocks = 0;\r
+ // clear screen ???\r
+ memset(&ram[cs_addr], 0, bottom - cs_addr);\r
+ }\r
+ break;\r
+ case 0x11:\r
+ // turn on/off lcd\r
+ if(cmd6303_buf->count() == 1) {\r
+ lcd_on = cmd6303_buf->read();\r
+ rsp6303_buf->write(RCD00);\r
+ psr |= BIT_F1;\r
+ }\r
+ break;\r
+ case 0x12:\r
+ // select screen\r
+ if(cmd6303_buf->count() == 1) {\r
+ scr_mode = cmd6303_buf->read();\r
+ if(!scr_mode) {\r
+ scr_ptr = cs_addr;\r
+ }\r
+ rsp6303_buf->write(RCD00);\r
+ psr |= BIT_F1;\r
+ }\r
+ break;\r
+ case 0x13:\r
+ // read screen pointer\r
+ rsp6303_buf->write(RCD00);\r
+ rsp6303_buf->write(scr_ptr >> 8);\r
+ rsp6303_buf->write(scr_ptr & 0xff);\r
+ psr |= BIT_F1;\r
+ break;\r
+ case 0x14:\r
+ // set screen pointer\r
+ if(cmd6303_buf->count() == 2) {\r
+ scr_ptr = cmd6303_buf->read() << 8;\r
+ scr_ptr |= cmd6303_buf->read();\r
+ rsp6303_buf->write(RCD00);\r
+ psr |= BIT_F1;\r
+ // stop block flashing ???\r
+ flash_block = 0;\r
+ cs_blocks = gs_blocks = 0;\r
+ }\r
+ break;\r
+ case 0x15:\r
+ // define number of lines\r
+ if(cmd6303_buf->count() == 1) {\r
+ num_lines = cmd6303_buf->read();\r
+ rsp6303_buf->write(RCD00);\r
+ psr |= BIT_F1;\r
+ }\r
+ break;\r
+ case 0x16:\r
+ // define cursor mode\r
+ if(cmd6303_buf->count() == 1) {\r
+ curs_mode = cmd6303_buf->read();\r
+ rsp6303_buf->write(RCD00);\r
+ psr |= BIT_F1;\r
+ }\r
+ break;\r
+ case 0x17:\r
+ // read cursur position\r
+ rsp6303_buf->write(RCD00);\r
+ rsp6303_buf->write(curs_x);\r
+ rsp6303_buf->write(curs_y);\r
+ psr |= BIT_F1;\r
+ break;\r
+ case 0x18:\r
+ // set cursor position\r
+ if(cmd6303_buf->count() == 2) {\r
+ curs_x = cmd6303_buf->read();\r
+ curs_y = cmd6303_buf->read();\r
+ rsp6303_buf->write(RCD00);\r
+ psr |= BIT_F1;\r
+ }\r
+ break;\r
+ case 0x19:\r
+ // start/stop control block flashing\r
+ if(cmd6303_buf->count() == 1) {\r
+ flash_block = cmd6303_buf->read();\r
+ rsp6303_buf->write(RCD00);\r
+ psr |= BIT_F1;\r
+ }\r
+ break;\r
+ case 0x1a:\r
+ // clear screen\r
+ if(cmd6303_buf->count() == 4) {\r
+ uint8 scr = cmd6303_buf->read();\r
+ uint8 code = cmd6303_buf->read();\r
+ int sy = cmd6303_buf->read();\r
+ int num = cmd6303_buf->read();\r
+ if(scr) {\r
+ // char screen\r
+ for(int y = 0; y < num; y++) {\r
+ if(sy + y < 64) {\r
+ memset(&ram[cs_addr + (sy + y) * 80], code, 80);\r
+ }\r
+ }\r
+ } else {\r
+ // graph screen\r
+ for(int y = 0; y < num; y++) {\r
+ if(sy + y < 8) {\r
+ memset(&ram[gs_addr + (sy + y) * 60 * 8], code, 60 * 8);\r
+ }\r
+ }\r
+ }\r
+ rsp6303_buf->write(RCD00);\r
+ psr |= BIT_F1;\r
+ }\r
+ break;\r
+ case 0x1b:\r
+ // read character font\r
+ if(cmd6303_buf->count() == 1) {\r
+ int ofs = cmd6303_buf->read() << 3;\r
+ rsp6303_buf->write(RCD00);\r
+ for(int i = 0; i < 8; i++) {\r
+ rsp6303_buf->write(font[ofs + i]);\r
+ }\r
+ psr |= BIT_F1;\r
+ }\r
+ break;\r
+ case 0x20:\r
+ // define user defined graphic character\r
+ if(cmd6303_buf->count() >= 3) {\r
+ int lx = cmd6303_buf->read_not_remove(1);\r
+ int ly = cmd6303_buf->read_not_remove(2);\r
+ if(cmd6303_buf->count() == lx * ly + 3) {\r
+ uint8 code = cmd6303_buf->read();\r
+ bool pre = (udgc[code][0] && udgc[code][1]);\r
+ for(int i = 0; i < lx * ly + 2; i++) {\r
+ uint8 d = cmd6303_buf->read();\r
+ if(!pre) {\r
+ udgc[code][i] = d;\r
+ }\r
+ }\r
+ if(!code) {\r
+ memset(udgc, 0, sizeof(udgc));\r
+ }\r
+ rsp6303_buf->write(RCD00);\r
+ psr |= BIT_F1;\r
+ }\r
+ }\r
+ break;\r
+ case 0x21:\r
+ // define graphic screen block flashing data\r
+ if(cmd6303_buf->count() >= 1) {\r
+ int cnt = cmd6303_buf->read_not_remove(0);\r
+ if(cmd6303_buf->count() == cnt * 3 + 1) {\r
+ gs_blocks = cmd6303_buf->read();\r
+ for(int i = 0; i < gs_blocks; i++) {\r
+ gs_block[i][0] = cmd6303_buf->read();\r
+ gs_block[i][1] = cmd6303_buf->read();\r
+ gs_block[i][2] = cmd6303_buf->read();\r
+ }\r
+ rsp6303_buf->write(RCD00);\r
+ psr |= BIT_F1;\r
+ }\r
+ }\r
+ break;\r
+ case 0x22:\r
+ // draw character font on graphic screen\r
+ if(cmd6303_buf->count() == 4) {\r
+ int x = cmd6303_buf->read() << 8;\r
+ x |= cmd6303_buf->read();\r
+ int y = cmd6303_buf->read();\r
+ int ofs = cmd6303_buf->read() << 3;\r
+ for(int l = 0; l < 8; l++) {\r
+ uint8 pat = font[ofs + l];\r
+ draw_point(x + 0, y + l, pat & 0x20);\r
+ draw_point(x + 1, y + l, pat & 0x10);\r
+ draw_point(x + 2, y + l, pat & 0x08);\r
+ draw_point(x + 3, y + l, pat & 0x04);\r
+ draw_point(x + 4, y + l, pat & 0x02);\r
+ draw_point(x + 5, y + l, pat & 0x01);\r
+ }\r
+ rsp6303_buf->write(RCD00);\r
+ psr |= BIT_F1;\r
+ }\r
+ break;\r
+ case 0x23:\r
+ // draw user defined character on graphics screen\r
+ if(cmd6303_buf->count() >= 3) {\r
+ int dx = cmd6303_buf->read();\r
+ int dy = cmd6303_buf->read();\r
+ uint8 code = cmd6303_buf->read();\r
+ int lx = udgc[code][0];\r
+ int ly = udgc[code][1];\r
+ uint8* pat = &udgc[code][2];\r
+ if(lx && ly) {\r
+ for(int y = 0; y < ly; y++) {\r
+ for(int x = 0; x < lx; x++) {\r
+ if(dx + x < 60 && dy + y < 64) {\r
+ ram[gs_addr + (dx + x + (dy + y) * 60)] = *pat++;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ rsp6303_buf->write(RCD00);\r
+ psr |= BIT_F1;\r
+ }\r
+ break;\r
+ case 0x24:\r
+ // read graphics screen data\r
+ if(cmd6303_buf->count() == 3) {\r
+ int x = cmd6303_buf->read();\r
+ int y = cmd6303_buf->read();\r
+ uint8* src = &ram[gs_addr + (x + y * 60)];\r
+ int cnt = cmd6303_buf->read();\r
+ rsp6303_buf->write(RCD00);\r
+ for(int i = 0; i < cnt; i++) {\r
+ rsp6303_buf->write(src[i]);\r
+ }\r
+ psr |= BIT_F1;\r
+ }\r
+ break;\r
+ case 0x25:\r
+ // display data on graphics screen\r
+ if(cmd6303_buf->count() >= 4) {\r
+ int lx = cmd6303_buf->read_not_remove(2);\r
+ int ly = cmd6303_buf->read_not_remove(3);\r
+ if(cmd6303_buf->count() == lx * ly + 5) {\r
+ int dx = cmd6303_buf->read();\r
+ int dy = cmd6303_buf->read();\r
+ lx = cmd6303_buf->read();\r
+ ly = cmd6303_buf->read();\r
+ uint8 ope = cmd6303_buf->read();\r
+ for(int y = 0; y < ly; y++) {\r
+ for(int x = 0; x < lx; x++) {\r
+ uint8 d = cmd6303_buf->read();\r
+ if(dx + x < 60 && dy + y < 64) {\r
+ if(ope == 1) {\r
+ ram[gs_addr + (dx + x + (dy + y) * 60)] &= d;\r
+ } else if(ope == 2) {\r
+ ram[gs_addr + (dx + x + (dy + y) * 60)] |= d;\r
+ } else if(ope == 3) {\r
+ ram[gs_addr + (dx + x + (dy + y) * 60)] ^= d;\r
+ } else {\r
+ ram[gs_addr + (dx + x + (dy + y) * 60)] = d;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ rsp6303_buf->write(RCD00);\r
+ psr |= BIT_F1;\r
+ }\r
+ }\r
+ break;\r
+ case 0x26:\r
+ // move graphics screen block\r
+ if(cmd6303_buf->count() == 6) {\r
+ int sx = cmd6303_buf->read();\r
+ int sy = cmd6303_buf->read();\r
+ int lx = cmd6303_buf->read();\r
+ int ly = cmd6303_buf->read();\r
+ int dx = cmd6303_buf->read();\r
+ int dy = cmd6303_buf->read();\r
+ for(int y = 0; y < ly; y++) {\r
+ for(int x = 0; x < lx; x++) {\r
+ if(sx + x < 60 && sy + y < 64) {\r
+ mov[y][x] = ram[gs_addr + (sx + x + (sy + y) * 60)];\r
+ ram[gs_addr + (sx + x + (sy + y) * 60)] = 0;\r
+ }\r
+ }\r
+ }\r
+ for(int y = 0; y < ly; y++) {\r
+ for(int x = 0; x < lx; x++) {\r
+ if(dx + x < 60 && dy + y < 64) {\r
+ ram[gs_addr + (dx + x + (dy + y) * 60)] = mov[y][x];\r
+ }\r
+ }\r
+ }\r
+ rsp6303_buf->write(RCD00);\r
+ psr |= BIT_F1;\r
+ }\r
+ break;\r
+ case 0x27:\r
+ // define point\r
+ if(cmd6303_buf->count() == 4) {\r
+ int x = cmd6303_buf->read() << 8;\r
+ x |= cmd6303_buf->read();\r
+ int y = cmd6303_buf->read();\r
+ uint8 ope = cmd6303_buf->read();\r
+ if(ope == 1) {\r
+ draw_point(x, y, 0);\r
+ } else {\r
+ draw_point(x, y, 1);\r
+ }\r
+ rsp6303_buf->write(RCD00);\r
+ psr |= BIT_F1;\r
+ }\r
+ break;\r
+ case 0x28:\r
+ // read point\r
+ if(cmd6303_buf->count() == 3) {\r
+ int x = cmd6303_buf->read() << 8;\r
+ x |= cmd6303_buf->read();\r
+ int y = cmd6303_buf->read();\r
+ rsp6303_buf->write(RCD00);\r
+ rsp6303_buf->write(get_point(x, y));\r
+ psr |= BIT_F1;\r
+ }\r
+ break;\r
+ case 0x29:\r
+ // draw line\r
+ if(cmd6303_buf->count() == 11) {\r
+ int sx = cmd6303_buf->read() << 8;\r
+ sx |= cmd6303_buf->read();\r
+ int sy = cmd6303_buf->read() << 8;\r
+ sy |= cmd6303_buf->read();\r
+ int ex = cmd6303_buf->read() << 8;\r
+ ex |= cmd6303_buf->read();\r
+ int ey = cmd6303_buf->read() << 8;\r
+ ey |= cmd6303_buf->read();\r
+ uint16 ope = cmd6303_buf->read() << 8;\r
+ ope |= cmd6303_buf->read();\r
+ uint8 mode = cmd6303_buf->read();\r
+ if(mode == 1) {\r
+ draw_line(sx, sy, ex, ey, ~ope);\r
+ } else {\r
+ draw_line(sx, sy, ex, ey, ope);\r
+ }\r
+ rsp6303_buf->write(RCD00);\r
+ psr |= BIT_F1;\r
+ }\r
+ break;\r
+ case 0x30:\r
+ // user defined character\r
+ if(cmd6303_buf->count() == 9) {\r
+ int code = cmd6303_buf->read();\r
+ if(code < 0xe0) {\r
+ for(int i = 0; i < 8; i++) {\r
+ cmd6303_buf->read();\r
+ }\r
+ rsp6303_buf->write(RCD06);\r
+ } else {\r
+ int ofs = code << 3;\r
+ for(int i = 0; i < 8; i++) {\r
+ font[ofs + i] = cmd6303_buf->read();\r
+ }\r
+ rsp6303_buf->write(RCD00);\r
+ }\r
+ psr |= BIT_F1;\r
+ }\r
+ break;\r
+ case 0x31:\r
+ // define character screen block flashing data\r
+ if(cmd6303_buf->count() >= 1) {\r
+ int cnt = cmd6303_buf->read_not_remove(0);\r
+ if(cmd6303_buf->count() == cnt * 3 + 1) {\r
+ cs_blocks = cmd6303_buf->read();\r
+ for(int i = 0; i < cs_blocks; i++) {\r
+ cs_block[i][0] = cmd6303_buf->read();\r
+ cs_block[i][1] = cmd6303_buf->read();\r
+ cs_block[i][2] = cmd6303_buf->read();\r
+ }\r
+ rsp6303_buf->write(RCD00);\r
+ psr |= BIT_F1;\r
+ }\r
+ }\r
+ break;\r
+ case 0x32:\r
+ // read window pointer\r
+ rsp6303_buf->write(RCD00);\r
+ rsp6303_buf->write(wnd_ptr_x);\r
+ rsp6303_buf->write(wnd_ptr_y);\r
+ psr |= BIT_F1;\r
+ break;\r
+ case 0x33:\r
+ // set window pointer\r
+ if(cmd6303_buf->count() == 2) {\r
+ wnd_ptr_x = cmd6303_buf->read();\r
+ wnd_ptr_y = cmd6303_buf->read();\r
+ rsp6303_buf->write(RCD00);\r
+ psr |= BIT_F1;\r
+ }\r
+ break;\r
+ case 0x34:\r
+ // read character screen data\r
+ if(cmd6303_buf->count() == 3) {\r
+ int x = cmd6303_buf->read();\r
+ int y = cmd6303_buf->read();\r
+ uint8* src = &ram[cs_addr + (x + y * 80)];\r
+ int cnt = cmd6303_buf->read();\r
+ rsp6303_buf->write(RCD00);\r
+ for(int i = 0; i < cnt; i++) {\r
+ rsp6303_buf->write(src[i]);\r
+ }\r
+ psr |= BIT_F1;\r
+ }\r
+ break;\r
+ case 0x35:\r
+ // display data on character screen\r
+ if(cmd6303_buf->count() >= 4) {\r
+ int cnt = cmd6303_buf->read_not_remove(2);\r
+ if(cmd6303_buf->count() == cnt + 3) {\r
+ int x = cmd6303_buf->read();\r
+ int y = cmd6303_buf->read();\r
+ uint8* dest = &ram[cs_addr + (x + y * 80)];\r
+ cnt = cmd6303_buf->read();\r
+ for(int i = 0; i < cnt; i++) {\r
+ dest[i] = cmd6303_buf->read();\r
+ }\r
+ rsp6303_buf->write(RCD00);\r
+ psr |= BIT_F1;\r
+ }\r
+ }\r
+ break;\r
+ case 0x36:\r
+ // move character screen block\r
+ if(cmd6303_buf->count() == 6) {\r
+ int sx = cmd6303_buf->read();\r
+ int sy = cmd6303_buf->read();\r
+ int lx = cmd6303_buf->read();\r
+ int ly = cmd6303_buf->read();\r
+ int dx = cmd6303_buf->read();\r
+ int dy = cmd6303_buf->read();\r
+ for(int y = 0; y < ly; y++) {\r
+ for(int x = 0; x < lx; x++) {\r
+ if(sx + x < 80 && sy + y < 64) {\r
+ mov[y][x] = ram[cs_addr + (sx + x + (sy + y) * 80)];\r
+// ram[cs_addr + (sx + x + (sy + y) * 80)] = 0;\r
+ }\r
+ }\r
+ }\r
+ for(int y = 0; y < ly; y++) {\r
+ for(int x = 0; x < lx; x++) {\r
+ if(dx + x < 80 && dy + y < 64) {\r
+ ram[cs_addr + (dx + x + (dy + y) * 80)] = mov[y][x];\r
+ }\r
+ }\r
+ }\r
+ rsp6303_buf->write(RCD00);\r
+ psr |= BIT_F1;\r
+ }\r
+ break;\r
+ case 0x40:\r
+ // read microcassette status\r
+ rsp6303_buf->write(RCD00);\r
+ rsp6303_buf->write(0);\r
+ psr |= BIT_F1;\r
+ break;\r
+ case 0x41:\r
+ // head on\r
+ rsp6303_buf->write(RCD07);\r
+ psr |= BIT_F1;\r
+ break;\r
+ case 0x42:\r
+ // head off\r
+ rsp6303_buf->write(RCD00);\r
+ psr |= BIT_F1;\r
+ break;\r
+ case 0x43:\r
+ // rewind n counts\r
+ case 0x44:\r
+ // fast foward n counts\r
+ if(cmd6303_buf->count() == 2) {\r
+ cmd6303_buf->read();\r
+ cmd6303_buf->read();\r
+ rsp6303_buf->write(RCD07);\r
+ psr |= BIT_F1;\r
+ }\r
+ break;\r
+ case 0x45:\r
+ // rewind\r
+ case 0x47:\r
+ // slow rewind\r
+ rsp6303_buf->write(RCD07);\r
+ psr |= BIT_F1;\r
+ break;\r
+ case 0x46:\r
+ // fast foward\r
+ case 0x48:\r
+ // play\r
+ case 0x49:\r
+ // record\r
+ case 0x4a:\r
+ // stop\r
+ rsp6303_buf->write(RCD00);\r
+ psr |= BIT_F1;\r
+ break;\r
+ case 0x4b:\r
+ // read write protect pin\r
+ rsp6303_buf->write(RCD00);\r
+ rsp6303_buf->write(0);\r
+ psr |= BIT_F1;\r
+ break;\r
+ case 0x4c:\r
+ // read counter\r
+ rsp6303_buf->write(RCD00);\r
+ rsp6303_buf->write(0);\r
+ rsp6303_buf->write(0);\r
+ psr |= BIT_F1;\r
+ break;\r
+ case 0x4d:\r
+ // set counter\r
+ if(cmd6303_buf->count() == 2) {\r
+ cmd6303_buf->read();\r
+ cmd6303_buf->read();\r
+ rsp6303_buf->write(RCD00);\r
+ psr |= BIT_F1;\r
+ }\r
+ break;\r
+ case 0x55:\r
+ // set write protect area pointer\r
+ if(cmd6303_buf->count() == 2) {\r
+ cmd6303_buf->read();\r
+ cmd6303_buf->read();\r
+ rsp6303_buf->write(RCD00);\r
+ psr |= BIT_F1;\r
+ }\r
+ break;\r
+ case 0x56:\r
+ // reset write protect area pointer\r
+ rsp6303_buf->write(RCD00);\r
+ psr |= BIT_F1;\r
+ break;\r
+ case 0x60:\r
+ // read serial i/o status\r
+ rsp6303_buf->write(RCD00);\r
+ rsp6303_buf->write(0x20 | (tf20_buf->count() ? 0x80 : 0));\r
+ psr |= BIT_F1;\r
+ break;\r
+ case 0x61:\r
+ // set serial port bit rate\r
+ if(cmd6303_buf->count() == 1) {\r
+ cmd6303_buf->read();\r
+ rsp6303_buf->write(RCD00);\r
+ psr |= BIT_F1;\r
+ }\r
+ break;\r
+ case 0x62:\r
+ // serial input\r
+ rsp6303_buf->write(RCD00);\r
+ rsp6303_buf->write(tf20_buf->read());\r
+ psr |= BIT_F1;\r
+ break;\r
+ case 0x63:\r
+ // serial output\r
+ if(cmd6303_buf->count() == 1) {\r
+ d_tf20->write_signal(SIGNAL_TF20_SIO, cmd6303_buf->read(), 0xff);\r
+ rsp6303_buf->write(RCD00);\r
+ psr |= BIT_F1;\r
+ }\r
+ break;\r
+ case 0x64:\r
+ // send data with header\r
+ if(cmd6303_buf->count() >= 6) {\r
+ int cnt = cmd6303_buf->read_not_remove(5);\r
+ if(cmd6303_buf->count() == cnt + 7) {\r
+ int rcv = cmd6303_buf->read();\r
+ int fmt = cmd6303_buf->read();\r
+ int did = cmd6303_buf->read();\r
+ int sid = cmd6303_buf->read();\r
+ int fnc = cmd6303_buf->read();\r
+ int siz = cmd6303_buf->read();\r
+ \r
+ // epsp protocol\r
+ tf20_buf->clear();\r
+ d_tf20->write_signal(SIGNAL_TF20_SIO, DID_FIRST, 0xff);\r
+ d_tf20->write_signal(SIGNAL_TF20_SIO, did, 0xff);\r
+ d_tf20->write_signal(SIGNAL_TF20_SIO, sid, 0xff);\r
+ d_tf20->write_signal(SIGNAL_TF20_SIO, DS_SEL, 0xff);\r
+ tf20_buf->read(); // recv ack\r
+ d_tf20->write_signal(SIGNAL_TF20_SIO, SOH, 0xff);\r
+ d_tf20->write_signal(SIGNAL_TF20_SIO, fmt, 0xff);\r
+ d_tf20->write_signal(SIGNAL_TF20_SIO, did, 0xff);\r
+ d_tf20->write_signal(SIGNAL_TF20_SIO, sid, 0xff);\r
+ d_tf20->write_signal(SIGNAL_TF20_SIO, fnc, 0xff);\r
+ d_tf20->write_signal(SIGNAL_TF20_SIO, siz, 0xff);\r
+ d_tf20->write_signal(SIGNAL_TF20_SIO, 0, 0xff);\r
+ tf20_buf->read(); // recv ack\r
+ d_tf20->write_signal(SIGNAL_TF20_SIO, STX, 0xff);\r
+ for(int i = 0; i < siz + 1; i++) {\r
+ d_tf20->write_signal(SIGNAL_TF20_SIO, cmd6303_buf->read(), 0xff);\r
+ }\r
+ d_tf20->write_signal(SIGNAL_TF20_SIO, 0, 0xff);\r
+ d_tf20->write_signal(SIGNAL_TF20_SIO, 0, 0xff);\r
+ tf20_buf->read(); // recv ack\r
+ d_tf20->write_signal(SIGNAL_TF20_SIO, EOT, 0xff);\r
+ \r
+ rsp6303_buf->write(RCD00);\r
+ if(rcv) {\r
+ rsp6303_buf->write(0);\r
+ tf20_buf->read();\r
+ rsp6303_buf->write(fmt = tf20_buf->read());\r
+ rsp6303_buf->write(did = tf20_buf->read());\r
+ rsp6303_buf->write(sid = tf20_buf->read());\r
+ rsp6303_buf->write(fnc = tf20_buf->read());\r
+ rsp6303_buf->write(siz = tf20_buf->read());\r
+ tf20_buf->read();\r
+ d_tf20->write_signal(SIGNAL_TF20_SIO, ACK, 0xff); // ack\r
+ tf20_buf->read();\r
+ for(int i = 0; i < siz + 1; i++) {\r
+ rsp6303_buf->write(tf20_buf->read());\r
+ }\r
+ d_tf20->write_signal(SIGNAL_TF20_SIO, ACK, 0xff); // ack\r
+ d_tf20->write_signal(SIGNAL_TF20_SIO, EOT, 0xff); // eot\r
+ tf20_buf->clear();\r
+ }\r
+ psr |= BIT_F1;\r
+ }\r
+ }\r
+ break;\r
+ case 0x65:\r
+ // receive data with header\r
+ rsp6303_buf->write(RCD00);\r
+ {\r
+ // epsp protocol\r
+ int fmt, did, sid, fnc, siz;\r
+ rsp6303_buf->write(0);\r
+ tf20_buf->read();\r
+ rsp6303_buf->write(fmt = tf20_buf->read());\r
+ rsp6303_buf->write(did = tf20_buf->read());\r
+ rsp6303_buf->write(sid = tf20_buf->read());\r
+ rsp6303_buf->write(fnc = tf20_buf->read());\r
+ rsp6303_buf->write(siz = tf20_buf->read());\r
+ tf20_buf->read();\r
+ d_tf20->write_signal(SIGNAL_TF20_SIO, ACK, 0xff); // ack\r
+ tf20_buf->read();\r
+ for(int i = 0; i < siz + 1; i++) {\r
+ rsp6303_buf->write(tf20_buf->read());\r
+ }\r
+ d_tf20->write_signal(SIGNAL_TF20_SIO, ACK, 0xff); // ack\r
+ d_tf20->write_signal(SIGNAL_TF20_SIO, EOT, 0xff); // eot\r
+ tf20_buf->clear();\r
+ }\r
+ psr |= BIT_F1;\r
+ break;\r
+ case 0x70:\r
+ // turn on/off prom cupsule power\r
+ if(cmd6303_buf->count() == 1) {\r
+ cmd6303_buf->read();\r
+ rsp6303_buf->write(RCD00);\r
+ psr |= BIT_F1;\r
+ }\r
+ break;\r
+ case 0x71:\r
+ // read data\r
+ if(cmd6303_buf->count() == 4) {\r
+ cmd6303_buf->read();\r
+ uint16 addr = cmd6303_buf->read() << 8;\r
+ addr |= cmd6303_buf->read();\r
+ addr ^= 0x4000;\r
+ int cnt = cmd6303_buf->read();\r
+ if(cnt == 0) cnt = 256;\r
+ rsp6303_buf->write(RCD00);\r
+ for(int i = 0; i < cnt; i++) {\r
+ if(addr & 0x8000) {\r
+ rsp6303_buf->write(util[(addr + i) & 0x7fff]);\r
+ } else {\r
+ rsp6303_buf->write(basic[(addr + i) & 0x7fff]);\r
+ }\r
+ }\r
+ psr |= BIT_F1;\r
+ }\r
+ break;\r
+ case 0x72:\r
+ // turn on/off speaker power\r
+ if(cmd6303_buf->count() == 1) {\r
+ cmd6303_buf->read();\r
+ rsp6303_buf->write(RCD00);\r
+ psr |= BIT_F1;\r
+ }\r
+ break;\r
+ case 0x73:\r
+ // turn on/off speaker power\r
+ if(cmd6303_buf->count() == 3) {\r
+ cmd6303_buf->read();\r
+ cmd6303_buf->read();\r
+ cmd6303_buf->read();\r
+ rsp6303_buf->write(RCD00);\r
+ psr |= BIT_F1;\r
+ }\r
+ break;\r
+ case 0x74:\r
+ // melody\r
+ if(cmd6303_buf->count() == 3) {\r
+ cmd6303_buf->read();\r
+ cmd6303_buf->read();\r
+ cmd6303_buf->read();\r
+ rsp6303_buf->write(RCD00);\r
+ psr |= BIT_F1;\r
+ }\r
+ break;\r
+ }\r
+}\r
+\r
+uint8 IO::get_point(int x, int y)\r
+{\r
+ if(0 <= x && x < 480 && 0 <= y && y < 64) {\r
+ uint8 bit = dot_tbl[x & 7];\r
+ int ofs = y * 60 + (x >> 3);\r
+ return ram[gs_addr + ofs] & bit;\r
+ }\r
+ return 0;\r
+}\r
+\r
+void IO::draw_point(int x, int y, uint16 dot)\r
+{\r
+ if(0 <= x && x < 480 && 0 <= y && y < 64) {\r
+ uint8 bit = dot_tbl[x & 7];\r
+ int ofs = y * 60 + (x >> 3);\r
+ if(dot) {\r
+ ram[gs_addr + ofs] |= bit;\r
+ } else {\r
+ ram[gs_addr + ofs] &= ~bit;\r
+ }\r
+ }\r
+}\r
+\r
+void IO::draw_line(int sx, int sy, int ex, int ey, uint16 ope)\r
+{\r
+ int next_x = sx, next_y = sy;\r
+ int delta_x = abs(ex - sx) * 2;\r
+ int delta_y = abs(ey - sy) * 2;\r
+ int step_x = (ex < sx) ? -1 : 1;\r
+ int step_y = (ey < sy) ? -1 : 1;\r
+ \r
+ draw_point(sx, sy, ope & 0x8000);\r
+ ope = (ope << 1) | (ope & 0x8000 ? 1 : 0);\r
+ if(delta_x > delta_y) {\r
+ int frac = delta_y - delta_x / 2;\r
+ while(next_x != ex) {\r
+ if(frac >= 0) {\r
+ next_y += step_y;\r
+ frac -= delta_x;\r
+ }\r
+ next_x += step_x;\r
+ frac += delta_y;\r
+ draw_point(next_x, next_y, ope & 0x8000);\r
+ ope = (ope << 1) | (ope & 0x8000 ? 1 : 0);\r
+ }\r
+ } else {\r
+ int frac = delta_x - delta_y / 2;\r
+ while(next_y != ey) {\r
+ if(frac >= 0) {\r
+ next_x += step_x;\r
+ frac -= delta_y;\r
+ }\r
+ next_y += step_y;\r
+ frac += delta_x;\r
+ draw_point(next_x, next_y, ope & 0x8000);\r
+ ope = (ope << 1) | (ope & 0x8000 ? 1 : 0);\r
+ }\r
+ }\r
+ draw_point(ex, ey, ope & 0x8000);\r
+}\r
+\r
+// ----------------------------------------------------------------------------\r
+// intelligent ram disk by Mr.Dennis Heynlein\r
+// ----------------------------------------------------------------------------\r
+\r
+/*\r
+0x81 (W) CommandByte c to RAMDisk\r
+0x81 (R) Statusbyte \r
+ Bit 0 : Readable DataByte on 0x81 is pending\r
+ Bit 1 : Receive of Data/Command is busy\r
+ Bit 7 and 6 = 0 (ident the RAMdisc)\r
+\r
+0x80 (R/W) DataByte d\r
+\r
+Commands: RESET - input: c(00)\r
+ output: d(SWITCHSTATE) \r
+\r
+ READSECTOR - input: c(01) d(TRACK) d(SECTOR)\r
+ output: d(ERRORSTATE) d(SECTORBYTE)*128\r
+ \r
+ READMEMDIRECT - input: c(02) d(BANK) d(HIGHBYTE) d(LOWBYTE)\r
+ output: d(ERRORSTATE) d(BYTE)\r
+\r
+ WRITESECTOR - input: c(03) d(TRACK) d(SECTOR) d(SECTORBYTE)*128\r
+ output: d(ERRORSTATE)\r
+\r
+ WRITEMEMDIRECT - input: c(04) d(HIGHBYTE) d(LOWBYTE) d(BYTE)\r
+ output: d(ERRORSTATE)\r
+\r
+ INIT_BITMAP - input: c(05)\r
+ output: d(ERRORSTATE)\r
+\r
+ERRORSTATE: Bit 0 = Ramdiscsize\r
+ Bit 1 = Geometric\r
+ Bit 2 = Writeprotect\r
+\r
+HIGHBYTE: 0 - 0xef\r
+LOWBYTE: 0-255\r
+TRACK: 0-14\r
+SECTOR: 0-63\r
+BANK: 1 or 2\r
+*/\r
+\r
+void IO::iramdisk_write_data(uint8 val)\r
+{\r
+ if(iramdisk_dest == IRAMDISK_IN && iramdisk_count) {\r
+ *(iramdisk_ptr++) = val;\r
+ iramdisk_count--;\r
+ }\r
+ if(!iramdisk_count) {\r
+ iramdisk_dest = IRAMDISK_OUT;\r
+ iramdisk_ptr = iramdisk_buf;\r
+ int track = iramdisk_buf[0];\r
+ int sector = iramdisk_buf[1];\r
+ \r
+ switch(iramdisk_cmd) {\r
+ case 1: //READSECTOR\r
+ if(track > 14 || sector > 63) {\r
+ iramdisk_buf[0] = 2;\r
+ } else {\r
+ iramdisk_buf[0] = 0;\r
+ for(int t = 0;t < 128; t++) {\r
+ iramdisk_buf[t + 1] = iramdisk_sectors[track][sector][t];\r
+ }\r
+ }\r
+ iramdisk_count = 129; //ERRORCODE + 128 Bytes\r
+ break;\r
+ case 3: //WRITESECTOR\r
+ if(track > 14 || sector > 63) {\r
+ iramdisk_buf[0] = 2;\r
+ } else {\r
+ iramdisk_buf[0] = 0;\r
+ for(int t = 0; t < 128; t++) {\r
+ iramdisk_sectors[track][sector][t] = iramdisk_buf[t+2];\r
+ }\r
+ }\r
+ iramdisk_count = 1; //ERRORCODE\r
+ break;\r
+ case 2: //READMEMDIRECT\r
+ iramdisk_count = 2; //ERRORCODE + 1 Byte\r
+ break;\r
+ case 4: //WRITEMEMDIRECT\r
+ iramdisk_count = 1; //ERRORCODE\r
+ break;\r
+ }\r
+ }\r
+}\r
+\r
+void IO::iramdisk_write_cmd(uint8 val)\r
+{\r
+ iramdisk_cmd = val;\r
+ iramdisk_count = 0;\r
+ iramdisk_ptr = iramdisk_buf;\r
+ iramdisk_dest = IRAMDISK_IN;\r
+ \r
+ switch(iramdisk_cmd) {\r
+ case 1:\r
+ iramdisk_count = 2;\r
+ break;\r
+ case 2:\r
+ case 4:\r
+ iramdisk_count = 3;\r
+ break;\r
+ case 3:\r
+ iramdisk_count = 130;\r
+ break;\r
+ default:\r
+ //PROCESS-1-BYTE_CMDs\r
+ iramdisk_count = 1;\r
+ iramdisk_dest = IRAMDISK_OUT;\r
+ if(iramdisk_cmd == 0) {\r
+ iramdisk_buf[0] = 1; // RESET\r
+ } else {\r
+ iramdisk_buf[0] = 0; //INIT\r
+ }\r
+ }\r
+}\r
+\r
+uint8 IO::iramdisk_read_data()\r
+{\r
+ if(iramdisk_dest == IRAMDISK_OUT) {\r
+ if(iramdisk_count) {\r
+ iramdisk_count--;\r
+ if(!iramdisk_count) {\r
+ iramdisk_dest = IRAMDISK_IN;\r
+ }\r
+ return *(iramdisk_ptr++);\r
+ }\r
+ }\r
+ return 0;\r
+}\r
+\r
+uint8 IO::iramdisk_read_stat()\r
+{\r
+ if(iramdisk_dest == IRAMDISK_OUT) {\r
+ return IRAMDISK_WAIT;\r
+ } else {\r
+ return 0;\r
+ }\r
+}\r
+\r
+// ----------------------------------------------------------------------------\r
+// video\r
+// ----------------------------------------------------------------------------\r
+\r
+\r
+void IO::draw_screen()\r
+{\r
+ if(lcd_on) {\r
+ memset(lcd, 0, sizeof(lcd));\r
+ if(scr_mode) {\r
+ // char screen\r
+ uint8* vram = &ram[scr_ptr];\r
+ for(int y = 0; y < (num_lines ? 7 : 8); y++) {\r
+ int py = num_lines ? (y * 9 + 1) : y * 8;\r
+ for(int x = 0; x < 80; x++) {\r
+ int px = x * 6;\r
+ int ofs = vram[y * 80 + x] << 3;\r
+ for(int l = 0; l < 8; l++) {\r
+ uint8 pat = font[ofs + l];\r
+ lcd[py + l][px + 0] = (pat & 0x20) ? 0xff : 0;\r
+ lcd[py + l][px + 1] = (pat & 0x10) ? 0xff : 0;\r
+ lcd[py + l][px + 2] = (pat & 0x08) ? 0xff : 0;\r
+ lcd[py + l][px + 3] = (pat & 0x04) ? 0xff : 0;\r
+ lcd[py + l][px + 4] = (pat & 0x02) ? 0xff : 0;\r
+ lcd[py + l][px + 5] = (pat & 0x01) ? 0xff : 0;\r
+ }\r
+ }\r
+ }\r
+ // block flashing\r
+ if(flash_block) {\r
+ int yofs = (scr_ptr - cs_addr) / 80;\r
+ for(int i = 0; i < cs_blocks; i++) {\r
+ int x = cs_block[i][0];\r
+ int y = cs_block[i][1] - yofs;\r
+ if(0 <= x && x < 80 && 0 <= y && y < 8) {\r
+ int px = x * 6;\r
+ int py = y * 8;\r
+ for(int l = 0; l < 8; l++) {\r
+ lcd[py + l][px + 0] = ~lcd[py + l][px + 0];\r
+ lcd[py + l][px + 1] = ~lcd[py + l][px + 1];\r
+ lcd[py + l][px + 2] = ~lcd[py + l][px + 2];\r
+ lcd[py + l][px + 3] = ~lcd[py + l][px + 3];\r
+ lcd[py + l][px + 4] = ~lcd[py + l][px + 4];\r
+ lcd[py + l][px + 5] = ~lcd[py + l][px + 5];\r
+ }\r
+ }\r
+ }\r
+ }\r
+ // draw cursor\r
+ if(curs_mode & 1) {\r
+ if(!(curs_mode & 2) || (blink & 32)) {\r
+ int px = curs_x * 6;\r
+ int py = curs_y * 8;\r
+ int st = (curs_mode & 4) ? 0 : 7;\r
+ if(px + 6 - 1 < SCREEN_WIDTH) {\r
+ for(int l = st; l < 8 && py + l < SCREEN_HEIGHT; l++) {\r
+ memset(&lcd[py + l][px], 0xff, 6);\r
+ }\r
+ }\r
+ }\r
+ }\r
+ } else {\r
+ // graph screen\r
+ uint8* vram = &ram[gs_addr];\r
+ for(int y = 0; y < 64; y++) {\r
+ for(int x = 0; x < 60; x++) {\r
+ int px = x * 8;\r
+ uint8 pat = *vram++;\r
+ lcd[y][px + 0] = (pat & 0x80) ? 0xff : 0;\r
+ lcd[y][px + 1] = (pat & 0x40) ? 0xff : 0;\r
+ lcd[y][px + 2] = (pat & 0x20) ? 0xff : 0;\r
+ lcd[y][px + 3] = (pat & 0x10) ? 0xff : 0;\r
+ lcd[y][px + 4] = (pat & 0x08) ? 0xff : 0;\r
+ lcd[y][px + 5] = (pat & 0x04) ? 0xff : 0;\r
+ lcd[y][px + 6] = (pat & 0x02) ? 0xff : 0;\r
+ lcd[y][px + 7] = (pat & 0x01) ? 0xff : 0;\r
+ }\r
+ }\r
+ // block flashing\r
+ if(flash_block) {\r
+ for(int i = 0; i < gs_blocks; i++) {\r
+ int x = gs_block[i][0];\r
+ int y = gs_block[i][1];\r
+ if(0 <= x && x < 60 && 0 <= y && y < 8) {\r
+ int px = x * 8;\r
+ int py = y * 8;\r
+ for(int l = 0; l < 8; l++) {\r
+ lcd[py + l][px + 0] = ~lcd[py + l][px + 0];\r
+ lcd[py + l][px + 1] = ~lcd[py + l][px + 1];\r
+ lcd[py + l][px + 2] = ~lcd[py + l][px + 2];\r
+ lcd[py + l][px + 3] = ~lcd[py + l][px + 3];\r
+ lcd[py + l][px + 4] = ~lcd[py + l][px + 4];\r
+ lcd[py + l][px + 5] = ~lcd[py + l][px + 5];\r
+ lcd[py + l][px + 6] = ~lcd[py + l][px + 6];\r
+ lcd[py + l][px + 7] = ~lcd[py + l][px + 7];\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ for(int y = 0; y < 64; y++) {\r
+ scrntype* dest = emu->screen_buffer(y);\r
+ for(int x = 0; x < 480; x++) {\r
+ dest[x] = lcd[y][x] ? pd : pb;\r
+ }\r
+ }\r
+ } else {\r
+ for(int y = 0; y < 64; y++) {\r
+ scrntype* dest = emu->screen_buffer(y);\r
+ for(int x = 0; x < 480; x++) {\r
+ dest[x] = pb;\r
+ }\r
+ }\r
+ }\r
+}\r