OSDN Git Service

[General][Qt] Merge updtream 2016-03-05 (1).FTBFSs exist yet.
[csp-qt/common_source_project-fm7.git] / source / src / vm / fmr30 / fmr30.cpp
1 /*
2         FUJITSU FMR-30 Emulator 'eFMR-30'
3
4         Author : Takeda.Toshiya
5         Date   : 2008.12.29 -
6
7         [ virtual machine ]
8 */
9
10 #include "fmr30.h"
11 #include "../../emu.h"
12 #include "../device.h"
13 #include "../event.h"
14
15 #include "../i8237.h"
16 #include "../i8251.h"
17 #include "../i8253.h"
18 #include "../i8259.h"
19 #include "../i286.h"
20 #include "../io.h"
21 #include "../mb8877.h"
22 #include "../scsi_hdd.h"
23 #include "../scsi_host.h"
24 #include "../sn76489an.h"
25
26 #ifdef USE_DEBUGGER
27 #include "../debugger.h"
28 #endif
29
30 #include "../fmr50/bios.h"
31 #include "cmos.h"
32 #include "floppy.h"
33 #include "keyboard.h"
34 #include "memory.h"
35 #include "rtc.h"
36 #include "scsi.h"
37 #include "serial.h"
38 #include "system.h"
39 #include "timer.h"
40
41 // ----------------------------------------------------------------------------
42 // initialize
43 // ----------------------------------------------------------------------------
44
45 VM::VM(EMU* parent_emu) : emu(parent_emu)
46 {
47         // create devices
48         first_device = last_device = NULL;
49         dummy = new DEVICE(this, emu);  // must be 1st device
50         event = new EVENT(this, emu);   // must be 2nd device
51         
52         dma = new I8237(this, emu);
53         sio_kb = new I8251(this, emu);  // keyboard
54         sio_sub = new I8251(this, emu); // sub display
55         sio_ch1 = new I8251(this, emu); // RS-232C ch.1
56         sio_ch2 = new I8251(this, emu); // RS-232C ch.2
57         pit = new I8253(this, emu);
58         pic = new I8259(this, emu);
59         cpu = new I286(this, emu);
60         io = new IO(this, emu);
61         fdc = new MB8877(this, emu);
62         scsi_host = new SCSI_HOST(this, emu);
63         for(int i = 0; i < 7; i++) {
64                 if(FILEIO::IsFileExisting(create_local_path(_T("SCSI%d.DAT"), i))) {
65                         SCSI_HDD* scsi_hdd = new SCSI_HDD(this, emu);
66                         scsi_hdd->scsi_id = i;
67                         scsi_hdd->set_context_interface(scsi_host);
68                         scsi_host->set_context_target(scsi_hdd);
69                 }
70         }
71         psg = new SN76489AN(this, emu);
72         
73         if(FILEIO::IsFileExisting(create_local_path(_T("IPL.ROM")))) {
74                 bios = NULL;
75         } else {
76                 bios = new BIOS(this, emu);
77         }
78         cmos = new CMOS(this, emu);
79         floppy = new FLOPPY(this, emu);
80         keyboard = new KEYBOARD(this, emu);
81         memory = new MEMORY(this, emu);
82         rtc = new RTC(this, emu);
83         scsi = new SCSI(this, emu);
84         serial = new SERIAL(this, emu);
85         system = new SYSTEM(this, emu);
86         timer = new TIMER(this, emu);
87         
88         // set contexts
89         event->set_context_cpu(cpu);
90         event->set_context_sound(psg);
91         
92         dma->set_context_memory(memory);
93         dma->set_context_ch0(fdc);
94         dma->set_context_ch1(scsi_host);
95         dma->set_context_tc1(scsi, SIG_SCSI_TC, 1);
96         sio_kb->set_context_rxrdy(serial, SIG_SERIAL_RXRDY_KB, 1);
97         sio_kb->set_context_txrdy(serial, SIG_SERIAL_TXRDY_KB, 1);
98         sio_sub->set_context_rxrdy(serial, SIG_SERIAL_RXRDY_SUB, 1);
99         sio_sub->set_context_txrdy(serial, SIG_SERIAL_TXRDY_SUB, 1);
100         sio_ch1->set_context_rxrdy(serial, SIG_SERIAL_RXRDY_CH1, 1);
101         sio_ch1->set_context_txrdy(serial, SIG_SERIAL_TXRDY_CH1, 1);
102         sio_ch2->set_context_rxrdy(serial, SIG_SERIAL_RXRDY_CH2, 1);
103         sio_ch2->set_context_txrdy(serial, SIG_SERIAL_TXRDY_CH2, 1);
104         pit->set_context_ch0(timer, SIG_TIMER_CH0, 1);
105         pit->set_context_ch1(timer, SIG_TIMER_CH1, 1);
106         pit->set_constant_clock(0, 1000000);
107         pit->set_constant_clock(1, 1000000);
108         pic->set_context_cpu(cpu);
109         fdc->set_context_drq(dma, SIG_I8237_CH0, 1);
110         fdc->set_context_irq(floppy, SIG_FLOPPY_IRQ, 1);
111         scsi_host->set_context_irq(scsi, SIG_SCSI_IRQ, 1);
112         scsi_host->set_context_drq(scsi, SIG_SCSI_DRQ, 1);
113         
114         floppy->set_context_fdc(fdc);
115         floppy->set_context_pic(pic);
116         keyboard->set_context_sio(sio_kb);
117         memory->set_context_cpu(cpu);
118         memory->set_context_dma(dma);
119         rtc->set_context_pic(pic);
120         scsi->set_context_dma(dma);
121         scsi->set_context_pic(pic);
122         scsi->set_context_host(scsi_host);
123         serial->set_context_pic(pic);
124         serial->set_context_sio(sio_kb, sio_sub, sio_ch1, sio_ch2);
125         timer->set_context_pic(pic);
126         
127         // cpu bus
128         cpu->set_context_mem(memory);
129         cpu->set_context_io(io);
130         cpu->set_context_intr(pic);
131         if(bios) {
132                 bios->set_context_mem(memory);
133                 bios->set_context_io(io);
134                 bios->set_cmos_ptr(cmos->get_cmos());
135                 bios->set_vram_ptr(memory->get_vram());
136                 bios->set_cvram_ptr(memory->get_cvram());
137                 bios->set_kvram_ptr(memory->get_kvram());
138                 cpu->set_context_bios(bios);
139         }
140 #ifdef SINGLE_MODE_DMA
141         cpu->set_context_dma(dma);
142 #endif
143 #ifdef USE_DEBUGGER
144         cpu->set_context_debugger(new DEBUGGER(this, emu));
145 #endif
146         
147         // i/o bus
148         io->set_iomap_range_rw(0x00, 0x07, rtc);
149         io->set_iomap_range_rw(0x08, 0x09, sio_kb);
150         io->set_iomap_range_rw(0x0a, 0x0b, serial);
151         io->set_iomap_range_rw(0x10, 0x11, sio_sub);
152         io->set_iomap_range_rw(0x12, 0x13, serial);
153         io->set_iomap_single_r(0x18, system);
154         io->set_iomap_range_rw(0x1d, 0x1e, memory);
155         io->set_iomap_range_r(0x20, 0x21, system);
156         io->set_iomap_single_rw(0x26, memory);
157         io->set_iomap_range_rw(0x30, 0x33, fdc);
158         io->set_iomap_range_rw(0x34, 0x36, floppy);
159         io->set_iomap_single_w(0x40, psg);
160         io->set_iomap_range_rw(0x42, 0x43, timer);
161         io->set_iomap_range_rw(0x46, 0x47, system);
162         io->set_iomap_range_rw(0x60, 0x61, sio_ch1);
163         io->set_iomap_range_rw(0x62, 0x66, serial);
164         io->set_iomap_range_rw(0x70, 0x71, sio_ch2);
165         io->set_iomap_range_rw(0x72, 0x76, serial);
166         io->set_iomap_alias_rw(0x100, pic, I8259_ADDR_CHIP0 | 0);
167         io->set_iomap_alias_rw(0x101, pic, I8259_ADDR_CHIP0 | 1);
168         io->set_iomap_alias_rw(0x108, pic, I8259_ADDR_CHIP1 | 0);
169         io->set_iomap_alias_rw(0x10a, pic, I8259_ADDR_CHIP1 | 1);
170         io->set_iomap_range_rw(0x110, 0x11f, dma);
171         io->set_iomap_range_w(0x120, 0x123, memory);
172         io->set_iomap_range_rw(0x130, 0x133, pit);
173         io->set_iomap_range_rw(0x2f0, 0x2f3, scsi);
174         io->set_iomap_range_rw(0x300, 0x30f, memory);
175         io->set_iomap_range_rw(0xc000, 0xdfff, cmos);
176         io->set_iomap_single_rw(0xff00, system);
177         
178         // initialize all devices
179         for(DEVICE* device = first_device; device; device = device->next_device) {
180                 device->initialize();
181         }
182         if(bios) {
183                 for(int i = 0; i < MAX_DRIVE; i++) {
184                         bios->set_disk_handler(i, fdc->get_disk_handler(i));
185                 }
186         }
187 }
188
189 VM::~VM()
190 {
191         // delete all devices
192         for(DEVICE* device = first_device; device;) {
193                 DEVICE *next_device = device->next_device;
194                 device->release();
195                 delete device;
196                 device = next_device;
197         }
198 }
199
200 DEVICE* VM::get_device(int id)
201 {
202         for(DEVICE* device = first_device; device; device = device->next_device) {
203                 if(device->this_device_id == id) {
204                         return device;
205                 }
206         }
207         return NULL;
208 }
209
210 // ----------------------------------------------------------------------------
211 // drive virtual machine
212 // ----------------------------------------------------------------------------
213
214 void VM::reset()
215 {
216         // reset all devices
217         for(DEVICE* device = first_device; device; device = device->next_device) {
218                 device->reset();
219         }
220         // temporary fix...
221         for(DEVICE* device = first_device; device; device = device->next_device) {
222                 device->reset();
223         }
224         
225         // set devices
226         sio_kb->write_signal(SIG_I8251_DSR, 1, 1);
227         sio_sub->write_signal(SIG_I8251_DSR, 0, 0);
228 }
229
230 void VM::run()
231 {
232         event->drive();
233 }
234
235 // ----------------------------------------------------------------------------
236 // debugger
237 // ----------------------------------------------------------------------------
238
239 #ifdef USE_DEBUGGER
240 DEVICE *VM::get_cpu(int index)
241 {
242         if(index == 0) {
243                 return cpu;
244         }
245         return NULL;
246 }
247 #endif
248
249 // ----------------------------------------------------------------------------
250 // draw screen
251 // ----------------------------------------------------------------------------
252
253 void VM::draw_screen()
254 {
255         memory->draw_screen();
256 }
257
258 uint32_t VM::get_access_lamp_status()
259 {
260         uint32_t status_fdd = fdc->read_signal(0);
261         uint32_t status_hdd = scsi_host->read_signal(0);
262         if(bios) {
263                 uint32_t status = bios->read_signal(0);
264                 status_fdd |= status & 0x0f;
265                 status_hdd |= status >> 4;
266         }
267         return (status_hdd) ? 4 : (status_fdd & (1 | 4)) ? 1 : (status_fdd & (2 | 8)) ? 2 : 0;
268 }
269
270 // ----------------------------------------------------------------------------
271 // soud manager
272 // ----------------------------------------------------------------------------
273
274 void VM::initialize_sound(int rate, int samples)
275 {
276         // init sound manager
277         event->initialize_sound(rate, samples);
278         
279         // init sound gen
280         psg->initialize_sound(rate, 125000, 10000);
281 }
282
283 uint16_t* VM::create_sound(int* extra_frames)
284 {
285         return event->create_sound(extra_frames);
286 }
287
288 int VM::get_sound_buffer_ptr()
289 {
290         return event->get_sound_buffer_ptr();
291 }
292
293 #ifdef USE_SOUND_VOLUME
294 void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
295 {
296         if(ch == 0) {
297                 psg->set_volume(0, decibel_l, decibel_r);
298         }
299 }
300 #endif
301
302 // ----------------------------------------------------------------------------
303 // notify key
304 // ----------------------------------------------------------------------------
305
306 void VM::key_down(int code, bool repeat)
307 {
308         keyboard->key_down(code);
309 }
310
311 void VM::key_up(int code)
312 {
313         keyboard->key_up(code);
314 }
315
316 // ----------------------------------------------------------------------------
317 // user interface
318 // ----------------------------------------------------------------------------
319
320 void VM::open_floppy_disk(int drv, const _TCHAR* file_path, int bank)
321 {
322         fdc->open_disk(drv, file_path, bank);
323         floppy->change_disk(drv);
324 }
325
326 void VM::close_floppy_disk(int drv)
327 {
328         fdc->close_disk(drv);
329 }
330
331 bool VM::is_floppy_disk_inserted(int drv)
332 {
333         return fdc->is_disk_inserted(drv);
334 }
335
336 void VM::is_floppy_disk_protected(int drv, bool value)
337 {
338         fdc->is_disk_protected(drv, value);
339 }
340
341 bool VM::is_floppy_disk_protected(int drv)
342 {
343         return fdc->is_disk_protected(drv);
344 }
345
346 bool VM::is_frame_skippable()
347 {
348         return event->is_frame_skippable();
349 }
350
351 void VM::update_config()
352 {
353         for(DEVICE* device = first_device; device; device = device->next_device) {
354                 device->update_config();
355         }
356 }
357
358 #define STATE_VERSION   2
359
360 void VM::save_state(FILEIO* state_fio)
361 {
362         state_fio->FputUint32(STATE_VERSION);
363         
364         for(DEVICE* device = first_device; device; device = device->next_device) {
365                 device->save_state(state_fio);
366         }
367 }
368
369 bool VM::load_state(FILEIO* state_fio)
370 {
371         if(state_fio->FgetUint32() != STATE_VERSION) {
372                 return false;
373         }
374         for(DEVICE* device = first_device; device; device = device->next_device) {
375                 if(!device->load_state(state_fio)) {
376                         return false;
377                 }
378         }
379         return true;
380 }
381