OSDN Git Service

[VM][General] Merge upstream 2016-02-13. Still don't implement OSD/Gui part of joysti...
[csp-qt/common_source_project-fm7.git] / source / src / vm / jx / jx.cpp
1 /*
2         IBM Japan Ltd PC/JX Emulator 'eJX'
3
4         Author : Takeda.Toshiya
5         Date   : 2011.05.09-
6
7         [ virtual machine ]
8 */
9
10 #include "jx.h"
11 #include "../../emu.h"
12 #include "../device.h"
13 #include "../event.h"
14
15 #include "../disk.h"
16 #include "../hd46505.h"
17 #include "../i8251.h"
18 #include "../i8253.h"
19 #include "../i8255.h"
20 #include "../i8259.h"
21 #include "../i86.h"
22 #include "../io.h"
23 #include "../memory.h"
24 #include "../pcm1bit.h"
25 #include "../sn76489an.h"
26 #include "../upd765a.h"
27
28 #ifdef USE_DEBUGGER
29 #include "../debugger.h"
30 #endif
31
32 #include "display.h"
33 #include "floppy.h"
34 #include "keyboard.h"
35 #include "speaker.h"
36
37 // ----------------------------------------------------------------------------
38 // initialize
39 // ----------------------------------------------------------------------------
40
41 VM::VM(EMU* parent_emu) : emu(parent_emu)
42 {
43         // create devices
44         first_device = last_device = NULL;
45         dummy = new DEVICE(this, emu);  // must be 1st device
46         event = new EVENT(this, emu);   // must be 2nd device
47         
48         crtc = new HD46505(this, emu);
49         sio = new I8251(this, emu);
50         pit = new I8253(this, emu);
51         pio = new I8255(this, emu);
52         pic = new I8259(this, emu);
53         cpu = new I86(this, emu);       // 8088
54         io = new IO(this, emu);
55         mem = new MEMORY(this, emu);
56         pcm = new PCM1BIT(this, emu);
57         psg = new SN76489AN(this, emu); // SN76496N
58         fdc = new UPD765A(this, emu);
59         
60         display = new DISPLAY(this, emu);
61         floppy = new FLOPPY(this, emu);
62         keyboard = new KEYBOARD(this, emu);
63         speaker = new SPEAKER(this, emu);
64         
65         /* IRQ  0 Timer Clock Interrupt
66                 1 I/O Channel (Reserved)
67                 2 I/O Channel
68                 3 Asynchronous Port Interrupt (RS-232C)
69                 4 Modem Interrupt
70                 5 Vertical Retrace Interrupt (Display)
71                 6 Diskette Interrupt (WDT)
72                 7 I/O Channel (Parallel Printer)
73         */
74         
75         // set contexts
76         event->set_context_cpu(cpu);
77         event->set_context_sound(pcm);
78         
79         // cpu bus
80         cpu->set_context_mem(mem);
81         cpu->set_context_io(io);
82         cpu->set_context_intr(pic);
83 #ifdef USE_DEBUGGER
84         cpu->set_context_debugger(new DEBUGGER(this, emu));
85 #endif
86         
87         crtc->set_context_disp(display, SIG_DISPLAY_ENABLE, 1);
88         crtc->set_context_vblank(display, SIG_DISPLAY_VBLANK, 1);
89         crtc->set_context_vblank(pic, SIG_I8259_IR5, 1);
90         
91         /* PIT  0 Interrupt
92                 2 Speaker
93         */
94         pit->set_constant_clock(0, CPU_CLOCKS / 4);
95 #ifdef TIMER_HACK
96         pit->set_constant_clock(1, CPU_CLOCKS / 4);
97 #endif
98         pit->set_constant_clock(2, CPU_CLOCKS / 4);
99         pit->set_context_ch0(pic, SIG_I8259_IR0, 1);                    // to IRQ0
100 #ifndef TIMER_HACK
101         pit->set_context_ch0(keyboard, SIG_KEYBOARD_TIMER, 1);          // to clock of timer1
102 #endif
103         pit->set_context_ch2(pio, SIG_I8255_PORT_C, 0x20);              // to PC5
104         pit->set_context_ch2(pcm, SIG_PCM1BIT_SIGNAL, 0x20);            // to speaker
105         pio->set_context_port_b(pit, SIG_I8253_GATE_2, 0x01, 0);        // PB0
106         pio->set_context_port_b(speaker, SIG_SPEAKER_PIO, 0x62, 0);     // PB1+5+6
107         pio->set_context_port_b(display, SIG_DISPLAY_PIO, 0x04, 0);     // PB2
108         pic->set_context_cpu(cpu);
109         
110         display->set_context_mem(mem);
111         display->set_regs_ptr(crtc->get_regs());
112         floppy->set_context_fdc(fdc);
113         floppy->set_context_pic(pic);
114         keyboard->set_context_cpu(cpu);
115         keyboard->set_context_pio(pio);
116         keyboard->set_context_pit(pit);
117         speaker->set_context_pcm(pcm);
118         speaker->set_context_psg(psg);
119         
120         // memory bus
121         //      00000-7FFFF     RAM
122         //      80000-B7FFF     KANJI ROM ???
123         //      A0000-A7FFF     EXT-VRAM
124         //      B8000-BFFFF     VRAM
125         //      D0000-FFFFF     CART+IPL
126         
127         memset(font, 0xff, sizeof(font));
128         memset(kanji, 0xff, sizeof(kanji));
129         memset(ram, 0, sizeof(ram));
130         memset(ipl, 0xff, sizeof(ipl));
131         
132         mem->read_bios(_T("FONT.ROM"), font, sizeof(font));
133         mem->read_bios(_T("KANJI.ROM"), kanji, sizeof(kanji));
134         int length = mem->read_bios(_T("IPL.ROM"), ipl, sizeof(ipl));
135         int offset = 0x30000 - length;
136         memmove(ipl + offset, ipl, length);
137         memset(ipl, 0xff, offset);
138         
139         mem->set_memory_rw(0x00000, 0x7ffff, ram);
140 //      mem->set_memory_r(0x80000, 0xb7fff, kanji);
141         mem->set_memory_r(0xd0000, 0xfffff, ipl);
142         
143         display->set_font_ptr(font);
144         display->set_kanji_ptr(kanji);
145         
146         // i/o bus
147         for(int i = 0x20; i <= 0x27; i++) {
148                 io->set_iomap_alias_rw(i, pic, i & 1);
149         }
150         io->set_iomap_range_rw(0x40, 0x43, pit);
151         io->set_iomap_range_rw(0x60, 0x67, pio);
152         io->set_iomap_range_rw(0xa0, 0xa7, keyboard);
153         io->set_iomap_range_w(0xc0, 0xc7, psg);
154         
155         io->set_iomap_single_w(0xf2, floppy);
156         io->set_iomap_range_rw(0xf4, 0xf5, fdc);
157         
158         io->set_iomap_single_rw(0x1ff, display);
159         
160 ///     io->set_iovalue_range_r(0x200, 0x207, 0);
161         
162         io->set_iomap_range_rw(0x3d0, 0x3d1, crtc);
163         io->set_iomap_range_rw(0x3d4, 0x3d5, crtc);
164         io->set_iomap_range_rw(0x3d8, 0x3df, display);
165         
166         // initialize all devices
167         for(DEVICE* device = first_device; device; device = device->next_device) {
168                 device->initialize();
169         }
170         for(int i = 0; i < 4; i++) {
171                 fdc->set_drive_type(i, DRIVE_TYPE_2DD);
172         }
173 }
174
175 VM::~VM()
176 {
177         // delete all devices
178         for(DEVICE* device = first_device; device;) {
179                 DEVICE *next_device = device->next_device;
180                 device->release();
181                 delete device;
182                 device = next_device;
183         }
184 }
185
186 DEVICE* VM::get_device(int id)
187 {
188         for(DEVICE* device = first_device; device; device = device->next_device) {
189                 if(device->this_device_id == id) {
190                         return device;
191                 }
192         }
193         return NULL;
194 }
195
196 // ----------------------------------------------------------------------------
197 // drive virtual machine
198 // ----------------------------------------------------------------------------
199
200 void VM::reset()
201 {
202         // reset all devices
203         for(DEVICE* device = first_device; device; device = device->next_device) {
204                 device->reset();
205         }
206         
207         // initial device settings
208         pio->write_signal(SIG_I8255_PORT_C, 0x02, 0x02);        // PC1=1: Modem card is not installed
209         pio->write_signal(SIG_I8255_PORT_C, 0x00, 0x04);        // PC2=0: Diskette card is installed
210 //      pio->write_signal(SIG_I8255_PORT_C, 0x04, 0x04);        // PC2=0: Diskette card is no installed
211         pio->write_signal(SIG_I8255_PORT_C, 0x00, 0x08);        // PC3=0: 64KB Memory and Display Expansion is installed
212         pio->write_signal(SIG_I8255_PORT_C, 0x00, 0x80);        // PC7=0: Keyboard cable is connected
213 }
214
215 void VM::run()
216 {
217         event->drive();
218 }
219
220 // ----------------------------------------------------------------------------
221 // debugger
222 // ----------------------------------------------------------------------------
223
224 #ifdef USE_DEBUGGER
225 DEVICE *VM::get_cpu(int index)
226 {
227         if(index == 0) {
228                 return cpu;
229         }
230         return NULL;
231 }
232 #endif
233
234 // ----------------------------------------------------------------------------
235 // draw screen
236 // ----------------------------------------------------------------------------
237
238 void VM::draw_screen()
239 {
240         display->draw_screen();
241 }
242
243 int VM::access_lamp()
244 {
245         uint32 status = fdc->read_signal(0);
246         return (status & (1 | 4)) ? 1 : (status & (2 | 8)) ? 2 : 0;
247 }
248
249 // ----------------------------------------------------------------------------
250 // soud manager
251 // ----------------------------------------------------------------------------
252
253 void VM::initialize_sound(int rate, int samples)
254 {
255         // init sound manager
256         event->initialize_sound(rate, samples);
257         
258         // init sound gen
259         pcm->init(rate, 8000);
260         psg->init(rate, 3579545, 8000);
261 }
262
263 uint16* VM::create_sound(int* extra_frames)
264 {
265         return event->create_sound(extra_frames);
266 }
267
268 int VM::sound_buffer_ptr()
269 {
270         return event->sound_buffer_ptr();
271 }
272
273 #ifdef USE_SOUND_VOLUME
274 void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
275 {
276         if(ch == 0) {
277                 pcm->set_volume(0, decibel_l, decibel_r);
278         }
279 }
280 #endif
281
282 // ----------------------------------------------------------------------------
283 // notify key
284 // ----------------------------------------------------------------------------
285
286 void VM::key_down(int code, bool repeat)
287 {
288         keyboard->key_down(code);
289 }
290
291 void VM::key_up(int code)
292 {
293         keyboard->key_up(code);
294 }
295
296 // ----------------------------------------------------------------------------
297 // user interface
298 // ----------------------------------------------------------------------------
299
300 void VM::open_disk(int drv, const _TCHAR* file_path, int bank)
301 {
302         fdc->open_disk(drv, file_path, bank);
303 }
304
305 void VM::close_disk(int drv)
306 {
307         fdc->close_disk(drv);
308 }
309
310 bool VM::disk_inserted(int drv)
311 {
312         return fdc->disk_inserted(drv);
313 }
314
315 void VM::set_disk_protected(int drv, bool value)
316 {
317         fdc->set_disk_protected(drv, value);
318 }
319
320 bool VM::get_disk_protected(int drv)
321 {
322         return fdc->get_disk_protected(drv);
323 }
324
325 bool VM::now_skip()
326 {
327         return event->now_skip();
328 }
329
330 void VM::update_config()
331 {
332         for(DEVICE* device = first_device; device; device = device->next_device) {
333                 device->update_config();
334         }
335 }
336