OSDN Git Service

[VM][General] Merge Upstream 2017-03-30.
[csp-qt/common_source_project-fm7.git] / source / src / vm / babbage2nd / babbage2nd.cpp
1 /*
2         Gijutsu-Hyoron-Sha Babbage-2nd Emulator 'eBabbage-2nd'
3
4         Author : Takeda.Toshiya
5         Date   : 2009.12.26 -
6
7         [ virtual machine ]
8 */
9
10 #include "babbage2nd.h"
11 #include "../../emu.h"
12 #include "../device.h"
13 #include "../event.h"
14
15 #include "../io.h"
16 #include "../memory.h"
17 #include "../z80.h"
18 #include "../z80ctc.h"
19 #include "../z80pio.h"
20
21 #ifdef USE_DEBUGGER
22 #include "../debugger.h"
23 #endif
24
25 #include "display.h"
26 #include "keyboard.h"
27
28 // ----------------------------------------------------------------------------
29 // initialize
30 // ----------------------------------------------------------------------------
31
32 VM::VM(EMU* parent_emu) : emu(parent_emu)
33 {
34         // create devices
35         first_device = last_device = NULL;
36         dummy = new DEVICE(this, emu);  // must be 1st device
37         event = new EVENT(this, emu);   // must be 2nd device
38         
39         io = new IO(this, emu);
40         memory = new MEMORY(this, emu);
41         cpu = new Z80(this, emu);
42         ctc = new Z80CTC(this, emu);
43         pio1 = new Z80PIO(this, emu);
44         pio1->set_device_name(_T("Z80 PIO (LEDs)"));
45         pio2 = new Z80PIO(this, emu);
46         pio2->set_device_name(_T("Z80 PIO (7-Seg/Keyboard)"));
47         
48         display = new DISPLAY(this, emu);
49         keyboard = new KEYBOARD(this, emu);
50
51         // Set names
52 #if defined(_USE_QT)
53         dummy->set_device_name(_T("1st Dummy"));
54         event->set_device_name(_T("EVENT"));
55         cpu->set_device_name(_T("CPU(Z80)"));
56         ctc->set_device_name(_T("Z80 CTC"));
57         pio1->set_device_name(_T("Z80 PIO(LEDs)"));
58         pio2->set_device_name(_T("Z80 PIO(7SEG/KEYBOARD)"));
59         display->set_device_name(_T("7SEG/LEDs"));
60         keyboard->set_device_name(_T("KEYBOARD"));
61 #endif
62         // set contexts
63         event->set_context_cpu(cpu);
64         
65         pio2->set_context_port_b(display, SIG_DISPLAY_7SEG_LED, 0xff, 0);
66         keyboard->set_context_pio(pio2);
67         // p.145, fig.3-4
68         ctc->set_context_zc2(ctc, SIG_Z80CTC_TRIG_1, 1);
69         ctc->set_context_zc1(ctc, SIG_Z80CTC_TRIG_0, 1);
70         // p.114, fig.2-52
71         pio1->set_context_port_b(display, SIG_DISPLAY_8BIT_LED, 0xff, 0);
72         //pio1->set_context_port_b(pio1, SIG_Z80PIO_PORT_A, 0xff, 0);
73         
74         // cpu bus
75         cpu->set_context_mem(memory);
76         cpu->set_context_io(io);
77         cpu->set_context_intr(ctc);
78 #ifdef USE_DEBUGGER
79         cpu->set_context_debugger(new DEBUGGER(this, emu));
80 #endif
81         
82         // z80 family daisy chain
83         ctc->set_context_intr(cpu, 0);
84         ctc->set_context_child(pio1);
85         pio1->set_context_intr(cpu, 1);
86         pio1->set_context_child(pio2);
87         pio2->set_context_intr(cpu, 2);
88         
89         // memory bus
90         memset(ram, 0, sizeof(ram));
91         memset(rom, 0xff, sizeof(rom));
92         
93         memory->read_bios(_T("MON.ROM"), rom, sizeof(rom));
94         
95         memory->set_memory_r(0x0000, 0x07ff, rom);
96         memory->set_memory_rw(0x1000, 0x17ff, ram);
97         
98         // i/o bus
99         io->set_iomap_range_rw(0x00, 0x03, ctc);
100         io->set_iomap_range_rw(0x10, 0x13, pio1);
101         io->set_iomap_range_rw(0x20, 0x23, pio2);
102         
103         // initialize all devices
104         for(DEVICE* device = first_device; device; device = device->next_device) {
105                 device->initialize();
106         }
107 }
108
109 VM::~VM()
110 {
111         // delete all devices
112         for(DEVICE* device = first_device; device;) {
113                 DEVICE *next_device = device->next_device;
114                 device->release();
115                 delete device;
116                 device = next_device;
117         }
118 }
119
120 DEVICE* VM::get_device(int id)
121 {
122         for(DEVICE* device = first_device; device; device = device->next_device) {
123                 if(device->this_device_id == id) {
124                         return device;
125                 }
126         }
127         return NULL;
128 }
129
130 // ----------------------------------------------------------------------------
131 // drive virtual machine
132 // ----------------------------------------------------------------------------
133
134 void VM::reset()
135 {
136         // reset all devices
137         for(DEVICE* device = first_device; device; device = device->next_device) {
138                 device->reset();
139         }
140 }
141
142 void VM::run()
143 {
144         event->drive();
145 }
146
147 // ----------------------------------------------------------------------------
148 // debugger
149 // ----------------------------------------------------------------------------
150
151 #ifdef USE_DEBUGGER
152 DEVICE *VM::get_cpu(int index)
153 {
154         if(index == 0) {
155                 return cpu;
156         }
157         return NULL;
158 }
159 #endif
160
161 // ----------------------------------------------------------------------------
162 // draw screen
163 // ----------------------------------------------------------------------------
164
165 void VM::draw_screen()
166 {
167         display->draw_screen();
168 }
169
170 // ----------------------------------------------------------------------------
171 // soud manager
172 // ----------------------------------------------------------------------------
173
174 void VM::initialize_sound(int rate, int samples)
175 {
176         // init sound manager
177         event->initialize_sound(rate, samples);
178 }
179
180 uint16_t* VM::create_sound(int* extra_frames)
181 {
182         return event->create_sound(extra_frames);
183 }
184
185 int VM::get_sound_buffer_ptr()
186 {
187         return event->get_sound_buffer_ptr();
188 }
189
190 // ----------------------------------------------------------------------------
191 // notify key
192 // ----------------------------------------------------------------------------
193
194 void VM::key_down(int code, bool repeat)
195 {
196         keyboard->key_down(code);
197 }
198
199 void VM::key_up(int code)
200 {
201         //keyboard->key_up(code);
202 }
203
204 // ----------------------------------------------------------------------------
205 // user interface
206 // ----------------------------------------------------------------------------
207
208 void VM::load_binary(int drv, const _TCHAR* file_path)
209 {
210         if(drv == 0) {
211                 memory->read_image(file_path, ram, sizeof(ram));
212         }
213 }
214
215 void VM::save_binary(int drv, const _TCHAR* file_path)
216 {
217         if(drv == 0) {
218                 memory->write_image(file_path, ram, sizeof(ram));
219         }
220 }
221
222 bool VM::is_frame_skippable()
223 {
224         return event->is_frame_skippable();
225 }
226
227 void VM::update_config()
228 {
229         for(DEVICE* device = first_device; device; device = device->next_device) {
230                 device->update_config();
231         }
232 }
233
234 #define STATE_VERSION   1
235
236 void VM::save_state(FILEIO* state_fio)
237 {
238         state_fio->FputUint32(STATE_VERSION);
239         
240         for(DEVICE* device = first_device; device; device = device->next_device) {
241                 device->save_state(state_fio);
242         }
243         state_fio->Fwrite(ram, sizeof(ram), 1);
244 }
245
246 bool VM::load_state(FILEIO* state_fio)
247 {
248         if(state_fio->FgetUint32() != STATE_VERSION) {
249                 return false;
250         }
251         for(DEVICE* device = first_device; device; device = device->next_device) {
252                 if(!device->load_state(state_fio)) {
253                         return false;
254                 }
255         }
256         state_fio->Fread(ram, sizeof(ram), 1);
257         return true;
258 }
259