OSDN Git Service

[VM][Qt][UI][EMU][WIP] Use EMU_TEMPLATE:: instead of EMU:: . Some VMs are not apply...
[csp-qt/common_source_project-fm7.git] / source / src / vm / pcengine / pcengine.cpp
1 /*
2         NEC-HE PC Engine Emulator 'ePCEngine'
3
4         Author : Takeda.Toshiya
5         Date   : 2012.10.31-
6
7         [ virtual machine ]
8 */
9
10 #include "pcengine.h"
11 #include "../../emu.h"
12 #include "../device.h"
13 #include "../event.h"
14
15 #include "../huc6280.h"
16 #include "../msm5205.h"
17 #include "../scsi_cdrom.h"
18 #include "../scsi_host.h"
19
20 #ifdef USE_DEBUGGER
21 #include "../debugger.h"
22 #endif
23
24 #include "pce.h"
25 #include "./adpcm.h"
26
27 using PCEDEV::ADPCM;
28 using PCEDEV::PCE;
29 // ----------------------------------------------------------------------------
30 // initialize
31 // ----------------------------------------------------------------------------
32
33 VM::VM(EMU_TEMPLATE* parent_emu) : VM_TEMPLATE(parent_emu)
34 {
35         // create devices
36         first_device = last_device = NULL;
37         dummy = new DEVICE(this, emu);  // must be 1st device
38         
39         pceevent = new EVENT(this, emu);
40 //      pceevent->set_frames_per_sec(FRAMES_PER_SEC);
41 //      pceevent->set_lines_per_frame(LINES_PER_FRAME);
42         dummy->set_device_name(_T("1st Dummy"));
43         pceevent->set_device_name(_T("PC-ENGINE EVENT"));
44         
45         pcecpu = new HUC6280(this, emu);
46         pcecpu->set_device_name(_T("PC-ENGINE CPU(HuC6280)"));
47 //      pcecpu->set_context_event_manager(pceevent);
48         adpcm = new MSM5205(this, emu);
49 //      adpcm->set_context_event_manager(pceevent);
50         scsi_host = new SCSI_HOST(this, emu);
51 //      scsi_host->set_context_event_manager(pceevent);
52         scsi_cdrom = new SCSI_CDROM(this, emu);
53 //      scsi_cdrom->set_context_event_manager(pceevent);
54         
55         pce = new PCE(this, emu);
56         pce_adpcm = new ADPCM(this, emu);
57 //      pce->set_context_event_manager(pceevent);
58 #if defined(_USE_QT)
59         pce->set_device_name(_T("PC-ENGINE MAIN"));
60 #endif  
61         
62         pceevent->set_context_cpu(pcecpu, CPU_CLOCKS);
63         pceevent->set_context_sound(pce);
64         pceevent->set_context_sound(pce_adpcm);
65         // NOTE: SCSI_CDROM::mix() will be called in pce::mix()
66 //      pceevent->set_context_sound(scsi_cdrom);
67         
68         pcecpu->set_context_mem(pce);
69         pcecpu->set_context_io(pce);
70 #ifdef USE_DEBUGGER
71         pcecpu->set_context_debugger(new DEBUGGER(this, emu));
72 #endif
73         scsi_cdrom->scsi_id = 0;
74         scsi_cdrom->set_context_interface(scsi_host);
75         scsi_host->set_context_target(scsi_cdrom);
76         
77         scsi_host->set_context_irq(pce, SIG_PCE_SCSI_IRQ, 1);
78         scsi_host->set_context_drq(pce, SIG_PCE_SCSI_DRQ, 1);
79         scsi_host->set_context_bsy(pce, SIG_PCE_SCSI_BSY, 1);
80         scsi_cdrom->set_context_done(pce, SIG_PCE_CDDA_DONE, 1);
81         adpcm->set_context_vclk(pce, SIG_PCE_ADPCM_VCLK, 1);
82         
83         pce->set_context_cpu(pcecpu);
84         pce->set_context_msm(adpcm);
85         pce->set_context_scsi_host(scsi_host);
86         pce->set_context_scsi_cdrom(scsi_cdrom);
87         
88         pce->set_context_adpcm(pce_adpcm);
89         pce_adpcm->set_context_msm(adpcm);
90         pce_adpcm->set_context_pce(pce);
91         // initialize all devices
92 #if defined(__GIT_REPO_VERSION)
93         strncpy(_git_revision, __GIT_REPO_VERSION, sizeof(_git_revision) - 1);
94 #endif
95         for(DEVICE* device = first_device; device; device = device->next_device) {
96                 device->initialize();
97         }
98 }
99
100 VM::~VM()
101 {
102         // delete all devices
103         for(DEVICE* device = first_device; device;) {
104                 DEVICE *next_device = device->next_device;
105                 device->release();
106                 delete device;
107                 device = next_device;
108         }
109 }
110
111 DEVICE* VM::get_device(int id)
112 {
113         for(DEVICE* device = first_device; device; device = device->next_device) {
114                 if(device->this_device_id == id) {
115                         return device;
116                 }
117         }
118         return NULL;
119 }
120
121 // ----------------------------------------------------------------------------
122 // drive virtual machine
123 // ----------------------------------------------------------------------------
124
125 void VM::reset()
126 {
127         // reset all devices
128         for(DEVICE* device = first_device; device; device = device->next_device) {
129                 device->reset();
130         }
131 }
132
133 void VM::run()
134 {
135         pceevent->drive();
136 }
137
138 double VM::get_frame_rate()
139 {
140         return pceevent->get_frame_rate();
141 }
142
143 // ----------------------------------------------------------------------------
144 // debugger
145 // ----------------------------------------------------------------------------
146
147 #ifdef USE_DEBUGGER
148 DEVICE *VM::get_cpu(int index)
149 {
150         if(index == 0) {
151                 return pcecpu;
152         }
153         return NULL;
154 }
155 #endif
156
157 // ----------------------------------------------------------------------------
158 // draw screen
159 // ----------------------------------------------------------------------------
160
161 void VM::draw_screen()
162 {
163         pce->draw_screen();
164 }
165
166 // ----------------------------------------------------------------------------
167 // soud manager
168 // ----------------------------------------------------------------------------
169
170 void VM::initialize_sound(int rate, int samples)
171 {
172         // init sound manager
173         pceevent->initialize_sound(rate, samples);
174         
175         // init sound gen
176         pce->initialize_sound(rate);
177         adpcm->initialize_sound(ADPCM_CLOCK / 6, MSM5205_S48_4B);
178 }
179
180 uint16_t* VM::create_sound(int* extra_frames)
181 {
182         return pceevent->create_sound(extra_frames);
183 }
184
185 int VM::get_sound_buffer_ptr()
186 {
187         return pceevent->get_sound_buffer_ptr();
188 }
189
190 #ifdef USE_SOUND_VOLUME
191 void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
192 {
193         if(ch == 0) {
194                 pce->set_volume(0, decibel_l, decibel_r);
195         } else if(ch == 1) {
196                 scsi_cdrom->set_volume(0, decibel_l, decibel_r);
197         } else if(ch == 2) {
198                 adpcm->set_volume(0, decibel_l, decibel_r);
199         }
200 }
201 #endif
202
203 // ----------------------------------------------------------------------------
204 // user interface
205 // ----------------------------------------------------------------------------
206
207 void VM::open_cart(int drv, const _TCHAR* file_path)
208 {
209         pce->open_cart(file_path);
210         pce->reset();
211         pcecpu->reset();
212 }
213
214 void VM::close_cart(int drv)
215 {
216         pce->close_cart();
217         pce->reset();
218         pcecpu->reset();
219 }
220
221 bool VM::is_cart_inserted(int drv)
222 {
223         return pce->is_cart_inserted();
224 }
225
226 void VM::open_compact_disc(int drv, const _TCHAR* file_path)
227 {
228         scsi_cdrom->open(file_path);
229 }
230
231 void VM::close_compact_disc(int drv)
232 {
233         scsi_cdrom->close();
234 }
235
236 bool VM::is_compact_disc_inserted(int drv)
237 {
238         return scsi_cdrom->mounted();
239 }
240
241 uint32_t VM::is_compact_disc_accessed()
242 {
243         uint32_t n;
244         n = (scsi_cdrom->accessed()) ? 1 : 0;
245         return n;
246 }
247
248 void VM::update_config()
249 {
250         for(DEVICE* device = first_device; device; device = device->next_device) {
251                 device->update_config();
252         }
253 }
254
255 double VM::get_current_usec()
256 {
257         if(event == NULL) return 0.0;
258         return event->get_current_usec();
259 }
260
261 uint64_t VM::get_current_clock_uint64()
262 {
263                 if(event == NULL) return (uint64_t)0;
264                 return event->get_current_clock_uint64();
265 }
266
267 #define STATE_VERSION   2
268
269 bool VM::process_state(FILEIO* state_fio, bool loading)
270 {
271         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
272                 return false;
273         }
274         for(DEVICE* device = first_device; device; device = device->next_device) {
275                 // Note: typeid(foo).name is fixed by recent ABI.Not dec 6.
276                 // const char *name = typeid(*device).name();
277                 //       But, using get_device_name() instead of typeid(foo).name() 20181008 K.O
278                 const char *name = device->get_device_name();
279                 int len = strlen(name);
280                 
281                 if(!state_fio->StateCheckInt32(len)) {
282                         if(loading) {
283                                 printf("Class name len Error: DEVID=%d EXPECT=%s\n", device->this_device_id, name);
284                         }
285                         return false;
286                 }
287                 if(!state_fio->StateCheckBuffer(name, len, 1)) {
288                         if(loading) {
289                                 printf("Class name Error: DEVID=%d EXPECT=%s\n", device->this_device_id, name);
290                         }
291                         return false;
292                 }
293                 if(!device->process_state(state_fio, loading)) {
294                         if(loading) {
295                                 printf("Data loading Error: DEVID=%d\n", device->this_device_id);
296                         }
297                         return false;
298                 }
299         }
300         return true;
301 }