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;
68 // ----------------------------------------------------------------------------
70 // ----------------------------------------------------------------------------
72 VM::VM(EMU* parent_emu) : VM_TEMPLATE(parent_emu)
74 pseudo_sub_cpu = !(FILEIO::IsFileExisting(create_local_path(SUB_ROM_FILE_NAME)) && FILEIO::IsFileExisting(create_local_path(KBD_ROM_FILE_NAME)));
76 sound_type = config.sound_type;
79 first_device = last_device = NULL;
80 dummy = new DEVICE(this, emu); // must be 1st device
81 event = new EVENT(this, emu); // must be 2nd device
82 dummy->set_device_name(_T("1st Dummy"));
84 drec = new DATAREC(this, emu);
85 drec->set_context_noise_play(new NOISE(this, emu));
86 drec->set_context_noise_stop(new NOISE(this, emu));
87 drec->set_context_noise_fast(new NOISE(this, emu));
88 crtc = new HD46505(this, emu);
89 pio = new I8255(this, emu);
90 io = new IO(this, emu);
91 fdc = new MB8877(this, emu);
92 fdc->set_context_noise_seek(new NOISE(this, emu));
93 fdc->set_context_noise_head_down(new NOISE(this, emu));
94 fdc->set_context_noise_head_up(new NOISE(this, emu));
95 sasi_host = new SCSI_HOST(this, emu);
96 for (int i = 0; i < array_length(sasi_hdd); i++) {
97 sasi_hdd[i] = new SCSI_HDD(this, emu);
98 sasi_hdd[i]->set_device_name(_T("SASI Hard Disk Drive #%d"), i + 1);
99 sasi_hdd[i]->scsi_id = i;
100 sasi_hdd[i]->bytes_per_sec = 32 * 1024; // 32KB/s
101 sasi_hdd[i]->set_context_interface(sasi_host);
102 sasi_host->set_context_target(sasi_hdd[i]);
104 for(int drv = 0; drv < USE_HARD_DISK; drv++) {
105 sasi_hdd[drv >> 1]->set_disk_handler(drv & 1, new HARDDISK(emu));
107 // psg = new YM2203(this, emu);
108 psg = new AY_3_891X(this, emu);
109 cpu = new Z80(this, emu);
110 ctc = new Z80CTC(this, emu);
111 sio = new Z80SIO(this, emu);
112 if(sound_type >= 1) {
113 opm1 = new YM2151(this, emu);
114 opm1->set_device_name(_T("YM2151 OPM (CZ-8BS1 #1)"));
115 ctc1 = new Z80CTC(this, emu);
116 ctc1->set_device_name(_T("Z80 CTC (CZ-8BS1 #1)"));
118 if(sound_type == 2) {
119 opm2 = new YM2151(this, emu);
120 opm2->set_device_name(_T("YM2151 OPM (CZ-8BS1 #2)"));
121 ctc2 = new Z80CTC(this, emu);
122 ctc2->set_device_name(_T("Z80 CTC (CZ-8BS1 #2)"));
124 if(config.printer_type == 0) {
125 printer = new PRNFILE(this, emu);
126 } else if(config.printer_type == 1) {
127 printer = new MZ1P17(this, emu);
128 // } else if(config.printer_type == 2) {
129 // printer = new PCPR201(this, emu);
133 #ifdef _X1TURBO_FEATURE
134 dma = new Z80DMA(this, emu);
137 display = new DISPLAY(this, emu);
138 emm = new EMM(this, emu);
139 floppy = new FLOPPY(this, emu);
140 iobus = new IOBUS(this, emu);
141 joy = new JOYSTICK(this, emu);
142 memory = new MEMORY(this, emu);
143 mouse = new MOUSE(this, emu);
144 sasi = new SASI(this, emu);
147 psub = new PSUB(this, emu);
152 cpu_sub = new MCS48(this, emu);
153 cpu_sub->set_device_name(_T("MCS48 MCU (Sub)"));
154 pio_sub = new I8255(this, emu);
155 pio_sub->set_device_name(_T("i8255 PIO (Sub)"));
156 rtc_sub = new UPD1990A(this, emu);
157 rtc_sub->set_device_name(_T("uPD1990A RTC (Sub)"));
158 sub = new SUB(this, emu);
161 cpu_kbd = new MCS48(this, emu);
162 cpu_kbd->set_device_name(_T("MCS48 MCU (Keyboard)"));
163 kbd = new KEYBOARD(this, emu);
167 event->set_context_cpu(cpu);
168 if(!pseudo_sub_cpu) {
169 event->set_context_cpu(cpu_sub, 6000000);
170 event->set_context_cpu(cpu_kbd, 6000000);
172 if(sound_type >= 1) {
173 event->set_context_sound(opm1);
175 if(sound_type == 2) {
176 event->set_context_sound(opm2);
178 event->set_context_sound(psg);
179 event->set_context_sound(drec);
180 event->set_context_sound(fdc->get_context_noise_seek());
181 event->set_context_sound(fdc->get_context_noise_head_down());
182 event->set_context_sound(fdc->get_context_noise_head_up());
183 event->set_context_sound(drec->get_context_noise_play());
184 event->set_context_sound(drec->get_context_noise_stop());
185 event->set_context_sound(drec->get_context_noise_fast());
187 drec->set_context_ear(pio, SIG_I8255_PORT_B, 0x02);
188 crtc->set_context_vblank(display, SIG_DISPLAY_VBLANK, 1);
189 crtc->set_context_disp(display, SIG_DISPLAY_DISP, 1);
190 crtc->set_context_vblank(pio, SIG_I8255_PORT_B, 0x80);
191 crtc->set_context_vsync(pio, SIG_I8255_PORT_B, 0x04);
192 pio->set_context_port_a(printer, SIG_PRINTER_DATA, 0xff, 0);
193 pio->set_context_port_c(drec, SIG_DATAREC_MIC, 0x01, 0);
194 pio->set_context_port_c(display, SIG_DISPLAY_COLUMN40, 0x40, 0);
195 pio->set_context_port_c(iobus, SIG_IOBUS_MODE, 0x60, 0);
196 pio->set_context_port_c(printer, SIG_PRINTER_STROBE, 0x80, 0);
197 #ifdef _X1TURBO_FEATURE
198 fdc->set_context_drq(dma, SIG_Z80DMA_READY, 1);
200 sasi_host->set_context_irq(sasi, SIG_SASI_IRQ, 1);
201 sasi_host->set_context_drq(sasi, SIG_SASI_DRQ, 1);
202 ctc->set_context_zc0(ctc, SIG_Z80CTC_TRIG_3, 1);
203 ctc->set_context_zc1(sio, SIG_Z80SIO_TX_CLK_CH0, 1);
204 ctc->set_context_zc1(sio, SIG_Z80SIO_RX_CLK_CH0, 1);
205 ctc->set_context_zc2(sio, SIG_Z80SIO_TX_CLK_CH1, 1);
206 ctc->set_context_zc2(sio, SIG_Z80SIO_RX_CLK_CH1, 1);
207 ctc->set_constant_clock(1, CPU_CLOCKS >> 1);
208 ctc->set_constant_clock(2, CPU_CLOCKS >> 1);
209 sio->set_context_rts(1, mouse, SIG_MOUSE_RTS, 1);
210 // sio->set_tx_clock(0, 9600 * 16); // 9600 baud for RS-232C
211 // sio->set_rx_clock(0, 9600 * 16); // clock is from Z-80CTC ch1 (2MHz/13)
212 // sio->set_tx_clock(1, 4800 * 16); // 4800 baud for mouse
213 // sio->set_rx_clock(1, 4800 * 16); // clock is from Z-80CTC ch2 (2MHz/26)
215 if(sound_type >= 1) {
216 ctc1->set_context_zc0(ctc1, SIG_Z80CTC_TRIG_3, 1);
217 // ctc1->set_constant_clock(1, CPU_CLOCKS >> 1);
218 // ctc1->set_constant_clock(2, CPU_CLOCKS >> 1);
220 if(sound_type == 2) {
221 ctc2->set_context_zc0(ctc2, SIG_Z80CTC_TRIG_3, 1);
222 // ctc2->set_constant_clock(1, CPU_CLOCKS >> 1);
223 // ctc2->set_constant_clock(2, CPU_CLOCKS >> 1);
225 if(config.printer_type == 0) {
226 PRNFILE *prnfile = (PRNFILE *)printer;
227 prnfile->set_context_busy(pio, SIG_I8255_PORT_B, 0x08);
228 } else if(config.printer_type == 1) {
229 MZ1P17 *mz1p17 = (MZ1P17 *)printer;
230 mz1p17->mode = MZ1P17_MODE_X1;
231 mz1p17->set_context_busy(pio, SIG_I8255_PORT_B, 0x08);
232 // } else if(config.printer_type == 2) {
233 // PCPR201 *pcpr201 = (PCPR201 *)printer;
234 // pcpr201->set_context_busy(pio, SIG_I8255_PORT_B, 0x08);
236 #ifdef _X1TURBO_FEATURE
237 dma->set_context_memory(memory);
238 dma->set_context_io(iobus);
241 #ifdef _X1TURBO_FEATURE
242 display->set_context_cpu(cpu);
244 display->set_context_crtc(crtc);
245 display->set_vram_ptr(iobus->get_vram());
246 display->set_regs_ptr(crtc->get_regs());
247 floppy->set_context_fdc(fdc);
248 iobus->set_context_cpu(cpu);
249 iobus->set_context_display(display);
250 iobus->set_context_io(io);
251 joy->set_context_psg(psg);
252 #ifdef _X1TURBO_FEATURE
253 memory->set_context_pio(pio);
255 mouse->set_context_sio(sio);
256 sasi->set_context_host(sasi_host);
257 #ifdef _X1TURBO_FEATURE
258 sasi->set_context_dma(dma);
262 drec->set_context_remote(psub, SIG_PSUB_TAPE_REMOTE, 1);
263 drec->set_context_end(psub, SIG_PSUB_TAPE_END, 1);
264 psub->set_context_pio(pio);
265 psub->set_context_drec(drec);
268 cpu_sub->set_context_mem(new MCS48MEM(this, emu));
269 cpu_sub->set_context_io(sub);
271 cpu_sub->set_context_debugger(new DEBUGGER(this, emu));
273 drec->set_context_end(sub, SIG_SUB_TAPE_END, 1);
274 drec->set_context_apss(sub, SIG_SUB_TAPE_APSS, 1);
275 pio_sub->set_context_port_c(sub, SIG_SUB_PIO_PORT_C, 0x80, 0);
276 // pc1:break -> pb0 of 8255(main)
277 pio_sub->set_context_port_c(pio, SIG_I8255_PORT_B, 0x02, -1);
278 // pc5:ibf -> pb6 of 8255(main)
279 pio_sub->set_context_port_c(pio, SIG_I8255_PORT_B, 0x20, 1);
280 // pc7:obf -> pb5 of 8255(main)
281 pio_sub->set_context_port_c(pio, SIG_I8255_PORT_B, 0x80, -2);
282 // pc7:obf -> pb7 of 8255(sub)
283 pio_sub->set_context_port_c(pio_sub, SIG_I8255_PORT_B, 0x80, 0);
285 sub->set_context_pio(pio_sub);
286 sub->set_context_rtc(rtc_sub);
287 sub->set_context_drec(drec);
290 cpu_kbd->set_context_mem(new MCS48MEM(this, emu));
291 cpu_kbd->set_context_io(kbd);
293 cpu_kbd->set_context_debugger(new DEBUGGER(this, emu));
295 kbd->set_context_cpu(cpu_sub);
299 cpu->set_context_mem(memory);
300 cpu->set_context_io(iobus);
301 #if defined(_X1TURBO_FEATURE) && defined(SINGLE_MODE_DMA)
302 cpu->set_context_dma(dma);
305 cpu->set_context_debugger(new DEBUGGER(this, emu));
308 // z80 family daisy chain
309 DEVICE* parent_dev = NULL;
312 #define Z80_DAISY_CHAIN(dev) { \
313 if(parent_dev == NULL) { \
314 cpu->set_context_intr(dev); \
316 parent_dev->set_context_child(dev); \
318 dev->set_context_intr(cpu, level++); \
321 #ifndef _X1TURBO_FEATURE
322 Z80_DAISY_CHAIN(sio); // CZ-8BM2
323 Z80_DAISY_CHAIN(ctc);
325 if(sound_type >= 1) {
326 Z80_DAISY_CHAIN(ctc1);
328 if(sound_type == 2) {
329 Z80_DAISY_CHAIN(ctc2);
331 #ifdef _X1TURBO_FEATURE
332 Z80_DAISY_CHAIN(sio);
333 Z80_DAISY_CHAIN(dma);
334 Z80_DAISY_CHAIN(ctc);
337 Z80_DAISY_CHAIN(psub);
339 Z80_DAISY_CHAIN(sub);
343 if(sound_type >= 1) {
344 io->set_iomap_single_w(0x700, opm1);
345 io->set_iovalue_single_r(0x700, 0x00);
346 io->set_iomap_single_rw(0x701, opm1);
348 io->set_flipflop_single_rw(0x704, 0x00);
350 io->set_iomap_range_rw(0x704, 0x707, ctc1);
353 if(sound_type == 2) {
354 io->set_iomap_single_w(0x708, opm2);
355 io->set_iovalue_single_r(0x708, 0x00);
356 io->set_iomap_single_rw(0x709, opm2);
357 io->set_iomap_range_rw(0x70c, 0x70f, ctc2);
359 #ifdef _X1TURBO_FEATURE
360 io->set_iomap_single_rw(0xb00, memory);
362 io->set_iomap_range_rw(0xd00, 0xd03, emm);
363 io->set_iomap_range_r(0xe80, 0xe81, display);
364 io->set_iomap_range_w(0xe80, 0xe82, display);
365 io->set_iomap_range_rw(0xfd0, 0xfd3, sasi);
366 io->set_iomap_range_rw(0xff8, 0xffb, fdc);
367 io->set_iomap_single_w(0xffc, floppy);
368 #ifdef _X1TURBO_FEATURE
369 io->set_iomap_range_r(0xffc, 0xfff, floppy);
371 io->set_iomap_range_rw(0x1000, 0x17ff, display);
372 for(int i = 0x1800; i <= 0x18ff; i += 0x10) {
373 io->set_iomap_range_rw(i, i + 1, crtc);
376 io->set_iomap_range_rw(0x1900, 0x19ff, psub);
378 io->set_iomap_range_rw(0x1900, 0x19ff, sub);
380 for(int i = 0x1a00; i <= 0x1aff; i += 4) {
381 io->set_iomap_range_rw(i, i + 3, pio);
383 for(int i = 0x1b00; i <= 0x1bff; i++) {
384 io->set_iomap_alias_rw(i, psg, 1);
386 for(int i = 0x1c00; i <= 0x1cff; i++) {
387 io->set_iomap_alias_w(i, psg, 0);
389 io->set_iomap_range_r(0x1e00, 0x1eff, memory);
390 io->set_iomap_range_w(0x1d00, 0x1eff, memory);
391 #ifdef _X1TURBO_FEATURE
392 io->set_iomap_range_rw(0x1f80, 0x1f8f, dma);
393 io->set_iomap_range_rw(0x1f90, 0x1f93, sio);
394 io->set_iomap_range_rw(0x1fa0, 0x1fa3, ctc);
396 io->set_iomap_single_rw(0x1fb0, display);
397 io->set_iomap_range_rw(0x1fb9, 0x1fc5, display);
398 io->set_iomap_single_rw(0x1fd0, display);
399 io->set_iomap_single_rw(0x1fe0, display);
401 io->set_iomap_single_w(0x1fd0, display);
402 io->set_iomap_single_w(0x1fe0, display);
405 // io->set_iovalue_single_r(0x1ff0, 0x00);
408 io->set_iomap_range_rw(0x1f98, 0x1f9b, sio); // CZ-8BM2
409 io->set_iomap_range_rw(0x1fa8, 0x1fab, ctc);
411 io->set_iomap_range_rw(0x2000, 0x3fff, display); // tvram
415 pceevent = new EVENT(this, emu);
416 pceevent->set_frames_per_sec(PCE_FRAMES_PER_SEC);
417 pceevent->set_lines_per_frame(PCE_LINES_PER_FRAME);
418 pceevent->set_device_name(_T("EVENT (PC-ENGINE)"));
419 pcecpu = new HUC6280(this, emu);
420 pcecpu->set_device_name(_T("HuC6820 CPU (PC-ENGINE)"));
421 pcecpu->set_context_event_manager(pceevent);
422 pce = new PCE(this, emu);
423 pce->set_device_name(_T("SUB SYSTEM (PC-ENGINE)"));
424 pce->set_context_event_manager(pceevent);
426 pceevent->set_context_cpu(pcecpu, PCE_CPU_CLOCKS);
427 pceevent->set_context_sound(pce);
429 pcecpu->set_context_mem(pce);
430 pcecpu->set_context_io(pce);
432 pcecpu->set_context_debugger(new DEBUGGER(this, emu));
434 pce->set_context_cpu(pcecpu);
437 // initialize all devices
438 for(DEVICE* device = first_device; device; device = device->next_device) {
439 device->initialize();
441 if(!pseudo_sub_cpu) {
442 // load rom images after cpustate is allocated
443 cpu_sub->load_rom_image(create_local_path(SUB_ROM_FILE_NAME));
444 cpu_kbd->load_rom_image(create_local_path(KBD_ROM_FILE_NAME));
446 // patch to set the current year
447 uint8_t *rom = cpu_sub->get_rom_ptr();
448 sub->rom_crc32 = get_crc32(rom, 0x800); // 2KB
449 if(rom[0x23] == 0xb9 && rom[0x24] == 0x35 && rom[0x25] == 0xb1) {
450 //dll_cur_time_t cur_time;
452 get_host_time(&cur_time);
453 rom[0x26] = TO_BCD(cur_time.year);
456 for(int drv = 0; drv < MAX_DRIVE; drv++) {
457 //#ifdef _X1TURBO_FEATURE
458 // fdc->set_drive_type(drv, DRIVE_TYPE_2DD);
460 fdc->set_drive_type(drv, DRIVE_TYPE_2D);
462 // fdc->set_drive_rpm(drv, 300);
463 // fdc->set_drive_mfm(drv, true);
465 for(int drv = 0; drv < USE_HARD_DISK; drv++) {
466 #if defined(OPEN_HARD_DISK_IN_RESET)
467 create_local_path(hd_file_path[drv], _MAX_PATH, _T("SASI%d.DAT"), drv);
469 open_hard_disk_tmp(drv, create_local_path(_T("SASI%d.DAT"), drv));
477 // delete all devices
478 for(DEVICE* device = first_device; device;) {
479 DEVICE *next_device = device->next_device;
482 device = next_device;
486 DEVICE* VM::get_device(int id)
488 for(DEVICE* device = first_device; device; device = device->next_device) {
489 if(device->this_device_id == id) {
496 // ----------------------------------------------------------------------------
497 // drive virtual machine
498 // ----------------------------------------------------------------------------
503 for(DEVICE* device = first_device; device; device = device->next_device) {
506 pio->write_signal(SIG_I8255_PORT_B, 0x00, 0x08); // busy = low
507 psg->set_reg(0x2e, 0); // set prescaler
509 #if defined(OPEN_HARD_DISK_IN_RESET)
510 // open/close hard disk images
511 for(int drv = 0; drv < USE_HARD_DISK; drv++) {
512 if(hd_file_path[drv][0] != _T('\0')) {
513 open_hard_disk_tmp(drv, hd_file_path[drv]);
515 close_hard_disk_tmp(drv);
521 void VM::special_reset()
524 cpu->write_signal(SIG_CPU_NMI, 1, 1);
531 if(pce->is_cart_inserted()) {
537 double VM::get_frame_rate()
540 if(pce->is_cart_inserted()) {
541 return pceevent->get_frame_rate();
544 return event->get_frame_rate();
547 // ----------------------------------------------------------------------------
549 // ----------------------------------------------------------------------------
552 DEVICE *VM::get_cpu(int index)
556 } else if(index == 1) {
558 } else if(index == 2) {
561 } else if(index == 3 && pce->is_cart_inserted()) {
569 // ----------------------------------------------------------------------------
571 // ----------------------------------------------------------------------------
573 void VM::draw_screen()
575 display->draw_screen();
577 if(pce->is_cart_inserted()) {
583 // ----------------------------------------------------------------------------
585 // ----------------------------------------------------------------------------
587 void VM::initialize_sound(int rate, int samples)
589 // init sound manager
590 event->initialize_sound(rate, samples);
592 pceevent->initialize_sound(rate, samples);
596 if(sound_type >= 1) {
597 opm1->initialize_sound(rate, 4000000, samples, 0);
599 if(sound_type == 2) {
600 opm2->initialize_sound(rate, 4000000, samples, 0);
602 psg->initialize_sound(rate, 2000000, samples, 0, 0);
604 pce->initialize_sound(rate);
608 uint16_t* VM::create_sound(int* extra_frames)
611 if(pce->is_cart_inserted()) {
612 uint16_t* buffer = pceevent->create_sound(extra_frames);
613 for(int i = 0; i < *extra_frames; i++) {
619 return event->create_sound(extra_frames);
622 int VM::get_sound_buffer_ptr()
625 if(pce->is_cart_inserted()) {
626 return pceevent->get_sound_buffer_ptr();
629 return event->get_sound_buffer_ptr();
632 #ifdef USE_SOUND_VOLUME
633 void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
636 psg->set_volume(1, decibel_l, decibel_r);
638 if(sound_type >= 1) {
639 opm1->set_volume(0, decibel_l, decibel_r);
642 if(sound_type >= 2) {
643 opm2->set_volume(0, decibel_l, decibel_r);
646 drec->set_volume(0, decibel_l, decibel_r);
648 fdc->get_context_noise_seek()->set_volume(0, decibel_l, decibel_r);
649 fdc->get_context_noise_head_down()->set_volume(0, decibel_l, decibel_r);
650 fdc->get_context_noise_head_up()->set_volume(0, decibel_l, decibel_r);
652 drec->get_context_noise_play()->set_volume(0, decibel_l, decibel_r);
653 drec->get_context_noise_stop()->set_volume(0, decibel_l, decibel_r);
654 drec->get_context_noise_fast()->set_volume(0, decibel_l, decibel_r);
657 pce->set_volume(0, decibel_l, decibel_r);
663 // ----------------------------------------------------------------------------
665 // ----------------------------------------------------------------------------
667 void VM::key_down(int code, bool repeat)
670 if(!repeat && !pce->is_cart_inserted()) {
675 psub->key_down(code, false);
677 kbd->key_down(code, false);
682 void VM::key_up(int code)
685 if(!pce->is_cart_inserted()) {
697 bool VM::get_caps_locked()
700 if(!pce->is_cart_inserted()) {
703 return psub->get_caps_locked();
705 return kbd->get_caps_locked();
713 bool VM::get_kana_locked()
716 if(!pce->is_cart_inserted()) {
719 return psub->get_kana_locked();
721 return kbd->get_kana_locked();
729 // ----------------------------------------------------------------------------
731 // ----------------------------------------------------------------------------
733 void VM::open_floppy_disk(int drv, const _TCHAR* file_path, int bank)
735 fdc->open_disk(drv, file_path, bank);
738 void VM::close_floppy_disk(int drv)
740 fdc->close_disk(drv);
743 bool VM::is_floppy_disk_inserted(int drv)
745 return fdc->is_disk_inserted(drv);
748 void VM::is_floppy_disk_protected(int drv, bool value)
750 fdc->is_disk_protected(drv, value);
753 bool VM::is_floppy_disk_protected(int drv)
755 return fdc->is_disk_protected(drv);
758 uint32_t VM::is_floppy_disk_accessed()
760 return fdc->read_signal(0);
763 void VM::open_hard_disk(int drv, const _TCHAR* file_path)
765 if(drv < USE_HARD_DISK) {
766 #if defined(OPEN_HARD_DISK_IN_RESET)
767 my_tcscpy_s(hd_file_path[drv], _MAX_PATH, file_path);
769 open_hard_disk_tmp(drv, file_path);
774 void VM::close_hard_disk(int drv)
776 if(drv < USE_HARD_DISK) {
777 #if defined(OPEN_HARD_DISK_IN_RESET)
778 hd_file_path[drv][0] = _T('\0');
780 close_hard_disk_tmp(drv);
785 bool VM::is_hard_disk_inserted(int drv)
787 if(drv < USE_HARD_DISK) {
788 #if defined(OPEN_HARD_DISK_IN_RESET)
789 return (hd_file_path[drv][0] != _T('\0'));
791 return is_hard_disk_inserted_tmp(drv);
797 uint32_t VM::is_hard_disk_accessed()
801 for(int drv = 0; drv < USE_HARD_DISK; drv++) {
802 if(sasi_hdd[drv >> 1]->get_disk_handler(drv & 1)->accessed()) {
809 void VM::open_hard_disk_tmp(int drv, const _TCHAR* file_path)
811 if(drv < USE_HARD_DISK) {
812 sasi_hdd[drv >> 1]->get_disk_handler(drv & 1)->open(file_path);
816 void VM::close_hard_disk_tmp(int drv)
818 if(drv < USE_HARD_DISK) {
819 sasi_hdd[drv >> 1]->get_disk_handler(drv & 1)->close();
823 bool VM::is_hard_disk_inserted_tmp(int drv)
825 if(drv < USE_HARD_DISK) {
826 return sasi_hdd[drv >> 1]->get_disk_handler(drv & 1)->mounted();
831 void VM::play_tape(int drv, const _TCHAR* file_path)
833 bool value = drec->play_tape(file_path);
836 psub->play_tape(value);
839 sub->play_tape(value);
843 void VM::rec_tape(int drv, const _TCHAR* file_path)
845 bool value = drec->rec_tape(file_path);
848 psub->rec_tape(value);
851 sub->rec_tape(value);
855 void VM::close_tape(int drv)
867 bool VM::is_tape_inserted(int drv)
869 return drec->is_tape_inserted();
872 bool VM::is_tape_playing(int drv)
874 return drec->is_tape_playing();
877 bool VM::is_tape_recording(int drv)
879 return drec->is_tape_recording();
882 int VM::get_tape_position(int drv)
884 return drec->get_tape_position();
887 const _TCHAR* VM::get_tape_message(int drv)
889 return drec->get_message();
892 void VM::push_play(int drv)
895 drec->set_remote(true);
898 void VM::push_stop(int drv)
900 drec->set_remote(false);
903 void VM::push_fast_forward(int drv)
906 drec->set_remote(true);
909 void VM::push_fast_rewind(int drv)
911 drec->set_ff_rew(-1);
912 drec->set_remote(true);
915 void VM::push_apss_forward(int drv)
920 void VM::push_apss_rewind(int drv)
925 bool VM::is_frame_skippable()
928 if(pce->is_cart_inserted()) {
929 return pceevent->is_frame_skippable();
932 return event->is_frame_skippable();
936 void VM::open_cart(int drv, const _TCHAR* file_path)
939 pce->open_cart(file_path);
945 void VM::close_cart(int drv)
954 bool VM::is_cart_inserted(int drv)
957 return pce->is_cart_inserted();
964 void VM::update_config()
966 for(DEVICE* device = first_device; device; device = device->next_device) {
967 device->update_config();
969 #ifdef _X1TURBO_FEATURE
974 #ifdef _X1TURBO_FEATURE
975 void VM::update_dipswitch()
977 // bit0 0=High 1=Standard
978 // bit1-3 000=5"2D 001=5"2DD 010=5"2HD
979 io->set_iovalue_single_r(0x1ff0, (config.monitor_type & 1) | ((config.drive_type & 7) << 1));
983 #define STATE_VERSION 10
984 #include "../../statesub.h"
985 #include "../../qt/gui/csp_logger.h"
986 extern CSP_Logger DLL_PREFIX_I *csp_logger;
988 void VM::decl_state(void)
991 state_entry = new csp_state_utils(STATE_VERSION, 0, _T("CSP::X1_HEAD"), csp_logger);
992 #elif defined(_X1TURBO)
993 state_entry = new csp_state_utils(STATE_VERSION, 0, _T("CSP::X1_TURBO_HEAD"), csp_logger);
994 #elif defined(_X1TURBOZ)
995 state_entry = new csp_state_utils(STATE_VERSION, 0, _T("CSP::X1_TURBO_Z_HEAD"), csp_logger);
996 #elif defined(_X1TWIN)
997 state_entry = new csp_state_utils(STATE_VERSION, 0, _T("CSP::X1_TWIN_HEAD"), csp_logger);
999 state_entry = new csp_state_utils(STATE_VERSION, 0, _T("CSP::X1_SERIES_HEAD"), csp_logger);
1002 DECL_STATE_ENTRY_BOOL(pseudo_sub_cpu);
1003 DECL_STATE_ENTRY_INT32(sound_type);
1004 for(DEVICE* device = first_device; device; device = device->next_device) {
1005 device->decl_state();
1008 void VM::save_state(FILEIO* state_fio)
1010 if(state_entry != NULL) state_entry->save_state(state_fio);
1012 for(DEVICE* device = first_device; device; device = device->next_device) {
1013 device->save_state(state_fio);
1017 bool VM::load_state(FILEIO* state_fio)
1020 if(state_entry != NULL) {
1021 mb = state_entry->load_state(state_fio);
1023 if(!mb) return false;
1026 for(DEVICE* device = first_device; device; device = device->next_device) {
1027 if(!device->load_state(state_fio)) {
1028 printf("STATE ERROR at device #%d\n", n);
1033 #ifdef _X1TURBO_FEATURE