OSDN Git Service

[VM][STATE] Apply new framework to some VMs.
[csp-qt/common_source_project-fm7.git] / source / src / vm / pc100 / ioctrl.cpp
index b7d7ddb..df8204f 100644 (file)
-/*\r
-       NEC PC-100 Emulator 'ePC-100'\r
-\r
-       Author : Takeda.Toshiya\r
-       Date   : 2008.07.14 -\r
-\r
-       [ i/o controller ]\r
-*/\r
-\r
-#include "ioctrl.h"\r
-#include "../beep.h"\r
-#include "../i8259.h"\r
-#include "../pcm1bit.h"\r
-#include "../upd765a.h"\r
-#include "../../fifo.h"\r
-\r
-static const int key_table[256] = {\r
-         -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,0x18,0x12,  -1,  -1,  -1,0x38,  -1,  -1,\r
-         -1,0x04,0x05,0x09,  -1,  -1,  -1,  -1,  -1,0x10,  -1,0x11,  -1,  -1,  -1,  -1,\r
-       0x4A,  -1,  -1,0x5B,0x5A,0x15,0x13,0x16,0x14,  -1,  -1,  -1,  -1,0x17,  -1,  -1,\r
-       0x27,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20,0x26,  -1,  -1,  -1,  -1,  -1,  -1,\r
-         -1,0x31,0x45,0x43,0x33,0x23,0x34,0x35,0x36,0x30,0x3F,0x40,0x3B,0x47,0x46,0x2B,\r
-       0x29,0x21,0x2C,0x32,0x2D,0x2F,0x44,0x22,0x3A,0x2E,0x39,  -1,  -1,  -1,  -1,  -1,\r
-       0x4B,0x4F,0x50,0x51,0x52,0x53,0x54,0x56,0x57,0x58,0x59,0x55,  -1,0x5C,0x4D,0x5D,\r
-       0x0B,0x0C,0x0D,0x0E,0x0F,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,\r
-         -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,\r
-         -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,\r
-         -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,\r
-         -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,0x3D,0x3C,0x48,0x28,0x41,0x42,\r
-       0x2A,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,\r
-         -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,0x37,0x25,0x3E,0x24,  -1,\r
-         -1,  -1,0x49,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,\r
-         -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1\r
-};\r
-\r
-#define EVENT_KEY      0\r
-#define EVENT_600HZ    1\r
-#define EVENT_100HZ    2\r
-#define EVENT_50HZ     3\r
-#define EVENT_10HZ     4\r
-\r
-void IOCTRL::initialize()\r
-{\r
-       // init keyboard\r
-       key_stat = emu->key_buffer();\r
-       mouse_stat = emu->mouse_buffer();\r
-       key_buf = new FIFO(64);\r
-       caps = kana = false;\r
-       \r
-       // timer\r
-       ts = 0;\r
-       \r
-       // register event\r
-       register_event_by_clock(this, EVENT_600HZ, CPU_CLOCKS / 600, true, NULL);\r
-       register_event_by_clock(this, EVENT_100HZ, CPU_CLOCKS / 100, true, NULL);\r
-       register_event_by_clock(this, EVENT_50HZ, CPU_CLOCKS / 50, true, NULL);\r
-       register_event_by_clock(this, EVENT_10HZ, CPU_CLOCKS / 10, true, NULL);\r
-}\r
-\r
-void IOCTRL::release()\r
-{\r
-       key_buf->release();\r
-       delete key_buf;\r
-}\r
-\r
-void IOCTRL::reset()\r
-{\r
-       key_val = key_mouse = 0;\r
-       key_prev = -1;\r
-       key_res = false;\r
-       key_done = true;\r
-       key_buf->clear();\r
-       key_buf->write(0x1f0);\r
-       key_buf->write(0x100);\r
-       register_id = -1;\r
-       update_key();\r
-}\r
-\r
-void IOCTRL::write_io8(uint32 addr, uint32 data)\r
-{\r
-       switch(addr & 0x3f0) {\r
-       case 0x22:\r
-               ts = (data >> 3) & 3;\r
-               d_beep->write_signal(SIG_BEEP_ON, ~data, 0x40);         // tone (2400hz)\r
-               d_pcm->write_signal(SIG_PCM1BIT_ON, data, 0x40);        // direct\r
-               d_pcm->write_signal(SIG_PCM1BIT_SIGNAL, data, 0x80);    // signal\r
-               break;\r
-       case 0x24:\r
-               // tc/vfo\r
-               d_fdc->write_signal(SIG_UPD765A_TC, data, 0x40);\r
-               break;\r
-       }\r
-}\r
-\r
-uint32 IOCTRL::read_io8(uint32 addr)\r
-{\r
-       switch(addr & 0x3ff) {\r
-       case 0x20:\r
-               key_done = true;\r
-               update_key();\r
-               return key_val;\r
-       case 0x22:\r
-               if(config.monitor_type) {\r
-                       return key_mouse | 0x0d;        // virt monitor\r
-               } else {\r
-                       return key_mouse | 0x2d;        // horiz monitor\r
-               }\r
-       }\r
-       return 0xff;\r
-}\r
-\r
-void IOCTRL::event_callback(int event_id, int err)\r
-{\r
-       if(event_id == EVENT_KEY) {\r
-               if(!key_buf->empty()) {\r
-                       key_val = key_buf->read();\r
-                       key_mouse = (key_val & 0x100) ? 0x10 : 0;\r
-                       key_val &= 0xff;\r
-                       key_done = false;\r
-                       d_pic->write_signal(SIG_I8259_IR3, 1, 1);\r
-               }\r
-               register_id = -1;\r
-       } else if(event_id == EVENT_600HZ) {\r
-               if(ts == 0) {\r
-                       d_pic->write_signal(SIG_I8259_IR2, 1, 1);\r
-               }\r
-       } else if(event_id == EVENT_100HZ) {\r
-               if(ts == 1) {\r
-                       d_pic->write_signal(SIG_I8259_IR2, 1, 1);\r
-               }\r
-       } else if(event_id == EVENT_50HZ) {\r
-               if(ts == 2) {\r
-                       d_pic->write_signal(SIG_I8259_IR2, 1, 1);\r
-               }\r
-               // mouse\r
-               if(key_buf->empty()) {\r
-                       uint8 val = 0;\r
-                       if(!(mouse_stat[2] & 1)) val |= 1;\r
-                       if(!(mouse_stat[2] & 2)) val |= 2;\r
-                       if(caps) val |= 0x10;\r
-                       if(kana) val |= 0x20;\r
-                       if(key_stat[0xa0]) val |= 0x40; // lshift\r
-                       if(key_stat[0xa1]) val |= 0x80; // rshift\r
-                       if(mouse_stat[0] || mouse_stat[1]) {\r
-                               key_buf->write(val | 4);\r
-                               key_buf->write(mouse_stat[0] & 0xff);\r
-                               key_buf->write(mouse_stat[1] & 0xff);\r
-                               update_key();\r
-                               key_prev = val;\r
-                       } else if(key_prev != val) {\r
-                               key_buf->write(val);\r
-                               update_key();\r
-                               key_prev = val;\r
-                       }\r
-               }\r
-       } else if(event_id == EVENT_10HZ) {\r
-               if(ts == 3) {\r
-                       d_pic->write_signal(SIG_I8259_IR2, 1, 1);\r
-               }\r
-       }\r
-}\r
-\r
-void IOCTRL::write_signal(int id, uint32 data, uint32 mask)\r
-{\r
-       bool next = ((data & mask) != 0);\r
-       if(!key_res && next) {\r
-               // reset\r
-               caps = kana = false;\r
-               key_buf->clear();\r
-               key_buf->write(0x1f0);  // dummy\r
-               key_buf->write(0x1f0);  // init code\r
-               key_buf->write(0x100);  // error code\r
-               key_done = true;\r
-               update_key();\r
-       }\r
-       key_res = next;\r
-}\r
-\r
-void IOCTRL::key_down(int code)\r
-{\r
-       if(code == 0x14) {\r
-               caps = !caps;\r
-       } else if(code == 0x15) {\r
-               kana = !kana;\r
-       } else if((code = key_table[code & 0xff]) != -1) {\r
-               code |= 0x80;\r
-               key_buf->write(code | 0x100);\r
-               update_key();\r
-       }\r
-}\r
-\r
-void IOCTRL::key_up(int code)\r
-{\r
-       if((code = key_table[code & 0xff]) != -1) {\r
-               code &= ~0x80;\r
-               key_buf->write(code | 0x100);\r
-               update_key();\r
-       }\r
-}\r
-\r
-void IOCTRL::update_key()\r
-{\r
-       if(key_done && !key_buf->empty()) {\r
-               if(register_id == -1) {\r
-                       register_event(this, EVENT_KEY, 1000, false, &register_id);\r
-               }\r
-       }\r
-}\r
-\r
+/*
+       NEC PC-100 Emulator 'ePC-100'
+
+       Author : Takeda.Toshiya
+       Date   : 2008.07.14 -
+
+       [ i/o controller ]
+*/
+
+#include "ioctrl.h"
+#include "../beep.h"
+#include "../i8259.h"
+#include "../pcm1bit.h"
+#include "../upd765a.h"
+#include "../../fifo.h"
+
+static const int key_table[256] = {
+         -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,0x18,0x12,  -1,  -1,  -1,0x38,  -1,  -1,
+         -1,0x04,0x05,0x09,  -1,  -1,  -1,  -1,  -1,0x10,  -1,0x11,  -1,  -1,  -1,  -1,
+       0x4A,  -1,  -1,0x5B,0x5A,0x15,0x13,0x16,0x14,  -1,  -1,  -1,  -1,0x17,  -1,  -1,
+       0x27,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20,0x26,  -1,  -1,  -1,  -1,  -1,  -1,
+         -1,0x31,0x45,0x43,0x33,0x23,0x34,0x35,0x36,0x30,0x3F,0x40,0x3B,0x47,0x46,0x2B,
+       0x29,0x21,0x2C,0x32,0x2D,0x2F,0x44,0x22,0x3A,0x2E,0x39,  -1,  -1,  -1,  -1,  -1,
+       0x4B,0x4F,0x50,0x51,0x52,0x53,0x54,0x56,0x57,0x58,0x59,0x55,  -1,0x5C,0x4D,0x5D,
+       0x0B,0x0C,0x0D,0x0E,0x0F,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
+         -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
+         -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
+         -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
+         -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,0x3D,0x3C,0x48,0x28,0x41,0x42,
+       0x2A,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
+         -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,0x37,0x25,0x3E,0x24,  -1,
+         -1,  -1,0x49,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
+         -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1
+};
+
+#define EVENT_KEY      0
+#define EVENT_600HZ    1
+#define EVENT_100HZ    2
+#define EVENT_50HZ     3
+#define EVENT_10HZ     4
+
+void IOCTRL::initialize()
+{
+       // init keyboard
+       key_stat = emu->get_key_buffer();
+       mouse_stat = emu->get_mouse_buffer();
+       key_buf = new FIFO(64);
+       caps = kana = false;
+       
+       // timer
+       ts = 0;
+       
+       // register event
+       register_event_by_clock(this, EVENT_600HZ, CPU_CLOCKS / 600, true, NULL);
+       register_event_by_clock(this, EVENT_100HZ, CPU_CLOCKS / 100, true, NULL);
+       register_event_by_clock(this, EVENT_50HZ, CPU_CLOCKS / 50, true, NULL);
+       register_event_by_clock(this, EVENT_10HZ, CPU_CLOCKS / 10, true, NULL);
+}
+
+void IOCTRL::release()
+{
+       key_buf->release();
+       delete key_buf;
+}
+
+void IOCTRL::reset()
+{
+       key_val = key_mouse = 0;
+       key_prev = -1;
+       key_res = false;
+       key_done = true;
+       key_buf->clear();
+       key_buf->write(0x1f0);
+       key_buf->write(0x100);
+       register_id = -1;
+       update_key();
+}
+
+void IOCTRL::write_io8(uint32_t addr, uint32_t data)
+{
+       switch(addr & 0x3f0) {
+       case 0x22:
+               ts = (data >> 3) & 3;
+               d_beep->write_signal(SIG_BEEP_ON, ~data, 0x40);         // tone (2400hz)
+               d_pcm->write_signal(SIG_PCM1BIT_ON, data, 0x40);        // direct
+               d_pcm->write_signal(SIG_PCM1BIT_SIGNAL, data, 0x80);    // signal
+               break;
+       case 0x24:
+               // tc/vfo
+               d_fdc->write_signal(SIG_UPD765A_TC, data, 0x40);
+               break;
+       }
+}
+
+uint32_t IOCTRL::read_io8(uint32_t addr)
+{
+       switch(addr & 0x3ff) {
+       case 0x20:
+               key_done = true;
+               update_key();
+               return key_val;
+       case 0x22:
+               // bit1: 0 = Color Mode, 1 = Monochrome Mode
+               // bit2: 1 = Double FDD, 0 = Single FDD
+               // bit3: 1 = 2D, 0 = 2DD
+               // bit4: 1 = KD, 0 = MD
+               // bit5: 1 = Horizontal Monitor, 0 = Virtical Monitor
+               {
+                       uint32_t value = key_mouse | 0x05;
+                       if(!config.drive_type) {
+                               value |= 0x08; // 2D
+                       }
+                       if(!config.monitor_type) {
+                               value |= 0x20; // Horizontal Monitor
+                       }
+                       return value;
+               }
+       }
+       return 0xff;
+}
+
+void IOCTRL::event_callback(int event_id, int err)
+{
+       if(event_id == EVENT_KEY) {
+               if(!key_buf->empty()) {
+                       key_val = key_buf->read();
+                       key_mouse = (key_val & 0x100) ? 0x10 : 0;
+                       key_val &= 0xff;
+                       key_done = false;
+                       d_pic->write_signal(SIG_I8259_IR3, 1, 1);
+               }
+               register_id = -1;
+       } else if(event_id == EVENT_600HZ) {
+               if(ts == 0) {
+                       d_pic->write_signal(SIG_I8259_IR2, 1, 1);
+               }
+       } else if(event_id == EVENT_100HZ) {
+               if(ts == 1) {
+                       d_pic->write_signal(SIG_I8259_IR2, 1, 1);
+               }
+       } else if(event_id == EVENT_50HZ) {
+               if(ts == 2) {
+                       d_pic->write_signal(SIG_I8259_IR2, 1, 1);
+               }
+               // mouse
+               if(key_buf->empty()) {
+                       uint8_t val = 0;
+                       if(!(mouse_stat[2] & 1)) val |= 1;
+                       if(!(mouse_stat[2] & 2)) val |= 2;
+                       if(caps) val |= 0x10;
+                       if(kana) val |= 0x20;
+                       if(key_stat[0xa0]) val |= 0x40; // lshift
+                       if(key_stat[0xa1]) val |= 0x80; // rshift
+                       if(mouse_stat[0] || mouse_stat[1]) {
+                               key_buf->write(val | 4);
+                               key_buf->write(mouse_stat[0] & 0xff);
+                               key_buf->write(mouse_stat[1] & 0xff);
+                               update_key();
+                               key_prev = val;
+                       } else if(key_prev != val) {
+                               key_buf->write(val);
+                               update_key();
+                               key_prev = val;
+                       }
+               }
+       } else if(event_id == EVENT_10HZ) {
+               if(ts == 3) {
+                       d_pic->write_signal(SIG_I8259_IR2, 1, 1);
+               }
+       }
+}
+
+void IOCTRL::write_signal(int id, uint32_t data, uint32_t mask)
+{
+       bool next = ((data & mask) != 0);
+       if(!key_res && next) {
+               // reset
+               caps = kana = false;
+               key_buf->clear();
+               key_buf->write(0x1f0);  // dummy
+               key_buf->write(0x1f0);  // init code
+               key_buf->write(0x100);  // error code
+               key_done = true;
+               update_key();
+       }
+       key_res = next;
+}
+
+void IOCTRL::key_down(int code)
+{
+       if(code == 0x14) {
+               caps = !caps;
+       } else if(code == 0x15) {
+               kana = !kana;
+       } else if((code = key_table[code & 0xff]) != -1) {
+               code |= 0x80;
+               key_buf->write(code | 0x100);
+               update_key();
+       }
+}
+
+void IOCTRL::key_up(int code)
+{
+       if((code = key_table[code & 0xff]) != -1) {
+               code &= ~0x80;
+               key_buf->write(code | 0x100);
+               update_key();
+       }
+}
+
+void IOCTRL::update_key()
+{
+       if(key_done && !key_buf->empty()) {
+               if(register_id == -1) {
+                       register_event(this, EVENT_KEY, 1000, false, &register_id);
+               }
+       }
+}
+
+#define STATE_VERSION  1
+
+bool IOCTRL::process_state(FILEIO* state_fio, bool loading)
+{
+       if(!state_fio->StateCheckUint32(STATE_VERSION)) {
+               return false;
+       }
+       if(!state_fio->StateCheckInt32(this_device_id)) {
+               return false;
+       }
+       state_fio->StateBool(caps);
+       state_fio->StateBool(kana);
+       if(!key_buf->process_state((void *)state_fio, loading)) {
+               return false;
+       }
+       state_fio->StateUint32(key_val);
+       state_fio->StateUint32(key_mouse);
+       state_fio->StateInt32(key_prev);
+       state_fio->StateBool(key_res);
+       state_fio->StateBool(key_done);
+       state_fio->StateInt32(register_id);
+       state_fio->StateUint8(ts);
+       return true;
+}