2 NEC PC-9801 Emulator 'ePC-9801'
\r
3 NEC PC-9801E/F/M Emulator 'ePC-9801E'
\r
4 NEC PC-98DO Emulator 'ePC-98DO'
\r
6 Author : Takeda.Toshiya
\r
13 #include "../../emu.h"
\r
14 #include "../device.h"
\r
15 #include "../event.h"
\r
17 #if defined(SUPPORT_OLD_BUZZER)
\r
18 #include "../beep.h"
\r
20 #include "../disk.h"
\r
21 #include "../i8237.h"
\r
22 #include "../i8251.h"
\r
23 #include "../i8253.h"
\r
24 #include "../i8255.h"
\r
25 #include "../i8259.h"
\r
26 #if defined(HAS_V30)
\r
29 #include "../i286.h"
\r
32 #include "../ls244.h"
\r
33 #include "../memory.h"
\r
34 #if defined(HAS_I86) || defined(HAS_V30)
\r
37 #if !defined(SUPPORT_OLD_BUZZER)
\r
38 #include "../pcm1bit.h"
\r
40 #include "../upd1990a.h"
\r
41 #include "../upd7220.h"
\r
42 #include "../upd765a.h"
\r
43 #include "../ym2203.h"
\r
46 #include "../debugger.h"
\r
49 #include "display.h"
\r
51 #include "fmsound.h"
\r
52 #include "joystick.h"
\r
53 #include "keyboard.h"
\r
55 #include "printer.h"
\r
57 #if defined(SUPPORT_320KB_FDD_IF)
\r
58 #include "../pc80s31k.h"
\r
61 #if defined(SUPPORT_CMT_IF)
\r
65 #if defined(_PC98DO)
\r
66 #include "../beep.h"
\r
67 #include "../pc80s31k.h"
\r
69 #include "../pc8801/pc88.h"
\r
72 #include "../../fileio.h"
\r
74 // ----------------------------------------------------------------------------
\r
76 // ----------------------------------------------------------------------------
\r
78 VM::VM(EMU* parent_emu) : emu(parent_emu)
\r
81 #if defined(_PC98DO)
\r
82 boot_mode = config.boot_mode;
\r
84 int cpu_clocks = CPU_CLOCKS;
\r
85 #if defined(PIT_CLOCK_8MHZ)
\r
86 pit_clock_8mhz = true;
\r
88 pit_clock_8mhz = false;
\r
90 #if defined(_PC9801E)
\r
91 if(config.cpu_type != 0) {
\r
93 cpu_clocks = 4992030;
\r
94 pit_clock_8mhz = false;
\r
96 #elif defined(_PC9801VM) || defined(_PC98DO)
\r
97 if(config.cpu_type != 0) {
\r
99 cpu_clocks = 7987248;
\r
100 pit_clock_8mhz = true;
\r
103 int pit_clocks = pit_clock_8mhz ? 1996812 : 2457600;
\r
106 first_device = last_device = NULL;
\r
107 dummy = new DEVICE(this, emu); // must be 1st device
\r
108 event = new EVENT(this, emu); // must be 2nd device
\r
110 #if defined(SUPPORT_OLD_BUZZER)
\r
111 beep = new BEEP(this, emu);
\r
113 beep = new PCM1BIT(this, emu);
\r
115 dma = new I8237(this, emu);
\r
116 #if defined(SUPPORT_CMT_IF)
\r
117 sio_cmt = new I8251(this, emu); // for cmt
\r
119 sio_rs = new I8251(this, emu); // for rs232c
\r
120 sio_kbd = new I8251(this, emu); // for keyboard
\r
121 pit = new I8253(this, emu);
\r
122 #if defined(SUPPORT_320KB_FDD_IF)
\r
123 pio_fdd = new I8255(this, emu); // for 320kb fdd i/f
\r
125 pio_mouse = new I8255(this, emu); // for mouse
\r
126 pio_sys = new I8255(this, emu); // for system port
\r
127 pio_prn = new I8255(this, emu); // for printer
\r
128 pic = new I8259(this, emu);
\r
129 #if defined(HAS_V30)
\r
130 cpu = new I86(this, emu);
\r
132 cpu = new I286(this, emu);
\r
134 io = new IO(this, emu);
\r
135 dmareg1 = new LS244(this, emu);
\r
136 dmareg2 = new LS244(this, emu);
\r
137 dmareg3 = new LS244(this, emu);
\r
138 dmareg0 = new LS244(this, emu);
\r
139 rtcreg = new LS244(this, emu);
\r
140 memory = new MEMORY(this, emu);
\r
141 #if defined(HAS_I86) || defined(HAS_V30)
\r
142 not = new NOT(this, emu);
\r
144 rtc = new UPD1990A(this, emu);
\r
145 #if defined(SUPPORT_2HD_FDD_IF)
\r
146 fdc_2hd = new UPD765A(this, emu);
\r
148 #if defined(SUPPORT_2DD_FDD_IF)
\r
149 fdc_2dd = new UPD765A(this, emu);
\r
151 #if defined(SUPPORT_2HD_2DD_FDD_IF)
\r
152 fdc = new UPD765A(this, emu);
\r
154 gdc_chr = new UPD7220(this, emu);
\r
155 gdc_gfx = new UPD7220(this, emu);
\r
156 opn = new YM2203(this, emu);
\r
158 #if defined(SUPPORT_CMT_IF)
\r
159 cmt = new CMT(this, emu);
\r
161 display = new DISPLAY(this, emu);
\r
162 floppy = new FLOPPY(this, emu);
\r
163 fmsound = new FMSOUND(this, emu);
\r
164 joystick = new JOYSTICK(this, emu);
\r
165 keyboard = new KEYBOARD(this, emu);
\r
166 mouse = new MOUSE(this, emu);
\r
167 printer = new PRINTER(this, emu);
\r
169 #if defined(SUPPORT_320KB_FDD_IF)
\r
170 // 320kb fdd drives
\r
171 pio_sub = new I8255(this, emu);
\r
172 pc80s31k = new PC80S31K(this, emu);
\r
173 fdc_sub = new UPD765A(this, emu);
\r
174 cpu_sub = new Z80(this, emu);
\r
196 event->set_context_cpu(cpu, cpu_clocks);
\r
197 #if defined(SUPPORT_320KB_FDD_IF)
\r
198 event->set_context_cpu(cpu_sub, 4000000);
\r
200 event->set_context_sound(beep);
\r
201 event->set_context_sound(opn);
\r
203 dma->set_context_memory(memory);
\r
205 // dma ch.1: memory refresh
\r
206 #if defined(SUPPORT_2HD_FDD_IF)
\r
207 dma->set_context_ch2(fdc_2hd);
\r
209 #if defined(SUPPORT_2DD_FDD_IF)
\r
210 dma->set_context_ch3(fdc_2dd);
\r
212 #if defined(SUPPORT_2HD_2DD_FDD_IF)
\r
213 dma->set_context_ch2(fdc);
\r
214 dma->set_context_ch3(fdc);
\r
216 // sio_rs->set_context_rxrdy(pic, SIG_I8259_CHIP0 | SIG_I8259_IR4, 1);
\r
217 sio_kbd->set_context_rxrdy(pic, SIG_I8259_CHIP0 | SIG_I8259_IR1, 1);
\r
218 pit->set_context_ch0(pic, SIG_I8259_CHIP0 | SIG_I8259_IR0, 1);
\r
219 #if defined(SUPPORT_OLD_BUZZER)
\r
220 // pit ch.1: memory refresh
\r
222 // pit ch.1: buzzer
\r
223 pit->set_context_ch1(beep, SIG_PCM1BIT_SIGNAL, 1);
\r
225 // pit ch.2: rs-232c
\r
226 pit->set_constant_clock(0, pit_clocks);
\r
227 pit->set_constant_clock(1, pit_clocks);
\r
228 pit->set_constant_clock(2, pit_clocks);
\r
229 pio_mouse->set_context_port_c(mouse, SIG_MOUSE_PORT_C, 0xf0, 0);
\r
230 // sysport port.c bit6: printer strobe
\r
231 #if defined(SUPPORT_OLD_BUZZER)
\r
232 pio_sys->set_context_port_c(beep, SIG_BEEP_MUTE, 8, 0);
\r
234 pio_sys->set_context_port_c(beep, SIG_PCM1BIT_MUTE, 8, 0);
\r
236 // sysport port.c bit2: enable txrdy interrupt
\r
237 // sysport port.c bit1: enable txempty interrupt
\r
238 // sysport port.c bit0: enable rxrdy interrupt
\r
239 pio_prn->set_context_port_a(printer, SIG_PRINTER_OUT, 0xff, 0);
\r
240 pio_prn->set_context_port_c(printer, SIG_PRINTER_STB, 0x80, 0);
\r
241 #if defined(HAS_I86) || defined(HAS_V30)
\r
242 pio_prn->set_context_port_c(not, SIG_NOT_INPUT, 8, 0);
\r
243 not->set_context_out(pic, SIG_I8259_CHIP1 | SIG_I8259_IR0, 1);
\r
245 dmareg1->set_context_output(dma, SIG_I8237_BANK1, 0x0f, 0);
\r
246 dmareg2->set_context_output(dma, SIG_I8237_BANK2, 0x0f, 0);
\r
247 dmareg3->set_context_output(dma, SIG_I8237_BANK3, 0x0f, 0);
\r
248 dmareg0->set_context_output(dma, SIG_I8237_BANK0, 0x0f, 0);
\r
249 rtcreg->set_context_output(rtc, SIG_UPD1990A_CMD, 0x07, 0);
\r
250 rtcreg->set_context_output(rtc, SIG_UPD1990A_DIN, 0x20, 0);
\r
251 rtcreg->set_context_output(rtc, SIG_UPD1990A_STB, 0x08, 0);
\r
252 rtcreg->set_context_output(rtc, SIG_UPD1990A_CLK, 0x10, 0);
\r
253 pic->set_context_cpu(cpu);
\r
254 rtc->set_context_dout(pio_sys, SIG_I8255_PORT_B, 1);
\r
255 opn->set_context_irq(pic, SIG_I8259_CHIP1 | SIG_I8259_IR4, 1);
\r
256 opn->set_context_port_b(joystick, SIG_JOYSTICK_SELECT, 0xc0, 0);
\r
258 display->set_context_pic(pic);
\r
259 display->set_context_gdc_chr(gdc_chr, gdc_chr->get_ra());
\r
260 display->set_context_gdc_gfx(gdc_gfx, gdc_gfx->get_ra(), gdc_gfx->get_cs());
\r
261 fmsound->set_context_opn(opn);
\r
262 joystick->set_context_opn(opn);
\r
263 keyboard->set_context_sio(sio_kbd);
\r
264 mouse->set_context_pic(pic);
\r
265 mouse->set_context_pio(pio_mouse);
\r
267 #if defined(SUPPORT_2HD_FDD_IF)
\r
268 fdc_2hd->set_context_irq(floppy, SIG_FLOPPY_2HD_IRQ, 1);
\r
269 fdc_2hd->set_context_drq(floppy, SIG_FLOPPY_2HD_DRQ, 1);
\r
270 fdc_2hd->raise_irq_when_media_changed = true;
\r
271 floppy->set_context_fdc_2hd(fdc_2hd);
\r
273 #if defined(SUPPORT_2DD_FDD_IF)
\r
274 fdc_2dd->set_context_irq(floppy, SIG_FLOPPY_2DD_IRQ, 1);
\r
275 fdc_2dd->set_context_drq(floppy, SIG_FLOPPY_2DD_DRQ, 1);
\r
276 fdc_2dd->raise_irq_when_media_changed = true;
\r
277 floppy->set_context_fdc_2dd(fdc_2dd);
\r
279 #if defined(SUPPORT_2HD_2DD_FDD_IF)
\r
280 fdc->set_context_irq(floppy, SIG_FLOPPY_IRQ, 1);
\r
281 fdc->set_context_drq(floppy, SIG_FLOPPY_DRQ, 1);
\r
282 fdc->raise_irq_when_media_changed = true;
\r
283 floppy->set_context_fdc(fdc);
\r
285 floppy->set_context_dma(dma);
\r
286 floppy->set_context_pic(pic);
\r
288 #if defined(SUPPORT_CMT_IF)
\r
289 sio_cmt->set_context_out(cmt, SIG_CMT_OUT);
\r
290 // sio_cmt->set_context_txrdy(cmt, SIG_CMT_TXRDY, 1);
\r
291 // sio_cmt->set_context_rxrdy(cmt, SIG_CMT_RXRDY, 1);
\r
292 // sio_cmt->set_context_txe(cmt, SIG_CMT_TXEMP, 1);
\r
293 cmt->set_context_sio(sio_cmt);
\r
297 cpu->set_context_mem(memory);
\r
298 cpu->set_context_io(io);
\r
299 cpu->set_context_intr(pic);
\r
300 #ifdef SINGLE_MODE_DMA
\r
301 cpu->set_context_dma(dma);
\r
303 #ifdef USE_DEBUGGER
\r
304 cpu->set_context_debugger(new DEBUGGER(this, emu));
\r
307 #if defined(SUPPORT_320KB_FDD_IF)
\r
308 // 320kb fdd drives
\r
309 pc80s31k->set_context_cpu(cpu_sub);
\r
310 pc80s31k->set_context_fdc(fdc_sub);
\r
311 pc80s31k->set_context_pio(pio_sub);
\r
312 pio_fdd->set_context_port_a(pio_sub, SIG_I8255_PORT_A, 0xff, 0);
\r
313 pio_fdd->set_context_port_b(pio_sub, SIG_I8255_PORT_A, 0xff, 0);
\r
314 pio_fdd->set_context_port_c(pio_sub, SIG_I8255_PORT_C, 0x0f, 4);
\r
315 pio_fdd->set_context_port_c(pio_sub, SIG_I8255_PORT_C, 0xf0, -4);
\r
316 pio_fdd->clear_ports_by_cmdreg = true;
\r
317 pio_sub->set_context_port_a(pio_fdd, SIG_I8255_PORT_B, 0xff, 0);
\r
318 pio_sub->set_context_port_b(pio_fdd, SIG_I8255_PORT_A, 0xff, 0);
\r
319 pio_sub->set_context_port_c(pio_fdd, SIG_I8255_PORT_C, 0x0f, 4);
\r
320 pio_sub->set_context_port_c(pio_fdd, SIG_I8255_PORT_C, 0xf0, -4);
\r
321 pio_sub->clear_ports_by_cmdreg = true;
\r
322 fdc_sub->set_context_irq(cpu_sub, SIG_CPU_IRQ, 1);
\r
323 cpu_sub->set_context_mem(pc80s31k);
\r
324 cpu_sub->set_context_io(pc80s31k);
\r
325 cpu_sub->set_context_intr(pc80s31k);
\r
326 #ifdef USE_DEBUGGER
\r
327 cpu_sub->set_context_debugger(new DEBUGGER(this, emu));
\r
332 memset(ram, 0, sizeof(ram));
\r
333 memset(ipl, 0xff, sizeof(ipl));
\r
334 memset(sound_bios, 0xff, sizeof(sound_bios));
\r
335 #if defined(_PC9801) || defined(_PC9801E)
\r
336 memset(fd_bios_2hd, 0xff, sizeof(fd_bios_2hd));
\r
337 memset(fd_bios_2dd, 0xff, sizeof(fd_bios_2dd));
\r
340 memory->read_bios(_T("IPL.ROM"), ipl, sizeof(ipl));
\r
341 int sound_bios_ok = memory->read_bios(_T("SOUND.ROM"), sound_bios, sizeof(sound_bios));
\r
342 #if defined(_PC9801) || defined(_PC9801E)
\r
343 memory->read_bios(_T("2HDIF.ROM"), fd_bios_2hd, sizeof(fd_bios_2hd));
\r
344 memory->read_bios(_T("2DDIF.ROM"), fd_bios_2dd, sizeof(fd_bios_2dd));
\r
347 memory->set_memory_rw(0x00000, 0x9ffff, ram);
\r
348 // A0000h - A1FFFh: TEXT VRAM
\r
349 // A2000h - A3FFFh: ATTRIBUTE
\r
350 memory->set_memory_mapped_io_rw(0xa0000, 0xa3fff, display);
\r
351 // A8000h - BFFFFh: VRAM
\r
352 memory->set_memory_mapped_io_rw(0xa8000, 0xbffff, display);
\r
353 memory->set_memory_r(0xcc000, 0xcffff, sound_bios);
\r
354 #if defined(_PC9801) || defined(_PC9801E)
\r
355 memory->set_memory_r(0xd6000, 0xd6fff, fd_bios_2dd);
\r
356 memory->set_memory_r(0xd7000, 0xd7fff, fd_bios_2hd);
\r
358 #if defined(SUPPORT_16_COLORS)
\r
359 // E0000h - E7FFFh: VRAM
\r
360 memory->set_memory_mapped_io_rw(0xe0000, 0xe7fff, display);
\r
362 memory->set_memory_r(0xe8000, 0xfffff, ipl);
\r
364 display->sound_bios_ok = (sound_bios_ok != 0); // memory switch
\r
367 io->set_iomap_alias_rw(0x00, pic, 0);
\r
368 io->set_iomap_alias_rw(0x02, pic, 1);
\r
369 io->set_iomap_alias_rw(0x08, pic, 2);
\r
370 io->set_iomap_alias_rw(0x0a, pic, 3);
\r
372 io->set_iomap_alias_rw(0x01, dma, 0x00);
\r
373 io->set_iomap_alias_rw(0x03, dma, 0x01);
\r
374 io->set_iomap_alias_rw(0x05, dma, 0x02);
\r
375 io->set_iomap_alias_rw(0x07, dma, 0x03);
\r
376 io->set_iomap_alias_rw(0x09, dma, 0x04);
\r
377 io->set_iomap_alias_rw(0x0b, dma, 0x05);
\r
378 io->set_iomap_alias_rw(0x0d, dma, 0x06);
\r
379 io->set_iomap_alias_rw(0x0f, dma, 0x07);
\r
380 io->set_iomap_alias_rw(0x11, dma, 0x08);
\r
381 io->set_iomap_alias_w(0x13, dma, 0x09);
\r
382 io->set_iomap_alias_w(0x15, dma, 0x0a);
\r
383 io->set_iomap_alias_w(0x17, dma, 0x0b);
\r
384 io->set_iomap_alias_w(0x19, dma, 0x0c);
\r
385 io->set_iomap_alias_rw(0x1b, dma, 0x0d);
\r
386 io->set_iomap_alias_w(0x1d, dma, 0x0e);
\r
387 io->set_iomap_alias_w(0x1f, dma, 0x0f);
\r
388 io->set_iomap_single_w(0x21, dmareg1);
\r
389 io->set_iomap_single_w(0x23, dmareg2);
\r
390 io->set_iomap_single_w(0x25, dmareg3);
\r
391 io->set_iomap_single_w(0x27, dmareg0);
\r
393 io->set_iomap_single_w(0x20, rtcreg);
\r
395 io->set_iomap_alias_rw(0x30, sio_rs, 0);
\r
396 io->set_iomap_alias_rw(0x32, sio_rs, 1);
\r
398 io->set_iomap_alias_rw(0x31, pio_sys, 0);
\r
399 io->set_iomap_alias_rw(0x33, pio_sys, 1);
\r
400 io->set_iomap_alias_rw(0x35, pio_sys, 2);
\r
401 io->set_iomap_alias_w(0x37, pio_sys, 3);
\r
403 io->set_iomap_alias_rw(0x40, pio_prn, 0);
\r
404 io->set_iomap_alias_rw(0x42, pio_prn, 1);
\r
405 io->set_iomap_alias_rw(0x44, pio_prn, 2);
\r
406 io->set_iomap_alias_w(0x46, pio_prn, 3);
\r
408 io->set_iomap_alias_rw(0x41, sio_kbd, 0);
\r
409 io->set_iomap_alias_rw(0x43, sio_kbd, 1);
\r
411 // 50h, 52h: NMI Flip Flop
\r
413 #if defined(SUPPORT_320KB_FDD_IF)
\r
414 io->set_iomap_alias_rw(0x51, pio_fdd, 0);
\r
415 io->set_iomap_alias_rw(0x53, pio_fdd, 1);
\r
416 io->set_iomap_alias_rw(0x55, pio_fdd, 2);
\r
417 io->set_iomap_alias_w(0x57, pio_fdd, 3);
\r
420 io->set_iomap_alias_rw(0x60, gdc_chr, 0);
\r
421 io->set_iomap_alias_rw(0x62, gdc_chr, 1);
\r
423 io->set_iomap_single_w(0x64, display);
\r
424 io->set_iomap_single_w(0x68, display);
\r
425 #if defined(SUPPORT_16_COLORS)
\r
426 io->set_iomap_single_w(0x6a, display);
\r
428 io->set_iomap_single_w(0x6c, display);
\r
429 io->set_iomap_single_w(0x6e, display);
\r
431 io->set_iomap_single_w(0x70, display);
\r
432 io->set_iomap_single_w(0x72, display);
\r
433 io->set_iomap_single_w(0x74, display);
\r
434 io->set_iomap_single_w(0x76, display);
\r
435 io->set_iomap_single_w(0x78, display);
\r
436 io->set_iomap_single_w(0x7a, display);
\r
437 #if defined(SUPPORT_16_COLORS)
\r
438 io->set_iomap_single_w(0x7c, display);
\r
439 io->set_iomap_single_w(0x7e, display);
\r
442 io->set_iomap_alias_rw(0x71, pit, 0);
\r
443 io->set_iomap_alias_rw(0x73, pit, 1);
\r
444 io->set_iomap_alias_rw(0x75, pit, 2);
\r
445 io->set_iomap_alias_w(0x77, pit, 3);
\r
449 io->set_iomap_single_rw(0x90, floppy);
\r
450 io->set_iomap_single_rw(0x92, floppy);
\r
451 io->set_iomap_single_rw(0x94, floppy);
\r
453 #if defined(SUPPORT_CMT_IF)
\r
454 io->set_iomap_alias_rw(0x91, sio_cmt, 0);
\r
455 io->set_iomap_alias_rw(0x93, sio_cmt, 1);
\r
456 io->set_iomap_single_w(0x95, cmt);
\r
457 io->set_iomap_single_w(0x97, cmt);
\r
460 io->set_iomap_alias_rw(0xa0, gdc_gfx, 0);
\r
461 io->set_iomap_alias_rw(0xa2, gdc_gfx, 1);
\r
463 #if defined(SUPPORT_2ND_VRAM)
\r
464 io->set_iomap_single_w(0xa4, display);
\r
465 io->set_iomap_single_w(0xa6, display);
\r
467 io->set_iomap_single_rw(0xa8, display);
\r
468 io->set_iomap_single_rw(0xaa, display);
\r
469 io->set_iomap_single_rw(0xac, display);
\r
470 io->set_iomap_single_rw(0xae, display);
\r
472 io->set_iomap_single_w(0xa1, display);
\r
473 io->set_iomap_single_w(0xa3, display);
\r
474 io->set_iomap_single_w(0xa5, display);
\r
475 io->set_iomap_single_rw(0xa9, display);
\r
477 #if defined(SUPPORT_2HD_2DD_FDD_IF)
\r
478 io->set_iomap_single_rw(0xbe, floppy);
\r
480 io->set_iomap_single_rw(0xc8, floppy);
\r
481 io->set_iomap_single_rw(0xca, floppy);
\r
482 io->set_iomap_single_rw(0xcc, floppy);
\r
484 io->set_iomap_single_rw(0x188, fmsound);
\r
485 io->set_iomap_single_rw(0x18a, fmsound);
\r
487 io->set_iomap_single_rw(0x18c, fmsound);
\r
488 io->set_iomap_single_rw(0x18e, fmsound);
\r
489 io->set_iomap_single_rw(0xa460, fmsound);
\r
492 #if !defined(SUPPORT_OLD_BUZZER)
\r
493 io->set_iomap_alias_rw(0x3fd9, pit, 0);
\r
494 io->set_iomap_alias_rw(0x3fdb, pit, 1);
\r
495 io->set_iomap_alias_rw(0x3fdd, pit, 2);
\r
496 io->set_iomap_alias_w(0x3fdf, pit, 3);
\r
499 io->set_iomap_alias_rw(0x7fd9, pio_mouse, 0);
\r
500 io->set_iomap_alias_rw(0x7fdb, pio_mouse, 1);
\r
501 io->set_iomap_alias_rw(0x7fdd, pio_mouse, 2);
\r
502 io->set_iomap_alias_w(0x7fdf, pio_mouse, 3);
\r
503 #if !(defined(_PC9801) || defined(_PC9801E))
\r
504 io->set_iomap_single_w(0xbfdb, mouse);
\r
507 #if defined(_PC98DO)
\r
508 pc88event = new EVENT(this, emu);
\r
509 pc88event->set_frames_per_sec(60);
\r
510 pc88event->set_lines_per_frame(260);
\r
512 pc88 = new PC88(this, emu);
\r
513 pc88->set_context_event_manager(pc88event);
\r
514 pc88beep = new BEEP(this, emu);
\r
515 pc88beep->set_context_event_manager(pc88event);
\r
516 pc88sio = new I8251(this, emu);
\r
517 pc88sio->set_context_event_manager(pc88event);
\r
518 pc88pio = new I8255(this, emu);
\r
519 pc88pio->set_context_event_manager(pc88event);
\r
520 pc88pcm = new PCM1BIT(this, emu);
\r
521 pc88pcm->set_context_event_manager(pc88event);
\r
522 pc88rtc = new UPD1990A(this, emu);
\r
523 pc88rtc->set_context_event_manager(pc88event);
\r
524 pc88opn = new YM2203(this, emu);
\r
525 pc88opn->set_context_event_manager(pc88event);
\r
526 pc88cpu = new Z80(this, emu);
\r
527 pc88cpu->set_context_event_manager(pc88event);
\r
529 pc88sub = new PC80S31K(this, emu);
\r
530 pc88sub->set_context_event_manager(pc88event);
\r
531 pc88pio_sub = new I8255(this, emu);
\r
532 pc88pio_sub->set_context_event_manager(pc88event);
\r
533 pc88fdc_sub = new UPD765A(this, emu);
\r
534 pc88fdc_sub->set_context_event_manager(pc88event);
\r
535 pc88cpu_sub = new Z80(this, emu);
\r
536 pc88cpu_sub->set_context_event_manager(pc88event);
\r
538 pc88event->set_context_cpu(pc88cpu, (config.cpu_type != 0) ? 3993624 : 7987248);
\r
539 pc88event->set_context_cpu(pc88cpu_sub, 3993624);
\r
540 pc88event->set_context_sound(pc88beep);
\r
541 pc88event->set_context_sound(pc88opn);
\r
542 pc88event->set_context_sound(pc88pcm);
\r
544 pc88->set_context_beep(pc88beep);
\r
545 pc88->set_context_cpu(pc88cpu);
\r
546 pc88->set_context_opn(pc88opn);
\r
547 pc88->set_context_pcm(pc88pcm);
\r
548 pc88->set_context_pio(pc88pio);
\r
549 pc88->set_context_rtc(pc88rtc);
\r
550 pc88->set_context_sio(pc88sio);
\r
551 pc88cpu->set_context_mem(pc88);
\r
552 pc88cpu->set_context_io(pc88);
\r
553 pc88cpu->set_context_intr(pc88);
\r
554 #ifdef USE_DEBUGGER
\r
555 pc88cpu->set_context_debugger(new DEBUGGER(this, emu));
\r
557 pc88opn->set_context_irq(pc88, SIG_PC88_SOUND_IRQ, 1);
\r
558 pc88sio->set_context_rxrdy(pc88, SIG_PC88_USART_IRQ, 1);
\r
559 pc88sio->set_context_out(pc88, SIG_PC88_USART_OUT);
\r
561 pc88sub->set_context_cpu(pc88cpu_sub);
\r
562 pc88sub->set_context_fdc(pc88fdc_sub);
\r
563 pc88sub->set_context_pio(pc88pio_sub);
\r
564 pc88pio->set_context_port_a(pc88pio_sub, SIG_I8255_PORT_B, 0xff, 0);
\r
565 pc88pio->set_context_port_b(pc88pio_sub, SIG_I8255_PORT_A, 0xff, 0);
\r
566 pc88pio->set_context_port_c(pc88pio_sub, SIG_I8255_PORT_C, 0x0f, 4);
\r
567 pc88pio->set_context_port_c(pc88pio_sub, SIG_I8255_PORT_C, 0xf0, -4);
\r
568 pc88pio->clear_ports_by_cmdreg = true;
\r
569 pc88pio_sub->set_context_port_a(pc88pio, SIG_I8255_PORT_B, 0xff, 0);
\r
570 pc88pio_sub->set_context_port_b(pc88pio, SIG_I8255_PORT_A, 0xff, 0);
\r
571 pc88pio_sub->set_context_port_c(pc88pio, SIG_I8255_PORT_C, 0x0f, 4);
\r
572 pc88pio_sub->set_context_port_c(pc88pio, SIG_I8255_PORT_C, 0xf0, -4);
\r
573 pc88pio_sub->clear_ports_by_cmdreg = true;
\r
574 pc88fdc_sub->set_context_irq(pc88cpu_sub, SIG_CPU_IRQ, 1);
\r
575 pc88cpu_sub->set_context_mem(pc88sub);
\r
576 pc88cpu_sub->set_context_io(pc88sub);
\r
577 pc88cpu_sub->set_context_intr(pc88sub);
\r
578 #ifdef USE_DEBUGGER
\r
579 pc88cpu_sub->set_context_debugger(new DEBUGGER(this, emu));
\r
583 // initialize all devices
\r
584 for(DEVICE* device = first_device; device; device = device->next_device) {
\r
585 device->initialize();
\r
591 // delete all devices
\r
592 for(DEVICE* device = first_device; device;) {
\r
593 DEVICE *next_device = device->next_device;
\r
596 device = next_device;
\r
600 DEVICE* VM::get_device(int id)
\r
602 for(DEVICE* device = first_device; device; device = device->next_device) {
\r
603 if(device->this_device_id == id) {
\r
610 // ----------------------------------------------------------------------------
\r
611 // drive virtual machine
\r
612 // ----------------------------------------------------------------------------
\r
616 // reset all devices
\r
617 for(DEVICE* device = first_device; device; device = device->next_device) {
\r
620 #if defined(_PC98DO)
\r
621 for(DEVICE* device = first_device; device; device = device->next_device) {
\r
626 // initial device settings
\r
627 pio_mouse->write_signal(SIG_I8255_PORT_A, 0xf0, 0xff); // clear mouse status
\r
628 pio_mouse->write_signal(SIG_I8255_PORT_B, 0x40, 0xff); // cpu high & sw3-6
\r
629 uint8 port_c = 0x08; // normal mode & sw1-5 & sw1-6
\r
630 #if defined(HAS_V30) || defined(HAS_V33)
\r
631 port_c |= 0x04; // V30
\r
633 pio_mouse->write_signal(SIG_I8255_PORT_C, 0x40, 0xff);
\r
635 pio_sys->write_signal(SIG_I8255_PORT_A, 0xe3, 0xff);
\r
636 pio_sys->write_signal(SIG_I8255_PORT_B, 0xf8, 0xff);//0xe8??
\r
638 #if defined(_PC9801)
\r
639 uint8 prn_b = 0x00; // system type = first PC-9801
\r
640 #elif defined(_PC9801U)
\r
641 uint8 prn_b = 0xc0; // system type = PC-9801U,PC-98LT,PC-98HA
\r
643 uint8 prn_b = 0x80; // system type = others
\r
645 if(pit_clock_8mhz) {
\r
646 prn_b |= 0x20; // system clock is 8MHz
\r
648 prn_b |= 0x10; // don't use LCD display
\r
649 #if !defined(SUPPORT_16_COLORS)
\r
650 prn_b |= 0x08; // standard graphics
\r
652 prn_b |= 0x04; // printer is not busy
\r
653 #if defined(HAS_V30) || defined(HAS_V33)
\r
656 #if defined(_PC9801VF) || defined(_PC9801U)
\r
657 prn_b |= 0x01; // PC-9801VF or PC-9801U
\r
659 pio_prn->write_signal(SIG_I8255_PORT_B, prn_b, 0xff);
\r
661 #if defined(SUPPORT_320KB_FDD_IF)
\r
662 pio_fdd->write_signal(SIG_I8255_PORT_A, 0xff, 0xff);
\r
663 pio_fdd->write_signal(SIG_I8255_PORT_B, 0xff, 0xff);
\r
664 pio_fdd->write_signal(SIG_I8255_PORT_C, 0xff, 0xff);
\r
666 #if defined(SUPPORT_2DD_FDD_IF)
\r
667 fdc_2dd->write_signal(SIG_UPD765A_FREADY, 1, 1); // 2DD FDC RDY is pulluped
\r
670 opn->write_signal(SIG_YM2203_PORT_A, 0xff, 0xff); // PC-9801-26(K) IRQ=12
\r
672 #if defined(SUPPORT_OLD_BUZZER)
\r
673 beep->write_signal(SIG_BEEP_ON, 1, 1);
\r
674 beep->write_signal(SIG_BEEP_MUTE, 1, 1);
\r
676 beep->write_signal(SIG_PCM1BIT_ON, 1, 1);
\r
677 beep->write_signal(SIG_PCM1BIT_MUTE, 1, 1);
\r
680 #if defined(_PC98DO)
\r
681 pc88opn->SetReg(0x29, 3); // for Misty Blue
\r
682 pc88pio->write_signal(SIG_I8255_PORT_C, 0, 0xff);
\r
683 pc88pio_sub->write_signal(SIG_I8255_PORT_C, 0, 0xff);
\r
689 #if defined(_PC98DO)
\r
690 if(boot_mode != 0) {
\r
691 pc88event->drive();
\r
697 double VM::frame_rate()
\r
699 #if defined(_PC98DO)
\r
700 if(config.boot_mode != 0) {
\r
701 return pc88event->frame_rate();
\r
704 return event->frame_rate();
\r
707 // ----------------------------------------------------------------------------
\r
709 // ----------------------------------------------------------------------------
\r
711 #ifdef USE_DEBUGGER
\r
712 DEVICE *VM::get_cpu(int index)
\r
714 #if defined(_PC98DO)
\r
715 if(index == 0 && boot_mode == 0) {
\r
717 } else if(index == 1 && boot_mode != 0) {
\r
719 } else if(index == 2 && boot_mode != 0) {
\r
720 return pc88cpu_sub;
\r
725 #if defined(SUPPORT_320KB_FDD_IF)
\r
726 } else if(index == 1) {
\r
735 // ----------------------------------------------------------------------------
\r
737 // ----------------------------------------------------------------------------
\r
739 void VM::draw_screen()
\r
741 #if defined(_PC98DO)
\r
742 if(boot_mode != 0) {
\r
743 pc88->draw_screen();
\r
746 display->draw_screen();
\r
749 int VM::access_lamp()
\r
751 #if defined(_PC9801) || defined(_PC9801E)
\r
752 return (fdc_2hd->read_signal(0) & 3) | (fdc_2dd->read_signal(0) & 3) | (fdc_sub->read_signal(0) & 3);
\r
753 #elif defined(_PC9801VF) || defined(_PC9801U)
\r
754 return fdc_2dd->read_signal(0);
\r
755 #elif defined(_PC98DO)
\r
756 if(boot_mode != 0) {
\r
757 return pc88fdc_sub->read_signal(0);
\r
759 return fdc->read_signal(0);
\r
762 return fdc->read_signal(0);
\r
766 // ----------------------------------------------------------------------------
\r
768 // ----------------------------------------------------------------------------
\r
770 void VM::initialize_sound(int rate, int samples)
\r
772 // init sound manager
\r
773 event->initialize_sound(rate, samples);
\r
776 #if defined(SUPPORT_OLD_BUZZER)
\r
777 beep->init(rate, 2400, 8000);
\r
779 beep->init(rate, 8000);
\r
782 opn->init(rate, 7987248, samples, 0, 0);
\r
784 opn->init(rate, 3993624, samples, 0, 0);
\r
787 #if defined(_PC98DO)
\r
788 // init sound manager
\r
789 pc88event->initialize_sound(rate, samples);
\r
792 pc88beep->init(rate, 2400, 8000);
\r
794 pc88opn->init(rate, 7987248, samples, 0, 0);
\r
796 pc88opn->init(rate, 3993624, samples, 0, 0);
\r
798 pc88pcm->init(rate, 8000);
\r
802 uint16* VM::create_sound(int* extra_frames)
\r
804 #if defined(_PC98DO)
\r
805 if(boot_mode != 0) {
\r
806 return pc88event->create_sound(extra_frames);
\r
809 return event->create_sound(extra_frames);
\r
812 int VM::sound_buffer_ptr()
\r
814 #if defined(_PC98DO)
\r
815 if(boot_mode != 0) {
\r
816 return pc88event->sound_buffer_ptr();
\r
819 return event->sound_buffer_ptr();
\r
822 // ----------------------------------------------------------------------------
\r
824 // ----------------------------------------------------------------------------
\r
826 void VM::key_down(int code, bool repeat)
\r
828 #if defined(_PC98DO)
\r
829 if(boot_mode != 0) {
\r
830 pc88->key_down(code, repeat);
\r
833 keyboard->key_down(code, repeat);
\r
836 void VM::key_up(int code)
\r
838 #if defined(_PC98DO)
\r
839 if(boot_mode != 0) {
\r
840 // pc88->key_up(code);
\r
843 keyboard->key_up(code);
\r
846 // ----------------------------------------------------------------------------
\r
848 // ----------------------------------------------------------------------------
\r
850 void VM::open_disk(int drv, _TCHAR* file_path, int offset)
\r
852 #if defined(_PC9801) || defined(_PC9801E)
\r
853 if(drv == 0 || drv == 1) {
\r
854 fdc_2hd->open_disk(drv, file_path, offset);
\r
855 } else if(drv == 2 || drv == 3) {
\r
856 fdc_2dd->open_disk(drv - 2, file_path, offset);
\r
857 } else if(drv == 4 || drv == 5) {
\r
858 fdc_sub->open_disk(drv - 4, file_path, offset);
\r
860 #elif defined(_PC9801VF) || defined(_PC9801U)
\r
861 if(drv == 0 || drv == 1) {
\r
862 fdc_2dd->open_disk(drv, file_path, offset);
\r
864 #elif defined(_PC98DO)
\r
865 if(drv == 0 || drv == 1) {
\r
866 fdc->open_disk(drv, file_path, offset);
\r
867 } else if(drv == 2 || drv == 3) {
\r
868 pc88fdc_sub->open_disk(drv - 2, file_path, offset);
\r
871 if(drv == 0 || drv == 1) {
\r
872 fdc->open_disk(drv, file_path, offset);
\r
877 void VM::close_disk(int drv)
\r
879 #if defined(_PC9801) || defined(_PC9801E)
\r
880 if(drv == 0 || drv == 1) {
\r
881 fdc_2hd->close_disk(drv);
\r
882 } else if(drv == 2 || drv == 3) {
\r
883 fdc_2dd->close_disk(drv - 2);
\r
884 } else if(drv == 4 || drv == 5) {
\r
885 fdc_sub->close_disk(drv - 4);
\r
887 #elif defined(_PC9801VF) || defined(_PC9801U)
\r
888 if(drv == 0 || drv == 1) {
\r
889 fdc_2dd->close_disk(drv);
\r
891 #elif defined(_PC98DO)
\r
892 if(drv == 0 || drv == 1) {
\r
893 fdc->close_disk(drv);
\r
894 } else if(drv == 2 || drv == 3) {
\r
895 pc88fdc_sub->close_disk(drv - 2);
\r
898 if(drv == 0 || drv == 1) {
\r
899 fdc->close_disk(drv);
\r
904 bool VM::disk_inserted(int drv)
\r
906 #if defined(_PC9801) || defined(_PC9801E)
\r
907 if(drv == 0 || drv == 1) {
\r
908 return fdc_2hd->disk_inserted(drv);
\r
909 } else if(drv == 2 || drv == 3) {
\r
910 return fdc_2dd->disk_inserted(drv - 2);
\r
911 } else if(drv == 4 || drv == 5) {
\r
912 return fdc_sub->disk_inserted(drv - 4);
\r
914 #elif defined(_PC9801VF) || defined(_PC9801U)
\r
915 if(drv == 0 || drv == 1) {
\r
916 return fdc_2dd->disk_inserted(drv);
\r
918 #elif defined(_PC98DO)
\r
919 if(drv == 0 || drv == 1) {
\r
920 return fdc->disk_inserted(drv);
\r
921 } else if(drv == 2 || drv == 3) {
\r
922 return pc88fdc_sub->disk_inserted(drv - 2);
\r
925 if(drv == 0 || drv == 1) {
\r
926 return fdc->disk_inserted(drv);
\r
932 #if defined(SUPPORT_CMT_IF) || defined(_PC98DO)
\r
933 void VM::play_tape(_TCHAR* file_path)
\r
935 #if defined(_PC98DO)
\r
936 pc88->play_tape(file_path);
\r
938 cmt->play_tape(file_path);
\r
942 void VM::rec_tape(_TCHAR* file_path)
\r
944 #if defined(_PC98DO)
\r
945 pc88->rec_tape(file_path);
\r
947 cmt->rec_tape(file_path);
\r
951 void VM::close_tape()
\r
953 #if defined(_PC98DO)
\r
954 pc88->close_tape();
\r
960 bool VM::tape_inserted()
\r
962 #if defined(_PC98DO)
\r
963 return pc88->tape_inserted();
\r
965 return cmt->tape_inserted();
\r
970 bool VM::now_skip()
\r
972 #if defined(_PC98DO)
\r
973 if(boot_mode != 0) {
\r
974 // return pc88event->now_skip();
\r
975 return pc88->now_skip();
\r
978 return event->now_skip();
\r
981 void VM::update_config()
\r
983 #if defined(_PC98DO)
\r
984 if(boot_mode != config.boot_mode) {
\r
985 // boot mode is changed !!!
\r
986 boot_mode = config.boot_mode;
\r
990 for(DEVICE* device = first_device; device; device = device->next_device) {
\r
991 device->update_config();
\r
995 #define STATE_VERSION 1
\r
997 void VM::save_state(FILEIO* state_fio)
\r
999 state_fio->FputUint32(STATE_VERSION);
\r
1001 for(DEVICE* device = first_device; device; device = device->next_device) {
\r
1002 device->save_state(state_fio);
\r
1004 state_fio->Fwrite(ram, sizeof(ram), 1);
\r
1005 state_fio->FputBool(pit_clock_8mhz);
\r
1006 #if defined(_PC98DO)
\r
1007 state_fio->FputInt32(boot_mode);
\r
1011 bool VM::load_state(FILEIO* state_fio)
\r
1013 if(state_fio->FgetUint32() != STATE_VERSION) {
\r
1016 for(DEVICE* device = first_device; device; device = device->next_device) {
\r
1017 if(!device->load_state(state_fio)) {
\r
1021 state_fio->Fread(ram, sizeof(ram), 1);
\r
1022 pit_clock_8mhz = state_fio->FgetBool();
\r
1023 #if defined(_PC98DO)
\r
1024 boot_mode = state_fio->FgetInt32();
\r