OSDN Git Service

[VM][DEVICE] Add name of devices (or blocks) from BABAGE2nd to MZ-2500, PC-8001/8801...
[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
19 #ifdef USE_DEBUGGER
20 #include "../debugger.h"
21 #endif
22
23 #include "memory.h"
24
25 // ----------------------------------------------------------------------------
26 // initialize
27 // ----------------------------------------------------------------------------
28
29 VM::VM(EMU* parent_emu) : emu(parent_emu)
30 {
31         // create devices
32         first_device = last_device = NULL;
33         dummy = new DEVICE(this, emu);  // must be 1st device
34         event = new EVENT(this, emu);   // must be 2nd device
35         
36         drec = new DATAREC(this, emu);
37         cpu = new MC6800(this, emu);
38         pia = new MC6820(this, emu);
39         
40         memory = new MEMORY(this, emu);
41         
42         // Set names
43 #if defined(_USE_QT)
44         dummy->set_device_name(_T("1st Dummy"));
45         event->set_device_name(_T("EVENT"));
46         cpu->set_device_name(_T("CPU(MC6800)"));
47         pia->set_device_name(_T("MC6820 PIA"));
48         memory->set_device_name(_T("MEMORY"));
49 #endif
50         // set contexts
51         event->set_context_cpu(cpu);
52         event->set_context_sound(drec);
53         event->set_context_sound(memory);
54         
55         drec->set_context_ear(memory, SIG_MEMORY_DATAREC_EAR, 1);
56         
57         memory->set_context_drec(drec);
58         memory->set_context_cpu(cpu);
59         memory->set_context_pia(pia);
60         
61         // cpu bus
62         cpu->set_context_mem(memory);
63 #ifdef USE_DEBUGGER
64         cpu->set_context_debugger(new DEBUGGER(this, emu));
65 #endif
66         
67         // initialize all devices
68         for(DEVICE* device = first_device; device; device = device->next_device) {
69                 device->initialize();
70         }
71 }
72
73 VM::~VM()
74 {
75         // delete all devices
76         for(DEVICE* device = first_device; device;) {
77                 DEVICE *next_device = device->next_device;
78                 device->release();
79                 delete device;
80                 device = next_device;
81         }
82 }
83
84 DEVICE* VM::get_device(int id)
85 {
86         for(DEVICE* device = first_device; device; device = device->next_device) {
87                 if(device->this_device_id == id) {
88                         return device;
89                 }
90         }
91         return NULL;
92 }
93
94 // ----------------------------------------------------------------------------
95 // drive virtual machine
96 // ----------------------------------------------------------------------------
97
98 void VM::reset()
99 {
100         // reset all devices
101         for(DEVICE* device = first_device; device; device = device->next_device) {
102                 device->reset();
103         }
104 }
105
106 void VM::special_reset()
107 {
108         // reset all devices
109         for(DEVICE* device = first_device; device; device = device->next_device) {
110                 device->reset();
111         }
112 }
113
114 void VM::run()
115 {
116         event->drive();
117 }
118
119 double VM::get_frame_rate()
120 {
121         return event->get_frame_rate();
122 }
123
124 // ----------------------------------------------------------------------------
125 // debugger
126 // ----------------------------------------------------------------------------
127
128 #ifdef USE_DEBUGGER
129 DEVICE *VM::get_cpu(int index)
130 {
131         if(index == 0) {
132                 return cpu;
133         }
134         return NULL;
135 }
136 #endif
137
138 // ----------------------------------------------------------------------------
139 // draw screen
140 // ----------------------------------------------------------------------------
141
142 void VM::draw_screen()
143 {
144         memory->draw_screen();
145 }
146
147 // ----------------------------------------------------------------------------
148 // soud manager
149 // ----------------------------------------------------------------------------
150
151 void VM::initialize_sound(int rate, int samples)
152 {
153         // init sound manager
154         event->initialize_sound(rate, samples);
155 }
156
157 uint16_t* VM::create_sound(int* extra_frames)
158 {
159         return event->create_sound(extra_frames);
160 }
161
162 int VM::get_sound_buffer_ptr()
163 {
164         return event->get_sound_buffer_ptr();
165 }
166
167 #ifdef USE_SOUND_VOLUME
168 void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
169 {
170         if(ch == 0) {
171                 memory->set_volume(0, decibel_l, decibel_r);
172         } else if(ch == 1) {
173                 drec->set_volume(0, decibel_l, decibel_r);
174         }
175 }
176 #endif
177
178 // ----------------------------------------------------------------------------
179 // notify key
180 // ----------------------------------------------------------------------------
181
182 void VM::key_down(int code, bool repeat)
183 {
184         if(!repeat) {
185                 memory->key_down(code);
186         }
187 }
188
189 void VM::key_up(int code)
190 {
191 }
192
193 // ----------------------------------------------------------------------------
194 // user interface
195 // ----------------------------------------------------------------------------
196
197 void VM::play_tape(const _TCHAR* file_path)
198 {
199         drec->play_tape(file_path);
200         push_play();
201 }
202
203 void VM::rec_tape(const _TCHAR* file_path)
204 {
205         drec->rec_tape(file_path);
206         push_play();
207 }
208
209 void VM::close_tape()
210 {
211         push_stop();
212         drec->close_tape();
213 }
214
215 bool VM::is_tape_inserted()
216 {
217         return drec->is_tape_inserted();
218 }
219
220 bool VM::is_tape_playing()
221 {
222         return drec->is_tape_playing();
223 }
224
225 bool VM::is_tape_recording()
226 {
227         return drec->is_tape_recording();
228 }
229
230 int VM::get_tape_position()
231 {
232         return drec->get_tape_position();
233 }
234
235 void VM::push_play()
236 {
237         drec->set_ff_rew(0);
238         drec->set_remote(true);
239 }
240
241 void VM::push_stop()
242 {
243         drec->set_remote(false);
244 }
245
246 void VM::push_fast_forward()
247 {
248         drec->set_ff_rew(1);
249         drec->set_remote(true);
250 }
251
252 void VM::push_fast_rewind()
253 {
254         drec->set_ff_rew(-1);
255         drec->set_remote(true);
256 }
257
258 bool VM::is_frame_skippable()
259 {
260         return event->is_frame_skippable();
261 }
262
263 void VM::update_config()
264 {
265         for(DEVICE* device = first_device; device; device = device->next_device) {
266                 device->update_config();
267         }
268 }
269
270 #define STATE_VERSION   1
271
272 void VM::save_state(FILEIO* state_fio)
273 {
274         state_fio->FputUint32(STATE_VERSION);
275         
276         for(DEVICE* device = first_device; device; device = device->next_device) {
277                 device->save_state(state_fio);
278         }
279 }
280
281 bool VM::load_state(FILEIO* state_fio)
282 {
283         if(state_fio->FgetUint32() != STATE_VERSION) {
284                 return false;
285         }
286         for(DEVICE* device = first_device; device; device = device->next_device) {
287                 if(!device->load_state(state_fio)) {
288                         return false;
289                 }
290         }
291         return true;
292 }
293