2 NEC PC-6001 Emulator 'yaPC-6001'
3 NEC PC-6001mkII Emulator 'yaPC-6201'
4 NEC PC-6001mkIISR Emulator 'yaPC-6401'
5 NEC PC-6601 Emulator 'yaPC-6601'
6 NEC PC-6601SR Emulator 'yaPC-6801'
15 #include "../../emu.h"
16 #include "../device.h"
23 #include "../mc6847.h"
26 #include "../upd7752.h"
28 #include "../pc6031.h"
29 #include "../pc80s31k.h"
30 #include "../prnfile.h"
31 #include "../upd765a.h"
32 #include "../ym2203.h"
35 #include "../datarec.h"
39 #include "../debugger.h"
42 #if defined(_PC6601) || defined(_PC6601SR)
51 // ----------------------------------------------------------------------------
53 // ----------------------------------------------------------------------------
55 VM::VM(EMU* parent_emu) : emu(parent_emu)
57 support_pc80s31k = FILEIO::IsFileExists(create_local_path(_T("DISK.ROM")));
59 support_sub_cpu = false;
61 support_sub_cpu = FILEIO::IsFileExists(create_local_path(_T(SUB_CPU_ROM_FILE_NAME)));
65 first_device = last_device = NULL;
66 dummy = new DEVICE(this, emu); // must be 1st device
67 event = new EVENT(this, emu); // must be 2nd device
69 pio_sub = new I8255(this, emu);
70 io = new IO(this, emu);
71 psg = new YM2203(this, emu);
72 cpu = new Z80(this, emu);
74 if(config.printer_device_type == 0) {
75 printer = new PRNFILE(this, emu);
80 #if defined(_PC6601) || defined(_PC6601SR)
81 floppy = new FLOPPY(this, emu);
83 joystick = new JOYSTICK(this, emu);
84 memory = new MEMORY(this, emu);
85 timer = new TIMER(this, emu);
88 event->set_context_cpu(cpu);
89 event->set_context_sound(psg);
91 pio_sub->set_context_port_b(printer, SIG_PRINTER_DATA, 0xff, 0);
92 pio_sub->set_context_port_c(printer, SIG_PRINTER_STROBE, 0x01, 0);
93 pio_sub->set_context_port_c(memory, SIG_MEMORY_PIO_PORT_C, 0x06, 0); // CRTKILL,CGSWN
96 display = new DISPLAY(this, emu);
97 vdp = new MC6847(this, emu);
98 display->set_context_vdp(vdp);
99 display->set_vram_ptr(memory->get_vram());
100 display->set_context_timer(timer);
101 vdp->load_font_image(create_local_path(_T("CGROM60.60")));
102 vdp->set_context_cpu(cpu);
103 pio_sub->set_context_port_c(vdp, SIG_MC6847_ENABLE, 0x02, 0); // CRTKILL
105 voice = new UPD7752(this, emu);
106 event->set_context_sound(voice);
107 memory->set_context_timer(timer);
109 memory->set_context_cpu(cpu);
110 joystick->set_context_psg(psg);
112 timer->set_context_cpu(cpu);
114 timer->set_context_memory(memory);
116 if(support_sub_cpu) {
117 cpu_sub = new MCS48(this, emu);
118 sub = new SUB(this, emu);
119 drec = new DATAREC(this, emu);
120 event->set_context_cpu(cpu_sub, 8000000);
121 event->set_context_sound(drec);
122 cpu_sub->set_context_mem(new MCS48MEM(this, emu));
123 cpu_sub->set_context_io(sub);
125 cpu_sub->set_context_debugger(new DEBUGGER(this, emu));
127 //#ifdef DATAREC_SOUND
128 // event->set_context_sound(drec);
130 sub->set_context_pio(pio_sub);
131 sub->set_context_drec(drec);
132 sub->set_context_timer(timer);
133 pio_sub->set_context_port_c(cpu_sub, SIG_CPU_IRQ, 0x80, 0);
134 drec->set_context_ear(sub, SIG_SUB_DATAREC, 1);
135 timer->set_context_sub(sub);
137 psub = new PSUB(this, emu);
138 psub->set_context_pio(pio_sub);
139 psub->set_context_timer(timer);
140 timer->set_context_sub(psub);
143 if(support_pc80s31k) {
144 pio_fdd = new I8255(this, emu);
145 pio_pc80s31k = new I8255(this, emu);
146 pc80s31k = new PC80S31K(this, emu);
147 fdc_pc80s31k = new UPD765A(this, emu);
148 cpu_pc80s31k = new Z80(this, emu);
150 event->set_context_cpu(cpu_pc80s31k, 4000000);
151 pc80s31k->set_context_cpu(cpu_pc80s31k);
152 pc80s31k->set_context_fdc(fdc_pc80s31k);
153 pc80s31k->set_context_pio(pio_pc80s31k);
154 pio_fdd->set_context_port_a(pio_pc80s31k, SIG_I8255_PORT_B, 0xff, 0);
155 pio_fdd->set_context_port_b(pio_pc80s31k, SIG_I8255_PORT_A, 0xff, 0);
156 pio_fdd->set_context_port_c(pio_pc80s31k, SIG_I8255_PORT_C, 0x0f, 4);
157 pio_fdd->set_context_port_c(pio_pc80s31k, SIG_I8255_PORT_C, 0xf0, -4);
158 pio_fdd->clear_ports_by_cmdreg = true;
159 pio_pc80s31k->set_context_port_a(pio_fdd, SIG_I8255_PORT_B, 0xff, 0);
160 pio_pc80s31k->set_context_port_b(pio_fdd, SIG_I8255_PORT_A, 0xff, 0);
161 pio_pc80s31k->set_context_port_c(pio_fdd, SIG_I8255_PORT_C, 0x0f, 4);
162 pio_pc80s31k->set_context_port_c(pio_fdd, SIG_I8255_PORT_C, 0xf0, -4);
163 pio_pc80s31k->clear_ports_by_cmdreg = true;
164 fdc_pc80s31k->set_context_irq(cpu_pc80s31k, SIG_CPU_IRQ, 1);
165 cpu_pc80s31k->set_context_mem(pc80s31k);
166 cpu_pc80s31k->set_context_io(pc80s31k);
167 cpu_pc80s31k->set_context_intr(pc80s31k);
169 cpu_pc80s31k->set_context_debugger(new DEBUGGER(this, emu));
171 #if defined(_PC6601) || defined(_PC6601SR)
172 floppy->set_context_ext(pio_fdd);
175 pc6031 = new PC6031(this, emu);
176 #if defined(_PC6601) || defined(_PC6601SR)
177 floppy->set_context_ext(pc6031);
183 cpu->set_context_mem(memory);
184 cpu->set_context_io(io);
185 cpu->set_context_intr(timer);
187 cpu->set_context_debugger(new DEBUGGER(this, emu));
191 if(support_sub_cpu) {
192 io->set_iomap_range_rw(0x90, 0x93, sub);
194 io->set_iomap_range_rw(0x90, 0x93, psub);
196 io->set_iomap_alias_w(0xa0, psg, 0); // PSG ch
197 io->set_iomap_alias_w(0xa1, psg, 1); // PSG data
198 io->set_iomap_alias_r(0xa2, psg, 1); // PSG data
199 #if defined(_PC6601SR) || defined(_PC6001MK2SR)
200 io->set_iomap_alias_r(0xa3, psg, 0); // FM status
201 io->set_iomap_range_rw(0x40, 0x6f, memory); // VRAM addr
204 io->set_iomap_single_w(0xb0, display); // VRAM addr
205 io->set_iomap_single_w(0x00, memory); // MEMORY MAP
207 io->set_iomap_single_w(0xb0, memory); // VRAM addr
208 io->set_iomap_range_rw(0xc0, 0xcf, memory); // VRAM addr
209 io->set_iomap_range_rw(0xe0, 0xe3, voice); // VOICE
210 #if defined(_PC6601) || defined(_PC6601SR)
211 io->set_iomap_range_rw(0xb8, 0xbf, timer); // IRQ
212 io->set_iomap_range_rw(0xfa, 0xfb, timer); // IRQ
214 io->set_iomap_range_rw(0xf3, 0xf7, timer); // IRQ/Timer
217 #if defined(_PC6601) || defined(_PC6601SR)
218 io->set_iomap_range_rw(0xb1, 0xb3, floppy); // DISK DRIVE
219 io->set_iomap_range_rw(0xb5, 0xb7, floppy); // DISK DRIVE (Mirror)
220 io->set_iomap_range_rw(0xd0, 0xde, floppy); // DISK DRIVE
222 io->set_iovalue_single_r(0xb1, 0x01);
223 #if defined(_PC6601SR)
224 io->set_iovalue_single_r(0xb2, 0x02);
225 #elif defined(_PC6001MK2SR)
226 io->set_iovalue_single_r(0xb2, 0x00);
229 if(support_pc80s31k) {
230 io->set_iomap_range_rw(0xd0, 0xd2, pio_fdd);
231 io->set_iomap_single_w(0xd3, pio_fdd);
233 io->set_iomap_range_rw(0xd0, 0xd3, pc6031);
236 io->set_iomap_range_rw(0xf0, 0xf2, memory); // MEMORY MAP
238 // initialize all devices
239 for(DEVICE* device = first_device; device; device = device->next_device) {
240 device->initialize();
242 if(support_sub_cpu) {
243 // load rom images after cpustate is allocated
246 cpu_sub->load_rom_image(create_local_path(_T(SUB_CPU_ROM_FILE_NAME)));
250 #if defined(_PC6601) || defined(_PC6601SR)
251 floppy->get_disk_handler(0)->drive_num = drive_num++;
252 floppy->get_disk_handler(1)->drive_num = drive_num++;
254 if(support_pc80s31k) {
255 fdc_pc80s31k->get_disk_handler(0)->drive_num = drive_num++;
256 fdc_pc80s31k->get_disk_handler(1)->drive_num = drive_num++;
258 pc6031->get_disk_handler(0)->drive_num = drive_num++;
259 pc6031->get_disk_handler(1)->drive_num = drive_num++;
265 // delete all devices
266 for(DEVICE* device = first_device; device;) {
267 DEVICE *next_device = device->next_device;
270 device = next_device;
274 DEVICE* VM::get_device(int id)
276 for(DEVICE* device = first_device; device; device = device->next_device) {
277 if(device->this_device_id == id) {
284 // ----------------------------------------------------------------------------
285 // drive virtual machine
286 // ----------------------------------------------------------------------------
290 for(DEVICE* device = first_device; device; device = device->next_device) {
293 if(support_pc80s31k) {
294 pio_fdd->write_signal(SIG_I8255_PORT_C, 0, 0xff);
295 pio_pc80s31k->write_signal(SIG_I8255_PORT_C, 0, 0xff);
304 // ----------------------------------------------------------------------------
306 // ----------------------------------------------------------------------------
309 DEVICE *VM::get_cpu(int index)
313 } else if(index == 1) {
315 } else if(index == 2) {
322 // ----------------------------------------------------------------------------
324 // ----------------------------------------------------------------------------
326 void VM::draw_screen()
329 display->draw_screen();
331 memory->draw_screen();
334 // ----------------------------------------------------------------------------
336 // ----------------------------------------------------------------------------
338 void VM::initialize_sound(int rate, int samples)
340 // init sound manager
341 event->initialize_sound(rate, samples);
344 psg->init(rate, 4000000, samples, 0, 0);
350 uint16* VM::create_sound(int* extra_frames)
352 return event->create_sound(extra_frames);
355 int VM::sound_buffer_ptr()
357 return event->sound_buffer_ptr();
360 // ----------------------------------------------------------------------------
362 // ----------------------------------------------------------------------------
364 void VM::open_cart(int drv, const _TCHAR* file_path)
367 memory->open_cart(file_path);
372 void VM::close_cart(int drv)
375 memory->close_cart();
380 bool VM::cart_inserted(int drv)
383 return memory->cart_inserted();
389 int VM::access_lamp()
391 uint32 status = 0; /// fdc->read_signal(0);
392 #if defined(_PC6601) || defined(_PC6601SR)
393 status = floppy->read_signal(0);
395 if(support_pc80s31k) {
396 status |= fdc_pc80s31k->read_signal(0);
398 status |= pc6031->read_signal(0);
403 void VM::open_disk(int drv, const _TCHAR* file_path, int bank)
405 #if defined(_PC6601) || defined(_PC6601SR)
407 floppy->open_disk(drv, file_path, bank);
413 if(support_pc80s31k) {
414 fdc_pc80s31k->open_disk(drv, file_path, bank);
416 pc6031->open_disk(drv, file_path, bank);
420 void VM::close_disk(int drv)
422 #if defined(_PC6601) || defined(_PC6601SR)
424 floppy->close_disk(drv);
430 if(support_pc80s31k) {
431 fdc_pc80s31k->close_disk(drv);
433 pc6031->close_disk(drv);
437 bool VM::disk_inserted(int drv)
439 #if defined(_PC6601) || defined(_PC6601SR)
441 return floppy->disk_inserted(drv);
446 if(support_pc80s31k) {
447 return fdc_pc80s31k->disk_inserted(drv);
449 return pc6031->disk_inserted(drv);
453 void VM::set_disk_protected(int drv, bool value)
455 #if defined(_PC6601) || defined(_PC6601SR)
457 floppy->set_disk_protected(drv, value);
463 if(support_pc80s31k) {
464 fdc_pc80s31k->set_disk_protected(drv, value);
466 pc6031->set_disk_protected(drv, value);
470 bool VM::get_disk_protected(int drv)
472 #if defined(_PC6601) || defined(_PC6601SR)
474 return floppy->get_disk_protected(drv);
479 if(support_pc80s31k) {
480 return fdc_pc80s31k->get_disk_protected(drv);
482 return pc6031->get_disk_protected(drv);
486 void VM::play_tape(const _TCHAR* file_path)
488 if(support_sub_cpu) {
489 // support both p6/p6t and wav
490 drec->play_tape(file_path);
492 // support only p6/p6t
493 psub->play_tape(file_path);
497 void VM::rec_tape(const _TCHAR* file_path)
499 if(support_sub_cpu) {
500 // support both p6/p6t and wav
501 sub->rec_tape(file_path); // temporary
502 // drec->rec_tape(file_path);
504 // support both p6/p6t and wav
505 psub->rec_tape(file_path);
509 void VM::close_tape()
511 if(support_sub_cpu) {
512 if(sub->tape_inserted()) {
513 sub->close_tape(); // temporary
522 bool VM::tape_inserted()
524 if(support_sub_cpu) {
525 return drec->tape_inserted() || sub->tape_inserted();
527 return psub->tape_inserted();
531 bool VM::tape_playing()
533 if(support_sub_cpu) {
534 return drec->tape_playing();
540 bool VM::tape_recording()
542 if(support_sub_cpu) {
543 return drec->tape_recording();
549 int VM::tape_position()
551 if(support_sub_cpu) {
552 return drec->tape_position();
560 return event->now_skip();
563 void VM::update_config()
565 for(DEVICE* device = first_device; device; device = device->next_device) {
566 device->update_config();
570 #define STATE_VERSION 2
572 void VM::save_state(FILEIO* state_fio)
574 state_fio->FputUint32(STATE_VERSION);
576 for(DEVICE* device = first_device; device; device = device->next_device) {
577 device->save_state(state_fio);
579 state_fio->FputInt32(sr_mode);
582 bool VM::load_state(FILEIO* state_fio)
584 if(state_fio->FgetUint32() != STATE_VERSION) {
587 for(DEVICE* device = first_device; device; device = device->next_device) {
588 if(!device->load_state(state_fio)) {
592 sr_mode = state_fio->FgetInt32();