2 SHARP X1 Emulator 'eX1'
3 SHARP X1twin Emulator 'eX1twin'
4 SHARP X1turbo Emulator 'eX1turbo'
5 SHARP X1turboZ Emulator 'eX1turboZ'
7 Author : Takeda.Toshiya
14 #include "../../emu.h"
15 #include "../device.h"
18 #include "../datarec.h"
20 #include "../harddisk.h"
21 #include "../hd46505.h"
24 #include "../mb8877.h"
25 #include "../mz1p17.h"
27 //#include "../pcpr201.h"
28 #include "../prnfile.h"
29 #include "../scsi_hdd.h"
30 #include "../scsi_host.h"
31 #include "../ym2151.h"
32 //#include "../ym2203.h"
33 #include "../ay_3_891x.h"
35 #include "../z80ctc.h"
36 #include "../z80sio.h"
37 #ifdef _X1TURBO_FEATURE
38 #include "../z80dma.h"
42 #include "../debugger.h"
56 #include "../upd1990a.h"
61 #include "../huc6280.h"
62 #include "../pcengine/pce.h"
65 DLL_PREFIX_I struct cur_time_s cur_time;
82 // ----------------------------------------------------------------------------
84 // ----------------------------------------------------------------------------
86 VM::VM(EMU* parent_emu) : VM_TEMPLATE(parent_emu)
88 pseudo_sub_cpu = !(FILEIO::IsFileExisting(create_local_path(SUB_ROM_FILE_NAME)) && FILEIO::IsFileExisting(create_local_path(KBD_ROM_FILE_NAME)));
90 sound_type = config.sound_type;
93 first_device = last_device = NULL;
94 dummy = new DEVICE(this, emu); // must be 1st device
95 event = new EVENT(this, emu); // must be 2nd device
96 dummy->set_device_name(_T("1st Dummy"));
98 drec = new DATAREC(this, emu);
99 drec->set_context_noise_play(new NOISE(this, emu));
100 drec->set_context_noise_stop(new NOISE(this, emu));
101 drec->set_context_noise_fast(new NOISE(this, emu));
102 crtc = new HD46505(this, emu);
103 pio = new I8255(this, emu);
104 io = new IO(this, emu);
105 fdc = new MB8877(this, emu);
106 fdc->set_context_noise_seek(new NOISE(this, emu));
107 fdc->set_context_noise_head_down(new NOISE(this, emu));
108 fdc->set_context_noise_head_up(new NOISE(this, emu));
109 sasi_host = new SCSI_HOST(this, emu);
110 for(int i = 0; i < array_length(sasi_hdd); i++) {
111 sasi_hdd[i] = new SASI_HDD(this, emu);
112 sasi_hdd[i]->set_device_name(_T("SASI Hard Disk Drive #%d"), i + 1);
113 sasi_hdd[i]->scsi_id = i;
114 sasi_hdd[i]->bytes_per_sec = 32 * 1024; // 32KB/s
115 sasi_hdd[i]->set_context_interface(sasi_host);
116 sasi_host->set_context_target(sasi_hdd[i]);
118 for(int drv = 0; drv < USE_HARD_DISK; drv++) {
119 sasi_hdd[drv >> 1]->set_disk_handler(drv & 1, new HARDDISK(emu));
121 // psg = new YM2203(this, emu);
122 psg = new AY_3_891X(this, emu);
123 cpu = new Z80(this, emu);
124 ctc = new Z80CTC(this, emu);
125 sio = new Z80SIO(this, emu);
126 if(sound_type >= 1) {
127 opm1 = new YM2151(this, emu);
128 opm1->set_device_name(_T("YM2151 OPM (CZ-8BS1 #1)"));
129 ctc1 = new Z80CTC(this, emu);
130 ctc1->set_device_name(_T("Z80 CTC (CZ-8BS1 #1)"));
132 if(sound_type == 2) {
133 opm2 = new YM2151(this, emu);
134 opm2->set_device_name(_T("YM2151 OPM (CZ-8BS1 #2)"));
135 ctc2 = new Z80CTC(this, emu);
136 ctc2->set_device_name(_T("Z80 CTC (CZ-8BS1 #2)"));
138 if(config.printer_type == 0) {
139 printer = new PRNFILE(this, emu);
140 } else if(config.printer_type == 1) {
141 printer = new MZ1P17(this, emu);
142 // } else if(config.printer_type == 2) {
143 // printer = new PCPR201(this, emu);
147 #ifdef _X1TURBO_FEATURE
148 dma = new Z80DMA(this, emu);
151 display = new DISPLAY(this, emu);
152 emm = new EMM(this, emu);
153 floppy = new FLOPPY(this, emu);
154 iobus = new IOBUS(this, emu);
155 joy = new JOYSTICK(this, emu);
156 memory = new MEMORY(this, emu);
157 mouse = new MOUSE(this, emu);
158 sasi = new SASI(this, emu);
161 psub = new PSUB(this, emu);
166 cpu_sub = new MCS48(this, emu);
167 cpu_sub->set_device_name(_T("MCS48 MCU (Sub)"));
168 pio_sub = new I8255(this, emu);
169 pio_sub->set_device_name(_T("i8255 PIO (Sub)"));
170 rtc_sub = new UPD1990A(this, emu);
171 rtc_sub->set_device_name(_T("uPD1990A RTC (Sub)"));
172 sub = new SUB(this, emu);
175 cpu_kbd = new MCS48(this, emu);
176 cpu_kbd->set_device_name(_T("MCS48 MCU (Keyboard)"));
177 kbd = new KEYBOARD(this, emu);
181 event->set_context_cpu(cpu);
182 if(!pseudo_sub_cpu) {
183 event->set_context_cpu(cpu_sub, 6000000);
184 event->set_context_cpu(cpu_kbd, 6000000);
186 if(sound_type >= 1) {
187 event->set_context_sound(opm1);
189 if(sound_type == 2) {
190 event->set_context_sound(opm2);
192 event->set_context_sound(psg);
193 event->set_context_sound(drec);
194 event->set_context_sound(fdc->get_context_noise_seek());
195 event->set_context_sound(fdc->get_context_noise_head_down());
196 event->set_context_sound(fdc->get_context_noise_head_up());
197 event->set_context_sound(drec->get_context_noise_play());
198 event->set_context_sound(drec->get_context_noise_stop());
199 event->set_context_sound(drec->get_context_noise_fast());
201 drec->set_context_ear(pio, SIG_I8255_PORT_B, 0x02);
202 crtc->set_context_vblank(display, SIG_DISPLAY_VBLANK, 1);
203 crtc->set_context_disp(display, SIG_DISPLAY_DISP, 1);
204 crtc->set_context_vblank(pio, SIG_I8255_PORT_B, 0x80);
205 crtc->set_context_vsync(pio, SIG_I8255_PORT_B, 0x04);
206 pio->set_context_port_a(printer, SIG_PRINTER_DATA, 0xff, 0);
207 pio->set_context_port_c(drec, SIG_DATAREC_MIC, 0x01, 0);
208 pio->set_context_port_c(display, SIG_DISPLAY_COLUMN40, 0x40, 0);
209 pio->set_context_port_c(iobus, SIG_IOBUS_MODE, 0x60, 0);
210 pio->set_context_port_c(printer, SIG_PRINTER_STROBE, 0x80, 0);
211 #ifdef _X1TURBO_FEATURE
212 fdc->set_context_drq(dma, SIG_Z80DMA_READY, 1);
214 sasi_host->set_context_irq(sasi, SIG_SASI_IRQ, 1);
215 sasi_host->set_context_drq(sasi, SIG_SASI_DRQ, 1);
216 ctc->set_context_zc0(ctc, SIG_Z80CTC_TRIG_3, 1);
217 ctc->set_context_zc1(sio, SIG_Z80SIO_TX_CLK_CH0, 1);
218 ctc->set_context_zc1(sio, SIG_Z80SIO_RX_CLK_CH0, 1);
219 ctc->set_context_zc2(sio, SIG_Z80SIO_TX_CLK_CH1, 1);
220 ctc->set_context_zc2(sio, SIG_Z80SIO_RX_CLK_CH1, 1);
221 ctc->set_constant_clock(1, CPU_CLOCKS >> 1);
222 ctc->set_constant_clock(2, CPU_CLOCKS >> 1);
223 sio->set_context_rts(1, mouse, SIG_MOUSE_RTS, 1);
224 // sio->set_tx_clock(0, 9600 * 16); // 9600 baud for RS-232C
225 // sio->set_rx_clock(0, 9600 * 16); // clock is from Z-80CTC ch1 (2MHz/13)
226 // sio->set_tx_clock(1, 4800 * 16); // 4800 baud for mouse
227 // sio->set_rx_clock(1, 4800 * 16); // clock is from Z-80CTC ch2 (2MHz/26)
229 if(sound_type >= 1) {
230 ctc1->set_context_zc0(ctc1, SIG_Z80CTC_TRIG_3, 1);
231 // ctc1->set_constant_clock(1, CPU_CLOCKS >> 1);
232 // ctc1->set_constant_clock(2, CPU_CLOCKS >> 1);
234 if(sound_type == 2) {
235 ctc2->set_context_zc0(ctc2, SIG_Z80CTC_TRIG_3, 1);
236 // ctc2->set_constant_clock(1, CPU_CLOCKS >> 1);
237 // ctc2->set_constant_clock(2, CPU_CLOCKS >> 1);
239 if(config.printer_type == 0) {
240 PRNFILE *prnfile = (PRNFILE *)printer;
241 prnfile->set_context_busy(pio, SIG_I8255_PORT_B, 0x08);
242 } else if(config.printer_type == 1) {
243 MZ1P17 *mz1p17 = (MZ1P17 *)printer;
244 mz1p17->mode = MZ1P17_MODE_X1;
245 mz1p17->set_context_busy(pio, SIG_I8255_PORT_B, 0x08);
246 // } else if(config.printer_type == 2) {
247 // PCPR201 *pcpr201 = (PCPR201 *)printer;
248 // pcpr201->set_context_busy(pio, SIG_I8255_PORT_B, 0x08);
250 #ifdef _X1TURBO_FEATURE
251 dma->set_context_memory(memory);
252 dma->set_context_io(iobus);
255 #ifdef _X1TURBO_FEATURE
256 display->set_context_cpu(cpu);
258 display->set_context_crtc(crtc);
259 display->set_vram_ptr(iobus->get_vram());
260 display->set_regs_ptr(crtc->get_regs());
261 floppy->set_context_fdc(fdc);
262 iobus->set_context_cpu(cpu);
263 iobus->set_context_display(display);
264 iobus->set_context_io(io);
265 joy->set_context_psg(psg);
266 #ifdef _X1TURBO_FEATURE
267 memory->set_context_pio(pio);
269 mouse->set_context_sio(sio);
270 sasi->set_context_host(sasi_host);
271 #ifdef _X1TURBO_FEATURE
272 sasi->set_context_dma(dma);
276 drec->set_context_remote(psub, SIG_PSUB_TAPE_REMOTE, 1);
277 drec->set_context_end(psub, SIG_PSUB_TAPE_END, 1);
278 psub->set_context_pio(pio);
279 psub->set_context_drec(drec);
282 cpu_sub->set_context_mem(new MCS48MEM(this, emu));
283 cpu_sub->set_context_io(sub);
285 cpu_sub->set_context_debugger(new DEBUGGER(this, emu));
287 drec->set_context_end(sub, SIG_SUB_TAPE_END, 1);
288 drec->set_context_apss(sub, SIG_SUB_TAPE_APSS, 1);
289 pio_sub->set_context_port_c(sub, SIG_SUB_PIO_PORT_C, 0x80, 0);
290 // pc1:break -> pb0 of 8255(main)
291 pio_sub->set_context_port_c(pio, SIG_I8255_PORT_B, 0x02, -1);
292 // pc5:ibf -> pb6 of 8255(main)
293 pio_sub->set_context_port_c(pio, SIG_I8255_PORT_B, 0x20, 1);
294 // pc7:obf -> pb5 of 8255(main)
295 pio_sub->set_context_port_c(pio, SIG_I8255_PORT_B, 0x80, -2);
296 // pc7:obf -> pb7 of 8255(sub)
297 pio_sub->set_context_port_c(pio_sub, SIG_I8255_PORT_B, 0x80, 0);
299 sub->set_context_pio(pio_sub);
300 sub->set_context_rtc(rtc_sub);
301 sub->set_context_drec(drec);
304 cpu_kbd->set_context_mem(new MCS48MEM(this, emu));
305 cpu_kbd->set_context_io(kbd);
307 cpu_kbd->set_context_debugger(new DEBUGGER(this, emu));
309 kbd->set_context_cpu(cpu_sub);
313 cpu->set_context_mem(memory);
314 cpu->set_context_io(iobus);
315 #if defined(_X1TURBO_FEATURE) && defined(SINGLE_MODE_DMA)
316 cpu->set_context_dma(dma);
319 cpu->set_context_debugger(new DEBUGGER(this, emu));
322 // z80 family daisy chain
323 DEVICE* parent_dev = NULL;
326 #define Z80_DAISY_CHAIN(dev) { \
327 if(parent_dev == NULL) { \
328 cpu->set_context_intr(dev); \
330 parent_dev->set_context_child(dev); \
332 dev->set_context_intr(cpu, level++); \
335 #ifndef _X1TURBO_FEATURE
336 Z80_DAISY_CHAIN(sio); // CZ-8BM2
337 Z80_DAISY_CHAIN(ctc);
339 if(sound_type >= 1) {
340 Z80_DAISY_CHAIN(ctc1);
342 if(sound_type == 2) {
343 Z80_DAISY_CHAIN(ctc2);
345 #ifdef _X1TURBO_FEATURE
346 Z80_DAISY_CHAIN(sio);
347 Z80_DAISY_CHAIN(dma);
348 Z80_DAISY_CHAIN(ctc);
351 Z80_DAISY_CHAIN(psub);
353 Z80_DAISY_CHAIN(sub);
357 if(sound_type >= 1) {
358 io->set_iomap_single_w(0x700, opm1);
359 io->set_iovalue_single_r(0x700, 0x00);
360 io->set_iomap_single_rw(0x701, opm1);
362 io->set_flipflop_single_rw(0x704, 0x00);
364 io->set_iomap_range_rw(0x704, 0x707, ctc1);
367 if(sound_type == 2) {
368 io->set_iomap_single_w(0x708, opm2);
369 io->set_iovalue_single_r(0x708, 0x00);
370 io->set_iomap_single_rw(0x709, opm2);
371 io->set_iomap_range_rw(0x70c, 0x70f, ctc2);
373 #ifdef _X1TURBO_FEATURE
374 io->set_iomap_single_rw(0xb00, memory);
376 io->set_iomap_range_rw(0xd00, 0xd03, emm);
377 io->set_iomap_range_r(0xe80, 0xe81, display);
378 io->set_iomap_range_w(0xe80, 0xe82, display);
379 io->set_iomap_range_rw(0xfd0, 0xfd3, sasi);
380 io->set_iomap_range_rw(0xff8, 0xffb, fdc);
381 io->set_iomap_single_w(0xffc, floppy);
382 #ifdef _X1TURBO_FEATURE
383 io->set_iomap_range_r(0xffc, 0xfff, floppy);
385 io->set_iomap_range_rw(0x1000, 0x17ff, display);
386 for(int i = 0x1800; i <= 0x18ff; i += 0x10) {
387 io->set_iomap_range_rw(i, i + 1, crtc);
390 io->set_iomap_range_rw(0x1900, 0x19ff, psub);
392 io->set_iomap_range_rw(0x1900, 0x19ff, sub);
394 for(int i = 0x1a00; i <= 0x1aff; i += 4) {
395 io->set_iomap_range_rw(i, i + 3, pio);
397 for(int i = 0x1b00; i <= 0x1bff; i++) {
398 io->set_iomap_alias_rw(i, psg, 1);
400 for(int i = 0x1c00; i <= 0x1cff; i++) {
401 io->set_iomap_alias_w(i, psg, 0);
403 io->set_iomap_range_r(0x1e00, 0x1eff, memory);
404 io->set_iomap_range_w(0x1d00, 0x1eff, memory);
405 #ifdef _X1TURBO_FEATURE
406 io->set_iomap_range_rw(0x1f80, 0x1f8f, dma);
407 io->set_iomap_range_rw(0x1f90, 0x1f93, sio);
408 io->set_iomap_range_rw(0x1fa0, 0x1fa3, ctc);
410 io->set_iomap_single_rw(0x1fb0, display);
411 io->set_iomap_range_rw(0x1fb9, 0x1fc5, display);
412 io->set_iomap_single_rw(0x1fd0, display);
413 io->set_iomap_single_rw(0x1fe0, display);
415 io->set_iomap_single_w(0x1fd0, display);
416 io->set_iomap_single_w(0x1fe0, display);
419 // io->set_iovalue_single_r(0x1ff0, 0x00);
422 io->set_iomap_range_rw(0x1f98, 0x1f9b, sio); // CZ-8BM2
423 io->set_iomap_range_rw(0x1fa8, 0x1fab, ctc);
425 io->set_iomap_range_rw(0x2000, 0x3fff, display); // tvram
429 pceevent = new EVENT(this, emu);
430 pceevent->set_frames_per_sec(PCE_FRAMES_PER_SEC);
431 pceevent->set_lines_per_frame(PCE_LINES_PER_FRAME);
432 pceevent->set_device_name(_T("EVENT (PC-ENGINE)"));
433 pcecpu = new HUC6280(this, emu);
434 pcecpu->set_device_name(_T("HuC6820 CPU (PC-ENGINE)"));
435 pcecpu->set_context_event_manager(pceevent);
436 pce = new PCE(this, emu);
437 pce->set_device_name(_T("SUB SYSTEM (PC-ENGINE)"));
438 pce->set_context_event_manager(pceevent);
440 pceevent->set_context_cpu(pcecpu, PCE_CPU_CLOCKS);
441 pceevent->set_context_sound(pce);
443 pcecpu->set_context_mem(pce);
444 pcecpu->set_context_io(pce);
446 pcecpu->set_context_debugger(new DEBUGGER(this, emu));
448 pce->set_context_cpu(pcecpu);
451 // initialize all devices
452 #if defined(__GIT_REPO_VERSION)
453 strncpy(_git_revision, __GIT_REPO_VERSION, sizeof(_git_revision) - 1);
455 for(DEVICE* device = first_device; device; device = device->next_device) {
456 device->initialize();
458 if(!pseudo_sub_cpu) {
459 // load rom images after cpustate is allocated
460 cpu_sub->load_rom_image(create_local_path(SUB_ROM_FILE_NAME));
461 cpu_kbd->load_rom_image(create_local_path(KBD_ROM_FILE_NAME));
463 // patch to set the current year
464 uint8_t *rom = cpu_sub->get_rom_ptr();
465 sub->rom_crc32 = get_crc32(rom, 0x800); // 2KB
466 if(rom[0x23] == 0xb9 && rom[0x24] == 0x35 && rom[0x25] == 0xb1) {
467 //dll_cur_time_t cur_time;
469 get_host_time(&cur_time);
470 rom[0x26] = TO_BCD(cur_time.year);
473 for(int drv = 0; drv < MAX_DRIVE; drv++) {
474 //#ifdef _X1TURBO_FEATURE
475 // if(config.drive_type == 2) {
476 // fdc->set_drive_type(drv, DRIVE_TYPE_2HD);
479 fdc->set_drive_type(drv, DRIVE_TYPE_2D);
480 // fdc->set_drive_rpm(drv, 300);
481 // fdc->set_drive_mfm(drv, true);
483 for(int drv = 0; drv < USE_HARD_DISK; drv++) {
484 if(!(config.last_hard_disk_path[drv][0] != _T('\0') && FILEIO::IsFileExisting(config.last_hard_disk_path[drv]))) {
485 create_local_path(config.last_hard_disk_path[drv], _MAX_PATH, _T("SASI%d.DAT"), drv);
492 // delete all devices
493 for(DEVICE* device = first_device; device;) {
494 DEVICE *next_device = device->next_device;
497 device = next_device;
501 DEVICE* VM::get_device(int id)
503 for(DEVICE* device = first_device; device; device = device->next_device) {
504 if(device->this_device_id == id) {
511 // ----------------------------------------------------------------------------
512 // drive virtual machine
513 // ----------------------------------------------------------------------------
518 for(DEVICE* device = first_device; device; device = device->next_device) {
521 pio->write_signal(SIG_I8255_PORT_B, 0x00, 0x08); // busy = low
522 psg->set_reg(0x2e, 0); // set prescaler
525 void VM::special_reset()
528 cpu->write_signal(SIG_CPU_NMI, 1, 1);
535 if(pce->is_cart_inserted()) {
541 double VM::get_frame_rate()
544 if(pce->is_cart_inserted()) {
545 return pceevent->get_frame_rate();
548 return event->get_frame_rate();
551 // ----------------------------------------------------------------------------
553 // ----------------------------------------------------------------------------
556 DEVICE *VM::get_cpu(int index)
560 } else if(index == 1) {
562 } else if(index == 2) {
565 } else if(index == 3 && pce->is_cart_inserted()) {
573 // ----------------------------------------------------------------------------
575 // ----------------------------------------------------------------------------
577 void VM::draw_screen()
579 display->draw_screen();
581 if(pce->is_cart_inserted()) {
587 // ----------------------------------------------------------------------------
589 // ----------------------------------------------------------------------------
591 void VM::initialize_sound(int rate, int samples)
593 // init sound manager
594 event->initialize_sound(rate, samples);
596 pceevent->initialize_sound(rate, samples);
600 if(sound_type >= 1) {
601 opm1->initialize_sound(rate, 4000000, samples, 0);
603 if(sound_type == 2) {
604 opm2->initialize_sound(rate, 4000000, samples, 0);
606 psg->initialize_sound(rate, 2000000, samples, 0, 0);
608 pce->initialize_sound(rate);
612 uint16_t* VM::create_sound(int* extra_frames)
615 if(pce->is_cart_inserted()) {
616 uint16_t* buffer = pceevent->create_sound(extra_frames);
617 for(int i = 0; i < *extra_frames; i++) {
623 return event->create_sound(extra_frames);
626 int VM::get_sound_buffer_ptr()
629 if(pce->is_cart_inserted()) {
630 return pceevent->get_sound_buffer_ptr();
633 return event->get_sound_buffer_ptr();
636 #ifdef USE_SOUND_VOLUME
637 void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
640 psg->set_volume(1, decibel_l, decibel_r);
642 if(sound_type >= 1) {
643 opm1->set_volume(0, decibel_l, decibel_r);
646 if(sound_type >= 2) {
647 opm2->set_volume(0, decibel_l, decibel_r);
650 drec->set_volume(0, decibel_l, decibel_r);
652 fdc->get_context_noise_seek()->set_volume(0, decibel_l, decibel_r);
653 fdc->get_context_noise_head_down()->set_volume(0, decibel_l, decibel_r);
654 fdc->get_context_noise_head_up()->set_volume(0, decibel_l, decibel_r);
656 drec->get_context_noise_play()->set_volume(0, decibel_l, decibel_r);
657 drec->get_context_noise_stop()->set_volume(0, decibel_l, decibel_r);
658 drec->get_context_noise_fast()->set_volume(0, decibel_l, decibel_r);
661 pce->set_volume(0, decibel_l, decibel_r);
667 // ----------------------------------------------------------------------------
669 // ----------------------------------------------------------------------------
671 void VM::key_down(int code, bool repeat)
674 if(!repeat && !pce->is_cart_inserted()) {
679 psub->key_down(code, false);
681 kbd->key_down(code, false);
686 void VM::key_up(int code)
689 if(!pce->is_cart_inserted()) {
701 bool VM::get_caps_locked()
704 if(!pce->is_cart_inserted()) {
707 return psub->get_caps_locked();
709 return kbd->get_caps_locked();
717 bool VM::get_kana_locked()
720 if(!pce->is_cart_inserted()) {
723 return psub->get_kana_locked();
725 return kbd->get_kana_locked();
733 // ----------------------------------------------------------------------------
735 // ----------------------------------------------------------------------------
737 void VM::open_floppy_disk(int drv, const _TCHAR* file_path, int bank)
739 fdc->open_disk(drv, file_path, bank);
741 #ifdef _X1TURBO_FEATURE
742 if(fdc->get_media_type(drv) == MEDIA_TYPE_2DD) {
743 if(fdc->get_drive_type(drv) == DRIVE_TYPE_2D) {
744 fdc->set_drive_type(drv, DRIVE_TYPE_2DD);
746 } else if(fdc->get_media_type(drv) == MEDIA_TYPE_2D) {
747 if(fdc->get_drive_type(drv) == DRIVE_TYPE_2DD) {
748 fdc->set_drive_type(drv, DRIVE_TYPE_2D);
754 void VM::close_floppy_disk(int drv)
756 fdc->close_disk(drv);
759 bool VM::is_floppy_disk_inserted(int drv)
761 return fdc->is_disk_inserted(drv);
764 void VM::is_floppy_disk_protected(int drv, bool value)
766 fdc->is_disk_protected(drv, value);
769 bool VM::is_floppy_disk_protected(int drv)
771 return fdc->is_disk_protected(drv);
774 uint32_t VM::is_floppy_disk_accessed()
776 return fdc->read_signal(0);
779 void VM::open_hard_disk(int drv, const _TCHAR* file_path)
781 if(drv < USE_HARD_DISK) {
782 sasi_hdd[drv >> 1]->open(drv & 1, file_path, 256);
786 void VM::close_hard_disk(int drv)
788 if(drv < USE_HARD_DISK) {
789 sasi_hdd[drv >> 1]->close(drv & 1);
793 bool VM::is_hard_disk_inserted(int drv)
795 if(drv < USE_HARD_DISK) {
796 return sasi_hdd[drv >> 1]->mounted(drv & 1);
801 uint32_t VM::is_hard_disk_accessed()
805 for(int drv = 0; drv < USE_HARD_DISK; drv++) {
806 if(sasi_hdd[drv >> 1]->accessed(drv & 1)) {
813 void VM::play_tape(int drv, const _TCHAR* file_path)
815 bool value = drec->play_tape(file_path);
818 psub->play_tape(value);
821 sub->play_tape(value);
825 void VM::rec_tape(int drv, const _TCHAR* file_path)
827 bool value = drec->rec_tape(file_path);
830 psub->rec_tape(value);
833 sub->rec_tape(value);
837 void VM::close_tape(int drv)
849 bool VM::is_tape_inserted(int drv)
851 return drec->is_tape_inserted();
854 bool VM::is_tape_playing(int drv)
856 return drec->is_tape_playing();
859 bool VM::is_tape_recording(int drv)
861 return drec->is_tape_recording();
864 int VM::get_tape_position(int drv)
866 return drec->get_tape_position();
869 const _TCHAR* VM::get_tape_message(int drv)
871 return drec->get_message();
874 void VM::push_play(int drv)
877 drec->set_remote(true);
880 void VM::push_stop(int drv)
882 drec->set_remote(false);
885 void VM::push_fast_forward(int drv)
888 drec->set_remote(true);
891 void VM::push_fast_rewind(int drv)
893 drec->set_ff_rew(-1);
894 drec->set_remote(true);
897 void VM::push_apss_forward(int drv)
902 void VM::push_apss_rewind(int drv)
907 bool VM::is_frame_skippable()
910 if(pce->is_cart_inserted()) {
911 return pceevent->is_frame_skippable();
914 return event->is_frame_skippable();
918 void VM::open_cart(int drv, const _TCHAR* file_path)
921 pce->open_cart(file_path);
927 void VM::close_cart(int drv)
936 bool VM::is_cart_inserted(int drv)
939 return pce->is_cart_inserted();
946 void VM::update_config()
948 for(DEVICE* device = first_device; device; device = device->next_device) {
949 device->update_config();
951 #ifdef _X1TURBO_FEATURE
956 #ifdef _X1TURBO_FEATURE
957 void VM::update_dipswitch()
959 // bit0 0=High 1=Standard
960 // bit1-3 000=5"2D 001=5"2DD 010=5"2HD
961 io->set_iovalue_single_r(0x1ff0, (config.monitor_type & 1) | ((config.drive_type & 7) << 1));
965 #define STATE_VERSION 10
967 bool VM::process_state(FILEIO* state_fio, bool loading)
969 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
972 for(DEVICE* device = first_device; device; device = device->next_device) {
973 // Note: typeid(foo).name is fixed by recent ABI.Not decr. 6.
974 // const char *name = typeid(*device).name();
975 // But, using get_device_name() instead of typeid(foo).name() 20181008 K.O
976 const char *name = device->get_device_name();
977 int len = strlen(name);
978 if(!state_fio->StateCheckInt32(len)) {
981 if(!state_fio->StateCheckBuffer(name, len, 1)) {
984 if(!device->process_state(state_fio, loading)) {
986 printf("Data loading Error: DEVID=%d\n", device->this_device_id);
991 state_fio->StateBool(pseudo_sub_cpu);
992 state_fio->StateInt32(sound_type);
994 #ifdef _X1TURBO_FEATURE