OSDN Git Service

55713ca4d62e7116ac5109c0c5c4834b7edb8bcb
[csp-qt/common_source_project-fm7.git] / source / src / vm / pc100 / pc100.cpp
1 /*\r
2         NEC PC-100 Emulator 'ePC-100'\r
3 \r
4         Author : Takeda.Toshiya\r
5         Date   : 2008.07.12 -\r
6 \r
7         [ virtual machine ]\r
8 */\r
9 \r
10 #include "pc100.h"\r
11 #include "../../emu.h"\r
12 #include "../device.h"\r
13 #include "../event.h"\r
14 \r
15 #include "../and.h"\r
16 #include "../beep.h"\r
17 #include "../disk.h"\r
18 #include "../i8251.h"\r
19 #include "../i8255.h"\r
20 #include "../i8259.h"\r
21 #include "../i286.h"\r
22 #include "../io.h"\r
23 #include "../memory.h"\r
24 #include "../msm58321.h"\r
25 #include "../pcm1bit.h"\r
26 #include "../upd765a.h"\r
27 \r
28 #ifdef USE_DEBUGGER\r
29 #include "../debugger.h"\r
30 #endif\r
31 \r
32 #include "crtc.h"\r
33 #include "ioctrl.h"\r
34 #include "kanji.h"\r
35 \r
36 #include "../../fileio.h"\r
37 \r
38 // ----------------------------------------------------------------------------\r
39 // initialize\r
40 // ----------------------------------------------------------------------------\r
41 \r
42 VM::VM(EMU* parent_emu) : emu(parent_emu)\r
43 {\r
44         // create devices\r
45         first_device = last_device = NULL;\r
46         dummy = new DEVICE(this, emu);  // must be 1st device\r
47         event = new EVENT(this, emu);   // must be 2nd device\r
48         \r
49         and = new AND(this, emu);\r
50         beep = new BEEP(this, emu);\r
51         sio = new I8251(this, emu);\r
52         pio0 = new I8255(this, emu);\r
53         pio1 = new I8255(this, emu);\r
54         pic = new I8259(this, emu);\r
55         cpu = new I286(this, emu);\r
56         io = new IO(this, emu);\r
57         memory = new MEMORY(this, emu);\r
58         rtc = new MSM58321(this, emu);\r
59         pcm = new PCM1BIT(this, emu);\r
60         fdc = new UPD765A(this, emu);\r
61         \r
62         crtc = new CRTC(this, emu);\r
63         ioctrl = new IOCTRL(this, emu);\r
64         kanji = new KANJI(this, emu);\r
65         \r
66         // set contexts\r
67         event->set_context_cpu(cpu);\r
68         event->set_context_sound(beep);\r
69         event->set_context_sound(pcm);\r
70         \r
71         and->set_context_out(cpu, SIG_CPU_NMI, 1);\r
72         and->set_mask(SIG_AND_BIT_0 | SIG_AND_BIT_1);\r
73         sio->set_context_rxrdy(pic, SIG_I8259_IR1, 1);\r
74         pio0->set_context_port_a(rtc, SIG_MSM58321_READ, 1, 0);\r
75         pio0->set_context_port_a(rtc, SIG_MSM58321_WRITE, 2, 0);\r
76         pio0->set_context_port_a(rtc, SIG_MSM58321_ADDR_WRITE, 4, 0);\r
77         pio0->set_context_port_c(rtc, SIG_MSM58321_DATA, 0x0f, 0);\r
78         pio1->set_context_port_a(crtc, SIG_CRTC_BITMASK_LOW, 0xff, 0);\r
79         pio1->set_context_port_b(crtc, SIG_CRTC_BITMASK_HIGH, 0xff, 0);\r
80         pio1->set_context_port_c(crtc, SIG_CRTC_VRAM_PLANE, 0x3f, 0);\r
81         pio1->set_context_port_c(and, SIG_AND_BIT_0, 0x80, 0);\r
82         pio1->set_context_port_c(ioctrl, SIG_IOCTRL_RESET, 0x40, 0);\r
83         pic->set_context_cpu(cpu);\r
84         rtc->set_context_data(pio0, SIG_I8255_PORT_C, 0x0f, 0);\r
85         rtc->set_context_busy(pio0, SIG_I8255_PORT_C, 0x10);\r
86         fdc->set_context_irq(cpu, SIG_CPU_NMI, 1);\r
87         fdc->set_context_drq(and, SIG_AND_BIT_1, 1);\r
88         \r
89         crtc->set_context_pic(pic);\r
90         ioctrl->set_context_pic(pic);\r
91         ioctrl->set_context_fdc(fdc);\r
92         ioctrl->set_context_beep(beep);\r
93         ioctrl->set_context_pcm(pcm);\r
94         \r
95         // cpu bus\r
96         cpu->set_context_mem(memory);\r
97         cpu->set_context_io(io);\r
98         cpu->set_context_intr(pic);\r
99 #ifdef USE_DEBUGGER\r
100         cpu->set_context_debugger(new DEBUGGER(this, emu));\r
101 #endif\r
102         \r
103         // memory bus\r
104         memset(ram, 0, sizeof(ram));\r
105         memset(ipl, 0xff, sizeof(ipl));\r
106         \r
107         memory->read_bios(_T("IPL.ROM"), ipl, sizeof(ipl));\r
108         \r
109         memory->set_memory_rw(0x00000, 0xbffff, ram);\r
110         memory->set_memory_mapped_io_rw(0xc0000, 0xdffff, crtc);\r
111         memory->set_memory_r(0xf8000, 0xfffff, ipl);\r
112         \r
113         // i/o bus\r
114         io->set_iomap_alias_rw(0x00, pic, 0);\r
115         io->set_iomap_alias_rw(0x02, pic, 1);\r
116 //      io->set_iomap_alias_rw(0x04, dma, 0);\r
117 //      io->set_iomap_alias_rw(0x06, dma, 1);\r
118         io->set_iomap_alias_r(0x08, fdc, 0);\r
119         io->set_iomap_alias_rw(0x0a, fdc, 1);\r
120         io->set_iomap_alias_rw(0x10, pio0, 0);\r
121         io->set_iomap_alias_rw(0x12, pio0, 1);\r
122         io->set_iomap_alias_rw(0x14, pio0, 2);\r
123         io->set_iomap_alias_rw(0x16, pio0, 3);\r
124         io->set_iomap_alias_rw(0x18, pio1, 0);\r
125         io->set_iomap_alias_rw(0x1a, pio1, 1);\r
126         io->set_iomap_alias_rw(0x1c, pio1, 2);\r
127         io->set_iomap_alias_rw(0x1e, pio1, 3);\r
128         io->set_iomap_single_r(0x20, ioctrl);\r
129         io->set_iomap_single_rw(0x22, ioctrl);\r
130         io->set_iomap_single_w(0x24, ioctrl);\r
131         io->set_iomap_alias_rw(0x28, sio, 0);\r
132         io->set_iomap_alias_rw(0x2a, sio, 1);\r
133         io->set_iomap_single_rw(0x30, crtc);\r
134         io->set_iomap_single_rw(0x38, crtc);\r
135         io->set_iomap_single_rw(0x3a, crtc);\r
136         io->set_iomap_single_rw(0x3c, crtc);\r
137         io->set_iomap_single_rw(0x3e, crtc);\r
138         for(int i = 0x40; i < 0x62; i++) {\r
139                 io->set_iomap_single_rw(i, crtc);\r
140         }\r
141         io->set_iomap_single_rw(0x80, kanji);\r
142         io->set_iomap_single_rw(0x81, kanji);\r
143         io->set_iomap_single_w(0x84, kanji);\r
144         io->set_iomap_single_w(0x86, kanji);\r
145         \r
146         // initialize all devices\r
147         for(DEVICE* device = first_device; device; device = device->next_device) {\r
148                 device->initialize();\r
149         }\r
150         for(int i = 0; i < 4; i++) {\r
151                 fdc->set_drive_type(i, DRIVE_TYPE_2D);\r
152         }\r
153 }\r
154 \r
155 VM::~VM()\r
156 {\r
157         // delete all devices\r
158         for(DEVICE* device = first_device; device;) {\r
159                 DEVICE *next_device = device->next_device;\r
160                 device->release();\r
161                 delete device;\r
162                 device = next_device;\r
163         }\r
164 }\r
165 \r
166 DEVICE* VM::get_device(int id)\r
167 {\r
168         for(DEVICE* device = first_device; device; device = device->next_device) {\r
169                 if(device->this_device_id == id) {\r
170                         return device;\r
171                 }\r
172         }\r
173         return NULL;\r
174 }\r
175 \r
176 // ----------------------------------------------------------------------------\r
177 // drive virtual machine\r
178 // ----------------------------------------------------------------------------\r
179 \r
180 void VM::reset()\r
181 {\r
182         // reset all devices\r
183         for(DEVICE* device = first_device; device; device = device->next_device) {\r
184                 device->reset();\r
185         }\r
186 }\r
187 \r
188 void VM::run()\r
189 {\r
190         event->drive();\r
191 }\r
192 \r
193 // ----------------------------------------------------------------------------\r
194 // debugger\r
195 // ----------------------------------------------------------------------------\r
196 \r
197 #ifdef USE_DEBUGGER\r
198 DEVICE *VM::get_cpu(int index)\r
199 {\r
200         if(index == 0) {\r
201                 return cpu;\r
202         }\r
203         return NULL;\r
204 }\r
205 #endif\r
206 \r
207 // ----------------------------------------------------------------------------\r
208 // draw screen\r
209 // ----------------------------------------------------------------------------\r
210 \r
211 void VM::draw_screen()\r
212 {\r
213         crtc->draw_screen();\r
214 }\r
215 \r
216 int VM::access_lamp()\r
217 {\r
218         uint32 status = fdc->read_signal(0);\r
219         return (status & (1 | 4)) ? 1 : (status & (2 | 8)) ? 2 : 0;\r
220 }\r
221 \r
222 // ----------------------------------------------------------------------------\r
223 // soud manager\r
224 // ----------------------------------------------------------------------------\r
225 \r
226 void VM::initialize_sound(int rate, int samples)\r
227 {\r
228         // init sound manager\r
229         event->initialize_sound(rate, samples);\r
230         \r
231         // init sound gen\r
232         beep->init(rate, 2400, 8000);\r
233         pcm->init(rate, 8000);\r
234 }\r
235 \r
236 uint16* VM::create_sound(int* extra_frames)\r
237 {\r
238         return event->create_sound(extra_frames);\r
239 }\r
240 \r
241 int VM::sound_buffer_ptr()\r
242 {\r
243         return event->sound_buffer_ptr();\r
244 }\r
245 \r
246 // ----------------------------------------------------------------------------\r
247 // notify key\r
248 // ----------------------------------------------------------------------------\r
249 \r
250 void VM::key_down(int code, bool repeat)\r
251 {\r
252         ioctrl->key_down(code);\r
253 }\r
254 \r
255 void VM::key_up(int code)\r
256 {\r
257         ioctrl->key_up(code);\r
258 }\r
259 \r
260 // ----------------------------------------------------------------------------\r
261 // user interface\r
262 // ----------------------------------------------------------------------------\r
263 \r
264 void VM::open_disk(int drv, _TCHAR* file_path, int offset)\r
265 {\r
266         fdc->open_disk(drv, file_path, offset);\r
267 }\r
268 \r
269 void VM::close_disk(int drv)\r
270 {\r
271         fdc->close_disk(drv);\r
272 }\r
273 \r
274 bool VM::disk_inserted(int drv)\r
275 {\r
276         return fdc->disk_inserted(drv);\r
277 }\r
278 \r
279 bool VM::now_skip()\r
280 {\r
281         return event->now_skip();\r
282 }\r
283 \r
284 void VM::update_config()\r
285 {\r
286         for(DEVICE* device = first_device; device; device = device->next_device) {\r
287                 device->update_config();\r
288         }\r
289 }\r
290 \r
291 #define STATE_VERSION   1\r
292 \r
293 void VM::save_state(FILEIO* state_fio)\r
294 {\r
295         state_fio->FputUint32(STATE_VERSION);\r
296         \r
297         for(DEVICE* device = first_device; device; device = device->next_device) {\r
298                 device->save_state(state_fio);\r
299         }\r
300         state_fio->Fwrite(ram, sizeof(ram), 1);\r
301 }\r
302 \r
303 bool VM::load_state(FILEIO* state_fio)\r
304 {\r
305         if(state_fio->FgetUint32() != STATE_VERSION) {\r
306                 return false;\r
307         }\r
308         for(DEVICE* device = first_device; device; device = device->next_device) {\r
309                 if(!device->load_state(state_fio)) {\r
310                         return false;\r
311                 }\r
312         }\r
313         state_fio->Fread(ram, sizeof(ram), 1);\r
314         return true;\r
315 }\r
316 \r