OSDN Git Service

[BUILD] Set SOVERSION and GIT hash automatically.
[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) : VM_TEMPLATE(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         // initialize all devices
253 #if defined(__GIT_REPO_VERSION)
254         strncpy(_git_revision, __GIT_REPO_VERSION, sizeof(_git_revision) - 1);
255 #endif
256         for(DEVICE* device = first_device; device; device = device->next_device) {
257                 device->initialize();
258         }
259 #ifdef TYPE_SL
260         //pcm->set_realtime_render(true);
261 #endif
262 }
263
264 VM::~VM()
265 {
266         // delete all devices
267         for(DEVICE* device = first_device; device;) {
268                 DEVICE *next_device = device->next_device;
269                 device->release();
270                 delete device;
271                 device = next_device;
272         }
273 }
274
275 DEVICE* VM::get_device(int id)
276 {
277         for(DEVICE* device = first_device; device; device = device->next_device) {
278                 if(device->this_device_id == id) {
279                         return device;
280                 }
281         }
282         return NULL;
283 }
284
285 // ----------------------------------------------------------------------------
286 // drive virtual machine
287 // ----------------------------------------------------------------------------
288
289 void VM::reset()
290 {
291         // reset all devices
292         for(DEVICE* device = first_device; device; device = device->next_device) {
293                 device->reset();
294         }
295 }
296
297 void VM::run()
298 {
299         event->drive();
300 }
301
302 // ----------------------------------------------------------------------------
303 // debugger
304 // ----------------------------------------------------------------------------
305
306 #ifdef USE_DEBUGGER
307 DEVICE *VM::get_cpu(int index)
308 {
309         if(index == 0) {
310                 return cpu;
311         }
312         return NULL;
313 }
314 #endif
315
316 // ----------------------------------------------------------------------------
317 // draw screen
318 // ----------------------------------------------------------------------------
319
320 void VM::draw_screen()
321 {
322         display->draw_screen();
323 }
324
325 // ----------------------------------------------------------------------------
326 // soud manager
327 // ----------------------------------------------------------------------------
328
329 void VM::initialize_sound(int rate, int samples)
330 {
331         // init sound manager
332         event->initialize_sound(rate, samples);
333         
334         // init sound gen
335         pcm->initialize_sound(rate, 8000);
336 }
337
338 uint16_t* VM::create_sound(int* extra_frames)
339 {
340         return event->create_sound(extra_frames);
341 }
342
343 int VM::get_sound_buffer_ptr()
344 {
345         return event->get_sound_buffer_ptr();
346 }
347
348 #ifdef USE_SOUND_VOLUME
349 void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
350 {
351         if(ch == 0) {
352                 pcm->set_volume(0, decibel_l, decibel_r);
353         } else if(ch == 1) {
354                 fdc->get_context_noise_seek()->set_volume(0, decibel_l, decibel_r);
355                 fdc->get_context_noise_head_down()->set_volume(0, decibel_l, decibel_r);
356                 fdc->get_context_noise_head_up()->set_volume(0, decibel_l, decibel_r);
357         }
358 }
359 #endif
360
361 // ----------------------------------------------------------------------------
362 // notify key
363 // ----------------------------------------------------------------------------
364
365 void VM::key_down(int code, bool repeat)
366 {
367         keyboard->key_down(code);
368 }
369
370 void VM::key_up(int code)
371 {
372         keyboard->key_up(code);
373 }
374
375 // ----------------------------------------------------------------------------
376 // user interface
377 // ----------------------------------------------------------------------------
378
379 void VM::open_floppy_disk(int drv, const _TCHAR* file_path, int bank)
380 {
381         fdc->open_disk(drv, file_path, bank);
382 }
383
384 void VM::close_floppy_disk(int drv)
385 {
386         fdc->close_disk(drv);
387 }
388
389 bool VM::is_floppy_disk_inserted(int drv)
390 {
391         return fdc->is_disk_inserted(drv);
392 }
393
394 void VM::is_floppy_disk_protected(int drv, bool value)
395 {
396         fdc->is_disk_protected(drv, value);
397 }
398
399 bool VM::is_floppy_disk_protected(int drv)
400 {
401         return fdc->is_disk_protected(drv);
402 }
403
404 uint32_t VM::is_floppy_disk_accessed()
405 {
406         return fdc->read_signal(0);
407 }
408
409 bool VM::is_frame_skippable()
410 {
411         return event->is_frame_skippable();
412 }
413
414 void VM::update_config()
415 {
416         for(DEVICE* device = first_device; device; device = device->next_device) {
417                 device->update_config();
418         }
419 }
420