OSDN Git Service

63e539897753c1ea5f224c43a762521a645fc4f9
[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
26 // ----------------------------------------------------------------------------
27 // initialize
28 // ----------------------------------------------------------------------------
29
30 VM::VM(EMU* parent_emu) : VM_TEMPLATE(parent_emu)
31 {
32         // create devices
33         first_device = last_device = NULL;
34         dummy = new DEVICE(this, emu);  // must be 1st device
35         
36         pceevent = new EVENT(this, emu);
37 //      pceevent->set_frames_per_sec(FRAMES_PER_SEC);
38 //      pceevent->set_lines_per_frame(LINES_PER_FRAME);
39         dummy->set_device_name(_T("1st Dummy"));
40         pceevent->set_device_name(_T("PC-ENGINE EVENT"));
41         
42         pcecpu = new HUC6280(this, emu);
43         pcecpu->set_device_name(_T("PC-ENGINE CPU(HuC6280)"));
44 //      pcecpu->set_context_event_manager(pceevent);
45         adpcm = new MSM5205(this, emu);
46 //      adpcm->set_context_event_manager(pceevent);
47         scsi_host = new SCSI_HOST(this, emu);
48 //      scsi_host->set_context_event_manager(pceevent);
49         scsi_cdrom = new SCSI_CDROM(this, emu);
50 //      scsi_cdrom->set_context_event_manager(pceevent);
51         
52         pce = new PCE(this, emu);
53 //      pce->set_context_event_manager(pceevent);
54 #if defined(_USE_QT)
55         pce->set_device_name(_T("PC-ENGINE MAIN"));
56 #endif  
57         
58         pceevent->set_context_cpu(pcecpu, CPU_CLOCKS);
59         pceevent->set_context_sound(pce);
60         // NOTE: adpcm::mix() and scsi_cdrom::mix() will be called in pce::mix()
61 //      pceevent->set_context_sound(adpcm);
62 //      pceevent->set_context_sound(scsi_cdrom);
63         
64         pcecpu->set_context_mem(pce);
65         pcecpu->set_context_io(pce);
66 #ifdef USE_DEBUGGER
67         pcecpu->set_context_debugger(new DEBUGGER(this, emu));
68 #endif
69         scsi_cdrom->scsi_id = 0;
70         scsi_cdrom->set_context_interface(scsi_host);
71         scsi_host->set_context_target(scsi_cdrom);
72         
73         scsi_host->set_context_irq(pce, SIG_PCE_SCSI_IRQ, 1);
74         scsi_host->set_context_drq(pce, SIG_PCE_SCSI_DRQ, 1);
75         scsi_host->set_context_bsy(pce, SIG_PCE_SCSI_BSY, 1);
76         scsi_cdrom->set_context_done(pce, SIG_PCE_CDDA_DONE, 1);
77         adpcm->set_context_vclk(pce, SIG_PCE_ADPCM_VCLK, 1);
78         
79         pce->set_context_cpu(pcecpu);
80         pce->set_context_adpcm(adpcm);
81         pce->set_context_scsi_host(scsi_host);
82         pce->set_context_scsi_cdrom(scsi_cdrom);
83         
84         // initialize all devices
85         for(DEVICE* device = first_device; device; device = device->next_device) {
86                 device->initialize();
87         }
88         decl_state();
89 }
90
91 VM::~VM()
92 {
93         // delete all devices
94         for(DEVICE* device = first_device; device;) {
95                 DEVICE *next_device = device->next_device;
96                 device->release();
97                 delete device;
98                 device = next_device;
99         }
100 }
101
102 DEVICE* VM::get_device(int id)
103 {
104         for(DEVICE* device = first_device; device; device = device->next_device) {
105                 if(device->this_device_id == id) {
106                         return device;
107                 }
108         }
109         return NULL;
110 }
111
112 // ----------------------------------------------------------------------------
113 // drive virtual machine
114 // ----------------------------------------------------------------------------
115
116 void VM::reset()
117 {
118         // reset all devices
119         for(DEVICE* device = first_device; device; device = device->next_device) {
120                 device->reset();
121         }
122 }
123
124 void VM::run()
125 {
126         pceevent->drive();
127 }
128
129 double VM::get_frame_rate()
130 {
131         return pceevent->get_frame_rate();
132 }
133
134 // ----------------------------------------------------------------------------
135 // debugger
136 // ----------------------------------------------------------------------------
137
138 #ifdef USE_DEBUGGER
139 DEVICE *VM::get_cpu(int index)
140 {
141         if(index == 0) {
142                 return pcecpu;
143         }
144         return NULL;
145 }
146 #endif
147
148 // ----------------------------------------------------------------------------
149 // draw screen
150 // ----------------------------------------------------------------------------
151
152 void VM::draw_screen()
153 {
154         pce->draw_screen();
155 }
156
157 // ----------------------------------------------------------------------------
158 // soud manager
159 // ----------------------------------------------------------------------------
160
161 void VM::initialize_sound(int rate, int samples)
162 {
163         // init sound manager
164         pceevent->initialize_sound(rate, samples);
165         
166         // init sound gen
167         pce->initialize_sound(rate);
168         adpcm->initialize_sound(ADPCM_CLOCK / 6, MSM5205_S48_4B);
169 }
170
171 uint16_t* VM::create_sound(int* extra_frames)
172 {
173         return pceevent->create_sound(extra_frames);
174 }
175
176 int VM::get_sound_buffer_ptr()
177 {
178         return pceevent->get_sound_buffer_ptr();
179 }
180
181 #ifdef USE_SOUND_VOLUME
182 void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
183 {
184         if(ch == 0) {
185                 pce->set_volume(0, decibel_l, decibel_r);
186         } else if(ch == 1) {
187                 scsi_cdrom->set_volume(0, decibel_l, decibel_r);
188         } else if(ch == 2) {
189                 adpcm->set_volume(0, decibel_l, decibel_r);
190         }
191 }
192 #endif
193
194 // ----------------------------------------------------------------------------
195 // user interface
196 // ----------------------------------------------------------------------------
197
198 void VM::open_cart(int drv, const _TCHAR* file_path)
199 {
200         pce->open_cart(file_path);
201         pce->reset();
202         pcecpu->reset();
203 }
204
205 void VM::close_cart(int drv)
206 {
207         pce->close_cart();
208         pce->reset();
209         pcecpu->reset();
210 }
211
212 bool VM::is_cart_inserted(int drv)
213 {
214         return pce->is_cart_inserted();
215 }
216
217 void VM::open_compact_disc(int drv, const _TCHAR* file_path)
218 {
219         scsi_cdrom->open(file_path);
220 }
221
222 void VM::close_compact_disc(int drv)
223 {
224         scsi_cdrom->close();
225 }
226
227 bool VM::is_compact_disc_inserted(int drv)
228 {
229         return scsi_cdrom->mounted();
230 }
231
232 uint32_t VM::is_compact_disc_accessed()
233 {
234         return scsi_cdrom->accessed();
235 }
236
237 void VM::update_config()
238 {
239         for(DEVICE* device = first_device; device; device = device->next_device) {
240                 device->update_config();
241         }
242 }
243
244 #define STATE_VERSION   2
245
246 #include "../../statesub.h"
247 #include "../../qt/gui/csp_logger.h"
248 extern CSP_Logger DLL_PREFIX_I *csp_logger;
249
250 void VM::decl_state(void)
251 {
252         state_entry = new csp_state_utils(STATE_VERSION, 0, (_TCHAR *)(_T("CSP::PC_ENGINE_HEAD")), csp_logger);
253         for(DEVICE* device = first_device; device; device = device->next_device) {
254                 device->decl_state();
255         }
256 }
257
258 void VM::save_state(FILEIO* state_fio)
259 {
260         //state_fio->FputUint32(STATE_VERSION);
261         
262         if(state_entry != NULL) {
263                 state_entry->save_state(state_fio);
264         }
265         for(DEVICE* device = first_device; device; device = device->next_device) {
266                 device->save_state(state_fio);
267         }
268 }
269
270 bool VM::load_state(FILEIO* state_fio)
271 {
272         //if(state_fio->FgetUint32() != STATE_VERSION) {
273         //      return false;
274         //}
275         bool mb = false;
276         if(state_entry != NULL) {
277                 mb = state_entry->load_state(state_fio);
278         }
279         if(!mb) {
280                 emu->out_debug_log("INFO: HEADER DATA ERROR");
281                 return false;
282         }
283         for(DEVICE* device = first_device; device; device = device->next_device) {
284                 if(!device->load_state(state_fio)) {
285                         return false;
286                 }
287         }
288         return true;
289 }
290