2 NEC PC-8801MA Emulator 'ePC-8801MA'
3 NEC PC-8001mkIISR Emulator 'ePC-8001mkIISR'
5 Author : Takeda.Toshiya
12 #include "../../emu.h"
13 #include "../device.h"
18 #include "../pcm1bit.h"
19 #include "../prnfile.h"
20 #include "../upd1990a.h"
21 #include "../ym2203.h"
25 #include "../pc80s31k.h"
26 #include "../upd765a.h"
29 #include "../debugger.h"
32 #ifdef SUPPORT_PC88_PCG8100
38 // ----------------------------------------------------------------------------
40 // ----------------------------------------------------------------------------
42 VM::VM(EMU* parent_emu) : emu(parent_emu)
45 boot_mode = config.boot_mode;
48 first_device = last_device = NULL;
49 dummy = new DEVICE(this, emu); // must be 1st device
51 pc88event = new EVENT(this, emu);
52 // pc88event->set_frames_per_sec(60);
53 // pc88event->set_lines_per_frame(260);
55 pc88 = new PC88(this, emu);
56 // pc88->set_context_event_manager(pc88event);
57 pc88sio = new I8251(this, emu);
58 // pc88sio->set_context_event_manager(pc88event);
59 pc88pio = new I8255(this, emu);
60 // pc88pio->set_context_event_manager(pc88event);
61 pc88pcm = new PCM1BIT(this, emu);
62 // pc88pcm->set_context_event_manager(pc88event);
63 pc88rtc = new UPD1990A(this, emu);
64 // pc88rtc->set_context_event_manager(pc88event);
65 // config.sound_device_type
66 // 0: 44h:OPNA A4h:None PC-8801FH/MH or later
67 // 1: 44h:OPN A4h:None PC-8801mkIISR/TR/MR/FR
68 // 2: 44h:OPN A4h:OPNA PC-8801mkIISR/TR/MR/FR + PC-8801-23
69 pc88opn = new YM2203(this, emu);
70 // pc88opn->set_context_event_manager(pc88event);
71 #ifdef USE_SOUND_DEVICE_TYPE
72 #ifdef SUPPORT_PC88_OPNA
73 pc88opn->is_ym2608 = (config.sound_device_type == 0);
75 #ifdef SUPPORT_PC88_SB2
76 if(config.sound_device_type == 2) {
77 pc88sb2 = new YM2203(this, emu);
78 #ifdef SUPPORT_PC88_OPNA
79 pc88sb2->is_ym2608 = true;
81 // pc88sb2->set_context_event_manager(pc88event);
87 if(config.printer_device_type == 0) {
88 pc88prn = new PRNFILE(this, emu);
89 // pc88prn->set_context_event_manager(pc88event);
93 pc88cpu = new Z80(this, emu);
94 // pc88cpu->set_context_event_manager(pc88event);
95 dummycpu = new DEVICE(this, emu);
97 pc88sub = new PC80S31K(this, emu);
98 // pc88sub->set_context_event_manager(pc88event);
99 pc88pio_sub = new I8255(this, emu);
100 // pc88pio_sub->set_context_event_manager(pc88event);
101 pc88fdc_sub = new UPD765A(this, emu);
102 // pc88fdc_sub->set_context_event_manager(pc88event);
103 pc88cpu_sub = new Z80(this, emu);
104 // pc88cpu_sub->set_context_event_manager(pc88event);
106 #ifdef SUPPORT_PC88_PCG8100
107 pc88pit = new I8253(this, emu);
108 // pc88pit->set_context_event_manager(pc88event);
109 pc88pcm0 = new PCM1BIT(this, emu);
110 // pc88pcm->set_context_event_manager(pc88event);
111 pc88pcm1 = new PCM1BIT(this, emu);
112 // pc88pcm->set_context_event_manager(pc88event);
113 pc88pcm2 = new PCM1BIT(this, emu);
114 // pc88pcm->set_context_event_manager(pc88event);
117 #ifdef SUPPORT_PC88_HIGH_CLOCK
118 pc88event->set_context_cpu(dummycpu, 7987248 / 8);
119 pc88event->set_context_cpu(pc88cpu, (config.cpu_type != 0) ? 3993624 : 7987248);
121 pc88event->set_context_cpu(dummycpu, 3993624 / 4);
122 pc88event->set_context_cpu(pc88cpu, 3993624);
124 pc88event->set_context_cpu(pc88cpu_sub, 3993624);
125 pc88event->set_context_sound(pc88opn);
126 #ifdef SUPPORT_PC88_SB2
127 if(pc88sb2 != NULL) {
128 pc88event->set_context_sound(pc88sb2);
131 pc88event->set_context_sound(pc88pcm);
132 #ifdef SUPPORT_PC88_PCG8100
133 pc88event->set_context_sound(pc88pcm0);
134 pc88event->set_context_sound(pc88pcm1);
135 pc88event->set_context_sound(pc88pcm2);
137 pc88->set_context_cpu(pc88cpu);
138 pc88->set_context_opn(pc88opn);
139 #ifdef SUPPORT_PC88_SB2
140 pc88->set_context_sb2(pc88sb2);
142 pc88->set_context_pcm(pc88pcm);
143 pc88->set_context_pio(pc88pio);
144 pc88->set_context_prn(pc88prn);
145 pc88->set_context_rtc(pc88rtc);
146 pc88->set_context_sio(pc88sio);
147 #ifdef SUPPORT_PC88_PCG8100
148 pc88->set_context_pcg_pit(pc88pit);
149 pc88->set_context_pcg_pcm0(pc88pcm0);
150 pc88->set_context_pcg_pcm1(pc88pcm1);
151 pc88->set_context_pcg_pcm2(pc88pcm2);
153 pc88cpu->set_context_mem(pc88);
154 pc88cpu->set_context_io(pc88);
155 pc88cpu->set_context_intr(pc88);
157 pc88cpu->set_context_debugger(new DEBUGGER(this, emu));
159 pc88opn->set_context_irq(pc88, SIG_PC88_SOUND_IRQ, 1);
160 #ifdef SUPPORT_PC88_SB2
161 if(pc88sb2 != NULL) {
162 pc88sb2->set_context_irq(pc88, SIG_PC88_SB2_IRQ, 1);
165 pc88sio->set_context_rxrdy(pc88, SIG_PC88_USART_IRQ, 1);
166 pc88sio->set_context_out(pc88, SIG_PC88_USART_OUT);
168 pc88sub->set_context_cpu(pc88cpu_sub);
169 pc88sub->set_context_fdc(pc88fdc_sub);
170 pc88sub->set_context_pio(pc88pio_sub);
171 pc88pio->set_context_port_a(pc88pio_sub, SIG_I8255_PORT_B, 0xff, 0);
172 pc88pio->set_context_port_b(pc88pio_sub, SIG_I8255_PORT_A, 0xff, 0);
173 pc88pio->set_context_port_c(pc88pio_sub, SIG_I8255_PORT_C, 0x0f, 4);
174 pc88pio->set_context_port_c(pc88pio_sub, SIG_I8255_PORT_C, 0xf0, -4);
175 pc88pio->clear_ports_by_cmdreg = true;
176 pc88pio_sub->set_context_port_a(pc88pio, SIG_I8255_PORT_B, 0xff, 0);
177 pc88pio_sub->set_context_port_b(pc88pio, SIG_I8255_PORT_A, 0xff, 0);
178 pc88pio_sub->set_context_port_c(pc88pio, SIG_I8255_PORT_C, 0x0f, 4);
179 pc88pio_sub->set_context_port_c(pc88pio, SIG_I8255_PORT_C, 0xf0, -4);
180 pc88pio_sub->clear_ports_by_cmdreg = true;
181 pc88fdc_sub->set_context_irq(pc88cpu_sub, SIG_CPU_IRQ, 1);
182 pc88cpu_sub->set_context_mem(pc88sub);
183 pc88cpu_sub->set_context_io(pc88sub);
184 pc88cpu_sub->set_context_intr(pc88sub);
186 pc88cpu_sub->set_context_debugger(new DEBUGGER(this, emu));
189 #ifdef SUPPORT_PC88_PCG8100
190 pc88pit->set_context_ch0(pc88pcm0, SIG_PCM1BIT_SIGNAL, 1);
191 pc88pit->set_context_ch1(pc88pcm1, SIG_PCM1BIT_SIGNAL, 1);
192 pc88pit->set_context_ch2(pc88pcm2, SIG_PCM1BIT_SIGNAL, 1);
193 pc88pit->set_constant_clock(0, 3993624);
194 pc88pit->set_constant_clock(1, 3993624);
195 pc88pit->set_constant_clock(2, 3993624);
198 // initialize all devices
199 for(DEVICE* device = first_device; device; device = device->next_device) {
200 device->initialize();
206 // delete all devices
207 for(DEVICE* device = first_device; device;) {
208 DEVICE *next_device = device->next_device;
211 device = next_device;
215 DEVICE* VM::get_device(int id)
217 for(DEVICE* device = first_device; device; device = device->next_device) {
218 if(device->this_device_id == id) {
225 // ----------------------------------------------------------------------------
226 // drive virtual machine
227 // ----------------------------------------------------------------------------
232 for(DEVICE* device = first_device; device; device = device->next_device) {
235 for(DEVICE* device = first_device; device; device = device->next_device) {
239 // initial device settings
240 pc88opn->SetReg(0x29, 3); // for Misty Blue
241 pc88pio->write_signal(SIG_I8255_PORT_C, 0, 0xff);
242 pc88pio_sub->write_signal(SIG_I8255_PORT_C, 0, 0xff);
250 double VM::frame_rate()
252 return pc88event->frame_rate();
255 // ----------------------------------------------------------------------------
257 // ----------------------------------------------------------------------------
260 DEVICE *VM::get_cpu(int index)
264 } else if(index == 1) {
271 // ----------------------------------------------------------------------------
273 // ----------------------------------------------------------------------------
275 void VM::draw_screen()
280 int VM::access_lamp()
282 return pc88fdc_sub->read_signal(0);
285 // ----------------------------------------------------------------------------
287 // ----------------------------------------------------------------------------
289 void VM::initialize_sound(int rate, int samples)
291 // init sound manager
292 pc88event->initialize_sound(rate, samples);
295 #ifdef SUPPORT_PC88_OPNA
296 if(pc88opn->is_ym2608) {
297 pc88opn->init(rate, 7987248, samples, 0, 0);
300 pc88opn->init(rate, 3993624, samples, 0, 0);
301 #ifdef SUPPORT_PC88_SB2
302 if(pc88sb2 != NULL) {
303 #ifdef SUPPORT_PC88_OPNA
304 if(pc88sb2->is_ym2608) {
305 pc88sb2->init(rate, 7987248, samples, 0, 0);
308 pc88sb2->init(rate, 3993624, samples, 0, 0);
311 pc88pcm->init(rate, 8000);
312 #ifdef SUPPORT_PC88_PCG8100
313 pc88pcm0->init(rate, 8000);
314 pc88pcm1->init(rate, 8000);
315 pc88pcm2->init(rate, 8000);
319 uint16* VM::create_sound(int* extra_frames)
321 return pc88event->create_sound(extra_frames);
324 int VM::sound_buffer_ptr()
326 return pc88event->sound_buffer_ptr();
329 // ----------------------------------------------------------------------------
331 // ----------------------------------------------------------------------------
333 void VM::key_down(int code, bool repeat)
335 pc88->key_down(code, repeat);
338 void VM::key_up(int code)
342 // ----------------------------------------------------------------------------
344 // ----------------------------------------------------------------------------
346 void VM::open_disk(int drv, const _TCHAR* file_path, int bank)
348 pc88fdc_sub->open_disk(drv, file_path, bank);
351 void VM::close_disk(int drv)
353 pc88fdc_sub->close_disk(drv);
356 bool VM::disk_inserted(int drv)
358 return pc88fdc_sub->disk_inserted(drv);
361 void VM::set_disk_protected(int drv, bool value)
363 pc88fdc_sub->set_disk_protected(drv, value);
366 bool VM::get_disk_protected(int drv)
368 return pc88fdc_sub->get_disk_protected(drv);
371 void VM::play_tape(const _TCHAR* file_path)
373 pc88->play_tape(file_path);
376 void VM::rec_tape(const _TCHAR* file_path)
378 pc88->rec_tape(file_path);
381 void VM::close_tape()
386 bool VM::tape_inserted()
388 return pc88->tape_inserted();
393 // return event->now_skip();
394 return pc88->now_skip();
397 void VM::update_config()
401 #ifdef USE_MULTIPLE_SOUNDCARDS
402 vol1 = vol2 = (config.sound_device_level[1] + 32768) >> 8; // Card1
403 pc88opn->write_signal(SIG_YM2203_LVOLUME, vol1, 0xffffffff); // OPN: LEFT
404 pc88opn->write_signal(SIG_YM2203_RVOLUME, vol2, 0xffffffff); // OPN: RIGHT
405 # ifdef SUPPORT_PC88_SB2
406 if(pc88sb2 != NULL) {
407 vol1 = vol2 = (config.sound_device_level[2] + 32768) >> 8; // Card2
408 pc88sb2->write_signal(SIG_YM2203_LVOLUME, vol1, 0xffffffff); // OPN: LEFT
409 pc88sb2->write_signal(SIG_YM2203_RVOLUME, vol2, 0xffffffff); // OPN: RIGHT
413 if(boot_mode != config.boot_mode) {
414 // boot mode is changed !!!
415 boot_mode = config.boot_mode;
418 for(DEVICE* device = first_device; device; device = device->next_device) {
419 device->update_config();
424 #define STATE_VERSION 5
426 void VM::save_state(FILEIO* state_fio)
428 state_fio->FputUint32(STATE_VERSION);
430 for(DEVICE* device = first_device; device; device = device->next_device) {
431 device->save_state(state_fio);
433 state_fio->FputInt32(boot_mode);
436 bool VM::load_state(FILEIO* state_fio)
438 if(state_fio->FgetUint32() != STATE_VERSION) {
441 for(DEVICE* device = first_device; device; device = device->next_device) {
442 if(!device->load_state(state_fio)) {
446 boot_mode = state_fio->FgetInt32();