OSDN Git Service

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