OSDN Git Service

[VM][DATAREC][FDD] Add sounds of SEEK/CMT, excepts either pseudo devices / bios.
[csp-qt/common_source_project-fm7.git] / source / src / vm / mz700 / mz700.cpp
1 /*
2         SHARP MZ-700 Emulator 'EmuZ-700'
3         SHARP MZ-800 Emulator 'EmuZ-800'
4         SHARP MZ-1500 Emulator 'EmuZ-1500'
5
6         Author : Takeda.Toshiya
7         Date   : 2008.06.05 -
8
9         [ virtual machine ]
10 */
11
12 #include "mz700.h"
13 #include "../../emu.h"
14 #include "../device.h"
15 #include "../event.h"
16
17 #include "../and.h"
18 #include "../datarec.h"
19 #include "../i8253.h"
20 #include "../i8255.h"
21 #include "../io.h"
22 #include "../pcm1bit.h"
23 #include "../z80.h"
24
25 #ifdef USE_DEBUGGER
26 #include "../debugger.h"
27 #endif
28
29 //#include "cmos.h"
30 #include "emm.h"
31 #include "kanji.h"
32 #include "keyboard.h"
33 #include "memory.h"
34 #include "ramfile.h"
35
36 #if defined(_MZ800) || defined(_MZ1500)
37 #include "../disk.h"
38 #include "../mb8877.h"
39 #include "../not.h"
40 #include "../sn76489an.h"
41 #include "../z80pio.h"
42 #include "../z80sio.h"
43 #include "floppy.h"
44 #if defined(_MZ1500)
45 #include "../mz1p17.h"
46 #include "../prnfile.h"
47 #include "psg.h"
48 #endif
49 #include "quickdisk.h"
50 #endif
51
52 // ----------------------------------------------------------------------------
53 // initialize
54 // ----------------------------------------------------------------------------
55
56 VM::VM(EMU* parent_emu) : emu(parent_emu)
57 {
58 #if defined(_MZ800)
59         boot_mode = config.boot_mode;
60 #endif
61         
62         // create devices
63         first_device = last_device = NULL;
64         dummy = new DEVICE(this, emu);  // must be 1st device
65         event = new EVENT(this, emu);   // must be 2nd device
66 #if defined(_USE_QT)
67         dummy->set_device_name(_T("1st Dummy"));
68         event->set_device_name(_T("EVENT"));
69 #endif  
70         and_int = new AND(this, emu);
71         drec = new DATAREC(this, emu);
72         pit = new I8253(this, emu);
73         pio = new I8255(this, emu);
74         io = new IO(this, emu);
75         pcm = new PCM1BIT(this, emu);
76         cpu = new Z80(this, emu);
77 #if defined(_USE_QT)
78         and_int->set_device_name(_T("AND GATE(INTERRUPT)"));
79         cpu->set_device_name(_T("CPU(Z80)"));
80 #endif  
81         
82 //      cmos = new CMOS(this, emu);
83         emm = new EMM(this, emu);
84         kanji = new KANJI(this, emu);
85         keyboard = new KEYBOARD(this, emu);
86         memory = new MEMORY(this, emu);
87         ramfile = new RAMFILE(this, emu);
88 #if defined(_USE_QT)
89         emm->set_device_name(_T("EMM"));
90         kanji->set_device_name(_T("KANJI ROM"));
91         keyboard->set_device_name(_T("KEYBOARD I/F"));
92         memory->set_device_name(_T("MEMORY"));
93         ramfile->set_device_name(_T("RAM FILES"));
94 #endif  
95 #if defined(_MZ800) || defined(_MZ1500)
96         and_snd = new AND(this, emu);
97   #if defined(_USE_QT)
98         and_snd->set_device_name(_T("AND GATE(SOUND)"));
99   #endif
100         fdc = new MB8877(this, emu);    // mb8876
101 #if defined(_MZ800)
102         not_pit = new NOT(this, emu);
103   #if defined(_USE_QT)
104         not_pit->set_device_name(_T("NOT GATE(PIT)"));
105   #endif
106         psg = new SN76489AN(this, emu);
107 #elif defined(_MZ1500)
108         if(config.printer_device_type == 0) {
109                 printer = new PRNFILE(this, emu);
110         } else if(config.printer_device_type == 1) {
111                 printer = new MZ1P17(this, emu);
112         } else {
113                 printer = dummy;
114         }
115         not_reset = new NOT(this, emu);
116         not_strobe = new NOT(this, emu);
117         psg_l = new SN76489AN(this, emu);
118         psg_r = new SN76489AN(this, emu);
119   #if defined(_USE_QT)
120         not_reset->set_device_name(_T("NOT GATE(RESET)"));
121         not_strobe->set_device_name(_T("NOT GATE(PRINTER STROBE)"));
122         psg_l->set_device_name(_T("SN76489AN PSG(LEFT)"));
123         psg_r->set_device_name(_T("SN76489AN PSG(RIGHT)"));
124   #endif
125 #endif
126         pio_int = new Z80PIO(this, emu);
127         sio_rs = new Z80SIO(this, emu);
128         sio_qd = new Z80SIO(this, emu);
129         
130         floppy = new FLOPPY(this, emu);
131 #if defined(_USE_QT)
132         floppy->set_device_name(_T("FLOPPY I/F"));
133 #endif
134 #if defined(_MZ1500)
135         psg = new PSG(this, emu);
136 #if defined(_USE_QT)
137         psg->set_device_name(_T("PSG I/F"));
138 #endif
139 #endif
140         qd = new QUICKDISK(this, emu);
141 #if defined(_USE_QT)
142         qd->set_device_name(_T("QUICKDISK I/F"));
143 #endif
144 #endif
145         
146         // set contexts
147         event->set_context_cpu(cpu);
148         event->set_context_sound(pcm);
149 #if defined(_MZ800)
150         event->set_context_sound(psg);
151 #elif defined(_MZ1500)
152         event->set_context_sound(psg_l);
153         event->set_context_sound(psg_r);
154 #endif
155         event->set_context_sound(drec);
156
157 #if defined(USE_SOUND_FILES)
158 #if defined(_MZ800) || defined(_MZ1500)
159         if(fdc->load_sound_data(MB8877_SND_TYPE_SEEK, _T("FDDSEEK.WAV"))) {
160                 event->set_context_sound(fdc);
161         }
162         //if(qd->load_sound_data(MB8877_SND_TYPE_SEEK, _T("QD_SEEK.WAV"))) {
163         //      event->set_context_sound(qd);
164         //}
165 #endif
166         drec->load_sound_data(DATAREC_SNDFILE_EJECT, _T("CMTEJECT.WAV"));
167         //drec->load_sound_data(DATAREC_SNDFILE_PLAY, _T("CMTPLAY.WAV"));
168         //drec->load_sound_data(DATAREC_SNDFILE_STOP, _T("CMTSTOP.WAV"));
169 #if defined(_MZ1500)
170         // Is MZ-821?
171         drec->load_sound_data(DATAREC_SNDFILE_RELAY_ON, _T("RELAY_ON.WAV"));
172         drec->load_sound_data(DATAREC_SNDFILE_RELAY_OFF, _T("RELAYOFF.WAV"));
173 #else
174         drec->load_sound_data(DATAREC_SNDFILE_RELAY_ON, _T("CMTPLAY.WAV"));
175         drec->load_sound_data(DATAREC_SNDFILE_RELAY_OFF, _T("CMTSTOP.WAV"));
176 #endif
177 #endif
178         
179         // VRAM/PCG wait
180         memory->set_context_cpu(cpu);
181         
182         // memory mapped I/O
183         memory->set_context_pio(pio);
184         memory->set_context_pit(pit);
185         
186 #if defined(_MZ1500)
187         // psg mixer
188         psg->set_context_psg_l(psg_l);
189         psg->set_context_psg_r(psg_r);
190 #endif
191         
192 #if defined(_MZ800)
193         // 8253:CLK#0 <- 1.10MHz
194         pit->set_constant_clock(0, 1100000);
195 #else
196         // 8253:CLK#0 <- 895KHz
197         pit->set_constant_clock(0, CPU_CLOCKS / 4);
198 #endif
199         
200 #if defined(_MZ800) || defined(_MZ1500)
201         // 8253:OUT#0 AND 8255:PC0 -> SPEAKER
202         pit->set_context_ch0(and_snd, SIG_AND_BIT_0, 1);
203         pio->set_context_port_c(and_snd, SIG_AND_BIT_1, 1, 0);
204         and_snd->set_context_out(pcm, SIG_PCM1BIT_SIGNAL, 1);
205         and_snd->set_mask(SIG_AND_BIT_0 | SIG_AND_BIT_1);
206 #else
207         // 8253:OUT#0 -> SPEAKER
208         pit->set_context_ch0(pcm, SIG_PCM1BIT_SIGNAL, 1);
209 #endif
210 #if defined(_MZ800)
211         // 8253:OUT#0 -> NOT -> Z80PIO:PA4
212         pit->set_context_ch0(not_pit, SIG_NOT_INPUT, 1);
213         not_pit->set_context_out(pio_int, SIG_Z80PIO_PORT_A, 0x10);
214 #elif defined(_MZ1500)
215         // 8253:OUT#0 -> Z80PIO:PA4
216         pit->set_context_ch0(pio_int, SIG_Z80PIO_PORT_A, 0x10);
217 #endif
218         
219         // 8253:CLK#1 <- 15.7KHz
220         pit->set_constant_clock(1, CPU_CLOCKS / 228);
221         
222         // 8253:OUT#1 -> 8253:CLK#2
223         pit->set_context_ch1(pit, SIG_I8253_CLOCK_2, 1);
224         
225         // 8253:OUT#2 (N)AND 8255:PC2 -> Z80:INT
226         pit->set_context_ch2(and_int, SIG_AND_BIT_0, 1);
227         pio->set_context_port_c(and_int, SIG_AND_BIT_1, 4, 0);
228         and_int->set_context_out(cpu, SIG_CPU_IRQ, 1);
229         and_int->set_mask(SIG_AND_BIT_0 | SIG_AND_BIT_1);
230         
231 #if defined(_MZ1500)
232         // 8253:OUT#2 -> Z80PIO:PA5
233         pit->set_context_ch2(pio_int, SIG_Z80PIO_PORT_A, 0x20);
234 #endif
235         
236         // 8255:PA0-3 -> KEYBOARD:STROBE
237         pio->set_context_port_a(keyboard, SIG_KEYBOARD_COLUMN, 0x0f, 0);
238 #if defined(_MZ800)
239         // 8255:PA4 -> JOYSTICK #1
240         // 8255:PA5 -> JOYSTICK #2
241 #endif
242         // 8255:PA7 -> 556 RESET
243         
244         // 8255:PB0-7 <- KEYBOARD:DATA
245         keyboard->set_context_pio(pio);
246         
247         // 8255:PC0 -> AND -> SPEAKER
248         // 8255:PC1 -> DATA RECORDER:WRITE DATA
249         pio->set_context_port_c(drec, SIG_DATAREC_MIC, 0x02, 0);
250         // 8255:PC2 -> (N)AND -> Z80:INT
251         // 8255:PC3 -> DATA RECORDER:MOTOR ON/OFF
252         pio->set_context_port_c(drec, SIG_DATAREC_TRIG, 0x08, 0);
253         // 8255:PC4 <- DATA RECORDER:MOTOR REMOTE
254         drec->set_context_remote(pio, SIG_I8255_PORT_C, 0x10);
255         // 8255:PC5 <- DATA RECORDER:READ DATA
256         drec->set_context_ear(pio, SIG_I8255_PORT_C, 0x20);
257         // 8255:PC6 <- MEMORY:556 OUT (1.5KHz)
258         // 8255:PC7 <- MEMORY:VBLANK
259         
260 #if defined(_MZ800) || defined(_MZ1500)
261         // Z80PIO:PA2 <- GND
262         // Z80PIO:PA3 <- GND
263 #if defined(_MZ800)
264         // Z80PIO:PA4 <- NOT <- 8253:OUT#0
265         // Z80PIO:PA5 <- HBLANK
266         memory->set_context_pio_int(pio_int);
267 #elif defined(_MZ1500)
268         // Z80PIO:PA0 <- PRINTER:RDA (BUSY)
269         // Z80PIO:PA1 <- PRINTER:STA (PE)
270         if(config.printer_device_type == 0) {
271                 PRNFILE *prnfile = (PRNFILE *)printer;
272                 prnfile->set_context_busy(pio_int, SIG_Z80PIO_PORT_A, 0x01);
273         } else if(config.printer_device_type == 1) {
274                 MZ1P17 *mz1p17 = (MZ1P17 *)printer;
275                 mz1p17->mode = MZ1P17_MODE_MZ2;
276                 mz1p17->set_context_busy(pio_int, SIG_Z80PIO_PORT_A, 0x01);
277         }
278         // Z80PIO:PA4 <- 8253:OUT#0
279         // Z80PIO:PA5 <- 8253:OUT#2
280         // Z80PIO:PA6 -> NOT -> PRINTER:IRT (RESET)
281         // Z80PIO:PA7 -> NOT -> PRINTER:RDP (STROBE)
282         // Z80PIO:PB  -> PRINTER:DATA
283         pio_int->set_context_port_a(not_reset, SIG_NOT_INPUT, 0x40, 0);
284         not_reset->set_context_out(printer, SIG_PRINTER_RESET, 0x01);
285         pio_int->set_context_port_a(not_strobe, SIG_NOT_INPUT, 0x80, 0);
286         not_strobe->set_context_out(printer, SIG_PRINTER_STROBE, 0x01);
287         pio_int->set_context_port_b(printer, SIG_PRINTER_DATA, 0xff, 0);
288 #endif
289 #endif
290         
291 #if defined(_MZ800) || defined(_MZ1500)
292         // Z80SIO:RTSA -> QD:WRGA
293         sio_qd->set_context_rts(0, qd, QUICKDISK_SIO_RTSA, 1);
294         // Z80SIO:DTRB -> QD:MTON
295         sio_qd->set_context_dtr(1, qd, QUICKDISK_SIO_DTRB, 1);
296         // Z80SIO:SENDA -> QD:RECV
297         sio_qd->set_context_sync(0, qd, QUICKDISK_SIO_SYNC, 1);
298         sio_qd->set_context_rxdone(0, qd, QUICKDISK_SIO_RXDONE, 1);
299         sio_qd->set_context_send(0, qd, QUICKDISK_SIO_DATA);
300         sio_qd->set_context_break(0, qd, QUICKDISK_SIO_BREAK, 1);
301         // Z80SIO:CTSA <- QD:PROTECT
302         // Z80SIO:DCDA <- QD:INSERT
303         // Z80SIO:DCDB <- QD:HOE
304         qd->set_context_sio(sio_qd);
305         
306         sio_rs->set_tx_clock(0, 1200 * 16);     // 1200 baud
307         sio_rs->set_rx_clock(0, 1200 * 16);     // baud-rate can be changed by jumper pin
308         sio_rs->set_tx_clock(1, 1200 * 16);
309         sio_rs->set_rx_clock(1, 1200 * 16);
310         
311         sio_qd->set_tx_clock(0, 101562.5);
312         sio_qd->set_rx_clock(0, 101562.5);
313         sio_qd->set_tx_clock(1, 101562.5);
314         sio_qd->set_rx_clock(1, 101562.5);
315         
316         // floppy drives
317         floppy->set_context_cpu(cpu);
318         floppy->set_context_fdc(fdc);
319         fdc->set_context_drq(floppy, SIG_FLOPPY_DRQ, 1);
320 #endif
321         
322         // cpu bus
323         cpu->set_context_mem(memory);
324         cpu->set_context_io(io);
325 #if defined(_MZ800) || defined(_MZ1500)
326         cpu->set_context_intr(pio_int);
327         // z80 family daisy chain
328         // 0=8253:OUT2
329         pio_int->set_context_intr(cpu, 1);
330         pio_int->set_context_child(sio_rs);
331         sio_rs->set_context_intr(cpu, 2);
332         sio_rs->set_context_child(sio_qd);
333         sio_qd->set_context_intr(cpu, 3);
334 #else
335         cpu->set_context_intr(dummy);
336 #endif
337 #ifdef USE_DEBUGGER
338         cpu->set_context_debugger(new DEBUGGER(this, emu));
339 #endif
340         
341         // emm
342         io->set_iomap_range_rw(0x00, 0x03, emm);
343         // kanji
344         io->set_iomap_range_rw(0xb8, 0xb9, kanji);
345         // ramfile
346         io->set_iomap_range_rw(0xea, 0xeb, ramfile);
347         // cmos
348 //      io->set_iomap_range_rw(0xf8, 0xfa, cmos);
349         
350 #if defined(_MZ800)
351         // 8255/8253
352         io->set_iomap_range_rw(0xd0, 0xd3, pio);
353         io->set_iomap_range_rw(0xd4, 0xd7, pit);
354 #endif
355         
356 #if defined(_MZ800) || defined(_MZ1500)
357         // floppy drives
358         io->set_iomap_range_rw(0xd8, 0xdb, fdc);
359         io->set_iomap_range_w(0xdc, 0xdf, floppy);
360 #endif
361         
362         // memory mapper
363 #if defined(_MZ800)
364         io->set_iomap_range_r(0xe0, 0xe1, memory);
365         io->set_iomap_range_w(0xe0, 0xe6, memory);
366 #elif defined(_MZ1500)
367         io->set_iomap_range_w(0xe0, 0xe6, memory);
368 #else
369         io->set_iomap_range_w(0xe0, 0xe4, memory);
370 #endif
371         
372 #if defined(_MZ800)
373         // crtc
374         io->set_iomap_range_w(0xcc, 0xcf, memory);
375         io->set_iomap_single_r(0xce, memory);
376         // palette
377         io->set_iomap_single_w(0xf0, memory);
378 #elif defined(_MZ1500)
379         // palette
380         io->set_iomap_range_w(0xf0, 0xf1, memory);
381 #endif
382         
383 #if defined(_MZ800)
384         // joystick
385 //      io->set_iomap_range_r(0xf0, 0xf1, joystick);
386 #endif
387         
388         // psg
389 #if defined(_MZ800)
390         io->set_iomap_single_w(0xf2, psg);
391 #elif defined(_MZ1500)
392         io->set_iomap_single_w(0xe9, psg);
393         io->set_iomap_single_w(0xf2, psg_l);
394         io->set_iomap_single_w(0xf3, psg_r);
395 #endif
396         
397 #if defined(_MZ800) || defined(_MZ1500)
398         // z80pio/sio
399         // z80pio and z80sio*2
400         static const int z80_sio_addr[4] = {0, 2, 1, 3};
401         static const int z80_pio_addr[4] = {1, 3, 0, 2};
402         for(int i = 0; i < 4; i++) {
403                 io->set_iomap_alias_rw(0xb0 + i, sio_rs, z80_sio_addr[i]);
404                 io->set_iomap_alias_rw(0xf4 + i, sio_qd, z80_sio_addr[i]);
405                 io->set_iomap_alias_rw(0xfc + i, pio_int, z80_pio_addr[i]);
406         }
407 #else
408         // printer
409         io->set_iovalue_single_r(0xfe, 0xc0);
410 #endif
411
412         // initialize all devices
413         for(DEVICE* device = first_device; device; device = device->next_device) {
414                 device->initialize();
415         }
416 #if defined(_MZ800) || defined(_MZ1500)
417         for(int i = 0; i < MAX_DRIVE; i++) {
418                 fdc->set_drive_type(i, DRIVE_TYPE_2DD);
419         }
420 #endif
421 }
422
423 VM::~VM()
424 {
425         // delete all devices
426         for(DEVICE* device = first_device; device;) {
427                 DEVICE *next_device = device->next_device;
428                 device->release();
429                 delete device;
430                 device = next_device;
431         }
432 }
433
434 DEVICE* VM::get_device(int id)
435 {
436         for(DEVICE* device = first_device; device; device = device->next_device) {
437                 if(device->this_device_id == id) {
438                         return device;
439                 }
440         }
441         return NULL;
442 }
443
444 // ----------------------------------------------------------------------------
445 // drive virtual machine
446 // ----------------------------------------------------------------------------
447
448 void VM::reset()
449 {
450         // reset all devices
451         for(DEVICE* device = first_device; device; device = device->next_device) {
452                 device->reset();
453         }
454         and_int->write_signal(SIG_AND_BIT_0, 0, 1);     // CLOCK = L
455         and_int->write_signal(SIG_AND_BIT_1, 1, 1);     // INTMASK = H
456 #if defined(_MZ800) || defined(_MZ1500)
457         and_snd->write_signal(SIG_AND_BIT_1, 1, 1);     // SNDMASK = H
458 #endif
459 #if defined(_MZ1500)
460         pio_int->write_signal(SIG_Z80PIO_PORT_A, 0x02, 0x03);   // BUSY = L, PE = H
461 #endif
462 }
463
464 void VM::run()
465 {
466         event->drive();
467 }
468
469 // ----------------------------------------------------------------------------
470 // debugger
471 // ----------------------------------------------------------------------------
472
473 #ifdef USE_DEBUGGER
474 DEVICE *VM::get_cpu(int index)
475 {
476         if(index == 0) {
477                 return cpu;
478         }
479         return NULL;
480 }
481 #endif
482
483 // ----------------------------------------------------------------------------
484 // draw screen
485 // ----------------------------------------------------------------------------
486
487 void VM::draw_screen()
488 {
489         memory->draw_screen();
490 }
491
492 #if defined(_MZ800) || defined(_MZ1500)
493 uint32_t VM::get_access_lamp_status()
494 {
495         uint32_t status = fdc->read_signal(0) | qd->read_signal(0);
496         return (status & (1 | 4)) ? 1 : (status & (2 | 8)) ? 2 : 0;
497 }
498 #endif
499
500 // ----------------------------------------------------------------------------
501 // soud manager
502 // ----------------------------------------------------------------------------
503
504 void VM::initialize_sound(int rate, int samples)
505 {
506         // init sound manager
507         event->initialize_sound(rate, samples);
508         
509         // init sound gen
510         pcm->initialize_sound(rate, 8000);
511 #if defined(_MZ800)
512         psg->initialize_sound(rate, 3579545, 8000);
513 #elif defined(_MZ1500)
514         psg_l->initialize_sound(rate, 3579545, 8000);
515         psg_r->initialize_sound(rate, 3579545, 8000);
516 #endif
517 }
518
519 uint16_t* VM::create_sound(int* extra_frames)
520 {
521         return event->create_sound(extra_frames);
522 }
523
524 int VM::get_sound_buffer_ptr()
525 {
526         return event->get_sound_buffer_ptr();
527 }
528
529 #ifdef USE_SOUND_VOLUME
530 void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
531 {
532 #if defined(_MZ800)
533         if(ch-- == 0) {
534                 psg->set_volume(0, decibel_l, decibel_r);
535         } else
536 #elif defined(_MZ1500)
537         if(ch-- == 0) {
538                 psg_l->set_volume(0, decibel_l, decibel_r);
539         } else if(ch-- == 0) {
540                 psg_r->set_volume(0, decibel_l, decibel_r);
541         } else
542 #endif
543         if(ch-- == 0) {
544                 pcm->set_volume(0, decibel_l, decibel_r);
545         } else if(ch-- == 0) {
546                 drec->set_volume(0, decibel_l, decibel_r);
547         }
548 #if defined(USE_SOUND_FILES)
549 #if defined(_MZ1500) || defined(_MZ800)
550         else if(ch-- == 0) {
551                 fdc->set_volume(MB8877_SND_TYPE_SEEK, decibel_l, decibel_r);
552         }
553 #endif
554         else if(ch-- == 0) {
555                 drec->set_volume(2 + DATAREC_SNDFILE_RELAY_ON, decibel_l, decibel_r);
556                 drec->set_volume(2 + DATAREC_SNDFILE_RELAY_OFF, decibel_l, decibel_r);
557                 drec->set_volume(2 + DATAREC_SNDFILE_EJECT, decibel_l, decibel_r);
558         }               
559 #endif
560 }
561 #endif
562
563 // ----------------------------------------------------------------------------
564 // user interface
565 // ----------------------------------------------------------------------------
566
567 void VM::play_tape(const _TCHAR* file_path)
568 {
569         drec->play_tape(file_path);
570         drec->set_remote(true);
571 }
572
573 void VM::rec_tape(const _TCHAR* file_path)
574 {
575         drec->rec_tape(file_path);
576         drec->set_remote(true);
577 }
578
579 void VM::close_tape()
580 {
581 #if defined(USE_SOUND_FILES)
582         drec->write_signal(SIG_SOUNDER_ADD + DATAREC_SNDFILE_EJECT, 1, 1);
583 #endif
584         emu->lock_vm();
585         drec->close_tape();
586         emu->unlock_vm();
587
588         drec->set_remote(false);
589 }
590
591 bool VM::is_tape_inserted()
592 {
593         return drec->is_tape_inserted();
594 }
595
596 bool VM::is_tape_playing()
597 {
598         return drec->is_tape_playing();
599 }
600
601 bool VM::is_tape_recording()
602 {
603         return drec->is_tape_recording();
604 }
605
606 int VM::get_tape_position()
607 {
608         return drec->get_tape_position();
609 }
610
611 void VM::push_play()
612 {
613         drec->set_ff_rew(0);
614         drec->set_remote(true);
615 }
616
617 void VM::push_stop()
618 {
619         drec->set_remote(false);
620 }
621
622 void VM::push_fast_forward()
623 {
624         drec->set_ff_rew(1);
625         drec->set_remote(true);
626 }
627
628 void VM::push_fast_rewind()
629 {
630         drec->set_ff_rew(-1);
631         drec->set_remote(true);
632 }
633
634 #if defined(_MZ800) || defined(_MZ1500)
635 void VM::open_quick_disk(int drv, const _TCHAR* file_path)
636 {
637         if(drv == 0) {
638                 qd->open_disk(file_path);
639         }
640 }
641
642 void VM::close_quick_disk(int drv)
643 {
644         if(drv == 0) {
645                 qd->close_disk();
646         }
647 }
648
649 bool VM::is_quick_disk_inserted(int drv)
650 {
651         if(drv == 0) {
652                 return qd->is_disk_inserted();
653         } else {
654                 return false;
655         }
656 }
657
658 void VM::open_floppy_disk(int drv, const _TCHAR* file_path, int bank)
659 {
660         fdc->open_disk(drv, file_path, bank);
661 }
662
663 void VM::close_floppy_disk(int drv)
664 {
665         fdc->close_disk(drv);
666 }
667
668 bool VM::is_floppy_disk_inserted(int drv)
669 {
670         return fdc->is_disk_inserted(drv);
671 }
672
673 void VM::is_floppy_disk_protected(int drv, bool value)
674 {
675         fdc->is_disk_protected(drv, value);
676 }
677
678 bool VM::is_floppy_disk_protected(int drv)
679 {
680         return fdc->is_disk_protected(drv);
681 }
682 #endif
683
684 bool VM::is_frame_skippable()
685 {
686         return event->is_frame_skippable();
687 }
688
689 void VM::update_config()
690 {
691 #if defined(_MZ800)
692         if(boot_mode != config.boot_mode) {
693                 // boot mode is changed !!!
694                 boot_mode = config.boot_mode;
695                 reset();
696         } else {
697 #endif
698                 for(DEVICE* device = first_device; device; device = device->next_device) {
699                         device->update_config();
700                 }
701 #if defined(_MZ800)
702         }
703 #endif
704 }
705
706 #define STATE_VERSION   1
707
708 void VM::save_state(FILEIO* state_fio)
709 {
710         state_fio->FputUint32(STATE_VERSION);
711         
712         for(DEVICE* device = first_device; device; device = device->next_device) {
713                 device->save_state(state_fio);
714         }
715 #if defined(_MZ800)
716         state_fio->FputInt32(boot_mode);
717 #endif
718 }
719
720 bool VM::load_state(FILEIO* state_fio)
721 {
722         if(state_fio->FgetUint32() != STATE_VERSION) {
723                 return false;
724         }
725         for(DEVICE* device = first_device; device; device = device->next_device) {
726                 if(!device->load_state(state_fio)) {
727                         return false;
728                 }
729         }
730 #if defined(_MZ800)
731         boot_mode = state_fio->FgetInt32();
732 #endif
733         return true;
734 }
735