OSDN Git Service

[VM][WIP] Use namespace to devices per VMs.
[csp-qt/common_source_project-fm7.git] / source / src / vm / gamegear / mastersystem.cpp
1 /*
2         SEGA MASTER SYSTEM Emulator 'yaMASTER SYSTEM'
3
4         Author : tanam
5         Date   : 2013.10.20-
6
7         [ virtual machine ]
8 */
9
10 #include "mastersystem.h"
11 #include "../../emu.h"
12 #include "../device.h"
13 #include "../event.h"
14
15 ///#include "../datarec.h"
16 ///#include "../disk.h"
17 ///#include "../i8251.h"
18 #include "../i8255.h"
19 #include "../io.h"
20 ///#include "../noise.h"
21 #include "../ym2413.h"
22 #include "../sn76489an.h"
23 #include "../315-5124.h"
24 ///#include "../upd765a.h"
25 #include "../z80.h"
26
27 #ifdef USE_DEBUGGER
28 #include "../debugger.h"
29 #endif
30
31 #include "keyboard.h"
32 #include "./memory.h"
33 #include "./system.h"
34
35 // ----------------------------------------------------------------------------
36 // initialize
37 // ----------------------------------------------------------------------------
38
39 using GAMEGEAR::KEYBOARD;
40 using GAMEGEAR::MEMORY;
41 using GAMEGEAR::SYSTEM;
42
43 VM::VM(EMU* parent_emu) : VM_TEMPLATE(parent_emu)
44 {
45         // create devices
46         first_device = last_device = NULL;
47         dummy = new DEVICE(this, emu);  // must be 1st device
48         event = new EVENT(this, emu);   // must be 2nd device
49         dummy->set_device_name(_T("1st Dummy"));
50 ///     drec = new DATAREC(this, emu);
51 ///     drec->set_context_noise_play(new NOISE(this, emu));
52 ///     drec->set_context_noise_stop(new NOISE(this, emu));
53 ///     drec->set_context_noise_fast(new NOISE(this, emu));
54 ///     sio = new I8251(this, emu);
55         pio_k = new I8255(this, emu);
56         pio_k->set_device_name(_T("8255 PIO (Keyboard)"));
57         pio_f = new I8255(this, emu);
58         pio_f->set_device_name(_T("8255 PIO (Floppy I/F)"));
59         io = new IO(this, emu);
60         psg = new SN76489AN(this, emu);
61         fm = new YM2413(this, emu);
62         vdp = new _315_5124(this, emu);
63 ///     fdc = new UPD765A(this, emu);
64 ///     fdc->set_context_noise_seek(new NOISE(this, emu));
65 ///     fdc->set_context_noise_head_down(new NOISE(this, emu));
66 //      fdc->set_context_noise_head_up(new NOISE(this, emu));
67         cpu = new Z80(this, emu);
68         
69         key = new KEYBOARD(this, emu);
70         memory = new MEMORY(this, emu);
71         system = new SYSTEM(this, emu);
72
73         // set contexts
74         event->set_context_cpu(cpu);
75         event->set_context_sound(psg);
76         event->set_context_sound(fm);
77 ///     event->set_context_sound(fdc->get_context_noise_seek());
78 ///     event->set_context_sound(fdc->get_context_noise_head_down());
79 ///     event->set_context_sound(fdc->get_context_noise_head_up());
80 ///     event->set_context_sound(drec->get_context_noise_play());
81 ///     event->set_context_sound(drec->get_context_noise_stop());
82 ///     event->set_context_sound(drec->get_context_noise_fast());
83         
84
85 ///     drec->set_context_ear(pio_k, SIG_I8255_PORT_B, 0x80);
86         pio_k->set_context_port_c(key, SIG_KEYBOARD_COLUMN, 0x07, 0);
87 ///     pio_k->set_context_port_c(drec, SIG_DATAREC_REMOTE, 0x08, 0);
88 ///     pio_k->set_context_port_c(drec, SIG_DATAREC_MIC, 0x10, 0);
89 ///     pio_f->set_context_port_c(fdc, SIG_UPD765A_MOTOR_NEG, 2, 0);
90 ///     pio_f->set_context_port_c(fdc, SIG_UPD765A_TC, 4, 0);
91 ///     pio_f->set_context_port_c(fdc, SIG_UPD765A_RESET, 8, 0);
92         pio_f->set_context_port_c(memory, SIG_MEMORY_SEL, 0x40, 0);
93         vdp->set_context_irq(cpu, SIG_CPU_IRQ, 1);
94 ///     fdc->set_context_irq(pio_f, SIG_I8255_PORT_A, 1);
95 ///     fdc->set_context_index(pio_f, SIG_I8255_PORT_A, 4);
96         
97         key->set_context_cpu(cpu);
98         key->set_context_pio(pio_k);
99         system->set_context_key(key);
100         vdp->set_context_key(key);
101         vdp->set_context_psg(psg);
102 ///     vdp->set_context_cpu(cpu);
103         
104         // cpu bus
105         cpu->set_context_mem(memory);
106         cpu->set_context_io(io);
107         cpu->set_context_intr(system);
108 #ifdef USE_DEBUGGER
109         cpu->set_context_debugger(new DEBUGGER(this, emu));
110 #endif
111         
112         // i/o bus
113         io->set_iomap_single_r(0x00, system);           // GG  START
114         io->set_iomap_single_w(0x80, system);           // COL TENKEY
115         io->set_iomap_single_w(0xc0, system);           // COL JOYPAD
116         io->set_iomap_range_rw(0xfc, 0xfe, system);     // COL JOYPAD
117         io->set_iomap_range_rw(0xff, 0xff, psg);        // COL PSG
118         io->set_iomap_range_rw(0x7e, 0x7f, vdp);        // SG  VDP
119         io->set_iomap_range_rw(0xbe, 0xbf, vdp);        // SG  VDP
120         io->set_iomap_range_rw(0xdc, 0xdf, pio_k);      // SG  KEY
121 ///     io->set_iomap_range_rw(0xe0, 0xe3, fdc);        // SG  FDD
122 ///     io->set_iomap_range_rw(0xe4, 0xe7, pio_f);      // SG  FDD
123 ///     io->set_iomap_range_rw(0xe8, 0xe9, sio);        // SG  SERIAL
124         io->set_iomap_range_rw(0xf0, 0xf2, fm);         // MS  FM
125         
126         // initialize all devices
127 #if defined(__GIT_REPO_VERSION)
128         strncpy(_git_revision, __GIT_REPO_VERSION, sizeof(_git_revision) - 1);
129 #endif
130         for(DEVICE* device = first_device; device; device = device->next_device) {
131                 device->initialize();
132         }
133         
134         // BIOS
135 ///     memory->bios();
136         memory->open_cart(create_local_path(_T("SMS.ROM")));
137 ///     for(int i = 0; i < 4; i++) {
138 ///             fdc->set_drive_type(i, DRIVE_TYPE_2D);
139 ///     }
140 }
141
142 VM::~VM()
143 {
144         // delete all devices
145         for(DEVICE* device = first_device; device;) {
146                 DEVICE *next_device = device->next_device;
147                 device->release();
148                 delete device;
149                 device = next_device;
150         }
151 }
152
153 DEVICE* VM::get_device(int id)
154 {
155         for(DEVICE* device = first_device; device; device = device->next_device) {
156                 if(device->this_device_id == id) {
157                         return device;
158                 }
159         }
160         return NULL;
161 }
162
163 // ----------------------------------------------------------------------------
164 // drive virtual machine
165 // ----------------------------------------------------------------------------
166
167 void VM::reset()
168 {
169         // reset all devices
170         for(DEVICE* device = first_device; device; device = device->next_device) {
171                 device->reset();
172         }
173 }
174
175 void VM::run()
176 {
177         event->drive();
178 }
179
180 // ----------------------------------------------------------------------------
181 // debugger
182 // ----------------------------------------------------------------------------
183
184 #ifdef USE_DEBUGGER
185 DEVICE *VM::get_cpu(int index)
186 {
187         if(index == 0) {
188                 return cpu;
189         }
190         return NULL;
191 }
192 #endif
193
194 // ----------------------------------------------------------------------------
195 // draw screen
196 // ----------------------------------------------------------------------------
197
198 void VM::draw_screen()
199 {
200         vdp->draw_screen();
201 }
202
203 // ----------------------------------------------------------------------------
204 // soud manager
205 // ----------------------------------------------------------------------------
206
207 void VM::initialize_sound(int rate, int samples)
208 {
209         // init sound manager
210         event->initialize_sound(rate, samples);
211         
212         // init sound gen
213         psg->initialize_sound(rate, 3579545, 4000);
214         fm->initialize_sound(rate, 3579545, samples);
215 }
216
217 uint16_t* VM::create_sound(int* extra_frames)
218 {
219         return event->create_sound(extra_frames);
220 }
221
222 int VM::get_sound_buffer_ptr()
223 {
224         return event->get_sound_buffer_ptr();
225 }
226
227 #ifdef USE_SOUND_VOLUME
228 void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
229 {
230         if(ch == 0) {
231                 psg->set_volume(0, decibel_l, decibel_r);
232         } else if(ch == 1) {
233                 fm->set_volume(0, decibel_l, decibel_r);
234 ///     } else if(ch == 2) {
235 ///             fdc->get_context_noise_seek()->set_volume(0, decibel_l, decibel_r);
236 ///             fdc->get_context_noise_head_down()->set_volume(0, decibel_l, decibel_r);
237 ///             fdc->get_context_noise_head_up()->set_volume(0, decibel_l, decibel_r);
238 ///     } else if(ch == 3) {
239 ///             drec->get_context_noise_play()->set_volume(0, decibel_l, decibel_r);
240 ///             drec->get_context_noise_stop()->set_volume(0, decibel_l, decibel_r);
241 ///             drec->get_context_noise_fast()->set_volume(0, decibel_l, decibel_r);
242         }
243 }
244 #endif
245
246 // ----------------------------------------------------------------------------
247 // user interface
248 // ----------------------------------------------------------------------------
249
250 void VM::open_cart(int drv, const _TCHAR* file_path)
251 {
252         if(drv == 0) {
253                 memory->open_cart(file_path);
254                 if (check_file_extension(file_path, _T(".col"))) {
255                         vdp->set_context_irq(cpu, SIG_CPU_NMI, 1);
256                         vdp->set_console(0x00);
257                         memory->bios();
258                 } else {
259                         vdp->set_context_irq(cpu, SIG_CPU_IRQ, 1);
260                         if (check_file_extension(file_path, _T(".gg"))) {
261                                 vdp->set_console(0x40);
262                         } else {
263                                 vdp->set_console(0x20);
264                         }
265                 }
266                 reset();
267         }
268 }
269
270 void VM::close_cart(int drv)
271 {
272         if(drv == 0) {
273                 memory->close_cart();
274                 reset();
275         }
276 }
277
278 bool VM::is_cart_inserted(int drv)
279 {
280         if(drv == 0) {
281                 return memory->is_cart_inserted();
282         } else {
283                 return false;
284         }
285 }
286
287 ///void VM::open_floppy_disk(int drv, const _TCHAR* file_path, int bank)
288 ///{
289 ///     fdc->open_disk(drv, file_path, bank);
290 ///}
291
292 ///void VM::close_floppy_disk(int drv)
293 ///{
294 ///     fdc->close_disk(drv);
295 ///}
296
297 ///bool VM::is_floppy_disk_inserted(int drv)
298 ///{
299 ///     return fdc->is_disk_inserted(drv);
300 ///}
301
302 ///void VM::is_floppy_disk_protected(int drv, bool value)
303 ///{
304 ///     fdc->is_disk_protected(drv, value);
305 ///}
306
307 ///bool VM::is_floppy_disk_protected(int drv)
308 ///{
309 ///     return fdc->is_disk_protected(drv);
310 ///}
311
312 ///uint32_t VM::is_floppy_disk_accessed()
313 ///{
314 ///     return fdc->read_signal(0);
315 ///}
316
317 ///void VM::play_tape(int drv, const _TCHAR* file_path)
318 ///{
319 ///     drec->play_tape(file_path);
320 ///     drec->set_remote(true);
321 ///}
322
323 ///void VM::rec_tape(int drv, const _TCHAR* file_path)
324 ///{
325 ///     drec->rec_tape(file_path);
326 ///     drec->set_remote(true);
327 ///}
328
329 ///void VM::close_tape(int drv)
330 ///{
331 ///     emu->lock_vm();
332 ///     drec->close_tape();
333 ///     emu->unlock_vm();
334 ///     drec->set_remote(false);
335 ///}
336
337 ///bool VM::is_tape_inserted(int drv)
338 ///{
339 ///     return drec->is_tape_inserted();
340 ///}
341
342 ///bool VM::is_tape_playing(int drv)
343 ///{
344 ///     return drec->is_tape_playing();
345 ///}
346
347 ///bool VM::is_tape_recording(int drv)
348 ///{
349 ///     return drec->is_tape_recording();
350 ///}
351
352 ///int VM::get_tape_position(int drv)
353 ///{
354 ///     return drec->get_tape_position();
355 ///}
356
357 ///const _TCHAR* VM::get_tape_message(int drv)
358 ///{
359 ///     return drec->get_message();
360 ///}
361
362 ///void VM::push_play(int drv)
363 ///{
364 ///     drec->set_ff_rew(0);
365 ///     drec->set_remote(true);
366 ///}
367
368 ///void VM::push_stop(int drv)
369 ///{
370 ///     drec->set_remote(false);
371 ///}
372
373 ///void VM::push_fast_forward(int drv)
374 ///{
375 ///     drec->set_ff_rew(1);
376 ///     drec->set_remote(true);
377 ///}
378
379 ///void VM::push_fast_rewind(int drv)
380 ///{
381 ///     drec->set_ff_rew(-1);
382 ///     drec->set_remote(true);
383 ///}
384
385 bool VM::is_frame_skippable()
386 {
387         return event->is_frame_skippable();
388 }
389
390 void VM::update_config()
391 {
392         for(DEVICE* device = first_device; device; device = device->next_device) {
393                 device->update_config();
394         }
395 }
396
397 #define STATE_VERSION   1
398
399 bool VM::process_state(FILEIO* state_fio, bool loading)
400 {
401         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
402                 return false;
403         }
404         for(DEVICE* device = first_device; device; device = device->next_device) {
405                 // Note: typeid(foo).name is fixed by recent ABI.Not dec 6.
406                 // const char *name = typeid(*device).name();
407                 //       But, using get_device_name() instead of typeid(foo).name() 20181008 K.O
408                 const char *name = device->get_device_name();
409                 int len = strlen(name);
410                 
411                 if(!state_fio->StateCheckInt32(len)) {
412                         if(loading) {
413                                 printf("Class name len Error: DEVID=%d EXPECT=%s\n", device->this_device_id, name);
414                         }
415                         return false;
416                 }
417                 if(!state_fio->StateCheckBuffer(name, len, 1)) {
418                         if(loading) {
419                                 printf("Class name Error: DEVID=%d EXPECT=%s\n", device->this_device_id, name);
420                         }
421                         return false;
422                 }
423                 if(!device->process_state(state_fio, loading)) {
424                         if(loading) {
425                                 printf("Data loading Error: DEVID=%d\n", device->this_device_id);
426                         }
427                         return false;
428                 }
429         }
430         // Machine specified.
431         return true;
432 }
433