OSDN Git Service

[VM] Apply new APIs to all VMs.
[csp-qt/common_source_project-fm7.git] / source / src / vm / fp200 / fp200.cpp
1 /*
2         CASIO FP-200 Emulator 'eFP-200'
3
4         Author : Takeda.Toshiya
5         Date   : 2013.03.21-
6
7         [ virtual machine ]
8 */
9
10 #include "fp200.h"
11 #include "../../emu.h"
12 #include "../device.h"
13 #include "../event.h"
14
15 #include "../datarec.h"
16 #include "../i8080.h"
17 #include "../memory.h"
18 #include "../noise.h"
19 #include "../rp5c01.h"
20
21 #ifdef USE_DEBUGGER
22 #include "../debugger.h"
23 #endif
24
25 #include "./io.h"
26
27 // ----------------------------------------------------------------------------
28 // initialize
29 // ----------------------------------------------------------------------------
30 using FP200::IO;
31
32 VM::VM(EMU_TEMPLATE* parent_emu) : VM_TEMPLATE(parent_emu)
33 {
34         // create devices
35         first_device = last_device = NULL;
36         dummy = new DEVICE(this, emu);  // must be 1st device
37         event = new EVENT(this, emu);   // must be 2nd device
38         dummy->set_device_name(_T("1st Dummy"));
39
40         drec = new DATAREC(this, emu);
41         drec->set_context_noise_play(new NOISE(this, emu));
42         drec->set_context_noise_stop(new NOISE(this, emu));
43         drec->set_context_noise_fast(new NOISE(this, emu));
44         cpu = new I8080(this, emu);     // i8085
45         memory = new MEMORY(this, emu);
46         
47         rtc = new RP5C01(this, emu);
48         
49         io = new IO(this, emu);
50         // set contexts
51         event->set_context_cpu(cpu);
52         event->set_context_sound(drec);
53         event->set_context_sound(drec->get_context_noise_play());
54         event->set_context_sound(drec->get_context_noise_stop());
55         event->set_context_sound(drec->get_context_noise_fast());
56         
57         drec->set_context_ear(io, SIG_IO_CMT, 1);
58         cpu->set_context_sod(io, SIG_IO_SOD, 1);
59         
60         io->set_context_cpu(cpu);
61         io->set_context_drec(drec);
62         io->set_context_rtc(rtc);
63         
64         // cpu bus
65         cpu->set_context_mem(memory);
66         cpu->set_context_io(io);
67         cpu->set_context_intr(io);
68 #ifdef USE_DEBUGGER
69         cpu->set_context_debugger(new DEBUGGER(this, emu));
70 #endif
71         
72         // memory bus
73         memset(rom, 0xff, sizeof(rom));
74         memset(ram, 0, sizeof(ram));
75         
76         memory->read_bios(_T("BIOS.ROM"), rom, sizeof(rom));
77         
78         FILEIO* fio = new FILEIO();
79         if(fio->Fopen(create_local_path(_T("RAM.BIN")), FILEIO_READ_BINARY)) {
80                 fio->Fread(ram, sizeof(ram), 1);
81                 fio->Fclose();
82         }
83         delete fio;
84         
85         memory->set_memory_r(0x0000, 0x7fff, rom);
86         memory->set_memory_rw(0x8000, 0xffff, ram);
87         memory->set_wait_rw(0x0000, 0xffff, 1);
88         
89         // initialize all devices
90 #if defined(__GIT_REPO_VERSION)
91         set_git_repo_version(__GIT_REPO_VERSION);
92 #endif
93         initialize_devices();
94         
95 }
96
97 VM::~VM()
98 {
99         FILEIO* fio = new FILEIO();
100         if(fio->Fopen(create_local_path(_T("RAM.BIN")), FILEIO_WRITE_BINARY)) {
101                 fio->Fwrite(ram, sizeof(ram), 1);
102                 fio->Fclose();
103         }
104         delete fio;
105         
106         // delete all devices
107         for(DEVICE* device = first_device; device;) {
108                 DEVICE *next_device = device->next_device;
109                 device->release();
110                 delete device;
111                 device = next_device;
112         }
113 }
114
115 // ----------------------------------------------------------------------------
116 // drive virtual machine
117 // ----------------------------------------------------------------------------
118 void VM::run()
119 {
120         event->drive();
121 }
122
123 // ----------------------------------------------------------------------------
124 // debugger
125 // ----------------------------------------------------------------------------
126
127 #ifdef USE_DEBUGGER
128 DEVICE *VM::get_cpu(int index)
129 {
130         if(index == 0) {
131                 return cpu;
132         }
133         return NULL;
134 }
135 #endif
136
137 // ----------------------------------------------------------------------------
138 // draw screen
139 // ----------------------------------------------------------------------------
140
141 void VM::draw_screen()
142 {
143         io->draw_screen();
144 }
145
146 // ----------------------------------------------------------------------------
147 // soud manager
148 // ----------------------------------------------------------------------------
149
150 void VM::initialize_sound(int rate, int samples)
151 {
152         // init sound manager
153         event->initialize_sound(rate, samples);
154 }
155
156 uint16_t* VM::create_sound(int* extra_frames)
157 {
158         return event->create_sound(extra_frames);
159 }
160
161 int VM::get_sound_buffer_ptr()
162 {
163         return event->get_sound_buffer_ptr();
164 }
165
166 #ifdef USE_SOUND_VOLUME
167 void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
168 {
169         if(ch == 0) {
170                 drec->set_volume(0, decibel_l, decibel_r);
171         } else if(ch == 1) {
172                 drec->get_context_noise_play()->set_volume(0, decibel_l, decibel_r);
173                 drec->get_context_noise_stop()->set_volume(0, decibel_l, decibel_r);
174                 drec->get_context_noise_fast()->set_volume(0, decibel_l, decibel_r);
175         }
176 }
177 #endif
178
179 // ----------------------------------------------------------------------------
180 // notify key
181 // ----------------------------------------------------------------------------
182
183 void VM::key_down(int code, bool repeat)
184 {
185         if(!repeat) {
186                 io->key_down(code);
187         }
188 }
189
190 void VM::key_up(int code)
191 {
192         io->key_up();
193 }
194
195 // ----------------------------------------------------------------------------
196 // user interface
197 // ----------------------------------------------------------------------------
198
199 void VM::play_tape(int drv, const _TCHAR* file_path)
200 {
201         io->close_tape();
202         
203         bool remote = drec->get_remote();
204         
205         if(drec->play_tape(file_path) && remote) {
206                 // if machine already sets remote on, start playing now
207                 push_play(drv);
208         }
209 }
210
211 void VM::rec_tape(int drv, const _TCHAR* file_path)
212 {
213         emu->lock_vm();
214         drec->close_tape();
215         emu->unlock_vm();
216         drec->set_remote(false);
217         io->rec_tape(file_path);
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         io->close_tape();
228 }
229
230 bool VM::is_tape_inserted(int drv)
231 {
232         return drec->is_tape_inserted() || io->is_tape_inserted();
233 }
234
235 bool VM::is_tape_playing(int drv)
236 {
237         if(drec->is_tape_inserted()) {
238                 return drec->is_tape_playing();
239         } else {
240                 return io->is_tape_playing();
241         }
242 }
243
244 bool VM::is_tape_recording(int drv)
245 {
246         if(drec->is_tape_inserted()) {
247                 return drec->is_tape_recording();
248         } else {
249                 return io->is_tape_recording();
250         }
251 }
252
253 int VM::get_tape_position(int drv)
254 {
255         if(drec->is_tape_inserted()) {
256                 return drec->get_tape_position();
257         } else {
258                 return io->get_tape_position();
259         }
260 }
261
262 const _TCHAR* VM::get_tape_message(int drv)
263 {
264         if(drec->is_tape_inserted()) {
265                 return drec->get_message();
266         } else {
267                 return NULL;
268         }
269 }
270
271 void VM::push_play(int drv)
272 {
273         if(drec->is_tape_inserted()) {
274                 drec->set_remote(false);
275                 drec->set_ff_rew(0);
276                 drec->set_remote(true);
277         }
278 }
279
280 void VM::push_stop(int drv)
281 {
282         if(drec->is_tape_inserted()) {
283                 drec->set_remote(false);
284         }
285 }
286
287 void VM::push_fast_forward(int drv)
288 {
289         if(drec->is_tape_inserted()) {
290                 drec->set_remote(false);
291                 drec->set_ff_rew(1);
292                 drec->set_remote(true);
293         }
294 }
295
296 void VM::push_fast_rewind(int drv)
297 {
298         if(drec->is_tape_inserted()) {
299                 drec->set_remote(false);
300                 drec->set_ff_rew(-1);
301                 drec->set_remote(true);
302         }
303 }
304
305 bool VM::is_frame_skippable()
306 {
307         return event->is_frame_skippable();
308 }
309
310
311 double VM::get_current_usec()
312 {
313         __UNLIKELY_IF(event == NULL) return 0.0;
314         return event->get_current_usec();
315 }
316
317 uint64_t VM::get_current_clock_uint64()
318 {
319         __UNLIKELY_IF(event == NULL) return (uint64_t)0;
320         return event->get_current_clock_uint64();
321 }
322
323 #define STATE_VERSION   3
324
325 bool VM::process_state(FILEIO* state_fio, bool loading)
326 {
327         if(!(VM_TEMPLATE::process_state_core(state_fio, loading, STATE_VERSION))) {
328                 return false;
329         }
330         state_fio->StateArray(ram, sizeof(ram), 1);
331         return true;
332 }