OSDN Git Service

[General] Merge Upstream 2017-03-07.
[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 "../pcm1bit.h"
19 #include "../upd16434.h"
20 #include "../upd1990a.h"
21 #include "../upd7810.h"
22
23 #ifdef USE_DEBUGGER
24 #include "../debugger.h"
25 #endif
26
27 #include "io.h"
28
29 // ----------------------------------------------------------------------------
30 // initialize
31 // ----------------------------------------------------------------------------
32
33 VM::VM(EMU* parent_emu) : emu(parent_emu)
34 {
35         // create devices
36         first_device = last_device = NULL;
37         dummy = new DEVICE(this, emu);  // must be 1st device
38         event = new EVENT(this, emu);   // must be 2nd device
39 #if defined(_USE_QT)
40         dummy->set_device_name(_T("1st Dummy"));
41         event->set_device_name(_T("EVENT"));
42 #endif  
43         
44         drec = new DATAREC(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 #if defined(_USE_QT)
58         lcd[0]->set_device_name(_T("uPD16434 LCD CONTROLLER #1"));
59         lcd[1]->set_device_name(_T("uPD16434 LCD CONTROLLER #2"));
60         lcd[2]->set_device_name(_T("uPD16434 LCD CONTROLLER #3"));
61         lcd[3]->set_device_name(_T("uPD16434 LCD CONTROLLER #4"));
62         cpu->set_device_name(_T("CPU(uPD7810)"));
63 #endif  
64         
65         io = new IO(this, emu);
66 #if defined(_USE_QT)
67         io->set_device_name(_T("I/O BUS"));
68 #endif  
69         // set contexts
70         event->set_context_cpu(cpu);
71         event->set_context_sound(pcm);
72         event->set_context_sound(drec);
73 #if defined(USE_SOUND_FILES)
74         drec->load_sound_data(DATAREC_SNDFILE_RELAY_ON,  _T("CMTPLAY.WAV"));
75         drec->load_sound_data(DATAREC_SNDFILE_RELAY_OFF, _T("CMTSTOP.WAV"));
76         drec->load_sound_data(DATAREC_SNDFILE_EJECT,     _T("CMTEJECT.WAV"));
77 #endif
78         drec->set_context_ear(io, SIG_IO_DREC_IN, 1);
79         rtc->set_context_dout(io, SIG_IO_RTC_IN, 1);
80         cpu->set_context_to(pcm, SIG_PCM1BIT_SIGNAL, 1);
81         
82         io->set_context_lcd(0, lcd[0]);
83         io->set_context_lcd(1, lcd[1]);
84         io->set_context_lcd(2, lcd[2]);
85         io->set_context_lcd(3, lcd[3]);
86         io->set_context_drec(drec);
87         io->set_context_rtc(rtc);
88         io->set_context_cpu(cpu);
89         
90         // memory bus
91         memset(ram, 0xff, sizeof(ram));
92 //      memset(ram, 0, sizeof(ram));
93         memset(rom1, 0xff, sizeof(rom1));
94         memset(rom2, 0xff, sizeof(rom2));
95         
96         memory->read_bios(_T("0000-0FFF.ROM"), rom1, sizeof(rom1));
97         memory->read_bios(_T("2000-5FFF.ROM"), rom2, sizeof(rom2));
98         
99         memory->set_memory_r(0x0000, 0x0fff, rom1);
100         memory->set_memory_r(0x2000, 0x5fff, rom2);
101         memory->set_memory_rw(0xb000, 0xffff, ram);
102         
103         // cpu bus
104         cpu->set_context_mem(memory);
105         cpu->set_context_io(io);
106 #ifdef USE_DEBUGGER
107         cpu->set_context_debugger(new DEBUGGER(this, emu));
108 #endif
109         
110         // initialize all devices
111         for(DEVICE* device = first_device; device; device = device->next_device) {
112                 device->initialize();
113         }
114 }
115
116 VM::~VM()
117 {
118         // delete all devices
119         for(DEVICE* device = first_device; device;) {
120                 DEVICE *next_device = device->next_device;
121                 device->release();
122                 delete device;
123                 device = next_device;
124         }
125 }
126
127 DEVICE* VM::get_device(int id)
128 {
129         for(DEVICE* device = first_device; device; device = device->next_device) {
130                 if(device->this_device_id == id) {
131                         return device;
132                 }
133         }
134         return NULL;
135 }
136
137 // ----------------------------------------------------------------------------
138 // drive virtual machine
139 // ----------------------------------------------------------------------------
140
141 void VM::reset()
142 {
143         // reset all devices
144         for(DEVICE* device = first_device; device; device = device->next_device) {
145                 device->reset();
146         }
147 }
148
149 void VM::run()
150 {
151         event->drive();
152 }
153
154 // ----------------------------------------------------------------------------
155 // debugger
156 // ----------------------------------------------------------------------------
157
158 #ifdef USE_DEBUGGER
159 DEVICE *VM::get_cpu(int index)
160 {
161         if(index == 0) {
162                 return cpu;
163         }
164         return NULL;
165 }
166 #endif
167
168 // ----------------------------------------------------------------------------
169 // draw screen
170 // ----------------------------------------------------------------------------
171
172 void VM::draw_screen()
173 {
174         for(int i = 0; i < 4; i++) {
175                 lcd[i]->draw(60 * i);
176         }
177 }
178
179 // ----------------------------------------------------------------------------
180 // soud manager
181 // ----------------------------------------------------------------------------
182
183 void VM::initialize_sound(int rate, int samples)
184 {
185         // init sound manager
186         event->initialize_sound(rate, samples);
187         
188         // init sound gen
189         pcm->initialize_sound(rate, 8000);
190 }
191
192 uint16_t* VM::create_sound(int* extra_frames)
193 {
194         return event->create_sound(extra_frames);
195 }
196
197 int VM::get_sound_buffer_ptr()
198 {
199         return event->get_sound_buffer_ptr();
200 }
201
202 #ifdef USE_SOUND_VOLUME
203 void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
204 {
205         if(ch == 0) {
206                 pcm->set_volume(0, decibel_l, decibel_r);
207         } else if(ch == 1) {
208                 drec->set_volume(0, decibel_l, decibel_r);
209         }
210 #if defined(USE_SOUND_FILES)
211          else if(ch == 2) {
212                  for(int i = 0; i < DATAREC_SNDFILE_END; i++) {
213                          drec->set_volume(i + 2, decibel_l, decibel_r);
214                  }
215          }
216 #endif
217 }
218 #endif
219
220 // ----------------------------------------------------------------------------
221 // user interface
222 // ----------------------------------------------------------------------------
223
224 void VM::play_tape(const _TCHAR* file_path)
225 {
226         drec->play_tape(file_path);
227         drec->write_signal(SIG_DATAREC_REMOTE, 1, 1);
228 }
229
230 void VM::rec_tape(const _TCHAR* file_path)
231 {
232         drec->rec_tape(file_path);
233         drec->write_signal(SIG_DATAREC_REMOTE, 1, 1);
234 }
235
236 void VM::close_tape()
237 {
238 #if defined(USE_SOUND_FILES)
239         drec->write_signal(SIG_SOUNDER_ADD + DATAREC_SNDFILE_EJECT, 1, 1);
240 #endif
241         emu->lock_vm();
242         drec->close_tape();
243         emu->unlock_vm();
244         drec->write_signal(SIG_DATAREC_REMOTE, 0, 0);
245 }
246
247 bool VM::is_tape_inserted()
248 {
249         return drec->is_tape_inserted();
250 }
251
252 bool VM::is_tape_playing()
253 {
254         return drec->is_tape_playing();
255 }
256
257 bool VM::is_tape_recording()
258 {
259         return drec->is_tape_recording();
260 }
261
262 int VM::get_tape_position()
263 {
264         return drec->get_tape_position();
265 }
266
267 bool VM::is_frame_skippable()
268 {
269         return event->is_frame_skippable();
270 }
271
272 void VM::update_config()
273 {
274         for(DEVICE* device = first_device; device; device = device->next_device) {
275                 device->update_config();
276         }
277 }
278
279 #define STATE_VERSION   1
280
281 void VM::save_state(FILEIO* state_fio)
282 {
283         state_fio->FputUint32(STATE_VERSION);
284         
285         for(DEVICE* device = first_device; device; device = device->next_device) {
286                 device->save_state(state_fio);
287         }
288         state_fio->Fwrite(ram, sizeof(ram), 1);
289 }
290
291 bool VM::load_state(FILEIO* state_fio)
292 {
293         if(state_fio->FgetUint32() != STATE_VERSION) {
294                 return false;
295         }
296         for(DEVICE* device = first_device; device; device = device->next_device) {
297                 if(!device->load_state(state_fio)) {
298                         return false;
299                 }
300         }
301         state_fio->Fread(ram, sizeof(ram), 1);
302         return true;
303 }
304