1 #include <stdarg.h>
2
3 #include <libretro.h>
4
5 #include "mednafen/mempatcher.h"
6 #include "mednafen/git.h"
7 #include "mednafen/state_helpers.h"
8 #include "mednafen/masmem.h"
9 #include "mednafen/settings.h"
10
11 /* Forward declarations */
12 void MDFN_LoadGameCheats(void *override);
13 void MDFN_FlushGameCheats(int nosave);
14
15 struct retro_perf_callback perf_cb;
16 retro_get_cpu_features_t perf_get_cpu_features_cb = NULL;
17 retro_log_printf_t log_cb;
18 static retro_video_refresh_t video_cb;
19 static retro_audio_sample_t audio_cb;
20 static retro_audio_sample_batch_t audio_batch_cb;
21 static retro_environment_t environ_cb;
22 static retro_input_poll_t input_poll_cb;
23 static retro_input_state_t input_state_cb;
24
25 static bool libretro_supports_bitmasks = false;
26
27 static bool overscan;
28 static double last_sound_rate;
29 static struct MDFN_PixelFormat last_pixel_format;
30
31 static struct MDFN_Surface surf;
32
33 /* Mednafen - Multi-system Emulator
34 *
35 * This program is free software; you can redistribute it and/or modify
36 * it under the terms of the GNU General Public License as published by
37 * the Free Software Foundation; either version 2 of the License, or
38 * (at your option) any later version.
39 *
40 * This program is distributed in the hope that it will be useful,
41 * but WITHOUT ANY WARRANTY; without even the implied warranty of
42 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
43 * GNU General Public License for more details.
44 *
45 * You should have received a copy of the GNU General Public License
46 * along with this program; if not, write to the Free Software
47 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
48 */
49
50 #include "mednafen/vb/vb.h"
51 #include "mednafen/vb/timer.h"
52 #include "mednafen/vb/vsu.h"
53 #include "mednafen/vb/vip.h"
54 #ifdef WANT_DEBUGGER
55 #include "mednafen/vb/debug.h"
56 #endif
57 #include "mednafen/vb/input.h"
58 #include "mednafen/mempatcher.h"
59 #include "mednafen/hw_cpu/v810/v810_cpu.h"
60
61 #include "libretro_core_options.h"
62
63 enum
64 {
65 ANAGLYPH_PRESET_DISABLED = 0,
66 ANAGLYPH_PRESET_RED_BLUE,
67 ANAGLYPH_PRESET_RED_CYAN,
68 ANAGLYPH_PRESET_RED_ELECTRICCYAN,
69 ANAGLYPH_PRESET_RED_GREEN,
70 ANAGLYPH_PRESET_GREEN_MAGENTA,
71 ANAGLYPH_PRESET_YELLOW_BLUE,
72 };
73
74 static const uint32 AnaglyphPreset_Colors[][2] =
75 {
76 { 0, 0 },
77 { 0xFF0000, 0x0000FF },
78 { 0xFF0000, 0x00B7EB },
79 { 0xFF0000, 0x00FFFF },
80 { 0xFF0000, 0x00FF00 },
81 { 0x00FF00, 0xFF00FF },
82 { 0xFFFF00, 0x0000FF },
83 };
84
85 #define STICK_DEADZONE 0x4000
86 #define RIGHT_DPAD_LEFT 0x1000
87 #define RIGHT_DPAD_RIGHT 0x0020
88 #define RIGHT_DPAD_UP 0x0010
89 #define RIGHT_DPAD_DOWN 0x2000
90
91 static uint32 VB3DMode;
92
93 static Blip_Buffer sbuf[2];
94
95 static uint8 *WRAM = NULL;
96
97 static uint8 *GPRAM = NULL;
98 static uint32 GPRAM_Mask;
99
100 static uint8 *GPROM = NULL;
101 static uint32 GPROM_Mask;
102
103 V810 *VB_V810 = NULL;
104
105 VSU *VB_VSU = NULL;
106 static uint32 VSU_CycleFix;
107
108 static uint8 WCR;
109
110 static int32 next_vip_ts, next_timer_ts, next_input_ts;
111
112 static uint32 IRQ_Asserted;
113
114 MDFNGI EmulatedVB =
115 {
116 MDFN_MASTERCLOCK_FIXED(VB_MASTER_CLOCK),
117 0,
118
119 0, // lcm_width
120 0, // lcm_height
121
122 384, // Nominal width
123 224, // Nominal height
124
125 384, // Framebuffer width
126 256, // Framebuffer height
127
128 2, // Number of output sound channels
129 };
130
131 MDFNGI *MDFNGameInfo = &EmulatedVB;
132
RecalcIntLevel(void)133 static INLINE void RecalcIntLevel(void)
134 {
135 int ilevel = -1;
136
137 for(int i = 4; i >= 0; i--)
138 {
139 if(IRQ_Asserted & (1 << i))
140 {
141 ilevel = i;
142 break;
143 }
144 }
145
146 VB_V810->SetInt(ilevel);
147 }
148
VBIRQ_Assert(int source,bool assert)149 extern "C" void VBIRQ_Assert(int source, bool assert)
150 {
151 assert(source >= 0 && source <= 4);
152
153 IRQ_Asserted &= ~(1 << source);
154
155 if(assert)
156 IRQ_Asserted |= 1 << source;
157
158 RecalcIntLevel();
159 }
160
HWCTRL_Read(v810_timestamp_t & timestamp,uint32 A)161 static uint8 HWCTRL_Read(v810_timestamp_t ×tamp, uint32 A)
162 {
163 uint8 ret = 0;
164
165 /* HWCtrl Bogus Read? */
166 if(A & 0x3)
167 return(ret);
168
169 switch(A & 0xFF)
170 {
171 case 0x18:
172 case 0x1C:
173 case 0x20:
174 ret = TIMER_Read(timestamp, A);
175 break;
176 case 0x24:
177 ret = WCR | 0xFC;
178 break;
179 case 0x10:
180 case 0x14:
181 case 0x28:
182 ret = VBINPUT_Read(timestamp, A);
183 break;
184 }
185
186 return(ret);
187 }
188
HWCTRL_Write(v810_timestamp_t & timestamp,uint32 A,uint8 V)189 static void HWCTRL_Write(v810_timestamp_t ×tamp, uint32 A, uint8 V)
190 {
191 /* HWCtrl Bogus Write? */
192 if(A & 0x3)
193 return;
194
195 switch(A & 0xFF)
196 {
197 case 0x18:
198 case 0x1C:
199 case 0x20:
200 TIMER_Write(timestamp, A, V);
201 break;
202 case 0x24:
203 WCR = V & 0x3;
204 break;
205 case 0x10:
206 case 0x14:
207 case 0x28:
208 VBINPUT_Write(timestamp, A, V);
209 break;
210 }
211 }
212
MemRead8(v810_timestamp_t & timestamp,uint32 A)213 uint8 MDFN_FASTCALL MemRead8(v810_timestamp_t ×tamp, uint32 A)
214 {
215 uint8 ret = 0;
216 A &= (1 << 27) - 1;
217
218 switch(A >> 24)
219 {
220 case 0:
221 ret = VIP_Read8(timestamp, A);
222 break;
223
224 case 2:
225 ret = HWCTRL_Read(timestamp, A);
226 break;
227
228 case 1:
229 case 3:
230 case 4:
231 break;
232
233 case 5:
234 ret = WRAM[A & 0xFFFF];
235 break;
236
237 case 6:
238 if(GPRAM)
239 ret = GPRAM[A & GPRAM_Mask];
240 break;
241
242 case 7:
243 ret = GPROM[A & GPROM_Mask];
244 break;
245 }
246 return(ret);
247 }
248
MemRead16(v810_timestamp_t & timestamp,uint32 A)249 uint16 MDFN_FASTCALL MemRead16(v810_timestamp_t ×tamp, uint32 A)
250 {
251 uint16 ret = 0;
252
253 A &= (1 << 27) - 1;
254
255 switch(A >> 24)
256 {
257 case 0:
258 ret = VIP_Read16(timestamp, A);
259 break;
260 case 2:
261 ret = HWCTRL_Read(timestamp, A);
262 break;
263 case 1:
264 case 3:
265 case 4:
266 break;
267 case 5:
268 ret = LoadU16_LE((uint16 *)&WRAM[A & 0xFFFF]);
269 break;
270 case 6:
271 if(GPRAM)
272 ret = LoadU16_LE((uint16 *)&GPRAM[A & GPRAM_Mask]);
273 break;
274
275 case 7:
276 ret = LoadU16_LE((uint16 *)&GPROM[A & GPROM_Mask]);
277 break;
278 }
279 return(ret);
280 }
281
MemWrite8(v810_timestamp_t & timestamp,uint32 A,uint8 V)282 void MDFN_FASTCALL MemWrite8(v810_timestamp_t ×tamp, uint32 A, uint8 V)
283 {
284 A &= (1 << 27) - 1;
285
286 switch(A >> 24)
287 {
288 case 0:
289 VIP_Write8(timestamp, A, V);
290 break;
291 case 1:
292 VB_VSU->Write((timestamp + VSU_CycleFix) >> 2, A, V);
293 break;
294 case 2:
295 HWCTRL_Write(timestamp, A, V);
296 break;
297 case 3:
298 case 4:
299 break;
300 case 5:
301 WRAM[A & 0xFFFF] = V;
302 break;
303 case 6:
304 if(GPRAM)
305 GPRAM[A & GPRAM_Mask] = V;
306 break;
307
308 case 7:
309 // ROM, no writing allowed!
310 break;
311 }
312 }
313
MemWrite16(v810_timestamp_t & timestamp,uint32 A,uint16 V)314 void MDFN_FASTCALL MemWrite16(v810_timestamp_t ×tamp, uint32 A, uint16 V)
315 {
316 A &= (1 << 27) - 1;
317
318 switch(A >> 24)
319 {
320 case 0:
321 VIP_Write16(timestamp, A, V);
322 break;
323 case 1:
324 VB_VSU->Write((timestamp + VSU_CycleFix) >> 2, A, V);
325 break;
326 case 2:
327 HWCTRL_Write(timestamp, A, V);
328 break;
329 case 3:
330 case 4:
331 break;
332 case 5:
333 StoreU16_LE((uint16 *)&WRAM[A & 0xFFFF], V);
334 break;
335 case 6:
336 if(GPRAM)
337 StoreU16_LE((uint16 *)&GPRAM[A & GPRAM_Mask], V);
338 break;
339 case 7:
340 /* ROM, no writing allowed! */
341 break;
342 }
343 }
344
FixNonEvents(void)345 static void FixNonEvents(void)
346 {
347 if(next_vip_ts & 0x40000000)
348 next_vip_ts = VB_EVENT_NONONO;
349
350 if(next_timer_ts & 0x40000000)
351 next_timer_ts = VB_EVENT_NONONO;
352
353 if(next_input_ts & 0x40000000)
354 next_input_ts = VB_EVENT_NONONO;
355 }
356
EventReset(void)357 static void EventReset(void)
358 {
359 next_vip_ts = VB_EVENT_NONONO;
360 next_timer_ts = VB_EVENT_NONONO;
361 next_input_ts = VB_EVENT_NONONO;
362 }
363
CalcNextTS(void)364 static INLINE int32 CalcNextTS(void)
365 {
366 int32 next_timestamp = next_vip_ts;
367
368 if(next_timestamp > next_timer_ts)
369 next_timestamp = next_timer_ts;
370
371 if(next_timestamp > next_input_ts)
372 next_timestamp = next_input_ts;
373
374 return(next_timestamp);
375 }
376
RebaseTS(const v810_timestamp_t timestamp)377 static void RebaseTS(const v810_timestamp_t timestamp)
378 {
379 assert(next_vip_ts > timestamp);
380 assert(next_timer_ts > timestamp);
381 assert(next_input_ts > timestamp);
382
383 next_vip_ts -= timestamp;
384 next_timer_ts -= timestamp;
385 next_input_ts -= timestamp;
386 }
387
VB_SetEvent(const int type,const v810_timestamp_t next_timestamp)388 extern "C" void VB_SetEvent(const int type,
389 const v810_timestamp_t next_timestamp)
390 {
391 if(type == VB_EVENT_VIP)
392 next_vip_ts = next_timestamp;
393 else if(type == VB_EVENT_TIMER)
394 next_timer_ts = next_timestamp;
395 else if(type == VB_EVENT_INPUT)
396 next_input_ts = next_timestamp;
397
398 if(next_timestamp < VB_V810->GetEventNT())
399 VB_V810->SetEventNT(next_timestamp);
400 }
401
EventHandler(const v810_timestamp_t timestamp)402 static int32 MDFN_FASTCALL EventHandler(const v810_timestamp_t timestamp)
403 {
404 if(timestamp >= next_vip_ts)
405 next_vip_ts = VIP_Update(timestamp);
406
407 if(timestamp >= next_timer_ts)
408 next_timer_ts = TIMER_Update(timestamp);
409
410 if(timestamp >= next_input_ts)
411 next_input_ts = VBINPUT_Update(timestamp);
412
413 return(CalcNextTS());
414 }
415
416 // Called externally from debug.cpp in some cases.
ForceEventUpdates(const v810_timestamp_t timestamp)417 static void ForceEventUpdates(const v810_timestamp_t timestamp)
418 {
419 next_vip_ts = VIP_Update(timestamp);
420 next_timer_ts = TIMER_Update(timestamp);
421 next_input_ts = VBINPUT_Update(timestamp);
422
423 VB_V810->SetEventNT(CalcNextTS());
424 }
425
VB_Power(void)426 static void VB_Power(void)
427 {
428 memset(WRAM, 0, 65536);
429
430 VIP_Power();
431 VB_VSU->Power();
432 TIMER_Power();
433 VBINPUT_Power();
434
435 EventReset();
436 IRQ_Asserted = 0;
437 RecalcIntLevel();
438 VB_V810->Reset();
439
440 VSU_CycleFix = 0;
441 WCR = 0;
442
443 ForceEventUpdates(0);
444 }
445
SettingChanged(const char * name)446 static void SettingChanged(const char *name)
447 {
448 if(!strcmp(name, "vb.3dmode"))
449 {
450 VB3DMode = MDFN_GetSettingUI("vb.3dmode");
451 uint32 prescale = MDFN_GetSettingUI("vb.liprescale");
452 uint32 sbs_separation = MDFN_GetSettingUI("vb.sidebyside.separation");
453
454 VIP_Set3DMode(VB3DMode, MDFN_GetSettingUI("vb.3dreverse"), prescale, sbs_separation);
455 }
456 else if(!strcmp(name, "vb.disable_parallax"))
457 {
458 VIP_SetParallaxDisable(MDFN_GetSettingB("vb.disable_parallax"));
459 }
460 else if(!strcmp(name, "vb.anaglyph.lcolor") || !strcmp(name, "vb.anaglyph.rcolor") ||
461 !strcmp(name, "vb.anaglyph.preset") || !strcmp(name, "vb.default_color"))
462 {
463 uint32 lcolor = MDFN_GetSettingUI("vb.anaglyph.lcolor"), rcolor = MDFN_GetSettingUI("vb.anaglyph.rcolor");
464 int preset = MDFN_GetSettingI("vb.anaglyph.preset");
465
466 if(preset != ANAGLYPH_PRESET_DISABLED)
467 {
468 lcolor = AnaglyphPreset_Colors[preset][0];
469 rcolor = AnaglyphPreset_Colors[preset][1];
470 }
471 VIP_SetAnaglyphColors(lcolor, rcolor);
472 VIP_SetDefaultColor(MDFN_GetSettingUI("vb.default_color"));
473 }
474 else if(!strcmp(name, "vb.input.instant_read_hack"))
475 {
476 VBINPUT_SetInstantReadHack(MDFN_GetSettingB("vb.input.instant_read_hack"));
477 }
478 else if(!strcmp(name, "vb.instant_display_hack"))
479 VIP_SetInstantDisplayHack(MDFN_GetSettingB("vb.instant_display_hack"));
480 else if(!strcmp(name, "vb.allow_draw_skip"))
481 VIP_SetAllowDrawSkip(MDFN_GetSettingB("vb.allow_draw_skip"));
482 }
483
484 struct VB_HeaderInfo
485 {
486 char game_title[256];
487 uint32 game_code;
488 uint16 manf_code;
489 uint8 version;
490 };
491
492 struct VBGameEntry
493 {
494 uint32 checksums[16];
495 const char *title;
496 uint32 patch_address[512];
497 };
498
499 static const struct VBGameEntry VBGames[] =
500 {
501 { { 0xbb71b522 } , "3D Tetris (US)", { 0xFFF1E740,
502 0xfff1e75a,
503 0xfff5c958,
504 0xfff5c9a4,
505 0xfff5c9b6,
506 0xfff677a6,
507 0xfff677f0,
508 0xfff6c72a,
509 0xfffeffc2,
510 0xfff6df22,
511 0xfff6e01a,
512 0xfff6e20a,
513 0xfff6e302,
514 0xfff6e5e4,
515 0xfff6eb34,
516 0xfff6eb8a,
517 0xfff00cd0,
518 0xfffd9508,
519 0xfffdad90,
520 0xfffd9f1c,
521 0xfffca7a2,
522 0xfffca986,
523 0xfffcaad4,
524 0xfffcacb0,
525 0xfff3dbc6,
526 0xfff3dc58,
527 0xfff3ca1a,
528 0xfff3effe,
529 0xfff3f06c,
530 0xfff3f122,
531 0xfff3f2da,
532 0xfff3c9d8,
533 0xfff01892,
534 0xfff017f4,
535 0xfff016c8,
536 0xfff4677c,
537 0xfff4620a,
538 0xfff3503e,
539 0xfff3f97a,
540 0xfff3fae0,
541 0xfff01270,
542 0xfff473c8,
543 0xfff472dc,
544 0xfff0160a,
545 0xfff6e112,
546 0xfff6e7d2,
547 0xfffc1730,
548 0xfff3f1e6,
549 0xfffc22da,
550 0xfffc20a2,
551 0xfffc2378,
552 0xfff36152,
553 0xfff37120,
554 0xfff378b4,
555 0xfffc1b44,
556 0xfffc1b8e,
557 0xfff3f258,
558 0xfff3655c,
559 0xfffd9902,
560 0xfff49b60,
561 0xfff86ef0,
562 0xfff3cf08,
563 0xfff5894c,
564 0xfff3cec2,
565 0xfff5a73e,
566 0xfff400ce,
567 0xfff3c2ec,
568 0xfff5b5c2,
569 0xfff5b64a,
570 0xfffd2968,
571 0xfffd2ca0,
572 0xfffd2be0,
573 0xfffd2b40,
574 0xfffd2d10,
575 0xfffd2d26,
576 0xfff5a6a0,
577 0xfff5a564,
578 0xfffd9800,
579 0xfffd9a04,
580 0xfffd9b30,
581 0xfffcd8d0,
582 0xfffcd830,
583 0xfffc15a4,
584 0xfff4b5f2,
585 0xfff3f346,
586 0xfff374ae,
587 0xfff3fa42,
588 0xfff3720c,
589 0xfff38298,
590 0xfff38370,
591 0xfff2b8a2,
592 0xfff2bf52,
593 0xfff0199a,
594 0xfff01dc0,
595 0xfffd169e,
596 0xfffd19d6,
597 0xfffd1876,
598 0xfffd1a46,
599 0xfffd1a5c,
600 0xfff676b6,
601 0xfff675fc,
602 0xfff37b48,
603 0xfffc246e,
604 0xfffc24b8,
605 0xfff365e8,
606 0xfff2dfa0,
607 0xfff36674,
608 0xfff36700,
609 0xfff598f4,
610 0xfff59992,
611 0xfff59c2a,
612 0xfff59c74,
613 0xfff4709a,
614 0xfff46eec,
615 0xfff4714c,
616 0xfff4b808,
617 0xfff3f3b2,
618 0xfffdaeda,
619 0xfffdb044,
620 0xfffdae36,
621 0xfff4b698,
622 0xfff4b73c,
623 0xfff49c06,
624 0xfffdb322,
625 0xfffdb18c,
626 0xfff4ba68,
627 0xfff4b8d2,
628 0xfff474aa,
629 0xfffd1916,
630 0xfff3d0ac,
631 0xfff477ac,
632 0xfff3d2ca,
633 0xfff476c0,
634 0xfff5a41e,
635 0xfff5a04c,
636 0xfff4788e,
637 0xfffc1392,
638 0xfffc14f8,
639 } },
640
641 { { 0xe81a3703 }, "Bound High!", { 0x0703181A , 0x070229BE, 0x07002CA6,
642 0x07024f20,
643 0x070317ae,
644 0x07030986,
645 0x070309ca,
646 0x07031968,
647 0x07030ad2,
648 0x07030b16,
649 0x070319be,
650 0x07031a20,
651 0x070296b4,
652 0x0702984e,
653 0x07029888,
654 0x070298d0,
655 0x07029910,
656 0x070299ce,
657 0x07030c3a,
658 0x07030dfc,
659 0x07030e52,
660 0x07030eb4,
661 0x070250fa,
662 0x07025148,
663 0x07025776,
664 0x070257c6,
665 0x07025828,
666 0x07021dc0,
667 0x07021e50,
668 0x070008e6,
669 0x0700155c,
670 0x070005f4,
671 0x07022a08,
672 0x07031e2e,
673 0x07032308,
674 0x0703234a,
675 0x070323ac,
676 0x0703a27a,
677 0x0703a754,
678 0x0703a77c,
679 0x0703a7b4,
680 0x0703a816,
681 0x07002104,
682 0x070028e2,
683 0x0700299e,
684 0x070029d8,
685 0x07001782,
686 0x07001912,
687 0x070024da,
688 0x070347e6,
689 0x07035ec4,
690 0x07035f16,
691 0x07035f78,
692 0x0702d152,
693 0x0702d19a,
694 0x0702d548,
695 0x0702d5cc,
696 0x07001c30,
697 0x0702e97e,
698 0x0702e9bc,
699 0x070009b2,
700 0x07030422,
701 0x070305fc,
702 0x0703064c,
703 0x070306ae,
704 0x07026c80,
705 0x07027618,
706 0x07027656,
707 0x07001a92,
708 0x0702eff8,
709 0x0702f4e6,
710 0x0702f54e,
711 0x0702f5b0,
712 0x07025df6,
713 0x07025fb2,
714 0x07026036,
715 0x0702e01a,
716 0x0702e090,
717 0x0702e114,
718 0x0702e8ea,
719 0x07001440,
720 0x0702c46e,
721 0x0702c4b6,
722 0x0702c9e4,
723 0x0702ca6e,
724 0x0702a532,
725 0x0702a5bc,
726 0x0702aba0,
727 0x0702b4ce,
728 0x0702b536,
729 } },
730
731 { { 0xc9710a36} , "Galactic Pinball", { 0xFFF4018A,
732 0xfff40114,
733 0xfff51886,
734 0xfff51abe,
735 0xfff4b704,
736 0xfff4ec7a,
737 0xfff53708,
738 0xfff53a3c,
739 }},
740
741 { { 0x2199af41 }, "Golf (US)", { 0xFFE0141A, 0xFFE097C4, 0xFFE1F47A, 0xFFE0027E, 0xFFE05CA0, 0xFFE014A0,
742 0xffe00286,
743 0xffe013d0,
744 0xffe013f0,
745 0xffe01482,
746 0xffe01004,
747 0xffe01024,
748 0xffe00d30,
749 0xffe00d50,
750 0xffe00db4,
751 0xffe00dd4,
752 0xffe13efe,
753 0xffe13f62,
754 0xffe13fd2,
755 0xffe01744,
756 0xffe01764,
757 0xffe05c90,
758 0xffe017b2,
759 0xffe017d2,
760 0xffe01930,
761 0xffe01950,
762 0xffe01c4a,
763 0xffe01c6a,
764 0xffe01cb8,
765 0xffe01cd8,
766 0xffe01dce,
767 0xffe01de8,
768 0xffe01e5a,
769 0xffe01e7a,
770 0xffe1409e,
771 0xffe02450,
772 0xffe02470,
773 0xffe024b0,
774 0xffe024d0,
775 0xffe02530,
776 0xffe02550,
777 0xffe0257e,
778 0xffe0259e,
779 0xffe1429c,
780 0xffe027c4,
781 0xffe027e4,
782 0xffe13f2a,
783 0xffe097a4,
784 0xffe181bc,
785 0xffe1ce40,
786 0xffe1ce60,
787 0xffe07e80,
788 0xffe07ea0,
789 0xffe07ec0,
790 0xffe07ee0,
791 0xffe0810e,
792 0xffe08158,
793 0xffe1e468,
794 0xffe1e488,
795 0xffe2198c,
796 0xffe09a96,
797 0xffe09ab6,
798 0xffe1f7be,
799 0xffe1f7de,
800 0xffe1f8ae,
801 0xffe1f9d6,
802 0xffe1fa18,
803 0xffe1fa38,
804 0xffe05c68,
805 0xffe05c78,
806 0xffe14344,
807 0xffe09e06,
808 0xffe16d8a,
809 0xffe16daa,
810 0xffe21712,
811 0xffe1f37a,
812 0xffe1f39a,
813 0xffe1f624,
814 0xffe1f666,
815 0xffe1f686,
816 0xffe141f8,
817 0xffe151d2,
818 0xffe17622,
819 } },
820
821 { { 0xefd0ac36 }, "Innsmouth House (Japan)", { 0x070082F4,
822 0x07017546,
823 0x07016f9a,
824 0x07017558,
825 0x07016fac,
826 0x07017692,
827 0x070176a4,
828 }},
829
830 { { 0xa44de03c, 0x81af4d6d /*[b1]*/, 0xb15d706e /*(Enable Cheats Hack)*/, 0x79a99f3c /*[T+Ger1.0_KR155E]*/ }, "Jack Bros (US)", { 0x070001A6 }},
831 { { 0xcab61e8b }, "Jack Bros (Japan)", {
832 0x07000192,
833 } },
834
835 // Is 0xbf0d0ab0 the bad dump?
836 { { 0xa47de78c, 0xbf0d0ab0 }, "Mario Clash", { 0xFFFF5BB4, 0xFFFE6FF0, 0xFFFE039E,
837 0xfffdd786,
838 0xfffdd76c,
839 0xffff5bc6,
840 0xffff73a4,
841 0xffff73b6,
842 0xfffdd836,
843 0xfffdd848,
844 0xffff916c,
845 0xffff917e,
846 0xfffe7002,
847 0xfffe7c36,
848 0xfffe7c48,
849 0xffff44f4,
850 0xffff4506,
851 0xfffe03b0,
852 0xffff2514,
853 0xffff2526,
854 0xffff9be2,
855 0xffff9bf4,
856 } },
857
858 { { 0x7ce7460d }, "Mario's Tennis", { 0xFFF8017C, 0xFFF90FEA, 0xFFF86DFA, 0xFFF873D6, 0xFFF9301C,
859 0xfff801a2,
860 0xfff90f98,
861 0xfff90fae,
862 0xfff90fc8,
863 0xfff914c4,
864 0xfff9150e,
865 0xfff82a00,
866 0xfff82a1a,
867 0xfff82a38,
868 0xfff86b98,
869 0xfff86e66,
870 0xfff871a2,
871 0xfff8d9b6,
872 0xfff8da5a,
873 0xfff8dcf8,
874 0xfff87aa8,
875 0xfff93c86,
876 0xfff93ca8,
877 0xfff93ce0,
878 0xfff94338,
879 0xfff93158,
880 } },
881
882 { { 0xdf4d56b4 }, "Nester's Funky Bowling (US)", { 0xFFE00B78, 0xFFE00D82, 0xFFE0105A, 0xFFE00FCE,
883 0xffe00f6a,
884 0xffe00f72,
885 0xffe00ddc,
886 0xffe0089e,
887 0xffe00fba,
888 0xffe03702,
889 0xffe01064,
890 0xffe0c024,
891 0xffe00bba,
892 0xffe0d86c,
893 0xffe0d51c,
894 } },
895
896 { { 0x19bb2dfb, 0x25fb89bb /*[b1]*/, 0x21d224af /*[h1]*/, 0xc767fe4b /*[h2]*/ }, "Panic Bomber (US)", { 0x07001FE8,
897 0x07001f34,
898 0x07001fc6,
899 } },
900
901 // Japan and US versions probably use the same code.
902 { { 0xaa10a7b4, 0x7e85c45d }, "Red Alarm", { 0x202CE, 0x070202B4,
903 0x070202e2,
904 0x07020642,
905 0x0702074c,
906 0x07001f50,
907 0x0703ca0a,
908 0x07045c9e,
909 0x0703326a,
910 0x07031aae,
911 0x070328a4,
912 0x07032e5e,
913 0x0703748e,
914 0x07035868,
915 0x07035948,
916 0x07031c88,
917 0x0703786a,
918 0x0703628e,
919 0x07035b20,
920 0x07035bc0,
921 0x07033856,
922 0x07037370,
923 0x07031a2e,
924 0x070373c4,
925 0x0703cfd8,
926 0x0703d03c,
927 0x0703d0a4,
928 0x0702eae2,
929 0x0703ce00,
930 0x07044f02,
931 0x07041922,
932 0x07041df0,
933 0x0701ba38,
934 0x07045176,
935 0x07044f8c,
936 0x0703c926,
937 0x0703c940,
938 0x0703c712,
939 0x0703c73c,
940 0x07023158,
941 0x070231d6,
942 0x0702320c,
943 0x07020a60,
944 0x0700489c,
945 0x07032174,
946 0x070324ca,
947 0x0702ef56,
948 0x070414b0,
949 0x0702052e,
950 0x070321a6,
951 0x070321fe,
952 0x07032224,
953 0x07021866,
954 0x07021aa4,
955 0x07021b36,
956 0x07021b5e,
957 0x07021b88,
958 0x0703c6ba,
959 0x0703cb3c,
960 0x0703c67a,
961 0x070412d2,
962 0x0704132a,
963 0x07041428,
964 0x07020d2e,
965 0x07020d48,
966 0x0703755a,
967 0x070375ac,
968 0x070375da,
969 0x07020aaa,
970 0x0701ba8a,
971 0x07041b0c,
972 0x070355d8,
973 0x07051ce0,
974 0x070049e0,
975 0x070049fa,
976 0x07004a94,
977 0x07020fb8,
978 0x07021046,
979 0x070210dc,
980 0x07004bc2,
981 0x07004ac0,
982 0x07041640,
983 0x07041698,
984 0x07041744,
985 0x07020eb0,
986 0x070208bc,
987 0x07020db6,
988 0x07020e40,
989 0x07004b28,
990 0x070417c0,
991 0x07041d3c,
992 0x07035f18,
993
994 0x07022bd2,
995 0x07020504,
996 0x070419a4,
997 0x07041a78,
998 } },
999
1000 { { 0x44788197 }, "SD Gundam Dimension War (Japan)", {
1001 0xfff296de,
1002 0xfff2970a,
1003 0xfff29730,
1004 0xfff298b0,
1005 0xfff298fa,
1006 0xfff29aac,
1007 0xfff29af2,
1008 0xfff29b1a,
1009 0xfff065ba,
1010 0xfff29b56,
1011 0xfff29cd6,
1012 0xfff4b7aa,
1013 0xfff4b8e4,
1014 0xfff4b9e2,
1015 0xfff4ba2e,
1016 0xfff4bbba,
1017 0xfff2824c,
1018 0xfff2835a,
1019 0xfff2848e,
1020 0xfff28aa4,
1021 0xfff28b20,
1022 0xfff28d66,
1023 0xfff28e5c,
1024 0xfff28e76,
1025 0xfff065e6,
1026 0xfff29504,
1027 0xfff5869e,
1028 0xfff58134,
1029 0xfff563e4,
1030 0xfff5687e,
1031 0xfff19686,
1032 0xfff196e6,
1033 0xfff19726,
1034 0xfff1974e,
1035 0xfff1a3a2,
1036 0xfff1083e,
1037 0xfff140b2,
1038 0xfff1372c,
1039 0xfff13c0e,
1040 0xfff13c70,
1041 0xfff166f2,
1042 0xfff18010,
1043 0xfff18070,
1044 0xfff18604,
1045 0xfff10654,
1046 0xfff44a7a,
1047 0xfff44a90,
1048 0xfff44ab4,
1049 0xfff44af8,
1050 0xfff4bd2e,
1051 0xfff4517a,
1052 0xfff439e6,
1053 0xfff43e92,
1054 0xfff43ea8,
1055 0xfff43ecc,
1056 0xfff43ef8,
1057 0xfff442ee,
1058 0xfff444c8,
1059 0xfff1995c,
1060 0xfff191ce,
1061 0xfff264d4,
1062 0xfff267ae,
1063 0xfff489aa,
1064 0xfff489ee,
1065 0xfff48a32,
1066 0xfff48a76,
1067 0xfff48aba,
1068 0xfff48ccc,
1069 0xfff48dae,
1070 0xfff493f2,
1071 0xfff49422,
1072 0xfff494c0,
1073 0xfff49620,
1074 0xfff4a822,
1075 0xfff4a940,
1076 0xfff4aa46,
1077 0xfff4ab2a,
1078 0xfff1b3b6,
1079 0xfff1b3fc,
1080 0xfff1b456,
1081 0xfff1b496,
1082 0xfff1b4d6,
1083 0xfff1b516,
1084 0xfff1b556,
1085 0xfff1bc6e,
1086 0xfff1bc94,
1087 0xfff1bcaa,
1088 0xfff1bcce,
1089 0xfff1bcf6,
1090 0xfff1bd0c,
1091 0xfff1bd48,
1092 0xfff1bdca,
1093 0xfff1be2a,
1094 0xfff1bed6,
1095 0xfff26c88,
1096 0xfff4ac00,
1097 0xfff4ad68,
1098 0xfff4b0f8,
1099 0xfff26a70,
1100 0xfff26b18,
1101 0xfff1bf5e,
1102 0xfff26dbe,
1103 0xfff26e54,
1104 0xfff441c4,
1105 0xfff2d548,
1106 0xfff2d630,
1107 0xfff2d67c,
1108 0xfff2d6c0,
1109 0xfff2d750,
1110 0xfff2d7de,
1111 0xfff2d872,
1112 0xfff2d90e,
1113 0xfff2d9bc,
1114 0xfff2da64,
1115 0xfff2daec,
1116 0xfff2db74,
1117 0xfff2dc1c,
1118 0xfff2dc94,
1119 0xfff2dd32,
1120 0xfff2ddf4,
1121 0xfff2df4c,
1122 0xfff3017a,
1123 0xfff3091c,
1124 0xfff271f2,
1125 0xfff272a0,
1126 0xfff4be52,
1127 0xfff4bf06,
1128 0xfff4bf36,
1129 0xfff4bf5e,
1130 0xfff4c4fe,
1131 0xfff19852,
1132 0xfff44b38,
1133 0xfff44e4a,
1134 0xfff44f4c,
1135 0xfff0edc0,
1136 0xfff0f142,
1137 } },
1138
1139 { { 0xfa44402d }, "Space Invaders VC (Japan)", {
1140 0xfff80154,
1141 0xfff87e04,
1142 0xfff87e18,
1143 } },
1144
1145 // Is 0xc2211fcc a bad dump?
1146 { {0x60895693, 0xc2211fcc, 0x7cb69b3a /*[T+Eng]*/ }, "Space Squash (Japan)", {
1147 0x0701a97e,
1148 } },
1149
1150 { { 0x6ba07915, 0x41fb63bf /*[b1]*/ }, "T&E Virtual Golf (Japan)", {
1151 0x0700027e,
1152 0x07000286,
1153 0x070013d0,
1154 0x070013f0,
1155 0x0700141a,
1156 0x07001004,
1157 0x07001024,
1158 0x07000d30,
1159 0x07000d50,
1160 0x07000db4,
1161 0x07000dd4,
1162 0x07013c4e,
1163 0x07013cb2,
1164 0x07013d22,
1165 0x07001718,
1166 0x07001738,
1167 0x07001a32,
1168 0x07001a52,
1169 0x07005988,
1170 0x07005998,
1171 0x07001aa0,
1172 0x07001ac0,
1173 0x07001bb6,
1174 0x07001bd0,
1175 0x07001c36,
1176 0x07001c56,
1177 0x07013dee,
1178 0x0700223c,
1179 0x0700225c,
1180 0x0700229c,
1181 0x070022bc,
1182 0x07013fec,
1183 0x070024ee,
1184 0x0700250e,
1185 0x07013c7a,
1186 0x0700947c,
1187 0x0700949c,
1188 0x07009ade,
1189 0x0702162c,
1190 0x07017e2c,
1191 0x0701cae0,
1192 0x0701cb00,
1193 0x07007b70,
1194 0x07007b90,
1195 0x07007bb0,
1196 0x07007bd0,
1197 0x07007dfe,
1198 0x07007e48,
1199 0x0701e108,
1200 0x0701e128,
1201 0x07017280,
1202 0x0700976e,
1203 0x0700978e,
1204 0x0701f45e,
1205 0x0701f47e,
1206 0x0701f54e,
1207 0x0701f676,
1208 0x0701f6b8,
1209 0x0701f6d8,
1210 0x07005960,
1211 0x07005970,
1212 0x07014094,
1213 0x070169e6,
1214 0x07016a06,
1215 0x07013f48,
1216 0x0701f01a,
1217 0x0701f03a,
1218 0x0701f11a,
1219 0x0701f2c4,
1220 0x0701f306,
1221 0x0701f326,
1222 0x07014f22,
1223 0x07007982,
1224 0x070079a2,
1225 } },
1226
1227 { { 0x36103000, 0xa6e0d6db /*[T+Ger.4b_KR155E]*/, 0x126123ad /*[T+Ger1.0_KR155E]*/ }, "Teleroboxer", {
1228 0xfff2c408,
1229 0xfff2c3f2,
1230 0xfff2b626,
1231 0xfff2c2ee,
1232 0xfff2c2ae,
1233 0xfff2b71c,
1234 0xfff2b736,
1235 0xfff2c1da,
1236 0xfff2c21a,
1237 0xfff2c36c,
1238 0xfff2b876,
1239 0xfff2b996,
1240 0xfff2b9b0,
1241 0xfff2b970,
1242 0xfff2baf4,
1243 0xfff2bb50,
1244 0xfff2bc7e,
1245 0xfff2bc9c,
1246 0xfff6c2a2,
1247 0xfff6c386,
1248 0xfff6c39c,
1249 0xfff6ad22,
1250 0xfff0304c,
1251 0xfff03b8e,
1252 0xfff042ce,
1253 0xfff04782,
1254 0xfff04c5c,
1255 0xfff04d90,
1256 0xfff11242,
1257 0xfff12f4a,
1258 0xfff141b8,
1259 0xfff04192,
1260 0xfff0414c,
1261 0xfff0616c,
1262 0xfff069d0,
1263 0xfff07912,
1264 0xfff1a980,
1265 0xfff1dc7e,
1266 0xfff1f060,
1267 0xfff22c92,
1268 0xfff2ae50,
1269 0xfff2af42,
1270 0xfff2af60,
1271 0xfff2e08c,
1272 0xfff32112,
1273 0xfff3213a,
1274 0xfff2e9aa,
1275
1276 0xfff2e66c,
1277 0xfff2eb50,
1278 0xfff2eb6e,
1279 0xfff29f8c,
1280 0xfff2a1e4,
1281 0xfff2a36e,
1282 0xfff2a38c,
1283 0xfff339b0,
1284 0xfff339c6,
1285 0xfff25802,
1286 0xfff25a1e,
1287 0xfff2637c,
1288 0xfff2745c,
1289 0xfff27a74,
1290 0xfff29010,
1291 0xfff04014,
1292
1293 0xfff32368,
1294 0xfff32382,
1295 0xfff32398,
1296 0xfff325ea,
1297 0xfff325a4,
1298 0xfff32668,
1299 0xfff326c0,
1300 0xfff326fc,
1301 0xfff32730,
1302 0xfff32764,
1303 0xfff32798,
1304 0xfff327c2,
1305 0xfff327f0,
1306 0xfff0811c,
1307 0xfff083ac,
1308 0xfff098e4,
1309
1310 0xfff0ed12,
1311 0xfff0f114,
1312 0xfff0f7aa,
1313 0xfff101f0,
1314 0xfff102ae,
1315 0xfff108be,
1316 0xfff0a568,
1317 0xfff0aa78,
1318 0xfff0be3c,
1319 0xfff043a4,
1320 0xfff0435e,
1321 0xfff0dcf8,
1322 0xfff0dcb2,
1323
1324 0xfff054a4,
1325 0xfff05706,
1326 0xfff05934,
1327 0xfff23ad2,
1328 0xfff23b76,
1329 0xfff2420e,
1330
1331 0xfff5d454,
1332 0xfff5d51a,
1333 0xfff5d550,
1334 0xfff30eac,
1335 } },
1336
1337 { { 0x40498f5e }, "Tobidase! Panibomb (Japan)", {
1338 0x07001fe4,
1339 0x07001f30,
1340 0x07001fc2,
1341 } },
1342
1343 { { 0x133e9372 }, "VB Wario Land", { 0x1c232e, 0x1BFB98, 0x1C215C, 0x1C27C6,
1344 0xfffc2814,
1345 0xfffbf49a,
1346 0xfffbf48c,
1347 0xfffc45bc,
1348 0xfffc2956,
1349 } },
1350
1351 // Good grief(probably not even all of them!):
1352 { { 0x3ccb67ae }, "V-Tetris (Japan)", { 0xFFFA2ED4, 0xFFFA9FDC, 0xFFFA776A, 0xFFFA341C, 0xFFFABAB2, 0xFFFACCAE, 0xFFF8B38A, 0xFFFA9C14, 0xFFF8F086, 0xFFF925FE,
1353 0xfffa2e58,
1354 0xfffa2e78,
1355 0xfffa2e98,
1356 0xfffa2f02,
1357 0xfffa2f32,
1358 0xfffa2fb6,
1359 0xfffa2fd4,
1360 0xfff965e4,
1361 0xfffa9f6c,
1362 0xfffa9f8c,
1363 0xfffa9fac,
1364 0xfffaa026,
1365 0xfffaa044,
1366 0xfffa76c6,
1367 0xfffa7704,
1368 0xfffa7724,
1369 0xfffa7a2a,
1370 0xfffa7aba,
1371 0xfffa30d4,
1372 0xfffa30f2,
1373 0xfffa3142,
1374 0xfffa3158,
1375 0xfffa3268,
1376 0xfffa33c0,
1377 0xfffa33f4,
1378 0xfffa34b6,
1379 0xfffa35dc,
1380 0xfffa35f2,
1381 0xfffa3684,
1382 0xfffa369a,
1383 0xfffa376e,
1384 0xfffa3784,
1385 0xfffa3918,
1386 0xfffa3930,
1387 0xfffa3946,
1388 0xfffa39e4,
1389 0xfffa3a4e,
1390 0xfffa3ba6,
1391 0xfffa3bea,
1392 0xfffa3c00,
1393 0xfffa3cde,
1394 0xfffa3db4,
1395 0xfffa3de0,
1396 0xfffa3dfe,
1397 0xfffaba16,
1398 0xfffaba44,
1399 0xfffaba76,
1400 0xfffabc48,
1401 0xfffabf3e,
1402 0xfffac0f6,
1403 0xfffac45e,
1404 0xfffac59e,
1405 0xfffac904,
1406 0xfffaca44,
1407 0xfffaca94,
1408 0xfffacbc0,
1409 0xfffacbf0,
1410 0xfffacc2c,
1411 0xfffad262,
1412 0xfffacfe6,
1413 0xfffad01c,
1414 0xfffad296,
1415 0xfffad2f0,
1416 0xfff8b012,
1417 0xfff8b2de,
1418 0xfff8b2f2,
1419 0xfff8b31e,
1420 0xfff8b33e,
1421 0xfff8bf62,
1422 0xfff8c20e,
1423 0xfff8b98e,
1424 0xfff8bc4e,
1425 0xfff8c554,
1426 0xfff8c800,
1427 0xfff8c824,
1428 0xfff8c842,
1429 0xfff8d15e,
1430 0xfff8d188,
1431 0xfff8d1c0,
1432 0xfff8d1f6,
1433 0xfff8d5da,
1434 0xfff8d25e,
1435 0xfff8d27c,
1436 0xfffa9b98,
1437 0xfffa9bb8,
1438 0xfffa9bd8,
1439 0xfffa9f22,
1440 0xfffa9f40,
1441 0xfff9233c,
1442 0xfff923d0,
1443 0xfff923e4,
1444 0xfff9244a,
1445 0xfff92492,
1446 0xfff924b2,
1447 0xfff8f056,
1448 0xfff8f46a,
1449 0xfff9250e,
1450 0xfff925ba,
1451 0xfff925e0,
1452 0xfff94036,
1453 0xfff92f56,
1454 0xfff93d72,
1455 0xfff9409c,
1456 0xfff94270,
1457 0xfff928c0,
1458 0xfff92920,
1459 0xfff92940,
1460 0xfff9296e,
1461 0xfff929c8,
1462 0xfff92a74,
1463 0xfff92a9c,
1464 0xfff92aba,
1465 0xfff9265c,
1466 0xfff92688,
1467 0xfff926ba,
1468 0xfff926e6,
1469 0xfff92712,
1470 0xfff8f7b0,
1471 0xfff8f886,
1472 0xfff8f8a8,
1473 0xfff8f96a,
1474 0xfff8f998,
1475 0xfff8fae0,
1476 0xfff8faf6,
1477 0xfff8fb14,
1478 0xfff8fba4,
1479 0xfff8fcd0,
1480 0xfff8fd0c,
1481 0xfff8fd9c,
1482 0xfff8fe4c,
1483 0xfff8ff7a,
1484 0xfff8ffc8,
1485 0xfff90058,
1486 0xfff90108,
1487 0xfff90236,
1488 0xfff90284,
1489 0xfff90314,
1490 0xfff903c4,
1491 0xfff904f2,
1492 0xfff90540,
1493 0xfff905d0,
1494 0xfff90680,
1495 0xfff907ae,
1496 0xfff907fc,
1497 0xfff9088c,
1498 0xfff908ae,
1499 0xfff908de,
1500 0xfff909cc,
1501 0xfff8f4c6,
1502 0xfff8f586,
1503 0xfff8f59a,
1504 0xfff8f5bc,
1505 0xfff8f5ec,
1506 0xfff8f642,
1507 0xfff8f714,
1508 0xfff8f740,
1509 0xfff8f77c,
1510 0xfff940f4,
1511 0xfff9411a,
1512 0xfff94134,
1513 0xfffad91e,
1514 0xfff94152,
1515 0xfffad98a,
1516 0xfffad9f8,
1517 0xfffada66,
1518 0xfffadad8,
1519 0xfffadb4a,
1520 0xfffadbbc,
1521 0xfffadc2e,
1522 0xfffadc7e,
1523 0xfffb72e2,
1524 0xfff94172,
1525 0xfff941a6,
1526 0xfffa79b0,
1527 0xfffa7924,
1528 0xfffabd9e,
1529 0xfffabe32,
1530 0xfffabe54,
1531 0xfffabee8,
1532 0xfffabf18,
1533 0xfffac11a,
1534 0xfffac2c2,
1535 0xfffac41a,
1536 0xfffac5c0,
1537 0xfffac5d6,
1538 0xfffac768,
1539 0xfffac8c0,
1540 0xfffaca66,
1541 0xfffacc78,
1542 0xfffaddb2,
1543 0xfffade64,
1544 0xfffadf18,
1545 0xfffadfcc,
1546 0xfffae084,
1547 0xfffae13c,
1548 0xfffae1f4,
1549 0xfffae2ac,
1550 0xfffae2d8,
1551 0xfffa6dda,
1552 0xfffa6dfa,
1553 0xfffa6e24,
1554 0xfffa6e62,
1555 0xfffa6e82,
1556 0xfff9c9e2,
1557 0xfff9ca02,
1558 0xfff9ca2e,
1559 0xfff9cbd4,
1560 0xfff9cc14,
1561 0xfff9ccba,
1562 0xfff9cce6,
1563 0xfff9cd8c,
1564 0xfff9cdea,
1565 0xfff9ce86,
1566 0xfff9cea4,
1567 0xfffa6f46,
1568 0xfffa6f70,
1569 0xfffa6fae,
1570 0xfffa6fce,
1571 0xfff944fe,
1572 0xfff9453a,
1573 0xfff945bc,
1574 0xfff94604,
1575 0xfff946b0,
1576 0xfff946d6,
1577 0xfff946f4,
1578 0xfff9616a,
1579 0xfff95e7e,
1580 0xfff950be,
1581 0xfff961d0,
1582 0xfff964f8,
1583 0xfff948ca,
1584 0xfff948ea,
1585 0xfff94918,
1586 0xfff94972,
1587 0xfff94a1e,
1588 0xfff94a46,
1589 0xfff94a64,
1590 0xfff962d2,
1591 0xfff962f8,
1592 0xfff96312,
1593 0xfff96330,
1594 0xfffb7226,
1595 0xfff96350,
1596 0xfff96384,
1597 0xfff9652a,
1598 0xfff96554,
1599 0xfffa706a,
1600 0xffface1a,
1601 0xffface50,
1602 0xffface70,
1603 0xfff8c238,
1604 0xfff8c3a4,
1605 0xfff8c3ce,
1606 0xfff8c536,
1607 0xfff8de2a,
1608 0xfff8de54,
1609 0xfff8de8e,
1610 0xfff8dec6,
1611 0xfff8e284,
1612 0xfff8df1e,
1613 0xfff8df3c,
1614 0xfffa9dce,
1615 0xfffa9e56,
1616 0xfff943a2,
1617 0xfff94454,
1618 0xfff944e8,
1619 0xfff9486a,
1620 0xfff8cc76,
1621 0xfff8cca0,
1622 0xfff8ccda,
1623 0xfff8cd12,
1624 0xfff8d0d0,
1625 0xfff8cd6a,
1626 0xfff8cd88,
1627 0xfff8dda4,
1628 0xfff8d8bc,
1629 0xfff8ddc8,
1630 0xfff8ddf0,
1631 0xfff8c8de,
1632 0xfff8cbaa,
1633 0xfff8cbbe,
1634 0xfff8cbe8,
1635 0xfff8cc10,
1636 0xfff8d0f4,
1637 0xfff8d11c,
1638 0xfff8e2a8,
1639 0xfff8e2d0,
1640 0xfff8bc6c,
1641 0xfff8bf2c,
1642 0xfff8bf44,
1643 0xfff8f680,
1644 0xfff8e4f8,
1645 0xfff8e518,
1646 0xfff8e5ce,
1647 0xfff8e606,
1648 0xfff8ed2e,
1649 0xfff8eb30,
1650 0xfff8efa6,
1651 0xfff8efd0,
1652 0xfff8f012,
1653 0xfff9cdb2,
1654 0xfffa146a,
1655 0xfffa169c,
1656 0xfffa16ca,
1657 0xfffa16fa,
1658 0xfffa1766,
1659 0xfffa179e,
1660 0xfffa21d8,
1661 0xfffa2272,
1662 0xfffa2290,
1663 0xfffa22a6,
1664 0xfffa24d4,
1665 0xfff8df6e,
1666 0xfff8df98,
1667 0xfff8dfc6,
1668 0xfff8cdba,
1669 0xfff8cde4,
1670 0xfff8ce12,
1671 0xfff8d2ae,
1672 0xfff8d2d8,
1673 0xfff8d30e,
1674 } },
1675
1676 { { 0x4c32ba5e, 0xdc8c0bf4 /*[h1]*/ }, "Vertical Force (US)", { 0x7000BF4 } },
1677
1678 // Is 0x05d06377 a bad dump?
1679 { { 0x9e9b8b92, 0x05d06377 }, "Vertical Force (Japan)", { 0x7000BF4 } },
1680
1681 { { 0x20688279, 0xddf9abe0 /*(Debug Menu Hack)*/ }, "Virtual Bowling (Japan)", {
1682 0xfff24eda,
1683 0xfff28bea,
1684 0xfff28c00,
1685 0xfff1fb9a,
1686 0xfff1c284,
1687 0xfff1ddc4,
1688 0xfff0b93e,
1689 0xfff249ac,
1690 0xfff0b9a4,
1691 0xfff258fc,
1692 0xfff172aa,
1693 0xfff2606e,
1694 0xfff1a0e6,
1695 0xfff1a0fc,
1696 0xfff17222,
1697 0xfff26058,
1698 0xfff0b984,
1699 0xfff21080,
1700 0xfff21096,
1701 0xfff1ddae,
1702 0xfff13288,
1703 0xfff132d8,
1704 0xfff13ec8,
1705 0xfff0b920,
1706 0xfff284e8,
1707 0xfff284fe,
1708 0xfff154ac,
1709 0xfff155f8,
1710 0xfff15706,
1711 0xfff2f51e,
1712 0xfff1fb84,
1713 0xfff27310,
1714 0xfff0c480,
1715 0xfff2d618,
1716 0xfff2d62e,
1717 } },
1718
1719 { { 0x526cc969, 0x45471e40 /*[b1]*/ }, "Virtual Fishing (Japan)", {
1720 0x07000388,
1721 0x07000368,
1722 } },
1723
1724
1725 { { 0x8989fe0a }, "Virtual Lab (Japan)", {
1726 0x070000ae,
1727 0x0700395a,
1728 0x070051ac,
1729 0x070039cc,
1730 0x07003a96,
1731 0x07003b1c,
1732 0x07003bce,
1733 0x07003c4e,
1734 0x07003d42,
1735 0x07003e42,
1736 0x07003e9c,
1737 0x07003f30,
1738 0x07004098,
1739 0x070041ee,
1740 0x07003180,
1741 0x070050f4,
1742 0x07002fc4,
1743 0x07000960,
1744 0x070009a6,
1745 0x07000b60,
1746 0x07000bb4,
1747 0x07001764,
1748 0x070020ec,
1749 0x070075cc,
1750 0x07003112,
1751 0x070001b2,
1752 0x07001074,
1753 0x070010e4,
1754 0x070011d0,
1755 0x07001262,
1756 0x070012f6,
1757 0x070013f4,
1758 0x070014bc,
1759 0x070015a2,
1760 0x0700162e,
1761 0x070023b8,
1762 0x07002790,
1763 0x070033ca,
1764 0x070034c8,
1765 0x07003254,
1766 0x070035d0,
1767 0x0700369e,
1768 0x0700370a,
1769 0x07003796,
1770 0x070037fc,
1771 0x070032f6,
1772 } },
1773
1774 // Is 0xcc62ab38 a bad dump?
1775 { { 0x736b40d6, 0xcc62ab38 }, "Virtual League Baseball (US)", {
1776 0x07000bbc,
1777 0x070011a4,
1778 0x07000cc4,
1779 0x07000c1c,
1780 0x07000c6a,
1781 0x07000be0,
1782 0x07000c40,
1783 } },
1784
1785 { { 0x9ba8bb5e }, "Virtual Pro Yakyuu '95", {
1786 0x07000bbc,
1787 0x070011a4,
1788 0x07000cc4,
1789 0x07000c1c,
1790 0x07000c6a,
1791 0x07000be0,
1792 0x07000c40,
1793 } },
1794
1795 { { 0x82a95e51, 0x742298d1 /*[b1]*/ }, "Waterworld (US)", { // Apparently has complex wait loop.
1796 0x070008fc,
1797 0x0700090e,
1798 0x0700209e,
1799 0x070020b4,
1800 0x070009da,
1801 0x0700222a,
1802 0x07002312,
1803 0x070023f8,
1804 0x07002680,
1805 0x07002c68,
1806 0x0700303c,
1807 0x07003052,
1808 0x0700397e,
1809 0x07003994,
1810 0x07000bb4,
1811 0x07000ac8,
1812 } },
1813
1814 { { 0x44C2B723 } , "Space Pinball (Prototype)", {
1815 0x0702EA7A
1816 }},
1817 };
1818
1819 // Source: http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
1820 // Rounds up to the nearest power of 2.
round_up_pow2(uint32 v)1821 static INLINE uint32 round_up_pow2(uint32 v)
1822 {
1823 v--;
1824 v |= v >> 1;
1825 v |= v >> 2;
1826 v |= v >> 4;
1827 v |= v >> 8;
1828 v |= v >> 16;
1829 v++;
1830
1831 v += (v == 0);
1832
1833 return(v);
1834 }
1835
Load(const uint8_t * data,size_t size)1836 static int Load(const uint8_t *data, size_t size)
1837 {
1838 V810_Emu_Mode cpu_mode = (V810_Emu_Mode)MDFN_GetSettingI("vb.cpu_emulation");
1839
1840 /* VB ROM image size is not a power of 2??? */
1841 if(size != round_up_pow2(size))
1842 return(0);
1843
1844 /* VB ROM image size is too small?? */
1845 if(size < 256)
1846 return(0);
1847
1848 /* VB ROM image size is too large?? */
1849 if(size > (1 << 24))
1850 return(0);
1851
1852 VB_HeaderInfo hinfo;
1853
1854 log_cb(RETRO_LOG_INFO, "Title: %s\n", hinfo.game_title);
1855 log_cb(RETRO_LOG_INFO, "Game ID Code: %u\n", hinfo.game_code);
1856 log_cb(RETRO_LOG_INFO, "Manufacturer Code: %d\n", hinfo.manf_code);
1857 log_cb(RETRO_LOG_INFO, "Version: %u\n", hinfo.version);
1858
1859 log_cb(RETRO_LOG_INFO, "ROM: %dKiB\n", (int)(size / 1024));
1860
1861 log_cb(RETRO_LOG_INFO, "V810 Emulation Mode: %s\n", (cpu_mode == V810_EMU_MODE_ACCURATE) ? "Accurate" : "Fast");
1862
1863 VB_V810 = new V810();
1864 VB_V810->Init(cpu_mode, true);
1865
1866 VB_V810->SetMemReadHandlers(MemRead8, MemRead16, NULL);
1867 VB_V810->SetMemWriteHandlers(MemWrite8, MemWrite16, NULL);
1868
1869 VB_V810->SetIOReadHandlers(MemRead8, MemRead16, NULL);
1870 VB_V810->SetIOWriteHandlers(MemWrite8, MemWrite16, NULL);
1871
1872 for(int i = 0; i < 256; i++)
1873 {
1874 VB_V810->SetMemReadBus32(i, false);
1875 VB_V810->SetMemWriteBus32(i, false);
1876 }
1877
1878 std::vector<uint32> Map_Addresses;
1879
1880 for(uint64 A = 0; A < 1ULL << 32; A += (1 << 27))
1881 {
1882 for(uint64 sub_A = 5 << 24; sub_A < (6 << 24); sub_A += 65536)
1883 {
1884 Map_Addresses.push_back(A + sub_A);
1885 }
1886 }
1887
1888 WRAM = VB_V810->SetFastMap(&Map_Addresses[0], 65536, Map_Addresses.size(), "WRAM");
1889 Map_Addresses.clear();
1890
1891
1892 // Round up the ROM size to 65536(we mirror it a little later)
1893 GPROM_Mask = (size < 65536) ? (65536 - 1) : (size - 1);
1894
1895 for(uint64 A = 0; A < 1ULL << 32; A += (1 << 27))
1896 {
1897 for(uint64 sub_A = 7 << 24; sub_A < (8 << 24); sub_A += GPROM_Mask + 1)
1898 {
1899 Map_Addresses.push_back(A + sub_A);
1900 //printf("%08x\n", (uint32)(A + sub_A));
1901 }
1902 }
1903
1904
1905 GPROM = VB_V810->SetFastMap(&Map_Addresses[0], GPROM_Mask + 1, Map_Addresses.size(), "Cart ROM");
1906 Map_Addresses.clear();
1907
1908 // Mirror ROM images < 64KiB to 64KiB
1909 for(uint64 i = 0; i < 65536; i += size)
1910 memcpy(GPROM + i, data, size);
1911
1912 GPRAM_Mask = 0xFFFF;
1913
1914 for(uint64 A = 0; A < 1ULL << 32; A += (1 << 27))
1915 {
1916 for(uint64 sub_A = 6 << 24; sub_A < (7 << 24); sub_A += GPRAM_Mask + 1)
1917 {
1918 //printf("GPRAM: %08x\n", A + sub_A);
1919 Map_Addresses.push_back(A + sub_A);
1920 }
1921 }
1922
1923
1924 GPRAM = VB_V810->SetFastMap(&Map_Addresses[0], GPRAM_Mask + 1, Map_Addresses.size(), "Cart RAM");
1925 Map_Addresses.clear();
1926
1927 memset(GPRAM, 0, GPRAM_Mask + 1);
1928
1929 VIP_Init();
1930 VB_VSU = new VSU(&sbuf[0], &sbuf[1]);
1931 VBINPUT_Init();
1932
1933 VB3DMode = MDFN_GetSettingUI("vb.3dmode");
1934 uint32 prescale = MDFN_GetSettingUI("vb.liprescale");
1935 uint32 sbs_separation = MDFN_GetSettingUI("vb.sidebyside.separation");
1936
1937 VIP_Set3DMode(VB3DMode, MDFN_GetSettingUI("vb.3dreverse"), prescale, sbs_separation);
1938
1939
1940 SettingChanged("vb.3dmode");
1941 SettingChanged("vb.disable_parallax");
1942 SettingChanged("vb.anaglyph.lcolor");
1943 SettingChanged("vb.anaglyph.rcolor");
1944 SettingChanged("vb.anaglyph.preset");
1945 SettingChanged("vb.default_color");
1946
1947 SettingChanged("vb.instant_display_hack");
1948 SettingChanged("vb.allow_draw_skip");
1949
1950 SettingChanged("vb.input.instant_read_hack");
1951
1952 MDFNGameInfo->fps = (int64)20000000 * 65536 * 256 / (259 * 384 * 4);
1953
1954
1955 VB_Power();
1956
1957
1958 #ifdef WANT_DEBUGGER
1959 VBDBG_Init();
1960 #endif
1961
1962
1963 MDFNGameInfo->nominal_width = 384;
1964 MDFNGameInfo->nominal_height = 224;
1965 MDFNGameInfo->fb_width = 384;
1966 MDFNGameInfo->fb_height = 224;
1967
1968 switch(VB3DMode)
1969 {
1970 default: break;
1971
1972 case VB3DMODE_VLI:
1973 MDFNGameInfo->nominal_width = 768 * prescale;
1974 MDFNGameInfo->nominal_height = 224;
1975 MDFNGameInfo->fb_width = 768 * prescale;
1976 MDFNGameInfo->fb_height = 224;
1977 break;
1978
1979 case VB3DMODE_HLI:
1980 MDFNGameInfo->nominal_width = 384;
1981 MDFNGameInfo->nominal_height = 448 * prescale;
1982 MDFNGameInfo->fb_width = 384;
1983 MDFNGameInfo->fb_height = 448 * prescale;
1984 break;
1985
1986 case VB3DMODE_CSCOPE:
1987 MDFNGameInfo->nominal_width = 512;
1988 MDFNGameInfo->nominal_height = 384;
1989 MDFNGameInfo->fb_width = 512;
1990 MDFNGameInfo->fb_height = 384;
1991 break;
1992
1993 case VB3DMODE_SIDEBYSIDE:
1994 MDFNGameInfo->nominal_width = 384 * 2 + sbs_separation;
1995 MDFNGameInfo->nominal_height = 224;
1996 MDFNGameInfo->fb_width = 384 * 2 + sbs_separation;
1997 MDFNGameInfo->fb_height = 224;
1998 break;
1999 }
2000 MDFNGameInfo->lcm_width = MDFNGameInfo->fb_width;
2001 MDFNGameInfo->lcm_height = MDFNGameInfo->fb_height;
2002
2003
2004 MDFNMP_Init(32768, ((uint64)1 << 27) / 32768);
2005 MDFNMP_AddRAM(65536, 5 << 24, WRAM);
2006 if((GPRAM_Mask + 1) >= 32768)
2007 MDFNMP_AddRAM(GPRAM_Mask + 1, 6 << 24, GPRAM);
2008 return(1);
2009 }
2010
CloseGame(void)2011 static void CloseGame(void)
2012 {
2013 //VIP_Kill();
2014
2015 if(VB_VSU)
2016 {
2017 delete VB_VSU;
2018 VB_VSU = NULL;
2019 }
2020
2021 /*
2022 if(GPRAM)
2023 {
2024 MDFN_free(GPRAM);
2025 GPRAM = NULL;
2026 }
2027
2028 if(GPROM)
2029 {
2030 MDFN_free(GPROM);
2031 GPROM = NULL;
2032 }
2033 */
2034
2035 if(VB_V810)
2036 {
2037 VB_V810->Kill();
2038 delete VB_V810;
2039 VB_V810 = NULL;
2040 }
2041 }
2042
VB_ExitLoop(void)2043 extern "C" void VB_ExitLoop(void)
2044 {
2045 VB_V810->Exit();
2046 }
2047
Emulate(EmulateSpecStruct * espec,int16_t * sound_buf)2048 static void Emulate(EmulateSpecStruct *espec, int16_t *sound_buf)
2049 {
2050 v810_timestamp_t v810_timestamp;
2051
2052 MDFNMP_ApplyPeriodicCheats();
2053
2054 VBINPUT_Frame();
2055
2056 if(espec->SoundFormatChanged)
2057 {
2058 for(int y = 0; y < 2; y++)
2059 {
2060 Blip_Buffer_set_sample_rate(&sbuf[y], espec->SoundRate ? espec->SoundRate : 44100, 50);
2061 Blip_Buffer_set_clock_rate(&sbuf[y], (long)(VB_MASTER_CLOCK / 4));
2062 Blip_Buffer_bass_freq(&sbuf[y], 20);
2063 }
2064 }
2065
2066 VIP_StartFrame(espec);
2067
2068 v810_timestamp = VB_V810->Run(EventHandler);
2069
2070 FixNonEvents();
2071 ForceEventUpdates(v810_timestamp);
2072
2073 VB_VSU->EndFrame((v810_timestamp + VSU_CycleFix) >> 2);
2074
2075 if(sound_buf)
2076 {
2077 for(int y = 0; y < 2; y++)
2078 {
2079 Blip_Buffer_end_frame(&sbuf[y], (v810_timestamp + VSU_CycleFix) >> 2);
2080 espec->SoundBufSize = Blip_Buffer_read_samples(&sbuf[y], sound_buf + y, espec->SoundBufMaxSize);
2081 }
2082 }
2083
2084 VSU_CycleFix = (v810_timestamp + VSU_CycleFix) & 3;
2085
2086 espec->MasterCycles = v810_timestamp;
2087
2088 TIMER_ResetTS();
2089 VBINPUT_ResetTS();
2090 VIP_ResetTS();
2091
2092 RebaseTS(v810_timestamp);
2093
2094 VB_V810->ResetTS(0);
2095 }
2096
2097 #ifdef WANT_DEBUGGER
2098 static DebuggerInfoStruct DBGInfo =
2099 {
2100 "shift_jis",
2101 4,
2102 2, // Instruction alignment(bytes)
2103 32,
2104 32,
2105 0x00000000,
2106 ~0U,
2107
2108 VBDBG_MemPeek,
2109 VBDBG_Disassemble,
2110 NULL,
2111 NULL, //ForceIRQ,
2112 NULL,
2113 VBDBG_FlushBreakPoints,
2114 VBDBG_AddBreakPoint,
2115 VBDBG_SetCPUCallback,
2116 VBDBG_EnableBranchTrace,
2117 VBDBG_GetBranchTrace,
2118 NULL, //KING_SetGraphicsDecode,
2119 VBDBG_SetLogFunc,
2120 };
2121 #endif
2122
StateAction(StateMem * sm,int load,int data_only)2123 extern "C" int StateAction(StateMem *sm, int load, int data_only)
2124 {
2125 const v810_timestamp_t timestamp = VB_V810->v810_timestamp;
2126 int ret = 1;
2127
2128 SFORMAT StateRegs[] =
2129 {
2130 SFARRAY(WRAM, 65536),
2131 SFARRAY(GPRAM, GPRAM_Mask ? (GPRAM_Mask + 1) : 0),
2132 SFVARN(WCR, "WCR"),
2133 SFVARN(IRQ_Asserted, "IRQ_Asserted"),
2134 SFVARN(VSU_CycleFix, "VSU_CycleFix"),
2135 SFEND
2136 };
2137
2138 ret &= MDFNSS_StateAction(sm, load, data_only, StateRegs, "MAIN", false);
2139
2140 ret &= VB_V810->StateAction(sm, load, data_only);
2141
2142 ret &= VB_VSU->StateAction(sm, load, data_only);
2143 ret &= TIMER_StateAction(sm, load, data_only);
2144 ret &= VBINPUT_StateAction(sm, load, data_only);
2145 ret &= VIP_StateAction(sm, load, data_only);
2146
2147 if(load)
2148 {
2149 // Needed to recalculate next_*_ts since we don't bother storing their deltas in save states.
2150 ForceEventUpdates(timestamp);
2151 }
2152 return(ret);
2153 }
2154
SetLayerEnableMask(uint64 mask)2155 static void SetLayerEnableMask(uint64 mask) { }
2156
DoSimpleCommand(int cmd)2157 static void DoSimpleCommand(int cmd)
2158 {
2159 switch(cmd)
2160 {
2161 case MDFN_MSC_POWER:
2162 case MDFN_MSC_RESET:
2163 VB_Power();
2164 break;
2165 }
2166 }
2167
2168 static const InputDeviceInputInfoStruct IDII[] =
2169 {
2170 { "a", "A", 7, IDIT_BUTTON_CAN_RAPID, NULL },
2171 { "b", "B", 6, IDIT_BUTTON_CAN_RAPID, NULL },
2172 { "rt", "Right-Back", 13, IDIT_BUTTON, NULL },
2173 { "lt", "Left-Back", 12, IDIT_BUTTON, NULL },
2174
2175 { "up-r", "UP ↑ (Right D-Pad)", 8, IDIT_BUTTON, "down-r" },
2176 { "right-r", "RIGHT → (Right D-Pad)", 11, IDIT_BUTTON, "left-r" },
2177
2178 { "right-l", "RIGHT → (Left D-Pad)", 3, IDIT_BUTTON, "left-l" },
2179 { "left-l", "LEFT ← (Left D-Pad)", 2, IDIT_BUTTON, "right-l" },
2180 { "down-l", "DOWN ↓ (Left D-Pad)", 1, IDIT_BUTTON, "up-l" },
2181 { "up-l", "UP ↑ (Left D-Pad)", 0, IDIT_BUTTON, "down-l" },
2182
2183 { "start", "Start", 5, IDIT_BUTTON, NULL },
2184 { "select", "Select", 4, IDIT_BUTTON, NULL },
2185
2186 { "left-r", "LEFT ← (Right D-Pad)", 10, IDIT_BUTTON, "right-r" },
2187 { "down-r", "DOWN ↓ (Right D-Pad)", 9, IDIT_BUTTON, "up-r" },
2188 };
2189
2190 static InputDeviceInfoStruct InputDeviceInfo[] =
2191 {
2192 {
2193 "gamepad",
2194 "Gamepad",
2195 NULL,
2196 NULL,
2197 sizeof(IDII) / sizeof(InputDeviceInputInfoStruct),
2198 IDII,
2199 }
2200 };
2201
2202 static const InputPortInfoStruct PortInfo[] =
2203 {
2204 { "builtin", "Built-In", sizeof(InputDeviceInfo) / sizeof(InputDeviceInfoStruct), InputDeviceInfo, "gamepad" }
2205 };
2206
2207 static InputInfoStruct InputInfo =
2208 {
2209 sizeof(PortInfo) / sizeof(InputPortInfoStruct),
2210 PortInfo
2211 };
2212
MDFNI_LoadGame(const uint8_t * data,size_t size)2213 static bool MDFNI_LoadGame(const uint8_t *data, size_t size)
2214 {
2215 MDFNGameInfo = &EmulatedVB;
2216
2217 if(Load(data, size) <= 0)
2218 goto error;
2219
2220 MDFN_LoadGameCheats(NULL);
2221 MDFNMP_InstallReadPatches();
2222
2223 return true;
2224
2225 error:
2226 MDFNGameInfo = NULL;
2227 return false;
2228 }
2229
MDFNI_CloseGame(void)2230 static void MDFNI_CloseGame(void)
2231 {
2232 if(!MDFNGameInfo)
2233 return;
2234
2235 MDFN_FlushGameCheats(0);
2236
2237 CloseGame();
2238
2239 MDFNMP_Kill();
2240
2241 MDFNGameInfo = NULL;
2242 }
2243
2244 static void hookup_ports(bool force);
2245
2246 static bool initial_ports_hookup = false;
2247
2248 #define MEDNAFEN_CORE_NAME_MODULE "vb"
2249 #define MEDNAFEN_CORE_NAME "Beetle VB"
2250 #define MEDNAFEN_CORE_VERSION "v0.9.36.1"
2251 #define MEDNAFEN_CORE_EXTENSIONS "vb|vboy|bin"
2252 #define MEDNAFEN_CORE_TIMING_FPS 50.27
2253 #define MEDNAFEN_CORE_GEOMETRY_BASE_W (EmulatedVB.nominal_width)
2254 #define MEDNAFEN_CORE_GEOMETRY_BASE_H (EmulatedVB.nominal_height)
2255 #define MEDNAFEN_CORE_GEOMETRY_MAX_W 384 * 2
2256 #define MEDNAFEN_CORE_GEOMETRY_MAX_H 224 * 2
2257 #define MEDNAFEN_CORE_GEOMETRY_ASPECT_RATIO (12.0 / 7.0)
2258 #define FB_WIDTH 384 * 2
2259 #define FB_HEIGHT 224 * 2
2260
2261
2262 #define FB_MAX_HEIGHT FB_HEIGHT
2263
2264 const char *mednafen_core_str = MEDNAFEN_CORE_NAME;
2265
check_system_specs(void)2266 static void check_system_specs(void)
2267 {
2268 unsigned level = 0;
2269 environ_cb(RETRO_ENVIRONMENT_SET_PERFORMANCE_LEVEL, &level);
2270 }
2271
retro_init(void)2272 void retro_init(void)
2273 {
2274 struct retro_log_callback log;
2275 #if defined(WANT_16BPP) && defined(FRONTEND_SUPPORTS_RGB565)
2276 enum retro_pixel_format rgb565 = RETRO_PIXEL_FORMAT_RGB565;
2277 #endif
2278 if (environ_cb(RETRO_ENVIRONMENT_GET_LOG_INTERFACE, &log))
2279 log_cb = log.log;
2280 else
2281 log_cb = NULL;
2282
2283 #if defined(WANT_16BPP) && defined(FRONTEND_SUPPORTS_RGB565)
2284 if (environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &rgb565) && log_cb)
2285 log_cb(RETRO_LOG_INFO, "Frontend supports RGB565 - will use that instead of XRGB1555.\n");
2286 #endif
2287
2288 if (environ_cb(RETRO_ENVIRONMENT_GET_PERF_INTERFACE, &perf_cb))
2289 perf_get_cpu_features_cb = perf_cb.get_cpu_features;
2290 else
2291 perf_get_cpu_features_cb = NULL;
2292
2293 check_system_specs();
2294
2295 if (environ_cb(RETRO_ENVIRONMENT_GET_INPUT_BITMASKS, NULL))
2296 libretro_supports_bitmasks = true;
2297 }
2298
retro_reset(void)2299 void retro_reset(void)
2300 {
2301 DoSimpleCommand(MDFN_MSC_RESET);
2302 }
2303
retro_load_game_special(unsigned,const struct retro_game_info *,size_t)2304 bool retro_load_game_special(unsigned, const struct retro_game_info *, size_t)
2305 {
2306 return false;
2307 }
2308
set_volume(uint32_t * ptr,unsigned number)2309 static void set_volume (uint32_t *ptr, unsigned number)
2310 {
2311 switch(number)
2312 {
2313 default:
2314 *ptr = number;
2315 break;
2316 }
2317 }
2318
check_variables(void)2319 static void check_variables(void)
2320 {
2321 struct retro_variable var = {0};
2322
2323 var.key = "vb_3dmode";
2324
2325 if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
2326 {
2327 unsigned old_3dmode = setting_vb_3dmode;
2328
2329 if (strcmp(var.value, "anaglyph") == 0)
2330 setting_vb_3dmode = VB3DMODE_ANAGLYPH;
2331 else if (strcmp(var.value, "cyberscope") == 0)
2332 setting_vb_3dmode = VB3DMODE_CSCOPE;
2333 else if (strcmp(var.value, "side-by-side") == 0)
2334 setting_vb_3dmode = VB3DMODE_SIDEBYSIDE;
2335 else if (strcmp(var.value, "vli") == 0)
2336 setting_vb_3dmode = VB3DMODE_VLI;
2337 else if (strcmp(var.value, "hli") == 0)
2338 setting_vb_3dmode = VB3DMODE_HLI;
2339
2340 if (old_3dmode != setting_vb_3dmode)
2341 {
2342 SettingChanged("vb.3dmode");
2343
2344 log_cb(RETRO_LOG_INFO, "[%s]: 3D mode changed: %s .\n", mednafen_core_str, var.value);
2345 }
2346 }
2347
2348 var.key = "vb_anaglyph_preset";
2349
2350 if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
2351 {
2352 unsigned old_preset = setting_vb_anaglyph_preset;
2353
2354 if (strcmp(var.value, "disabled") == 0)
2355 setting_vb_anaglyph_preset = 0;
2356 else if (strcmp(var.value, "red & blue") == 0)
2357 setting_vb_anaglyph_preset = 1;
2358 else if (strcmp(var.value, "red & cyan") == 0)
2359 setting_vb_anaglyph_preset = 2;
2360 else if (strcmp(var.value, "red & electric cyan") == 0)
2361 setting_vb_anaglyph_preset = 3;
2362 else if (strcmp(var.value, "red & green") == 0)
2363 setting_vb_anaglyph_preset = 4;
2364 else if (strcmp(var.value, "green & magenta") == 0)
2365 setting_vb_anaglyph_preset = 5;
2366 else if (strcmp(var.value, "yellow & blue") == 0)
2367 setting_vb_anaglyph_preset = 6;
2368
2369 if (old_preset != setting_vb_anaglyph_preset)
2370 {
2371 SettingChanged("vb.anaglyph.preset");
2372
2373 log_cb(RETRO_LOG_INFO, "[%s]: Palette changed: %s .\n", mednafen_core_str, var.value);
2374 }
2375 }
2376
2377 var.key = "vb_color_mode";
2378
2379 if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
2380 {
2381 unsigned old_color = setting_vb_default_color;
2382
2383 if (strcmp(var.value, "black & red") == 0)
2384 {
2385 setting_vb_lcolor = 0xFF0000;
2386 setting_vb_rcolor = 0x000000;
2387 }
2388 else if (strcmp(var.value, "black & white") == 0)
2389 {
2390 setting_vb_lcolor = 0xFFFFFF;
2391 setting_vb_rcolor = 0x000000;
2392 }
2393 else if (strcmp(var.value, "black & blue") == 0)
2394 {
2395 setting_vb_lcolor = 0x0000FF;
2396 setting_vb_rcolor = 0x000000;
2397 }
2398 else if (strcmp(var.value, "black & cyan") == 0)
2399 {
2400 setting_vb_lcolor = 0x00B7EB;
2401 setting_vb_rcolor = 0x000000;
2402 }
2403 else if (strcmp(var.value, "black & electric cyan") == 0)
2404 {
2405 setting_vb_lcolor = 0x00FFFF;
2406 setting_vb_rcolor = 0x000000;
2407 }
2408 else if (strcmp(var.value, "black & green") == 0)
2409 {
2410 setting_vb_lcolor = 0x00FF00;
2411 setting_vb_rcolor = 0x000000;
2412 }
2413 else if (strcmp(var.value, "black & magenta") == 0)
2414 {
2415 setting_vb_lcolor = 0xFF00FF;
2416 setting_vb_rcolor = 0x000000;
2417 }
2418 else if (strcmp(var.value, "black & yellow") == 0)
2419 {
2420 setting_vb_lcolor = 0xFFFF00;
2421 setting_vb_rcolor = 0x000000;
2422 }
2423 setting_vb_default_color = setting_vb_lcolor;
2424
2425 if (old_color != setting_vb_default_color)
2426 {
2427 SettingChanged("vb.default_color");
2428
2429 log_cb(RETRO_LOG_INFO, "[%s]: Palette changed: %s .\n", mednafen_core_str, var.value);
2430 }
2431 }
2432
2433 var.key = "vb_right_analog_to_digital";
2434
2435 if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
2436 {
2437 if (strcmp(var.value, "disabled") == 0)
2438 setting_vb_right_analog_to_digital = false;
2439 else if (strcmp(var.value, "enabled") == 0)
2440 {
2441 setting_vb_right_analog_to_digital = true;
2442 setting_vb_right_invert_x = false;
2443 setting_vb_right_invert_y = false;
2444 }
2445 else if (strcmp(var.value, "invert x") == 0)
2446 {
2447 setting_vb_right_analog_to_digital = true;
2448 setting_vb_right_invert_x = true;
2449 setting_vb_right_invert_y = false;
2450 }
2451 else if (strcmp(var.value, "invert y") == 0)
2452 {
2453 setting_vb_right_analog_to_digital = true;
2454 setting_vb_right_invert_x = false;
2455 setting_vb_right_invert_y = true;
2456 }
2457 else if (strcmp(var.value, "invert both") == 0)
2458 {
2459 setting_vb_right_analog_to_digital = true;
2460 setting_vb_right_invert_x = true;
2461 setting_vb_right_invert_y = true;
2462 }
2463 else
2464 setting_vb_right_analog_to_digital = false;
2465 }
2466
2467 var.key = "vb_cpu_emulation";
2468
2469 if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
2470 {
2471 setting_vb_cpu_emulation = !strcmp(var.value, "accurate")
2472 ? V810_EMU_MODE_ACCURATE
2473 : V810_EMU_MODE_FAST;
2474 }
2475 }
2476
2477 #define MAX_PLAYERS 1
2478 #define MAX_BUTTONS 14
2479 static uint16_t input_buf[MAX_PLAYERS];
2480
hookup_ports(bool force)2481 static void hookup_ports(bool force)
2482 {
2483 if (initial_ports_hookup && !force)
2484 return;
2485
2486 /* Possible endian bug ... */
2487 VBINPUT_SetInput(0, "gamepad", &input_buf[0]);
2488
2489 initial_ports_hookup = true;
2490 }
2491
retro_load_game(const struct retro_game_info * info)2492 bool retro_load_game(const struct retro_game_info *info)
2493 {
2494 void *rpix = NULL;
2495 if (!info)
2496 return false;
2497
2498 static struct retro_input_descriptor desc[] = {
2499 { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "Left D-Pad Left" },
2500 { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "Left D-Pad Up" },
2501 { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "Left D-Pad Down" },
2502 { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "Left D-Pad Right" },
2503 { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "B" },
2504 { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "A" },
2505 { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "L" },
2506 { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "R" },
2507 { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R2, "Right D-Pad Left" },
2508 { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L2, "Right D-Pad Up" },
2509 { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L3, "Right D-Pad Down" },
2510 { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3, "Right D-Pad Right" },
2511 { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Select" },
2512 { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" },
2513
2514 { 0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X, "Right D-Pad X" },
2515 { 0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y, "Right D-Pad Y" },
2516 { 0 },
2517 };
2518
2519 environ_cb(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, desc);
2520
2521 #ifdef WANT_32BPP
2522 enum retro_pixel_format fmt = RETRO_PIXEL_FORMAT_XRGB8888;
2523 if (!environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &fmt))
2524 {
2525 if (log_cb)
2526 log_cb(RETRO_LOG_ERROR, "Pixel format XRGB8888 not supported by platform, cannot use %s.\n", MEDNAFEN_CORE_NAME);
2527 return false;
2528 }
2529 #endif
2530
2531 overscan = false;
2532 environ_cb(RETRO_ENVIRONMENT_GET_OVERSCAN, &overscan);
2533
2534 check_variables();
2535
2536 if (!MDFNI_LoadGame((const uint8_t*)info->data, info->size))
2537 return false;
2538
2539 struct MDFN_PixelFormat pix_fmt;
2540 #ifdef WANT_16BPP
2541 pix_fmt.bpp = 16;
2542 #else
2543 pix_fmt.bpp = 32;
2544 #endif
2545 pix_fmt.colorspace = MDFN_COLORSPACE_RGB;
2546 pix_fmt.Rshift = 16;
2547 pix_fmt.Gshift = 8;
2548 pix_fmt.Bshift = 0;
2549 pix_fmt.Ashift = 24;
2550
2551 last_pixel_format.bpp = 0;
2552 last_pixel_format.colorspace = 0;
2553 last_pixel_format.Rshift = 0;
2554 last_pixel_format.Gshift = 0;
2555 last_pixel_format.Bshift = 0;
2556 last_pixel_format.Ashift = 0;
2557
2558 surf.format = pix_fmt;
2559 surf.pixels16 = NULL;
2560 surf.pixels = NULL;
2561
2562 if(!(rpix = calloc(1, FB_WIDTH * FB_HEIGHT * (pix_fmt.bpp / 8))))
2563 return false;
2564
2565 #if defined(WANT_16BPP)
2566 surf.pixels16 = (uint16 *)rpix;
2567 #elif defined(WANT_32BPP)
2568 surf.pixels = (uint32 *)rpix;
2569 #endif
2570 surf.w = FB_WIDTH;
2571 surf.h = FB_HEIGHT;
2572 surf.pitchinpix = FB_WIDTH;
2573
2574 hookup_ports(true);
2575
2576 check_variables();
2577
2578 return true;
2579 }
2580
retro_unload_game(void)2581 void retro_unload_game(void)
2582 {
2583 MDFNI_CloseGame();
2584 }
2585
update_input(void)2586 static void update_input(void)
2587 {
2588 unsigned i,j;
2589 int16_t joy_bits[MAX_PLAYERS] = {0};
2590
2591 input_buf[0] = 0;
2592
2593 static unsigned map[] = {
2594 RETRO_DEVICE_ID_JOYPAD_A,
2595 RETRO_DEVICE_ID_JOYPAD_B,
2596 RETRO_DEVICE_ID_JOYPAD_R,
2597 RETRO_DEVICE_ID_JOYPAD_L,
2598 RETRO_DEVICE_ID_JOYPAD_L2, //right d-pad UP
2599 RETRO_DEVICE_ID_JOYPAD_R3, //right d-pad RIGHT
2600 RETRO_DEVICE_ID_JOYPAD_RIGHT, //left d-pad
2601 RETRO_DEVICE_ID_JOYPAD_LEFT, //left d-pad
2602 RETRO_DEVICE_ID_JOYPAD_DOWN, //left d-pad
2603 RETRO_DEVICE_ID_JOYPAD_UP, //left d-pad
2604 RETRO_DEVICE_ID_JOYPAD_START,
2605 RETRO_DEVICE_ID_JOYPAD_SELECT,
2606 RETRO_DEVICE_ID_JOYPAD_R2, //right d-pad LEFT
2607 RETRO_DEVICE_ID_JOYPAD_L3, //right d-pad DOWN
2608 };
2609
2610 for (j = 0; j < MAX_PLAYERS; j++)
2611 {
2612 if (libretro_supports_bitmasks)
2613 joy_bits[j] = input_state_cb(j, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_MASK);
2614 else
2615 {
2616 for (i = 0; i < (RETRO_DEVICE_ID_JOYPAD_R3+1); i++)
2617 joy_bits[j] |= input_state_cb(j, RETRO_DEVICE_JOYPAD, 0, i) ? (1 << i) : 0;
2618 }
2619 }
2620
2621 for (j = 0; j < MAX_PLAYERS; j++)
2622 {
2623 for (i = 0; i < MAX_BUTTONS; i++)
2624 input_buf[j] |= (map[i] != -1u) && (joy_bits[j] & (1 << map[i])) ? (1 << i) : 0;
2625
2626 if (setting_vb_right_analog_to_digital) {
2627 int16_t analog_x = input_state_cb(j, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X);
2628 int16_t analog_y = input_state_cb(j, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y);
2629
2630 if (abs(analog_x) > STICK_DEADZONE)
2631 input_buf[j] |= (analog_x < 0) ^ !setting_vb_right_invert_x ? RIGHT_DPAD_RIGHT : RIGHT_DPAD_LEFT;
2632 if (abs(analog_y) > STICK_DEADZONE)
2633 input_buf[j] |= (analog_y < 0) ^ !setting_vb_right_invert_y ? RIGHT_DPAD_DOWN : RIGHT_DPAD_UP;
2634 }
2635
2636 #ifdef MSB_FIRST
2637 union {
2638 uint8_t b[2];
2639 uint16_t s;
2640 } u;
2641 u.s = input_buf[j];
2642 input_buf[j] = u.b[0] | u.b[1] << 8;
2643 #endif
2644 }
2645 }
2646
update_geometry(unsigned width,unsigned height)2647 static void update_geometry(unsigned width, unsigned height)
2648 {
2649 struct retro_system_av_info info;
2650
2651 memset(&info, 0, sizeof(info));
2652 info.timing.fps = MEDNAFEN_CORE_TIMING_FPS;
2653 info.timing.sample_rate = 44100;
2654 info.geometry.base_width = width;
2655 info.geometry.base_height = height;
2656 info.geometry.max_width = MEDNAFEN_CORE_GEOMETRY_MAX_W;
2657 info.geometry.max_height = MEDNAFEN_CORE_GEOMETRY_MAX_H;
2658 info.geometry.aspect_ratio = (float) width / (float) height;
2659
2660 environ_cb(RETRO_ENVIRONMENT_SET_GEOMETRY, &info);
2661 }
2662
2663 static uint64_t video_frames, audio_frames;
2664
retro_run(void)2665 void retro_run(void)
2666 {
2667 input_poll_cb();
2668
2669 update_input();
2670
2671 static int16_t sound_buf[0x10000];
2672 static MDFN_Rect rects[FB_MAX_HEIGHT];
2673 static unsigned width = 0, height = 0;
2674 bool resolution_changed = false;
2675 rects[0].w = ~0;
2676
2677 EmulateSpecStruct spec = {0};
2678 spec.surface = &surf;
2679 spec.SoundRate = 44100;
2680 spec.LineWidths = rects;
2681 spec.SoundBufMaxSize = sizeof(sound_buf) / 2;
2682 spec.SoundBufSize = 0;
2683 spec.VideoFormatChanged = false;
2684 spec.SoundFormatChanged = false;
2685
2686 if (memcmp(&last_pixel_format, &spec.surface->format, sizeof(struct MDFN_PixelFormat)))
2687 {
2688 spec.VideoFormatChanged = true;
2689
2690 last_pixel_format = spec.surface->format;
2691 }
2692
2693 if (spec.SoundRate != last_sound_rate)
2694 {
2695 spec.SoundFormatChanged = true;
2696 last_sound_rate = spec.SoundRate;
2697 }
2698
2699 Emulate(&spec, sound_buf);
2700
2701 int16 *const SoundBuf = sound_buf + spec.SoundBufSizeALMS * EmulatedVB.soundchan;
2702 int32 SoundBufSize = spec.SoundBufSize - spec.SoundBufSizeALMS;
2703 const int32 SoundBufMaxSize = spec.SoundBufMaxSize - spec.SoundBufSizeALMS;
2704
2705 spec.SoundBufSize = spec.SoundBufSizeALMS + SoundBufSize;
2706
2707 if (width != spec.DisplayRect.w || height != spec.DisplayRect.h)
2708 resolution_changed = true;
2709
2710 width = spec.DisplayRect.w;
2711 height = spec.DisplayRect.h;
2712
2713 #if defined(WANT_32BPP)
2714 const uint32_t *pix = surf.pixels;
2715 video_cb(pix, width, height, FB_WIDTH << 2);
2716 #elif defined(WANT_16BPP)
2717 const uint16_t *pix = surf.pixels16;
2718 video_cb(pix, width, height, FB_WIDTH << 1);
2719 #endif
2720
2721 video_frames++;
2722 audio_frames += spec.SoundBufSize;
2723
2724 audio_batch_cb(sound_buf, spec.SoundBufSize);
2725
2726 bool updated = false;
2727 if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated)
2728 check_variables();
2729
2730 if (resolution_changed)
2731 update_geometry(width, height);
2732 }
2733
retro_get_system_info(struct retro_system_info * info)2734 void retro_get_system_info(struct retro_system_info *info)
2735 {
2736 memset(info, 0, sizeof(*info));
2737 info->library_name = MEDNAFEN_CORE_NAME;
2738 #ifndef GIT_VERSION
2739 #define GIT_VERSION ""
2740 #endif
2741 info->library_version = MEDNAFEN_CORE_VERSION GIT_VERSION;
2742 info->need_fullpath = false;
2743 info->valid_extensions = MEDNAFEN_CORE_EXTENSIONS;
2744 info->block_extract = false;
2745 }
2746
retro_get_system_av_info(struct retro_system_av_info * info)2747 void retro_get_system_av_info(struct retro_system_av_info *info)
2748 {
2749 memset(info, 0, sizeof(*info));
2750 info->timing.fps = MEDNAFEN_CORE_TIMING_FPS;
2751 info->timing.sample_rate = 44100;
2752 info->geometry.base_width = MEDNAFEN_CORE_GEOMETRY_BASE_W;
2753 info->geometry.base_height = MEDNAFEN_CORE_GEOMETRY_BASE_H;
2754 info->geometry.max_width = MEDNAFEN_CORE_GEOMETRY_MAX_W;
2755 info->geometry.max_height = MEDNAFEN_CORE_GEOMETRY_MAX_H;
2756 info->geometry.aspect_ratio = MEDNAFEN_CORE_GEOMETRY_ASPECT_RATIO;
2757 }
2758
retro_deinit(void)2759 void retro_deinit(void)
2760 {
2761 #if defined(WANT_16BPP)
2762 if(surf.pixels16)
2763 free(surf.pixels16);
2764 #elif defined(WANT_32BPP)
2765 if(surf.pixels)
2766 free(surf.pixels);
2767 #endif
2768 surf.pixels8 = NULL;
2769 surf.pixels16 = NULL;
2770 surf.pixels = NULL;
2771 surf.w = 0;
2772 surf.h = 0;
2773 surf.pitchinpix = 0;
2774 surf.format.bpp = 0;
2775 surf.format.colorspace = 0;
2776 surf.format.Rshift = 0;
2777 surf.format.Gshift = 0;
2778 surf.format.Bshift = 0;
2779 surf.format.Ashift = 0;
2780
2781 if (log_cb)
2782 {
2783 log_cb(RETRO_LOG_INFO, "[%s]: Samples / Frame: %.5f\n",
2784 mednafen_core_str, (double)audio_frames / video_frames);
2785 log_cb(RETRO_LOG_INFO, "[%s]: Estimated FPS: %.5f\n",
2786 mednafen_core_str, (double)video_frames * 44100 / audio_frames);
2787 }
2788
2789 libretro_supports_bitmasks = false;
2790 }
2791
retro_get_region(void)2792 unsigned retro_get_region(void)
2793 {
2794 return RETRO_REGION_NTSC; // FIXME: Regions for other cores.
2795 }
2796
retro_api_version(void)2797 unsigned retro_api_version(void)
2798 {
2799 return RETRO_API_VERSION;
2800 }
2801
retro_set_controller_port_device(unsigned in_port,unsigned device)2802 void retro_set_controller_port_device(unsigned in_port, unsigned device) { }
2803
retro_set_environment(retro_environment_t cb)2804 void retro_set_environment(retro_environment_t cb)
2805 {
2806 environ_cb = cb;
2807 libretro_set_core_options(environ_cb);
2808 }
2809
retro_set_audio_sample(retro_audio_sample_t cb)2810 void retro_set_audio_sample(retro_audio_sample_t cb)
2811 {
2812 audio_cb = cb;
2813 }
2814
retro_set_audio_sample_batch(retro_audio_sample_batch_t cb)2815 void retro_set_audio_sample_batch(retro_audio_sample_batch_t cb)
2816 {
2817 audio_batch_cb = cb;
2818 }
2819
retro_set_input_poll(retro_input_poll_t cb)2820 void retro_set_input_poll(retro_input_poll_t cb)
2821 {
2822 input_poll_cb = cb;
2823 }
2824
retro_set_input_state(retro_input_state_t cb)2825 void retro_set_input_state(retro_input_state_t cb)
2826 {
2827 input_state_cb = cb;
2828 }
2829
retro_set_video_refresh(retro_video_refresh_t cb)2830 void retro_set_video_refresh(retro_video_refresh_t cb)
2831 {
2832 video_cb = cb;
2833 }
2834
retro_serialize_size(void)2835 size_t retro_serialize_size(void)
2836 {
2837 StateMem st;
2838
2839 st.data = NULL;
2840 st.loc = 0;
2841 st.len = 0;
2842 st.malloced = 0;
2843 st.initial_malloc = 0;
2844
2845 if (!MDFNSS_SaveSM(&st, 0, 0, NULL, NULL, NULL))
2846 return 0;
2847
2848 free(st.data);
2849 return st.len;
2850 }
2851
retro_serialize(void * data,size_t size)2852 bool retro_serialize(void *data, size_t size)
2853 {
2854 StateMem st;
2855 bool ret = false;
2856 uint8_t *_dat = (uint8_t*)malloc(size);
2857
2858 if (!_dat)
2859 return false;
2860
2861 /* Mednafen can realloc the buffer so we need to ensure this is safe. */
2862 st.data = _dat;
2863 st.loc = 0;
2864 st.len = 0;
2865 st.malloced = size;
2866 st.initial_malloc = 0;
2867
2868 ret = MDFNSS_SaveSM(&st, 0, 0, NULL, NULL, NULL);
2869
2870 memcpy(data, st.data, size);
2871 free(st.data);
2872
2873 return ret;
2874 }
2875
retro_unserialize(const void * data,size_t size)2876 bool retro_unserialize(const void *data, size_t size)
2877 {
2878 StateMem st;
2879
2880 st.data = (uint8_t*)data;
2881 st.loc = 0;
2882 st.len = size;
2883 st.malloced = 0;
2884 st.initial_malloc = 0;
2885
2886 return MDFNSS_LoadSM(&st, 0, 0);
2887 }
2888
retro_get_memory_data(unsigned type)2889 void *retro_get_memory_data(unsigned type)
2890 {
2891 switch(type)
2892 {
2893 case RETRO_MEMORY_SYSTEM_RAM:
2894 return WRAM;
2895 case RETRO_MEMORY_SAVE_RAM:
2896 return GPRAM;
2897 default:
2898 break;
2899 }
2900
2901 return NULL;
2902 }
2903
retro_get_memory_size(unsigned type)2904 size_t retro_get_memory_size(unsigned type)
2905 {
2906 switch(type)
2907 {
2908 case RETRO_MEMORY_SYSTEM_RAM:
2909 return 0x10000;
2910 case RETRO_MEMORY_SAVE_RAM:
2911 return GPRAM_Mask + 1;
2912 default:
2913 break;
2914 }
2915
2916 return 0;
2917 }
2918
retro_cheat_reset(void)2919 void retro_cheat_reset(void) { }
retro_cheat_set(unsigned,bool,const char *)2920 void retro_cheat_set(unsigned, bool, const char *) { }
2921
MDFND_DispMessage(unsigned char * str)2922 void MDFND_DispMessage(unsigned char *str)
2923 {
2924 if (log_cb)
2925 log_cb(RETRO_LOG_INFO, "%s\n", str);
2926 }
2927
MDFND_MidSync(const EmulateSpecStruct *)2928 void MDFND_MidSync(const EmulateSpecStruct *) { }
2929
MDFN_MidLineUpdate(EmulateSpecStruct * espec,int y)2930 void MDFN_MidLineUpdate(EmulateSpecStruct *espec, int y) { }
2931
MDFND_PrintError(const char * err)2932 void MDFND_PrintError(const char* err)
2933 {
2934 if (log_cb)
2935 log_cb(RETRO_LOG_ERROR, "%s\n", err);
2936 }
2937