OSDN Git Service

[BUILD] Set SOVERSION and GIT hash automatically.
[csp-qt/common_source_project-fm7.git] / source / src / vm / pc2001 / pc2001.cpp
1 /*
2         NEC PC-2001 Emulator 'ePC-2001'
3
4         Origin : PockEmul
5         Author : Takeda.Toshiya
6         Date   : 2016.03.18-
7
8         [ virtual machine ]
9 */
10
11 #include "pc2001.h"
12 #include "../../emu.h"
13 #include "../device.h"
14 #include "../event.h"
15
16 #include "../datarec.h"
17 #include "../memory.h"
18 #include "../noise.h"
19 #include "../pcm1bit.h"
20 #include "../upd16434.h"
21 #include "../upd1990a.h"
22 #include "../upd7810.h"
23
24 #ifdef USE_DEBUGGER
25 #include "../debugger.h"
26 #endif
27
28 #include "io.h"
29
30 // ----------------------------------------------------------------------------
31 // initialize
32 // ----------------------------------------------------------------------------
33
34 VM::VM(EMU* parent_emu) : VM_TEMPLATE(parent_emu)
35 {
36         // create devices
37         first_device = last_device = NULL;
38         dummy = new DEVICE(this, emu);  // must be 1st device
39         event = new EVENT(this, emu);   // must be 2nd device
40         
41         drec = new DATAREC(this, emu);
42         drec->set_context_noise_play(new NOISE(this, emu));
43         drec->set_context_noise_stop(new NOISE(this, emu));
44         drec->set_context_noise_fast(new NOISE(this, emu));
45         memory = new MEMORY(this, emu);
46         pcm = new PCM1BIT(this, emu);
47         lcd[0] = new UPD16434(this, emu);
48         lcd[0]->set_device_name(_T("uPD16434 LCD Controller #0"));
49         lcd[1] = new UPD16434(this, emu);
50         lcd[1]->set_device_name(_T("uPD16434 LCD Controller #1"));
51         lcd[2] = new UPD16434(this, emu);
52         lcd[2]->set_device_name(_T("uPD16434 LCD Controller #2"));
53         lcd[3] = new UPD16434(this, emu);
54         lcd[3]->set_device_name(_T("uPD16434 LCD Controller #3"));
55         rtc = new UPD1990A(this, emu);
56         cpu = new UPD7810(this, emu);
57         
58         io = new IO(this, emu);
59         
60         // set contexts
61         event->set_context_cpu(cpu);
62         event->set_context_sound(pcm);
63         event->set_context_sound(drec);
64         event->set_context_sound(drec->get_context_noise_play());
65         event->set_context_sound(drec->get_context_noise_stop());
66         event->set_context_sound(drec->get_context_noise_fast());
67         
68         drec->set_context_ear(io, SIG_IO_DREC_IN, 1);
69         rtc->set_context_dout(io, SIG_IO_RTC_IN, 1);
70         cpu->set_context_to(pcm, SIG_PCM1BIT_SIGNAL, 1);
71         
72         io->set_context_lcd(0, lcd[0]);
73         io->set_context_lcd(1, lcd[1]);
74         io->set_context_lcd(2, lcd[2]);
75         io->set_context_lcd(3, lcd[3]);
76         io->set_context_drec(drec);
77         io->set_context_rtc(rtc);
78         io->set_context_cpu(cpu);
79         
80         // memory bus
81         memset(ram, 0xff, sizeof(ram));
82 //      memset(ram, 0, sizeof(ram));
83         memset(rom1, 0xff, sizeof(rom1));
84         memset(rom2, 0xff, sizeof(rom2));
85         
86         memory->read_bios(_T("0000-0FFF.ROM"), rom1, sizeof(rom1));
87         memory->read_bios(_T("2000-5FFF.ROM"), rom2, sizeof(rom2));
88         
89         memory->set_memory_r(0x0000, 0x0fff, rom1);
90         memory->set_memory_r(0x2000, 0x5fff, rom2);
91         memory->set_memory_rw(0xb000, 0xffff, ram);
92         
93         // cpu bus
94         cpu->set_context_mem(memory);
95         cpu->set_context_io(io);
96 #ifdef USE_DEBUGGER
97         cpu->set_context_debugger(new DEBUGGER(this, emu));
98 #endif
99         
100         // initialize all devices
101 #if defined(__GIT_REPO_VERSION)
102         strncpy(_git_revision, __GIT_REPO_VERSION, sizeof(_git_revision) - 1);
103 #endif
104         for(DEVICE* device = first_device; device; device = device->next_device) {
105                 device->initialize();
106         }
107         decl_state();
108 }
109
110 VM::~VM()
111 {
112         // delete all devices
113         for(DEVICE* device = first_device; device;) {
114                 DEVICE *next_device = device->next_device;
115                 device->release();
116                 delete device;
117                 device = next_device;
118         }
119 }
120
121 DEVICE* VM::get_device(int id)
122 {
123         for(DEVICE* device = first_device; device; device = device->next_device) {
124                 if(device->this_device_id == id) {
125                         return device;
126                 }
127         }
128         return NULL;
129 }
130
131 // ----------------------------------------------------------------------------
132 // drive virtual machine
133 // ----------------------------------------------------------------------------
134
135 void VM::reset()
136 {
137         // reset all devices
138         for(DEVICE* device = first_device; device; device = device->next_device) {
139                 device->reset();
140         }
141 }
142
143 void VM::run()
144 {
145         event->drive();
146 }
147
148 // ----------------------------------------------------------------------------
149 // debugger
150 // ----------------------------------------------------------------------------
151
152 #ifdef USE_DEBUGGER
153 DEVICE *VM::get_cpu(int index)
154 {
155         if(index == 0) {
156                 return cpu;
157         }
158         return NULL;
159 }
160 #endif
161
162 // ----------------------------------------------------------------------------
163 // draw screen
164 // ----------------------------------------------------------------------------
165
166 void VM::draw_screen()
167 {
168         for(int i = 0; i < 4; i++) {
169                 lcd[i]->draw(60 * i);
170         }
171 }
172
173 // ----------------------------------------------------------------------------
174 // soud manager
175 // ----------------------------------------------------------------------------
176
177 void VM::initialize_sound(int rate, int samples)
178 {
179         // init sound manager
180         event->initialize_sound(rate, samples);
181         
182         // init sound gen
183         pcm->initialize_sound(rate, 8000);
184 }
185
186 uint16_t* VM::create_sound(int* extra_frames)
187 {
188         return event->create_sound(extra_frames);
189 }
190
191 int VM::get_sound_buffer_ptr()
192 {
193         return event->get_sound_buffer_ptr();
194 }
195
196 #ifdef USE_SOUND_VOLUME
197 void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
198 {
199         if(ch == 0) {
200                 pcm->set_volume(0, decibel_l, decibel_r);
201         } else if(ch == 1) {
202                 drec->set_volume(0, decibel_l, decibel_r);
203         } else if(ch == 2) {
204                 drec->get_context_noise_play()->set_volume(0, decibel_l, decibel_r);
205                 drec->get_context_noise_stop()->set_volume(0, decibel_l, decibel_r);
206                 drec->get_context_noise_fast()->set_volume(0, decibel_l, decibel_r);
207         }
208 }
209 #endif
210
211 // ----------------------------------------------------------------------------
212 // user interface
213 // ----------------------------------------------------------------------------
214
215 void VM::play_tape(int drv, const _TCHAR* file_path)
216 {
217         drec->play_tape(file_path);
218 //      drec->set_remote(true);
219 }
220
221 void VM::rec_tape(int drv, const _TCHAR* file_path)
222 {
223         drec->rec_tape(file_path);
224 //      drec->set_remote(true);
225 }
226
227 void VM::close_tape(int drv)
228 {
229         emu->lock_vm();
230         drec->close_tape();
231         emu->unlock_vm();
232 //      drec->set_remote(false);
233 }
234
235 bool VM::is_tape_inserted(int drv)
236 {
237         return drec->is_tape_inserted();
238 }
239
240 bool VM::is_tape_playing(int drv)
241 {
242         return drec->is_tape_playing();
243 }
244
245 bool VM::is_tape_recording(int drv)
246 {
247         return drec->is_tape_recording();
248 }
249
250 int VM::get_tape_position(int drv)
251 {
252         return drec->get_tape_position();
253 }
254
255 const _TCHAR* VM::get_tape_message(int drv)
256 {
257         return drec->get_message();
258 }
259
260 void VM::push_play(int drv)
261 {
262         drec->set_ff_rew(0);
263         drec->set_remote(true);
264 }
265
266 void VM::push_stop(int drv)
267 {
268         drec->set_remote(false);
269 }
270
271 void VM::push_fast_forward(int drv)
272 {
273         drec->set_ff_rew(1);
274         drec->set_remote(true);
275 }
276
277 void VM::push_fast_rewind(int drv)
278 {
279         drec->set_ff_rew(-1);
280         drec->set_remote(true);
281 }
282
283 bool VM::is_frame_skippable()
284 {
285         return event->is_frame_skippable();
286 }
287
288 void VM::update_config()
289 {
290         for(DEVICE* device = first_device; device; device = device->next_device) {
291                 device->update_config();
292         }
293 }
294
295 #define STATE_VERSION   3
296
297 #include "../../statesub.h"
298 #include "../../qt/gui/csp_logger.h"
299 extern CSP_Logger DLL_PREFIX_I *csp_logger;
300
301 void VM::decl_state(void)
302 {
303         state_entry = new csp_state_utils(STATE_VERSION, 0, (_TCHAR *)(_T("CSP::PC_2001_HEAD")), csp_logger);
304         DECL_STATE_ENTRY_MULTI(void, ram, sizeof(ram));
305         for(DEVICE* device = first_device; device; device = device->next_device) {
306                 device->decl_state();
307         }
308 }
309
310 void VM::save_state(FILEIO* state_fio)
311 {
312         //state_fio->FputUint32(STATE_VERSION);
313         
314         if(state_entry != NULL) {
315                 state_entry->save_state(state_fio);
316         }
317         for(DEVICE* device = first_device; device; device = device->next_device) {
318                 device->save_state(state_fio);
319         }
320         //state_fio->Fwrite(ram, sizeof(ram), 1);
321 }
322
323 bool VM::load_state(FILEIO* state_fio)
324 {
325         //if(state_fio->FgetUint32() != STATE_VERSION) {
326         //      return false;
327         //}
328         bool mb = false;
329         if(state_entry != NULL) {
330                 mb = state_entry->load_state(state_fio);
331         }
332         if(!mb) {
333                 emu->out_debug_log("INFO: HEADER DATA ERROR");
334                 return false;
335         }
336         for(DEVICE* device = first_device; device; device = device->next_device) {
337                 if(!device->load_state(state_fio)) {
338                         return false;
339                 }
340         }
341         //state_fio->Fread(ram, sizeof(ram), 1);
342         return true;
343 }
344