2 FUJITSU FM-Towns Emulator 'eFMR-60'
4 Author : Kyuma Ohta <whatisthis.sowhat _at_ gmail.com>
9 2016-12-28 Copy from eFMR-50.
13 #include "../../emu.h"
14 #include "../device.h"
17 #include "towns_crtc.h"
18 //#include "../hd46505.h"
26 #include "../mb8877.h"
27 #include "../msm58321.h"
28 #include "../pcm1bit.h"
29 #include "../scsi_hdd.h"
30 #include "../scsi_host.h"
31 #include "../upd71071.h"
34 //#include "mb87078.h"
36 //#include "../ym2612.h"
44 #include "../debugger.h"
56 // ----------------------------------------------------------------------------
58 // ----------------------------------------------------------------------------
60 VM::VM(EMU* parent_emu) : VM_TEMPLATE(parent_emu)
79 static const int cpu_clock[] = {
82 #elif defined(HAS_I486)
87 #if defined(_FMR60) && (defined(HAS_I386) || defined(HAS_I486) || defined(HAS_PENTIUM))
88 uint8_t machine_id = 0xf0; // FMR-70/80
90 uint8_t machine_id = 0xf8; // FMR-50/60
93 FILEIO* fio = new FILEIO();
94 if(fio->Fopen(create_local_path(_T("MACHINE.ID")), FILEIO_READ_BINARY)) {
95 machine_id = fio->Fgetc();
101 #if defined(HAS_I286)
102 machine_id |= 0; // 286
103 #elif defined(HAS_I386)
104 // machine_id |= 1; // 386DX
105 machine_id |= 3; // 386SX
106 #elif defined(HAS_I486)
107 machine_id |= 2; // 486SX/DX
111 first_device = last_device = NULL;
112 dummy = new DEVICE(this, emu); // must be 1st device
113 event = new EVENT(this, emu); // must be 2nd device
115 dummy->set_device_name(_T("1st Dummy"));
116 event->set_device_name(_T("EVENT"));
119 cpu = new I386(this, emu);
121 #if defined(HAS_I386)
122 cpu->set_device_name(_T("CPU(i386)"));
123 #elif defined(HAS_I486)
124 cpu->set_device_name(_T("CPU(i486)"));
125 #elif defined(HAS_PENTIUM)
126 cpu->set_device_name(_T("CPU(Pentium)"));
130 crtc = new TOWNS_CRTC(this, emu);
133 crtc->set_device_name(_T("TOWNS CRTC"));
136 sio = new I8251(this, emu);
137 pit0 = new I8253(this, emu);
138 pit1 = new I8253(this, emu);
139 pic = new I8259(this, emu);
140 io = new IO(this, emu);
141 fdc = new MB8877(this, emu);
142 rtc = new MSM58321(this, emu);
143 pcm = new PCM1BIT(this, emu);
145 sio->set_device_name(_T("i8251 SIO"));
146 pit0->set_device_name(_T("i8253 PIT #0"));
147 pit1->set_device_name(_T("i8253 PIT #1"));
148 pic->set_device_name(_T("i8259 PIC"));
149 rtc->set_device_name(_T("MSM58321 RTC"));
150 pcm->set_device_name(_T("PCM SOUND"));
153 scsi_host = new SCSI_HOST(this, emu);
155 scsi_host->set_device_name(_T("SCSI HOST"));
157 for(int i = 0; i < 7; i++) {
158 if(FILEIO::IsFileExisting(create_local_path(_T("SCSI%d.DAT"), i))) {
159 SCSI_HDD* scsi_hdd = new SCSI_HDD(this, emu);
161 char d_name[64] = {0};
162 snprintf(d_name, 64, "SCSI DISK #%d", i + 1);
163 scsi_hdd->set_device_name(d_name);
165 scsi_hdd->scsi_id = i;
166 scsi_hdd->set_context_interface(scsi_host);
167 scsi_host->set_context_target(scsi_hdd);
170 dma = new UPD71071(this, emu);
172 dma->set_device_name(_T("uPD71071 DMAC"));
174 if(FILEIO::IsFileExisting(create_local_path(_T("IPL.ROM")))) {
177 bios = new BIOS(this, emu);
179 bios->set_device_name(_T("PSEUDO BIOS"));
182 cmos = new CMOS(this, emu);
183 floppy = new FLOPPY(this, emu);
184 keyboard = new KEYBOARD(this, emu);
185 memory = new MEMORY(this, emu);
186 scsi = new SCSI(this, emu);
187 // serial = new SERIAL(this, emu);
188 timer = new TIMER(this, emu);
190 cmos->set_device_name(_T("CMOS RAM"));
191 floppy->set_device_name(_T("FLOPPY I/F"));
192 keyboard->set_device_name(_T("KEYBOARD"));
193 memory->set_device_name(_T("MEMORY"));
194 scsi->set_device_name(_T("SCSI I/F"));
195 //serial->set_device_name(_T("SERIAL I/F"));
196 timer->set_device_name(_T("TIMER I/F"));
200 event->set_context_cpu(cpu, cpu_clock[config.cpu_type & 1]);
201 event->set_context_sound(pcm);
202 #if defined(USE_SOUND_FILES)
203 if(fdc->load_sound_data(MB8877_SND_TYPE_SEEK, _T("FDDSEEK.WAV"))) {
204 event->set_context_sound(fdc);
214 6 floppy drive or dma ???
230 crtc->set_context_disp(memory, SIG_MEMORY_DISP, 1);
231 crtc->set_context_vsync(memory, SIG_MEMORY_VSYNC, 1);
233 acrtc->set_vram_ptr((uint16_t*)memory->get_vram(), 0x80000);
235 pit0->set_context_ch0(timer, SIG_TIMER_CH0, 1);
236 pit0->set_context_ch1(timer, SIG_TIMER_CH1, 1);
237 pit0->set_context_ch2(pcm, SIG_PCM1BIT_SIGNAL, 1);
238 pit0->set_constant_clock(0, 307200);
239 pit0->set_constant_clock(1, 307200);
240 pit0->set_constant_clock(2, 307200);
241 pit1->set_constant_clock(1, 1228800);
242 pic->set_context_cpu(cpu);
243 fdc->set_context_drq(dma, SIG_UPD71071_CH0, 1);
244 fdc->set_context_irq(floppy, SIG_FLOPPY_IRQ, 1);
245 rtc->set_context_data(timer, SIG_TIMER_RTC, 0x0f, 0);
246 rtc->set_context_busy(timer, SIG_TIMER_RTC, 0x80);
247 scsi_host->set_context_irq(scsi, SIG_SCSI_IRQ, 1);
248 scsi_host->set_context_drq(scsi, SIG_SCSI_DRQ, 1);
249 dma->set_context_memory(memory);
250 dma->set_context_ch0(fdc);
251 dma->set_context_ch1(scsi_host);
253 floppy->set_context_fdc(fdc);
254 floppy->set_context_pic(pic);
255 keyboard->set_context_pic(pic);
256 memory->set_context_cpu(cpu);
257 memory->set_machine_id(machine_id);
258 memory->set_context_crtc(crtc);
259 memory->set_chregs_ptr(crtc->get_regs());
260 scsi->set_context_dma(dma);
261 scsi->set_context_pic(pic);
262 scsi->set_context_host(scsi_host);
263 timer->set_context_pcm(pcm);
264 timer->set_context_pic(pic);
265 timer->set_context_rtc(rtc);
268 cpu->set_context_mem(memory);
269 cpu->set_context_io(io);
270 cpu->set_context_intr(pic);
272 bios->set_context_mem(memory);
273 bios->set_context_io(io);
274 bios->set_cmos_ptr(cmos->get_cmos());
275 bios->set_vram_ptr(memory->get_vram());
276 bios->set_cvram_ptr(memory->get_cvram());
278 bios->set_avram_ptr(memory->get_avram());
280 bios->set_kvram_ptr(memory->get_kvram());
282 cpu->set_context_bios(bios);
284 #ifdef SINGLE_MODE_DMA
285 cpu->set_context_dma(dma);
288 cpu->set_context_debugger(new DEBUGGER(this, emu));
292 io->set_iomap_alias_rw(0x00, pic, I8259_ADDR_CHIP0 | 0);
293 io->set_iomap_alias_rw(0x02, pic, I8259_ADDR_CHIP0 | 1);
294 io->set_iomap_alias_rw(0x10, pic, I8259_ADDR_CHIP1 | 0);
295 io->set_iomap_alias_rw(0x12, pic, I8259_ADDR_CHIP1 | 1);
296 io->set_iomap_single_rw(0x20, memory); // reset
297 io->set_iomap_single_r(0x21, memory); // cpu misc
298 io->set_iomap_single_w(0x22, memory); // dma
299 io->set_iomap_single_rw(0x24, memory); // dma
300 io->set_iomap_single_r(0x26, timer);
301 io->set_iomap_single_r(0x27, timer);
302 io->set_iomap_single_r(0x30, memory); // cpu id
303 io->set_iomap_alias_rw(0x40, pit0, 0);
304 io->set_iomap_alias_rw(0x42, pit0, 1);
305 io->set_iomap_alias_rw(0x44, pit0, 2);
306 io->set_iomap_alias_rw(0x46, pit0, 3);
307 io->set_iomap_alias_rw(0x50, pit1, 0);
308 io->set_iomap_alias_rw(0x52, pit1, 1);
309 io->set_iomap_alias_rw(0x54, pit1, 2);
310 io->set_iomap_alias_rw(0x56, pit1, 3);
311 io->set_iomap_single_rw(0x60, timer);
312 io->set_iomap_single_rw(0x70, timer);
313 io->set_iomap_single_w(0x80, timer);
315 io->set_iomap_single_w(0x90, cmos);
317 io->set_iomap_range_rw(0xa0, 0xaf, dma);
318 io->set_iomap_alias_rw(0x200, fdc, 0);
319 io->set_iomap_alias_rw(0x202, fdc, 1);
320 io->set_iomap_alias_rw(0x204, fdc, 2);
321 io->set_iomap_alias_rw(0x206, fdc, 3);
322 io->set_iomap_single_rw(0x208, floppy);
323 io->set_iomap_single_rw(0x20c, floppy);
324 io->set_iomap_single_rw(0x400, memory); // crtc
325 io->set_iomap_single_rw(0x402, memory); // crtc
326 io->set_iomap_single_rw(0x404, memory); // crtc
327 io->set_iomap_single_w(0x408, memory); // crtc
328 io->set_iomap_single_rw(0x40a, memory); // crtc
329 io->set_iomap_single_rw(0x40c, memory); // crtc
330 io->set_iomap_single_rw(0x40e, memory); // crtc
331 io->set_iomap_alias_rw(0x500, crtc, 0);
332 io->set_iomap_alias_rw(0x502, crtc, 1);
334 io->set_iomap_range_rw(0x520, 0x523, acrtc);
336 io->set_iomap_single_rw(0x600, keyboard);
337 io->set_iomap_single_rw(0x602, keyboard);
338 io->set_iomap_single_rw(0x604, keyboard);
339 io->set_iomap_alias_rw(0xa00, sio, 0);
340 io->set_iomap_alias_rw(0xa02, sio, 1);
341 // io->set_iomap_single_r(0xa04, serial);
342 // io->set_iomap_single_r(0xa06, serial);
343 // io->set_iomap_single_w(0xa08, serial);
344 io->set_iomap_single_rw(0xc30, scsi);
345 io->set_iomap_single_rw(0xc32, scsi);
346 io->set_iomap_range_rw(0x3000, 0x3fff, cmos);
347 io->set_iomap_range_rw(0xfd98, 0xfd9f, memory); // crtc
348 io->set_iomap_single_rw(0xfda0, memory); // crtc
350 // initialize all devices
351 #if defined(__GIT_REPO_VERSION)
352 strncpy(_git_revision, __GIT_REPO_VERSION, sizeof(_git_revision) - 1);
354 for(DEVICE* device = first_device; device; device = device->next_device) {
355 device->initialize();
358 for(int i = 0; i < MAX_DRIVE; i++) {
359 bios->set_disk_handler(i, fdc->get_disk_handler(i));
366 // delete all devices
367 for(DEVICE* device = first_device; device;) {
368 DEVICE *next_device = device->next_device;
371 device = next_device;
375 DEVICE* VM::get_device(int id)
377 for(DEVICE* device = first_device; device; device = device->next_device) {
378 if(device->this_device_id == id) {
385 // ----------------------------------------------------------------------------
386 // drive virtual machine
387 // ----------------------------------------------------------------------------
392 for(DEVICE* device = first_device; device; device = device->next_device) {
396 for(DEVICE* device = first_device; device; device = device->next_device) {
406 // ----------------------------------------------------------------------------
408 // ----------------------------------------------------------------------------
411 DEVICE *VM::get_cpu(int index)
420 // ----------------------------------------------------------------------------
422 // ----------------------------------------------------------------------------
424 void VM::draw_screen()
426 memory->draw_screen();
429 uint32_t VM::is_floppy_disk_accessed()
431 return fdc->read_signal(0);
434 // ----------------------------------------------------------------------------
436 // ----------------------------------------------------------------------------
438 void VM::initialize_sound(int rate, int samples)
440 // init sound manager
441 event->initialize_sound(rate, samples);
444 pcm->initialize_sound(rate, 8000);
447 uint16_t* VM::create_sound(int* extra_frames)
449 return event->create_sound(extra_frames);
452 int VM::get_sound_buffer_ptr()
454 return event->get_sound_buffer_ptr();
457 #ifdef USE_SOUND_VOLUME
458 void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
461 pcm->set_volume(0, decibel_l, decibel_r);
463 #if defined(USE_SOUND_FILES)
465 fdc->set_volume(0, decibel_l, decibel_r);
471 // ----------------------------------------------------------------------------
473 // ----------------------------------------------------------------------------
475 void VM::key_down(int code, bool repeat)
477 keyboard->key_down(code);
480 void VM::key_up(int code)
482 keyboard->key_up(code);
485 // ----------------------------------------------------------------------------
487 // ----------------------------------------------------------------------------
489 void VM::open_floppy_disk(int drv, const _TCHAR* file_path, int bank)
491 fdc->open_disk(drv, file_path, bank);
492 floppy->change_disk(drv);
495 void VM::close_floppy_disk(int drv)
497 fdc->close_disk(drv);
500 bool VM::is_floppy_disk_inserted(int drv)
502 return fdc->is_disk_inserted(drv);
505 void VM::is_floppy_disk_protected(int drv, bool value)
507 fdc->is_disk_protected(drv, value);
510 bool VM::is_floppy_disk_protected(int drv)
512 return fdc->is_disk_protected(drv);
515 bool VM::is_frame_skippable()
517 return event->is_frame_skippable();
520 void VM::update_config()
522 for(DEVICE* device = first_device; device; device = device->next_device) {
523 device->update_config();
527 #define STATE_VERSION 3
529 void VM::save_state(FILEIO* state_fio)
531 state_fio->FputUint32(STATE_VERSION);
533 for(DEVICE* device = first_device; device; device = device->next_device) {
534 device->save_state(state_fio);
538 bool VM::load_state(FILEIO* state_fio)
540 if(state_fio->FgetUint32() != STATE_VERSION) {
543 for(DEVICE* device = first_device; device; device = device->next_device) {
544 if(!device->load_state(state_fio)) {