OSDN Git Service

[BUILD] Set SOVERSION and GIT hash automatically.
[csp-qt/common_source_project-fm7.git] / source / src / vm / pc6001 / pc6001.cpp
1 /*
2         NEC PC-6001 Emulator 'yaPC-6001'
3         NEC PC-6001mkII Emulator 'yaPC-6201'
4         NEC PC-6001mkIISR Emulator 'yaPC-6401'
5         NEC PC-6601 Emulator 'yaPC-6601'
6         NEC PC-6601SR Emulator 'yaPC-6801'
7
8         Author : tanam
9         Date   : 2013.07.15-
10
11         [ virtual machine ]
12 */
13
14 #include "pc6001.h"
15 #include "../../emu.h"
16 #include "../device.h"
17 #include "../event.h"
18
19 #include "../disk.h"
20 #include "../i8255.h"
21 #include "../io.h"
22 #ifdef _PC6001
23 #include "../mc6847.h"
24 #include "display.h"
25 #else
26 #include "../upd7752.h"
27 #endif
28 #include "../noise.h"
29 #include "../pc6031.h"
30 #include "../pc80s31k.h"
31 #include "../prnfile.h"
32 #include "../upd765a.h"
33 #if defined(_PC6001MK2SR) || defined(_PC6601SR)
34 #include "../ym2203.h"
35 #else
36 #include "../ay_3_891x.h"
37 #endif
38 #include "../z80.h"
39
40 #include "../datarec.h"
41 #include "../mcs48.h"
42
43 #ifdef USE_DEBUGGER
44 #include "../debugger.h"
45 #endif
46
47 #if defined(_PC6601) || defined(_PC6601SR)
48 #include "floppy.h"
49 #endif
50 #include "joystick.h"
51 #include "memory.h"
52 #include "psub.h"
53 #include "sub.h"
54 #include "timer.h"
55
56 // ----------------------------------------------------------------------------
57 // initialize
58 // ----------------------------------------------------------------------------
59
60 VM::VM(EMU* parent_emu) : VM_TEMPLATE(parent_emu)
61 {
62         support_pc80s31k = FILEIO::IsFileExisting(create_local_path(_T("DISK.ROM")));
63 #ifdef _PC6601SR
64         support_sub_cpu = false;
65 #else
66         support_sub_cpu = FILEIO::IsFileExisting(create_local_path(_T(SUB_CPU_ROM_FILE_NAME)));
67 #endif
68         
69         // create devices
70         first_device = last_device = NULL;
71         dummy = new DEVICE(this, emu);  // must be 1st device
72         event = new EVENT(this, emu);   // must be 2nd device
73         
74         pio_sub = new I8255(this, emu);
75         io = new IO(this, emu);
76         noise_seek = new NOISE(this, emu);
77         noise_head_down = new NOISE(this, emu);
78         noise_head_up = new NOISE(this, emu);
79 #if defined(_PC6001MK2SR) || defined(_PC6601SR)
80         psg = new YM2203(this, emu);
81 #else
82         psg = new AY_3_891X(this, emu);
83 #endif
84         cpu = new Z80(this, emu);
85         
86         if(config.printer_type == 0) {
87                 printer = new PRNFILE(this, emu);
88         } else {
89                 printer = dummy;
90         }
91         
92 #if defined(_PC6601) || defined(_PC6601SR)
93         floppy = new FLOPPY(this, emu);
94         floppy->set_context_noise_seek(noise_seek);
95 //      floppy->set_context_noise_head_down(noise_head_down);
96 //      floppy->set_context_noise_head_up(noise_head_up);
97 #endif
98         joystick = new JOYSTICK(this, emu);
99         memory = new MEMORY(this, emu);
100         timer = new TIMER(this, emu);
101         
102         // set contexts
103         event->set_context_cpu(cpu);
104         event->set_context_sound(psg);
105         event->set_context_sound(noise_seek);
106         event->set_context_sound(noise_head_down);
107         event->set_context_sound(noise_head_up);
108         
109         pio_sub->set_context_port_b(printer, SIG_PRINTER_DATA, 0xff, 0);
110         pio_sub->set_context_port_c(printer, SIG_PRINTER_STROBE, 0x01, 0);
111         pio_sub->set_context_port_c(memory, SIG_MEMORY_PIO_PORT_C, 0x06, 0);    // CRTKILL,CGSWN
112         
113 #ifdef _PC6001
114         display = new DISPLAY(this, emu);
115         vdp = new MC6847(this, emu);
116         display->set_context_vdp(vdp);
117         display->set_vram_ptr(memory->get_vram());
118         display->set_context_timer(timer);
119         vdp->load_font_image(create_local_path(_T("CGROM60.60")));
120         vdp->set_context_cpu(cpu);
121         pio_sub->set_context_port_c(vdp, SIG_MC6847_ENABLE, 0x02, 0);   // CRTKILL
122 #else
123         voice = new UPD7752(this, emu);
124         event->set_context_sound(voice);
125         memory->set_context_timer(timer);
126 #endif
127         memory->set_context_cpu(cpu);
128         joystick->set_context_psg(psg);
129         
130         timer->set_context_cpu(cpu);
131 #ifndef _PC6001
132         timer->set_context_memory(memory);
133 #endif
134         if(support_sub_cpu) {
135                 cpu_sub = new MCS48(this, emu);
136                 cpu_sub->set_device_name(_T("MCS48 MCU (Sub)"));
137                 sub = new SUB(this, emu);
138                 drec = new DATAREC(this, emu);
139                 drec->set_device_name(_T("Data Recorder (Sub)"));
140                 drec->set_context_noise_play(new NOISE(this, emu));
141                 drec->set_context_noise_stop(new NOISE(this, emu));
142                 drec->set_context_noise_fast(new NOISE(this, emu));
143                 event->set_context_cpu(cpu_sub, 8000000);
144                 event->set_context_sound(drec);
145                 event->set_context_sound(drec->get_context_noise_play());
146                 event->set_context_sound(drec->get_context_noise_stop());
147                 event->set_context_sound(drec->get_context_noise_fast());
148                 cpu_sub->set_context_mem(new MCS48MEM(this, emu));
149                 cpu_sub->set_context_io(sub);
150 #ifdef USE_DEBUGGER
151                 cpu_sub->set_context_debugger(new DEBUGGER(this, emu));
152 #endif
153                 sub->set_context_pio(pio_sub);
154                 sub->set_context_drec(drec);
155                 sub->set_context_timer(timer);
156                 pio_sub->set_context_port_c(cpu_sub, SIG_CPU_IRQ, 0x80, 0);
157                 drec->set_context_ear(sub, SIG_SUB_DATAREC, 1);
158                 timer->set_context_sub(sub);
159         } else {
160                 psub = new PSUB(this, emu);
161                 psub->set_context_pio(pio_sub);
162                 psub->set_context_timer(timer);
163                 timer->set_context_sub(psub);
164                 cpu_sub = NULL;
165         }
166         if(support_pc80s31k) {
167                 pio_fdd = new I8255(this, emu);
168                 pio_fdd->set_device_name(_T("8255 PIO (FDD I/F)"));
169                 pio_pc80s31k = new I8255(this, emu);
170                 pio_pc80s31k->set_device_name(_T("8255 PIO (320KB FDD)"));
171                 pc80s31k = new PC80S31K(this, emu);
172                 pc80s31k->set_device_name(_T("PC-80S31K (320KB FDD)"));
173                 fdc_pc80s31k = new UPD765A(this, emu);
174                 fdc_pc80s31k->set_device_name(_T("uPD765A FDC (320KB FDD)"));
175                 cpu_pc80s31k = new Z80(this, emu);
176                 cpu_pc80s31k->set_device_name(_T("Z80 CPU (320KB FDD)"));
177                 
178                 event->set_context_cpu(cpu_pc80s31k, 4000000);
179                 
180                 pc80s31k->set_context_cpu(cpu_pc80s31k);
181                 pc80s31k->set_context_fdc(fdc_pc80s31k);
182                 pc80s31k->set_context_pio(pio_pc80s31k);
183                 pio_fdd->set_context_port_a(pio_pc80s31k, SIG_I8255_PORT_B, 0xff, 0);
184                 pio_fdd->set_context_port_b(pio_pc80s31k, SIG_I8255_PORT_A, 0xff, 0);
185                 pio_fdd->set_context_port_c(pio_pc80s31k, SIG_I8255_PORT_C, 0x0f, 4);
186                 pio_fdd->set_context_port_c(pio_pc80s31k, SIG_I8255_PORT_C, 0xf0, -4);
187                 pio_fdd->clear_ports_by_cmdreg = true;
188                 pio_pc80s31k->set_context_port_a(pio_fdd, SIG_I8255_PORT_B, 0xff, 0);
189                 pio_pc80s31k->set_context_port_b(pio_fdd, SIG_I8255_PORT_A, 0xff, 0);
190                 pio_pc80s31k->set_context_port_c(pio_fdd, SIG_I8255_PORT_C, 0x0f, 4);
191                 pio_pc80s31k->set_context_port_c(pio_fdd, SIG_I8255_PORT_C, 0xf0, -4);
192                 pio_pc80s31k->clear_ports_by_cmdreg = true;
193                 fdc_pc80s31k->set_context_irq(cpu_pc80s31k, SIG_CPU_IRQ, 1);
194                 fdc_pc80s31k->set_context_noise_seek(noise_seek);
195                 fdc_pc80s31k->set_context_noise_head_down(noise_head_down);
196                 fdc_pc80s31k->set_context_noise_head_up(noise_head_up);
197                 cpu_pc80s31k->set_context_mem(pc80s31k);
198                 cpu_pc80s31k->set_context_io(pc80s31k);
199                 cpu_pc80s31k->set_context_intr(pc80s31k);
200 #ifdef USE_DEBUGGER
201                 cpu_pc80s31k->set_context_debugger(new DEBUGGER(this, emu));
202 #endif
203 #if defined(_PC6601) || defined(_PC6601SR)
204                 floppy->set_context_ext(pio_fdd);
205 #endif
206         } else {
207                 pc6031 = new PC6031(this, emu);
208                 pc6031->set_context_noise_seek(noise_seek);
209 //              pc6031->set_context_noise_head_down(noise_head_down);
210 //              pc6031->set_context_noise_head_up(noise_head_up);
211 #if defined(_PC6601) || defined(_PC6601SR)
212                 floppy->set_context_ext(pc6031);
213 #endif
214                 cpu_pc80s31k = NULL;
215         }
216         
217         // cpu bus
218         cpu->set_context_mem(memory);
219         cpu->set_context_io(io);
220         cpu->set_context_intr(timer);
221 #ifdef USE_DEBUGGER
222         cpu->set_context_debugger(new DEBUGGER(this, emu));
223 #endif
224         
225         // i/o bus
226         if(support_sub_cpu) {
227                 io->set_iomap_range_rw(0x90, 0x93, sub);
228         } else {
229                 io->set_iomap_range_rw(0x90, 0x93, psub);
230         }
231         io->set_iomap_alias_w(0xa0, psg, 0);                    // PSG ch
232         io->set_iomap_alias_w(0xa1, psg, 1);                    // PSG data
233         io->set_iomap_alias_r(0xa2, psg, 1);                    // PSG data
234 #if defined(_PC6601SR) || defined(_PC6001MK2SR)
235         io->set_iomap_alias_r(0xa3, psg, 0);                    // FM status
236         io->set_iomap_range_rw(0x40, 0x6f, memory);             // VRAM addr
237 #endif
238 #ifdef _PC6001
239         io->set_iomap_single_w(0xb0, display);                  // VRAM addr
240         io->set_iomap_single_w(0x00, memory);                   // MEMORY MAP
241 #else
242         io->set_iomap_single_w(0xb0, memory);                   // VRAM addr
243         io->set_iomap_range_rw(0xc0, 0xcf, memory);             // VRAM addr
244         io->set_iomap_range_rw(0xe0, 0xe3, voice);              // VOICE
245 #if defined(_PC6601) || defined(_PC6601SR)
246         io->set_iomap_range_rw(0xb8, 0xbf, timer);              // IRQ
247         io->set_iomap_range_rw(0xfa, 0xfb, timer);              // IRQ
248 #endif
249         io->set_iomap_range_rw(0xf3, 0xf7, timer);              // IRQ/Timer
250 #endif
251         
252 #if defined(_PC6601) || defined(_PC6601SR)
253         io->set_iomap_range_rw(0xb1, 0xb3, floppy);             // DISK DRIVE
254         io->set_iomap_range_rw(0xb5, 0xb7, floppy);             // DISK DRIVE (Mirror)
255         io->set_iomap_range_rw(0xd0, 0xde, floppy);             // DISK DRIVE
256 #else
257         io->set_iovalue_single_r(0xb1, 0x01);
258 #if defined(_PC6601SR)
259         io->set_iovalue_single_r(0xb2, 0x02);
260 #elif defined(_PC6001MK2SR)
261         io->set_iovalue_single_r(0xb2, 0x00);
262 #endif
263         
264         if(support_pc80s31k) {
265                 io->set_iomap_range_rw(0xd0, 0xd2, pio_fdd);
266                 io->set_iomap_single_w(0xd3, pio_fdd);
267         } else {
268                 io->set_iomap_range_rw(0xd0, 0xd3, pc6031);
269         }
270 #endif
271         io->set_iomap_range_rw(0xf0, 0xf2, memory);             // MEMORY MAP
272         
273         // initialize all devices
274 #if defined(__GIT_REPO_VERSION)
275         strncpy(_git_revision, __GIT_REPO_VERSION, sizeof(_git_revision) - 1);
276 #endif
277         for(DEVICE* device = first_device; device; device = device->next_device) {
278                 device->initialize();
279         }
280
281         if(support_sub_cpu) {
282                 // load rom images after cpustate is allocated
283 #ifdef _PC6601SR
284 #else
285                 cpu_sub->load_rom_image(create_local_path(_T(SUB_CPU_ROM_FILE_NAME)));
286 #endif
287         }
288         int drive_num = 0;
289 #if defined(_PC6601) || defined(_PC6601SR)
290         floppy->get_disk_handler(0)->drive_num = drive_num++;
291         floppy->get_disk_handler(1)->drive_num = drive_num++;
292 #endif
293         if(support_pc80s31k) {
294                 fdc_pc80s31k->get_disk_handler(0)->drive_num = drive_num++;
295                 fdc_pc80s31k->get_disk_handler(1)->drive_num = drive_num++;
296         } else {
297                 pc6031->get_disk_handler(0)->drive_num = drive_num++;
298                 pc6031->get_disk_handler(1)->drive_num = drive_num++;
299         }
300         decl_state();
301 }
302
303 VM::~VM()
304 {
305         // delete all devices
306         for(DEVICE* device = first_device; device;) {
307                 DEVICE *next_device = device->next_device;
308                 device->release();
309                 delete device;
310                 device = next_device;
311         }
312 }
313
314 DEVICE* VM::get_device(int id)
315 {
316         for(DEVICE* device = first_device; device; device = device->next_device) {
317                 if(device->this_device_id == id) {
318                         return device;
319                 }
320         }
321         return NULL;
322 }
323
324 // ----------------------------------------------------------------------------
325 // drive virtual machine
326 // ----------------------------------------------------------------------------
327 void VM::reset()
328 {
329         // reset all devices
330         for(DEVICE* device = first_device; device; device = device->next_device) {
331                 device->reset();
332         }
333         if(support_pc80s31k) {
334                 pio_fdd->write_signal(SIG_I8255_PORT_C, 0, 0xff);
335                 pio_pc80s31k->write_signal(SIG_I8255_PORT_C, 0, 0xff);
336         }
337 }
338
339 void VM::run()
340 {
341         event->drive();
342 }
343
344 // ----------------------------------------------------------------------------
345 // debugger
346 // ----------------------------------------------------------------------------
347
348 #ifdef USE_DEBUGGER
349 DEVICE *VM::get_cpu(int index)
350 {
351         if(index == 0) {
352                 return cpu;
353         } else if(index == 1) {
354                 return cpu_sub;
355         } else if(index == 2) {
356                 return cpu_pc80s31k;
357         }
358         return NULL;
359 }
360 #endif
361
362 // ----------------------------------------------------------------------------
363 // draw screen
364 // ----------------------------------------------------------------------------
365
366 void VM::draw_screen()
367 {
368 #ifdef _PC6001
369         display->draw_screen();
370 #else
371         memory->draw_screen();
372 #endif
373 }
374 // ----------------------------------------------------------------------------
375 // soud manager
376 // ----------------------------------------------------------------------------
377
378 void VM::initialize_sound(int rate, int samples)
379 {
380         // init sound manager
381         event->initialize_sound(rate, samples);
382         
383         // init sound gen
384         psg->initialize_sound(rate, 4000000, samples, 0, 0);
385 #ifndef _PC6001
386         voice->initialize_sound(rate);
387 #endif
388 }
389
390 uint16_t* VM::create_sound(int* extra_frames)
391 {
392         return event->create_sound(extra_frames);
393 }
394
395 int VM::get_sound_buffer_ptr()
396 {
397         return event->get_sound_buffer_ptr();
398 }
399
400 #ifdef USE_SOUND_VOLUME
401 void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
402 {
403         if(ch-- == 0) {
404                 psg->set_volume(1, decibel_l, decibel_r);
405 #if !defined(_PC6001)
406         } else if(ch-- == 0) {
407                 voice->set_volume(0, decibel_l, decibel_r);
408 #endif
409         } else if(ch-- == 0) {
410                 if(support_sub_cpu) {
411                         drec->set_volume(0, decibel_l, decibel_r);
412                 }
413         } else if(ch-- == 0) {
414                 noise_seek->set_volume(0, decibel_l, decibel_r);
415                 noise_head_down->set_volume(0, decibel_l, decibel_r);
416                 noise_head_up->set_volume(0, decibel_l, decibel_r);
417         } else if(ch-- == 0) {
418                 if(support_sub_cpu) {
419                         drec->get_context_noise_play()->set_volume(0, decibel_l, decibel_r);
420                         drec->get_context_noise_stop()->set_volume(0, decibel_l, decibel_r);
421                         drec->get_context_noise_fast()->set_volume(0, decibel_l, decibel_r);
422                 }
423         }
424 }
425 #endif
426
427 // ----------------------------------------------------------------------------
428 // notify key
429 // ----------------------------------------------------------------------------
430
431 void VM::key_down(int code, bool repeat)
432 {
433         if(!support_sub_cpu) {
434                 psub->key_down(code);
435         }
436 }
437
438 void VM::key_up(int code)
439 {
440         if(!support_sub_cpu) {
441                 psub->key_up(code);
442         }
443 }
444
445 // ----------------------------------------------------------------------------
446 // user interface
447 // ----------------------------------------------------------------------------
448
449 void VM::open_cart(int drv, const _TCHAR* file_path)
450 {
451         if(drv == 0) {
452                 memory->open_cart(file_path);
453                 reset();
454         }
455 }
456
457 void VM::close_cart(int drv)
458 {
459         if(drv == 0) {
460                 memory->close_cart();
461                 reset();
462         }
463 }
464
465 bool VM::is_cart_inserted(int drv)
466 {
467         if(drv == 0) {
468                 return memory->is_cart_inserted();
469         } else {
470                 return false;
471         }
472 }
473
474 void VM::open_floppy_disk(int drv, const _TCHAR* file_path, int bank)
475 {
476 #if defined(_PC6601) || defined(_PC6601SR)
477         if(drv < 2) {
478                 floppy->open_disk(drv, file_path, bank);
479                 return;
480         } else {
481                 drv -= 2;
482         }
483 #endif
484         if(support_pc80s31k) {
485                 fdc_pc80s31k->open_disk(drv, file_path, bank);
486         } else {
487                 pc6031->open_disk(drv, file_path, bank);
488         }
489 }
490
491 void VM::close_floppy_disk(int drv)
492 {
493 #if defined(_PC6601) || defined(_PC6601SR)
494         if(drv < 2) {
495                 floppy->close_disk(drv);
496                 return;
497         } else {
498                 drv -= 2;
499         }
500 #endif
501         if(support_pc80s31k) {
502                 fdc_pc80s31k->close_disk(drv);
503         } else {
504                 pc6031->close_disk(drv);
505         }
506 }
507
508 bool VM::is_floppy_disk_inserted(int drv)
509 {
510 #if defined(_PC6601) || defined(_PC6601SR)
511         if(drv < 2) {
512                 return floppy->is_disk_inserted(drv);
513         } else {
514                 drv -= 2;
515         }
516 #endif
517         if(support_pc80s31k) {
518                 return fdc_pc80s31k->is_disk_inserted(drv);
519         } else {
520                 return pc6031->is_disk_inserted(drv);
521         }
522 }
523
524 void VM::is_floppy_disk_protected(int drv, bool value)
525 {
526 #if defined(_PC6601) || defined(_PC6601SR)
527         if(drv < 2) {
528                 floppy->is_disk_protected(drv, value);
529                 return;
530         } else {
531                 drv -= 2;
532         }
533 #endif
534         if(support_pc80s31k) {
535                 fdc_pc80s31k->is_disk_protected(drv, value);
536         } else {
537                 pc6031->is_disk_protected(drv, value);
538         }
539 }
540
541 bool VM::is_floppy_disk_protected(int drv)
542 {
543 #if defined(_PC6601) || defined(_PC6601SR)
544         if(drv < 2) {
545                 return floppy->is_disk_protected(drv);
546         } else {
547                 drv -= 2;
548         }
549 #endif
550         if(support_pc80s31k) {
551                 return fdc_pc80s31k->is_disk_protected(drv);
552         } else {
553                 return pc6031->is_disk_protected(drv);
554         }
555 }
556
557 uint32_t VM::is_floppy_disk_accessed()
558 {
559         uint32_t status = 0; /// fdc->read_signal(0);
560         if(support_pc80s31k) {
561                 status |= fdc_pc80s31k->read_signal(0);
562         } else {
563                 status |= pc6031->read_signal(0);
564         }
565 #if defined(_PC6601) || defined(_PC6601SR)
566         status <<= 2;
567         status |= floppy->read_signal(0);
568 #endif
569         return status;
570 }
571
572 void VM::play_tape(int drv, const _TCHAR* file_path)
573 {
574         if(support_sub_cpu) {
575                 // support both p6/p6t and wav
576                 drec->play_tape(file_path);
577 //              drec->set_remote(true);
578         } else {
579                 // support only p6/p6t
580                 psub->play_tape(file_path);
581         }
582 }
583
584 void VM::rec_tape(int drv, const _TCHAR* file_path)
585 {
586         if(support_sub_cpu) {
587                 // support both p6/p6t and wav
588                 sub->rec_tape(file_path);       // temporary
589 //              drec->rec_tape(file_path);
590 //              drec->set_remote(true);
591         } else {
592                 // support both p6/p6t and wav
593                 psub->rec_tape(file_path);
594         }
595 }
596
597 void VM::close_tape(int drv)
598 {
599         if(support_sub_cpu) {
600                 if(sub->is_tape_inserted()) {
601                         sub->close_tape();      // temporary
602                 } else {
603                         emu->lock_vm();
604                         drec->close_tape();
605                         emu->unlock_vm();
606 //                      drec->set_remote(false);
607                 }
608         } else {
609                 psub->close_tape();
610         }
611 }
612
613 bool VM::is_tape_inserted(int drv)
614 {
615         if(support_sub_cpu) {
616                 return drec->is_tape_inserted() || sub->is_tape_inserted();
617         } else {
618                 return psub->is_tape_inserted();
619         }
620 }
621
622 bool VM::is_tape_playing(int drv)
623 {
624         if(support_sub_cpu) {
625                 return drec->is_tape_playing();
626         } else {
627                 return false;
628         }
629 }
630
631 bool VM::is_tape_recording(int drv)
632 {
633         if(support_sub_cpu) {
634                 return drec->is_tape_recording();
635         } else {
636                 return false;
637         }
638 }
639
640 int VM::get_tape_position(int drv)
641 {
642         if(support_sub_cpu) {
643                 return drec->get_tape_position();
644         } else {
645                 return 0;
646         }
647 }
648
649 const _TCHAR* VM::get_tape_message(int drv)
650 {
651         if(support_sub_cpu) {
652                 return drec->get_message();
653         } else {
654                 return NULL;
655         }
656 }
657
658 void VM::push_play(int drv)
659 {
660         if(support_sub_cpu) {
661                 drec->set_ff_rew(0);
662                 drec->set_remote(true);
663         }
664 }
665
666 void VM::push_stop(int drv)
667 {
668         if(support_sub_cpu) {
669                 drec->set_remote(false);
670         }
671 }
672
673 void VM::push_fast_forward(int drv)
674 {
675         if(support_sub_cpu) {
676                 drec->set_ff_rew(1);
677                 drec->set_remote(true);
678         }
679 }
680
681 void VM::push_fast_rewind(int drv)
682 {
683         if(support_sub_cpu) {
684                 drec->set_ff_rew(-1);
685                 drec->set_remote(true);
686         }
687 }
688
689 bool VM::is_frame_skippable()
690 {
691         return event->is_frame_skippable();
692 }
693
694 void VM::update_config()
695 {
696         for(DEVICE* device = first_device; device; device = device->next_device) {
697                 device->update_config();
698         }
699 }
700
701 #define STATE_VERSION   6
702
703 #include "../../statesub.h"
704 #include "../../qt/gui/csp_logger.h"
705 extern CSP_Logger DLL_PREFIX_I *csp_logger;
706
707 void VM::decl_state(void)
708 {
709 #if defined(_PC6001)
710         state_entry = new csp_state_utils(STATE_VERSION, 0, (_TCHAR *)(_T("CSP::PC_6001_HEAD")), csp_logger);
711 #elif defined(_PC6001MK2)
712         state_entry = new csp_state_utils(STATE_VERSION, 0, (_TCHAR *)(_T("CSP::PC_6001_MK2_HEAD")), csp_logger);
713 #elif defined(_PC6001MK2SR)
714         state_entry = new csp_state_utils(STATE_VERSION, 0, (_TCHAR *)(_T("CSP::PC_6001_MK2_SR_HEAD")), csp_logger);
715 #elif defined(_PC6601)
716         state_entry = new csp_state_utils(STATE_VERSION, 0, (_TCHAR *)(_T("CSP::PC_6601_HEAD")), csp_logger);
717 #elif defined(_PC601SR)
718         state_entry = new csp_state_utils(STATE_VERSION, 0, (_TCHAR *)(_T("CSP::PC_6601_SR_HEAD")), csp_logger);
719 #else
720         state_entry = new csp_state_utils(STATE_VERSION, 0, (_TCHAR *)(_T("CSP::PC_6001_SERIES_HEAD")), csp_logger);
721 #endif
722         DECL_STATE_ENTRY_INT32(sr_mode);
723         for(DEVICE* device = first_device; device; device = device->next_device) {
724                 device->decl_state();
725         }
726 }
727
728 void VM::save_state(FILEIO* state_fio)
729 {
730         //state_fio->FputUint32(STATE_VERSION);
731         
732         if(state_entry != NULL) {
733                 state_entry->save_state(state_fio);
734         }
735         for(DEVICE* device = first_device; device; device = device->next_device) {
736                 device->save_state(state_fio);
737         }
738         //state_fio->FputInt32(sr_mode);
739 }
740
741 bool VM::load_state(FILEIO* state_fio)
742 {
743         //if(state_fio->FgetUint32() != STATE_VERSION) {
744         //      return false;
745         //}
746         bool mb = false;
747         if(state_entry != NULL) {
748                 mb = state_entry->load_state(state_fio);
749         }
750         if(!mb) {
751                 emu->out_debug_log("INFO: HEADER DATA ERROR");
752                 return false;
753         }
754         for(DEVICE* device = first_device; device; device = device->next_device) {
755                 if(!device->load_state(state_fio)) {
756                         return false;
757                 }
758         }
759         //sr_mode = state_fio->FgetInt32();
760         return true;
761 }
762