OSDN Git Service

a2c5b5575372f0790b4f65bdf207979ee5762014
[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 PC2001_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 }
108
109 VM::~VM()
110 {
111         // delete all devices
112         for(DEVICE* device = first_device; device;) {
113                 DEVICE *next_device = device->next_device;
114                 device->release();
115                 delete device;
116                 device = next_device;
117         }
118 }
119
120 DEVICE* VM::get_device(int id)
121 {
122         for(DEVICE* device = first_device; device; device = device->next_device) {
123                 if(device->this_device_id == id) {
124                         return device;
125                 }
126         }
127         return NULL;
128 }
129
130 // ----------------------------------------------------------------------------
131 // drive virtual machine
132 // ----------------------------------------------------------------------------
133
134 void VM::reset()
135 {
136         // reset all devices
137         for(DEVICE* device = first_device; device; device = device->next_device) {
138                 device->reset();
139         }
140 }
141
142 void VM::run()
143 {
144         event->drive();
145 }
146
147 // ----------------------------------------------------------------------------
148 // debugger
149 // ----------------------------------------------------------------------------
150
151 #ifdef USE_DEBUGGER
152 DEVICE *VM::get_cpu(int index)
153 {
154         if(index == 0) {
155                 return cpu;
156         }
157         return NULL;
158 }
159 #endif
160
161 // ----------------------------------------------------------------------------
162 // draw screen
163 // ----------------------------------------------------------------------------
164
165 void VM::draw_screen()
166 {
167         for(int i = 0; i < 4; i++) {
168                 lcd[i]->draw(60 * i);
169         }
170 }
171
172 // ----------------------------------------------------------------------------
173 // soud manager
174 // ----------------------------------------------------------------------------
175
176 void VM::initialize_sound(int rate, int samples)
177 {
178         // init sound manager
179         event->initialize_sound(rate, samples);
180         
181         // init sound gen
182         pcm->initialize_sound(rate, 8000);
183 }
184
185 uint16_t* VM::create_sound(int* extra_frames)
186 {
187         return event->create_sound(extra_frames);
188 }
189
190 int VM::get_sound_buffer_ptr()
191 {
192         return event->get_sound_buffer_ptr();
193 }
194
195 #ifdef USE_SOUND_VOLUME
196 void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
197 {
198         if(ch == 0) {
199                 pcm->set_volume(0, decibel_l, decibel_r);
200         } else if(ch == 1) {
201                 drec->set_volume(0, decibel_l, decibel_r);
202         } else if(ch == 2) {
203                 drec->get_context_noise_play()->set_volume(0, decibel_l, decibel_r);
204                 drec->get_context_noise_stop()->set_volume(0, decibel_l, decibel_r);
205                 drec->get_context_noise_fast()->set_volume(0, decibel_l, decibel_r);
206         }
207 }
208 #endif
209
210 // ----------------------------------------------------------------------------
211 // user interface
212 // ----------------------------------------------------------------------------
213
214 void VM::play_tape(int drv, const _TCHAR* file_path)
215 {
216         drec->play_tape(file_path);
217 //      drec->set_remote(true);
218 }
219
220 void VM::rec_tape(int drv, const _TCHAR* file_path)
221 {
222         drec->rec_tape(file_path);
223 //      drec->set_remote(true);
224 }
225
226 void VM::close_tape(int drv)
227 {
228         emu->lock_vm();
229         drec->close_tape();
230         emu->unlock_vm();
231 //      drec->set_remote(false);
232 }
233
234 bool VM::is_tape_inserted(int drv)
235 {
236         return drec->is_tape_inserted();
237 }
238
239 bool VM::is_tape_playing(int drv)
240 {
241         return drec->is_tape_playing();
242 }
243
244 bool VM::is_tape_recording(int drv)
245 {
246         return drec->is_tape_recording();
247 }
248
249 int VM::get_tape_position(int drv)
250 {
251         return drec->get_tape_position();
252 }
253
254 const _TCHAR* VM::get_tape_message(int drv)
255 {
256         return drec->get_message();
257 }
258
259 void VM::push_play(int drv)
260 {
261         drec->set_ff_rew(0);
262         drec->set_remote(true);
263 }
264
265 void VM::push_stop(int drv)
266 {
267         drec->set_remote(false);
268 }
269
270 void VM::push_fast_forward(int drv)
271 {
272         drec->set_ff_rew(1);
273         drec->set_remote(true);
274 }
275
276 void VM::push_fast_rewind(int drv)
277 {
278         drec->set_ff_rew(-1);
279         drec->set_remote(true);
280 }
281
282 bool VM::is_frame_skippable()
283 {
284         return event->is_frame_skippable();
285 }
286
287 void VM::update_config()
288 {
289         for(DEVICE* device = first_device; device; device = device->next_device) {
290                 device->update_config();
291         }
292 }
293
294 #define STATE_VERSION   3
295
296 bool VM::process_state(FILEIO* state_fio, bool loading)
297 {
298         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
299                 return false;
300         }
301         for(DEVICE* device = first_device; device; device = device->next_device) {
302                 const char *name = typeid(*device).name() + 6; // skip "class "
303                 int len = strlen(name);
304                 
305                 if(!state_fio->StateCheckInt32(len)) {
306                         return false;
307                 }
308                 if(!state_fio->StateCheckBuffer(name, len, 1)) {
309                         return false;
310                 }
311                 if(!device->process_state(state_fio, loading)) {
312                         return false;
313                 }
314         }
315         state_fio->StateBuffer(ram, sizeof(ram), 1);
316         return true;
317 }