2 FUJITSU FM16beta Emulator 'eFM16beta'
4 Author : Takeda.Toshiya
11 #include "../../emu.h"
12 #include "../device.h"
16 #include "../hd46505.h"
22 #include "../mb8877.h"
23 #include "../mc6809.h"
24 #include "../mc6840.h"
25 #include "../msm58321.h"
27 #include "../pcm1bit.h"
30 #include "../debugger.h"
38 // ----------------------------------------------------------------------------
40 // ----------------------------------------------------------------------------
42 VM::VM(EMU* parent_emu) : VM_TEMPLATE(parent_emu)
45 first_device = last_device = NULL;
46 dummy = new DEVICE(this, emu); // must be 1st device
47 event = new EVENT(this, emu); // must be 2nd device
49 crtc = new HD46505(this, emu);
50 cpu = new I286(this, emu);
51 io = new IO(this, emu);
52 dma = new I8237(this, emu);
53 sio = new I8251(this, emu);
54 pic = new I8259(this, emu);
55 fdc_2hd = new MB8877(this, emu);
56 fdc_2hd->set_context_noise_seek(new NOISE(this, emu));
57 fdc_2hd->set_context_noise_head_down(new NOISE(this, emu));
58 fdc_2hd->set_context_noise_head_up(new NOISE(this, emu));
59 fdc_2d = new MB8877(this, emu);
60 fdc_2d->set_context_noise_seek(new NOISE(this, emu));
61 fdc_2d->set_context_noise_head_down(new NOISE(this, emu));
62 fdc_2d->set_context_noise_head_up(new NOISE(this, emu));
63 subcpu = new MC6809(this, emu);
64 ptm = new MC6840(this, emu);
65 rtc = new MSM58321(this, emu);
66 pcm = new PCM1BIT(this, emu);
68 cmos = new CMOS(this, emu);
69 keyboard = new KEYBOARD(this, emu);
70 mainbus = new MAINBUS(this, emu);
76 subbus = new SUB(this, emu);
79 event->set_context_cpu(cpu, 8000000);
80 event->set_context_cpu(subcpu, 2000000);
81 event->set_context_sound(pcm);
82 event->set_context_sound(fdc_2hd->get_context_noise_seek());
83 event->set_context_sound(fdc_2hd->get_context_noise_head_down());
84 event->set_context_sound(fdc_2hd->get_context_noise_head_up());
85 event->set_context_sound(fdc_2d->get_context_noise_seek());
86 event->set_context_sound(fdc_2d->get_context_noise_head_down());
87 event->set_context_sound(fdc_2d->get_context_noise_head_up());
89 keyboard->set_context_main(mainbus);
91 mainbus->set_context_cpu(cpu);
93 mainbus->set_context_dma(dma);
94 mainbus->set_context_fdc_2hd(fdc_2hd);
95 mainbus->set_context_fdc_2d(fdc_2d);
96 mainbus->set_context_pic(pic);
97 mainbus->set_context_pcm(pcm);
98 mainbus->set_context_rtc(rtc);
99 mainbus->set_context_sub(subbus);
100 mainbus->set_context_keyboard(keyboard);
102 dma->set_context_memory(mainbus);
103 dma->set_context_ch0(fdc_2d);
104 dma->set_context_ch1(fdc_2hd);
106 sio->set_context_txrdy(mainbus, SIG_MAIN_IRQ0_TX, 1);
107 sio->set_context_rxrdy(mainbus, SIG_MAIN_IRQ0_RX, 1);
108 sio->set_context_syndet(mainbus, SIG_MAIN_IRQ0_SYN, 1);
110 fdc_2hd->set_context_irq(mainbus, SIG_MAIN_IRQ5, 1);
111 fdc_2hd->set_context_drq(mainbus, SIG_MAIN_DRQ_2HD, 1);
112 fdc_2hd->set_context_drq(dma, SIG_I8237_CH1, 1);
114 fdc_2d->set_context_irq(mainbus, SIG_MAIN_IRQ4, 1);
115 fdc_2d->set_context_drq(mainbus, SIG_MAIN_DRQ_2D, 1);
116 fdc_2d->set_context_drq(dma, SIG_I8237_CH0, 1);
118 ptm->set_context_ch0(pcm, SIG_PCM1BIT_SIGNAL, 1);
119 ptm->set_context_irq(mainbus, SIG_MAIN_IRQ8, 1);
120 ptm->set_internal_clock(19200); // temporary
121 ptm->set_external_clock(0, 19200);
122 ptm->set_external_clock(1, 19200);
123 ptm->set_external_clock(2, 19200);
125 rtc->set_context_data(mainbus, SIG_MAIN_RTC_DATA, 0x0f, 0);
126 rtc->set_context_busy(mainbus, SIG_MAIN_RTC_BUSY, 0x80);
128 crtc->set_context_disp(subbus, SIG_SUB_DISP, 1);
129 crtc->set_context_vsync(subbus, SIG_SUB_VSYNC, 1);
131 subbus->addr_max = 0x10000;
132 subbus->bank_size = 0x80;
133 subbus->set_context_crtc(crtc);
134 subbus->set_chregs_ptr(crtc->get_regs());
135 subbus->set_context_pcm(pcm);
136 subbus->set_context_main(mainbus);
137 subbus->set_context_subcpu(subcpu);
138 subbus->set_context_keyboard(keyboard);
141 cpu->set_context_mem(mainbus);
142 cpu->set_context_io(io);
143 cpu->set_context_intr(pic);
144 #ifdef SINGLE_MODE_DMA
145 cpu->set_context_dma(dma);
147 subcpu->set_context_mem(subbus);
149 cpu->set_context_debugger(new DEBUGGER(this, emu));
150 subcpu->set_context_debugger(new DEBUGGER(this, emu));
155 io->set_iomap_range_rw(0x0000, 0x0001, pic);
156 io->set_iomap_range_rw(0x0010, 0x001f, dma);
157 io->set_iomap_range_w(0x0020, 0x0023, mainbus); // dma bank regs
159 io->set_iomap_single_rw(0x0060, mainbus); // reset
162 io->set_iomap_range_rw(0xf000, 0xf7ff, cmos);
163 io->set_iomap_range_rw(0xfc80, 0xfcff, subbus); // shared ram
165 io->set_iomap_range_r(0xfd00, 0xfd01, keyboard);
166 io->set_iomap_range_rw(0xfd02, 0xfd05, mainbus);
168 io->set_iomap_range_rw(0xfd06, 0xfd07, sio);
170 io->set_iomap_single_rw(0xfd0f, mainbus);
172 io->set_iomap_range_rw(0xfd10, 0xfd11, mainbus);
174 io->set_iomap_range_rw(0xfd18, 0xfd1b, fdc_2d);
175 io->set_iomap_range_rw(0xfd1c, 0xfd1f, mainbus);
177 io->set_iomap_range_r(0xfd20, 0xfd22, subbus); // attention
179 io->set_iomap_single_rw(0xfd2c, mainbus);
181 io->set_iomap_range_rw(0xfd30, 0xfd33, fdc_2hd);
182 io->set_iomap_range_rw(0xfd34, 0xfd37, mainbus);
184 io->set_iomap_range_rw(0xfd38, 0xfd3f, ptm);
185 io->set_iomap_range_rw(0xfd98, 0xfd9f, subbus);
186 io->set_iomap_single_w(0xfda0, subbus);
187 io->set_iomap_single_r(0xfda0, mainbus);
190 // initialize all devices
191 #if defined(__GIT_REPO_VERSION)
192 strncpy(_git_revision, __GIT_REPO_VERSION, sizeof(_git_revision) - 1);
194 for(DEVICE* device = first_device; device; device = device->next_device) {
195 device->initialize();
199 for(int i = 0; i < 4; i++) {
200 fdc_2hd->set_drive_type(i, DRIVE_TYPE_2HD);
201 fdc_2d->set_drive_type(i, DRIVE_TYPE_2D);
203 fdc_2hd->get_disk_handler(0)->drive_num = 0;
204 fdc_2hd->get_disk_handler(1)->drive_num = 1;
205 fdc_2d->get_disk_handler(0)->drive_num = 2;
206 fdc_2d->get_disk_handler(1)->drive_num = 3;
211 // delete all devices
212 for(DEVICE* device = first_device; device;) {
213 DEVICE *next_device = device->next_device;
216 device = next_device;
220 DEVICE* VM::get_device(int id)
222 for(DEVICE* device = first_device; device; device = device->next_device) {
223 if(device->this_device_id == id) {
230 // ----------------------------------------------------------------------------
231 // drive virtual machine
232 // ----------------------------------------------------------------------------
237 for(DEVICE* device = first_device; device; device = device->next_device) {
241 emu->out_debug_log(_T("----- RESET -----\n"));
250 // ----------------------------------------------------------------------------
252 // ----------------------------------------------------------------------------
255 DEVICE *VM::get_cpu(int index)
259 } else if(index == 1) {
266 // ----------------------------------------------------------------------------
268 // ----------------------------------------------------------------------------
270 void VM::draw_screen()
272 subbus->draw_screen();
275 // ----------------------------------------------------------------------------
277 // ----------------------------------------------------------------------------
279 void VM::initialize_sound(int rate, int samples)
281 // init sound manager
282 event->initialize_sound(rate, samples);
285 pcm->initialize_sound(rate, 8000);
288 uint16_t* VM::create_sound(int* extra_frames)
290 return event->create_sound(extra_frames);
293 int VM::get_sound_buffer_ptr()
295 return event->get_sound_buffer_ptr();
298 #ifdef USE_SOUND_VOLUME
299 void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
302 pcm->set_volume(0, decibel_l, decibel_r);
304 fdc_2hd->get_context_noise_seek()->set_volume(0, decibel_l, decibel_r);
305 fdc_2hd->get_context_noise_head_down()->set_volume(0, decibel_l, decibel_r);
306 fdc_2hd->get_context_noise_head_up()->set_volume(0, decibel_l, decibel_r);
307 fdc_2d->get_context_noise_seek()->set_volume(0, decibel_l, decibel_r);
308 fdc_2d->get_context_noise_head_down()->set_volume(0, decibel_l, decibel_r);
309 fdc_2d->get_context_noise_head_up()->set_volume(0, decibel_l, decibel_r);
314 // ----------------------------------------------------------------------------
316 // ----------------------------------------------------------------------------
318 void VM::key_down(int code, bool repeat)
320 keyboard->key_down(code);
323 void VM::key_up(int code)
325 keyboard->key_up(code);
328 // ----------------------------------------------------------------------------
330 // ----------------------------------------------------------------------------
332 void VM::open_floppy_disk(int drv, const _TCHAR* file_path, int bank)
335 fdc_2hd->open_disk(drv, file_path, bank);
337 fdc_2d->open_disk(drv - 2, file_path, bank);
341 void VM::close_floppy_disk(int drv)
344 fdc_2hd->close_disk(drv);
346 fdc_2d->close_disk(drv - 2);
350 bool VM::is_floppy_disk_inserted(int drv)
353 return fdc_2hd->is_disk_inserted(drv);
355 return fdc_2d->is_disk_inserted(drv - 2);
360 void VM::is_floppy_disk_protected(int drv, bool value)
363 fdc_2hd->is_disk_protected(drv, value);
365 fdc_2d->is_disk_protected(drv - 2, value);
369 bool VM::is_floppy_disk_protected(int drv)
372 return fdc_2hd->is_disk_protected(drv);
374 return fdc_2d->is_disk_protected(drv - 2);
379 uint32_t VM::is_floppy_disk_accessed()
381 return (fdc_2hd->read_signal(0) & 3) | ((fdc_2d->read_signal(0) & 3) << 2);
384 bool VM::is_frame_skippable()
386 return event->is_frame_skippable();
389 void VM::update_config()
391 for(DEVICE* device = first_device; device; device = device->next_device) {
392 device->update_config();
396 #define STATE_VERSION 1
398 #include "../../statesub.h"
399 #include "../../qt/gui/csp_logger.h"
400 extern CSP_Logger DLL_PREFIX_I *csp_logger;
402 void VM::decl_state(void)
404 state_entry = new csp_state_utils(STATE_VERSION, 0, (_TCHAR *)(_T("CSP::FM16BETA_HEAD")), csp_logger);
405 for(DEVICE* device = first_device; device; device = device->next_device) {
406 device->decl_state();
410 void VM::save_state(FILEIO* state_fio)
412 //state_fio->FputUint32(STATE_VERSION);
414 if(state_entry != NULL) {
415 state_entry->save_state(state_fio);
417 for(DEVICE* device = first_device; device; device = device->next_device) {
418 device->save_state(state_fio);
422 bool VM::load_state(FILEIO* state_fio)
424 //if(state_fio->FgetUint32() != STATE_VERSION) {
428 if(state_entry != NULL) {
429 mb = state_entry->load_state(state_fio);
432 emu->out_debug_log("INFO: HEADER DATA ERROR");
435 for(DEVICE* device = first_device; device; device = device->next_device) {
436 if(!device->load_state(state_fio)) {
443 bool VM::process_state(FILEIO* state_fio, bool loading)
445 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
448 for(DEVICE* device = first_device; device; device = device->next_device) {
449 const char *name = typeid(*device).name() + 6; // skip "class "
450 int len = strlen(name);
452 if(!state_fio->StateCheckInt32(len)) {
455 if(!state_fio->StateCheckBuffer(name, len, 1)) {
458 if(!device->process_state(state_fio, loading)) {