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 &timestamp, 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 &timestamp, 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 &timestamp, 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 &timestamp, 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 &timestamp, 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 &timestamp, 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