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"
22 #include "../mc6847.h"
25 #include "../upd7752.h"
27 #include "../pc6031.h"
28 #include "../pc80s31k.h"
29 #include "../upd765a.h"
30 #include "../ym2203.h"
33 #include "../datarec.h"
37 #include "../debugger.h"
40 #if defined(_PC6601) || defined(_PC6601SR)
50 // ----------------------------------------------------------------------------
52 // ----------------------------------------------------------------------------
54 VM::VM(EMU* parent_emu) : emu(parent_emu)
56 support_pc80s31k = FILEIO::IsFileExists(emu->bios_path(_T("DISK.ROM")));
58 support_sub_cpu = false;
60 support_sub_cpu = FILEIO::IsFileExists(emu->bios_path(_T(SUB_CPU_ROM_FILE_NAME)));
64 first_device = last_device = NULL;
65 dummy = new DEVICE(this, emu); // must be 1st device
66 event = new EVENT(this, emu); // must be 2nd device
68 pio_sub = new I8255(this, emu);
69 io = new IO(this, emu);
70 psg = new YM2203(this, emu);
71 cpu = new Z80(this, emu);
73 #if defined(_PC6601) || defined(_PC6601SR)
74 floppy = new FLOPPY(this, emu);
76 joystick = new JOYSTICK(this, emu);
77 memory = new MEMORY(this, emu);
78 // printer = new PRINTER(this, emu);
79 timer = new TIMER(this, emu);
82 event->set_context_cpu(cpu);
83 event->set_context_sound(psg);
85 // pio_sub->set_context_port_b(printer, SIG_PRINTER_OUT, 0xff, 0);
86 // pio_sub->set_context_port_c(printer, SIG_PRINTER_STB, 0x01, 0);
87 pio_sub->set_context_port_c(memory, SIG_MEMORY_PIO_PORT_C, 0x06, 0); // CRTKILL,CGSWN
90 display = new DISPLAY(this, emu);
91 vdp = new MC6847(this, emu);
92 display->set_context_vdp(vdp);
93 display->set_vram_ptr(memory->get_vram());
94 display->set_context_timer(timer);
95 vdp->load_font_image(emu->bios_path(_T("CGROM60.60")));
96 vdp->set_context_cpu(cpu);
97 pio_sub->set_context_port_c(vdp, SIG_MC6847_ENABLE, 0x02, 0); // CRTKILL
99 voice = new UPD7752(this, emu);
100 event->set_context_sound(voice);
101 memory->set_context_timer(timer);
103 memory->set_context_cpu(cpu);
104 joystick->set_context_psg(psg);
106 timer->set_context_cpu(cpu);
108 timer->set_context_memory(memory);
110 if(support_sub_cpu) {
111 cpu_sub = new MCS48(this, emu);
112 sub = new SUB(this, emu);
113 drec = new DATAREC(this, emu);
114 event->set_context_cpu(cpu_sub, 8000000);
115 event->set_context_sound(drec);
116 cpu_sub->set_context_mem(new MCS48MEM(this, emu));
117 cpu_sub->set_context_io(sub);
119 cpu_sub->set_context_debugger(new DEBUGGER(this, emu));
122 event->set_context_sound(drec);
124 sub->set_context_pio(pio_sub);
125 sub->set_context_drec(drec);
126 sub->set_context_timer(timer);
127 pio_sub->set_context_port_c(cpu_sub, SIG_CPU_IRQ, 0x80, 0);
128 drec->set_context_out(sub, SIG_SUB_DATAREC, 1);
129 timer->set_context_sub(sub);
131 psub = new PSUB(this, emu);
132 psub->set_context_pio(pio_sub);
133 psub->set_context_timer(timer);
134 timer->set_context_sub(psub);
137 if(support_pc80s31k) {
138 pio_fdd = new I8255(this, emu);
139 pio_pc80s31k = new I8255(this, emu);
140 pc80s31k = new PC80S31K(this, emu);
141 fdc_pc80s31k = new UPD765A(this, emu);
142 cpu_pc80s31k = new Z80(this, emu);
144 event->set_context_cpu(cpu_pc80s31k, 4000000);
145 pc80s31k->set_context_cpu(cpu_pc80s31k);
146 pc80s31k->set_context_fdc(fdc_pc80s31k);
147 pc80s31k->set_context_pio(pio_pc80s31k);
148 pio_fdd->set_context_port_a(pio_pc80s31k, SIG_I8255_PORT_A, 0xff, 0);
149 pio_fdd->set_context_port_b(pio_pc80s31k, SIG_I8255_PORT_A, 0xff, 0);
150 pio_fdd->set_context_port_c(pio_pc80s31k, SIG_I8255_PORT_C, 0x0f, 4);
151 pio_fdd->set_context_port_c(pio_pc80s31k, SIG_I8255_PORT_C, 0xf0, -4);
152 pio_fdd->clear_ports_by_cmdreg = true;
153 pio_pc80s31k->set_context_port_a(pio_fdd, SIG_I8255_PORT_B, 0xff, 0);
154 pio_pc80s31k->set_context_port_b(pio_fdd, SIG_I8255_PORT_A, 0xff, 0);
155 pio_pc80s31k->set_context_port_c(pio_fdd, SIG_I8255_PORT_C, 0x0f, 4);
156 pio_pc80s31k->set_context_port_c(pio_fdd, SIG_I8255_PORT_C, 0xf0, -4);
157 pio_pc80s31k->clear_ports_by_cmdreg = true;
158 fdc_pc80s31k->set_context_irq(cpu_pc80s31k, SIG_CPU_IRQ, 1);
159 cpu_pc80s31k->set_context_mem(pc80s31k);
160 cpu_pc80s31k->set_context_io(pc80s31k);
161 cpu_pc80s31k->set_context_intr(pc80s31k);
163 cpu_pc80s31k->set_context_debugger(new DEBUGGER(this, emu));
165 #if defined(_PC6601) || defined(_PC6601SR)
166 floppy->set_context_ext(pio_fdd);
169 pc6031 = new PC6031(this, emu);
170 #if defined(_PC6601) || defined(_PC6601SR)
171 floppy->set_context_ext(pc6031);
177 cpu->set_context_mem(memory);
178 cpu->set_context_io(io);
179 cpu->set_context_intr(timer);
181 cpu->set_context_debugger(new DEBUGGER(this, emu));
185 if(support_sub_cpu) {
186 io->set_iomap_range_rw(0x90, 0x93, sub);
188 io->set_iomap_range_rw(0x90, 0x93, psub);
190 io->set_iomap_alias_w(0xa0, psg, 0); // PSG ch
191 io->set_iomap_alias_w(0xa1, psg, 1); // PSG data
192 io->set_iomap_alias_r(0xa2, psg, 1); // PSG data
193 #if defined(_PC6601SR) || defined(_PC6001MK2SR)
194 io->set_iomap_alias_r(0xa3, psg, 0); // FM status
195 io->set_iomap_range_rw(0x40, 0x6f, memory); // VRAM addr
198 io->set_iomap_single_w(0xb0, display); // VRAM addr
199 io->set_iomap_single_w(0x00, memory); // MEMORY MAP
201 io->set_iomap_single_w(0xb0, memory); // VRAM addr
202 io->set_iomap_range_rw(0xc0, 0xcf, memory); // VRAM addr
203 io->set_iomap_range_rw(0xe0, 0xe3, voice); // VOICE
204 #if defined(_PC6601) || defined(_PC6601SR)
205 io->set_iomap_range_rw(0xb8, 0xbf, timer); // IRQ
206 io->set_iomap_range_rw(0xfa, 0xfb, timer); // IRQ
208 io->set_iomap_range_rw(0xf3, 0xf7, timer); // IRQ/Timer
211 #if defined(_PC6601) || defined(_PC6601SR)
212 io->set_iomap_range_rw(0xb1, 0xb3, floppy); // DISK DRIVE
213 io->set_iomap_range_rw(0xb5, 0xb7, floppy); // DISK DRIVE (Mirror)
214 io->set_iomap_range_rw(0xd0, 0xde, floppy); // DISK DRIVE
216 io->set_iovalue_single_r(0xb1, 0x01);
217 #if defined(_PC6601SR)
218 io->set_iovalue_single_r(0xb2, 0x02);
219 #elif defined(_PC6001MK2SR)
220 io->set_iovalue_single_r(0xb2, 0x00);
223 if(support_pc80s31k) {
224 io->set_iomap_range_rw(0xd0, 0xd2, pio_fdd);
225 io->set_iomap_single_w(0xd3, pio_fdd);
227 io->set_iomap_range_rw(0xd0, 0xd3, pc6031);
230 io->set_iomap_range_rw(0xf0, 0xf2, memory); // MEMORY MAP
232 // initialize all devices
233 for(DEVICE* device = first_device; device; device = device->next_device) {
234 device->initialize();
236 if(support_sub_cpu) {
237 // load rom images after cpustate is allocated
240 cpu_sub->load_rom_image(emu->bios_path(SUB_CPU_ROM_FILE_NAME));
247 // delete all devices
248 for(DEVICE* device = first_device; device;) {
249 DEVICE *next_device = device->next_device;
252 device = next_device;
256 DEVICE* VM::get_device(int id)
258 for(DEVICE* device = first_device; device; device = device->next_device) {
259 if(device->this_device_id == id) {
266 // ----------------------------------------------------------------------------
267 // drive virtual machine
268 // ----------------------------------------------------------------------------
272 for(DEVICE* device = first_device; device; device = device->next_device) {
275 if(support_pc80s31k) {
276 pio_fdd->write_signal(SIG_I8255_PORT_C, 0, 0xff);
277 pio_pc80s31k->write_signal(SIG_I8255_PORT_C, 0, 0xff);
286 // ----------------------------------------------------------------------------
288 // ----------------------------------------------------------------------------
291 DEVICE *VM::get_cpu(int index)
295 } else if(index == 1) {
297 } else if(index == 2) {
304 // ----------------------------------------------------------------------------
306 // ----------------------------------------------------------------------------
308 void VM::draw_screen()
311 display->draw_screen();
313 memory->draw_screen();
316 // ----------------------------------------------------------------------------
318 // ----------------------------------------------------------------------------
320 void VM::initialize_sound(int rate, int samples)
322 // init sound manager
323 event->initialize_sound(rate, samples);
326 psg->init(rate, 4000000, samples, 0, 0);
332 uint16* VM::create_sound(int* extra_frames)
334 return event->create_sound(extra_frames);
337 int VM::sound_buffer_ptr()
339 return event->sound_buffer_ptr();
342 // ----------------------------------------------------------------------------
344 // ----------------------------------------------------------------------------
346 void VM::open_cart(int drv, _TCHAR* file_path)
349 memory->open_cart(file_path);
354 void VM::close_cart(int drv)
357 memory->close_cart();
362 bool VM::cart_inserted(int drv)
365 return memory->cart_inserted();
371 int VM::access_lamp()
373 uint32 status = 0; /// fdc->read_signal(0);
374 #if defined(_PC6601) || defined(_PC6601SR)
375 status = floppy->read_signal(0);
377 if(support_pc80s31k) {
378 status |= fdc_pc80s31k->read_signal(0);
380 status |= pc6031->read_signal(0);
385 void VM::open_disk(int drv, _TCHAR* file_path, int bank)
387 #if defined(_PC6601) || defined(_PC6601SR)
389 floppy->open_disk(drv, file_path, bank);
395 if(support_pc80s31k) {
396 fdc_pc80s31k->open_disk(drv, file_path, bank);
398 pc6031->open_disk(drv, file_path, bank);
402 void VM::close_disk(int drv)
404 #if defined(_PC6601) || defined(_PC6601SR)
406 floppy->close_disk(drv);
412 if(support_pc80s31k) {
413 fdc_pc80s31k->close_disk(drv);
415 pc6031->close_disk(drv);
419 bool VM::disk_inserted(int drv)
421 #if defined(_PC6601) || defined(_PC6601SR)
423 return floppy->disk_inserted(drv);
428 if(support_pc80s31k) {
429 return fdc_pc80s31k->disk_inserted(drv);
431 return pc6031->disk_inserted(drv);
435 void VM::write_protect_fd(int drv, bool flag)
437 #if defined(_PC6601) || defined(_PC6601SR)
439 return floppy->write_protect_fd(drv, flag);
444 if(support_pc80s31k) {
445 return fdc_pc80s31k->write_protect_fd(drv, flag);
447 return pc6031->write_protect_fd(drv, flag);
451 bool VM::is_write_protect_fd(int drv)
453 #if defined(_PC6601) || defined(_PC6601SR)
455 return floppy->is_write_protect_fd(drv);
460 if(support_pc80s31k) {
461 return fdc_pc80s31k->is_write_protect_fd(drv);
463 return pc6031->is_write_protect_fd(drv);
469 void VM::play_tape(_TCHAR* file_path)
471 if(support_sub_cpu) {
472 // support both p6/p6t and wav
473 drec->play_tape(file_path);
475 // support only p6/p6t
476 psub->play_tape(file_path);
480 void VM::rec_tape(_TCHAR* file_path)
482 if(support_sub_cpu) {
483 // support both p6/p6t and wav
484 sub->rec_tape(file_path); // temporary
485 // drec->rec_tape(file_path);
487 // support both p6/p6t and wav
488 psub->rec_tape(file_path);
492 void VM::close_tape()
494 if(support_sub_cpu) {
495 if(sub->tape_inserted()) {
496 sub->close_tape(); // temporary
505 bool VM::tape_inserted()
507 if(support_sub_cpu) {
508 return drec->tape_inserted() || sub->tape_inserted();
510 return psub->tape_inserted();
514 int VM::get_tape_ptr()
516 if(support_sub_cpu) {
517 return drec->get_tape_ptr();
519 return psub->get_tape_ptr();
527 return event->now_skip();
530 void VM::update_config()
532 for(DEVICE* device = first_device; device; device = device->next_device) {
533 device->update_config();
537 #define STATE_VERSION 1
539 void VM::save_state(FILEIO* state_fio)
541 state_fio->FputUint32(STATE_VERSION);
543 for(DEVICE* device = first_device; device; device = device->next_device) {
544 device->save_state(state_fio);
546 state_fio->FputInt32(sr_mode);
549 bool VM::load_state(FILEIO* state_fio)
551 if(state_fio->FgetUint32() != STATE_VERSION) {
554 for(DEVICE* device = first_device; device; device = device->next_device) {
555 if(!device->load_state(state_fio)) {
559 sr_mode = state_fio->FgetInt32();