OSDN Git Service

[INITIAL] Import 20141226 version of http://homepage3.nifty.com/takeda-toshiya/common...
[csp-qt/common_source_project-fm7.git] / source / src / vm / hc80 / io.cpp
diff --git a/source/src/vm/hc80/io.cpp b/source/src/vm/hc80/io.cpp
new file mode 100644 (file)
index 0000000..8b4e8a8
--- /dev/null
@@ -0,0 +1,1897 @@
+/*\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, &register_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, &register_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