OSDN Git Service

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