OSDN Git Service

[GENERAL] Merge Upstream 2017-11-28.
[csp-qt/common_source_project-fm7.git] / source / src / vm / j3100 / j3100.cpp
1 /*
2         TOSHIBA J-3100GT Emulator 'eJ-3100GT'
3         TOSHIBA J-3100SL Emulator 'eJ-3100SL'
4
5         Author : Takeda.Toshiya
6         Date   : 2011.08.16-
7
8         [ virtual machine ]
9 */
10
11 #include "j3100.h"
12 #include "../../emu.h"
13 #include "../device.h"
14 #include "../event.h"
15
16 #include "../hd46505.h"
17 #include "../i8237.h"
18 //#include "../i8250.h"
19 #include "../i8253.h"
20 #include "../i8259.h"
21 //#if defined(HAS_I286)
22 #include "../i286.h"
23 //#else
24 //#include "../i86.h"
25 //#endif
26 #include "../io.h"
27 #include "../noise.h"
28 #include "../pcm1bit.h"
29 #include "../upd765a.h"
30 #ifdef TYPE_SL
31 #include "../rp5c01.h"
32 #else
33 #include "../hd146818p.h"
34 #endif
35
36 #ifdef USE_DEBUGGER
37 #include "../debugger.h"
38 #endif
39
40 #include "display.h"
41 #include "dmareg.h"
42 #include "floppy.h"
43 #include "sasi.h"
44 #ifdef TYPE_SL
45 #include "slkeyboard.h"
46 #include "slmemory.h"
47 #include "slsystem.h"
48 #else
49 #include "keyboard.h"
50 #include "memory.h"
51 #include "system.h"
52 #endif
53
54 // ----------------------------------------------------------------------------
55 // initialize
56 // ----------------------------------------------------------------------------
57
58 VM::VM(EMU* parent_emu) : emu(parent_emu)
59 {
60         // create devices
61         first_device = last_device = NULL;
62         dummy = new DEVICE(this, emu);  // must be 1st device
63         event = new EVENT(this, emu);   // must be 2nd device
64         dummy->set_device_name(_T("1st Dummy"));
65         
66         crtc = new HD46505(this, emu);
67         dma = new I8237(this, emu);
68 #ifndef TYPE_SL
69         dma2 = new I8237(this, emu);
70 #endif
71 #ifndef TYPE_SL
72         dma->set_device_name(_T("i8237 DMAC #1"));
73         dma2->set_device_name(_T("i8237 DMAC #2"));
74 #endif
75 //      sio = new I8250(this, emu);
76         pit = new I8253(this, emu);     // i8254
77         pic = new I8259(this, emu);
78 //#if defined(HAS_I286)
79         cpu = new I286(this, emu);
80 //#else
81 //      cpu = new I86(this, emu);
82 //#endif
83         io = new IO(this, emu);
84         pcm = new PCM1BIT(this, emu);
85         fdc = new UPD765A(this, emu);
86         fdc->set_context_noise_seek(new NOISE(this, emu));
87         fdc->set_context_noise_head_down(new NOISE(this, emu));
88         fdc->set_context_noise_head_up(new NOISE(this, emu));
89 #ifdef TYPE_SL
90         rtc = new RP5C01(this, emu);
91 #else
92         rtc = new HD146818P(this, emu);
93 #endif
94         
95         display = new DISPLAY(this, emu);
96         dmareg = new DMAREG(this, emu);
97         floppy = new FLOPPY(this, emu);
98         keyboard = new KEYBOARD(this, emu);
99         memory = new MEMORY(this, emu);
100         sasi = new SASI(this, emu);
101         system = new SYSTEM(this, emu);
102         // set contexts
103         event->set_context_cpu(cpu);
104         event->set_context_sound(pcm);
105         event->set_context_sound(fdc->get_context_noise_seek());
106         event->set_context_sound(fdc->get_context_noise_head_down());
107         event->set_context_sound(fdc->get_context_noise_head_up());
108
109         // cpu bus
110         cpu->set_context_mem(memory);
111         cpu->set_context_io(io);
112         cpu->set_context_intr(pic);
113 #ifdef USE_DEBUGGER
114         cpu->set_context_debugger(new DEBUGGER(this, emu));
115 #endif
116         
117         // dmac
118         io->set_iomap_range_rw(0x00, 0x0f, dma);
119         io->set_iomap_range_w(0x80, 0x8f, dmareg);
120         dma->set_context_memory(memory);
121         dma->set_context_ch2(fdc);
122         dmareg->set_context_dma(dma);
123 #ifndef TYPE_SL
124         for(int i = 0xc0; i <= 0xde; i += 2) {
125                 io->set_iomap_alias_rw(i, dma2, i >> 1);
126         }
127         dma2->set_context_memory(memory);
128         dma2->set_mode_word(true);
129         dmareg->set_context_dma2(dma2);
130 #endif
131         
132         // pic
133         io->set_iomap_alias_rw(0x20, pic, I8259_ADDR_CHIP0 | 0);
134         io->set_iomap_alias_rw(0x21, pic, I8259_ADDR_CHIP0 | 1);
135 #ifndef TYPE_SL
136         io->set_iomap_alias_rw(0xa0, pic, I8259_ADDR_CHIP1 | 0);
137         io->set_iomap_alias_rw(0xa1, pic, I8259_ADDR_CHIP1 | 1);
138 #endif
139         pic->set_context_cpu(cpu);
140         
141         // pit
142         io->set_iomap_range_rw(0x40, 0x43, pit);
143         pit->set_constant_clock(0, 1190000);
144         pit->set_constant_clock(1, 1190000);
145         pit->set_constant_clock(2, 1190000);
146         pit->set_context_ch0(pic, SIG_I8259_IR0 | SIG_I8259_CHIP0, 1);  // to PIC#0 IR0
147         pit->set_context_ch2(pcm, SIG_PCM1BIT_SIGNAL, 1);
148 #ifndef TYPE_SL
149         pit->set_context_ch2(system, SIG_SYSTEM_TC2O, 1);
150 #endif
151         
152         // system status/command
153 #ifndef TYPE_SL
154         io->set_iomap_single_rw(0x61, system);
155         system->set_context_pcm(pcm);
156         system->set_context_pit(pit);
157 #endif
158         
159         // rtc
160 #ifdef TYPE_SL
161         io->set_iomap_range_rw(0x2c0, 0x2cf, rtc);
162 #else
163         io->set_iomap_alias_w(0x70, rtc, 1);    // bit7 = nmi mask
164         io->set_iomap_alias_rw(0x71, rtc, 0);
165         rtc->set_context_intr(pic, SIG_I8259_IR0 | SIG_I8259_CHIP1, 1); // to PIC#1 IR0 (IR8)
166 #endif
167         
168         // nmi mask register
169 #ifdef TYPE_SL
170         io->set_iomap_single_w(0xa0, system);
171 #else
172         // 0x70 bit7 (not implemented)
173 #endif
174         
175         // crtc
176         io->set_iomap_range_rw(0x3d0, 0x3d1, crtc);
177         io->set_iomap_range_rw(0x3d4, 0x3d5, crtc);
178         io->set_iomap_range_w(0x3d8, 0x3d9, display);
179         io->set_iomap_single_r(0x3da, display);
180         crtc->set_context_disp(display, SIG_DISPLAY_ENABLE, 1);
181         crtc->set_context_vblank(display, SIG_DISPLAY_VBLANK, 1);
182         display->set_regs_ptr(crtc->get_regs());
183         display->set_vram_ptr(memory->get_vram());
184         
185         // fdc
186         io->set_iomap_single_w(0x3f2, floppy);
187         io->set_iomap_range_rw(0x3f4, 0x3f5, fdc);
188         io->set_iomap_single_rw(0x3f7, floppy);
189         fdc->set_context_irq(pic, SIG_I8259_IR6 | SIG_I8259_CHIP0, 1);  // to PIC#0 IR6
190         fdc->set_context_drq(dma, SIG_I8237_CH2, 1);                    // to DMA Ch.2
191         floppy->set_context_fdc(fdc);
192         
193         // printer
194         io->set_flipflop_single_rw(0x378, 0x00);
195         io->set_iovalue_single_r(0x379, 0x78);
196         io->set_flipflop_single_rw(0x37a, 0x00);
197         
198         // keyboard
199 #ifdef TYPE_SL
200         io->set_iomap_range_rw(0x60, 0x61, keyboard);
201 #else
202 #endif
203         keyboard->set_context_pic(pic);
204         
205         // serial port
206         
207         // sasi
208 #if defined(_J3100GT) || defined(TYPE_SL)
209         io->set_iomap_range_rw(0x1f0, 0x1f3, sasi);
210         sasi->set_context_pic(pic);
211 #endif
212         
213         // ems
214         static const int ems_addr[] = {
215                 0x208, 0x4208, 0x8208, 0xc208,
216                 0x218, 0x4218, 0x8218, 0xc218,
217                 0x258, 0x4258, 0x8258, 0xc258,
218                 0x268, 0x4268, 0x8268, 0xc268,
219 #ifdef TYPE_SL
220                 0x2a8, 0x42a8, 0x82a8, 0xc2a8,
221                 0x2b8, 0x42b8, 0x82b8, 0xc2b8,
222                 0x2e8, 0x42e8, 0x82e8, 0xc2e8,
223 #endif
224         };
225         for(int i = 0; i < array_length(ems_addr); i++) {
226                 io->set_iomap_single_rw(ems_addr[i], memory);
227 #ifdef TYPE_SL
228                 io->set_iomap_single_w(ems_addr[i] + 1, memory);
229 #endif
230         }
231 #ifdef TYPE_SL
232         io->set_iomap_range_rw(0xee, 0xef, memory);
233 #endif
234         
235         // special registers for J-3100SL/SS/SE
236 #ifdef TYPE_SL
237 //      62      bit0
238 //              bit1    1=8087\82 \82è
239         io->set_iovalue_single_r(0x62, 0x26);   // unknown
240 //      io->set_flipflop_single_rw(0x63, 0x00); // unknown
241         static const int iovalues[0x20] = {
242                 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x14, 0xff, 0xff, 0x00, 0xff, 0xe0, 0xff, 0x00, 0xff, 0xff,
243                 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
244         };
245         for(int i = 0xe0; i <= 0xff; i++) {
246                 if(i == 0xee && i == 0xef) {
247                         continue;
248                 }
249                 io->set_flipflop_single_rw(i, iovalues[i & 0x1f]);
250         }
251 #endif
252
253
254
255
256         // initialize all devices
257         for(DEVICE* device = first_device; device; device = device->next_device) {
258                 device->initialize();
259         }
260 #ifdef TYPE_SL
261         //pcm->set_realtime_render(true);
262 #endif
263 }
264
265 VM::~VM()
266 {
267         // delete all devices
268         for(DEVICE* device = first_device; device;) {
269                 DEVICE *next_device = device->next_device;
270                 device->release();
271                 delete device;
272                 device = next_device;
273         }
274 }
275
276 DEVICE* VM::get_device(int id)
277 {
278         for(DEVICE* device = first_device; device; device = device->next_device) {
279                 if(device->this_device_id == id) {
280                         return device;
281                 }
282         }
283         return NULL;
284 }
285
286 // ----------------------------------------------------------------------------
287 // drive virtual machine
288 // ----------------------------------------------------------------------------
289
290 void VM::reset()
291 {
292         // reset all devices
293         for(DEVICE* device = first_device; device; device = device->next_device) {
294                 device->reset();
295         }
296 }
297
298 void VM::run()
299 {
300         event->drive();
301 }
302
303 // ----------------------------------------------------------------------------
304 // debugger
305 // ----------------------------------------------------------------------------
306
307 #ifdef USE_DEBUGGER
308 DEVICE *VM::get_cpu(int index)
309 {
310         if(index == 0) {
311                 return cpu;
312         }
313         return NULL;
314 }
315 #endif
316
317 // ----------------------------------------------------------------------------
318 // draw screen
319 // ----------------------------------------------------------------------------
320
321 void VM::draw_screen()
322 {
323         display->draw_screen();
324 }
325
326 // ----------------------------------------------------------------------------
327 // soud manager
328 // ----------------------------------------------------------------------------
329
330 void VM::initialize_sound(int rate, int samples)
331 {
332         // init sound manager
333         event->initialize_sound(rate, samples);
334         
335         // init sound gen
336         pcm->initialize_sound(rate, 8000);
337 }
338
339 uint16_t* VM::create_sound(int* extra_frames)
340 {
341         return event->create_sound(extra_frames);
342 }
343
344 int VM::get_sound_buffer_ptr()
345 {
346         return event->get_sound_buffer_ptr();
347 }
348
349 #ifdef USE_SOUND_VOLUME
350 void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
351 {
352         if(ch == 0) {
353                 pcm->set_volume(0, decibel_l, decibel_r);
354         } else if(ch == 1) {
355                 fdc->get_context_noise_seek()->set_volume(0, decibel_l, decibel_r);
356                 fdc->get_context_noise_head_down()->set_volume(0, decibel_l, decibel_r);
357                 fdc->get_context_noise_head_up()->set_volume(0, decibel_l, decibel_r);
358         }
359 }
360 #endif
361
362 // ----------------------------------------------------------------------------
363 // notify key
364 // ----------------------------------------------------------------------------
365
366 void VM::key_down(int code, bool repeat)
367 {
368         keyboard->key_down(code);
369 }
370
371 void VM::key_up(int code)
372 {
373         keyboard->key_up(code);
374 }
375
376 // ----------------------------------------------------------------------------
377 // user interface
378 // ----------------------------------------------------------------------------
379
380 void VM::open_floppy_disk(int drv, const _TCHAR* file_path, int bank)
381 {
382         fdc->open_disk(drv, file_path, bank);
383 }
384
385 void VM::close_floppy_disk(int drv)
386 {
387         fdc->close_disk(drv);
388 }
389
390 bool VM::is_floppy_disk_inserted(int drv)
391 {
392         return fdc->is_disk_inserted(drv);
393 }
394
395 void VM::is_floppy_disk_protected(int drv, bool value)
396 {
397         fdc->is_disk_protected(drv, value);
398 }
399
400 bool VM::is_floppy_disk_protected(int drv)
401 {
402         return fdc->is_disk_protected(drv);
403 }
404
405 uint32_t VM::is_floppy_disk_accessed()
406 {
407         return fdc->read_signal(0);
408 }
409
410 bool VM::is_frame_skippable()
411 {
412         return event->is_frame_skippable();
413 }
414
415 void VM::update_config()
416 {
417         for(DEVICE* device = first_device; device; device = device->next_device) {
418                 device->update_config();
419         }
420 }
421