OSDN Git Service

[VM] TRY:Use namespace {VMNAME} to separate around VMs. This feature still apply...
[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 using BABBAGE2ND::DISPLAY;
29 using BABBAGE2ND::KEYBOARD;
30
31 // ----------------------------------------------------------------------------
32 // initialize
33 // ----------------------------------------------------------------------------
34
35 VM::VM(EMU* parent_emu) : VM_TEMPLATE(parent_emu)
36 {
37         // create devices
38         first_device = last_device = NULL;
39         dummy = new DEVICE(this, emu);  // must be 1st device
40         event = new EVENT(this, emu);   // must be 2nd device
41         
42         io = new IO(this, emu);
43         memory = new MEMORY(this, emu);
44         cpu = new Z80(this, emu);
45         ctc = new Z80CTC(this, emu);
46         pio1 = new Z80PIO(this, emu);
47         pio1->set_device_name(_T("Z80 PIO (LEDs)"));
48         pio2 = new Z80PIO(this, emu);
49         pio2->set_device_name(_T("Z80 PIO (7-Seg/Keyboard)"));
50         
51         display = new DISPLAY(this, emu);
52         keyboard = new KEYBOARD(this, emu);
53
54         // Set names
55 #if defined(_USE_QT)
56         dummy->set_device_name(_T("1st Dummy"));
57         pio1->set_device_name(_T("Z80 PIO(LEDs)"));
58         pio2->set_device_name(_T("Z80 PIO(7SEG/KEYBOARD)"));
59 #endif
60         // set contexts
61         event->set_context_cpu(cpu);
62         
63         pio2->set_context_port_b(display, SIG_DISPLAY_7SEG_LED, 0xff, 0);
64         keyboard->set_context_pio(pio2);
65         // p.145, fig.3-4
66         ctc->set_context_zc2(ctc, SIG_Z80CTC_TRIG_1, 1);
67         ctc->set_context_zc1(ctc, SIG_Z80CTC_TRIG_0, 1);
68         // p.114, fig.2-52
69         pio1->set_context_port_b(display, SIG_DISPLAY_8BIT_LED, 0xff, 0);
70         //pio1->set_context_port_b(pio1, SIG_Z80PIO_PORT_A, 0xff, 0);
71         
72         // cpu bus
73         cpu->set_context_mem(memory);
74         cpu->set_context_io(io);
75         cpu->set_context_intr(ctc);
76 #ifdef USE_DEBUGGER
77         cpu->set_context_debugger(new DEBUGGER(this, emu));
78 #endif
79         
80         // z80 family daisy chain
81         ctc->set_context_intr(cpu, 0);
82         ctc->set_context_child(pio1);
83         pio1->set_context_intr(cpu, 1);
84         pio1->set_context_child(pio2);
85         pio2->set_context_intr(cpu, 2);
86         
87         // memory bus
88         memset(ram, 0, sizeof(ram));
89         memset(rom, 0xff, sizeof(rom));
90         
91         memory->read_bios(_T("MON.ROM"), rom, sizeof(rom));
92         
93         memory->set_memory_r(0x0000, 0x07ff, rom);
94         memory->set_memory_rw(0x1000, 0x17ff, ram);
95         
96         // i/o bus
97         io->set_iomap_range_rw(0x00, 0x03, ctc);
98         io->set_iomap_range_rw(0x10, 0x13, pio1);
99         io->set_iomap_range_rw(0x20, 0x23, pio2);
100         
101         // initialize all devices
102 #if defined(__GIT_REPO_VERSION)
103         strncpy(_git_revision, __GIT_REPO_VERSION, sizeof(_git_revision) - 1);
104 #endif
105         for(DEVICE* device = first_device; device; device = device->next_device) {
106                 device->initialize();
107         }
108 }
109
110 VM::~VM()
111 {
112         // delete all devices
113         for(DEVICE* device = first_device; device;) {
114                 DEVICE *next_device = device->next_device;
115                 device->release();
116                 delete device;
117                 device = next_device;
118         }
119 }
120
121 DEVICE* VM::get_device(int id)
122 {
123         for(DEVICE* device = first_device; device; device = device->next_device) {
124                 if(device->this_device_id == id) {
125                         return device;
126                 }
127         }
128         return NULL;
129 }
130
131 // ----------------------------------------------------------------------------
132 // drive virtual machine
133 // ----------------------------------------------------------------------------
134
135 void VM::reset()
136 {
137         // reset all devices
138         for(DEVICE* device = first_device; device; device = device->next_device) {
139                 device->reset();
140         }
141 }
142
143 void VM::run()
144 {
145         event->drive();
146 }
147
148 // ----------------------------------------------------------------------------
149 // debugger
150 // ----------------------------------------------------------------------------
151
152 #ifdef USE_DEBUGGER
153 DEVICE *VM::get_cpu(int index)
154 {
155         if(index == 0) {
156                 return cpu;
157         }
158         return NULL;
159 }
160 #endif
161
162 // ----------------------------------------------------------------------------
163 // draw screen
164 // ----------------------------------------------------------------------------
165
166 void VM::draw_screen()
167 {
168         display->draw_screen();
169 }
170
171 // ----------------------------------------------------------------------------
172 // soud manager
173 // ----------------------------------------------------------------------------
174
175 void VM::initialize_sound(int rate, int samples)
176 {
177         // init sound manager
178         event->initialize_sound(rate, samples);
179 }
180
181 uint16_t* VM::create_sound(int* extra_frames)
182 {
183         return event->create_sound(extra_frames);
184 }
185
186 int VM::get_sound_buffer_ptr()
187 {
188         return event->get_sound_buffer_ptr();
189 }
190
191 // ----------------------------------------------------------------------------
192 // notify key
193 // ----------------------------------------------------------------------------
194
195 void VM::key_down(int code, bool repeat)
196 {
197         keyboard->key_down(code);
198 }
199
200 void VM::key_up(int code)
201 {
202         //keyboard->key_up(code);
203 }
204
205 // ----------------------------------------------------------------------------
206 // user interface
207 // ----------------------------------------------------------------------------
208
209 void VM::load_binary(int drv, const _TCHAR* file_path)
210 {
211         if(drv == 0) {
212                 memory->read_image(file_path, ram, sizeof(ram));
213         }
214 }
215
216 void VM::save_binary(int drv, const _TCHAR* file_path)
217 {
218         if(drv == 0) {
219                 memory->write_image(file_path, ram, sizeof(ram));
220         }
221 }
222
223 bool VM::is_frame_skippable()
224 {
225         return event->is_frame_skippable();
226 }
227
228 void VM::update_config()
229 {
230         for(DEVICE* device = first_device; device; device = device->next_device) {
231                 device->update_config();
232         }
233 }
234
235 #define STATE_VERSION   2
236
237 bool VM::process_state(FILEIO* state_fio, bool loading)
238 {
239         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
240                 return false;
241         }
242         for(DEVICE* device = first_device; device; device = device->next_device) {
243                 // Note: typeid(foo).name is fixed by recent ABI.Not dec 6.
244                 // const char *name = typeid(*device).name();
245                 //       But, using get_device_name() instead of typeid(foo).name() 20181008 K.O
246                 const char *name = device->get_device_name();
247                 int len = strlen(name);
248                 
249                 if(!state_fio->StateCheckInt32(len)) {
250                         if(loading) {
251                                 printf("Class name len Error: DEVID=%d EXPECT=%s\n", device->this_device_id, name);
252                         }
253                         return false;
254                 }
255                 if(!state_fio->StateCheckBuffer(name, len, 1)) {
256                         if(loading) {
257                                 printf("Class name Error: DEVID=%d EXPECT=%s\n", device->this_device_id, name);
258                         }
259                         return false;
260                 }
261                 if(!device->process_state(state_fio, loading)) {
262                         if(loading) {
263                                 printf("Data loading Error: DEVID=%d\n", device->this_device_id);
264                         }
265                         return false;
266                 }
267         }
268         // Machine specified.
269         state_fio->StateBuffer(ram, sizeof(ram), 1);
270         if(loading) {
271                 update_config();
272         }
273         return true;
274 }