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 / bmjr / bmjr.cpp
1 /*
2         HITACH BASIC Master Jr Emulator 'eBASICMasterJr'
3
4         Author : Takeda.Toshiya
5         Date   : 2015.08.28-
6
7         [ virtual machine ]
8 */
9
10 #include "bmjr.h"
11 #include "../../emu.h"
12 #include "../device.h"
13 #include "../event.h"
14
15 #include "../datarec.h"
16 #include "../mc6800.h"
17 #include "../mc6820.h"
18 #include "../noise.h"
19
20 #ifdef USE_DEBUGGER
21 #include "../debugger.h"
22 #endif
23
24 #include "./memory.h"
25
26 // ----------------------------------------------------------------------------
27 // initialize
28 // ----------------------------------------------------------------------------
29 using BMJR::MEMORY;
30
31 VM::VM(EMU* parent_emu) : VM_TEMPLATE(parent_emu)
32 {
33         // create devices
34         first_device = last_device = NULL;
35         dummy = new DEVICE(this, emu);  // must be 1st device
36         event = new EVENT(this, emu);   // must be 2nd device
37         
38         drec = new DATAREC(this, emu);
39         drec->set_context_noise_play(new NOISE(this, emu));
40         drec->set_context_noise_stop(new NOISE(this, emu));
41         drec->set_context_noise_fast(new NOISE(this, emu));
42         cpu = new MC6800(this, emu);
43         pia = new MC6820(this, emu);
44         
45         memory = new MEMORY(this, emu);
46         
47         // Set names
48 #if defined(_USE_QT)
49         dummy->set_device_name(_T("1st Dummy"));
50 #endif
51         // set contexts
52         event->set_context_cpu(cpu);
53         event->set_context_sound(drec);
54         event->set_context_sound(memory);
55         event->set_context_sound(drec->get_context_noise_play());
56         event->set_context_sound(drec->get_context_noise_stop());
57         event->set_context_sound(drec->get_context_noise_fast());
58         
59         drec->set_context_ear(memory, SIG_MEMORY_DATAREC_EAR, 1);
60         
61         memory->set_context_drec(drec);
62         memory->set_context_cpu(cpu);
63         memory->set_context_pia(pia);
64         
65         // cpu bus
66         cpu->set_context_mem(memory);
67 #ifdef USE_DEBUGGER
68         cpu->set_context_debugger(new DEBUGGER(this, emu));
69 #endif
70         
71         // initialize all devices
72 #if defined(__GIT_REPO_VERSION)
73         strncpy(_git_revision, __GIT_REPO_VERSION, sizeof(_git_revision) - 1);
74 #endif
75         for(DEVICE* device = first_device; device; device = device->next_device) {
76                 device->initialize();
77         }
78 }
79
80 VM::~VM()
81 {
82         // delete all devices
83         for(DEVICE* device = first_device; device;) {
84                 DEVICE *next_device = device->next_device;
85                 device->release();
86                 delete device;
87                 device = next_device;
88         }
89 }
90
91 DEVICE* VM::get_device(int id)
92 {
93         for(DEVICE* device = first_device; device; device = device->next_device) {
94                 if(device->this_device_id == id) {
95                         return device;
96                 }
97         }
98         return NULL;
99 }
100
101 // ----------------------------------------------------------------------------
102 // drive virtual machine
103 // ----------------------------------------------------------------------------
104
105 void VM::reset()
106 {
107         // reset all devices
108         for(DEVICE* device = first_device; device; device = device->next_device) {
109                 device->reset();
110         }
111 }
112
113 void VM::special_reset()
114 {
115         // reset all devices
116         for(DEVICE* device = first_device; device; device = device->next_device) {
117                 device->reset();
118         }
119 }
120
121 void VM::run()
122 {
123         event->drive();
124 }
125
126 double VM::get_frame_rate()
127 {
128         return event->get_frame_rate();
129 }
130
131 // ----------------------------------------------------------------------------
132 // debugger
133 // ----------------------------------------------------------------------------
134
135 #ifdef USE_DEBUGGER
136 DEVICE *VM::get_cpu(int index)
137 {
138         if(index == 0) {
139                 return cpu;
140         }
141         return NULL;
142 }
143 #endif
144
145 // ----------------------------------------------------------------------------
146 // draw screen
147 // ----------------------------------------------------------------------------
148
149 void VM::draw_screen()
150 {
151         memory->draw_screen();
152 }
153
154 // ----------------------------------------------------------------------------
155 // soud manager
156 // ----------------------------------------------------------------------------
157
158 void VM::initialize_sound(int rate, int samples)
159 {
160         // init sound manager
161         event->initialize_sound(rate, samples);
162 }
163
164 uint16_t* VM::create_sound(int* extra_frames)
165 {
166         return event->create_sound(extra_frames);
167 }
168
169 int VM::get_sound_buffer_ptr()
170 {
171         return event->get_sound_buffer_ptr();
172 }
173
174 #ifdef USE_SOUND_VOLUME
175 void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
176 {
177         if(ch == 0) {
178                 memory->set_volume(0, decibel_l, decibel_r);
179         } else if(ch == 1) {
180                 drec->set_volume(0, decibel_l, decibel_r);
181         } else if(ch == 2) {
182                 drec->get_context_noise_play()->set_volume(0, decibel_l, decibel_r);
183                 drec->get_context_noise_stop()->set_volume(0, decibel_l, decibel_r);
184                 drec->get_context_noise_fast()->set_volume(0, decibel_l, decibel_r);
185         }
186 }
187 #endif
188
189 // ----------------------------------------------------------------------------
190 // notify key
191 // ----------------------------------------------------------------------------
192
193 void VM::key_down(int code, bool repeat)
194 {
195         if(!repeat) {
196                 memory->key_down(code);
197         }
198 }
199
200 void VM::key_up(int code)
201 {
202 }
203
204 // ----------------------------------------------------------------------------
205 // user interface
206 // ----------------------------------------------------------------------------
207
208 void VM::play_tape(int drv, const _TCHAR* file_path)
209 {
210         drec->play_tape(file_path);
211 //      drec->set_remote(true);
212 }
213
214 void VM::rec_tape(int drv, const _TCHAR* file_path)
215 {
216         drec->rec_tape(file_path);
217 //      drec->set_remote(true);
218 }
219
220 void VM::close_tape(int drv)
221 {
222         emu->lock_vm();
223         drec->close_tape();
224         emu->unlock_vm();
225 //      drec->set_remote(false);
226 }
227
228 bool VM::is_tape_inserted(int drv)
229 {
230         return drec->is_tape_inserted();
231 }
232
233 bool VM::is_tape_playing(int drv)
234 {
235         return drec->is_tape_playing();
236 }
237
238 bool VM::is_tape_recording(int drv)
239 {
240         return drec->is_tape_recording();
241 }
242
243 int VM::get_tape_position(int drv)
244 {
245         return drec->get_tape_position();
246 }
247
248 const _TCHAR* VM::get_tape_message(int drv)
249 {
250         return drec->get_message();
251 }
252
253 void VM::push_play(int drv)
254 {
255         drec->set_ff_rew(0);
256         drec->set_remote(true);
257 }
258
259 void VM::push_stop(int drv)
260 {
261         drec->set_remote(false);
262 }
263
264 void VM::push_fast_forward(int drv)
265 {
266         drec->set_ff_rew(1);
267         drec->set_remote(true);
268 }
269
270 void VM::push_fast_rewind(int drv)
271 {
272         drec->set_ff_rew(-1);
273         drec->set_remote(true);
274 }
275
276 bool VM::is_frame_skippable()
277 {
278         return event->is_frame_skippable();
279 }
280
281 void VM::update_config()
282 {
283         for(DEVICE* device = first_device; device; device = device->next_device) {
284                 device->update_config();
285         }
286 }
287
288 #define STATE_VERSION   3
289
290
291 bool VM::process_state(FILEIO* state_fio, bool loading)
292 {
293         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
294                 return false;
295         }
296         for(DEVICE* device = first_device; device; device = device->next_device) {
297                 // Note: typeid(foo).name is fixed by recent ABI.Not dec 6.
298                 // const char *name = typeid(*device).name();
299                 //       But, using get_device_name() instead of typeid(foo).name() 20181008 K.O
300                 const char *name = device->get_device_name();
301                 int len = strlen(name);
302                 
303                 if(!state_fio->StateCheckInt32(len)) {
304                         if(loading) {
305                                 printf("Class name len Error: DEVID=%d EXPECT=%s\n", device->this_device_id, name);
306                         }
307                         return false;
308                 }
309                 if(!state_fio->StateCheckBuffer(name, len, 1)) {
310                         if(loading) {
311                                 printf("Class name Error: DEVID=%d EXPECT=%s\n", device->this_device_id, name);
312                         }
313                         return false;
314                 }
315                 if(!device->process_state(state_fio, loading)) {
316                         if(loading) {
317                                 printf("Data loading Error: DEVID=%d\n", device->this_device_id);
318                         }
319                         return false;
320                 }
321         }
322         // Machine specified.
323         if(loading) {
324                 update_config();
325         }
326         return true;
327 }