OSDN Git Service

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