OSDN Git Service

f1eafccfe383b81b95f29caf83c86ab5bb8d4b4c
[csp-qt/common_source_project-fm7.git] / source / src / vm / pc100 / pc100.cpp
1 /*
2         NEC PC-100 Emulator 'ePC-100'
3
4         Author : Takeda.Toshiya
5         Date   : 2008.07.12 -
6
7         [ virtual machine ]
8 */
9
10 #include "pc100.h"
11 #include "../../emu.h"
12 #include "../device.h"
13 #include "../event.h"
14
15 #include "../and.h"
16 #include "../beep.h"
17 #include "../disk.h"
18 #include "../i8251.h"
19 #include "../i8255.h"
20 #include "../i8259.h"
21 #include "../i286.h"
22 #include "../io.h"
23 #include "../memory.h"
24 #include "../msm58321.h"
25 #include "../pcm1bit.h"
26 #include "../upd765a.h"
27
28 #ifdef USE_DEBUGGER
29 #include "../debugger.h"
30 #endif
31
32 #include "crtc.h"
33 #include "ioctrl.h"
34 #include "kanji.h"
35
36 // ----------------------------------------------------------------------------
37 // initialize
38 // ----------------------------------------------------------------------------
39
40 VM::VM(EMU* parent_emu) : emu(parent_emu)
41 {
42         // create devices
43         first_device = last_device = NULL;
44         dummy = new DEVICE(this, emu);  // must be 1st device
45         event = new EVENT(this, emu);   // must be 2nd device
46 #if defined(_USE_QT)
47         dummy->set_device_name(_T("1st Dummy"));
48         event->set_device_name(_T("EVENT"));
49 #endif  
50         
51         and_drq = new AND(this, emu);
52         beep = new BEEP(this, emu);
53         sio = new I8251(this, emu);
54         pio0 = new I8255(this, emu);
55         pio1 = new I8255(this, emu);
56         pic = new I8259(this, emu);
57         cpu = new I286(this, emu);
58         io = new IO(this, emu);
59         memory = new MEMORY(this, emu);
60         rtc = new MSM58321(this, emu);
61         pcm = new PCM1BIT(this, emu);
62         fdc = new UPD765A(this, emu);
63 #if defined(_USE_QT)
64         and_drq->set_device_name(_T("AND GATE(FDC DRQ)"));
65         pio0->set_device_name(_T("i8255 PIO(MSM5832 RTC)"));
66         pio1->set_device_name(_T("i8255 PIO(CRTC)"));
67         cpu->set_device_name(_T("CPU(i8086)"));
68 #endif  
69         
70         crtc = new CRTC(this, emu);
71         ioctrl = new IOCTRL(this, emu);
72         kanji = new KANJI(this, emu);
73 #if defined(_USE_QT)
74         crtc->set_device_name(_T("CRTC"));
75         ioctrl->set_device_name(_T("I/O CONTROL"));
76         kanji->set_device_name(_T("KANJI I/F"));
77 #endif  
78         // set contexts
79         event->set_context_cpu(cpu);
80         event->set_context_sound(beep);
81         event->set_context_sound(pcm);
82         
83         and_drq->set_context_out(cpu, SIG_CPU_NMI, 1);
84         and_drq->set_mask(SIG_AND_BIT_0 | SIG_AND_BIT_1);
85         sio->set_context_rxrdy(pic, SIG_I8259_IR1, 1);
86         pio0->set_context_port_a(rtc, SIG_MSM58321_READ, 1, 0);
87         pio0->set_context_port_a(rtc, SIG_MSM58321_WRITE, 2, 0);
88         pio0->set_context_port_a(rtc, SIG_MSM58321_ADDR_WRITE, 4, 0);
89         pio0->set_context_port_c(rtc, SIG_MSM58321_DATA, 0x0f, 0);
90         pio1->set_context_port_a(crtc, SIG_CRTC_BITMASK_LOW, 0xff, 0);
91         pio1->set_context_port_b(crtc, SIG_CRTC_BITMASK_HIGH, 0xff, 0);
92         pio1->set_context_port_c(crtc, SIG_CRTC_VRAM_PLANE, 0x3f, 0);
93         pio1->set_context_port_c(and_drq, SIG_AND_BIT_0, 0x80, 0);
94         pio1->set_context_port_c(ioctrl, SIG_IOCTRL_RESET, 0x40, 0);
95         pic->set_context_cpu(cpu);
96         rtc->set_context_data(pio0, SIG_I8255_PORT_C, 0x0f, 0);
97         rtc->set_context_busy(pio0, SIG_I8255_PORT_C, 0x10);
98         fdc->set_context_irq(cpu, SIG_CPU_NMI, 1);
99         fdc->set_context_drq(and_drq, SIG_AND_BIT_1, 1);
100         
101         crtc->set_context_pic(pic);
102         ioctrl->set_context_pic(pic);
103         ioctrl->set_context_fdc(fdc);
104         ioctrl->set_context_beep(beep);
105         ioctrl->set_context_pcm(pcm);
106         
107         // cpu bus
108         cpu->set_context_mem(memory);
109         cpu->set_context_io(io);
110         cpu->set_context_intr(pic);
111 #ifdef USE_DEBUGGER
112         cpu->set_context_debugger(new DEBUGGER(this, emu));
113 #endif
114         
115         // memory bus
116         memset(ram, 0, sizeof(ram));
117         memset(ipl, 0xff, sizeof(ipl));
118         
119         memory->read_bios(_T("IPL.ROM"), ipl, sizeof(ipl));
120         
121         memory->set_memory_rw(0x00000, 0xbffff, ram);
122         memory->set_memory_mapped_io_rw(0xc0000, 0xdffff, crtc);
123         memory->set_memory_r(0xf8000, 0xfffff, ipl);
124         
125         // i/o bus
126         io->set_iomap_alias_rw(0x00, pic, 0);
127         io->set_iomap_alias_rw(0x02, pic, 1);
128 //      io->set_iomap_alias_rw(0x04, dma, 0);
129 //      io->set_iomap_alias_rw(0x06, dma, 1);
130         io->set_iomap_alias_r(0x08, fdc, 0);
131         io->set_iomap_alias_rw(0x0a, fdc, 1);
132         io->set_iomap_alias_rw(0x10, pio0, 0);
133         io->set_iomap_alias_rw(0x12, pio0, 1);
134         io->set_iomap_alias_rw(0x14, pio0, 2);
135         io->set_iomap_alias_rw(0x16, pio0, 3);
136         io->set_iomap_alias_rw(0x18, pio1, 0);
137         io->set_iomap_alias_rw(0x1a, pio1, 1);
138         io->set_iomap_alias_rw(0x1c, pio1, 2);
139         io->set_iomap_alias_rw(0x1e, pio1, 3);
140         io->set_iomap_single_r(0x20, ioctrl);
141         io->set_iomap_single_rw(0x22, ioctrl);
142         io->set_iomap_single_w(0x24, ioctrl);
143         io->set_iomap_alias_rw(0x28, sio, 0);
144         io->set_iomap_alias_rw(0x2a, sio, 1);
145         io->set_iomap_single_rw(0x30, crtc);
146         io->set_iomap_single_rw(0x38, crtc);
147         io->set_iomap_single_rw(0x3a, crtc);
148         io->set_iomap_single_rw(0x3c, crtc);
149         io->set_iomap_single_rw(0x3e, crtc);
150         for(int i = 0x40; i < 0x62; i++) {
151                 io->set_iomap_single_rw(i, crtc);
152         }
153         io->set_iomap_single_rw(0x80, kanji);
154         io->set_iomap_single_rw(0x81, kanji);
155         io->set_iomap_single_w(0x84, kanji);
156         io->set_iomap_single_w(0x86, kanji);
157         
158         // initialize all devices
159         for(DEVICE* device = first_device; device; device = device->next_device) {
160                 device->initialize();
161         }
162         for(int i = 0; i < 4; i++) {
163                 fdc->set_drive_type(i, DRIVE_TYPE_2D);
164         }
165 }
166
167 VM::~VM()
168 {
169         // delete all devices
170         for(DEVICE* device = first_device; device;) {
171                 DEVICE *next_device = device->next_device;
172                 device->release();
173                 delete device;
174                 device = next_device;
175         }
176 }
177
178 DEVICE* VM::get_device(int id)
179 {
180         for(DEVICE* device = first_device; device; device = device->next_device) {
181                 if(device->this_device_id == id) {
182                         return device;
183                 }
184         }
185         return NULL;
186 }
187
188 // ----------------------------------------------------------------------------
189 // drive virtual machine
190 // ----------------------------------------------------------------------------
191
192 void VM::reset()
193 {
194         // reset all devices
195         for(DEVICE* device = first_device; device; device = device->next_device) {
196                 device->reset();
197         }
198 }
199
200 void VM::run()
201 {
202         event->drive();
203 }
204
205 // ----------------------------------------------------------------------------
206 // debugger
207 // ----------------------------------------------------------------------------
208
209 #ifdef USE_DEBUGGER
210 DEVICE *VM::get_cpu(int index)
211 {
212         if(index == 0) {
213                 return cpu;
214         }
215         return NULL;
216 }
217 #endif
218
219 // ----------------------------------------------------------------------------
220 // draw screen
221 // ----------------------------------------------------------------------------
222
223 void VM::draw_screen()
224 {
225         crtc->draw_screen();
226 }
227
228 uint32_t VM::get_access_lamp_status()
229 {
230         uint32_t status = fdc->read_signal(0);
231         return (status & (1 | 4)) ? 1 : (status & (2 | 8)) ? 2 : 0;
232 }
233
234 // ----------------------------------------------------------------------------
235 // soud manager
236 // ----------------------------------------------------------------------------
237
238 void VM::initialize_sound(int rate, int samples)
239 {
240         // init sound manager
241         event->initialize_sound(rate, samples);
242         
243         // init sound gen
244         beep->initialize_sound(rate, 2400, 8000);
245         pcm->initialize_sound(rate, 8000);
246 }
247
248 uint16_t* VM::create_sound(int* extra_frames)
249 {
250         return event->create_sound(extra_frames);
251 }
252
253 int VM::get_sound_buffer_ptr()
254 {
255         return event->get_sound_buffer_ptr();
256 }
257
258 #ifdef USE_SOUND_VOLUME
259 void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
260 {
261         if(ch == 0) {
262                 beep->set_volume(0, decibel_l, decibel_r);
263         } else if(ch == 1) {
264                 pcm->set_volume(0, decibel_l, decibel_r);
265         }
266 }
267 #endif
268
269 // ----------------------------------------------------------------------------
270 // notify key
271 // ----------------------------------------------------------------------------
272
273 void VM::key_down(int code, bool repeat)
274 {
275         ioctrl->key_down(code);
276 }
277
278 void VM::key_up(int code)
279 {
280         ioctrl->key_up(code);
281 }
282
283 // ----------------------------------------------------------------------------
284 // user interface
285 // ----------------------------------------------------------------------------
286
287 void VM::open_floppy_disk(int drv, const _TCHAR* file_path, int bank)
288 {
289         fdc->open_disk(drv, file_path, bank);
290 }
291
292 void VM::close_floppy_disk(int drv)
293 {
294         fdc->close_disk(drv);
295 }
296
297 bool VM::is_floppy_disk_inserted(int drv)
298 {
299         return fdc->is_disk_inserted(drv);
300 }
301
302 void VM::is_floppy_disk_protected(int drv, bool value)
303 {
304         fdc->is_disk_protected(drv, value);
305 }
306
307 bool VM::is_floppy_disk_protected(int drv)
308 {
309         return fdc->is_disk_protected(drv);
310 }
311
312 bool VM::is_frame_skippable()
313 {
314         return event->is_frame_skippable();
315 }
316
317 void VM::update_config()
318 {
319         for(DEVICE* device = first_device; device; device = device->next_device) {
320                 device->update_config();
321         }
322 }
323
324 #define STATE_VERSION   1
325
326 void VM::save_state(FILEIO* state_fio)
327 {
328         state_fio->FputUint32(STATE_VERSION);
329         
330         for(DEVICE* device = first_device; device; device = device->next_device) {
331                 device->save_state(state_fio);
332         }
333         state_fio->Fwrite(ram, sizeof(ram), 1);
334 }
335
336 bool VM::load_state(FILEIO* state_fio)
337 {
338         if(state_fio->FgetUint32() != STATE_VERSION) {
339                 return false;
340         }
341         for(DEVICE* device = first_device; device; device = device->next_device) {
342                 if(!device->load_state(state_fio)) {
343                         return false;
344                 }
345         }
346         state_fio->Fread(ram, sizeof(ram), 1);
347         return true;
348 }
349