OSDN Git Service

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