OSDN Git Service

[VM][I386_NP21] .
[csp-qt/common_source_project-fm7.git] / source / src / vm / fmtowns / fmtowns.cpp
1 /*
2         FUJITSU FM-Towns Emulator 'eFMTowns'
3
4         Author : Kyuma Ohta <whatisthis.sowhat _at_ gmail.com>
5         Date   : 2016.12.28 -
6
7         [ virtual machine ]
8         History: 
9                 2016-12-28 Copy from eFMR-50.
10 */
11
12 #include "fmtowns.h"
13 #include "../../emu.h"
14 #include "../device.h"
15 #include "../event.h"
16
17 //#include "../hd46505.h"
18 #include "../i8251.h"
19 #include "../i8253.h"
20 #include "../i8259.h"
21
22 #include "../i386_np21.h"
23 //#include "../i386.h"
24
25 #include "../io.h"
26 #include "../mb8877.h"
27 #include "../msm58321.h"
28 #include "../noise.h"
29 #include "../pcm1bit.h"
30 #include "../harddisk.h"
31 #include "../scsi_hdd.h"
32 #include "./towns_scsi_host.h"
33 #include "../upd71071.h"
34
35 #include "towns_cdrom.h"
36 #include "towns_crtc.h"
37 #include "towns_dictionary.h"
38 #include "towns_dmac.h"
39 #include "towns_memory.h"
40 #include "towns_sprite.h"
41 #include "towns_sysrom.h"
42 #include "towns_vram.h"
43
44 // Electric Volume
45 //#include "mb87078.h"
46 //YM-2612 "OPN2"
47 //#include "../ym2612.h"
48 //RF5C68 PCM
49 #include "rf5c68.h"
50 //AD7820 ADC
51 #include "ad7820kr.h"
52 #include "ym2612.h"
53 // 80387?
54
55 #ifdef USE_DEBUGGER
56 #include "../debugger.h"
57 #endif
58
59 #include "./adpcm.h"
60 //#include "./cdc.h"
61 #include "./floppy.h"
62 #include "./fontroms.h"
63 #include "./joystick.h"
64 #include "./keyboard.h"
65 #include "./msdosrom.h"
66 #include "./scsi.h"
67 #include "./serialrom.h"
68 #include "./timer.h"
69 #include "./iccard.h"
70
71 #include "./towns_planevram.h"
72
73 // ----------------------------------------------------------------------------
74 // initialize
75 // ----------------------------------------------------------------------------
76 using FMTOWNS::ADPCM;
77 //using FMTOWNS::CDC;
78 using FMTOWNS::DICTIONARY;
79 using FMTOWNS::FLOPPY;
80 using FMTOWNS::FONT_ROMS;
81 using FMTOWNS::JOYSTICK;
82 using FMTOWNS::KEYBOARD;
83 using FMTOWNS::MSDOSROM;
84 using FMTOWNS::SCSI;
85 using FMTOWNS::SERIAL_ROM;
86 using FMTOWNS::SYSROM;
87 using FMTOWNS::TIMER;
88 using FMTOWNS::TOWNS_ICCARD;
89
90 using FMTOWNS::TOWNS_CDROM;
91 using FMTOWNS::TOWNS_CRTC;
92 using FMTOWNS::TOWNS_DMAC;
93 using FMTOWNS::TOWNS_MEMORY;
94 using FMTOWNS::TOWNS_SCSI_HOST;
95 using FMTOWNS::TOWNS_SPRITE;
96 using FMTOWNS::TOWNS_VRAM;
97 using FMTOWNS::PLANEVRAM;
98
99
100 VM::VM(EMU_TEMPLATE* parent_emu) : VM_TEMPLATE(parent_emu)
101 {
102 /*
103         Machine ID & CPU ID
104
105         FMR-50FD/HD/LT  0xF8
106         FMR-50FX/HX     0xE0
107         FMR-50SFX/SHX   0xE8
108         FMR-50LT        0xF8
109         FMR-50NBX       0x28
110         FMR-50NB        0x60
111         FMR-50NE/T      0x08
112         FMR-CARD        0x70
113
114         80286           0x00
115         80386           0x01
116         80386SX         0x03
117         80486           0x02
118 */
119         
120         // create devices
121         first_device = last_device = NULL;
122         dummy = new DEVICE(this, emu);  // must be 1st device
123         event = new EVENT(this, emu);   // must be 2nd device
124 #if defined(_USE_QT)
125         dummy->set_device_name(_T("1st Dummy"));
126         event->set_device_name(_T("EVENT"));
127 #endif  
128
129         cpu = new I386(this, emu);
130 #if defined(_USE_QT)
131   #if defined(HAS_I386)
132         cpu->set_device_name(_T("CPU(i386)"));
133   #elif defined(HAS_I486)
134         cpu->set_device_name(_T("CPU(i486)"));
135   #elif defined(HAS_PENTIUM)
136         cpu->set_device_name(_T("CPU(Pentium)"));
137   #endif
138 #endif  
139
140         io = new IO(this, emu);
141         
142         crtc = new TOWNS_CRTC(this, emu);
143         cdrom = new TOWNS_CDROM(this, emu);
144
145         memory = new TOWNS_MEMORY(this, emu);
146         vram = new TOWNS_VRAM(this, emu);
147         sprite = new TOWNS_SPRITE(this, emu);
148         sysrom = new SYSROM(this, emu);
149         msdosrom = new MSDOSROM(this, emu);
150         fontrom = new FONT_ROMS(this, emu);
151         dictionary = new DICTIONARY(this, emu);
152 #if defined(HAS_20PIX_FONTS)
153         fontrom_20pix = new FONT_ROM_20PIX(this, emu);
154 #endif
155         serialrom = new SERIAL_ROM(this, emu);
156
157         adpcm = new ADPCM(this, emu);
158 //      mixer = new MIXER(this, emu); // Pseudo mixer.
159
160         planevram = new PLANEVRAM(this, emu);
161         
162         adc = new AD7820KR(this, emu);
163         rf5c68 = new RF5C68(this, emu);
164 //      e_volume[0] = new MB87878(this, emu);
165 //      e_volume[1] = new MB87878(this, emu);
166         
167         sio = new I8251(this, emu);
168         pit0 = new I8253(this, emu);
169         pit1 = new I8253(this, emu);
170         pic = new I8259(this, emu);
171         fdc = new MB8877(this, emu);
172         rtc = new MSM58321(this, emu);
173         beep = new PCM1BIT(this, emu);
174         opn2 = new YM2612(this, emu);
175
176         seek_sound = new NOISE(this, emu);
177         head_up_sound = new NOISE(this, emu);
178         head_down_sound = new NOISE(this, emu);
179         
180 //      scsi_host = new TOWNS_SCSI_HOST(this, emu);
181         scsi_host = new SCSI_HOST(this, emu);
182         
183         for(int i = 0; i < 7; i++) {
184                 scsi_hdd[i] = NULL;
185         }       
186 #if defined(USE_HARD_DISK)
187         for(int i = 0; i < USE_HARD_DISK; i++) {
188                 scsi_hdd[i] = new SCSI_HDD(this, emu);
189                 scsi_hdd[i]->set_device_name(_T("SCSI Hard Disk Drive #%d"), i + 1);
190                 scsi_hdd[i]->scsi_id = i ;
191                 scsi_hdd[i]->set_disk_handler(0, new HARDDISK(emu));
192                 scsi_hdd[i]->set_context_interface(scsi_host);
193                 my_sprintf_s(scsi_hdd[i]->vendor_id, 9, "FUJITSU");
194                 my_sprintf_s(scsi_hdd[i]->product_id, 17, "SCSI-HDD");
195                 scsi_host->set_context_target(scsi_hdd[i]);
196         }
197 #endif
198         dma = new TOWNS_DMAC(this, emu);
199         extra_dma = new TOWNS_DMAC(this, emu);
200
201         floppy = new FLOPPY(this, emu);
202         keyboard = new KEYBOARD(this, emu);
203         joystick = new JOYSTICK(this, emu);
204         scsi = new SCSI(this, emu);
205         timer = new TIMER(this, emu);
206
207         iccard1 = new TOWNS_ICCARD(this, emu);
208 #if 0
209         iccard2 = new TOWNS_ICCARD(this, emu);
210 #else
211         iccard2 = NULL;
212 #endif
213         
214         uint16_t machine_id = 0x0100; // FM-Towns1
215         uint16_t cpu_id = 0x0001;     // i386DX
216         uint32_t cpu_clock = 16000 * 1000; // 16MHz
217 #if defined(_FMTOWNS1_2ND_GEN)
218         machine_id = 0x0200;   // 1F/2F/1H/2H
219 #elif defined(_FMTOWNS_UX_VARIANTS)
220         machine_id = 0x0300;   // UX10/20/40
221         cpu_id = 0x0003;       // i386SX
222 #elif defined(_FMTOWNS1_3RD_GEN)
223         machine_id = 0x0400;  // 10F/20F.40H/80H
224 #elif defined(_FMTOWNS2_CX_VARIANTS)
225         machine_id = 0x0500;  // CX10/20/30/40
226 #elif defined(_FMTOWNS_UG_VARIANTS)
227         machine_id = 0x0600;  // UG10/20/40/80
228         cpu_id = 0x0003;      // i386SX
229         cpu_clock = 20000 * 1000; // 20MHz
230 #elif defined(_FMTOWNS_HR_VARIANTS)
231         machine_id = 0x0700;
232         cpu_id = 0x0002;      // i486SX
233         cpu_clock = 20000 * 1000; // 20MHz
234 #elif defined(_FMTOWNS_HG_VARIANTS)
235         machine_id = 0x0800;
236         cpu_clock = 20000 * 1000; // 20MHz
237 #elif defined(_FMTOWNS_SG_VARIANTS)
238         machine_id = 0x0800; // OK?
239 #elif defined(_FMTOWNS_SR_VARIANTS)
240         machine_id = 0x0700; // OK?
241         cpu_id = 0x0002;      // i486SX
242         cpu_clock = 20000 * 1000; // 20MHz
243 #elif defined(_FMTOWNS_MA_VARIANTS)
244         machine_id = 0x0b00; // OK?
245         cpu_id = 0x0002;      // i486SX
246         cpu_clock = 33000 * 1000; // 33MHz
247 #elif defined(_FMTOWNS_ME_VARIANTS)
248         machine_id = 0x0d00; // OK?
249         cpu_id = 0x0002;      // i486SX
250         cpu_clock = 25000 * 1000; // 25MHz
251 #elif defined(_FMTOWNS_MF_VARIANTS)
252         machine_id = 0x0f00; // OK?
253         cpu_id = 0x0002;      // i486SX
254         cpu_clock = 33000 * 1000; // 33MHz
255 #elif defined(_FMTOWNS_MX_VARIANTS)
256         machine_id = 0x0c00; // OK?
257         cpu_id = 0x0002;      // i486DX (With FPU?)
258         cpu_clock = 66000 * 1000; // 66MHz
259 #elif defined(_FMTOWNS_MX_VARIANTS)
260         machine_id = 0x0c00; // OK?
261         cpu_id = 0x0002;      // i486DX (With FPU?)
262         cpu_clock = 66000 * 1000; // 66MHz
263 #else
264         // ToDo: Pentium Model (After HB).
265
266 #endif
267         event->set_frames_per_sec(FRAMES_PER_SEC);
268         event->set_lines_per_frame(LINES_PER_FRAME);
269         
270         set_machine_type(machine_id, cpu_id);
271         // set contexts
272         event->set_context_cpu(cpu, cpu_clock);
273
274         adc_in_ch = -1;
275         line_in_ch = -1;
276         modem_in_ch = -1;
277         mic_in_ch = -1;
278
279         // Use pseudo mixer instead of event.Due to using ADC.
280 #if 0
281         line_mix_ch = -1;
282         modem_mix_ch = -1;
283         mic_mix_ch = -1;
284         //line_mix_ch = mixer->set_context_sound(line_in);
285         //modem_mix_ch = mixer->set_context_sound(modem_in);
286         //mic_mix_ch = mixer->set_context_sound(mic_in);
287         beep_mix_ch = mixer->set_context_sound(beep);
288         pcm_mix_ch  = mixer->set_context_sound(rf5c68);
289         opn2_mix_ch = mixer->set_context_sound(opn2);
290         cdc_mix_ch = mixer->set_context_sound(cdrom);
291         mixer->set_interpolate_filter_freq(pcm_mix_ch, 4000); // channel, freq; disable if freq <= 0.
292         event->set_context_sound(mixer);
293 #else
294         // Temporally not use mixer.
295         event->set_context_sound(beep);
296         event->set_context_sound(opn2);
297         event->set_context_sound(rf5c68);
298         event->set_context_sound(cdrom);
299 #endif
300         fdc->set_context_noise_seek(seek_sound);
301         fdc->set_context_noise_head_down(head_down_sound);
302         fdc->set_context_noise_head_up(head_up_sound);
303         event->set_context_sound(seek_sound);
304         event->set_context_sound(head_down_sound);
305         event->set_context_sound(head_up_sound);
306         
307 #ifdef USE_DEBUGGER
308         pit0->set_context_debugger(new DEBUGGER(this, emu));
309         pit1->set_context_debugger(new DEBUGGER(this, emu));
310 #endif  
311         pit0->set_context_ch0(timer, SIG_TIMER_CH0, 1);
312         pit0->set_context_ch1(timer, SIG_TIMER_CH1, 1);
313         pit0->set_context_ch2(beep,  SIG_PCM1BIT_SIGNAL, 1);
314         pit0->set_constant_clock(0, 307200);
315         pit0->set_constant_clock(1, 307200);
316         pit0->set_constant_clock(2, 307200);
317         pit1->set_constant_clock(0, 1229900);
318         pit1->set_constant_clock(1, 1229900);
319         pit1->set_constant_clock(2, 1229900);
320 //      pic->set_context_cpu(cpu);
321         pic->set_context_cpu(memory);
322         fdc->set_context_irq(floppy, SIG_FLOPPY_IRQ, 1);
323         rtc->set_context_data(timer, SIG_TIMER_RTC, 0x0f, 0);
324         rtc->set_context_busy(timer, SIG_TIMER_RTC_BUSY, 0x80);
325         scsi_host->set_context_irq(scsi, SIG_SCSI_IRQ, 1);
326         scsi_host->set_context_drq(scsi, SIG_SCSI_DRQ, 1);
327         dma->set_context_memory(memory);
328         dma->set_context_ch0(fdc);
329         dma->set_context_ch1(scsi_host);
330         //dma->set_context_ch2(printer);
331         dma->set_context_ch3(cdrom);
332         dma->set_context_tc3(cdrom, SIG_TOWNS_CDROM_DMAINT, 0xffffffff);
333         dma->set_context_ube1(scsi_host, SIG_SCSI_16BIT_BUS, 0x02);
334
335         dma->set_context_child_dma(extra_dma);
336         
337         floppy->set_context_fdc(fdc);
338         
339         sprite->set_context_vram(vram); 
340         sprite->set_context_font(fontrom);
341         sprite->set_context_crtc(crtc);
342 #ifdef USE_DEBUGGER
343         sprite->set_context_debugger(new DEBUGGER(this, emu));
344 #endif
345         
346         vram->set_context_sprite(sprite);
347         vram->set_context_crtc(crtc);
348         
349         planevram->set_context_vram(vram);
350         planevram->set_context_sprite(sprite);
351         planevram->set_context_crtc(crtc);
352         
353         crtc->set_context_sprite(sprite);
354         crtc->set_context_vram(vram);
355         crtc->set_context_font(fontrom);
356
357         //e_volume[0]->set_context_ch0(line_in, MB87878_VOLUME_LEFT);
358         //e_volume[0]->set_context_ch1(line_in, MB87878_VOLUME_RIGHT);
359         //e_volume[0]->set_context_ch2(NULL, MB87878_VOLUME_LEFT);
360         //e_volume[0]->set_context_ch3(NULL, MB87878_VOLUME_RIGHT);
361 //      e_volume[1]->set_context_ch0(cdrom, MB87878_VOLUME_LEFT);
362 //      e_volume[1]->set_context_ch1(cdrom, MB87878_VOLUME_RIGHT);
363         //e_volume[1]->set_context_ch2(mic, MB87878_VOLUME_LEFT | MB87878_VOLUME_RIGHT);
364         //e_volume[1]->set_context_ch3(modem, MB87878_VOLUME_LEFT | MB87878_VOLUME_RIGHT);
365         
366         memory->set_context_cpu(cpu);
367         memory->set_context_dmac(dma);
368         memory->set_context_vram(vram);
369         memory->set_context_planevram(planevram);
370         memory->set_context_crtc(crtc);
371         memory->set_context_system_rom(sysrom);
372         memory->set_context_msdos(msdosrom);
373         memory->set_context_dictionary(dictionary);
374         memory->set_context_font_rom(fontrom);
375         memory->set_context_beep(beep);
376         memory->set_context_serial_rom(serialrom);
377         memory->set_context_sprite(sprite);
378         memory->set_context_pcm(rf5c68);
379         memory->set_context_iccard(iccard1, 0);
380         memory->set_context_iccard(iccard2, 1);
381
382         adpcm->set_context_opn2(opn2);
383         adpcm->set_context_rf5c68(rf5c68);
384         adpcm->set_context_adc(adc);
385
386         rf5c68->set_context_interrupt_boundary(adpcm, SIG_ADPCM_WRITE_INTERRUPT, 0xffffffff);
387 #ifdef USE_DEBUGGER
388         rf5c68->set_context_debugger(new DEBUGGER(this, emu));
389 #endif
390         opn2->set_context_irq(adpcm, SIG_ADPCM_OPX_INTR, 0xffffffff);
391         
392         adc->set_sample_rate(19200);
393         adc->set_sound_bank(-1);
394         adc->set_context_interrupt(adpcm, SIG_ADPCM_ADC_INTR, 0xffffffff); 
395         
396         scsi->set_context_dma(dma);
397         scsi->set_context_host(scsi_host);
398         scsi->set_context_pic(pic);
399         timer->set_context_pcm(beep);
400         timer->set_context_rtc(rtc);
401         timer->set_context_halt_line(cpu, SIG_CPU_HALTREQ, 0xffffffff);
402         
403         // cpu bus
404         cpu->set_context_mem(memory);
405         cpu->set_context_io(io);
406         cpu->set_context_intr(pic);
407         cpu->set_context_dma(dma);
408         cpu->set_context_bios(NULL);
409         cpu->set_context_extreset(memory, SIG_FMTOWNS_NOTIFY_RESET, 0xffffffff);
410 #ifdef USE_DEBUGGER
411         cpu->set_context_debugger(new DEBUGGER(this, emu));
412 #endif
413         // Interrupts
414         // IRQ0  : TIMER
415         // IRQ1  : KEYBOARD
416         // IRQ2  : USART (ToDo)
417         // IRQ3  : EXTRA USART (ToDo)
418         // IRQ4  : EXTRA I/O (Maybe not implement)
419         // IRQ5  : EXTRA I/O (Maybe not implement)
420         // IRQ6  : FDC
421         // IRQ7  : Deisy chain (to IRQ8 - 15)
422         timer->set_context_intr_line(pic, SIG_I8259_CHIP0 | SIG_I8259_IR0, 0xffffffff);
423         keyboard->set_context_intr_line(pic, SIG_I8259_CHIP0 | SIG_I8259_IR1, 0xffffffff);
424         floppy->set_context_intr_line(pic, SIG_I8259_CHIP0 | SIG_I8259_IR6, 0xffffffff);
425         
426         // IRQ8  : SCSI (-> scsi.cpp)
427         // IRQ9  : CDC/CDROM
428         // IRQ10 : EXTRA I/O (Maybe not implement)
429         // IRQ11 : VSYNC
430         // IRQ12 : PRINTER (ToDo)
431         // IRQ13 : ADPCM AND OPN2 (Route to adpcm.cpp)
432         // IRQ14 : EXTRA I/O (Maybe not implement)
433         // IRQ15 : RESERVED.
434         cdrom->set_context_mpuint_line(pic, SIG_I8259_CHIP1 | SIG_I8259_IR1, 0xffffffff);
435         crtc->set_context_vsync(pic, SIG_I8259_CHIP1 | SIG_I8259_IR3, 0xffffffff);
436         adpcm->set_context_intr_line(pic, SIG_I8259_CHIP1 | SIG_I8259_IR5, 0xffffffff);
437
438         // DMA0  : FDC/DRQ
439         // DMA1  : SCSI (-> scsi.cpp)
440         // DMA2  : PRINTER (ToDo)
441         // DMA3  : CDC/CDROM
442         // EXTRA DMA0 : EXTRA SLOT (Maybe not implement)
443         // EXTRA DMA1 : Reserved
444         // EXTRA DMA2 : Reserved
445         // EXTRA DMA3 : Reserved
446         fdc->set_context_drq(dma, SIG_UPD71071_CH0, 1);
447         cdrom->set_context_drq_line(dma, SIG_UPD71071_CH3, 0xff);
448
449         // NMI0 : KEYBOARD (RAS)
450         // NMI1 : Extra SLOT (Maybe not implement)
451         keyboard->set_context_nmi_line(memory, SIG_CPU_NMI, 0xffffffff);
452
453         cdrom->set_context_dmac(dma);
454         // For Debugging, will remove 20200822 K.O
455         cdrom->set_context_cpu(cpu);
456
457         // i/o bus
458         io->set_iowait_range_rw(0x0000, 0xffff, 6); // ToDo: May variable wait.
459                 
460         io->set_iomap_alias_rw (0x0000, pic, I8259_ADDR_CHIP0 | 0);
461         io->set_iomap_alias_rw (0x0002, pic, I8259_ADDR_CHIP0 | 1);
462         io->set_iomap_alias_rw (0x0010, pic, I8259_ADDR_CHIP1 | 0);
463         io->set_iomap_alias_rw (0x0012, pic, I8259_ADDR_CHIP1 | 1);
464         
465         io->set_iomap_range_rw (0x0020, 0x0025, memory);
466         io->set_iomap_range_rw (0x0026, 0x0027, timer);  // Freerun counter
467         io->set_iomap_single_rw(0x0028, memory);
468         
469         io->set_iomap_range_r  (0x0030, 0x0031, memory);        // cpu id / machine id
470         io->set_iomap_single_rw(0x0032, memory);        // serial rom (routed from memory)
471         io->set_iomap_single_r (0x0034, scsi);  // ENABLE/ UNABLE to WORD DMA for SCSI
472
473         io->set_iomap_alias_rw(0x0040, pit0, 0);
474         io->set_iomap_alias_rw(0x0042, pit0, 1);
475         io->set_iomap_alias_rw(0x0044, pit0, 2);
476         io->set_iomap_alias_rw(0x0046, pit0, 3);
477         io->set_iomap_alias_rw(0x0050, pit1, 0);
478         io->set_iomap_alias_rw(0x0052, pit1, 1);
479         io->set_iomap_alias_rw(0x0054, pit1, 2);
480         io->set_iomap_alias_rw(0x0056, pit1, 3);
481         
482         io->set_iomap_single_rw(0x0060, timer); // Beep and interrupts register
483         io->set_iomap_single_rw(0x0068, timer); // Interval timer register2 (after Towns 10F).
484         io->set_iomap_single_rw(0x006a, timer); // Interval timer register2 (after Towns 10F).
485         io->set_iomap_single_rw(0x006b, timer); // Interval timer register2 (after Towns 10F).
486         io->set_iomap_single_rw(0x006c, timer); // 1uS wait register (after Towns 10F).
487         
488         io->set_iomap_single_rw(0x0070, timer); // RTC DATA
489         io->set_iomap_single_w (0x0080, timer); // RTC COMMAND
490         
491         io->set_iomap_range_rw (0x00a0, 0x00af, dma);
492         io->set_iomap_range_rw (0x00b0, 0x00bf, extra_dma);
493         
494         io->set_iomap_alias_rw (0x0200, fdc, 0);  // STATUS/COMMAND
495         io->set_iomap_alias_rw (0x0202, fdc, 1);  // TRACK
496         io->set_iomap_alias_rw (0x0204, fdc, 2);  // SECTOR
497         io->set_iomap_alias_rw (0x0206, fdc, 3);  // DATA
498         io->set_iomap_single_rw(0x0208, floppy);  // DRIVE STATUS / DRIVE CONTROL
499         io->set_iomap_single_rw(0x020c, floppy);  // DRIVE SELECT
500         io->set_iomap_single_rw(0x020e, floppy);  // Towns drive SW
501         
502         io->set_iomap_range_rw (0x0400, 0x0404, memory); // System Status
503         io->set_iomap_range_rw (0x0406, 0x403f, memory); // Reserved
504         
505         io->set_iomap_range_rw(0x0440, 0x0443, crtc); // CRTC
506         io->set_iomap_range_rw(0x0448, 0x044f, crtc); // VIDEO OUT (CRTC)
507         
508         io->set_iomap_range_rw(0x0450, 0x0452, sprite); // SPRITE
509         
510         io->set_iomap_single_rw(0x0458, vram);         // VRAM ACCESS CONTROLLER (ADDRESS)
511         io->set_iomap_range_rw (0x045a, 0x045f, vram); // VRAM ACCESS CONTROLLER (DATA)
512         
513         io->set_iomap_single_rw(0x0480, memory); //  MEMORY REGISTER
514         io->set_iomap_single_rw(0x0484, dictionary); // Dictionary
515         
516         io->set_iomap_alias_r(0x48a, iccard1, 0); //
517         //io->set_iomap_alias_rw(0x490, memory_card); // After Towns2
518         //io->set_iomap_alias_rw(0x491, memory_card); // After Towns2
519         
520         io->set_iomap_range_rw(0x04c0, 0x04cf, cdrom); // CDROM
521         // PAD, Sound
522 #if 1
523         io->set_iomap_single_r(0x04d0, joystick); // Pad1
524         io->set_iomap_single_r(0x04d2, joystick); // Pad 2
525         io->set_iomap_single_w(0x04d6, joystick); // Pad out
526 #endif  
527         io->set_iomap_single_rw(0x04d5, adpcm); // mute 
528         // OPN2(YM2612)
529         io->set_iomap_alias_rw(0x04d8, opn2, 0); // STATUS(R)/Addrreg 0(W)
530         io->set_iomap_alias_w (0x04da, opn2, 1);  // Datareg 0(W)
531         io->set_iomap_alias_w (0x04dc, opn2, 2);  // Addrreg 1(W)
532         io->set_iomap_alias_w (0x04de, opn2, 3);  // Datareg 1(W)
533         // Electrical volume
534 //      io->set_iomap_alias_rw(0x04e0, e_volume[0], 0);
535 //      io->set_iomap_alias_rw(0x04e1, e_volume[0], 1);
536 //      io->set_iomap_alias_rw(0x04e2, e_volume[1], 0);
537 //      io->set_iomap_alias_rw(0x04e3, e_volume[1], 1);
538
539         // ADPCM
540         io->set_iomap_range_rw(0x04e7, 0x04ef, adpcm); // A/D SAMPLING DATA REG 
541         io->set_iomap_range_rw(0x04f0, 0x04f8, rf5c68); // A/D SAMPLING DATA REG 
542
543         io->set_iomap_single_rw(0x05c0, memory); // NMI MASK
544         io->set_iomap_single_r (0x05c2, memory);  // NMI STATUS
545         io->set_iomap_single_r (0x05c8, sprite); // TVRAM EMULATION
546         io->set_iomap_single_w (0x05ca, crtc); // VSYNC INTERRUPT
547         if(machine_id < 0x0200) {
548                 io->set_iomap_single_rw(0x05e0, memory); //  MEMORY WAIT REGISTER ffrom AB.COM 
549         } else {
550                 io->set_iomap_single_rw(0x05e2, memory); // MEMORY WAIT REGISTER ffrom AB.COM 
551         }
552         io->set_iomap_single_rw(0x05e8, memory); // RAM capacity register.(later Towns1H/2H/1F/2F).
553         io->set_iomap_single_rw(0x05ec, memory); // RAM Wait register , ofcially after Towns2, but exists after Towns1H.
554         io->set_iomap_single_r (0x05ed, memory); // RAM Wait register , ofcially after Towns2, but exists after Towns1H.
555         
556         io->set_iomap_single_rw(0x0600, keyboard);
557         io->set_iomap_single_rw(0x0602, keyboard);
558         io->set_iomap_single_rw(0x0604, keyboard);
559
560         //io->set_iomap_single_rw(0x0800, printer);
561         //io->set_iomap_single_rw(0x0802, printer);
562         //io->set_iomap_single_rw(0x0804, printer);
563         
564         io->set_iomap_alias_rw (0x0a00, sio, 0);
565         io->set_iomap_alias_rw (0x0a02, sio, 1);
566 //      io->set_iomap_single_r (0x0a04, serial);
567 //      io->set_iomap_single_r (0x0a06, serial);
568 //      io->set_iomap_single_w (0x0a08, serial);
569 //      io->set_iomap_single_rw(0x0a0a, modem);
570         
571         io->set_iomap_single_rw(0x0c30, scsi);
572         io->set_iomap_single_rw(0x0c32, scsi);
573
574         io->set_iomap_range_rw (0x3000, 0x3fff, dictionary); // CMOS
575         
576         io->set_iomap_range_rw (0xfd90, 0xfda2, crtc);  // Palette and CRTC
577         io->set_iomap_single_rw(0xfda4, memory);        // memory
578         
579         io->set_iomap_range_rw (0xff80, 0xff83, planevram);     // MMIO
580         io->set_iomap_single_r (0xff84, planevram);     // MMIO
581         io->set_iomap_single_rw(0xff86, planevram);     // MMIO
582         io->set_iomap_single_rw(0xff88, memory);        // MMIO
583         io->set_iomap_range_rw (0xff94, 0xff99, memory);        // MMIO
584         io->set_iomap_range_r  (0xff9c, 0xff9d, memory);        // MMIO
585         io->set_iomap_single_rw(0xff9e, memory);        // MMIO
586         io->set_iomap_single_rw(0xffa0, planevram);     // MMIO
587         
588 //      io->set_iomap_range_w (0xff94, 0xff95, fontrom);
589 //      io->set_iomap_range_r (0xff96, 0xff97, fontrom);
590
591         // Vram allocation may be before initialize().
592         // initialize all devices
593 #if defined(__GIT_REPO_VERSION)
594         strncpy(_git_revision, __GIT_REPO_VERSION, sizeof(_git_revision) - 1);
595 #endif
596         // ToDo : Use config framework
597         int exram_size = config.current_ram_size;
598         if(exram_size < 1) {
599                 if(machine_id < 0x0200) { // Model1 - 2H
600                         exram_size = 6;
601                 } else if(machine_id == 0x0500) { // CX
602                         exram_size = 15;
603                 } else if(machine_id < 0x0700) {  // 10F,20H
604                         exram_size = 8;
605                 } else if(machine_id == 0x0800) { // HG
606                         exram_size = 15;
607                 } else { 
608                         exram_size = 31;
609                 }
610         }
611         if(exram_size < MIN_RAM_SIZE) {
612                 exram_size = MIN_RAM_SIZE;
613         }
614         
615         memory->set_extra_ram_size(exram_size);
616
617 #if defined(WITH_I386SX)
618         cpu->device_model = INTEL_80386;
619 #elif defined(WITH_I486SX)
620         cpu->device_model = INTEL_I486SX;
621 #elif defined(WITH_I486DX)
622         cpu->device_model = INTEL_I486DX;
623 #elif defined(WITH_PENTIUM)
624         cpu->device_model = INTEL_PENTIUM;
625 #else
626         // I386
627         cpu->device_model = INTEL_80386;
628 #endif  
629
630         for(DEVICE* device = first_device; device; device = device->next_device) {
631                 device->initialize();
632         }
633 //      cpu->set_address_mask(0xffffffff);
634 }
635
636 VM::~VM()
637 {
638         // delete all devices
639         for(DEVICE* device = first_device; device;) {
640                 DEVICE *next_device = device->next_device;
641 //              printf("DEVID=%d\n", device->this_device_id);
642                 device->release();
643                 delete device;
644                 device = next_device;
645         }
646 }
647
648 DEVICE* VM::get_device(int id)
649 {
650         for(DEVICE* device = first_device; device; device = device->next_device) {
651                 if(device->this_device_id == id) {
652                         return device;
653                 }
654         }
655         return NULL;
656 }
657
658 void VM::set_machine_type(uint16_t machine_id, uint16_t cpu_id)
659 {
660         if(memory != NULL) {
661                 memory->set_cpu_id(cpu_id);
662                 memory->set_machine_id(machine_id);
663         }
664         if(crtc != NULL) {
665                 crtc->set_cpu_id(cpu_id);
666                 crtc->set_machine_id(machine_id);
667         }
668         if(timer != NULL) {
669                 timer->set_cpu_id(cpu_id);
670                 timer->set_machine_id(machine_id);
671         }
672         if(cdrom != NULL) {
673                 cdrom->set_cpu_id(cpu_id);
674                 cdrom->set_machine_id(machine_id);
675         }
676         if(scsi != NULL) {
677                 scsi->set_cpu_id(cpu_id);
678                 scsi->set_machine_id(machine_id);
679         }
680         if(serialrom != NULL) {
681                 serialrom->set_cpu_id(cpu_id);
682                 serialrom->set_machine_id(machine_id);
683         }
684 #if defined(HAS_20PIX_FONTS)
685         if(fontrom_20pix != NULL) {
686                 fontrom_20pix->set_cpu_id(cpu_id);
687                 fontrom_20pix->set_machine_id(machine_id);
688         }
689 #endif
690         
691 }               
692
693
694 // ----------------------------------------------------------------------------
695 // drive virtual machine
696 // ----------------------------------------------------------------------------
697
698 void VM::reset()
699 {
700         // reset all devices
701         boot_seq = true;
702         for(DEVICE* device = first_device; device; device = device->next_device) {
703                 device->reset();
704         }
705 //      cpu->set_address_mask(0xffffffff);
706 }
707
708 void VM::special_reset(int num)
709 {
710         // reset all devices
711         boot_seq = true;
712         
713         for(DEVICE* device = first_device; device; device = device->next_device) {
714                 device->reset();
715         }
716         keyboard->special_reset(num);
717
718 //      cpu->set_address_mask(0xffffffff);
719 }
720
721 void VM::run()
722 {
723         event->drive();
724 }
725
726 // ----------------------------------------------------------------------------
727 // debugger
728 // ----------------------------------------------------------------------------
729
730 #ifdef USE_DEBUGGER
731 DEVICE *VM::get_cpu(int index)
732 {
733         if(index == 0) {
734                 return cpu;
735         }
736         return NULL;
737 }
738 #endif
739
740 // ----------------------------------------------------------------------------
741 // draw screen
742 // ----------------------------------------------------------------------------
743
744 void VM::draw_screen()
745 {
746         crtc->draw_screen();
747 }
748
749 uint32_t VM::is_floppy_disk_accessed()
750 {
751         uint32_t val = fdc->read_signal(0);
752         if(boot_seq) {
753                 if(val != 0) {
754                         keyboard->write_signal(SIG_KEYBOARD_BOOTSEQ_END, 0xffffffff, 0xffffffff);
755                         boot_seq = false;
756                 }
757         }
758         return val;
759 }
760
761 // ----------------------------------------------------------------------------
762 // soud manager
763 // ----------------------------------------------------------------------------
764
765 void VM::initialize_sound(int rate, int samples)
766 {
767         emu->lock_vm();
768         // init sound manager
769         event->initialize_sound(rate, samples);
770         
771         // init sound gen
772         beep->initialize_sound(rate, 8000);
773
774         // init OPN2
775         // MASTER CLOCK MAYBE 600KHz * 12 = 7200KHz .
776         // From FM-Towns Technical Databook (Rev.2), Page 201
777         opn2->initialize_sound(rate, (int)(600.0e3 * 12.0) , samples, 0.0, 0.0); 
778         //opn2->initialize_sound(rate, (int)(8000.0e3) , samples, 0.0, 0.0); 
779         //opn2->initialize_sound(rate, (int)(600.0e3 * 6.0) , samples, 0.0, 0.0); 
780
781         // init PCM
782         rf5c68->initialize_sound(rate, samples);
783         
784         // add_sound_in_source() must add after per initialize_sound().
785         adc_in_ch = event->add_sound_in_source(rate, samples, 2);
786         adc->set_sample_rate(19200);
787         adc->set_sound_bank(adc_in_ch);
788 #if 0   
789         mixer->set_context_out_line(adc_in_ch);
790         mixer->set_context_sample_out(adc_in_ch, rate, samples); // Must be 2ch.
791         // ToDo: Check recording sample rate & channels.
792         mic_in_ch = event->add_sound_in_source(rate, samples, 2);
793         mixer->set_context_mic_in(mic_in_ch, rate, samples);
794
795         line_in_ch = event->add_sound_in_source(rate, samples, 2);
796         mixer->set_context_line_in(line_in_ch, rate, samples);
797 #endif
798         emu->unlock_vm();
799 }
800
801 uint16_t* VM::create_sound(int* extra_frames)
802 {
803         return event->create_sound(extra_frames);
804 }
805
806 int VM::get_sound_buffer_ptr()
807 {
808         return event->get_sound_buffer_ptr();
809 }
810
811 void VM::clear_sound_in()
812 {
813         event->clear_sound_in_source(adc_in_ch);
814         event->clear_sound_in_source(mic_in_ch);
815         event->clear_sound_in_source(line_in_ch);
816         return;
817 }
818
819 int VM::get_sound_in_data(int ch, int32_t* dst, int expect_samples, int expect_rate, int expect_channels)
820 {
821         if(dst == NULL) return 0;
822         if(expect_samples <= 0) return 0;
823         int n_ch = -1;
824         switch(ch) {
825         case 0x00:
826                 n_ch = line_in_ch;
827                 break;
828         case 0x01:
829                 n_ch = mic_in_ch;
830                 break;
831         case 0x100:
832                 n_ch = adc_in_ch;
833                 break;
834         }
835         if(n_ch < 0) return 0;
836         int samples = event->get_sound_in_data(n_ch, dst, expect_samples, expect_rate, expect_channels);
837         return samples;
838 }
839
840 // Write to event's buffer
841 int VM::sound_in(int ch, int32_t* src, int samples)
842 {
843         if(ch < 0) return 0;
844         if(ch >= 2) return 0;
845         int n_ch = -1;
846         switch(ch) {
847         case 0x100:  // ADC in from MIXER, not connected.
848                 break;
849         case 0x00: // LINE
850                 n_ch = line_in_ch;
851                 break;
852         case 0x01: // MIC
853                 n_ch = mic_in_ch;
854                 break;
855         }
856         if(n_ch < 0) return 0;
857
858         int ss = 0;
859         {
860                 emu->lock_vm();
861                 ss =  event->write_sound_in_buffer(n_ch, src, samples);
862                 emu->unlock_vm();
863
864         }
865         return ss;
866 }
867
868 #if defined(USE_HARD_DISK)
869 void VM::open_hard_disk(int drv, const _TCHAR* file_path)
870 {
871         if((drv < USE_HARD_DISK) && (drv < 8) && (drv >= 0)) {
872                 if(scsi_hdd[drv] != NULL) {
873                         scsi_hdd[drv]->open(0, file_path, 512);
874                 }
875         }
876 }
877
878 void VM::close_hard_disk(int drv)
879 {
880         if((drv < USE_HARD_DISK) && (drv < 8) && (drv >= 0)) {
881                 if(scsi_hdd[drv] != NULL) {
882                         scsi_hdd[drv]->close(0);
883                 }
884         }
885 }
886
887 bool VM::is_hard_disk_inserted(int drv)
888 {
889         if((drv < USE_HARD_DISK) && (drv < 8) && (drv >= 0)) {
890                 if(scsi_hdd[drv] != NULL) {
891                         return scsi_hdd[drv]->mounted(0);
892                 }
893         }
894         return false;
895 }
896
897 uint32_t VM::is_hard_disk_accessed()
898 {
899         uint32_t status = 0;
900         
901         for(int drv = 0; drv < USE_HARD_DISK; drv++) {
902                 if(scsi_hdd[drv] != NULL) {
903                         if(scsi_hdd[drv]->accessed(0)) {
904                                 status |= 1 << drv;
905                         }
906                 }
907         }
908         if(boot_seq) {
909                 if(status != 0) {
910                         keyboard->write_signal(SIG_KEYBOARD_BOOTSEQ_END, 0xffffffff, 0xffffffff);
911                         boot_seq = false;
912                 }
913         }
914         return status;
915 }
916 #endif // USE_HARD_DISK
917
918 void VM::open_compact_disc(int drv, const _TCHAR* file_path)
919 {
920         cdrom->open(file_path);
921 }
922
923 void VM::close_compact_disc(int drv)
924 {
925         cdrom->close();
926 }
927
928 bool VM::is_compact_disc_inserted(int drv)
929 {
930         return cdrom->mounted();
931 }
932
933 uint32_t VM::is_compact_disc_accessed()
934 {
935         uint32_t status = cdrom->accessed();
936         if(boot_seq) {
937                 if(status != 0) {
938                         keyboard->write_signal(SIG_KEYBOARD_BOOTSEQ_END, 0xffffffff, 0xffffffff);
939                         boot_seq = false;
940                 }
941         }
942         return status;
943 }
944
945 #ifdef USE_SOUND_VOLUME
946 void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
947 {
948 #ifndef HAS_LINEIN_SOUND
949 //      if(ch >= 7) ch++;
950 #endif
951 #ifndef HAS_MIC_SOUND
952 //      if(ch >= 8) ch++;
953 #endif
954 #ifndef HAS_MODEM_SOUND
955 //      if(ch >= 9) ch++;
956 #endif
957 #ifndef HAS_2ND_ADPCM
958 //      if(ch >= 10) ch++;
959 #endif
960 #if 0   
961         if(ch == 0) { // BEEP
962                 mixer->set_volume(beep_mix_ch, decibel_l, decibel_r);
963         }
964         else if(ch == 1) { // CD-ROM
965                 //e_volume[1]->set_volume(0, decibel_l);
966                 //e_volume[1]->set_volume(1, decibel_r);
967                 mixer->set_volume(cdc_mix_ch, decibel_l, decibel_r);
968         }
969         else if(ch == 2) { // OPN2
970                 mixer->set_volume(opn2_mix_ch, decibel_l, decibel_r);
971         }
972         else if(ch == 3) { // ADPCM
973                 mixer->set_volume(pcm_mix_ch, decibel_l, decibel_r);
974         }
975         else if(ch == 4) { // LINE IN
976                 //mixer->set_volume(line_mix_ch, decibel_l, decibel_r);
977         } 
978         else if(ch == 5) { // MIC
979                 //mic->set_volume(0, (decibel_l + decibel_r) / 2);
980         } 
981         else if(ch == 6) { // MODEM
982                 //modem->set_volume(0, (decibel_l + decibel_r) / 2);
983         }
984 #ifdef HAS_2ND_ADPCM
985         else if(ch == 7) { // ADPCM
986                 adpcm2->set_volume(0, decibel_l, decibel_r);
987         }
988 #endif
989         else if(ch == 8) { // FDD
990                 fdc->set_volume(0, decibel_l, decibel_r);
991         }
992         else if(ch == 9) { // HDD(ToDo)
993                 fdc->set_volume(0, decibel_l, decibel_r);
994         }       
995 #else
996         if(ch == 0) { // BEEP
997                 beep->set_volume(0, decibel_l, decibel_r);
998         }
999         else if(ch == 1) { // CD-ROM
1000                 cdrom->set_volume(0, decibel_l, decibel_r);
1001         }       
1002         else if(ch == 2) { // OPN2
1003                 opn2->set_volume(0, decibel_l, decibel_r);
1004         }
1005         else if(ch == 3) { // ADPCM
1006                 rf5c68->set_volume(0, decibel_l, decibel_r);
1007         }
1008         else if(ch == 4) { // SEEK, HEAD UP / DOWN
1009                 seek_sound->set_volume(0, decibel_l, decibel_r);
1010                 head_up_sound->set_volume(0, decibel_l, decibel_r);
1011                 head_down_sound->set_volume(0, decibel_l, decibel_r);
1012         }
1013         
1014 #endif
1015 }
1016 #endif
1017
1018 // ----------------------------------------------------------------------------
1019 // notify key
1020 // ----------------------------------------------------------------------------
1021
1022 void VM::key_down(int code, bool repeat)
1023 {
1024         keyboard->key_down(code);
1025 }
1026
1027 void VM::key_up(int code)
1028 {
1029         keyboard->key_up(code);
1030 }
1031
1032 // ----------------------------------------------------------------------------
1033 // user interface
1034 // ----------------------------------------------------------------------------
1035 void VM::open_cart(int drv, const _TCHAR* file_path)
1036 {
1037         switch(drv) {
1038         case 0:
1039                 if(iccard1 != NULL) {
1040                         iccard1->open_cart(file_path);
1041                 }
1042                 break;
1043         case 1:
1044                 if(iccard2 != NULL) {
1045                         iccard2->open_cart(file_path);
1046                 }
1047                 break;
1048         }
1049 }
1050
1051 void VM::close_cart(int drv)
1052 {
1053         switch(drv) {
1054         case 0:
1055                 if(iccard1 != NULL) {
1056                         iccard1->close_cart();
1057                 }
1058                 break;
1059         case 1:
1060                 if(iccard2 != NULL) {
1061                         iccard2->close_cart();
1062                 }
1063                 break;
1064         }               
1065 }
1066
1067 bool VM::is_cart_inserted(int drv)
1068 {
1069         switch(drv) {
1070         case 0:
1071                 if(iccard1 != NULL) {
1072                         return iccard1->is_cart_inserted();
1073                 }
1074                 break;
1075         case 1:
1076                 if(iccard2 != NULL) {
1077                         return iccard2->is_cart_inserted();
1078                 }
1079                 break;
1080         }
1081         return false;
1082 }
1083
1084 void VM::open_floppy_disk(int drv, const _TCHAR* file_path, int bank)
1085 {
1086         fdc->open_disk(drv, file_path, bank);
1087 //      floppy->change_disk(drv);
1088 }
1089
1090 void VM::close_floppy_disk(int drv)
1091 {
1092         fdc->close_disk(drv);
1093 }
1094
1095 bool VM::is_floppy_disk_inserted(int drv)
1096 {
1097         return fdc->is_disk_inserted(drv);
1098 }
1099
1100 void VM::is_floppy_disk_protected(int drv, bool value)
1101 {
1102         fdc->is_disk_protected(drv, value);
1103 }
1104
1105 bool VM::is_floppy_disk_protected(int drv)
1106 {
1107         return fdc->is_disk_protected(drv);
1108 }
1109
1110 bool VM::is_frame_skippable()
1111 {
1112         return event->is_frame_skippable();
1113 }
1114
1115 void VM::update_config()
1116 {
1117         for(DEVICE* device = first_device; device; device = device->next_device) {
1118                 device->update_config();
1119         }
1120 }
1121
1122 double VM::get_current_usec()
1123 {
1124         if(event == NULL) return 0.0;
1125         return event->get_current_usec();
1126 }
1127
1128 uint64_t VM::get_current_clock_uint64()
1129 {
1130                 if(event == NULL) return (uint64_t)0;
1131                 return event->get_current_clock_uint64();
1132 }
1133
1134 #define STATE_VERSION   3
1135
1136 bool VM::process_state(FILEIO* state_fio, bool loading)
1137 {
1138         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
1139                 return false;
1140         }
1141         for(DEVICE* device = first_device; device; device = device->next_device) {
1142                 // Note: typeid(foo).name is fixed by recent ABI.Not decr. 6.
1143                 // const char *name = typeid(*device).name();
1144                 //       But, using get_device_name() instead of typeid(foo).name() 20181008 K.O
1145                 const char *name = device->get_device_name();
1146                 int len = strlen(name);
1147                 if(!state_fio->StateCheckInt32(len)) {
1148                         return false;
1149                 }
1150                 if(!state_fio->StateCheckBuffer(name, len, 1)) {
1151                         return false;
1152                 }
1153                 if(!device->process_state(state_fio, loading)) {
1154                         if(loading) {
1155                                 printf("Data loading Error: DEVID=%d\n", device->this_device_id);
1156                         }
1157                         return false;
1158                 }
1159         }
1160         // Machine specified.
1161         state_fio->StateValue(beep_mix_ch);
1162         state_fio->StateValue(cdc_mix_ch);
1163         state_fio->StateValue(opn2_mix_ch);
1164         state_fio->StateValue(pcm_mix_ch);
1165         state_fio->StateValue(line_mix_ch);
1166         state_fio->StateValue(modem_mix_ch);
1167         state_fio->StateValue(mic_mix_ch);
1168
1169         state_fio->StateValue(boot_seq);
1170         
1171         return true;
1172 }
1173