OSDN Git Service

[General][WIP] Merge upstream 2017-03-20.Still not implement UIs.
[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
30 VM::VM(EMU* parent_emu) : emu(parent_emu)
31 {
32         // create devices
33         first_device = last_device = NULL;
34         dummy = new DEVICE(this, emu);  // must be 1st device
35         event = new EVENT(this, emu);   // must be 2nd device
36         
37         drec = new DATAREC(this, emu);
38         drec->set_context_noise_play(new NOISE(this, emu));
39         drec->set_context_noise_stop(new NOISE(this, emu));
40         drec->set_context_noise_fast(new NOISE(this, emu));
41         cpu = new MC6800(this, emu);
42         pia = new MC6820(this, emu);
43         
44         memory = new MEMORY(this, emu);
45         
46         // Set names
47 #if defined(_USE_QT)
48         dummy->set_device_name(_T("1st Dummy"));
49         event->set_device_name(_T("EVENT"));
50         cpu->set_device_name(_T("CPU(MC6800)"));
51         pia->set_device_name(_T("MC6820 PIA"));
52         memory->set_device_name(_T("MEMORY"));
53 #endif
54         // set contexts
55         event->set_context_cpu(cpu);
56         event->set_context_sound(drec);
57         event->set_context_sound(memory);
58         event->set_context_sound(drec->get_context_noise_play());
59         event->set_context_sound(drec->get_context_noise_stop());
60         event->set_context_sound(drec->get_context_noise_fast());
61         
62         drec->set_context_ear(memory, SIG_MEMORY_DATAREC_EAR, 1);
63         
64         memory->set_context_drec(drec);
65         memory->set_context_cpu(cpu);
66         memory->set_context_pia(pia);
67         
68         // cpu bus
69         cpu->set_context_mem(memory);
70 #ifdef USE_DEBUGGER
71         cpu->set_context_debugger(new DEBUGGER(this, emu));
72 #endif
73         
74         // initialize all devices
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 }
188 #endif
189
190 // ----------------------------------------------------------------------------
191 // notify key
192 // ----------------------------------------------------------------------------
193
194 void VM::key_down(int code, bool repeat)
195 {
196         if(!repeat) {
197                 memory->key_down(code);
198         }
199 }
200
201 void VM::key_up(int code)
202 {
203 }
204
205 // ----------------------------------------------------------------------------
206 // user interface
207 // ----------------------------------------------------------------------------
208
209 void VM::play_tape(int drv, const _TCHAR* file_path)
210 {
211         drec->play_tape(file_path);
212         push_play(drv);
213 }
214
215 void VM::rec_tape(int drv, const _TCHAR* file_path)
216 {
217         drec->rec_tape(file_path);
218 //      push_play(drv);
219 }
220
221 void VM::close_tape(int drv)
222 {
223         push_stop(drv);
224         emu->lock_vm();
225         drec->close_tape();
226         emu->unlock_vm();
227 }
228
229 bool VM::is_tape_inserted(int drv)
230 {
231         return drec->is_tape_inserted();
232 }
233
234 bool VM::is_tape_playing(int drv)
235 {
236         return drec->is_tape_playing();
237 }
238
239 bool VM::is_tape_recording(int drv)
240 {
241         return drec->is_tape_recording();
242 }
243
244 int VM::get_tape_position(int drv)
245 {
246         return drec->get_tape_position();
247 }
248
249 const _TCHAR* VM::get_tape_message(int drv)
250 {
251         return drec->get_message();
252 }
253
254 void VM::push_play(int drv)
255 {
256         drec->set_ff_rew(0);
257         drec->set_remote(true);
258 }
259
260 void VM::push_stop(int drv)
261 {
262         drec->set_remote(false);
263 }
264
265 void VM::push_fast_forward(int drv)
266 {
267         drec->set_ff_rew(1);
268         drec->set_remote(true);
269 }
270
271 void VM::push_fast_rewind(int drv)
272 {
273         drec->set_ff_rew(-1);
274         drec->set_remote(true);
275 }
276
277 bool VM::is_frame_skippable()
278 {
279         return event->is_frame_skippable();
280 }
281
282 void VM::update_config()
283 {
284         for(DEVICE* device = first_device; device; device = device->next_device) {
285                 device->update_config();
286         }
287 }
288
289 #define STATE_VERSION   2
290
291 void VM::save_state(FILEIO* state_fio)
292 {
293         state_fio->FputUint32(STATE_VERSION);
294         
295         for(DEVICE* device = first_device; device; device = device->next_device) {
296                 device->save_state(state_fio);
297         }
298 }
299
300 bool VM::load_state(FILEIO* state_fio)
301 {
302         if(state_fio->FgetUint32() != STATE_VERSION) {
303                 return false;
304         }
305         for(DEVICE* device = first_device; device; device = device->next_device) {
306                 if(!device->load_state(state_fio)) {
307                         return false;
308                 }
309         }
310         return true;
311 }
312