2 Common Source Code Project
3 MSX Series (experimental)
5 Origin : src/vm/msx/msx.cpp
16 #include "../../emu.h"
17 #include "../device.h"
20 #include "../datarec.h"
28 //#include "../ym2203.h"
29 #include "../ay_3_891x.h"
30 #include "../pcm1bit.h"
31 #if !defined(_MSX1_VARIANTS)
32 #include "../rp5c01.h"
33 #if defined(_MSX_VDP_MESS)
39 #include "../tms9918a.h"
44 #include "../debugger.h"
49 #include "memory_ex.h"
50 #if !defined(_MSX1_VARIANTS)
54 #include "sound_cart.h"
57 //#include "../pcpr201.h"
58 #include "../prnfile.h"
61 #include "../mz1p17.h"
64 #include "../ym2413.h"
66 #if defined(MSX_PSG_STEREO)
67 #include "psg_stereo.h"
73 #if !defined(_MSX1_VARIANTS)
76 using MSX::SLOT_MAINROM;
78 using MSX::SOUND_CART;
80 #if defined(MSX_PSG_STEREO)
81 using MSX::PSG_STEREO;
89 #if defined(MAPPERRAM_SLOT)
90 using MSX::SLOT_MAPPERRAM;
92 #if defined(RAM64K_SLOT)
93 using MSX::SLOT_RAM64K;
95 #if defined(SUBROM_SLOT)
96 using MSX::SLOT_SUBROM;
98 #if defined(FIRMWARE32K1_SLOT)
99 using MSX::SLOT_FIRMWARE32K;
101 #if defined(FIRMWARE32K2_SLOT)
102 using MSX::SLOT_FIRMWARE32K;
104 #if defined(FDD_PATCH_SLOT)
105 using MSX::SLOT_FDD_PATCH;
107 #if defined(MSXDOS2_SLOT)
108 using MSX::SLOT_MSXDOS2;
110 #if defined(MSXMUSIC_SLOT)
111 using MSX::SLOT_MSXMUSIC;
116 class PORT_F4 : public DEVICE
122 PORT_F4(VM_TEMPLATE* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu) {
128 void __FASTCALL write_io8(uint32_t addr, uint32_t data) {
131 uint32_t __FASTCALL read_io8(uint32_t addr) {
140 // ----------------------------------------------------------------------------
142 // ----------------------------------------------------------------------------
144 VM::VM(EMU* parent_emu) : VM_TEMPLATE(parent_emu)
147 first_device = last_device = NULL;
148 dummy = new DEVICE(this, emu); // must be 1st device
149 event = new EVENT(this, emu); // must be 2nd device
151 drec = new DATAREC(this, emu);
152 drec->set_context_noise_play(new NOISE(this, emu));
153 drec->set_context_noise_stop(new NOISE(this, emu));
154 drec->set_context_noise_fast(new NOISE(this, emu));
155 pio = new I8255(this, emu);
156 io = new IO(this, emu);
157 #if defined(LDC_SLOT)
158 ldp = new LD700(this, emu);
160 not_remote = new NOT(this, emu);
161 psg = new AY_3_891X(this, emu);
163 psg->set_context_debugger(new DEBUGGER(this, emu));
165 pcm = new PCM1BIT(this, emu);
167 // pcm->set_context_debugger(new DEBUGGER(this, emu));
169 #if !defined(_MSX1_VARIANTS)
170 rtc = new RP5C01(this, emu);
171 vdp = new V99X8(this, emu);
173 vdp = new TMS9918A(this, emu);
175 vdp->set_context_debugger(new DEBUGGER(this, emu));
178 cpu = new Z80(this, emu);
180 joystick = new JOYSTICK(this, emu);
181 keyboard = new KEYBOARD(this, emu);
182 memory = new MEMORY_EX(this, emu);
183 #if !defined(_MSX1_VARIANTS)
184 rtcif = new RTCIF(this, emu);
186 // slot0 = new SLOT0(this, emu); // #0: main memory
187 // slot1 = new SLOT1(this, emu); // #1: rom-cartridge or msx-dos
188 // slot2 = new SLOT2(this, emu); // #2: fdd-cartridge or p-basic
189 // slot3 = new SLOT3(this, emu); // #3: rom-cartridge or ram-cartridge
190 slot_mainrom = new SLOT_MAINROM(this, emu);
191 slot_cart[0] = new SLOT_CART(this, emu);
192 slot_cart[1] = new SLOT_CART(this, emu);
193 sound_cart[0] = new SOUND_CART(this, emu);
194 sound_cart[1] = new SOUND_CART(this, emu);
195 kanjirom = new KANJIROM(this, emu);
197 printer = new PRINTER(this, emu);
199 #if defined(LDC_SLOT)
200 slot_ldc = new SLOT_LDC(this, emu);
202 #if defined(MAPPERRAM_SLOT)
203 slot_ram = new SLOT_MAPPERRAM(this, emu);
205 #if defined(RAM64K_SLOT)
206 slot_ram = new SLOT_RAM64K(this, emu);
208 #if defined(SUBROM_SLOT)
209 slot_subrom = new SLOT_SUBROM(this, emu);
211 #if defined(FIRMWARE32K1_SLOT)
212 slot_firmware32k1 = new SLOT_FIRMWARE32K(this, emu);
214 #if defined(FIRMWARE32K2_SLOT)
215 slot_firmware32k2 = new SLOT_FIRMWARE32K(this, emu);
217 #if defined(FDD_PATCH_SLOT)
218 slot_fdd_patch = new SLOT_FDD_PATCH(this, emu);
220 #if defined(MSXDOS2_SLOT)
221 slot_msxdos2 = new SLOT_MSXDOS2(this, emu);
223 ym2413 = new YM2413(this, emu);
224 #if defined(MSXMUSIC_SLOT)
225 slot_msxmusic = new SLOT_MSXMUSIC(this, emu);
227 #if defined(MSX_PSG_STEREO)
228 psg_stereo = new PSG_STEREO(this, emu);
232 event->set_context_cpu(cpu);
233 #if defined(MSX_PSG_STEREO)
234 event->set_context_sound(psg_stereo);
236 event->set_context_sound(psg);
238 event->set_context_sound(pcm);
239 event->set_context_sound(drec);
240 #if defined(LDC_SLOT)
241 event->set_context_sound(ldp);
243 event->set_context_sound(ym2413);
244 event->set_context_sound(sound_cart[0]);
245 event->set_context_sound(sound_cart[1]);
246 event->set_context_sound(drec->get_context_noise_play());
247 event->set_context_sound(drec->get_context_noise_stop());
248 event->set_context_sound(drec->get_context_noise_fast());
249 slot_cart[0]->set_context_sound(sound_cart[0]);
250 slot_cart[1]->set_context_sound(sound_cart[1]);
252 drec->set_context_ear(psg, SIG_AY_3_891X_PORT_A, 0x80);
253 pio->set_context_port_a(memory, SIG_MEMORY_SEL, 0xff, 0);
254 pio->set_context_port_c(keyboard, SIG_KEYBOARD_COLUMN, 0x0f, 0);
255 pio->set_context_port_c(not_remote, SIG_NOT_INPUT, 0x10, 0);
256 not_remote->set_context_out(drec, SIG_DATAREC_REMOTE, 1);
257 pio->set_context_port_c(drec, SIG_DATAREC_MIC, 0x20, 0);
258 pio->set_context_port_c(pcm, SIG_PCM1BIT_SIGNAL, 0x80, 0);
259 psg->set_context_port_b(joystick, SIG_JOYSTICK_SEL, 0x40, 0);
260 vdp->set_context_irq(cpu, SIG_CPU_IRQ, 1);
261 #if defined(LDC_SLOT)
262 pio->set_context_port_c(slot_ldc, SIG_LDC_MUTE, 0x10, 0);
263 ldp->set_context_exv(slot_ldc, SIG_LDC_EXV, 1);
264 ldp->set_context_ack(slot_ldc, SIG_LDC_ACK, 1);
265 ldp->set_context_sound(psg, SIG_AY_3_891X_PORT_A, 0x80);
268 joystick->set_context_psg(psg);
269 // keyboard->set_context_cpu(cpu);
270 keyboard->set_context_pio(pio);
271 // memory->set_context_slot(0, slot0);
272 // memory->set_context_slot(1, slot1);
273 // memory->set_context_slot(2, slot2);
274 // memory->set_context_slot(3, slot3);
275 memory->set_context_slot_dummy(dummy);
276 memory->set_context_slot(MAINROM_SLOT, slot_mainrom);
277 memory->set_context_slot(CART1_SLOT, slot_cart[0]);
278 #if defined(CART2_SLOT)
279 memory->set_context_slot(CART2_SLOT, slot_cart[1]);
281 #if defined(LDC_SLOT)
282 memory->set_context_slot(LDC_SLOT, slot_ldc);
284 #if defined(MAPPERRAM_SLOT)
285 memory->set_context_slot(MAPPERRAM_SLOT, slot_ram);
286 memory->set_context_mapper(slot_ram);
288 #if defined(RAM64K_SLOT)
289 memory->set_context_slot(RAM64K_SLOT, slot_ram);
291 #if defined(SUBROM_SLOT)
292 memory->set_context_slot(SUBROM_SLOT, slot_subrom);
294 #if defined(FIRMWARE32K1_SLOT)
295 slot_firmware32k1->set_context_filename(FIRMWARE32K1_FILENAME);
296 memory->set_context_slot(FIRMWARE32K1_SLOT, slot_firmware32k1);
298 #if defined(FIRMWARE32K2_SLOT)
299 slot_firmware32k2->set_context_filename(FIRMWARE32K2_FILENAME);
300 memory->set_context_slot(FIRMWARE32K2_SLOT, slot_firmware32k2);
302 #if defined(FDD_PATCH_SLOT)
303 memory->set_context_slot(FDD_PATCH_SLOT, slot_fdd_patch);
304 memory->set_context_fdd_patch(slot_fdd_patch);
306 #if defined(MSXDOS2_SLOT)
307 memory->set_context_slot(MSXDOS2_SLOT, slot_msxdos2);
309 #if defined(MSXMUSIC_SLOT)
310 memory->set_context_slot(MSXMUSIC_SLOT, slot_msxmusic);
312 #if defined(_MSX_VDP_MESS) && defined(FDD_PATCH_SLOT)
313 memory->set_context_vdp(vdp);
316 #if !defined(_MSX1_VARIANTS)
317 rtcif->set_context_rtc(rtc);
319 #if defined(LDC_SLOT)
320 slot_ldc->set_context_cpu(cpu);
321 slot_ldc->set_context_ldp(ldp);
322 slot_ldc->set_context_vdp(vdp);
326 if(config.printer_type == 0) {
327 printer->set_context_prn(new PRNFILE(this, emu));
329 } else if(config.printer_type == 1) {
330 MZ1P17 *mz1p17 = new MZ1P17(this, emu);
331 mz1p17->mode = MZ1P17_MODE_X1;
332 printer->set_context_prn(mz1p17);
333 } else if(config.printer_type == 2) {
334 MZ1P17 *mz1p17 = new MZ1P17(this, emu);
335 mz1p17->mode = MZ1P17_MODE_MZ80P4;
336 printer->set_context_prn(mz1p17);
338 // } else if(config.printer_type == 1) {
339 // HXP560 *hxp560 = new HXP560(this, emu);
340 // printer->set_context_prn(hxp560);
341 // } else if(config.printer_type == 2) {
342 // printer->set_context_prn(new PCPR201(this, emu));
345 // printer->set_context_prn(dummy);
346 printer->set_context_prn(printer);
351 cpu->set_context_mem(memory);
352 cpu->set_context_io(io);
353 cpu->set_context_intr(dummy);
354 #if defined(FDD_PATCH_SLOT)
355 cpu->set_context_bios(memory);
358 cpu->set_context_debugger(new DEBUGGER(this, emu));
362 #if !defined(_MSX1_VARIANTS)
363 io->set_iomap_range_rw(0xb4, 0xb5, rtcif);
364 io->set_iomap_range_rw(0x98, 0x9b, vdp);
366 io->set_iomap_range_rw(0x98, 0x99, vdp);
368 io->set_iomap_range_rw(0xa8, 0xab, pio);
369 #if defined(MSX_PSG_STEREO)
370 psg_stereo->set_context_psg(psg);
371 io->set_iomap_alias_w(0xa0, psg_stereo, 0); // PSG ch
372 io->set_iomap_alias_w(0xa1, psg_stereo, 1); // PSG data
373 io->set_iomap_alias_r(0xa2, psg_stereo, 1); // PSG data
375 io->set_iomap_alias_w(0xa0, psg, 0); // PSG ch
376 io->set_iomap_alias_w(0xa1, psg, 1); // PSG data
377 io->set_iomap_alias_r(0xa2, psg, 1); // PSG data
379 io->set_iomap_range_rw(0xfc, 0xff, memory);
380 io->set_iomap_range_rw(0xd8, 0xdb, kanjirom);
382 io->set_iomap_range_rw(0x90, 0x91, printer);
384 io->set_iomap_range_rw(0x7c, 0x7d, ym2413);
387 static PORT_F4 *port_f4;
388 port_f4 = new PORT_F4(this, emu);
389 io->set_iomap_range_rw(0xf4, 0xf4, port_f4);
392 // initialize all devices
393 #if defined(__GIT_REPO_VERSION)
394 strncpy(_git_revision, __GIT_REPO_VERSION, sizeof(_git_revision) - 1);
396 for(DEVICE* device = first_device; device; device = device->next_device) {
397 device->initialize();
403 // delete all devices
404 for(DEVICE* device = first_device; device;) {
405 DEVICE *next_device = device->next_device;
408 device = next_device;
412 DEVICE* VM::get_device(int id)
414 for(DEVICE* device = first_device; device; device = device->next_device) {
415 if(device->this_device_id == id) {
422 // ----------------------------------------------------------------------------
423 // drive virtual machine
424 // ----------------------------------------------------------------------------
429 for(DEVICE* device = first_device; device; device = device->next_device) {
439 // ----------------------------------------------------------------------------
441 // ----------------------------------------------------------------------------
444 DEVICE *VM::get_cpu(int index)
453 // ----------------------------------------------------------------------------
455 // ----------------------------------------------------------------------------
457 void VM::draw_screen()
462 // ----------------------------------------------------------------------------
464 // ----------------------------------------------------------------------------
466 void VM::initialize_sound(int rate, int samples)
468 // init sound manager
469 event->initialize_sound(rate, samples);
472 #if defined(MSX_PSG_STEREO)
473 psg_stereo->initialize_sound(rate, 3579545, samples, 0, 0);
475 psg->initialize_sound(rate, 3579545, samples, 0, 0);
477 pcm->initialize_sound(rate, 8000);
478 #if defined(LDC_SLOT)
479 ldp->initialize_sound(rate, samples);
481 ym2413->initialize_sound(rate, 3579545, samples);
482 sound_cart[0]->initialize_sound(rate, 3579545, samples);
483 sound_cart[1]->initialize_sound(rate, 3579545, samples);
486 uint16_t* VM::create_sound(int* extra_frames)
488 return event->create_sound(extra_frames);
491 int VM::get_sound_buffer_ptr()
493 return event->get_sound_buffer_ptr();
496 #if defined(LDC_SLOT)
497 void VM::movie_sound_callback(uint8_t *buffer, long size)
499 ldp->movie_sound_callback(buffer, size);
503 #ifdef USE_SOUND_VOLUME
504 void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
507 #if defined(MSX_PSG_STEREO)
508 psg_stereo->set_volume(1, decibel_l, decibel_r);
510 psg->set_volume(1, decibel_l, decibel_r);
513 pcm->set_volume(0, decibel_l, decibel_r);
515 drec->set_volume(0, decibel_l, decibel_r);
517 } else if(ch-- == 3) {
518 ldp->set_volume(0, decibel_l, decibel_r);
521 sound_cart[0]->set_volume(0, decibel_l, decibel_r);
523 sound_cart[1]->set_volume(0, decibel_l, decibel_r);
525 ym2413->set_volume(0, decibel_l, decibel_r);
527 drec->get_context_noise_play()->set_volume(0, decibel_l, decibel_r);
528 drec->get_context_noise_stop()->set_volume(0, decibel_l, decibel_r);
529 drec->get_context_noise_fast()->set_volume(0, decibel_l, decibel_r);
534 // ----------------------------------------------------------------------------
536 // ----------------------------------------------------------------------------
538 void VM::open_cart(int drv, const _TCHAR* file_path)
541 slot_cart[drv]->open_cart(file_path);
546 void VM::close_cart(int drv)
549 slot_cart[drv]->close_cart();
554 bool VM::is_cart_inserted(int drv)
557 return slot_cart[drv]->is_cart_inserted();
563 void VM::play_tape(int drv, const _TCHAR* file_path)
565 bool remote = drec->get_remote();
567 if(drec->play_tape(file_path) && remote) {
568 // if machine already sets remote on, start playing now
573 void VM::rec_tape(int drv, const _TCHAR* file_path)
575 bool remote = drec->get_remote();
577 if(drec->rec_tape(file_path) && remote) {
578 // if machine already sets remote on, start recording now
583 void VM::close_tape(int drv)
588 drec->set_remote(false);
591 bool VM::is_tape_inserted(int drv)
593 return drec->is_tape_inserted();
596 bool VM::is_tape_playing(int drv)
598 return drec->is_tape_playing();
601 bool VM::is_tape_recording(int drv)
603 return drec->is_tape_recording();
606 int VM::get_tape_position(int drv)
608 return drec->get_tape_position();
611 const _TCHAR* VM::get_tape_message(int drv)
613 return drec->get_message();
616 void VM::push_play(int drv)
618 drec->set_remote(false);
620 drec->set_remote(true);
623 void VM::push_stop(int drv)
625 drec->set_remote(false);
628 void VM::push_fast_forward(int drv)
630 drec->set_remote(false);
632 drec->set_remote(true);
635 void VM::push_fast_rewind(int drv)
637 drec->set_remote(false);
638 drec->set_ff_rew(-1);
639 drec->set_remote(true);
642 #if defined(LDC_SLOT)
643 void VM::open_laser_disc(int drv, const _TCHAR* file_path)
645 ldp->open_disc(file_path);
648 void VM::close_laser_disc(int drv)
653 bool VM::is_laser_disc_inserted(int drv)
655 return ldp->is_disc_inserted();
658 uint32_t VM::is_laser_disc_accessed()
660 return ldp->read_signal(0);
664 #if defined(FDD_PATCH_SLOT)
665 void VM::open_floppy_disk(int drv, const _TCHAR* file_path, int bank)
667 memory->open_disk(drv, file_path, bank);
670 void VM::close_floppy_disk(int drv)
672 memory->close_disk(drv);
675 bool VM::is_floppy_disk_inserted(int drv)
677 return memory->is_disk_inserted(drv);
680 void VM::is_floppy_disk_protected(int drv, bool value)
682 memory->is_disk_protected(drv, value);
685 bool VM::is_floppy_disk_protected(int drv)
687 return memory->is_disk_protected(drv);
690 uint32_t VM::is_floppy_disk_accessed()
692 return memory->read_signal(0);
696 bool VM::is_frame_skippable()
698 return event->is_frame_skippable();
701 void VM::update_config()
703 for(DEVICE* device = first_device; device; device = device->next_device) {
704 device->update_config();
708 double VM::get_current_usec()
710 if(event == NULL) return 0.0;
711 return event->get_current_usec();
714 uint64_t VM::get_current_clock_uint64()
716 if(event == NULL) return (uint64_t)0;
717 return event->get_current_clock_uint64();
720 #define STATE_VERSION 6
722 bool VM::process_state(FILEIO* state_fio, bool loading)
724 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
727 for(DEVICE* device = first_device; device; device = device->next_device) {
728 // Note: typeid(foo).name is fixed by recent ABI.Not dec 6.
729 // const char *name = typeid(*device).name();
730 // But, using get_device_name() instead of typeid(foo).name() 20181008 K.O
731 const char *name = device->get_device_name();
732 int len = strlen(name);
734 if(!state_fio->StateCheckInt32(len)) {
736 printf("Class name len Error: DEVID=%d EXPECT=%s\n", device->this_device_id, name);
740 if(!state_fio->StateCheckBuffer(name, len, 1)) {
742 printf("Class name Error: DEVID=%d EXPECT=%s\n", device->this_device_id, name);
746 if(!device->process_state(state_fio, loading)) {
748 printf("Data loading Error: DEVID=%d\n", device->this_device_id);
753 // Machine specified.