3 * (C) 2015 K.Ohta <whatisthis.sowhat _at_ gmail.com>
5 * Feb 27, 2015 : Initial
10 #include "../../config.h"
11 #include "../device.h"
13 #include "../memory.h"
14 #include "../prnfile.h"
17 #include "../debugger.h"
20 #include "../datarec.h"
23 #include "../mc6809.h"
25 #include "../mb8877.h"
28 #include "../pcm1bit.h"
29 #include "../ym2203.h"
30 #include "../ay_3_891x.h"
35 #if defined(_FM77AV_VARIANTS)
36 #include "mb61vh010.h"
43 #include "../hd46505.h"
47 #include "./bubblecasette.h"
51 #include "./fm8_mainio.h"
53 #include "./fm7_mainio.h"
55 #include "./fm7_mainmem.h"
56 #include "./fm7_display.h"
57 #include "./fm7_keyboard.h"
58 #include "./joystick.h"
60 #include "./kanjirom.h"
61 #if defined(CAPABLE_JCOMMCARD)
62 #include "./jcommcard.h"
66 #if defined(USE_BUBBLE)
67 using FM7::BUBBLECASETTE;
70 #if defined(CAPABLE_JCOMMCARD)
71 using FM7::FM7_JCOMMCARD;
75 using FM7::FM8_MAINIO;
77 using FM7::FM7_MAINIO;
79 using FM7::FM7_MAINMEM;
84 VM::VM(EMU_TEMPLATE* parent_emu): VM_TEMPLATE(parent_emu)
87 first_device = last_device = nullptr;
91 # if defined(_FM77AV_VARIANTS)
92 opn[0] = opn[1] = opn[2] = nullptr;
94 opn[0] = opn[1] = opn[2] = nullptr;
98 for(int i = 0; i < 3; i++) uart[i] = nullptr;
100 dummy = new DEVICE(this, emu); // must be 1st device
101 event = new EVENT(this, emu); // must be 2nd device
103 //dummycpu = new DEVICE(this, emu);
104 maincpu = new MC6809(this, emu);
105 subcpu = new MC6809(this, emu);
106 g_substat_display = new AND(this, emu);
107 g_substat_mainhalt = new AND(this, emu);
111 if((config.dipswitch & FM7_DIPSW_Z80CARD_ON) != 0) {
112 z80cpu = new Z80(this, emu);
113 g_mainstat = new AND(this, emu);
114 g_intr = new OR(this, emu);
116 g_intr_irq = new AND(this, emu);
117 g_intr_firq = new AND(this, emu);
118 g_nmi = new AND(this, emu);
121 g_mainstat = nullptr;
124 g_intr_irq = nullptr;
125 g_intr_firq = nullptr;
129 #if defined(CAPABLE_JCOMMCARD)
130 if((config.dipswitch & FM7_DIPSW_JSUBCARD_ON) != 0) {
131 jsubcpu = new MC6809(this, emu);
132 jcommcard = new FM7_JCOMMCARD(this, emu);
133 g_jsubhalt = new AND(this, emu);
137 g_jsubhalt = nullptr;
140 # if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX) || defined(_FM77AV20) \
141 || defined(_FM77AV20EX) || defined(_FM8)
142 uart[0] = new I8251(this, emu);
144 # if defined(CAPABLE_JCOMMCARD)
145 if((config.dipswitch & FM7_DIPSW_JSUBCARD_ON) != 0) uart[0] = new I8251(this, emu);
147 if(((config.dipswitch & FM7_DIPSW_RS232C_ON) != 0) && (uart[0] == nullptr)) uart[0] = new I8251(this, emu);
149 if((config.dipswitch & FM7_DIPSW_MODEM_ON) != 0) uart[1] = new I8251(this, emu);
150 if((config.dipswitch & FM7_DIPSW_MIDI_ON) != 0) uart[2] = new I8251(this, emu);
154 #if defined(_FM77AV_VARIANTS)
155 alu = new MB61VH010(this, emu);
156 keyboard_beep = new BEEP(this, emu);
158 // keyboard_beep->set_context_debugger(new DEBUGGER(this, emu));
165 # if defined(USE_AY_3_8910_AS_PSG)
166 psg = new AY_3_891X(this, emu);
168 psg = new YM2203(this, emu);
171 psg->set_context_debugger(new DEBUGGER(this, emu));
174 opn[0] = new YM2203(this, emu); // OPN
175 opn[1] = new YM2203(this, emu); // WHG
176 opn[2] = new YM2203(this, emu); // THG
178 opn[0]->set_context_debugger(new DEBUGGER(this, emu));
179 opn[1]->set_context_debugger(new DEBUGGER(this, emu));
180 opn[2]->set_context_debugger(new DEBUGGER(this, emu));
182 # if !defined(_FM77AV_VARIANTS)
183 # if defined(USE_AY_3_8910_AS_PSG)
184 psg = new AY_3_891X(this, emu);
186 psg = new YM2203(this, emu);
189 psg->set_context_debugger(new DEBUGGER(this, emu));
195 dmac = new HD6844(this, emu);
198 for(int i = 0; i < 2; i++) bubble_casette[i] = new BUBBLECASETTE(this, emu);
201 drec = new DATAREC(this, emu);
202 drec->set_context_noise_play(new NOISE(this, emu));
203 drec->set_context_noise_stop(new NOISE(this, emu));
204 drec->set_context_noise_fast(new NOISE(this, emu));
205 pcm1bit = new PCM1BIT(this, emu);
207 // pcm1bit->set_context_debugger(new DEBUGGER(this, emu));
210 connect_320kfdc = connect_1Mfdc = false;
216 #if defined(_FM8) || defined(_FM7) || defined(_FMNEW7)
217 if((config.dipswitch & FM7_DIPSW_CONNECT_320KFDC) != 0) {
218 fdc = new MB8877(this, emu);
219 fdc->set_context_noise_seek(new NOISE(this, emu));
220 fdc->set_context_noise_head_down(new NOISE(this, emu));
221 fdc->set_context_noise_head_up(new NOISE(this, emu));
222 connect_320kfdc = true;
226 fdc = new MB8877(this, emu);
227 fdc->set_context_noise_seek(new NOISE(this, emu));
228 fdc->set_context_noise_head_down(new NOISE(this, emu));
229 fdc->set_context_noise_head_up(new NOISE(this, emu));
230 connect_320kfdc = true;
234 if((config.dipswitch & FM7_DIPSW_CONNECT_1MFDC) != 0) {
235 fdc_2HD = new MB8877(this, emu);
236 fdc_2HD->set_context_noise_seek(new NOISE(this, emu));
237 fdc_2HD->set_context_noise_head_down(new NOISE(this, emu));
238 fdc_2HD->set_context_noise_head_up(new NOISE(this, emu));
239 connect_1Mfdc = true;
243 joystick = new JOYSTICK(this, emu);
244 printer = new PRNFILE(this, emu);
246 l4crtc = new HD46505(this, emu);;
249 #if defined(_FM8) || defined(_FM7) || defined(_FMNEW7)
250 if((config.dipswitch & FM7_DIPSW_CONNECT_KANJIROM) != 0) {
251 kanjiclass1 = new KANJIROM(this, emu, false);
253 kanjiclass1 = nullptr;
256 kanjiclass1 = new KANJIROM(this, emu, false);
258 #ifdef CAPABLE_KANJI_CLASS2
259 kanjiclass2 = new KANJIROM(this, emu, true);
263 keyboard = new KEYBOARD(this, emu);
264 // display = new DISPLAY(this, emu);
266 mainio = new FM8_MAINIO(this, emu);
268 mainio = new FM7_MAINIO(this, emu);
270 mainmem = new FM7_MAINMEM(this, emu);
271 display = new DISPLAY(this, emu);
273 # if defined(_FM77AV20) || defined(_FM77AV40) || defined(_FM77AV20EX) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
274 g_rs232c_dtr = new AND(this, emu);
275 g_rs232c_dtr->set_mask(SIG_AND_BIT_0);
276 g_rs232c_dtr->set_mask(SIG_AND_BIT_1);
281 if(g_mainstat != nullptr) {
282 g_mainstat->set_mask(SIG_AND_BIT_0);
283 g_mainstat->set_mask(SIG_AND_BIT_1);
284 maincpu->set_context_bus_ba(g_mainstat, SIG_AND_BIT_0, 0xffffffff);
285 maincpu->set_context_bus_bs(g_mainstat, SIG_AND_BIT_1, 0xffffffff);
286 g_mainstat->set_context_out(mainio, FM7_MAINIO_RUN_Z80, 0xffffffff);
288 if(z80cpu != nullptr) {
289 z80cpu->set_context_busack(mainio, FM7_MAINIO_RUN_6809, 0xffffffff);
290 mainio->set_context_z80cpu(z80cpu);
294 event->set_device_name(_T("EVENT"));
295 dummy->set_device_name(_T("1st Dummy"));
297 maincpu->set_device_name(_T("MAINCPU(MC6809B)"));
298 subcpu->set_device_name(_T("SUBCPU(MC6809B)"));
299 #if defined(CAPABLE_JCOMMCARD)
300 if(jsubcpu != nullptr) {
301 jsubcpu->set_device_name(_T("J.COMM BOARD CPU(MC6809)"));
303 if(jcommcard != nullptr) {
304 jcommcard->set_device_name(_T("Japanese COMM BOARD"));
306 if(g_jsubhalt != nullptr) {
307 g_jsubhalt->set_device_name(_T("J.COMM BOARD HALT(MC6809)"));
311 if(z80cpu != nullptr) z80cpu->set_device_name(_T("Z80 CPU BOARD"));
313 if(fdc != nullptr) fdc->set_device_name(_T("MB8877 FDC(320KB)"));
315 if(fdc_2HD != nullptr) fdc_2HD->set_device_name(_T("MB8877 FDC(1MB/2HD)"));
317 if(uart[0] != nullptr) {
318 uart[0]->set_device_name(_T("RS-232C BOARD(I8251 SIO)"));
320 #if defined(CAPABLE_JCOMMCARD)
321 if((config.dipswitch & FM7_DIPSW_JSUBCARD_ON) != 0) {
322 if(uart[0] != nullptr) uart[0]->set_device_name(_T("J.COMM BOARD RS-232C(I8251 SIO)"));
324 #elif defined(_FM77AV20) || defined(_FM77AV40) || defined(_FM77AV20EX) || \
325 defined(_FM77AV40EX) || defined(_FM77AV40SX) || defined(_FM8)
326 if(uart[0] != nullptr) uart[0]->set_device_name(_T("RS-232C(I8251 SIO)"));
329 if(uart[1] != nullptr) {
330 uart[1]->set_device_name(_T("MODEM BOARD(I8251 SIO)"));
332 if(uart[2] != nullptr) {
333 uart[2]->set_device_name(_T("MIDI BOARD(I8251 SIO)"));
339 psg->set_device_name(_T("AY-3-8910 PSG"));
341 opn[0]->set_device_name(_T("YM2203 OPN"));
342 opn[1]->set_device_name(_T("YM2203 WHG"));
343 opn[2]->set_device_name(_T("YM2203 THG"));
344 #if !defined(_FM77AV_VARIANTS)
345 psg->set_device_name(_T("AY-3-8910 PSG"));
347 pcm1bit->set_device_name(_T("BEEP"));
348 printer->set_device_name(_T("PRINTER I/F"));
349 #if defined(_FM77AV_VARIANTS)
350 keyboard_beep->set_device_name(_T("BEEP(KEYBOARD)"));
352 if(kanjiclass1 != nullptr) kanjiclass1->set_device_name(_T("KANJI ROM CLASS1"));
353 #ifdef CAPABLE_KANJI_CLASS2
354 if(kanjiclass2 != nullptr) kanjiclass2->set_device_name(_T("KANJI ROM CLASS2"));
357 bubble_casette[0]->set_device_name(_T("BUBBLE CASETTE #0"));
358 bubble_casette[1]->set_device_name(_T("BUBBLE CASETTE #1"));
361 # if defined(_FM77AV20) || defined(_FM77AV40) || defined(_FM77AV20EX) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
362 g_rs232c_dtr->set_device_name(_T("RS232C DTR(AND)"));
365 l4crtc->set_device_name(_T("CRTC OF 400LINES BOARD"));
368 if(g_intr != nullptr) g_intr->set_device_name(_T("Z80 INTR(OR)"));
369 if(g_mainstat != nullptr) g_mainstat->set_device_name(_T("Z80 HALT/RUN(AND)"));
370 if(g_intr_irq != nullptr) g_intr_irq->set_device_name(_T("Z80 IRQ(AND)"));
371 if(g_intr_firq != nullptr) g_intr_firq->set_device_name(_T("Z80 FIRQ(AND)"));
372 if(g_nmi != nullptr) g_nmi->set_device_name(_T("Z80 NMI(AND)"));
374 g_substat_display->set_device_name(_T("DISPLAY STATUS(AND)"));
375 g_substat_mainhalt->set_device_name(_T("SUBSYSTEM HALT STATUS(AND)"));
382 // delete all devices
386 void VM::connect_bus(void)
395 * |-> MAINCPU -> MAINMEM -> MAINIO -> MAIN DEVICES
397 * | -> SUBCPU -> SUBMEM -> SUBIO -> SUB DEVICES
401 * MAINMEM can access SUBMEM/IO, when SUBCPU is halted.
402 * MAINMEM and SUBMEM can access DISPLAY and KEYBOARD with exclusive.
403 * MAINCPU can access MAINMEM.
404 * SUBCPU can access SUBMEM.
405 * DISPLAY : R/W from MAINCPU and SUBCPU.
409 event->set_frames_per_sec(FRAMES_PER_SEC);
410 event->set_lines_per_frame(LINES_PER_FRAME);
411 mainclock = CPU_CLOCKS; // Hack
412 subclock = SUBCLOCK_NORMAL;
414 event->set_context_cpu(maincpu, mainclock);
415 event->set_context_cpu(subcpu, subclock);
418 if(z80cpu != nullptr) {
419 event->set_context_cpu(z80cpu, 4000000);
420 z80cpu->write_signal(SIG_CPU_BUSREQ, 1, 1);
422 g_intr_irq->set_mask(SIG_AND_BIT_0);
423 g_intr_irq->set_mask(SIG_AND_BIT_1);
425 g_intr_firq->set_mask(SIG_AND_BIT_0);
426 g_intr_firq->set_mask(SIG_AND_BIT_1);
428 g_nmi->set_mask(SIG_AND_BIT_0);
429 g_nmi->set_mask(SIG_AND_BIT_1);
431 mainio->set_context_irq(g_intr_irq, SIG_AND_BIT_1, 0xffffffff);
432 g_intr_irq->set_context_out(g_intr, SIG_OR_BIT_0, 0xffffffff);
434 mainio->set_context_firq(g_intr_firq, SIG_AND_BIT_1, 0xffffffff);
435 g_intr_firq->set_context_out(g_intr, SIG_OR_BIT_0, 0xffffffff);
437 g_intr->set_context_out(z80cpu, SIG_CPU_IRQ, 0xffffffff);
439 mainio->set_context_nmi(g_nmi, SIG_AND_BIT_1, 0xffffffff);
440 g_nmi->set_context_out(z80cpu, SIG_CPU_NMI, 0xffffffff);
442 maincpu->write_signal(SIG_CPU_HALTREQ, 0, 1);
444 #if defined(CAPABLE_JCOMMCARD)
445 if((jsubcpu != nullptr) && (jcommcard != nullptr)) {
446 event->set_context_cpu(jsubcpu, JCOMMCARD_CLOCK);
447 jcommcard->set_context_cpu(jsubcpu);
448 if(g_jsubhalt != nullptr) {
449 g_jsubhalt->set_mask(SIG_AND_BIT_0);
450 g_jsubhalt->set_mask(SIG_AND_BIT_1);
452 jsubcpu->set_context_bus_ba(g_jsubhalt, SIG_AND_BIT_0, 0xffffffff);
453 jsubcpu->set_context_bus_bs(g_jsubhalt, SIG_AND_BIT_1, 0xffffffff);
454 g_jsubhalt->set_context_out(jcommcard, FM7_JCOMMCARD_BUS_HALT, 0xffffffff);
455 mainio->set_context_jcommcard(jcommcard);
459 event->set_context_sound(pcm1bit);
461 event->set_context_sound(psg);
462 if(drec != nullptr) event->set_context_sound(drec);
464 event->set_context_sound(opn[0]);
465 event->set_context_sound(opn[1]);
466 event->set_context_sound(opn[2]);
467 #if !defined(_FM77AV_VARIANTS)
468 event->set_context_sound(psg);
470 event->set_context_sound(drec);
472 event->set_context_sound(fdc->get_context_noise_seek());
473 event->set_context_sound(fdc->get_context_noise_head_down());
474 event->set_context_sound(fdc->get_context_noise_head_up());
477 if(fdc_2HD != nullptr) {
478 event->set_context_sound(fdc_2HD->get_context_noise_seek());
479 event->set_context_sound(fdc_2HD->get_context_noise_head_down());
480 event->set_context_sound(fdc_2HD->get_context_noise_head_up());
483 if(drec != nullptr) {
484 event->set_context_sound(drec->get_context_noise_play());
485 event->set_context_sound(drec->get_context_noise_stop());
486 event->set_context_sound(drec->get_context_noise_fast());
488 #if defined(_FM77AV_VARIANTS)
489 event->set_context_sound(keyboard_beep);
492 #if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
493 //event->register_vline_event(display);
494 //event->register_frame_event(display);
496 mainio->set_context_maincpu(maincpu);
497 mainio->set_context_subcpu(subcpu);
499 mainio->set_context_display(display);
500 mainio->set_context_irq(maincpu, SIG_CPU_IRQ, 0xffffffff);
501 mainio->set_context_firq(maincpu, SIG_CPU_FIRQ, 0xffffffff);
502 mainio->set_context_nmi(maincpu, SIG_CPU_NMI, 0xffffffff);
503 #if defined(_FM77AV) || defined(_FM7) || defined(_FMNEW7) || defined(_FM77_VARIANTS)
504 if((config.dipswitch & FM7_DIPSW_RS232C_ON) != 0) mainio->set_context_uart(0, uart[0]); /* $FD06- : RS232C */
506 mainio->set_context_uart(0, uart[0]);
508 mainio->set_context_uart(1, uart[1]); /* $FD40- : MODEM */
509 mainio->set_context_uart(2, uart[2]); /* $FDEA- : MIDI */
511 #if defined(_FM77AV20) || defined(_FM77AV40) || defined(_FM77AV20EX) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
512 mainio->set_context_rs232c_dtr(g_rs232c_dtr);
513 if(uart[0] != nullptr) uart[0]->set_context_dtr(g_rs232c_dtr, SIG_AND_BIT_1, 0xffffffff);
515 if(uart[0] != nullptr) {
516 uart[0]->set_context_rxrdy(mainio, FM7_MAINIO_UART0_RXRDY, 0xffffffff);
517 uart[0]->set_context_txrdy(mainio, FM7_MAINIO_UART0_TXRDY, 0xffffffff);
518 uart[0]->set_context_syndet(mainio, FM7_MAINIO_UART0_SYNDET, 0xffffffff);
520 if(uart[1] != nullptr) {
521 uart[1]->set_context_rxrdy(mainio, FM7_MAINIO_MODEM_RXRDY, 0xffffffff);
522 uart[1]->set_context_txrdy(mainio, FM7_MAINIO_MODEM_TXRDY, 0xffffffff);
523 uart[1]->set_context_syndet(mainio, FM7_MAINIO_MODEM_SYNDET, 0xffffffff);
525 if(uart[2] != nullptr) {
526 uart[2]->set_context_rxrdy(mainio, FM7_MAINIO_MIDI_RXRDY, 0xffffffff);
527 uart[2]->set_context_txrdy(mainio, FM7_MAINIO_MIDI_TXRDY, 0xffffffff);
528 uart[2]->set_context_syndet(mainio, FM7_MAINIO_MIDI_SYNDET, 0xffffffff);
531 #if defined(_FM8) || defined(_FM7) || defined(_FMNEW7)
532 if((config.dipswitch & FM7_DIPSW_CONNECT_KANJIROM) != 0) {
533 mainio->set_context_kanjirom_class1(kanjiclass1);
536 mainio->set_context_kanjirom_class1(kanjiclass1);
538 mainio->set_context_mainmem(mainmem);
539 mainio->set_context_keyboard(keyboard);
540 mainio->set_context_printer(printer);
541 mainio->set_context_printer_reset(printer, SIG_PRINTER_RESET, 0xffffffff);
542 mainio->set_context_printer_strobe(printer, SIG_PRINTER_STROBE, 0xffffffff);
543 mainio->set_context_printer_select(printer, SIG_PRINTER_SELECT, 0xffffffff);
544 #if defined(CAPABLE_KANJI_CLASS2)
545 mainio->set_context_kanjirom_class2(kanjiclass2);
548 for(int i = 0; i < 2; i++) mainio->set_context_bubble(bubble_casette[i], i);
550 keyboard->set_context_break_line(mainio, FM7_MAINIO_PUSH_BREAK, 0xffffffff);
551 keyboard->set_context_int_line(mainio, FM7_MAINIO_KEYBOARDIRQ, 0xffffffff);
552 keyboard->set_context_int_line(display, SIG_FM7_SUB_KEY_FIRQ, 0xffffffff);
553 #if defined(_FM77AV_VARIANTS)
554 keyboard->set_context_beep(keyboard_beep);
556 keyboard->set_context_rxrdy(display, SIG_FM7KEY_RXRDY, 0x01);
557 keyboard->set_context_key_ack(display, SIG_FM7KEY_ACK, 0x01);
559 if(drec != nullptr) {
560 drec->set_context_ear(mainio, FM7_MAINIO_CMT_RECV, 0xffffffff);
561 //drec->set_context_remote(mainio, FM7_MAINIO_CMT_REMOTE, 0xffffffff);
562 mainio->set_context_datarec(drec);
564 mainmem->set_context_mainio(mainio);
565 mainmem->set_context_display(display);
566 mainmem->set_context_maincpu(maincpu);
567 #if defined(CAPABLE_DICTROM)
568 mainmem->set_context_kanjirom_class1(kanjiclass1);
570 display->set_context_mainio(mainio);
571 display->set_context_subcpu(subcpu);
572 display->set_context_keyboard(keyboard);
574 display->set_context_l4crtc(l4crtc);
577 mainio->set_context_clock_status(mainmem, FM7_MAINIO_CLOCKMODE, 0xffffffff);
578 mainio->set_context_clock_status(display, SIG_DISPLAY_CLOCK, 0xffffffff);
580 g_substat_display->set_mask(SIG_AND_BIT_0);
581 g_substat_display->set_mask(SIG_AND_BIT_1);
582 subcpu->set_context_bus_ba(g_substat_display, SIG_AND_BIT_0, 0xffffffff);
583 subcpu->set_context_bus_bs(g_substat_display, SIG_AND_BIT_1, 0xffffffff);
584 g_substat_display->set_context_out(display, SIG_FM7_SUB_HALT, 0xffffffff);
586 g_substat_mainhalt->set_mask(SIG_AND_BIT_0);
587 g_substat_mainhalt->set_mask(SIG_AND_BIT_1);
588 subcpu->set_context_bus_ba(g_substat_mainhalt, SIG_AND_BIT_0, 0xffffffff);
589 subcpu->set_context_bus_bs(g_substat_mainhalt, SIG_AND_BIT_1, 0xffffffff);
590 g_substat_mainhalt->set_context_out(mainmem, SIG_FM7_SUB_HALT, 0xffffffff);
592 #if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
593 display->set_context_kanjiclass1(kanjiclass1);
595 #if defined(CAPABLE_KANJI_CLASS2)
596 display->set_context_kanjiclass2(kanjiclass2);
598 #if defined(_FM77AV_VARIANTS)
599 display->set_context_alu(alu);
600 alu->set_context_memory(display);
601 alu->set_direct_access_offset(DISPLAY_VRAM_DIRECT_ACCESS);
603 // Palette, VSYNC, HSYNC, Multi-page, display mode.
604 mainio->set_context_display(display);
606 #if defined(_FM8) || (_FM7) || (_FMNEW7)
607 if(connect_320kfdc) {
611 fdc->set_context_irq(mainio, FM7_MAINIO_FDC_IRQ, 0x1);
612 fdc->set_context_drq(mainio, FM7_MAINIO_FDC_DRQ, 0x1);
613 fdc->set_context_rdy(mainio, SIG_FM7_MAINIO_FDC_MOTOR, 0xffffffff); // OK?
614 mainio->set_context_fdc(fdc);
616 #if defined(_FM8) || (_FM7) || (_FMNEW7)
620 if(connect_1Mfdc && (fdc_2HD != nullptr)) {
622 fdc_2HD->set_context_irq(mainio, FM7_MAINIO_FDC_IRQ_2HD, 0x1);
623 fdc_2HD->set_context_drq(mainio, FM7_MAINIO_FDC_DRQ_2HD, 0x1);
624 fdc_2HD->set_context_rdy(mainio, SIG_FM7_MAINIO_FDC_MOTOR_2HD, 0xffffffff);
625 mainio->set_context_fdc_2HD(fdc_2HD);
629 mainio->set_context_beep(pcm1bit);
631 mainio->set_context_psg(psg);
633 #if !defined(_FM77AV_VARIANTS)
634 mainio->set_context_psg(psg);
636 opn[0]->set_context_irq(mainio, FM7_MAINIO_OPN_IRQ, 0xffffffff);
637 mainio->set_context_opn(opn[0], 0);
638 joystick->set_context_opn(opn[0]);
639 mainio->set_context_joystick(joystick);
640 opn[0]->set_context_port_b(joystick, FM7_JOYSTICK_MOUSE_STROBE, 0xff, 0);
642 opn[1]->set_context_irq(mainio, FM7_MAINIO_WHG_IRQ, 0xffffffff);
643 mainio->set_context_opn(opn[1], 1);
644 opn[2]->set_context_irq(mainio, FM7_MAINIO_THG_IRQ, 0xffffffff);
645 mainio->set_context_opn(opn[2], 2);
647 //subcpu->set_context_bus_clr(display, SIG_FM7_SUB_USE_CLR, 0x0000000f);
649 event->register_frame_event(joystick);
651 dmac->set_context_src(fdc, 0);
652 dmac->set_context_dst(mainmem, 0);
653 dmac->set_context_int_line(mainio, FM7_MAINIO_DMA_INT, 0xffffffff);
654 dmac->set_context_busreq_line(maincpu, 1, SIG_CPU_BUSREQ, 0xffffffff);
655 mainio->set_context_dmac(dmac);
658 // MEMORIES must set before initialize().
659 //dummycpu->set_context_mem(dummy);
660 maincpu->set_context_mem(mainmem);
661 subcpu->set_context_mem(display);
662 //dummycpu->write_signal(SIG_CPU_BUSREQ, 1, 1);
664 if(z80cpu != nullptr) z80cpu->set_context_mem(mainmem);
666 #if defined(CAPABLE_JCOMMCARD)
667 if((jsubcpu != nullptr) && (jcommcard != nullptr)) {
668 jsubcpu->set_context_mem(jcommcard);
672 maincpu->set_context_debugger(new DEBUGGER(this, emu));
673 subcpu->set_context_debugger(new DEBUGGER(this, emu));
675 if(z80cpu != nullptr) z80cpu->set_context_debugger(new DEBUGGER(this, emu));
677 #if defined(CAPABLE_JCOMMCARD)
678 if(jsubcpu != nullptr) {
679 jsubcpu->set_context_debugger(new DEBUGGER(this, emu));
683 #if defined(__GIT_REPO_VERSION)
684 set_git_repo_version(__GIT_REPO_VERSION);
686 initialize_devices();
688 #if defined(WITH_Z80)
689 if(g_intr_irq != nullptr) g_intr_irq->write_signal(SIG_AND_BIT_0, ((config.dipswitch & FM7_DIPSW_Z80_IRQ_ON) != 0) ? 1 : 0, 1);
690 if(g_intr_firq != nullptr) g_intr_firq->write_signal(SIG_AND_BIT_0, ((config.dipswitch & FM7_DIPSW_Z80_FIRQ_ON) != 0) ? 1 : 0, 1);
691 if(g_nmi != nullptr) g_nmi->write_signal(SIG_AND_BIT_0, ((config.dipswitch & FM7_DIPSW_Z80_NMI_ON) != 0) ? 1 : 0, 1);
694 #if defined(_FM8) || (_FM7) || (_FMNEW7)
695 if(connect_320kfdc) {
698 for(int i = 0; i < 4; i++) {
699 #if defined(_FM77AV20) || defined(_FM77AV20EX) || \
700 defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
701 fdc->set_drive_type(i, DRIVE_TYPE_2DD);
703 fdc->set_drive_type(i, DRIVE_TYPE_2D);
705 fdc->set_drive_mfm(i, true);
706 fdc->set_drive_rpm(i, 300);
709 #if defined(_FM8) || (_FM7) || (_FMNEW7)
714 if(connect_1Mfdc && (fdc_2HD != nullptr)) {
715 // 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.
716 for(int i = 0; i < 2; i++) {
717 fdc_2HD->set_drive_type(i, DRIVE_TYPE_2HD);
718 fdc_2HD->set_drive_mfm(i, true);
719 fdc_2HD->set_drive_rpm(i, 300);
725 void VM::update_config()
727 VM_TEMPLATE::update_config();
734 VM_TEMPLATE::reset();
736 #if !defined(_FM77AV_VARIANTS) || defined(_FM8)
737 #if defined(USE_AY_3_8910_AS_PSG)
738 psg->set_reg(0x27, 0); // set prescaler
739 psg->set_reg(0x2e, 0); // set prescaler
740 psg->write_signal(SIG_AY_3_891X_MUTE, 0x00, 0x01); // Okay?
742 psg->set_reg(0x27, 0); // stop timer
743 psg->set_reg(0x2e, 0); // set prescaler
744 psg->write_signal(SIG_YM2203_MUTE, 0x00, 0x01); // Okay?
748 for(int i = 0; i < 3; i++) {
749 opn[i]->set_reg(0x27, 0); // stop timer
750 opn[i]->set_reg(0x2e, 0); // set prescaler
751 opn[i]->write_signal(SIG_YM2203_MUTE, 0x00, 0x01); // Okay?
754 //display->reset(); // 20180618 K.O for RELICS
757 void VM::special_reset(int num)
762 //mainio->write_signal(FM7_MAINIO_PUSH_BREAK, 1, 1);
763 //keyboard->write_signal(SIG_FM7KEY_OVERRIDE_PRESS_BREAK, 0xffffffff, 0xffffffff);
765 #if defined(FM77AV_VARIANTS)
766 mainio->write_signal(FM7_MAINIO_HOT_RESET, 1, 1);
771 mainio->write_signal(FM7_MAINIO_PUSH_BREAK, 1, 1);
772 keyboard->write_signal(SIG_FM7KEY_OVERRIDE_PRESS_BREAK, 0xffffffff, 0xffffffff);
773 event->register_event(mainio, EVENT_UP_BREAK, 1000.0 * 1000.0, false, nullptr);
778 __LIKELY_IF(event != nullptr) {
783 double VM::get_frame_rate()
785 __LIKELY_IF(event != nullptr) {
786 return event->get_frame_rate();
788 return VM_TEMPLATE::get_frame_rate();
791 void VM::set_vm_frame_rate(double fps)
793 __LIKELY_IF(event != nullptr) {
794 event->set_frames_per_sec(fps);
798 double VM::get_current_usec()
800 __LIKELY_IF(event != nullptr) {
801 return event->get_current_usec();
803 return VM_TEMPLATE::get_current_usec();
806 uint64_t VM::get_current_clock_uint64()
808 __LIKELY_IF(event != nullptr) {
809 return event->get_current_clock_uint64();
811 return VM_TEMPLATE::get_current_clock_uint64();
816 // ----------------------------------------------------------------------------
818 // ----------------------------------------------------------------------------
821 DEVICE *VM::get_cpu(int index)
825 } else if(index == 1) {
828 #if defined(WITH_Z80)
829 else if(index == 2) {
830 #if defined(CAPABLE_JCOMMCARD)
831 if(z80cpu == nullptr) {
837 #if defined(CAPABLE_JCOMMCARD)
838 else if(index == 3) {
843 #if defined(CAPABLE_JCOMMCARD)
844 else if(index == 2) {
853 // ----------------------------------------------------------------------------
855 // ----------------------------------------------------------------------------
857 void VM::draw_screen()
859 __UNLIKELY_IF(display == nullptr) return;
860 display->draw_screen();
863 void VM::initialize_sound(int rate, int samples)
865 // init sound manager
866 if(event != nullptr) {
867 event->initialize_sound(rate, samples);
872 psg->initialize_sound(rate, (int)(4.9152 * 1000.0 * 1000.0 / 4.0), samples, 0, 0);
875 if(opn[0] != nullptr) {
876 opn[0]->initialize_sound(rate, (int)(4.9152 * 1000.0 * 1000.0 / 4.0), samples, 0, 0);
878 if(opn[1] != nullptr) {
879 opn[1]->initialize_sound(rate, (int)(4.9152 * 1000.0 * 1000.0 / 4.0), samples, 0, 0);
881 if(opn[2] != nullptr) {
882 opn[2]->initialize_sound(rate, (int)(4.9152 * 1000.0 * 1000.0 / 4.0), samples, 0, 0);
884 # if !defined(_FM77AV_VARIANTS)
886 psg->initialize_sound(rate, (int)(4.9152 * 1000.0 * 1000.0 / 4.0), samples, 0, 0);
887 #if defined(USE_AY_3_8910_AS_PSG)
888 psg->set_low_pass_filter_freq(4500);
889 psg->set_high_pass_filter_freq(50);
893 #if defined(_FM77AV_VARIANTS)
894 if(keyboard_beep != nullptr) {
895 keyboard_beep->initialize_sound(rate, 2400.0, 512);
899 if(pcm1bit != nullptr) {
900 pcm1bit->initialize_sound(rate, 8000);
901 pcm1bit->set_high_pass_filter_freq(10);
902 pcm1bit->set_low_pass_filter_freq(1500);
904 //drec->initialize_sound(rate, 0);
907 uint16_t* VM::create_sound(int* extra_frames)
909 __LIKELY_IF(event != nullptr) {
910 uint16_t* p = event->create_sound(extra_frames);
913 return VM_TEMPLATE::create_sound(extra_frames);
916 int VM::get_sound_buffer_ptr()
918 __LIKELY_IF(event != nullptr) {
919 int pos = event->get_sound_buffer_ptr();
922 return VM_TEMPLATE::get_sound_buffer_ptr();
925 #ifdef USE_SOUND_VOLUME
926 void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
928 #if !defined(_FM77AV_VARIANTS)
931 psg->set_volume(0, decibel_l, decibel_r);
932 psg->set_volume(1, decibel_l, decibel_r);
938 if(opn[0] != nullptr) {
939 opn[0]->set_volume(0, decibel_l, decibel_r);
941 } else if(ch-- == 0) {
942 if(opn[0] != nullptr) {
943 opn[0]->set_volume(1, decibel_l, decibel_r);
945 } else if(ch-- == 0) {
946 if(opn[1] != nullptr) {
947 opn[1]->set_volume(0, decibel_l, decibel_r);
949 } else if(ch-- == 0) {
950 if(opn[1] != nullptr) {
951 opn[1]->set_volume(1, decibel_l, decibel_r);
953 } else if(ch-- == 0) {
954 if(opn[2] != nullptr) {
955 opn[2]->set_volume(0, decibel_l, decibel_r);
957 } else if(ch-- == 0) {
958 if(opn[2] != nullptr) {
959 opn[2]->set_volume(1, decibel_l, decibel_r);
964 if(pcm1bit != nullptr) {
965 pcm1bit->set_volume(0, decibel_l, decibel_r);
967 } else if(ch-- == 0) {
968 if(drec != nullptr) {
969 drec->set_volume(0, decibel_l, decibel_r);
972 #if defined(_FM77AV_VARIANTS)
974 if(keyboard_beep != nullptr) {
975 keyboard_beep->set_volume(0, decibel_l, decibel_r);
981 fdc->get_context_noise_seek()->set_volume(0, decibel_l, decibel_r);
982 fdc->get_context_noise_head_down()->set_volume(0, decibel_l, decibel_r);
983 fdc->get_context_noise_head_up()->set_volume(0, decibel_l, decibel_r);
988 if(fdc_2HD != nullptr) {
989 fdc_2HD->get_context_noise_seek()->set_volume(0, decibel_l, decibel_r);
990 fdc_2HD->get_context_noise_head_down()->set_volume(0, decibel_l, decibel_r);
991 fdc_2HD->get_context_noise_head_up()->set_volume(0, decibel_l, decibel_r);
996 if(drec != nullptr) {
997 drec->get_context_noise_play()->set_volume(0, decibel_l, decibel_r);
998 drec->get_context_noise_stop()->set_volume(0, decibel_l, decibel_r);
999 drec->get_context_noise_fast()->set_volume(0, decibel_l, decibel_r);
1005 // ----------------------------------------------------------------------------
1007 // ----------------------------------------------------------------------------
1009 void VM::key_down(int code, bool repeat)
1011 __UNLIKELY_IF(keyboard == nullptr) return;
1013 keyboard->key_down(code);
1017 void VM::key_up(int code)
1019 __UNLIKELY_IF(keyboard == nullptr) return;
1020 keyboard->key_up(code);
1023 bool VM::get_caps_locked()
1025 __UNLIKELY_IF(keyboard == nullptr) return false;
1026 return keyboard->get_caps_locked();
1029 bool VM::get_kana_locked()
1031 __UNLIKELY_IF(keyboard == nullptr) return false;
1032 return keyboard->get_kana_locked();
1035 // Get INS status.Important with FM-7 series (^_^;
1036 uint32_t VM::get_led_status()
1038 __UNLIKELY_IF(keyboard == nullptr) return 0;
1039 return keyboard->read_signal(SIG_FM7KEY_LED_STATUS);
1043 // ----------------------------------------------------------------------------
1045 // ----------------------------------------------------------------------------
1047 void VM::open_floppy_disk(int drv, const _TCHAR* file_path, int bank)
1050 #if defined(HAS_2HD)
1052 if(fdc != nullptr) {
1053 fdc->open_disk(drv, file_path, bank);
1056 if(fdc_2HD != nullptr) {
1057 fdc_2HD->open_disk(drv - 2, file_path, bank);
1061 if(fdc != nullptr) {
1062 fdc->open_disk(drv, file_path, bank);
1065 //display->reset(); // 20180618 K.O for RELICS
1068 void VM::close_floppy_disk(int drv)
1070 #if defined(HAS_2HD)
1072 if(fdc != nullptr) fdc->close_disk(drv);
1074 if(fdc_2HD != nullptr) fdc_2HD->close_disk(drv - 2);
1077 if(fdc != nullptr) {
1078 fdc->close_disk(drv);
1083 bool VM::is_floppy_disk_inserted(int drv)
1085 #if defined(HAS_2HD)
1086 if((fdc != nullptr) && (drv < 2)) {
1087 return fdc->is_disk_inserted(drv);
1088 } else if(fdc_2HD != nullptr) {
1089 return fdc_2HD->is_disk_inserted(drv - 2);
1094 if(fdc != nullptr) {
1095 return fdc->is_disk_inserted(drv);
1102 void VM::is_floppy_disk_protected(int drv, bool value)
1104 #if defined(HAS_2HD)
1105 if((fdc != nullptr) && (drv < 2)) {
1106 fdc->is_disk_protected(drv, value);
1107 } else if(fdc_2HD != nullptr) {
1108 fdc_2HD->is_disk_protected(drv - 2, value);
1111 if(fdc != nullptr) {
1112 fdc->is_disk_protected(drv, value);
1117 bool VM::is_floppy_disk_protected(int drv)
1119 #if defined(HAS_2HD)
1120 if((fdc != nullptr) && (drv < 2)) {
1121 return fdc->is_disk_protected(drv);
1122 } else if(fdc_2HD != nullptr) {
1123 return fdc_2HD->is_disk_protected(drv);
1128 if(fdc != nullptr) {
1129 return fdc->is_disk_protected(drv);
1136 uint32_t VM::is_floppy_disk_accessed()
1139 #if defined(HAS_2HD)
1142 # if defined(_FM8) || (_FM7) || (_FMNEW7)
1143 if(connect_320kfdc) {
1145 if(fdc != nullptr) v1 = fdc->read_signal(0);
1146 # if defined(_FM8) || (_FM7) || (_FMNEW7)
1150 if(fdc_2HD != nullptr) v2 = fdc_2HD->read_signal(0);
1153 v2 = (v2 & 0x03) << 2;
1157 # if defined(_FM8) || (_FM7) || (_FMNEW7)
1158 if(connect_320kfdc) {
1160 v = fdc->read_signal(0);
1161 # if defined(_FM8) || (_FM7) || (_FMNEW7)
1168 void VM::play_tape(int drv, const _TCHAR* file_path)
1170 if(drec != nullptr) {
1171 bool remote = drec->get_remote();
1173 if(drec->play_tape(file_path) && remote) {
1174 // if machine already sets remote on, start playing now
1180 void VM::rec_tape(int drv, const _TCHAR* file_path)
1182 if(drec != nullptr) {
1183 bool remote = drec->get_remote();
1185 if(drec->rec_tape(file_path) && remote) {
1186 // if machine already sets remote on, start recording now
1192 void VM::close_tape(int drv)
1194 if(drec != nullptr) {
1198 drec->set_remote(false);
1202 bool VM::is_tape_inserted(int drv)
1204 if(drec != nullptr) {
1205 return drec->is_tape_inserted();
1210 bool VM::is_tape_playing(int drv)
1212 if(drec != nullptr) {
1213 return drec->is_tape_playing();
1218 bool VM::is_tape_recording(int drv)
1220 if(drec != nullptr) {
1221 return drec->is_tape_recording();
1226 int VM::get_tape_position(int drv)
1228 __LIKELY_IF(drec != nullptr) {
1229 return drec->get_tape_position();
1234 const _TCHAR* VM::get_tape_message(int drv)
1236 __LIKELY_IF(drec != nullptr) {
1237 return drec->get_message();
1242 void VM::push_play(int drv)
1244 if(drec != nullptr) {
1245 drec->set_remote(false);
1246 drec->set_ff_rew(0);
1247 drec->set_remote(true);
1252 void VM::push_stop(int drv)
1254 if(drec != nullptr) {
1255 drec->set_remote(false);
1259 void VM::push_fast_forward(int drv)
1261 if(drec != nullptr) {
1262 drec->set_remote(false);
1263 drec->set_ff_rew(1);
1264 drec->set_remote(true);
1268 void VM::push_fast_rewind(int drv)
1270 if(drec != nullptr) {
1271 drec->set_remote(false);
1272 drec->set_ff_rew(-1);
1273 drec->set_remote(true);
1277 void VM::push_apss_forward(int drv)
1279 if(drec != nullptr) {
1284 void VM::push_apss_rewind(int drv)
1286 __UNLIKELY_IF(drec != nullptr) {
1291 bool VM::is_frame_skippable()
1293 __UNLIKELY_IF(event == nullptr) {
1296 return event->is_frame_skippable();
1299 void VM::update_dipswitch()
1301 #if defined(WITH_Z80)
1302 if(g_intr_irq != nullptr) g_intr_irq->write_signal(SIG_AND_BIT_0, ((config.dipswitch & FM7_DIPSW_Z80_IRQ_ON) != 0) ? 1 : 0, 1);
1303 if(g_intr_firq != nullptr) g_intr_firq->write_signal(SIG_AND_BIT_0, ((config.dipswitch & FM7_DIPSW_Z80_FIRQ_ON) != 0) ? 1 : 0, 1);
1304 if(g_nmi != nullptr) g_nmi->write_signal(SIG_AND_BIT_0, ((config.dipswitch & FM7_DIPSW_Z80_NMI_ON) != 0) ? 1 : 0, 1);
1308 void VM::set_cpu_clock(DEVICE *cpu, uint32_t clocks)
1310 __LIKELY_IF(event != nullptr) {
1311 event->set_secondary_cpu_clock(cpu, clocks);
1315 #if defined(USE_BUBBLE)
1316 void VM::open_bubble_casette(int drv, const _TCHAR *path, int bank)
1318 __UNLIKELY_IF((drv >= 2) || (drv < 0)) return;
1319 __UNLIKELY_IF(bubble_casette[drv] == nullptr) return;
1320 bubble_casette[drv]->open((_TCHAR *)path, bank);
1323 void VM::close_bubble_casette(int drv)
1325 __UNLIKELY_IF((drv >= 2) || (drv < 0)) return;
1326 __UNLIKELY_IF(bubble_casette[drv] == nullptr) return;
1327 bubble_casette[drv]->close();
1330 bool VM::is_bubble_casette_inserted(int drv)
1332 if((drv >= 2) || (drv < 0)) return false;
1333 if(bubble_casette[drv] == nullptr) return false;
1334 return bubble_casette[drv]->is_bubble_inserted();
1337 bool VM::is_bubble_casette_protected(int drv)
1339 if((drv >= 2) || (drv < 0)) return false;
1340 if(bubble_casette[drv] == nullptr) return false;
1341 return bubble_casette[drv]->is_bubble_protected();
1344 void VM::is_bubble_casette_protected(int drv, bool flag)
1346 if((drv >= 2) || (drv < 0)) return;
1347 if(bubble_casette[drv] == nullptr) return;
1348 bubble_casette[drv]->set_bubble_protect(flag);
1352 #define STATE_VERSION 12
1354 bool VM::process_state(FILEIO* state_fio, bool loading)
1356 if(!(VM_TEMPLATE::process_state_core(state_fio, loading, STATE_VERSION))) {
1359 // Machine specified.
1360 state_fio->StateValue(connect_320kfdc);
1361 state_fio->StateValue(connect_1Mfdc);
1365 //mainio->restore_opn();
1368 #ifdef SUPPORT_QUERY_PHY_KEY_NAME
1369 int VM::get_key_name_table_size(void)
1371 if(keyboard != nullptr) {
1372 return keyboard->get_key_name_table_size();
1376 const _TCHAR *VM::get_phy_key_name_by_scancode(uint32_t scancode)
1378 if(keyboard != nullptr) {
1379 return keyboard->get_phy_key_name_by_scancode(scancode);
1381 return (const _TCHAR *)nullptr;
1384 const _TCHAR *VM::get_phy_key_name_by_vk(uint32_t vk)
1386 if(keyboard != nullptr) {
1387 return keyboard->get_phy_key_name_by_vk(vk);
1389 return (const _TCHAR *)nullptr;
1392 uint32_t VM::get_scancode_by_vk(uint32_t vk)
1394 if(keyboard != nullptr) {
1395 return keyboard->get_scancode_by_vk(vk);
1400 uint32_t VM::get_vk_by_scancode(uint32_t scancode)
1402 if(keyboard != nullptr) {
1403 return keyboard->get_vk_by_scancode(scancode);
1409 #ifdef USE_DIG_RESOLUTION
1410 void VM::get_screen_resolution(int *w, int *h)
1412 switch(display->get_screen_mode()) {
1413 case DISPLAY_MODE_8_200L:
1417 case DISPLAY_MODE_8_400L:
1418 case DISPLAY_MODE_1_400L:
1422 case DISPLAY_MODE_4096:
1423 case DISPLAY_MODE_256k:
1435 bool VM::is_screen_changed()
1438 #if defined(USE_MINIMUM_RENDERING)
1439 f = display->screen_update();
1440 display->reset_screen_update();