2 NEC PC-6001 Emulator 'yaPC-6001'
\r
3 NEC PC-6001mkII Emulator 'yaPC-6201'
\r
4 NEC PC-6001mkIISR Emulator 'yaPC-6401'
\r
5 NEC PC-6601 Emulator 'yaPC-6601'
\r
6 NEC PC-6601SR Emulator 'yaPC-6801'
\r
15 #include "../../emu.h"
\r
16 #include "../device.h"
\r
17 #include "../event.h"
\r
19 #include "../i8255.h"
\r
22 #include "../mc6847.h"
\r
23 #include "display.h"
\r
25 #include "../upd7752.h"
\r
27 #include "../pc6031.h"
\r
28 #include "../pc80s31k.h"
\r
29 #include "../upd765a.h"
\r
30 #include "../ym2203.h"
\r
33 #include "../datarec.h"
\r
34 #include "../mcs48.h"
\r
37 #include "../debugger.h"
\r
40 #if defined(_PC6601) || defined(_PC6601SR)
\r
43 #include "joystick.h"
\r
45 #include "printer.h"
\r
50 #include "../../fileio.h"
\r
52 // ----------------------------------------------------------------------------
\r
54 // ----------------------------------------------------------------------------
\r
56 VM::VM(EMU* parent_emu) : emu(parent_emu)
\r
58 support_pc80s31k = FILEIO::IsFileExists(emu->bios_path(_T("DISK.ROM")));
\r
60 support_sub_cpu = false;
\r
62 support_sub_cpu = FILEIO::IsFileExists(emu->bios_path(_T(SUB_CPU_ROM_FILE_NAME)));
\r
66 first_device = last_device = NULL;
\r
67 dummy = new DEVICE(this, emu); // must be 1st device
\r
68 event = new EVENT(this, emu); // must be 2nd device
\r
70 pio_sub = new I8255(this, emu);
\r
71 io = new IO(this, emu);
\r
72 psg = new YM2203(this, emu);
\r
73 cpu = new Z80(this, emu);
\r
75 #if defined(_PC6601) || defined(_PC6601SR)
\r
76 floppy = new FLOPPY(this, emu);
\r
78 joystick = new JOYSTICK(this, emu);
\r
79 memory = new MEMORY(this, emu);
\r
80 // printer = new PRINTER(this, emu);
\r
81 timer = new TIMER(this, emu);
\r
84 event->set_context_cpu(cpu);
\r
85 event->set_context_sound(psg);
\r
87 // pio_sub->set_context_port_b(printer, SIG_PRINTER_OUT, 0xff, 0);
\r
88 // pio_sub->set_context_port_c(printer, SIG_PRINTER_STB, 0x01, 0);
\r
89 pio_sub->set_context_port_c(memory, SIG_MEMORY_PIO_PORT_C, 0x06, 0); // CRTKILL,CGSWN
\r
92 display = new DISPLAY(this, emu);
\r
93 vdp = new MC6847(this, emu);
\r
94 display->set_context_vdp(vdp);
\r
95 display->set_vram_ptr(memory->get_vram());
\r
96 display->set_context_timer(timer);
\r
97 vdp->load_font_image(emu->bios_path(_T("CGROM60.60")));
\r
98 vdp->set_context_cpu(cpu);
\r
99 pio_sub->set_context_port_c(vdp, SIG_MC6847_ENABLE, 0x02, 0); // CRTKILL
\r
101 voice = new UPD7752(this, emu);
\r
102 event->set_context_sound(voice);
\r
103 memory->set_context_timer(timer);
\r
105 memory->set_context_cpu(cpu);
\r
106 joystick->set_context_psg(psg);
\r
108 timer->set_context_cpu(cpu);
\r
110 timer->set_context_memory(memory);
\r
112 if(support_sub_cpu) {
\r
113 cpu_sub = new MCS48(this, emu);
\r
114 sub = new SUB(this, emu);
\r
115 drec = new DATAREC(this, emu);
\r
116 event->set_context_cpu(cpu_sub, 8000000);
\r
117 cpu_sub->set_context_mem(new MCS48MEM(this, emu));
\r
118 cpu_sub->set_context_io(sub);
\r
119 #ifdef USE_DEBUGGER
\r
120 cpu_sub->set_context_debugger(new DEBUGGER(this, emu));
\r
122 sub->set_context_pio(pio_sub);
\r
123 sub->set_context_drec(drec);
\r
124 sub->set_context_timer(timer);
\r
125 pio_sub->set_context_port_c(cpu_sub, SIG_CPU_IRQ, 0x80, 0);
\r
126 drec->set_context_out(sub, SIG_SUB_DATAREC, 1);
\r
127 timer->set_context_sub(sub);
\r
129 psub = new PSUB(this, emu);
\r
130 psub->set_context_pio(pio_sub);
\r
131 psub->set_context_timer(timer);
\r
132 timer->set_context_sub(psub);
\r
135 if(support_pc80s31k) {
\r
136 pio_fdd = new I8255(this, emu);
\r
137 pio_pc80s31k = new I8255(this, emu);
\r
138 pc80s31k = new PC80S31K(this, emu);
\r
139 fdc_pc80s31k = new UPD765A(this, emu);
\r
140 cpu_pc80s31k = new Z80(this, emu);
\r
142 event->set_context_cpu(cpu_pc80s31k, 4000000);
\r
143 pc80s31k->set_context_cpu(cpu_pc80s31k);
\r
144 pc80s31k->set_context_fdc(fdc_pc80s31k);
\r
145 pc80s31k->set_context_pio(pio_pc80s31k);
\r
146 pio_fdd->set_context_port_a(pio_pc80s31k, SIG_I8255_PORT_A, 0xff, 0);
\r
147 pio_fdd->set_context_port_b(pio_pc80s31k, SIG_I8255_PORT_A, 0xff, 0);
\r
148 pio_fdd->set_context_port_c(pio_pc80s31k, SIG_I8255_PORT_C, 0x0f, 4);
\r
149 pio_fdd->set_context_port_c(pio_pc80s31k, SIG_I8255_PORT_C, 0xf0, -4);
\r
150 pio_fdd->clear_ports_by_cmdreg = true;
\r
151 pio_pc80s31k->set_context_port_a(pio_fdd, SIG_I8255_PORT_B, 0xff, 0);
\r
152 pio_pc80s31k->set_context_port_b(pio_fdd, SIG_I8255_PORT_A, 0xff, 0);
\r
153 pio_pc80s31k->set_context_port_c(pio_fdd, SIG_I8255_PORT_C, 0x0f, 4);
\r
154 pio_pc80s31k->set_context_port_c(pio_fdd, SIG_I8255_PORT_C, 0xf0, -4);
\r
155 pio_pc80s31k->clear_ports_by_cmdreg = true;
\r
156 fdc_pc80s31k->set_context_irq(cpu_pc80s31k, SIG_CPU_IRQ, 1);
\r
157 cpu_pc80s31k->set_context_mem(pc80s31k);
\r
158 cpu_pc80s31k->set_context_io(pc80s31k);
\r
159 cpu_pc80s31k->set_context_intr(pc80s31k);
\r
160 #ifdef USE_DEBUGGER
\r
161 cpu_pc80s31k->set_context_debugger(new DEBUGGER(this, emu));
\r
163 #if defined(_PC6601) || defined(_PC6601SR)
\r
164 floppy->set_context_ext(pio_fdd);
\r
167 pc6031 = new PC6031(this, emu);
\r
168 #if defined(_PC6601) || defined(_PC6601SR)
\r
169 floppy->set_context_ext(pc6031);
\r
171 cpu_pc80s31k = NULL;
\r
175 cpu->set_context_mem(memory);
\r
176 cpu->set_context_io(io);
\r
177 cpu->set_context_intr(timer);
\r
178 #ifdef USE_DEBUGGER
\r
179 cpu->set_context_debugger(new DEBUGGER(this, emu));
\r
183 if(support_sub_cpu) {
\r
184 io->set_iomap_range_rw(0x90, 0x93, sub);
\r
186 io->set_iomap_range_rw(0x90, 0x93, psub);
\r
188 io->set_iomap_alias_w(0xa0, psg, 0); // PSG ch
\r
189 io->set_iomap_alias_w(0xa1, psg, 1); // PSG data
\r
190 io->set_iomap_alias_r(0xa2, psg, 1); // PSG data
\r
191 #if defined(_PC6601SR) || defined(_PC6001MK2SR)
\r
192 io->set_iomap_alias_r(0xa3, psg, 0); // FM status
\r
193 io->set_iomap_range_rw(0x40, 0x6f, memory); // VRAM addr
\r
196 io->set_iomap_single_w(0xb0, display); // VRAM addr
\r
197 io->set_iomap_single_w(0x00, memory); // MEMORY MAP
\r
199 io->set_iomap_single_w(0xb0, memory); // VRAM addr
\r
200 io->set_iomap_range_rw(0xc0, 0xcf, memory); // VRAM addr
\r
201 io->set_iomap_range_rw(0xe0, 0xe3, voice); // VOICE
\r
202 #if defined(_PC6601) || defined(_PC6601SR)
\r
203 io->set_iomap_range_rw(0xb8, 0xbf, timer); // IRQ
\r
204 io->set_iomap_range_rw(0xfa, 0xfb, timer); // IRQ
\r
206 io->set_iomap_range_rw(0xf3, 0xf7, timer); // IRQ/Timer
\r
209 #if defined(_PC6601) || defined(_PC6601SR)
\r
210 io->set_iomap_range_rw(0xb1, 0xb3, floppy); // DISK DRIVE
\r
211 io->set_iomap_range_rw(0xb5, 0xb7, floppy); // DISK DRIVE (Mirror)
\r
212 io->set_iomap_range_rw(0xd0, 0xde, floppy); // DISK DRIVE
\r
214 io->set_iovalue_single_r(0xb1, 0x01);
\r
215 #if defined(_PC6601SR)
\r
216 io->set_iovalue_single_r(0xb2, 0x02);
\r
217 #elif defined(_PC6001MK2SR)
\r
218 io->set_iovalue_single_r(0xb2, 0x00);
\r
221 if(support_pc80s31k) {
\r
222 io->set_iomap_range_rw(0xd0, 0xd2, pio_fdd);
\r
223 io->set_iomap_single_w(0xd3, pio_fdd);
\r
225 io->set_iomap_range_rw(0xd0, 0xd3, pc6031);
\r
228 io->set_iomap_range_rw(0xf0, 0xf2, memory); // MEMORY MAP
\r
230 // initialize all devices
\r
231 for(DEVICE* device = first_device; device; device = device->next_device) {
\r
232 device->initialize();
\r
234 if(support_sub_cpu) {
\r
235 // load rom images after cpustate is allocated
\r
238 cpu_sub->load_rom_image(emu->bios_path(SUB_CPU_ROM_FILE_NAME));
\r
245 // delete all devices
\r
246 for(DEVICE* device = first_device; device;) {
\r
247 DEVICE *next_device = device->next_device;
\r
250 device = next_device;
\r
254 DEVICE* VM::get_device(int id)
\r
256 for(DEVICE* device = first_device; device; device = device->next_device) {
\r
257 if(device->this_device_id == id) {
\r
264 // ----------------------------------------------------------------------------
\r
265 // drive virtual machine
\r
266 // ----------------------------------------------------------------------------
\r
269 // reset all devices
\r
270 for(DEVICE* device = first_device; device; device = device->next_device) {
\r
273 if(support_pc80s31k) {
\r
274 pio_fdd->write_signal(SIG_I8255_PORT_C, 0, 0xff);
\r
275 pio_pc80s31k->write_signal(SIG_I8255_PORT_C, 0, 0xff);
\r
284 // ----------------------------------------------------------------------------
\r
286 // ----------------------------------------------------------------------------
\r
288 #ifdef USE_DEBUGGER
\r
289 DEVICE *VM::get_cpu(int index)
\r
293 } else if(index == 1) {
\r
295 } else if(index == 2) {
\r
296 return cpu_pc80s31k;
\r
302 // ----------------------------------------------------------------------------
\r
304 // ----------------------------------------------------------------------------
\r
306 void VM::draw_screen()
\r
309 display->draw_screen();
\r
311 memory->draw_screen();
\r
314 // ----------------------------------------------------------------------------
\r
316 // ----------------------------------------------------------------------------
\r
318 void VM::initialize_sound(int rate, int samples)
\r
320 // init sound manager
\r
321 event->initialize_sound(rate, samples);
\r
324 psg->init(rate, 4000000, samples, 0, 0);
\r
327 uint16* VM::create_sound(int* extra_frames)
\r
329 return event->create_sound(extra_frames);
\r
332 int VM::sound_buffer_ptr()
\r
334 return event->sound_buffer_ptr();
\r
337 // ----------------------------------------------------------------------------
\r
339 // ----------------------------------------------------------------------------
\r
341 void VM::open_cart(int drv, _TCHAR* file_path)
\r
344 memory->open_cart(file_path);
\r
349 void VM::close_cart(int drv)
\r
352 memory->close_cart();
\r
357 bool VM::cart_inserted(int drv)
\r
360 return memory->cart_inserted();
\r
366 int VM::access_lamp()
\r
368 uint32 status = 0; /// fdc->read_signal(0);
\r
369 #if defined(_PC6601) || defined(_PC6601SR)
\r
370 status = floppy->read_signal(0);
\r
372 if(support_pc80s31k) {
\r
373 status |= fdc_pc80s31k->read_signal(0);
\r
375 status |= pc6031->read_signal(0);
\r
380 void VM::open_disk(int drv, _TCHAR* file_path, int offset)
\r
382 #if defined(_PC6601) || defined(_PC6601SR)
\r
384 floppy->open_disk(drv, file_path, offset);
\r
390 if(support_pc80s31k) {
\r
391 fdc_pc80s31k->open_disk(drv, file_path, offset);
\r
393 pc6031->open_disk(drv, file_path, offset);
\r
397 void VM::close_disk(int drv)
\r
399 #if defined(_PC6601) || defined(_PC6601SR)
\r
401 floppy->close_disk(drv);
\r
407 if(support_pc80s31k) {
\r
408 fdc_pc80s31k->close_disk(drv);
\r
410 pc6031->close_disk(drv);
\r
414 bool VM::disk_inserted(int drv)
\r
416 #if defined(_PC6601) || defined(_PC6601SR)
\r
418 return floppy->disk_inserted(drv);
\r
423 if(support_pc80s31k) {
\r
424 return fdc_pc80s31k->disk_inserted(drv);
\r
426 return pc6031->disk_inserted(drv);
\r
430 void VM::play_tape(_TCHAR* file_path)
\r
432 if(support_sub_cpu) {
\r
433 // support both p6/p6t and wav
\r
434 drec->play_tape(file_path);
\r
436 // support only p6/p6t
\r
437 psub->play_tape(file_path);
\r
441 void VM::rec_tape(_TCHAR* file_path)
\r
443 if(support_sub_cpu) {
\r
444 // support both p6/p6t and wav
\r
445 sub->rec_tape(file_path); // temporary
\r
446 // drec->rec_tape(file_path);
\r
448 // support both p6/p6t and wav
\r
449 psub->rec_tape(file_path);
\r
453 void VM::close_tape()
\r
455 if(support_sub_cpu) {
\r
456 if(sub->tape_inserted()) {
\r
457 sub->close_tape(); // temporary
\r
459 drec->close_tape();
\r
462 psub->close_tape();
\r
466 bool VM::tape_inserted()
\r
468 if(support_sub_cpu) {
\r
469 return drec->tape_inserted() || sub->tape_inserted();
\r
471 return psub->tape_inserted();
\r
475 bool VM::now_skip()
\r
477 return event->now_skip();
\r
480 void VM::update_config()
\r
482 for(DEVICE* device = first_device; device; device = device->next_device) {
\r
483 device->update_config();
\r