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 / fm16pi / sub.cpp
1 /*\r
2         FUJITSU FM16pi Emulator 'eFM16pi'\r
3 \r
4         Author : Takeda.Toshiya\r
5         Date   : 2010.12.25-\r
6 \r
7         [ sub system ]\r
8 */\r
9 \r
10 #include "sub.h"\r
11 #include "../../fifo.h"\r
12 #include "../i8255.h"\r
13 #include "../i8259.h"\r
14 #include "../mb8877.h"\r
15 #include "../msm58321.h"\r
16 #include "../pcm1bit.h"\r
17 \r
18 #define EVENT_KEYSCAN   0\r
19 \r
20 static const int key_table[256] = {\r
21         // EXT -> END, GRAPH -> ALT\r
22           -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,0x0E,0x0F,  -1,  -1,  -1,0x1C,  -1,  -1,\r
23         0x37,0x36,0x3C,0x3E,0x39,0x3D,  -1,  -1,  -1,  -1,  -1,0x01,0x3B,0x3A,  -1,  -1,\r
24         0x34,  -1,  -1,0x44,0x47,0x48,0x49,0x4B,0x4A,  -1,  -1,  -1,  -1,0x45,0x46,  -1,\r
25         0x0B,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,  -1,  -1,  -1,  -1,  -1,  -1,\r
26           -1,0x1D,0x2D,0x2B,0x1F,0x12,0x20,0x21,0x22,0x17,0x23,0x24,0x25,0x2F,0x2E,0x18,\r
27         0x19,0x10,0x13,0x1E,0x14,0x16,0x2C,0x11,0x2A,0x15,0x29,  -1,  -1,  -1,  -1,  -1,\r
28         0x0B,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,  -1,  -1,  -1,  -1,0x31,  -1,\r
29         0x3F,0x40,0x41,0x42,0x43,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,\r
30           -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,\r
31           -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,\r
32           -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,\r
33           -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,0x27,0x26,0x30,0x0C,0x31,0x32,\r
34         0x1A,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,\r
35           -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,0x1B,0x35,0x28,0x0D,  -1,\r
36           -1,  -1,0x33,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,\r
37           -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,\r
38 };\r
39 \r
40 void SUB::initialize()\r
41 {\r
42         key_buffer = new FIFO(16);\r
43         \r
44         // key scan (15ms)\r
45         register_event(this, EVENT_KEYSCAN, 15000, true, NULL);\r
46 }\r
47 \r
48 void SUB::release()\r
49 {\r
50         key_buffer->release();\r
51         delete key_buffer;\r
52 }\r
53 \r
54 void SUB::reset()\r
55 {\r
56         key_buffer->clear();\r
57         key_buffer->write(0xf0);        // self check result\r
58         key_data = 0xf0;\r
59         key_irq = false;\r
60         fdc_drive = fdc_side = 0;       // 0xff ???\r
61         rtc_data = 0;\r
62 }\r
63 \r
64 void SUB::write_io8(uint32 addr, uint32 data)\r
65 {\r
66         switch(addr) {\r
67         case 0x40:\r
68                 d_rtc->write_signal(SIG_MSM58321_CS, data, 0x10);\r
69                 d_rtc->write_signal(SIG_MSM58321_ADDR_WRITE, data, 0x20);       // prev data is written\r
70                 d_rtc->write_signal(SIG_MSM58321_DATA, data, 0x0f);\r
71                 d_rtc->write_signal(SIG_MSM58321_READ, data, 0x40);\r
72                 d_rtc->write_signal(SIG_MSM58321_WRITE, data, 0x80);            // current data is written\r
73                 break;\r
74         case 0xa0:\r
75                 if(!(data & 8)) {\r
76                         d_pic->write_signal(SIG_I8259_IR6, 0, 0);       // printer ack\r
77                 }\r
78                 if(!(data & 0x10)) {\r
79                         d_pic->write_signal(SIG_I8259_IR0, 0, 0);       // interval timer\r
80                         d_pio->write_signal(SIG_I8255_PORT_B, 0x20, 0x20);\r
81                 }\r
82                 if(data & 0x20) {\r
83                         // power off\r
84                         emu->power_off();\r
85                 }\r
86                 d_pcm->write_signal(SIG_PCM1BIT_ON, data, 0x40);\r
87                 rtc_data |= data & 0x80;\r
88                 break;\r
89         case 0xc8:\r
90                 d_fdc->write_signal(SIG_MB8877_SIDEREG, data, 1);\r
91                 fdc_side = data;\r
92                 break;\r
93         case 0xca:\r
94                 d_fdc->write_signal(SIG_MB8877_DRIVEREG, data, 3);\r
95                 // bit6: drive disable (1=disable)\r
96                 d_fdc->write_signal(SIG_MB8877_MOTOR, data, 0x80);\r
97                 fdc_drive = data;\r
98                 break;\r
99         }\r
100 }\r
101 \r
102 uint32 SUB::read_io8(uint32 addr)\r
103 {\r
104         switch(addr) {\r
105         case 0x40:\r
106                 return rtc_data;\r
107         case 0x60:\r
108                 if(key_irq) {\r
109                         d_pic->write_signal(SIG_I8259_IR4, 0, 0);\r
110                         d_pio->write_signal(SIG_I8255_PORT_C, 8, 8);\r
111                         key_irq = false;\r
112                 }\r
113                 return key_data;\r
114         case 0xc8:\r
115                 return fdc_side;\r
116         case 0xca:\r
117                 return fdc_drive;\r
118         }\r
119         return 0xff;\r
120 }\r
121 \r
122 void SUB::write_signal(int id, uint32 data, uint32 mask)\r
123 {\r
124         if(id == SIG_SUB_RTC) {\r
125                 // bit0-3: rtc data\r
126                 // bit4:   rtc busy\r
127                 rtc_data = (rtc_data & ~mask) | (data & mask);\r
128         }\r
129 }\r
130 \r
131 void SUB::event_callback(int event_id, int err)\r
132 {\r
133         if(!key_buffer->empty() && !key_irq) {\r
134                 d_pic->write_signal(SIG_I8259_IR4, 1, 1);\r
135                 d_pio->write_signal(SIG_I8255_PORT_C, 0, 8);\r
136                 key_irq = true;\r
137                 key_data = key_buffer->read();\r
138         }\r
139 }\r
140 \r
141 void SUB::key_down(int code)\r
142 {\r
143         if((code = key_table[code]) != -1) {\r
144                 key_buffer->write(code);\r
145         }\r
146 }\r
147 \r
148 void SUB::key_up(int code)\r
149 {\r
150         if((code = key_table[code]) != -1) {\r
151                 key_buffer->write(code | 0x80);\r
152         }\r
153 }\r
154 \r
155 void SUB::notify_power_off()\r
156 {\r
157         if(rtc_data & 0x80) {\r
158                 d_cpu->write_signal(SIG_CPU_NMI, 1, 1);\r
159         }\r
160 }\r
161 \r
162 void SUB::draw_screen()\r
163 {\r
164         // 640x200, msb->lsb\r
165         scrntype cd = RGB_COLOR(48, 56, 16);\r
166         scrntype cb = RGB_COLOR(160, 168, 160);\r
167         \r
168         for(int y = 0, ptr = 0; y < 200; y++) {\r
169                 scrntype *dest = emu->screen_buffer(y);\r
170                 for(int x = 0; x < 640; x += 8) {\r
171                         uint8 pat = vram[ptr++];\r
172                         dest[0] = (pat & 0x80) ? cd : cb;\r
173                         dest[1] = (pat & 0x40) ? cd : cb;\r
174                         dest[2] = (pat & 0x20) ? cd : cb;\r
175                         dest[3] = (pat & 0x10) ? cd : cb;\r
176                         dest[4] = (pat & 0x08) ? cd : cb;\r
177                         dest[5] = (pat & 0x04) ? cd : cb;\r
178                         dest[6] = (pat & 0x02) ? cd : cb;\r
179                         dest[7] = (pat & 0x01) ? cd : cb;\r
180                         dest += 8;\r
181                 }\r
182         }\r
183 }\r
184 \r