OSDN Git Service

[VM] Fix missing name of components.
[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 #if defined(_USE_QT)
63         dummy->set_device_name(_T("1st Dummy"));
64         event->set_device_name(_T("EVENT"));
65
66         dma->set_device_name(_T("i8237 DMAC"));
67         sio_kb->set_device_name(_T("i8251 SIO(KEYBOARD)"));
68         sio_sub->set_device_name(_T("i8251 SIO(SUB SYSTEM)"));
69         sio_ch1->set_device_name(_T("i8251 SIO(RS-232C #1)"));
70         sio_ch2->set_device_name(_T("i8251 SIO(RS-232C #2)"));
71         pit->set_device_name(_T("i8253 PIT"));
72         pic->set_device_name(_T("i8259 PIC"));
73         cpu->set_device_name(_T("CPU(i8086)"));
74 #endif
75         
76         scsi_host = new SCSI_HOST(this, emu);
77 #if defined(_USE_QT)
78         scsi_host->set_device_name(_T("SCSI HOST"));
79 #endif  
80         for(int i = 0; i < 7; i++) {
81                 if(FILEIO::IsFileExisting(create_local_path(_T("SCSI%d.DAT"), i))) {
82                         SCSI_HDD* scsi_hdd = new SCSI_HDD(this, emu);
83 #if defined(_USE_QT)
84                         char d_name[64] = {0};
85                         snprintf(d_name, 64, "SCSI DISK #%d", i + 1);
86                         scsi_hdd->set_device_name(d_name);
87 #endif                  
88                         scsi_hdd->scsi_id = i;
89                         scsi_hdd->set_context_interface(scsi_host);
90                         scsi_host->set_context_target(scsi_hdd);
91                 }
92         }
93         psg = new SN76489AN(this, emu);
94 #if defined(_USE_QT)
95         psg->set_device_name(_T("SN76489 PSG"));
96 #endif  
97         if(FILEIO::IsFileExisting(create_local_path(_T("IPL.ROM")))) {
98                 bios = NULL;
99         } else {
100                 bios = new BIOS(this, emu);
101 #if defined(_USE_QT)
102                 bios->set_device_name(_T("PSEUDO BIOS"));
103 #endif  
104         }
105         cmos = new CMOS(this, emu);
106         floppy = new FLOPPY(this, emu);
107         keyboard = new KEYBOARD(this, emu);
108         memory = new MEMORY(this, emu);
109         rtc = new RTC(this, emu);
110         scsi = new SCSI(this, emu);
111         serial = new SERIAL(this, emu);
112         system = new SYSTEM(this, emu);
113         timer = new TIMER(this, emu);
114 #if defined(_USE_QT)
115         cmos->set_device_name(_T("CMOS RAM"));
116         floppy->set_device_name(_T("FLOPPY I/F"));
117         keyboard->set_device_name(_T("KEYBOARD"));
118         memory->set_device_name(_T("MEMORY"));
119         rtc->set_device_name(_T("RTC"));
120         scsi->set_device_name(_T("SCSI I/F"));
121         serial->set_device_name(_T("SERIAL I/F"));
122         system->set_device_name(_T("SYSTEM I/O"));
123         timer->set_device_name(_T("TIMER I/F"));
124 #endif
125         // set contexts
126         event->set_context_cpu(cpu);
127         event->set_context_sound(psg);
128         
129         dma->set_context_memory(memory);
130         dma->set_context_ch0(fdc);
131         dma->set_context_ch1(scsi_host);
132         dma->set_context_tc1(scsi, SIG_SCSI_TC, 1);
133         sio_kb->set_context_rxrdy(serial, SIG_SERIAL_RXRDY_KB, 1);
134         sio_kb->set_context_txrdy(serial, SIG_SERIAL_TXRDY_KB, 1);
135         sio_sub->set_context_rxrdy(serial, SIG_SERIAL_RXRDY_SUB, 1);
136         sio_sub->set_context_txrdy(serial, SIG_SERIAL_TXRDY_SUB, 1);
137         sio_ch1->set_context_rxrdy(serial, SIG_SERIAL_RXRDY_CH1, 1);
138         sio_ch1->set_context_txrdy(serial, SIG_SERIAL_TXRDY_CH1, 1);
139         sio_ch2->set_context_rxrdy(serial, SIG_SERIAL_RXRDY_CH2, 1);
140         sio_ch2->set_context_txrdy(serial, SIG_SERIAL_TXRDY_CH2, 1);
141         pit->set_context_ch0(timer, SIG_TIMER_CH0, 1);
142         pit->set_context_ch1(timer, SIG_TIMER_CH1, 1);
143         pit->set_constant_clock(0, 1000000);
144         pit->set_constant_clock(1, 1000000);
145         pic->set_context_cpu(cpu);
146         fdc->set_context_drq(dma, SIG_I8237_CH0, 1);
147         fdc->set_context_irq(floppy, SIG_FLOPPY_IRQ, 1);
148         scsi_host->set_context_irq(scsi, SIG_SCSI_IRQ, 1);
149         scsi_host->set_context_drq(scsi, SIG_SCSI_DRQ, 1);
150         
151         floppy->set_context_fdc(fdc);
152         floppy->set_context_pic(pic);
153         keyboard->set_context_sio(sio_kb);
154         memory->set_context_cpu(cpu);
155         memory->set_context_dma(dma);
156         rtc->set_context_pic(pic);
157         scsi->set_context_dma(dma);
158         scsi->set_context_pic(pic);
159         scsi->set_context_host(scsi_host);
160         serial->set_context_pic(pic);
161         serial->set_context_sio(sio_kb, sio_sub, sio_ch1, sio_ch2);
162         timer->set_context_pic(pic);
163         
164         // cpu bus
165         cpu->set_context_mem(memory);
166         cpu->set_context_io(io);
167         cpu->set_context_intr(pic);
168         if(bios) {
169                 bios->set_context_mem(memory);
170                 bios->set_context_io(io);
171                 bios->set_cmos_ptr(cmos->get_cmos());
172                 bios->set_vram_ptr(memory->get_vram());
173                 bios->set_cvram_ptr(memory->get_cvram());
174                 bios->set_kvram_ptr(memory->get_kvram());
175                 cpu->set_context_bios(bios);
176         }
177 #ifdef SINGLE_MODE_DMA
178         cpu->set_context_dma(dma);
179 #endif
180 #ifdef USE_DEBUGGER
181         cpu->set_context_debugger(new DEBUGGER(this, emu));
182 #endif
183         
184         // i/o bus
185         io->set_iomap_range_rw(0x00, 0x07, rtc);
186         io->set_iomap_range_rw(0x08, 0x09, sio_kb);
187         io->set_iomap_range_rw(0x0a, 0x0b, serial);
188         io->set_iomap_range_rw(0x10, 0x11, sio_sub);
189         io->set_iomap_range_rw(0x12, 0x13, serial);
190         io->set_iomap_single_r(0x18, system);
191         io->set_iomap_range_rw(0x1d, 0x1e, memory);
192         io->set_iomap_range_r(0x20, 0x21, system);
193         io->set_iomap_single_rw(0x26, memory);
194         io->set_iomap_range_rw(0x30, 0x33, fdc);
195         io->set_iomap_range_rw(0x34, 0x36, floppy);
196         io->set_iomap_single_w(0x40, psg);
197         io->set_iomap_range_rw(0x42, 0x43, timer);
198         io->set_iomap_range_rw(0x46, 0x47, system);
199         io->set_iomap_range_rw(0x60, 0x61, sio_ch1);
200         io->set_iomap_range_rw(0x62, 0x66, serial);
201         io->set_iomap_range_rw(0x70, 0x71, sio_ch2);
202         io->set_iomap_range_rw(0x72, 0x76, serial);
203         io->set_iomap_alias_rw(0x100, pic, I8259_ADDR_CHIP0 | 0);
204         io->set_iomap_alias_rw(0x101, pic, I8259_ADDR_CHIP0 | 1);
205         io->set_iomap_alias_rw(0x108, pic, I8259_ADDR_CHIP1 | 0);
206         io->set_iomap_alias_rw(0x10a, pic, I8259_ADDR_CHIP1 | 1);
207         io->set_iomap_range_rw(0x110, 0x11f, dma);
208         io->set_iomap_range_w(0x120, 0x123, memory);
209         io->set_iomap_range_rw(0x130, 0x133, pit);
210         io->set_iomap_range_rw(0x2f0, 0x2f3, scsi);
211         io->set_iomap_range_rw(0x300, 0x30f, memory);
212         io->set_iomap_range_rw(0xc000, 0xdfff, cmos);
213         io->set_iomap_single_rw(0xff00, system);
214         
215         // initialize all devices
216         for(DEVICE* device = first_device; device; device = device->next_device) {
217                 device->initialize();
218         }
219         if(bios) {
220                 for(int i = 0; i < MAX_DRIVE; i++) {
221                         bios->set_disk_handler(i, fdc->get_disk_handler(i));
222                 }
223         }
224 }
225
226 VM::~VM()
227 {
228         // delete all devices
229         for(DEVICE* device = first_device; device;) {
230                 DEVICE *next_device = device->next_device;
231                 device->release();
232                 delete device;
233                 device = next_device;
234         }
235 }
236
237 DEVICE* VM::get_device(int id)
238 {
239         for(DEVICE* device = first_device; device; device = device->next_device) {
240                 if(device->this_device_id == id) {
241                         return device;
242                 }
243         }
244         return NULL;
245 }
246
247 // ----------------------------------------------------------------------------
248 // drive virtual machine
249 // ----------------------------------------------------------------------------
250
251 void VM::reset()
252 {
253         // reset all devices
254         for(DEVICE* device = first_device; device; device = device->next_device) {
255                 device->reset();
256         }
257         // temporary fix...
258         for(DEVICE* device = first_device; device; device = device->next_device) {
259                 device->reset();
260         }
261         
262         // set devices
263         sio_kb->write_signal(SIG_I8251_DSR, 1, 1);
264         sio_sub->write_signal(SIG_I8251_DSR, 0, 0);
265 }
266
267 void VM::run()
268 {
269         event->drive();
270 }
271
272 // ----------------------------------------------------------------------------
273 // debugger
274 // ----------------------------------------------------------------------------
275
276 #ifdef USE_DEBUGGER
277 DEVICE *VM::get_cpu(int index)
278 {
279         if(index == 0) {
280                 return cpu;
281         }
282         return NULL;
283 }
284 #endif
285
286 // ----------------------------------------------------------------------------
287 // draw screen
288 // ----------------------------------------------------------------------------
289
290 void VM::draw_screen()
291 {
292         memory->draw_screen();
293 }
294
295 uint32_t VM::get_access_lamp_status()
296 {
297         uint32_t status_fdd = fdc->read_signal(0);
298         uint32_t status_hdd = scsi_host->read_signal(0);
299         if(bios) {
300                 uint32_t status = bios->read_signal(0);
301                 status_fdd |= status & 0x0f;
302                 status_hdd |= status >> 4;
303         }
304         return (status_hdd) ? 4 : (status_fdd & (1 | 4)) ? 1 : (status_fdd & (2 | 8)) ? 2 : 0;
305 }
306
307 // ----------------------------------------------------------------------------
308 // soud manager
309 // ----------------------------------------------------------------------------
310
311 void VM::initialize_sound(int rate, int samples)
312 {
313         // init sound manager
314         event->initialize_sound(rate, samples);
315         
316         // init sound gen
317         psg->initialize_sound(rate, 125000, 10000);
318 }
319
320 uint16_t* VM::create_sound(int* extra_frames)
321 {
322         return event->create_sound(extra_frames);
323 }
324
325 int VM::get_sound_buffer_ptr()
326 {
327         return event->get_sound_buffer_ptr();
328 }
329
330 #ifdef USE_SOUND_VOLUME
331 void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
332 {
333         if(ch == 0) {
334                 psg->set_volume(0, decibel_l, decibel_r);
335         }
336 }
337 #endif
338
339 // ----------------------------------------------------------------------------
340 // notify key
341 // ----------------------------------------------------------------------------
342
343 void VM::key_down(int code, bool repeat)
344 {
345         keyboard->key_down(code);
346 }
347
348 void VM::key_up(int code)
349 {
350         keyboard->key_up(code);
351 }
352
353 // ----------------------------------------------------------------------------
354 // user interface
355 // ----------------------------------------------------------------------------
356
357 void VM::open_floppy_disk(int drv, const _TCHAR* file_path, int bank)
358 {
359         fdc->open_disk(drv, file_path, bank);
360         floppy->change_disk(drv);
361 }
362
363 void VM::close_floppy_disk(int drv)
364 {
365         fdc->close_disk(drv);
366 }
367
368 bool VM::is_floppy_disk_inserted(int drv)
369 {
370         return fdc->is_disk_inserted(drv);
371 }
372
373 void VM::is_floppy_disk_protected(int drv, bool value)
374 {
375         fdc->is_disk_protected(drv, value);
376 }
377
378 bool VM::is_floppy_disk_protected(int drv)
379 {
380         return fdc->is_disk_protected(drv);
381 }
382
383 bool VM::is_frame_skippable()
384 {
385         return event->is_frame_skippable();
386 }
387
388 void VM::update_config()
389 {
390         for(DEVICE* device = first_device; device; device = device->next_device) {
391                 device->update_config();
392         }
393 }
394
395 #define STATE_VERSION   3
396
397 void VM::save_state(FILEIO* state_fio)
398 {
399         state_fio->FputUint32(STATE_VERSION);
400         
401         for(DEVICE* device = first_device; device; device = device->next_device) {
402                 device->save_state(state_fio);
403         }
404 }
405
406 bool VM::load_state(FILEIO* state_fio)
407 {
408         if(state_fio->FgetUint32() != STATE_VERSION) {
409                 return false;
410         }
411         for(DEVICE* device = first_device; device; device = device->next_device) {
412                 if(!device->load_state(state_fio)) {
413                         return false;
414                 }
415         }
416         return true;
417 }
418