OSDN Git Service

[INITIAL] Import 20141226 version of http://homepage3.nifty.com/takeda-toshiya/common...
[csp-qt/common_source_project-fm7.git] / source / src / vm / fmr50 / fmr50.cpp
1 /*\r
2         FUJITSU FMR-50 Emulator 'eFMR-50'\r
3         FUJITSU FMR-60 Emulator 'eFMR-60'\r
4 \r
5         Author : Takeda.Toshiya\r
6         Date   : 2008.04.28 -\r
7 \r
8         [ virtual machine ]\r
9 */\r
10 \r
11 #include "fmr50.h"\r
12 #include "../../emu.h"\r
13 #include "../device.h"\r
14 #include "../event.h"\r
15 \r
16 #include "../hd46505.h"\r
17 #ifdef _FMR60\r
18 #include "../hd63484.h"\r
19 #endif\r
20 #include "../i8251.h"\r
21 #include "../i8253.h"\r
22 #include "../i8259.h"\r
23 #if defined(HAS_I286)\r
24 #include "../i286.h"\r
25 #else\r
26 #include "../i386.h"\r
27 #endif\r
28 #include "../io.h"\r
29 #include "../mb8877.h"\r
30 #include "../msm58321.h"\r
31 #include "../pcm1bit.h"\r
32 #include "../upd71071.h"\r
33 \r
34 #ifdef USE_DEBUGGER\r
35 #include "../debugger.h"\r
36 #endif\r
37 \r
38 #include "bios.h"\r
39 #include "cmos.h"\r
40 #include "floppy.h"\r
41 #include "keyboard.h"\r
42 #include "memory.h"\r
43 #include "scsi.h"\r
44 //#include "serial.h"\r
45 #include "timer.h"\r
46 \r
47 #include "../../fileio.h"\r
48 \r
49 // ----------------------------------------------------------------------------\r
50 // initialize\r
51 // ----------------------------------------------------------------------------\r
52 \r
53 VM::VM(EMU* parent_emu) : emu(parent_emu)\r
54 {\r
55 /*\r
56         Machine ID & CPU ID\r
57 \r
58         FMR-50FD/HD/LT  0xF8\r
59         FMR-50FX/HX     0xE0\r
60         FMR-50SFX/SHX   0xE8\r
61         FMR-50LT        0xF8\r
62         FMR-50NBX       0x28\r
63         FMR-50NB        0x60\r
64         FMR-50NE/T      0x08\r
65         FMR-CARD        0x70\r
66 \r
67         80286           0x00\r
68         80386           0x01\r
69         80386SX         0x03\r
70         80486           0x02\r
71 */\r
72         static const int cpu_clock[] = {\r
73 #if defined(HAS_I286)\r
74                  8000000, 12000000\r
75 #elif defined(HAS_I386)\r
76                 16000000, 20000000\r
77 #elif defined(HAS_I486)\r
78                 20000000, 25000000\r
79 #endif\r
80         };\r
81         \r
82 #if defined(_FMR60) && (defined(HAS_I386) || defined(HAS_I486) || defined(HAS_PENTIUM))\r
83         uint8 machine_id = 0xf0;        // FMR-70/80\r
84 #else\r
85         uint8 machine_id = 0xf8;        // FMR-50/60\r
86 #endif\r
87         \r
88         FILEIO* fio = new FILEIO();\r
89         if(fio->Fopen(emu->bios_path(_T("MACHINE.ID")), FILEIO_READ_BINARY)) {\r
90                 machine_id = fio->Fgetc();\r
91                 fio->Fclose();\r
92         }\r
93         delete fio;\r
94         \r
95         machine_id &= ~7;\r
96 #if defined(HAS_I286)\r
97         machine_id |= 0;        // 286\r
98 #elif defined(HAS_I386)\r
99 //      machine_id |= 1;        // 386DX\r
100         machine_id |= 3;        // 386SX\r
101 #elif defined(HAS_I486)\r
102         machine_id |= 2;        // 486SX/DX\r
103 #endif\r
104         \r
105         // create devices\r
106         first_device = last_device = NULL;\r
107         dummy = new DEVICE(this, emu);  // must be 1st device\r
108         event = new EVENT(this, emu);   // must be 2nd device\r
109         \r
110 #if defined(HAS_I286)\r
111         cpu = new I286(this, emu);\r
112 #else\r
113         cpu = new I386(this, emu);\r
114 #endif\r
115         crtc = new HD46505(this, emu);\r
116 #ifdef _FMR60\r
117         acrtc = new HD63484(this, emu);\r
118 #endif\r
119         sio = new I8251(this, emu);\r
120         pit0 = new I8253(this, emu);\r
121         pit1 = new I8253(this, emu);\r
122         pic = new I8259(this, emu);\r
123         io = new IO(this, emu);\r
124         fdc = new MB8877(this, emu);\r
125         rtc = new MSM58321(this, emu);\r
126         pcm = new PCM1BIT(this, emu);\r
127         dma = new UPD71071(this, emu);\r
128         \r
129         bios = new BIOS(this, emu);\r
130         cmos = new CMOS(this, emu);\r
131         floppy = new FLOPPY(this, emu);\r
132         keyboard = new KEYBOARD(this, emu);\r
133         memory = new MEMORY(this, emu);\r
134         scsi = new SCSI(this, emu);\r
135 //      serial = new SERIAL(this, emu);\r
136         timer = new TIMER(this, emu);\r
137         \r
138         // set contexts\r
139         event->set_context_cpu(cpu, cpu_clock[config.cpu_type & 1]);\r
140         event->set_context_sound(pcm);\r
141         \r
142 /*      pic     0       timer\r
143                 1       keyboard\r
144                 2       rs-232c\r
145                 3       ex rs-232c\r
146                 4       (option)\r
147                 5       (option)\r
148                 6       floppy drive or dma ???\r
149                 7       (slave)\r
150                 8       scsi\r
151                 9       (option)\r
152                 10      (option)\r
153                 11      (option)\r
154                 12      printer\r
155                 13      (option)\r
156                 14      (option)\r
157                 15      (reserve)\r
158 \r
159         dma     0       floppy drive\r
160                 1       hard drive\r
161                 2       (option)\r
162                 3       (reserve)\r
163 */\r
164         crtc->set_context_disp(memory, SIG_MEMORY_DISP, 1);\r
165         crtc->set_context_vsync(memory, SIG_MEMORY_VSYNC, 1);\r
166 #ifdef _FMR60\r
167         acrtc->set_vram_ptr((uint16*)memory->get_vram(), 0x80000);\r
168 #endif\r
169         pit0->set_context_ch0(timer, SIG_TIMER_CH0, 1);\r
170         pit0->set_context_ch1(timer, SIG_TIMER_CH1, 1);\r
171         pit0->set_context_ch2(pcm, SIG_PCM1BIT_SIGNAL, 1);\r
172         pit0->set_constant_clock(0, 307200);\r
173         pit0->set_constant_clock(1, 307200);\r
174         pit0->set_constant_clock(2, 307200);\r
175         pit1->set_constant_clock(1, 1228800);\r
176         pic->set_context_cpu(cpu);\r
177         fdc->set_context_drq(dma, SIG_UPD71071_CH0, 1);\r
178         fdc->set_context_irq(floppy, SIG_FLOPPY_IRQ, 1);\r
179         rtc->set_context_data(timer, SIG_TIMER_RTC, 0x0f, 0);\r
180         rtc->set_context_busy(timer, SIG_TIMER_RTC, 0x80);\r
181         dma->set_context_memory(memory);\r
182         dma->set_context_ch0(fdc);\r
183 //      dma->set_context_ch1(scsi);\r
184         \r
185         bios->set_context_mem(memory);\r
186         bios->set_context_io(io);\r
187         bios->set_cmos_ptr(cmos->get_cmos());\r
188         bios->set_vram_ptr(memory->get_vram());\r
189         bios->set_cvram_ptr(memory->get_cvram());\r
190 #ifdef _FMR60\r
191         bios->set_avram_ptr(memory->get_avram());\r
192 #else\r
193         bios->set_kvram_ptr(memory->get_kvram());\r
194 #endif\r
195         floppy->set_context_fdc(fdc);\r
196         floppy->set_context_pic(pic);\r
197         keyboard->set_context_pic(pic);\r
198         memory->set_context_cpu(cpu);\r
199         memory->set_machine_id(machine_id);\r
200         memory->set_context_crtc(crtc);\r
201         memory->set_chregs_ptr(crtc->get_regs());\r
202 //      scsi->set_context_dma(dma);\r
203 //      scsi->set_context_pic(pic);\r
204         timer->set_context_pcm(pcm);\r
205         timer->set_context_pic(pic);\r
206         timer->set_context_rtc(rtc);\r
207         \r
208         // cpu bus\r
209         cpu->set_context_mem(memory);\r
210         cpu->set_context_io(io);\r
211         cpu->set_context_intr(pic);\r
212         cpu->set_context_bios(bios);\r
213 #ifdef SINGLE_MODE_DMA\r
214         cpu->set_context_dma(dma);\r
215 #endif\r
216 #ifdef USE_DEBUGGER\r
217         cpu->set_context_debugger(new DEBUGGER(this, emu));\r
218 #endif\r
219         \r
220         // i/o bus\r
221         io->set_iomap_alias_rw(0x00, pic, I8259_ADDR_CHIP0 | 0);\r
222         io->set_iomap_alias_rw(0x02, pic, I8259_ADDR_CHIP0 | 1);\r
223         io->set_iomap_alias_rw(0x10, pic, I8259_ADDR_CHIP1 | 0);\r
224         io->set_iomap_alias_rw(0x12, pic, I8259_ADDR_CHIP1 | 1);\r
225         io->set_iomap_single_rw(0x20, memory);  // reset\r
226         io->set_iomap_single_r(0x21, memory);   // cpu misc\r
227         io->set_iomap_single_w(0x22, memory);   // dma\r
228         io->set_iomap_single_rw(0x24, memory);  // dma\r
229         io->set_iomap_single_r(0x26, timer);\r
230         io->set_iomap_single_r(0x27, timer);\r
231         io->set_iomap_single_r(0x30, memory);   // cpu id\r
232         io->set_iomap_alias_rw(0x40, pit0, 0);\r
233         io->set_iomap_alias_rw(0x42, pit0, 1);\r
234         io->set_iomap_alias_rw(0x44, pit0, 2);\r
235         io->set_iomap_alias_rw(0x46, pit0, 3);\r
236         io->set_iomap_alias_rw(0x50, pit1, 0);\r
237         io->set_iomap_alias_rw(0x52, pit1, 1);\r
238         io->set_iomap_alias_rw(0x54, pit1, 2);\r
239         io->set_iomap_alias_rw(0x56, pit1, 3);\r
240         io->set_iomap_single_rw(0x60, timer);\r
241         io->set_iomap_single_rw(0x70, timer);\r
242         io->set_iomap_single_w(0x80, timer);\r
243 #ifdef _FMRCARD\r
244         io->set_iomap_single_w(0x90, cmos);\r
245 #endif\r
246         io->set_iomap_range_rw(0xa0, 0xaf, dma);\r
247         io->set_iomap_alias_rw(0x200, fdc, 0);\r
248         io->set_iomap_alias_rw(0x202, fdc, 1);\r
249         io->set_iomap_alias_rw(0x204, fdc, 2);\r
250         io->set_iomap_alias_rw(0x206, fdc, 3);\r
251         io->set_iomap_single_rw(0x208, floppy);\r
252         io->set_iomap_single_rw(0x20c, floppy);\r
253         io->set_iomap_single_rw(0x400, memory); // crtc\r
254         io->set_iomap_single_rw(0x402, memory); // crtc\r
255         io->set_iomap_single_rw(0x404, memory); // crtc\r
256         io->set_iomap_single_w(0x408, memory);  // crtc\r
257         io->set_iomap_single_rw(0x40a, memory); // crtc\r
258         io->set_iomap_single_rw(0x40c, memory); // crtc\r
259         io->set_iomap_single_rw(0x40e, memory); // crtc\r
260         io->set_iomap_alias_rw(0x500, crtc, 0);\r
261         io->set_iomap_alias_rw(0x502, crtc, 1);\r
262 #ifdef _FMR60\r
263         io->set_iomap_range_rw(0x520, 0x523, acrtc);\r
264 #endif\r
265         io->set_iomap_single_rw(0x600, keyboard);\r
266         io->set_iomap_single_rw(0x602, keyboard);\r
267         io->set_iomap_single_rw(0x604, keyboard);\r
268         io->set_iomap_alias_rw(0xa00, sio, 0);\r
269         io->set_iomap_alias_rw(0xa02, sio, 1);\r
270 //      io->set_iomap_single_r(0xa04, serial);\r
271 //      io->set_iomap_single_r(0xa06, serial);\r
272 //      io->set_iomap_single_w(0xa08, serial);\r
273         io->set_iomap_single_rw(0xc30, scsi);\r
274         io->set_iomap_single_rw(0xc32, scsi);\r
275         io->set_iomap_range_rw(0x3000, 0x3fff, cmos);\r
276         io->set_iomap_range_rw(0xfd98, 0xfd9f, memory); // crtc\r
277         io->set_iomap_single_rw(0xfda0, memory);        // crtc\r
278         \r
279         // initialize all devices\r
280         for(DEVICE* device = first_device; device; device = device->next_device) {\r
281                 device->initialize();\r
282         }\r
283         for(int i = 0; i < MAX_DRIVE; i++) {\r
284                 bios->set_disk_handler(i, fdc->get_disk_handler(i));\r
285         }\r
286 }\r
287 \r
288 VM::~VM()\r
289 {\r
290         // delete all devices\r
291         for(DEVICE* device = first_device; device;) {\r
292                 DEVICE *next_device = device->next_device;\r
293                 device->release();\r
294                 delete device;\r
295                 device = next_device;\r
296         }\r
297 }\r
298 \r
299 DEVICE* VM::get_device(int id)\r
300 {\r
301         for(DEVICE* device = first_device; device; device = device->next_device) {\r
302                 if(device->this_device_id == id) {\r
303                         return device;\r
304                 }\r
305         }\r
306         return NULL;\r
307 }\r
308 \r
309 // ----------------------------------------------------------------------------\r
310 // drive virtual machine\r
311 // ----------------------------------------------------------------------------\r
312 \r
313 void VM::reset()\r
314 {\r
315         // reset all devices\r
316         for(DEVICE* device = first_device; device; device = device->next_device) {\r
317                 device->reset();\r
318         }\r
319         // temporary fix...\r
320         for(DEVICE* device = first_device; device; device = device->next_device) {\r
321                 device->reset();\r
322         }\r
323 }\r
324 \r
325 void VM::run()\r
326 {\r
327         event->drive();\r
328 }\r
329 \r
330 // ----------------------------------------------------------------------------\r
331 // debugger\r
332 // ----------------------------------------------------------------------------\r
333 \r
334 #ifdef USE_DEBUGGER\r
335 DEVICE *VM::get_cpu(int index)\r
336 {\r
337         if(index == 0) {\r
338                 return cpu;\r
339         }\r
340         return NULL;\r
341 }\r
342 #endif\r
343 \r
344 // ----------------------------------------------------------------------------\r
345 // draw screen\r
346 // ----------------------------------------------------------------------------\r
347 \r
348 void VM::draw_screen()\r
349 {\r
350         memory->draw_screen();\r
351 }\r
352 \r
353 int VM::access_lamp()\r
354 {\r
355         uint32 status = fdc->read_signal(0) | bios->read_signal(0);\r
356         return (status & 0x10) ? 4 : (status & (1 | 4)) ? 1 : (status & (2 | 8)) ? 2 : 0;\r
357 }\r
358 \r
359 // ----------------------------------------------------------------------------\r
360 // soud manager\r
361 // ----------------------------------------------------------------------------\r
362 \r
363 void VM::initialize_sound(int rate, int samples)\r
364 {\r
365         // init sound manager\r
366         event->initialize_sound(rate, samples);\r
367         \r
368         // init sound gen\r
369         pcm->init(rate, 8000);\r
370 }\r
371 \r
372 uint16* VM::create_sound(int* extra_frames)\r
373 {\r
374         return event->create_sound(extra_frames);\r
375 }\r
376 \r
377 int VM::sound_buffer_ptr()\r
378 {\r
379         return event->sound_buffer_ptr();\r
380 }\r
381 \r
382 // ----------------------------------------------------------------------------\r
383 // notify key\r
384 // ----------------------------------------------------------------------------\r
385 \r
386 void VM::key_down(int code, bool repeat)\r
387 {\r
388         keyboard->key_down(code);\r
389 }\r
390 \r
391 void VM::key_up(int code)\r
392 {\r
393         keyboard->key_up(code);\r
394 }\r
395 \r
396 // ----------------------------------------------------------------------------\r
397 // user interface\r
398 // ----------------------------------------------------------------------------\r
399 \r
400 void VM::open_disk(int drv, _TCHAR* file_path, int offset)\r
401 {\r
402         fdc->open_disk(drv, file_path, offset);\r
403         floppy->change_disk(drv);\r
404 }\r
405 \r
406 void VM::close_disk(int drv)\r
407 {\r
408         fdc->close_disk(drv);\r
409 }\r
410 \r
411 bool VM::disk_inserted(int drv)\r
412 {\r
413         return fdc->disk_inserted(drv);\r
414 }\r
415 \r
416 bool VM::now_skip()\r
417 {\r
418         return event->now_skip();\r
419 }\r
420 \r
421 void VM::update_config()\r
422 {\r
423         for(DEVICE* device = first_device; device; device = device->next_device) {\r
424                 device->update_config();\r
425         }\r
426 }\r
427 \r