OSDN Git Service

[General] Tracking to upstream, rev 2015-01-14.
[csp-qt/common_source_project-fm7.git] / source / src / vm / mz2500 / mz2500.cpp
1 /*\r
2         SHARP MZ-2500 Emulator 'EmuZ-2500'\r
3 \r
4         Author : Takeda.Toshiya\r
5         Date   : 2006.11.24 -\r
6 \r
7         [ virtual machine ]\r
8 */\r
9 \r
10 #include "mz2500.h"\r
11 #include "../../emu.h"\r
12 #include "../device.h"\r
13 #include "../event.h"\r
14 \r
15 #include "../datarec.h"\r
16 #include "../disk.h"\r
17 #include "../i8253.h"\r
18 #include "../i8255.h"\r
19 #include "../io.h"\r
20 #include "../mb8877.h"\r
21 #include "../pcm1bit.h"\r
22 #include "../rp5c01.h"\r
23 #include "../w3100a.h"\r
24 #include "../ym2203.h"\r
25 #include "../z80.h"\r
26 #include "../z80pio.h"\r
27 #include "../z80sio.h"\r
28 \r
29 #ifdef USE_DEBUGGER\r
30 #include "../debugger.h"\r
31 #endif\r
32 \r
33 #include "calendar.h"\r
34 #include "cmt.h"\r
35 #include "crtc.h"\r
36 #include "floppy.h"\r
37 #include "interrupt.h"\r
38 #include "joystick.h"\r
39 #include "keyboard.h"\r
40 #include "memory.h"\r
41 #include "mouse.h"\r
42 #include "mz1e26.h"\r
43 #include "mz1e30.h"\r
44 #include "mz1r13.h"\r
45 #include "mz1r37.h"\r
46 #include "timer.h"\r
47 \r
48 #include "../../fileio.h"\r
49 \r
50 // ----------------------------------------------------------------------------\r
51 // initialize\r
52 // ----------------------------------------------------------------------------\r
53 \r
54 VM::VM(EMU* parent_emu) : emu(parent_emu)\r
55 {\r
56         // create devices\r
57         first_device = last_device = NULL;\r
58         dummy = new DEVICE(this, emu);  // must be 1st device\r
59         event = new EVENT(this, emu);   // must be 2nd device\r
60         \r
61         drec = new DATAREC(this, emu);\r
62         pit = new I8253(this, emu);\r
63         pio_i = new I8255(this, emu);\r
64         io = new IO(this, emu);\r
65         fdc = new MB8877(this, emu);\r
66         pcm = new PCM1BIT(this, emu);\r
67         rtc = new RP5C01(this, emu);    // RP-5C15\r
68         w3100a = new W3100A(this, emu);\r
69         opn = new YM2203(this, emu);\r
70         cpu = new Z80(this, emu);\r
71         pio = new Z80PIO(this, emu);\r
72         sio = new Z80SIO(this, emu);\r
73         \r
74         calendar = new CALENDAR(this, emu);\r
75         cmt = new CMT(this, emu);\r
76         crtc = new CRTC(this, emu);\r
77         floppy = new FLOPPY(this, emu);\r
78         interrupt = new INTERRUPT(this, emu);\r
79         joystick = new JOYSTICK(this, emu);\r
80         keyboard = new KEYBOARD(this, emu);\r
81         memory = new MEMORY(this, emu);\r
82         mouse = new MOUSE(this, emu);\r
83         mz1e26 = new MZ1E26(this, emu);\r
84         mz1e30 = new MZ1E30(this, emu);\r
85         mz1r13 = new MZ1R13(this, emu);\r
86         mz1r37 = new MZ1R37(this, emu);\r
87         timer = new TIMER(this, emu);\r
88         \r
89         // set contexts\r
90         event->set_context_cpu(cpu);\r
91         event->set_context_sound(opn);\r
92         event->set_context_sound(pcm);\r
93         event->set_context_sound(drec);\r
94         \r
95         drec->set_context_out(cmt, SIG_CMT_OUT, 1);\r
96         drec->set_context_remote(cmt, SIG_CMT_REMOTE, 1);\r
97         drec->set_context_end(cmt, SIG_CMT_END, 1);\r
98         drec->set_context_top(cmt, SIG_CMT_TOP, 1);\r
99         \r
100         pit->set_context_ch0(interrupt, SIG_INTERRUPT_I8253, 1);\r
101         pit->set_context_ch0(pit, SIG_I8253_CLOCK_1, 1);\r
102         pit->set_context_ch1(pit, SIG_I8253_CLOCK_2, 1);\r
103         pit->set_constant_clock(0, 31250);\r
104         pio_i->set_context_port_a(cmt, SIG_CMT_PIO_PA, 0xff, 0);\r
105         pio_i->set_context_port_c(cmt, SIG_CMT_PIO_PC, 0xff, 0);\r
106         pio_i->set_context_port_c(crtc, SIG_CRTC_MASK, 0x01, 0);\r
107         pio_i->set_context_port_c(pcm, SIG_PCM1BIT_SIGNAL, 0x04, 0);\r
108         rtc->set_context_alarm(interrupt, SIG_INTERRUPT_RP5C15, 1);\r
109         rtc->set_context_pulse(opn, SIG_YM2203_PORT_B, 8);\r
110         opn->set_context_port_a(floppy, SIG_FLOPPY_REVERSE, 0x02, 0);\r
111         opn->set_context_port_a(crtc, SIG_CRTC_PALLETE, 0x04, 0);\r
112         opn->set_context_port_a(mouse, SIG_MOUSE_SEL, 0x08, 0);\r
113         pio->set_context_port_a(crtc, SIG_CRTC_COLUMN_SIZE, 0x20, 0);\r
114         pio->set_context_port_a(keyboard, SIG_KEYBOARD_COLUMN, 0x1f, 0);\r
115         sio->set_context_dtr1(mouse, SIG_MOUSE_DTR, 1);\r
116         \r
117         calendar->set_context_rtc(rtc);\r
118         cmt->set_context_pio(pio_i);\r
119         cmt->set_context_drec(drec);\r
120         crtc->set_context_mem(memory);\r
121         crtc->set_context_int(interrupt);\r
122         crtc->set_context_pio(pio_i);\r
123         crtc->set_vram_ptr(memory->get_vram());\r
124         crtc->set_tvram_ptr(memory->get_tvram());\r
125         crtc->set_kanji_ptr(memory->get_kanji());\r
126         crtc->set_pcg_ptr(memory->get_pcg());\r
127         floppy->set_context_fdc(fdc);\r
128         keyboard->set_context_pio_i(pio_i);\r
129         keyboard->set_context_pio(pio);\r
130         memory->set_context_cpu(cpu);\r
131         memory->set_context_crtc(crtc);\r
132         mouse->set_context_sio(sio);\r
133         timer->set_context_pit(pit);\r
134         \r
135         // cpu bus\r
136         cpu->set_context_mem(memory);\r
137         cpu->set_context_io(io);\r
138         cpu->set_context_intr(pio);\r
139 #ifdef USE_DEBUGGER\r
140         cpu->set_context_debugger(new DEBUGGER(this, emu));\r
141 #endif\r
142         \r
143         // z80 family daisy chain\r
144         pio->set_context_intr(cpu, 0);\r
145         pio->set_context_child(sio);\r
146         sio->set_context_intr(cpu, 1);\r
147         sio->set_context_child(interrupt);\r
148         interrupt->set_context_intr(cpu, 2);\r
149         \r
150         // i/o bus\r
151         io->set_iomap_range_rw(0x60, 0x63, w3100a);\r
152         io->set_iomap_range_rw(0xa0, 0xa3, sio);\r
153         io->set_iomap_range_rw(0xa4, 0xa5, mz1e30);\r
154         io->set_iomap_range_rw(0xa8, 0xa9, mz1e30);\r
155         io->set_iomap_range_rw(0xac, 0xad, mz1r37);\r
156         io->set_iomap_single_w(0xae, crtc);\r
157         io->set_iomap_range_rw(0xb0, 0xb3, sio);\r
158         io->set_iomap_range_rw(0xb4, 0xb5, memory);\r
159         io->set_iomap_range_rw(0xb8, 0xb9, mz1r13);\r
160         io->set_iomap_range_rw(0xbc, 0xbf, crtc);\r
161         io->set_iomap_range_w(0xc6, 0xc7, interrupt);\r
162         io->set_iomap_range_rw(0xc8, 0xc9, opn);\r
163         io->set_iomap_single_rw(0xca, mz1e26);\r
164         io->set_iomap_single_rw(0xcc, calendar);\r
165         io->set_iomap_range_w(0xce, 0xcf, memory);\r
166         io->set_iomap_range_rw(0xd8, 0xdb, fdc);\r
167         io->set_iomap_range_w(0xdc, 0xdd, floppy);\r
168         io->set_iomap_range_rw(0xe0, 0xe3, pio_i);\r
169         io->set_iomap_range_rw(0xe4, 0xe7, pit);\r
170         io->set_iomap_range_rw(0xe8, 0xeb, pio);\r
171         io->set_iomap_single_rw(0xef, joystick);\r
172         io->set_iomap_range_w(0xf0, 0xf3, timer);\r
173         io->set_iomap_range_rw(0xf4, 0xf7, crtc);\r
174         \r
175         io->set_iowait_range_rw(0xc8, 0xc9, 1);\r
176         io->set_iowait_single_rw(0xcc, 3);\r
177         io->set_iowait_range_rw(0xd8, 0xdf, 1);\r
178         io->set_iowait_range_rw(0xe8, 0xeb, 1);\r
179         \r
180         // initialize all devices\r
181         for(DEVICE* device = first_device; device; device = device->next_device) {\r
182                 device->initialize();\r
183         }\r
184         for(int i = 0; i < MAX_DRIVE; i++) {\r
185                 fdc->set_drive_type(i, DRIVE_TYPE_2DD);\r
186         }\r
187         monitor_type = config.monitor_type;\r
188 }\r
189 \r
190 VM::~VM()\r
191 {\r
192         // delete all devices\r
193         for(DEVICE* device = first_device; device;) {\r
194                 DEVICE *next_device = device->next_device;\r
195                 device->release();\r
196                 delete device;\r
197                 device = next_device;\r
198         }\r
199 }\r
200 \r
201 DEVICE* VM::get_device(int id)\r
202 {\r
203         for(DEVICE* device = first_device; device; device = device->next_device) {\r
204                 if(device->this_device_id == id) {\r
205                         return device;\r
206                 }\r
207         }\r
208         return NULL;\r
209 }\r
210 \r
211 // ----------------------------------------------------------------------------\r
212 // drive virtual machine\r
213 // ----------------------------------------------------------------------------\r
214 \r
215 void VM::reset()\r
216 {\r
217         // reset all devices\r
218         for(DEVICE* device = first_device; device; device = device->next_device) {\r
219                 device->reset();\r
220         }\r
221         \r
222         // set initial port status\r
223         opn->write_signal(SIG_YM2203_PORT_B, (monitor_type & 2) ? 0x77 : 0x37, 0xff);\r
224 }\r
225 \r
226 void VM::special_reset()\r
227 {\r
228         // reset all devices\r
229 //      for(DEVICE* device = first_device; device; device = device->next_device) {\r
230 //              device->special_reset();\r
231 //      }\r
232         memory->special_reset();\r
233         cpu->reset();\r
234 }\r
235 \r
236 void VM::run()\r
237 {\r
238         event->drive();\r
239 }\r
240 \r
241 // ----------------------------------------------------------------------------\r
242 // debugger\r
243 // ----------------------------------------------------------------------------\r
244 \r
245 #ifdef USE_DEBUGGER\r
246 DEVICE *VM::get_cpu(int index)\r
247 {\r
248         if(index == 0) {\r
249                 return cpu;\r
250         }\r
251         return NULL;\r
252 }\r
253 #endif\r
254 \r
255 // ----------------------------------------------------------------------------\r
256 // draw screen\r
257 // ----------------------------------------------------------------------------\r
258 \r
259 void VM::draw_screen()\r
260 {\r
261         crtc->draw_screen();\r
262 }\r
263 \r
264 int VM::access_lamp()\r
265 {\r
266         uint32 status = fdc->read_signal(0) | mz1e30->read_signal(0);\r
267         return (status & 0x30) ? 4 : (status & (1 | 4)) ? 1 : (status & (2 | 8)) ? 2 : 0;\r
268 }\r
269 \r
270 // ----------------------------------------------------------------------------\r
271 // soud manager\r
272 // ----------------------------------------------------------------------------\r
273 \r
274 void VM::initialize_sound(int rate, int samples)\r
275 {\r
276         // init sound manager\r
277         event->initialize_sound(rate, samples);\r
278         \r
279         // init sound gen\r
280         opn->init(rate, 2000000, samples, 0, -8);\r
281         pcm->init(rate, 4096);\r
282         drec->initialize_sound(rate, samples);\r
283 }\r
284 \r
285 uint16* VM::create_sound(int* extra_frames)\r
286 {\r
287         return event->create_sound(extra_frames);\r
288 }\r
289 \r
290 int VM::sound_buffer_ptr()\r
291 {\r
292         return event->sound_buffer_ptr();\r
293 }\r
294 \r
295 // ----------------------------------------------------------------------------\r
296 // socket\r
297 // ----------------------------------------------------------------------------\r
298 \r
299 void VM::network_connected(int ch)\r
300 {\r
301         w3100a->connected(ch);\r
302 }\r
303 \r
304 void VM::network_disconnected(int ch)\r
305 {\r
306         w3100a->disconnected(ch);\r
307 }\r
308 \r
309 uint8* VM::get_sendbuffer(int ch, int* size)\r
310 {\r
311         return w3100a->get_sendbuffer(ch, size);\r
312 }\r
313 \r
314 void VM::inc_sendbuffer_ptr(int ch, int size)\r
315 {\r
316         w3100a->inc_sendbuffer_ptr(ch, size);\r
317 }\r
318 \r
319 uint8* VM::get_recvbuffer0(int ch, int* size0, int* size1)\r
320 {\r
321         return w3100a->get_recvbuffer0(ch, size0, size1);\r
322 }\r
323 \r
324 uint8* VM::get_recvbuffer1(int ch)\r
325 {\r
326         return w3100a->get_recvbuffer1(ch);\r
327 }\r
328 \r
329 void VM::inc_recvbuffer_ptr(int ch, int size)\r
330 {\r
331         w3100a->inc_recvbuffer_ptr(ch, size);\r
332 }\r
333 \r
334 // ----------------------------------------------------------------------------\r
335 // user interface\r
336 // ----------------------------------------------------------------------------\r
337 \r
338 void VM::open_disk(int drv, _TCHAR* file_path, int offset)\r
339 {\r
340         fdc->open_disk(drv, file_path, offset);\r
341 }\r
342 \r
343 void VM::close_disk(int drv)\r
344 {\r
345         fdc->close_disk(drv);\r
346 }\r
347 \r
348 bool VM::disk_inserted(int drv)\r
349 {\r
350         return fdc->disk_inserted(drv);\r
351 }\r
352 \r
353 void VM::play_tape(_TCHAR* file_path)\r
354 {\r
355         bool value = drec->play_tape(file_path);\r
356         cmt->close_tape();\r
357         cmt->play_tape(value);\r
358 }\r
359 \r
360 void VM::rec_tape(_TCHAR* file_path)\r
361 {\r
362         bool value = drec->rec_tape(file_path);\r
363         cmt->close_tape();\r
364         cmt->rec_tape(value);\r
365 }\r
366 \r
367 void VM::close_tape()\r
368 {\r
369         drec->close_tape();\r
370         cmt->close_tape();\r
371 }\r
372 \r
373 bool VM::tape_inserted()\r
374 {\r
375         return drec->tape_inserted();\r
376 }\r
377 \r
378 bool VM::now_skip()\r
379 {\r
380         return event->now_skip();\r
381 }\r
382 \r
383 void VM::update_config()\r
384 {\r
385         for(DEVICE* device = first_device; device; device = device->next_device) {\r
386                 device->update_config();\r
387         }\r
388 }\r
389 \r
390 #define STATE_VERSION   1\r
391 \r
392 void VM::save_state(FILEIO* state_fio)\r
393 {\r
394         state_fio->FputUint32(STATE_VERSION);\r
395         \r
396         for(DEVICE* device = first_device; device; device = device->next_device) {\r
397                 device->save_state(state_fio);\r
398         }\r
399         state_fio->FputInt32(monitor_type);\r
400 }\r
401 \r
402 bool VM::load_state(FILEIO* state_fio)\r
403 {\r
404         if(state_fio->FgetUint32() != STATE_VERSION) {\r
405                 return false;\r
406         }\r
407         for(DEVICE* device = first_device; device; device = device->next_device) {\r
408                 if(!device->load_state(state_fio)) {\r
409                         return false;\r
410                 }\r
411         }\r
412         monitor_type = state_fio->FgetInt32();\r
413         return true;\r
414 }\r
415 \r