OSDN Git Service

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