OSDN Git Service

Merge branch 'master' of github.com:Artanejp/common_source_project-fm7
[csp-qt/common_source_project-fm7.git] / source / src / vm / rx78 / rx78.cpp
1 /*
2         BANDAI RX-78 Emulator 'eRX-78'
3
4         Author : Takeda.Toshiya
5         Date   : 2006.08.21 -
6
7         [ virtual machine ]
8 */
9
10 #include "rx78.h"
11 #include "../../emu.h"
12 #include "../device.h"
13 #include "../event.h"
14
15 #include "../datarec.h"
16 #include "../io.h"
17 #include "../noise.h"
18 #include "../sn76489an.h"
19 #include "../z80.h"
20
21 #ifdef USE_DEBUGGER
22 #include "../debugger.h"
23 #endif
24
25 #include "cmt.h"
26 #include "keyboard.h"
27 #include "memory.h"
28 #include "printer.h"
29 #include "vdp.h"
30
31 // ----------------------------------------------------------------------------
32 // initialize
33 // ----------------------------------------------------------------------------
34
35 VM::VM(EMU* parent_emu) : emu(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         dummy->set_device_name(_T("1st Dummy"));
42         
43         drec = new DATAREC(this, emu);
44         drec->set_context_noise_play(new NOISE(this, emu));
45         drec->set_context_noise_stop(new NOISE(this, emu));
46         drec->set_context_noise_fast(new NOISE(this, emu));
47         io = new IO(this, emu);
48         psg = new SN76489AN(this, emu);
49         cpu = new Z80(this, emu);
50         
51         cmt = new CMT(this, emu);
52         key = new KEYBOARD(this, emu);
53         memory = new MEMORY(this, emu);
54         prt = new PRINTER(this, emu);
55         vdp = new VDP(this, emu);
56         
57         // set contexts
58         event->set_context_cpu(cpu);
59         event->set_context_sound(psg);
60         event->set_context_sound(drec);
61         event->set_context_sound(drec->get_context_noise_play());
62         event->set_context_sound(drec->get_context_noise_stop());
63         event->set_context_sound(drec->get_context_noise_fast());
64         
65         drec->set_context_ear(cmt, SIG_CMT_IN, 1);
66         cmt->set_context_drec(drec);
67         vdp->set_context_cpu(cpu);
68         vdp->set_vram_ptr(memory->get_vram());
69         
70         // cpu bus
71         cpu->set_context_mem(memory);
72         cpu->set_context_io(io);
73         cpu->set_context_intr(dummy);
74 #ifdef USE_DEBUGGER
75         cpu->set_context_debugger(new DEBUGGER(this, emu));
76 #endif
77         
78         // i/o bus
79         io->set_iomap_range_rw(0xe2, 0xe3, prt);
80         io->set_iomap_single_rw(0xf0, cmt);
81         io->set_iomap_range_w(0xf1, 0xf2, memory);
82         io->set_iomap_single_rw(0xf4, key);
83         io->set_iomap_range_w(0xf5, 0xfc, vdp);
84         io->set_iomap_single_w(0xfe, vdp);
85         io->set_iomap_single_w(0xff, psg);
86         
87         // initialize all devices
88         for(DEVICE* device = first_device; device; device = device->next_device) {
89                 device->initialize();
90         }
91         decl_state();
92 }
93
94 VM::~VM()
95 {
96         // delete all devices
97         for(DEVICE* device = first_device; device;) {
98                 DEVICE *next_device = device->next_device;
99                 device->release();
100                 delete device;
101                 device = next_device;
102         }
103 }
104
105 DEVICE* VM::get_device(int id)
106 {
107         for(DEVICE* device = first_device; device; device = device->next_device) {
108                 if(device->this_device_id == id) {
109                         return device;
110                 }
111         }
112         return NULL;
113 }
114
115 // ----------------------------------------------------------------------------
116 // debugger
117 // ----------------------------------------------------------------------------
118
119 #ifdef USE_DEBUGGER
120 DEVICE *VM::get_cpu(int index)
121 {
122         if(index == 0) {
123                 return cpu;
124         }
125         return NULL;
126 }
127 #endif
128
129 // ----------------------------------------------------------------------------
130 // drive virtual machine
131 // ----------------------------------------------------------------------------
132
133 void VM::reset()
134 {
135         // reset all devices
136         for(DEVICE* device = first_device; device; device = device->next_device) {
137                 device->reset();
138         }
139 }
140
141 void VM::run()
142 {
143         event->drive();
144 }
145
146 // ----------------------------------------------------------------------------
147 // draw screen
148 // ----------------------------------------------------------------------------
149
150 void VM::draw_screen()
151 {
152         vdp->draw_screen();
153 }
154
155 // ----------------------------------------------------------------------------
156 // soud manager
157 // ----------------------------------------------------------------------------
158
159 void VM::initialize_sound(int rate, int samples)
160 {
161         // init sound manager
162         event->initialize_sound(rate, samples);
163         
164         // init sound gen
165         psg->initialize_sound(rate, 3579545, 8000);
166 }
167
168 uint16_t* VM::create_sound(int* extra_frames)
169 {
170         return event->create_sound(extra_frames);
171 }
172
173 int VM::get_sound_buffer_ptr()
174 {
175         return event->get_sound_buffer_ptr();
176 }
177
178 #ifdef USE_SOUND_VOLUME
179 void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
180 {
181         if(ch == 0) {
182                 psg->set_volume(0, decibel_l, decibel_r);
183         } else if(ch == 1) {
184                 drec->set_volume(0, decibel_l, decibel_r);
185         } else if(ch == 2) {
186                 drec->get_context_noise_play()->set_volume(0, decibel_l, decibel_r);
187                 drec->get_context_noise_stop()->set_volume(0, decibel_l, decibel_r);
188                 drec->get_context_noise_fast()->set_volume(0, decibel_l, decibel_r);
189         }
190 }
191 #endif
192
193 // ----------------------------------------------------------------------------
194 // user interface
195 // ----------------------------------------------------------------------------
196
197 void VM::open_cart(int drv, const _TCHAR* file_path)
198 {
199         if(drv == 0) {
200                 memory->open_cart(file_path);
201                 reset();
202         }
203 }
204
205 void VM::close_cart(int drv)
206 {
207         if(drv == 0) {
208                 memory->close_cart();
209                 reset();
210         }
211 }
212
213 bool VM::is_cart_inserted(int drv)
214 {
215         if(drv == 0) {
216                 return memory->is_cart_inserted();
217         } else {
218                 return false;
219         }
220 }
221
222 void VM::play_tape(int drv, const _TCHAR* file_path)
223 {
224         drec->play_tape(file_path);
225 //      drec->set_remote(true);
226 }
227
228 void VM::rec_tape(int drv, const _TCHAR* file_path)
229 {
230         drec->rec_tape(file_path);
231 //      drec->set_remote(true);
232 }
233
234 void VM::close_tape(int drv)
235 {
236         emu->lock_vm();
237         drec->close_tape();
238         emu->unlock_vm();
239 //      drec->set_remote(false);
240 }
241
242 bool VM::is_tape_inserted(int drv)
243 {
244         return drec->is_tape_inserted();
245 }
246
247 bool VM::is_tape_playing(int drv)
248 {
249         return drec->is_tape_playing();
250 }
251
252 bool VM::is_tape_recording(int drv)
253 {
254         return drec->is_tape_recording();
255 }
256
257 int VM::get_tape_position(int drv)
258 {
259         return drec->get_tape_position();
260 }
261
262 const _TCHAR* VM::get_tape_message(int drv)
263 {
264         return drec->get_message();
265 }
266
267 void VM::push_play(int drv)
268 {
269         drec->set_ff_rew(0);
270         drec->set_remote(true);
271 }
272
273 void VM::push_stop(int drv)
274 {
275         drec->set_remote(false);
276 }
277
278 void VM::push_fast_forward(int drv)
279 {
280         drec->set_ff_rew(1);
281         drec->set_remote(true);
282 }
283
284 void VM::push_fast_rewind(int drv)
285 {
286         drec->set_ff_rew(-1);
287         drec->set_remote(true);
288 }
289
290 bool VM::is_frame_skippable()
291 {
292         return event->is_frame_skippable();
293 }
294
295 void VM::update_config()
296 {
297         for(DEVICE* device = first_device; device; device = device->next_device) {
298                 device->update_config();
299         }
300 }
301
302 #define STATE_VERSION   3
303
304 #include "../../statesub.h"
305
306 void VM::decl_state(void)
307 {
308         state_entry = new csp_state_utils(STATE_VERSION, 0, (_TCHAR *)(_T("CSP::RX_78_HEAD")));
309         for(DEVICE* device = first_device; device; device = device->next_device) {
310                 device->decl_state();
311         }
312 }
313
314 void VM::save_state(FILEIO* state_fio)
315 {
316         //state_fio->FputUint32(STATE_VERSION);
317         
318         if(state_entry != NULL) {
319                 state_entry->save_state(state_fio);
320         }
321         for(DEVICE* device = first_device; device; device = device->next_device) {
322                 device->save_state(state_fio);
323         }
324 }
325
326 bool VM::load_state(FILEIO* state_fio)
327 {
328         //if(state_fio->FgetUint32() != STATE_VERSION) {
329         //      return false;
330         //}
331         bool mb = false;
332         if(state_entry != NULL) {
333                 mb = state_entry->load_state(state_fio);
334         }
335         if(!mb) {
336                 emu->out_debug_log("INFO: HEADER DATA ERROR");
337                 return false;
338         }
339         for(DEVICE* device = first_device; device; device = device->next_device) {
340                 if(!device->load_state(state_fio)) {
341                         return false;
342                 }
343         }
344         return true;
345 }
346