OSDN Git Service

[VM][FM7] Wait is CPU wait, not MEMORY WAIT.
[csp-qt/common_source_project-fm7.git] / source / src / vm / fm7 / fm7.cpp
1 /*
2  * FM7 -> VM
3  * (C) 2015 K.Ohta <whatisthis.sowhat _at_ gmail.com>
4  * History:
5  *   Feb 27, 2015 : Initial
6  */
7
8 #include "fm7.h"
9 #include "../../emu.h"
10 #include "../../config.h"
11 #include "../device.h"
12 #include "../event.h"
13 #include "../memory.h"
14 #include "../prnfile.h"
15
16 #ifdef USE_DEBUGGER
17 #include "../debugger.h"
18 #endif
19
20 #include "../datarec.h"
21 #include "../disk.h"
22
23 #include "../mc6809.h"
24 #include "../z80.h"
25 #include "../mb8877.h"
26 #include "../noise.h"
27
28 #include "../pcm1bit.h"
29 #include "../ym2203.h"
30 #include "../ay_3_891x.h"
31 #include "../and.h"
32 #include "../or.h"
33 #include "../i8251.h"
34
35 #if defined(_FM77AV_VARIANTS)
36 #include "mb61vh010.h"
37 #include "../beep.h"
38 #endif
39 #if defined(HAS_DMA)
40 #include "hd6844.h"
41 #endif
42 #if defined(_FM8)
43 #include "./bubblecasette.h"
44 #endif
45 #if defined(_FM8)
46 #include "./fm8_mainio.h"
47 #else
48 #include "./fm7_mainio.h"
49 #endif
50 #include "./fm7_mainmem.h"
51 #include "./fm7_display.h"
52 #include "./fm7_keyboard.h"
53 #include "./joystick.h"
54
55 #include "./kanjirom.h"
56 #if defined(CAPABLE_JCOMMCARD)
57 #include "./jcommcard.h"
58 #endif
59
60 VM::VM(EMU* parent_emu): emu(parent_emu)
61 {
62         
63         first_device = last_device = NULL;
64 #if defined(_FM8)
65         psg = NULL;
66 #else   
67 # if defined(_FM77AV_VARIANTS)
68         opn[0] = opn[1] = opn[2] = NULL;
69 # else   
70         opn[0] = opn[1] = opn[2] = NULL;
71         psg = NULL; 
72 # endif
73 #endif
74         for(int i = 0; i < 3; i++) uart[i] = NULL;
75         
76         dummy = new DEVICE(this, emu);  // must be 1st device
77         event = new EVENT(this, emu);   // must be 2nd device
78
79         //dummycpu = new DEVICE(this, emu);
80         maincpu = new MC6809(this, emu);
81         subcpu = new MC6809(this, emu);
82         g_substat_display = new AND(this, emu);
83         g_substat_mainhalt = new AND(this, emu);
84
85         
86 #ifdef WITH_Z80
87         if((config.dipswitch & FM7_DIPSW_Z80CARD_ON) != 0) {
88                 z80cpu = new Z80(this, emu);
89                 g_mainstat = new AND(this, emu);
90                 g_intr = new OR(this, emu);
91                 
92                 g_intr_irq = new AND(this, emu);
93                 g_intr_firq = new AND(this, emu);
94                 g_nmi = new AND(this, emu);
95         } else {
96                 z80cpu = NULL;
97                 g_mainstat = NULL;
98                 g_intr = NULL;
99
100                 g_intr_irq = NULL;
101                 g_intr_firq = NULL;
102                 g_nmi = NULL;
103         }
104 #endif
105 #if defined(CAPABLE_JCOMMCARD)
106         if((config.dipswitch & FM7_DIPSW_JSUBCARD_ON) != 0) {
107                 jsubcpu = new MC6809(this, emu);
108                 jcommcard = new FM7_JCOMMCARD(this, emu);
109                 g_jsubhalt = new AND(this, emu);
110         } else {
111                 jsubcpu = NULL;
112                 jcommcard = NULL;
113                 g_jsubhalt = NULL;
114         }
115 #endif
116 # if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX) || defined(_FM77AV20) \
117         || defined(_FM77AV20EX) || defined(_FM8)
118         uart[0] = new I8251(this, emu);
119 # else
120 #  if defined(CAPABLE_JCOMMCARD)
121         if((config.dipswitch & FM7_DIPSW_JSUBCARD_ON) != 0) uart[0] = new I8251(this, emu);
122 #  endif
123         if(((config.dipswitch & FM7_DIPSW_RS232C_ON) != 0) && (uart[0] == NULL)) uart[0] = new I8251(this, emu);
124 # endif
125         if((config.dipswitch & FM7_DIPSW_MODEM_ON) != 0) uart[1] = new I8251(this, emu);
126         if((config.dipswitch & FM7_DIPSW_MIDI_ON) != 0) uart[2] = new I8251(this, emu);
127
128                 
129         // basic devices
130         // I/Os
131 #if defined(HAS_DMA)
132         dmac = new HD6844(this, emu);
133 #endif   
134 #if defined(_FM8)
135 #  if defined(USE_AY_3_8910_AS_PSG)
136         psg = new AY_3_891X(this, emu);
137 #  else
138         psg = new YM2203(this, emu);
139 #  endif
140 #else   
141         opn[0] = new YM2203(this, emu); // OPN
142         opn[1] = new YM2203(this, emu); // WHG
143         opn[2] = new YM2203(this, emu); // THG
144 # if !defined(_FM77AV_VARIANTS)
145 #  if defined(USE_AY_3_8910_AS_PSG)
146         psg = new AY_3_891X(this, emu);
147 #  else
148         psg = new YM2203(this, emu);
149 #  endif
150 # endif 
151 #endif
152 #if defined(_FM8)
153         for(int i = 0; i < 2; i++) bubble_casette[i] = new BUBBLECASETTE(this, emu);
154 #endif
155         drec = NULL;
156         drec = new DATAREC(this, emu);
157         drec->set_context_noise_play(new NOISE(this, emu));
158         drec->set_context_noise_stop(new NOISE(this, emu));
159         drec->set_context_noise_fast(new NOISE(this, emu));
160         pcm1bit = new PCM1BIT(this, emu);
161
162         connect_320kfdc = connect_1Mfdc = false;
163         fdc = NULL;
164 #if defined(HAS_2HD)
165         fdc_2HD = NULL;
166 #endif
167
168 #if defined(_FM8) || defined(_FM7) || defined(_FMNEW7)
169         if((config.dipswitch & FM7_DIPSW_CONNECT_320KFDC) != 0) {
170                 fdc = new MB8877(this, emu);
171                 fdc->set_context_noise_seek(new NOISE(this, emu));
172                 fdc->set_context_noise_head_down(new NOISE(this, emu));
173                 fdc->set_context_noise_head_up(new NOISE(this, emu));
174                 connect_320kfdc = true;
175         }
176 #else
177         {
178                 fdc = new MB8877(this, emu);
179                 fdc->set_context_noise_seek(new NOISE(this, emu));
180                 fdc->set_context_noise_head_down(new NOISE(this, emu));
181                 fdc->set_context_noise_head_up(new NOISE(this, emu));
182                 connect_320kfdc = true;
183         }
184 #endif          
185 #if defined(HAS_2HD)
186         if((config.dipswitch & FM7_DIPSW_CONNECT_1MFDC) != 0) {
187                 fdc_2HD = new MB8877(this, emu);
188                 fdc_2HD->set_context_noise_seek(new NOISE(this, emu));
189                 fdc_2HD->set_context_noise_head_down(new NOISE(this, emu));
190                 fdc_2HD->set_context_noise_head_up(new NOISE(this, emu));
191                 connect_1Mfdc = true;
192         }
193 #endif
194         
195         joystick  = new JOYSTICK(this, emu);
196         printer = new PRNFILE(this, emu);
197 #if defined(_FM77AV_VARIANTS)
198         alu = new MB61VH010(this, emu);
199         keyboard_beep = new BEEP(this, emu);
200 #endif  
201         keyboard = new KEYBOARD(this, emu);
202         display = new DISPLAY(this, emu);       
203 #if defined(_FM8)
204         mainio  = new FM8_MAINIO(this, emu);
205 #else
206         mainio  = new FM7_MAINIO(this, emu);
207 #endif
208         mainmem = new FM7_MAINMEM(this, emu);
209
210 #if defined(_FM8) || defined(_FM7) || defined(_FMNEW7)
211         if((config.dipswitch & FM7_DIPSW_CONNECT_KANJIROM) != 0) {
212                 kanjiclass1 = new KANJIROM(this, emu, false);
213         } else {
214                 kanjiclass1 = NULL;
215         }
216 #else
217         kanjiclass1 = new KANJIROM(this, emu, false);
218 #endif  
219 #ifdef CAPABLE_KANJI_CLASS2
220         kanjiclass2 = new KANJIROM(this, emu, true);
221 #endif
222
223 # if defined(_FM77AV20) || defined(_FM77AV40) || defined(_FM77AV20EX) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
224         g_rs232c_dtr = new AND(this, emu);
225         g_rs232c_dtr->set_mask(SIG_AND_BIT_0);
226         g_rs232c_dtr->set_mask(SIG_AND_BIT_1);
227
228         // DCD
229 #endif
230 #ifdef WITH_Z80
231         if(g_mainstat != NULL) {
232                 g_mainstat->set_mask(SIG_AND_BIT_0);
233                 g_mainstat->set_mask(SIG_AND_BIT_1);
234                 maincpu->set_context_bus_ba(g_mainstat, SIG_AND_BIT_0, 0xffffffff);
235                 maincpu->set_context_bus_bs(g_mainstat, SIG_AND_BIT_1, 0xffffffff);
236                 g_mainstat->set_context_out(mainio, FM7_MAINIO_RUN_Z80, 0xffffffff);
237         }
238         if(z80cpu != NULL) {
239                 z80cpu->set_context_busack(mainio, FM7_MAINIO_RUN_6809, 0xffffffff);
240                 mainio->set_context_z80cpu(z80cpu);
241         }
242 #endif
243 #if defined(_USE_QT)
244         event->set_device_name(_T("EVENT"));
245         dummy->set_device_name(_T("1st Dummy"));
246         
247         maincpu->set_device_name(_T("MAINCPU(MC6809B)"));
248         subcpu->set_device_name(_T("SUBCPU(MC6809B)"));
249 #if defined(CAPABLE_JCOMMCARD)
250         if(jsubcpu != NULL) {
251                 jsubcpu->set_device_name(_T("J.COMM BOARD CPU(MC6809)"));
252         }
253         if(jcommcard != NULL) {
254                 jcommcard->set_device_name(_T("Japanese COMM BOARD"));
255         }
256         if(g_jsubhalt != NULL) {
257                 g_jsubhalt->set_device_name(_T("J.COMM BOARD HALT(MC6809)"));
258         }
259 # endif
260 # ifdef WITH_Z80
261         if(z80cpu != NULL) z80cpu->set_device_name(_T("Z80 CPU BOARD"));
262 # endif
263         if(fdc != NULL) fdc->set_device_name(_T("MB8877 FDC(320KB)"));
264 #if defined(HAS_2HD)
265         if(fdc_2HD != NULL) fdc_2HD->set_device_name(_T("MB8877 FDC(1MB/2HD)"));
266 #endif  
267         if(uart[0] != NULL) {
268                 uart[0]->set_device_name(_T("RS-232C BOARD(I8251 SIO)"));
269         }
270 # if defined(CAPABLE_JCOMMCARD)
271         if((config.dipswitch & FM7_DIPSW_JSUBCARD_ON) != 0) {
272                 if(uart[0] != NULL) uart[0]->set_device_name(_T("J.COMM BOARD RS-232C(I8251 SIO)"));
273         }
274 # elif defined(_FM77AV20) || defined(_FM77AV40) || defined(_FM77AV20EX) || \
275         defined(_FM77AV40EX) || defined(_FM77AV40SX) || defined(_FM8)
276         if(uart[0] != NULL) uart[0]->set_device_name(_T("RS-232C(I8251 SIO)"));
277 # endif
278                 
279         if(uart[1] != NULL) {
280                 uart[1]->set_device_name(_T("MODEM BOARD(I8251 SIO)"));
281         }
282         if(uart[2] != NULL) {
283                 uart[2]->set_device_name(_T("MIDI BOARD(I8251 SIO)"));
284         }
285                                                 
286         // basic devices
287         // I/Os
288 # if defined(_FM8)
289         psg->set_device_name(_T("AY-3-8910 PSG"));
290 # else  
291         opn[0]->set_device_name(_T("YM2203 OPN"));
292         opn[1]->set_device_name(_T("YM2203 WHG"));
293         opn[2]->set_device_name(_T("YM2203 THG"));
294 #  if !defined(_FM77AV_VARIANTS)
295         psg->set_device_name(_T("AY-3-8910 PSG"));
296 #  endif
297         pcm1bit->set_device_name(_T("BEEP"));
298         printer->set_device_name(_T("PRINTER I/F"));
299 # if defined(_FM77AV_VARIANTS)
300         keyboard_beep->set_device_name(_T("BEEP(KEYBOARD)"));
301 # endif 
302         if(kanjiclass1 != NULL) kanjiclass1->set_device_name(_T("KANJI ROM CLASS1"));
303 # ifdef CAPABLE_KANJI_CLASS2
304         if(kanjiclass2 != NULL) kanjiclass2->set_device_name(_T("KANJI ROM CLASS2"));
305 # endif
306 # if defined(_FM8)
307         bubble_casette[0]->set_device_name(_T("BUBBLE CASETTE #0"));
308         bubble_casette[1]->set_device_name(_T("BUBBLE CASETTE #1"));
309 # endif 
310 #endif
311 # if defined(_FM77AV20) || defined(_FM77AV40) || defined(_FM77AV20EX) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
312         g_rs232c_dtr->set_device_name(_T("RS232C DTR(AND)"));
313 #endif
314 #ifdef WITH_Z80
315         if(g_intr != NULL) g_intr->set_device_name(_T("Z80 INTR(OR)"));
316         if(g_mainstat != NULL) g_mainstat->set_device_name(_T("Z80 HALT/RUN(AND)"));
317         if(g_intr_irq != NULL) g_intr_irq->set_device_name(_T("Z80 IRQ(AND)"));
318         if(g_intr_firq != NULL) g_intr_firq->set_device_name(_T("Z80 FIRQ(AND)"));
319         if(g_nmi != NULL) g_nmi->set_device_name(_T("Z80 NMI(AND)"));
320 #endif
321         g_substat_display->set_device_name(_T("DISPLAY STATUS(AND)"));
322         g_substat_mainhalt->set_device_name(_T("SUBSYSTEM HALT STATUS(AND)"));
323 #endif  
324         this->connect_bus();
325         
326 }
327
328 VM::~VM()
329 {
330         // delete all devices
331         for(DEVICE* device = first_device; device;) {
332                 DEVICE *next_device = device->next_device;
333                 device->release();
334                 delete device;
335                 device = next_device;
336         }
337 }
338
339 DEVICE* VM::get_device(int id)
340 {
341         for(DEVICE* device = first_device; device; device = device->next_device) {
342                 if(device->this_device_id == id) {
343                         return device;
344                 }
345         }
346         return NULL;
347 }
348
349 void VM::connect_bus(void)
350 {
351         uint32_t mainclock;
352         uint32_t subclock;
353
354         /*
355          * CLASS CONSTRUCTION
356          *
357          * VM 
358          *  |-> MAINCPU -> MAINMEM -> MAINIO -> MAIN DEVICES
359          *  |             |        |      
360          *  | -> SUBCPU  -> SUBMEM  -> SUBIO -> SUB DEVICES
361          *  | -> DISPLAY
362          *  | -> KEYBOARD
363          *
364          *  MAINMEM can access SUBMEM/IO, when SUBCPU is halted.
365          *  MAINMEM and SUBMEM can access DISPLAY and KEYBOARD with exclusive.
366          *  MAINCPU can access MAINMEM.
367          *  SUBCPU  can access SUBMEM.
368          *  DISPLAY : R/W from MAINCPU and SUBCPU.
369          *  KEYBOARD : R/W
370          *
371          */
372         event->set_frames_per_sec(FRAMES_PER_SEC);
373         event->set_lines_per_frame(LINES_PER_FRAME);
374         mainclock = CPU_CLOCKS; // Hack
375         subclock = SUBCLOCK_NORMAL;
376
377         event->set_context_cpu(maincpu, mainclock);
378         event->set_context_cpu(subcpu,  subclock);      
379    
380 #ifdef WITH_Z80
381         if(z80cpu != NULL) {
382                 event->set_context_cpu(z80cpu,  4000000);
383                 z80cpu->write_signal(SIG_CPU_BUSREQ, 1, 1);
384
385                 g_intr_irq->set_mask(SIG_AND_BIT_0);
386                 g_intr_irq->set_mask(SIG_AND_BIT_1);
387                 
388                 g_intr_firq->set_mask(SIG_AND_BIT_0);
389                 g_intr_firq->set_mask(SIG_AND_BIT_1);
390         
391                 g_nmi->set_mask(SIG_AND_BIT_0);
392                 g_nmi->set_mask(SIG_AND_BIT_1);
393
394                 mainio->set_context_irq(g_intr_irq, SIG_AND_BIT_1, 0xffffffff);
395                 g_intr_irq->set_context_out(g_intr, SIG_OR_BIT_0, 0xffffffff);
396         
397                 mainio->set_context_firq(g_intr_firq, SIG_AND_BIT_1, 0xffffffff);
398                 g_intr_firq->set_context_out(g_intr, SIG_OR_BIT_0, 0xffffffff);
399                 
400                 g_intr->set_context_out(z80cpu, SIG_CPU_IRQ, 0xffffffff);
401
402                 mainio->set_context_nmi(g_nmi, SIG_AND_BIT_1, 0xffffffff);
403                 g_nmi->set_context_out(z80cpu, SIG_CPU_NMI, 0xffffffff);
404         }
405         maincpu->write_signal(SIG_CPU_HALTREQ, 0, 1);
406 #endif
407 #if defined(CAPABLE_JCOMMCARD)
408         if((jsubcpu != NULL) && (jcommcard != NULL)) {
409                 event->set_context_cpu(jsubcpu,  JCOMMCARD_CLOCK);
410                 jcommcard->set_context_cpu(jsubcpu);
411                 if(g_jsubhalt != NULL) {
412                         g_jsubhalt->set_mask(SIG_AND_BIT_0);
413                         g_jsubhalt->set_mask(SIG_AND_BIT_1);
414                 
415                         jsubcpu->set_context_bus_ba(g_jsubhalt, SIG_AND_BIT_0, 0xffffffff);
416                         jsubcpu->set_context_bus_bs(g_jsubhalt, SIG_AND_BIT_1, 0xffffffff);
417                         g_jsubhalt->set_context_out(jcommcard, FM7_JCOMMCARD_BUS_HALT, 0xffffffff);
418                         mainio->set_context_jcommcard(jcommcard);
419                 }
420         }
421 #endif
422         event->set_context_sound(pcm1bit);
423 #if defined(_FM8)
424         event->set_context_sound(psg);
425         if(drec != NULL) event->set_context_sound(drec);
426 #else
427         event->set_context_sound(opn[0]);
428         event->set_context_sound(opn[1]);
429         event->set_context_sound(opn[2]);
430 # if !defined(_FM77AV_VARIANTS)
431         event->set_context_sound(psg);
432 # endif
433         event->set_context_sound(drec);
434         if(fdc != NULL) {
435                 event->set_context_sound(fdc->get_context_noise_seek());
436                 event->set_context_sound(fdc->get_context_noise_head_down());
437                 event->set_context_sound(fdc->get_context_noise_head_up());
438         }
439 #if defined(HAS_2HD)
440         if(fdc_2HD != NULL) {
441                 event->set_context_sound(fdc_2HD->get_context_noise_seek());
442                 event->set_context_sound(fdc_2HD->get_context_noise_head_down());
443                 event->set_context_sound(fdc_2HD->get_context_noise_head_up());
444         }
445 #endif
446         if(drec != NULL) {
447                 event->set_context_sound(drec->get_context_noise_play());
448                 event->set_context_sound(drec->get_context_noise_stop());
449                 event->set_context_sound(drec->get_context_noise_fast());
450         }
451 # if defined(_FM77AV_VARIANTS)
452         event->set_context_sound(keyboard_beep);
453 # endif
454 #endif   
455 #if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
456         //event->register_vline_event(display);
457         //event->register_frame_event(display);
458 #endif  
459         mainio->set_context_maincpu(maincpu);
460         mainio->set_context_subcpu(subcpu);
461         
462         mainio->set_context_display(display);
463         mainio->set_context_irq(maincpu, SIG_CPU_IRQ, 0xffffffff);
464         mainio->set_context_firq(maincpu, SIG_CPU_FIRQ, 0xffffffff);
465         mainio->set_context_nmi(maincpu, SIG_CPU_NMI, 0xffffffff);
466 #if defined(_FM77AV) || defined(_FM7) || defined(_FMNEW7) || defined(_FM77_VARIANTS)
467         if((config.dipswitch & FM7_DIPSW_RS232C_ON) != 0)       mainio->set_context_uart(0, uart[0]); /* $FD06- : RS232C */
468 #else
469         mainio->set_context_uart(0, uart[0]);
470 #endif
471         mainio->set_context_uart(1, uart[1]); /* $FD40- : MODEM */
472         mainio->set_context_uart(2, uart[2]); /* $FDEA- : MIDI */
473
474 #if defined(_FM77AV20) || defined(_FM77AV40) || defined(_FM77AV20EX) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
475         mainio->set_context_rs232c_dtr(g_rs232c_dtr);
476         if(uart[0] != NULL) uart[0]->set_context_dtr(g_rs232c_dtr, SIG_AND_BIT_1, 0xffffffff);
477 #endif
478         if(uart[0] != NULL) {
479                 uart[0]->set_context_rxrdy(mainio, FM7_MAINIO_UART0_RXRDY, 0xffffffff);
480                 uart[0]->set_context_txrdy(mainio, FM7_MAINIO_UART0_TXRDY, 0xffffffff);
481                 uart[0]->set_context_syndet(mainio, FM7_MAINIO_UART0_SYNDET, 0xffffffff);
482         }
483         if(uart[1] != NULL) {
484                 uart[1]->set_context_rxrdy(mainio, FM7_MAINIO_MODEM_RXRDY, 0xffffffff);
485                 uart[1]->set_context_txrdy(mainio, FM7_MAINIO_MODEM_TXRDY, 0xffffffff);
486                 uart[1]->set_context_syndet(mainio, FM7_MAINIO_MODEM_SYNDET, 0xffffffff);
487         }
488         if(uart[2] != NULL) {
489                 uart[2]->set_context_rxrdy(mainio, FM7_MAINIO_MIDI_RXRDY, 0xffffffff);
490                 uart[2]->set_context_txrdy(mainio, FM7_MAINIO_MIDI_TXRDY, 0xffffffff);
491                 uart[2]->set_context_syndet(mainio, FM7_MAINIO_MIDI_SYNDET, 0xffffffff);
492         }
493         
494 #if defined(_FM8) || defined(_FM7) || defined(_FMNEW7)
495         if((config.dipswitch & FM7_DIPSW_CONNECT_KANJIROM) != 0) {
496                 mainio->set_context_kanjirom_class1(kanjiclass1);
497         }
498 #else
499         mainio->set_context_kanjirom_class1(kanjiclass1);
500 #endif  
501         mainio->set_context_mainmem(mainmem);
502         mainio->set_context_keyboard(keyboard);
503         mainio->set_context_printer(printer);
504         mainio->set_context_printer_reset(printer, SIG_PRINTER_RESET, 0xffffffff);
505         mainio->set_context_printer_strobe(printer, SIG_PRINTER_STROBE, 0xffffffff);
506         mainio->set_context_printer_select(printer, SIG_PRINTER_SELECT, 0xffffffff);
507 #if defined(CAPABLE_KANJI_CLASS2)
508         mainio->set_context_kanjirom_class2(kanjiclass2);
509 #endif
510 #if defined(_FM8)
511         for(int i = 0; i < 2; i++) mainio->set_context_bubble(bubble_casette[i], i);
512 #endif  
513         keyboard->set_context_break_line(mainio, FM7_MAINIO_PUSH_BREAK, 0xffffffff);
514         keyboard->set_context_int_line(mainio, FM7_MAINIO_KEYBOARDIRQ, 0xffffffff);
515         keyboard->set_context_int_line(display, SIG_FM7_SUB_KEY_FIRQ, 0xffffffff);
516 #if defined(_FM77AV_VARIANTS)
517         keyboard->set_context_beep(keyboard_beep);
518 #endif  
519         keyboard->set_context_rxrdy(display, SIG_FM7KEY_RXRDY, 0x01);
520         keyboard->set_context_key_ack(display, SIG_FM7KEY_ACK, 0x01);
521    
522         if(drec != NULL) {
523                 drec->set_context_ear(mainio, FM7_MAINIO_CMT_RECV, 0xffffffff);
524                 //drec->set_context_remote(mainio, FM7_MAINIO_CMT_REMOTE, 0xffffffff);
525                 mainio->set_context_datarec(drec);
526         }
527         mainmem->set_context_mainio(mainio);
528         mainmem->set_context_display(display);
529         mainmem->set_context_maincpu(maincpu);
530 #if defined(CAPABLE_DICTROM)
531         mainmem->set_context_kanjirom_class1(kanjiclass1);
532 #endif  
533         display->set_context_mainio(mainio);
534         display->set_context_subcpu(subcpu);
535         display->set_context_keyboard(keyboard);
536
537         mainio->set_context_clock_status(mainmem, FM7_MAINIO_CLOCKMODE, 0xffffffff);
538         mainio->set_context_clock_status(display, SIG_DISPLAY_CLOCK, 0xffffffff);
539
540         g_substat_display->set_mask(SIG_AND_BIT_0);
541         g_substat_display->set_mask(SIG_AND_BIT_1);
542         subcpu->set_context_bus_ba(g_substat_display, SIG_AND_BIT_0, 0xffffffff);
543         subcpu->set_context_bus_bs(g_substat_display, SIG_AND_BIT_1, 0xffffffff);
544         g_substat_display->set_context_out(display, SIG_FM7_SUB_HALT, 0xffffffff);
545
546         g_substat_mainhalt->set_mask(SIG_AND_BIT_0);
547         g_substat_mainhalt->set_mask(SIG_AND_BIT_1);
548         subcpu->set_context_bus_ba(g_substat_mainhalt, SIG_AND_BIT_0, 0xffffffff);
549         subcpu->set_context_bus_bs(g_substat_mainhalt, SIG_AND_BIT_1, 0xffffffff);
550         g_substat_mainhalt->set_context_out(mainmem, SIG_FM7_SUB_HALT, 0xffffffff);
551
552 #if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
553         display->set_context_kanjiclass1(kanjiclass1);
554 #endif  
555 #if defined(CAPABLE_KANJI_CLASS2)
556         display->set_context_kanjiclass2(kanjiclass2);
557 #endif   
558 #if defined(_FM77AV_VARIANTS)
559         display->set_context_alu(alu);
560         alu->set_context_memory(display);
561         alu->set_direct_access_offset(DISPLAY_VRAM_DIRECT_ACCESS);
562 #endif  
563         // Palette, VSYNC, HSYNC, Multi-page, display mode. 
564         mainio->set_context_display(display);
565  
566 #if defined(_FM8) || (_FM7) || (_FMNEW7)
567         if(connect_320kfdc) {
568 #endif
569                 if(fdc != NULL) {
570                         //FDC
571                         fdc->set_context_irq(mainio, FM7_MAINIO_FDC_IRQ, 0x1);
572                         fdc->set_context_drq(mainio, FM7_MAINIO_FDC_DRQ, 0x1);
573                         mainio->set_context_fdc(fdc);
574                 }
575 #if defined(_FM8) || (_FM7) || (_FMNEW7)
576         }
577 #endif  
578 #if defined(HAS_2HD)
579         if(connect_1Mfdc && (fdc_2HD != NULL)) {
580                 //FDC
581                 fdc_2HD->set_context_irq(mainio, FM7_MAINIO_FDC_IRQ_2HD, 0x1);
582                 fdc_2HD->set_context_drq(mainio, FM7_MAINIO_FDC_DRQ_2HD, 0x1);
583                 mainio->set_context_fdc_2HD(fdc_2HD);
584         }
585 #endif  
586         // SOUND
587         mainio->set_context_beep(pcm1bit);
588 #if defined(_FM8)       
589         mainio->set_context_psg(psg);
590 #else
591 # if !defined(_FM77AV_VARIANTS)
592         mainio->set_context_psg(psg);
593 # endif
594         opn[0]->set_context_irq(mainio, FM7_MAINIO_OPN_IRQ, 0xffffffff);
595         mainio->set_context_opn(opn[0], 0);
596         joystick->set_context_opn(opn[0]);
597         mainio->set_context_joystick(joystick);
598         opn[0]->set_context_port_b(joystick, FM7_JOYSTICK_MOUSE_STROBE, 0xff, 0);
599         
600         opn[1]->set_context_irq(mainio, FM7_MAINIO_WHG_IRQ, 0xffffffff);
601         mainio->set_context_opn(opn[1], 1);
602         opn[2]->set_context_irq(mainio, FM7_MAINIO_THG_IRQ, 0xffffffff);
603         mainio->set_context_opn(opn[2], 2);
604 #endif   
605         subcpu->set_context_bus_clr(display, SIG_FM7_SUB_USE_CLR, 0x0000000f);
606    
607         event->register_frame_event(joystick);
608 #if defined(HAS_DMA)
609         dmac->set_context_src(fdc, 0);
610         dmac->set_context_dst(mainmem, 0);
611         dmac->set_context_int_line(mainio, FM7_MAINIO_DMA_INT, 0xffffffff);
612         dmac->set_context_busreq_line(maincpu, 1, SIG_CPU_BUSREQ, 0xffffffff);
613         mainio->set_context_dmac(dmac);
614 #endif
615         
616         // MEMORIES must set before initialize().
617         //dummycpu->set_context_mem(dummy);
618         maincpu->set_context_mem(mainmem);
619         subcpu->set_context_mem(display);
620         //dummycpu->write_signal(SIG_CPU_BUSREQ, 1, 1);
621 #ifdef WITH_Z80
622         if(z80cpu != NULL) z80cpu->set_context_mem(mainmem);
623 #endif
624 #if defined(CAPABLE_JCOMMCARD)
625         if((jsubcpu != NULL) && (jcommcard != NULL)) {
626                 jsubcpu->set_context_mem(jcommcard);
627         }
628 #endif
629 #ifdef USE_DEBUGGER
630         maincpu->set_context_debugger(new DEBUGGER(this, emu));
631         subcpu->set_context_debugger(new DEBUGGER(this, emu));
632 # ifdef WITH_Z80
633         if(z80cpu != NULL) z80cpu->set_context_debugger(new DEBUGGER(this, emu));
634 # endif
635 # if defined(CAPABLE_JCOMMCARD)
636         if(jsubcpu != NULL) {
637                 jsubcpu->set_context_debugger(new DEBUGGER(this, emu));
638         }
639 # endif
640 #endif
641         for(DEVICE* device = first_device; device; device = device->next_device) {
642                 device->initialize();
643         }
644
645 #if defined(WITH_Z80)
646         if(g_intr_irq != NULL) g_intr_irq->write_signal(SIG_AND_BIT_0, ((config.dipswitch & FM7_DIPSW_Z80_IRQ_ON) != 0) ? 1 : 0, 1);
647         if(g_intr_firq != NULL) g_intr_firq->write_signal(SIG_AND_BIT_0, ((config.dipswitch & FM7_DIPSW_Z80_FIRQ_ON) != 0) ? 1 : 0, 1);
648         if(g_nmi != NULL) g_nmi->write_signal(SIG_AND_BIT_0, ((config.dipswitch & FM7_DIPSW_Z80_NMI_ON) != 0) ? 1 : 0, 1);
649 #endif
650         // Disks
651 #if defined(_FM8) || (_FM7) || (_FMNEW7)
652         if(connect_320kfdc) {
653 #endif
654                 if(fdc != NULL) {
655                         for(int i = 0; i < 4; i++) {
656 #if defined(_FM77AV20) || defined(_FM77AV20EX) || \
657         defined(_FM77AV40SX) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
658                                 fdc->set_drive_type(i, DRIVE_TYPE_2DD);
659 #else
660                                 fdc->set_drive_type(i, DRIVE_TYPE_2D);
661 #endif
662                                 fdc->set_drive_mfm(i, true);
663                                 fdc->set_drive_rpm(i, 300);
664                         }
665                 }
666 #if defined(_FM8) || (_FM7) || (_FMNEW7)
667         }
668 #endif  
669         
670 #if defined(HAS_2HD)
671         if(connect_1Mfdc && (fdc_2HD != NULL)) {
672 // ToDo: Implement another FDC for 1MB (2HD or 8''), this is used by FM-8 to FM-77? Not FM77AV or later? I still know this.
673                 for(int i = 0; i < 2; i++) {
674                         fdc_2HD->set_drive_type(i, DRIVE_TYPE_2HD);
675                         fdc_2HD->set_drive_mfm(i, true);
676                         fdc_2HD->set_drive_rpm(i, 300);
677                 }
678         }
679 #endif  
680 }  
681
682 void VM::update_config()
683 {
684         for(DEVICE* device = first_device; device; device = device->next_device) {
685                 device->update_config();
686         }
687         update_dipswitch();
688 }
689
690 void VM::reset()
691 {
692         // reset all devices
693         for(DEVICE* device = first_device; device; device = device->next_device) {
694                 device->reset();
695         }
696 #if !defined(_FM77AV_VARIANTS) || defined(_FM8)
697 # if defined(USE_AY_3_8910_AS_PSG)
698         psg->set_reg(0x2e, 0);  // set prescaler
699         psg->write_signal(SIG_AY_3_891X_MUTE, 0x00, 0x01); // Okay?
700 # else  
701         psg->set_reg(0x27, 0); // stop timer
702         psg->set_reg(0x2e, 0);  // set prescaler
703         psg->write_signal(SIG_YM2203_MUTE, 0x00, 0x01); // Okay?
704 #endif
705 #endif
706 #if !defined(_FM8)
707         for(int i = 0; i < 3; i++) {
708                 opn[i]->set_reg(0x27, 0); // stop timer
709                 opn[i]->set_reg(0x2e, 0);       // set prescaler
710                 opn[i]->write_signal(SIG_YM2203_MUTE, 0x00, 0x01); // Okay?
711         }
712 #endif
713 }
714
715 void VM::special_reset()
716 {
717         // BREAK + RESET
718         mainio->reset();
719         mainmem->reset();
720         //mainio->write_signal(FM7_MAINIO_PUSH_BREAK, 1, 1);
721         //keyboard->write_signal(SIG_FM7KEY_OVERRIDE_PRESS_BREAK, 0xffffffff, 0xffffffff);
722         
723 #if defined(FM77AV_VARIANTS)    
724         mainio->write_signal(FM7_MAINIO_HOT_RESET, 1, 1);
725 #endif  
726         display->reset();
727         subcpu->reset();
728         maincpu->reset();
729         mainio->write_signal(FM7_MAINIO_PUSH_BREAK, 1, 1);
730         keyboard->write_signal(SIG_FM7KEY_OVERRIDE_PRESS_BREAK, 0xffffffff, 0xffffffff);
731         event->register_event(mainio, EVENT_UP_BREAK, 1000.0 * 1000.0, false, NULL);
732 }
733
734 void VM::run()
735 {
736         event->drive();
737 }
738
739 double VM::get_frame_rate()
740 {
741         return event->get_frame_rate();
742 }
743
744
745
746 // ----------------------------------------------------------------------------
747 // debugger
748 // ----------------------------------------------------------------------------
749
750 #ifdef USE_DEBUGGER
751 DEVICE *VM::get_cpu(int index)
752 {
753         if(index == 0) {
754                 return maincpu;
755         } else if(index == 1) {
756                 return subcpu;
757         }
758 #if defined(WITH_Z80)
759         else if(index == 2) {
760 # if defined(CAPABLE_JCOMMCARD)
761                 if(z80cpu == NULL) {
762                         return jsubcpu;
763                 }
764 # endif
765                 return z80cpu;
766         }
767 # if defined(CAPABLE_JCOMMCARD)
768         else if(index == 3) {
769                 return jsubcpu;
770         }
771 # endif
772 #else
773 # if defined(CAPABLE_JCOMMCARD)
774         else if(index == 2) {
775                 return jsubcpu;
776         }
777 # endif
778 #endif
779         return NULL;
780 }
781 #endif
782
783 // ----------------------------------------------------------------------------
784 // draw screen
785 // ----------------------------------------------------------------------------
786
787 void VM::draw_screen()
788 {
789         display->draw_screen();
790 }
791
792 void VM::initialize_sound(int rate, int samples)
793 {
794         // init sound manager
795         event->initialize_sound(rate, samples);
796         // init sound gen
797 #if defined(_FM8)
798         psg->initialize_sound(rate, (int)(4.9152 * 1000.0 * 1000.0 / 4.0), samples, 0, 0);
799 #else   
800         opn[0]->initialize_sound(rate, (int)(4.9152 * 1000.0 * 1000.0 / 4.0), samples, 0, 0);
801         opn[1]->initialize_sound(rate, (int)(4.9152 * 1000.0 * 1000.0 / 4.0), samples, 0, 0);
802         opn[2]->initialize_sound(rate, (int)(4.9152 * 1000.0 * 1000.0 / 4.0), samples, 0, 0);
803 # if !defined(_FM77AV_VARIANTS)   
804         psg->initialize_sound(rate, (int)(4.9152 * 1000.0 * 1000.0 / 4.0), samples, 0, 0);
805 # endif
806 # if defined(_FM77AV_VARIANTS)
807         keyboard_beep->initialize_sound(rate, 2400.0, 512);
808 # endif
809 #endif  
810         pcm1bit->initialize_sound(rate, 2000);
811         //drec->initialize_sound(rate, 0);
812 }
813
814 uint16_t* VM::create_sound(int* extra_frames)
815 {
816         uint16_t* p = event->create_sound(extra_frames);
817         return p;
818 }
819
820 int VM::get_sound_buffer_ptr()
821 {
822         int pos = event->get_sound_buffer_ptr();
823         return pos; 
824 }
825
826 #ifdef USE_SOUND_VOLUME
827 void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
828 {
829 #if !defined(_FM77AV_VARIANTS)
830         if(ch-- == 0) {
831                 psg->set_volume(0, decibel_l, decibel_r);
832                 psg->set_volume(1, decibel_l, decibel_r);
833         } else
834 #endif
835 #if !defined(_FM8)              
836         if(ch-- == 0) {
837                 opn[0]->set_volume(0, decibel_l, decibel_r);
838         } else if(ch-- == 0) {
839                 opn[0]->set_volume(1, decibel_l, decibel_r);
840         } else if(ch-- == 0) {
841                 opn[1]->set_volume(0, decibel_l, decibel_r);
842         } else if(ch-- == 0) {
843                 opn[1]->set_volume(1, decibel_l, decibel_r);
844         } else if(ch-- == 0) {
845                 opn[2]->set_volume(0, decibel_l, decibel_r);
846         } else if(ch-- == 0) {
847                 opn[2]->set_volume(1, decibel_l, decibel_r);
848         } else
849 #endif  
850         if(ch-- == 0) {
851                 pcm1bit->set_volume(0, decibel_l, decibel_r);
852         } else if(ch-- == 0) {
853                 if(drec != NULL) drec->set_volume(0, decibel_l, decibel_r);
854         }
855 #if defined(_FM77AV_VARIANTS)
856         else if(ch-- == 0) {
857                 keyboard_beep->set_volume(0, decibel_l, decibel_r);
858         }
859 #endif
860         else if(ch-- == 0) {
861                 if(fdc != NULL) {
862                         fdc->get_context_noise_seek()->set_volume(0, decibel_l, decibel_r);
863                         fdc->get_context_noise_head_down()->set_volume(0, decibel_l, decibel_r);
864                         fdc->get_context_noise_head_up()->set_volume(0, decibel_l, decibel_r);
865                 }
866         } 
867 #if defined(HAS_2HD)
868         else if(ch-- == 0) {
869                 if(fdc_2HD != NULL) {
870                         fdc_2HD->get_context_noise_seek()->set_volume(0, decibel_l, decibel_r);
871                         fdc_2HD->get_context_noise_head_down()->set_volume(0, decibel_l, decibel_r);
872                         fdc_2HD->get_context_noise_head_up()->set_volume(0, decibel_l, decibel_r);
873                 }
874         } 
875 #endif
876         else if(ch-- == 0) {
877                 if(drec != NULL) {
878                         drec->get_context_noise_play()->set_volume(0, decibel_l, decibel_r);
879                         drec->get_context_noise_stop()->set_volume(0, decibel_l, decibel_r);
880                         drec->get_context_noise_fast()->set_volume(0, decibel_l, decibel_r);
881                 }
882         }
883 }
884 #endif
885
886 // ----------------------------------------------------------------------------
887 // notify key
888 // ----------------------------------------------------------------------------
889
890 void VM::key_down(int code, bool repeat)
891 {
892         if(!repeat) {
893                 keyboard->key_down(code);
894         }
895 }
896
897 void VM::key_up(int code)
898 {
899         keyboard->key_up(code);
900 }
901
902 bool VM::get_caps_locked()
903 {
904         return keyboard->get_caps_locked();
905 }
906
907 bool VM::get_kana_locked()
908 {
909         return keyboard->get_kana_locked();
910 }
911
912 // Get INS status.Important with FM-7 series (^_^;
913 uint32_t VM::get_extra_leds()
914 {
915         return keyboard->read_signal(SIG_FM7KEY_LED_STATUS);
916 }
917
918
919 // ----------------------------------------------------------------------------
920 // user interface
921 // ----------------------------------------------------------------------------
922
923 void VM::open_floppy_disk(int drv, const _TCHAR* file_path, int bank)
924 {
925         if(drv < 0) return;
926 #if defined(HAS_2HD)
927         if(drv < 2) {
928                 if(fdc != NULL) {
929                         fdc->open_disk(drv, file_path, bank);
930                 }
931         } else {
932                 if(fdc_2HD != NULL) {
933                         fdc_2HD->open_disk(drv - 2, file_path, bank);
934                 }
935         }
936 #else
937         if(fdc != NULL) {
938                 fdc->open_disk(drv, file_path, bank);
939         }
940 #endif
941 }
942
943 void VM::close_floppy_disk(int drv)
944 {
945 #if defined(HAS_2HD)
946         if(drv < 2) {
947                 if(fdc != NULL) fdc->close_disk(drv);
948         } else {
949                 if(fdc_2HD != NULL) fdc_2HD->close_disk(drv - 2);
950         }               
951 #else
952         if(fdc != NULL) {
953                 fdc->close_disk(drv);
954         }
955 #endif
956 }
957
958 bool VM::is_floppy_disk_inserted(int drv)
959 {
960 #if defined(HAS_2HD)
961         if((fdc != NULL) && (drv < 2)) {
962                 return fdc->is_disk_inserted(drv);
963         } else if(fdc_2HD != NULL) {
964                 return fdc_2HD->is_disk_inserted(drv - 2);
965         } else {
966                 return false;
967         }
968 #else
969         if(fdc != NULL) {
970                 return fdc->is_disk_inserted(drv);
971         } else {
972                 return false;
973         }
974 #endif
975 }
976
977 void VM::is_floppy_disk_protected(int drv, bool value)
978 {
979 #if defined(HAS_2HD)
980         if((fdc != NULL) && (drv < 2)) {
981                 fdc->is_disk_protected(drv, value);
982         } else if(fdc_2HD != NULL) {
983                 fdc_2HD->is_disk_protected(drv - 2, value);
984         }               
985 #else
986         if(fdc != NULL) {
987                 fdc->is_disk_protected(drv, value);
988         }
989 #endif
990 }
991
992 bool VM::is_floppy_disk_protected(int drv)
993 {
994 #if defined(HAS_2HD)
995         if((fdc != NULL) && (drv < 2)) {
996                 return fdc->is_disk_protected(drv);
997         } else if(fdc_2HD != NULL) {
998                 return fdc_2HD->is_disk_protected(drv);
999         } else {
1000                 return false;
1001         }
1002 #else
1003         if(fdc != NULL) {
1004                 return fdc->is_disk_protected(drv);
1005         } else {
1006                 return false;
1007         }
1008 #endif
1009 }
1010
1011 uint32_t VM::is_floppy_disk_accessed()
1012 {
1013         uint32_t v = 0;
1014 #if defined(HAS_2HD)
1015         uint32_t v1, v2;
1016         v1 = v2 = 0;
1017 # if defined(_FM8) || (_FM7) || (_FMNEW7)
1018         if(connect_320kfdc) {
1019 # endif
1020                 if(fdc != NULL) v1 = fdc->read_signal(0);
1021 # if defined(_FM8) || (_FM7) || (_FMNEW7)
1022         }
1023 # endif
1024         if(connect_1Mfdc) {
1025                 if(fdc_2HD != NULL) v2 = fdc_2HD->read_signal(0);
1026         }
1027         v1 = v1 & 0x03;
1028         v2 = (v2 & 0x03) << 2;
1029         v = v1 | v2;
1030         return v;
1031 #else
1032 # if defined(_FM8) || (_FM7) || (_FMNEW7)
1033         if(connect_320kfdc) {
1034 # endif         
1035                 v = fdc->read_signal(0);
1036 # if defined(_FM8) || (_FM7) || (_FMNEW7)
1037         }
1038 # endif
1039         return v;
1040 #endif
1041 }
1042
1043 void VM::play_tape(int drv, const _TCHAR* file_path)
1044 {
1045         if(drec != NULL) drec->play_tape(file_path);
1046 }
1047
1048 void VM::rec_tape(int drv, const _TCHAR* file_path)
1049 {
1050         if(drec != NULL) drec->rec_tape(file_path);
1051 }
1052
1053 void VM::close_tape(int drv)
1054 {
1055         if(drec != NULL) drec->close_tape();
1056 }
1057
1058 bool VM::is_tape_inserted(int drv)
1059 {
1060         if(drec != NULL) {
1061                 return drec->is_tape_inserted();
1062         }
1063         return false;
1064 }
1065
1066 bool VM::is_tape_playing(int drv)
1067 {
1068         if(drec != NULL) {
1069                 return drec->is_tape_playing();
1070         }
1071         return false;
1072 }
1073
1074 bool VM::is_tape_recording(int drv)
1075 {
1076         if(drec != NULL) {
1077                 return drec->is_tape_recording();
1078         }
1079         return false;
1080 }
1081
1082 int VM::get_tape_position(int drv)
1083 {
1084         if(drec != NULL) {
1085                 return drec->get_tape_position();
1086         }
1087         return 0;
1088 }
1089
1090 const _TCHAR* VM::get_tape_message(int drv)
1091 {
1092         if(drec != NULL) {
1093                 return drec->get_message();
1094         }
1095         return NULL;
1096 }
1097
1098 void VM::push_play(int drv)
1099 {
1100         if(drec != NULL) {
1101                 drec->set_ff_rew(0);
1102                 drec->set_remote(true);
1103         }
1104 }
1105
1106
1107 void VM::push_stop(int drv)
1108 {
1109         if(drec != NULL) {
1110                 drec->set_remote(false);
1111         }
1112 }
1113
1114 void VM::push_fast_forward(int drv)
1115 {
1116         if(drec != NULL) {
1117                 drec->set_ff_rew(1);
1118                 drec->set_remote(true);
1119         }
1120 }
1121
1122 void VM::push_fast_rewind(int drv)
1123 {
1124         if(drec != NULL) {
1125                 drec->set_ff_rew(-1);
1126                 drec->set_remote(true);
1127         }
1128 }
1129
1130 void VM::push_apss_forward(int drv)
1131 {
1132         if(drec != NULL) {
1133                 drec->do_apss(1);
1134         }
1135 }
1136
1137 void VM::push_apss_rewind(int drv)
1138 {
1139         if(drec != NULL) {
1140                 drec->do_apss(-1);
1141         }
1142 }
1143
1144 bool VM::is_frame_skippable()
1145 {
1146         return event->is_frame_skippable();
1147 }
1148
1149 void VM::update_dipswitch()
1150 {
1151 #if defined(WITH_Z80)
1152         if(g_intr_irq != NULL) g_intr_irq->write_signal(SIG_AND_BIT_0, ((config.dipswitch & FM7_DIPSW_Z80_IRQ_ON) != 0) ? 1 : 0, 1);
1153         if(g_intr_firq != NULL) g_intr_firq->write_signal(SIG_AND_BIT_0, ((config.dipswitch & FM7_DIPSW_Z80_FIRQ_ON) != 0) ? 1 : 0, 1);
1154         if(g_nmi != NULL) g_nmi->write_signal(SIG_AND_BIT_0, ((config.dipswitch & FM7_DIPSW_Z80_NMI_ON) != 0) ? 1 : 0, 1);
1155 #endif
1156 }
1157
1158 void VM::set_cpu_clock(DEVICE *cpu, uint32_t clocks) {
1159         event->set_secondary_cpu_clock(cpu, clocks);
1160 }
1161
1162 #if defined(USE_BUBBLE1)
1163 void VM::open_bubble_casette(int drv, const _TCHAR *path, int bank)
1164 {
1165         if((drv >= 2) || (drv < 0)) return;
1166         if(bubble_casette[drv] == NULL) return;
1167         bubble_casette[drv]->open((_TCHAR *)path, bank);
1168 }
1169
1170 void VM::close_bubble_casette(int drv)
1171 {
1172         if((drv >= 2) || (drv < 0)) return;
1173         if(bubble_casette[drv] == NULL) return;
1174         bubble_casette[drv]->close();
1175 }
1176
1177 bool VM::is_bubble_casette_inserted(int drv)
1178 {
1179         if((drv >= 2) || (drv < 0)) return false;
1180         if(bubble_casette[drv] == NULL) return false;
1181         return bubble_casette[drv]->is_bubble_inserted();
1182 }
1183
1184 bool VM::is_bubble_casette_protected(int drv)
1185 {
1186         if((drv >= 2) || (drv < 0)) return false;
1187         if(bubble_casette[drv] == NULL) return false;
1188         return bubble_casette[drv]->is_bubble_protected();
1189 }
1190
1191 void VM::is_bubble_casette_protected(int drv, bool flag)
1192 {
1193         if((drv >= 2) || (drv < 0)) return;
1194         if(bubble_casette[drv] == NULL) return;
1195         bubble_casette[drv]->set_bubble_protect(flag);
1196 }
1197 #endif
1198
1199
1200 #define STATE_VERSION   8
1201 void VM::save_state(FILEIO* state_fio)
1202 {
1203         state_fio->FputUint32_BE(STATE_VERSION);
1204         state_fio->FputBool(connect_320kfdc);
1205         state_fio->FputBool(connect_1Mfdc);
1206         for(DEVICE* device = first_device; device; device = device->next_device) {
1207                 const char *name = typeid(*device).name() + 6; // skip "class "
1208                 int _len = strlen(name);
1209                 if(_len <= 0) _len = 1;
1210                 if(_len >= 128) _len = 128;
1211                 state_fio->FputInt32(_len);
1212                 state_fio->Fwrite(name, _len, 1);
1213                 //printf("SAVE State: DEVID=%d NAME=%s\n", device->this_device_id, name);
1214                 device->save_state(state_fio);
1215         }
1216 }
1217
1218 bool VM::load_state(FILEIO* state_fio)
1219 {
1220         uint32_t version = state_fio->FgetUint32_BE();
1221         if(version != STATE_VERSION) {
1222                 return false;
1223         }
1224         connect_320kfdc = state_fio->FgetBool();
1225         connect_1Mfdc = state_fio->FgetBool();
1226         for(DEVICE* device = first_device; device; device = device->next_device) {
1227                 const char *name = typeid(*device).name() + 6; // skip "class "
1228                 char nr_data[130];
1229                 int _len;
1230                 bool b_stat = false;
1231                 _len = state_fio->FgetInt32();
1232                 if(_len > 0) {
1233                         if(_len >= 128) _len = 128;
1234                         memset(nr_data, 0x00, sizeof(nr_data));
1235                         state_fio->Fread(nr_data, _len, 1);
1236                         int stat = strncmp(name, nr_data, _len);
1237                         if(stat == 0) b_stat = true;
1238                 } 
1239                 if(!b_stat) {
1240                         //printf("Load Error: DEVID=%d NAME=%s\n", device->this_device_id, name);
1241                         return false;
1242                 }
1243                 if(!device->load_state(state_fio)) {
1244                         //printf("Load Error: DEVID=%d\n", device->this_device_id);
1245                         return false;
1246                 }
1247         }
1248         return true;
1249 }
1250
1251 #ifdef USE_DIG_RESOLUTION
1252 void VM::get_screen_resolution(int *w, int *h)
1253 {
1254         switch(display->get_screen_mode()) {
1255         case DISPLAY_MODE_8_200L:
1256         case DISPLAY_MODE_8_200L_TEXT:
1257                 *w = 640;
1258                 *h = 200;
1259                 break;
1260         case DISPLAY_MODE_8_400L:
1261         case DISPLAY_MODE_8_400L_TEXT:
1262                 *w = 640;
1263                 *h = 400;
1264                 break;
1265         case DISPLAY_MODE_4096:
1266         case DISPLAY_MODE_256k:
1267                 *w = 320;
1268                 *h = 200;
1269                 break;
1270         default:
1271                 *w = 640;
1272                 *h = 200;
1273                 break;
1274         }
1275 }
1276 #endif
1277
1278 bool VM::is_screen_changed()
1279 {
1280         bool f = true;
1281 #if defined(USE_MINIMUM_RENDERING)
1282         f = display->screen_update();
1283         display->reset_screen_update();
1284 #endif  
1285         return f;
1286 }