Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/genplus-gx32/libretro/libretro.c
2 views
1
#ifndef _MSC_VER
2
#include <stdbool.h>
3
#endif
4
#include <stddef.h>
5
#include <stdarg.h>
6
#include <stdio.h>
7
8
#ifdef _MSC_VER
9
#define snprintf _snprintf
10
#endif
11
12
#ifdef _XBOX1
13
#include <xtl.h>
14
#endif
15
16
#include "shared.h"
17
#include "libretro.h"
18
#include "state.h"
19
#include "genesis.h"
20
#include "md_ntsc.h"
21
#include "sms_ntsc.h"
22
23
sms_ntsc_t *sms_ntsc;
24
md_ntsc_t *md_ntsc;
25
26
char GG_ROM[256];
27
char AR_ROM[256];
28
char SK_ROM[256];
29
char SK_UPMEM[256];
30
char GG_BIOS[256];
31
char MS_BIOS_EU[256];
32
char MS_BIOS_JP[256];
33
char MS_BIOS_US[256];
34
char CD_BIOS_EU[256];
35
char CD_BIOS_US[256];
36
char CD_BIOS_JP[256];
37
char CD_BRAM_JP[256];
38
char CD_BRAM_US[256];
39
char CD_BRAM_EU[256];
40
char CART_BRAM[256];
41
42
static int vwidth;
43
static int vheight;
44
45
static uint32_t brm_crc[2];
46
static uint8_t brm_format[0x40] =
47
{
48
0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x00,0x00,0x00,0x00,0x40,
49
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
50
0x53,0x45,0x47,0x41,0x5f,0x43,0x44,0x5f,0x52,0x4f,0x4d,0x00,0x01,0x00,0x00,0x00,
51
0x52,0x41,0x4d,0x5f,0x43,0x41,0x52,0x54,0x52,0x49,0x44,0x47,0x45,0x5f,0x5f,0x5f
52
};
53
54
static uint8_t temp[0x10000];
55
static int16 soundbuffer[3068];
56
static uint16_t bitmap_data_[1024 * 512];
57
static const double pal_fps = 53203424.0 / (3420.0 * 313.0);
58
static const double ntsc_fps = 53693175.0 / (3420.0 * 262.0);
59
60
static char g_rom_dir[1024];
61
62
static retro_video_refresh_t video_cb;
63
static retro_input_poll_t input_poll_cb;
64
static retro_input_state_t input_state_cb;
65
static retro_environment_t environ_cb;
66
static retro_audio_sample_batch_t audio_cb;
67
68
/************************************
69
* Genesis Plus GX implementation
70
************************************/
71
#define CHUNKSIZE (0x10000)
72
73
void error(char * msg, ...)
74
{
75
#ifndef _XBOX1
76
va_list ap;
77
va_start(ap, msg);
78
vfprintf(stderr, msg, ap);
79
va_end(ap);
80
#endif
81
}
82
83
int load_archive(char *filename, unsigned char *buffer, int maxsize, char *extension)
84
{
85
int size, left;
86
87
/* Open file */
88
FILE *fd = fopen(filename, "rb");
89
90
if (!fd)
91
{
92
/* Master System & Game Gear BIOS are optional files */
93
if (!strcmp(filename,MS_BIOS_US) || !strcmp(filename,MS_BIOS_EU) || !strcmp(filename,MS_BIOS_JP) || !strcmp(filename,GG_BIOS))
94
{
95
return 0;
96
}
97
98
/* Mega CD BIOS are required files */
99
if (!strcmp(filename,CD_BIOS_US) || !strcmp(filename,CD_BIOS_EU) || !strcmp(filename,CD_BIOS_JP))
100
{
101
fprintf(stderr, "ERROR - Unable to open CD BIOS: %s.\n", filename);
102
return 0;
103
}
104
105
fprintf(stderr, "ERROR - Unable to open file.\n");
106
return 0;
107
}
108
109
/* Get file size */
110
fseek(fd, 0, SEEK_END);
111
size = ftell(fd);
112
113
/* size limit */
114
if(size > maxsize)
115
{
116
fclose(fd);
117
fprintf(stderr, "ERROR - File is too large.\n");
118
return 0;
119
}
120
121
fprintf(stderr, "INFORMATION - Loading %d bytes ...\n", size);
122
123
/* filename extension */
124
if (extension)
125
{
126
memcpy(extension, &filename[strlen(filename) - 3], 3);
127
extension[3] = 0;
128
}
129
130
/* Read into buffer */
131
left = size;
132
fseek(fd, 0, SEEK_SET);
133
while (left > CHUNKSIZE)
134
{
135
fread(buffer, CHUNKSIZE, 1, fd);
136
buffer += CHUNKSIZE;
137
left -= CHUNKSIZE;
138
}
139
140
/* Read remaining bytes */
141
fread(buffer, left, 1, fd);
142
143
/* Close file */
144
fclose(fd);
145
146
/* Return loaded ROM size */
147
return size;
148
}
149
150
void osd_input_update(void)
151
{
152
int i, padnum = 0;
153
unsigned int temp;
154
155
input_poll_cb();
156
157
for(i = 0; i < MAX_INPUTS; i++)
158
{
159
temp = 0;
160
switch (input.dev[i])
161
{
162
case DEVICE_PAD6B:
163
{
164
if (input_state_cb(padnum, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L))
165
temp |= INPUT_X;
166
if (input_state_cb(padnum, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X))
167
temp |= INPUT_Y;
168
if (input_state_cb(padnum, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R))
169
temp |= INPUT_Z;
170
if (input_state_cb(padnum, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT))
171
temp |= INPUT_MODE;
172
}
173
174
case DEVICE_PAD3B:
175
{
176
if (input_state_cb(padnum, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y))
177
temp |= INPUT_A;
178
}
179
180
case DEVICE_PAD2B:
181
{
182
if (input_state_cb(padnum, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B))
183
temp |= INPUT_B;
184
if (input_state_cb(padnum, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A))
185
temp |= INPUT_C;
186
if (input_state_cb(padnum, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START))
187
temp |= INPUT_START;
188
if (input_state_cb(padnum, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP))
189
temp |= INPUT_UP;
190
if (input_state_cb(padnum, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN))
191
temp |= INPUT_DOWN;
192
if (input_state_cb(padnum, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT))
193
temp |= INPUT_LEFT;
194
if (input_state_cb(padnum, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT))
195
temp |= INPUT_RIGHT;
196
197
padnum++;
198
break;
199
}
200
201
default:
202
break;
203
}
204
205
input.pad[i] = temp;
206
}
207
}
208
209
static void init_bitmap(void)
210
{
211
memset(&bitmap, 0, sizeof(bitmap));
212
bitmap.width = 1024;
213
bitmap.height = 512;
214
bitmap.pitch = 1024 * 2;
215
bitmap.data = (uint8_t *)bitmap_data_;
216
bitmap.viewport.w = 0;
217
bitmap.viewport.h = 0;
218
bitmap.viewport.x = 0;
219
bitmap.viewport.y = 0;
220
}
221
222
static void config_default(void)
223
{
224
int i;
225
226
/* sound options */
227
config.psg_preamp = 150;
228
config.fm_preamp = 100;
229
config.hq_fm = 1; /* high-quality resampling */
230
config.psgBoostNoise = 1;
231
config.filter = 0; /* no filter */
232
config.lp_range = 0x9999; /* 0.6 in 16.16 fixed point */
233
config.low_freq = 880;
234
config.high_freq = 5000;
235
config.lg = 1.0;
236
config.mg = 1.0;
237
config.hg = 1.0;
238
config.dac_bits = 14; /* MAX DEPTH */
239
config.ym2413 = 2; /* AUTO */
240
config.mono = 0; /* STEREO output */
241
242
/* system options */
243
config.system = 0; /* AUTO */
244
config.region_detect = 0; /* AUTO */
245
config.vdp_mode = 0; /* AUTO */
246
config.master_clock = 0; /* AUTO */
247
config.force_dtack = 0;
248
config.addr_error = 1;
249
config.bios = 0;
250
config.lock_on = 0;
251
252
/* video options */
253
config.overscan = 0;
254
config.gg_extra = 0;
255
config.ntsc = 0;
256
config.render = 0;
257
}
258
259
static void bram_load(void)
260
{
261
FILE *fp;
262
263
/* automatically load internal backup RAM */
264
switch (region_code)
265
{
266
case REGION_JAPAN_NTSC:
267
fp = fopen(CD_BRAM_JP, "rb");
268
break;
269
case REGION_EUROPE:
270
fp = fopen(CD_BRAM_EU, "rb");
271
break;
272
case REGION_USA:
273
fp = fopen(CD_BRAM_US, "rb");
274
break;
275
default:
276
return;
277
}
278
279
if (fp != NULL)
280
{
281
fread(scd.bram, 0x2000, 1, fp);
282
fclose(fp);
283
284
/* update CRC */
285
brm_crc[0] = crc32(0, scd.bram, 0x2000);
286
}
287
else
288
{
289
/* force internal backup RAM format (does not use previous region backup RAM) */
290
scd.bram[0x1fff] = 0;
291
}
292
293
/* check if internal backup RAM is correctly formatted */
294
if (memcmp(scd.bram + 0x2000 - 0x20, brm_format + 0x20, 0x20))
295
{
296
/* clear internal backup RAM */
297
memset(scd.bram, 0x00, 0x2000 - 0x40);
298
299
/* internal Backup RAM size fields */
300
brm_format[0x10] = brm_format[0x12] = brm_format[0x14] = brm_format[0x16] = 0x00;
301
brm_format[0x11] = brm_format[0x13] = brm_format[0x15] = brm_format[0x17] = (sizeof(scd.bram) / 64) - 3;
302
303
/* format internal backup RAM */
304
memcpy(scd.bram + 0x2000 - 0x40, brm_format, 0x40);
305
306
/* clear CRC to force file saving (in case previous region backup RAM was also formatted) */
307
brm_crc[0] = 0;
308
}
309
310
/* automatically load cartridge backup RAM (if enabled) */
311
if (scd.cartridge.id)
312
{
313
fp = fopen(CART_BRAM, "rb");
314
if (fp != NULL)
315
{
316
int filesize = scd.cartridge.mask + 1;
317
int done = 0;
318
319
/* Read into buffer (2k blocks) */
320
while (filesize > CHUNKSIZE)
321
{
322
fread(scd.cartridge.area + done, CHUNKSIZE, 1, fp);
323
done += CHUNKSIZE;
324
filesize -= CHUNKSIZE;
325
}
326
327
/* Read remaining bytes */
328
if (filesize)
329
{
330
fread(scd.cartridge.area + done, filesize, 1, fp);
331
}
332
333
/* close file */
334
fclose(fp);
335
336
/* update CRC */
337
brm_crc[1] = crc32(0, scd.cartridge.area, scd.cartridge.mask + 1);
338
}
339
340
/* check if cartridge backup RAM is correctly formatted */
341
if (memcmp(scd.cartridge.area + scd.cartridge.mask + 1 - 0x20, brm_format + 0x20, 0x20))
342
{
343
/* clear cartridge backup RAM */
344
memset(scd.cartridge.area, 0x00, scd.cartridge.mask + 1);
345
346
/* Cartridge Backup RAM size fields */
347
brm_format[0x10] = brm_format[0x12] = brm_format[0x14] = brm_format[0x16] = (((scd.cartridge.mask + 1) / 64) - 3) >> 8;
348
brm_format[0x11] = brm_format[0x13] = brm_format[0x15] = brm_format[0x17] = (((scd.cartridge.mask + 1) / 64) - 3) & 0xff;
349
350
/* format cartridge backup RAM */
351
memcpy(scd.cartridge.area + scd.cartridge.mask + 1 - 0x40, brm_format, 0x40);
352
}
353
}
354
}
355
356
static void bram_save(void)
357
{
358
FILE *fp;
359
360
/* verify that internal backup RAM has been modified */
361
if (crc32(0, scd.bram, 0x2000) != brm_crc[0])
362
{
363
/* check if it is correctly formatted before saving */
364
if (!memcmp(scd.bram + 0x2000 - 0x20, brm_format + 0x20, 0x20))
365
{
366
switch (region_code)
367
{
368
case REGION_JAPAN_NTSC:
369
fp = fopen(CD_BRAM_JP, "wb");
370
break;
371
case REGION_EUROPE:
372
fp = fopen(CD_BRAM_EU, "wb");
373
break;
374
case REGION_USA:
375
fp = fopen(CD_BRAM_US, "wb");
376
break;
377
default:
378
return;
379
}
380
381
if (fp != NULL)
382
{
383
fwrite(scd.bram, 0x2000, 1, fp);
384
fclose(fp);
385
386
/* update CRC */
387
brm_crc[0] = crc32(0, scd.bram, 0x2000);
388
}
389
}
390
}
391
392
/* verify that cartridge backup RAM has been modified */
393
if (scd.cartridge.id && (crc32(0, scd.cartridge.area, scd.cartridge.mask + 1) != brm_crc[1]))
394
{
395
/* check if it is correctly formatted before saving */
396
if (!memcmp(scd.cartridge.area + scd.cartridge.mask + 1 - 0x20, brm_format + 0x20, 0x20))
397
{
398
fp = fopen(CART_BRAM, "wb");
399
if (fp != NULL)
400
{
401
int filesize = scd.cartridge.mask + 1;
402
int done = 0;
403
404
/* Write to file (2k blocks) */
405
while (filesize > CHUNKSIZE)
406
{
407
fwrite(scd.cartridge.area + done, CHUNKSIZE, 1, fp);
408
done += CHUNKSIZE;
409
filesize -= CHUNKSIZE;
410
}
411
412
/* Write remaining bytes */
413
if (filesize)
414
{
415
fwrite(scd.cartridge.area + done, filesize, 1, fp);
416
}
417
418
/* Close file */
419
fclose(fp);
420
421
/* update CRC */
422
brm_crc[1] = crc32(0, scd.cartridge.area, scd.cartridge.mask + 1);
423
}
424
}
425
}
426
}
427
428
static void extract_directory(char *buf, const char *path, size_t size)
429
{
430
char *base;
431
strncpy(buf, path, size - 1);
432
buf[size - 1] = '\0';
433
434
base = strrchr(buf, '/');
435
if (!base)
436
base = strrchr(buf, '\\');
437
438
if (base)
439
*base = '\0';
440
else
441
buf[0] = '\0';
442
}
443
444
static void update_viewport(void)
445
{
446
vwidth = bitmap.viewport.w + (bitmap.viewport.x * 2);
447
vheight = bitmap.viewport.h + (bitmap.viewport.y * 2);
448
449
if (config.ntsc)
450
{
451
if (reg[12] & 1)
452
vwidth = MD_NTSC_OUT_WIDTH(vwidth);
453
else
454
vwidth = SMS_NTSC_OUT_WIDTH(vwidth);
455
}
456
457
if (config.render && interlaced)
458
{
459
vheight = vheight * 2;
460
}
461
}
462
463
static void check_variables(void)
464
{
465
unsigned orig_value;
466
bool update_viewports = false;
467
bool reinit = false;
468
struct retro_variable var = {0};
469
470
var.key = "system_hw";
471
environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var);
472
{
473
orig_value = config.system;
474
if (!strcmp(var.value, "sg-1000"))
475
config.system = SYSTEM_SG;
476
else if (!strcmp(var.value, "mark-III"))
477
config.system = SYSTEM_MARKIII;
478
else if (!strcmp(var.value, "master system"))
479
config.system = SYSTEM_SMS;
480
else if (!strcmp(var.value, "master system II"))
481
config.system = SYSTEM_SMS2;
482
else if (!strcmp(var.value, "game gear"))
483
config.system = SYSTEM_GG;
484
else if (!strcmp(var.value, "mega drive / genesis"))
485
config.system = SYSTEM_MD;
486
else
487
config.system = 0;
488
489
if (orig_value != config.system)
490
{
491
if (system_hw)
492
{
493
switch (config.system)
494
{
495
case 0:
496
system_hw = romtype; /* AUTO */
497
break;
498
499
case SYSTEM_MD:
500
system_hw = (romtype & SYSTEM_MD) ? romtype : SYSTEM_PBC;
501
break;
502
503
case SYSTEM_GG:
504
system_hw = (romtype == SYSTEM_GG) ? SYSTEM_GG : SYSTEM_GGMS;
505
break;
506
507
default:
508
system_hw = config.system;
509
break;
510
}
511
512
reinit = true;
513
}
514
}
515
}
516
517
var.key = "region_detect";
518
environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var);
519
{
520
orig_value = config.region_detect;
521
if (!strcmp(var.value, "ntsc-u"))
522
config.region_detect = 1;
523
else if (!strcmp(var.value, "pal"))
524
config.region_detect = 2;
525
else if (!strcmp(var.value, "ntsc-j"))
526
config.region_detect = 3;
527
else
528
config.region_detect = 0;
529
530
if (orig_value != config.region_detect)
531
{
532
if (system_hw)
533
{
534
get_region(NULL);
535
reinit = true;
536
}
537
}
538
}
539
540
var.key = "force_dtack";
541
environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var);
542
{
543
if (!strcmp(var.value, "enabled"))
544
config.force_dtack = 1;
545
else
546
config.force_dtack = 0;
547
}
548
549
var.key = "addr_error";
550
environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var);
551
{
552
if (!strcmp(var.value, "enabled"))
553
m68k.aerr_enabled = config.addr_error = 1;
554
else
555
m68k.aerr_enabled = config.addr_error = 0;
556
}
557
558
var.key = "lock_on";
559
environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var);
560
{
561
orig_value = config.lock_on;
562
if (!strcmp(var.value, "game genie"))
563
config.lock_on = TYPE_GG;
564
else if (!strcmp(var.value, "action replay (pro)"))
565
config.lock_on = TYPE_AR;
566
else if (!strcmp(var.value, "sonic & knuckles"))
567
config.lock_on = TYPE_SK;
568
else
569
config.lock_on = 0;
570
571
if (orig_value != config.lock_on)
572
{
573
if (system_hw == SYSTEM_MD)
574
reinit = true;
575
}
576
}
577
578
var.key = "ym2413";
579
environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var);
580
{
581
orig_value = config.ym2413;
582
if (!strcmp(var.value, "enabled"))
583
config.ym2413 = 1;
584
else if (!strcmp(var.value, "disabled"))
585
config.ym2413 = 0;
586
else
587
config.ym2413 = 2;
588
589
if (orig_value != config.ym2413)
590
{
591
if (system_hw && (config.ym2413 & 2) && ((system_hw & SYSTEM_PBC) != SYSTEM_MD))
592
{
593
memcpy(temp, sram.sram, sizeof(temp));
594
sms_cart_init();
595
memcpy(sram.sram, temp, sizeof(temp));
596
}
597
}
598
}
599
600
var.key = "dac_bits";
601
environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var);
602
{
603
if (!strcmp(var.value, "enabled"))
604
config.dac_bits = 9;
605
else
606
config.dac_bits = 14;
607
608
YM2612Config(config.dac_bits);
609
}
610
611
var.key = "blargg_ntsc_filter";
612
environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var);
613
{
614
orig_value = config.ntsc;
615
616
if (strcmp(var.value, "disabled") == 0)
617
config.ntsc = 0;
618
else if (strcmp(var.value, "monochrome") == 0)
619
{
620
config.ntsc = 1;
621
sms_ntsc_init(sms_ntsc, &sms_ntsc_monochrome);
622
md_ntsc_init(md_ntsc, &md_ntsc_monochrome);
623
}
624
else if (strcmp(var.value, "composite") == 0)
625
{
626
config.ntsc = 1;
627
sms_ntsc_init(sms_ntsc, &sms_ntsc_composite);
628
md_ntsc_init(md_ntsc, &md_ntsc_composite);
629
}
630
else if (strcmp(var.value, "svideo") == 0)
631
{
632
config.ntsc = 1;
633
sms_ntsc_init(sms_ntsc, &sms_ntsc_svideo);
634
md_ntsc_init(md_ntsc, &md_ntsc_svideo);
635
}
636
else if (strcmp(var.value, "rgb") == 0)
637
{
638
config.ntsc = 1;
639
sms_ntsc_init(sms_ntsc, &sms_ntsc_rgb);
640
md_ntsc_init(md_ntsc, &md_ntsc_rgb);
641
}
642
643
if (orig_value != config.ntsc)
644
update_viewports = true;
645
}
646
647
var.key = "overscan";
648
environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var);
649
{
650
orig_value = config.overscan;
651
if (strcmp(var.value, "disabled") == 0)
652
config.overscan = 0;
653
else if (strcmp(var.value, "top/bottom") == 0)
654
config.overscan = 1;
655
else if (strcmp(var.value, "left/right") == 0)
656
config.overscan = 2;
657
else if (strcmp(var.value, "full") == 0)
658
config.overscan = 3;
659
if (orig_value != config.overscan)
660
update_viewports = true;
661
}
662
663
var.key = "gg_extra";
664
environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var);
665
{
666
orig_value = config.gg_extra;
667
if (strcmp(var.value, "disabled") == 0)
668
config.gg_extra = 0;
669
else if (strcmp(var.value, "enabled") == 0)
670
config.gg_extra = 1;
671
if (orig_value != config.gg_extra)
672
update_viewports = true;
673
}
674
675
var.key = "render";
676
environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var);
677
{
678
orig_value = config.render;
679
if (strcmp(var.value, "normal") == 0)
680
config.render = 0;
681
else
682
config.render = 1;
683
if (orig_value != config.render)
684
update_viewports = true;
685
}
686
687
if (reinit)
688
{
689
audio_init(44100, snd.frame_rate);
690
memcpy(temp, sram.sram, sizeof(temp));
691
system_init();
692
system_reset();
693
memcpy(sram.sram, temp, sizeof(temp));
694
}
695
696
if (update_viewports)
697
{
698
bitmap.viewport.changed = 3;
699
if ((system_hw == SYSTEM_GG) && !config.gg_extra)
700
bitmap.viewport.x = (config.overscan & 2) ? 14 : -48;
701
else
702
bitmap.viewport.x = (config.overscan & 2) * 7;
703
}
704
}
705
706
static void configure_controls(void)
707
{
708
int i;
709
struct retro_variable var;
710
711
input.system[0] = SYSTEM_MD_GAMEPAD;
712
input.system[1] = SYSTEM_MD_GAMEPAD;
713
714
var.key = "padtype";
715
environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var);
716
if (!strcmp(var.value, "6-buttons"))
717
for(i = 0; i < MAX_INPUTS; i++)
718
config.input[i].padtype = DEVICE_PAD6B;
719
else if (!strcmp(var.value, "3-buttons"))
720
for(i = 0; i < MAX_INPUTS; i++)
721
config.input[i].padtype = DEVICE_PAD3B;
722
else if (!strcmp(var.value, "2-buttons"))
723
for(i = 0; i < MAX_INPUTS; i++)
724
config.input[i].padtype = DEVICE_PAD2B;
725
else if ((system_hw & SYSTEM_PBC) != SYSTEM_MD)
726
for(i = 0; i < MAX_INPUTS; i++)
727
config.input[i].padtype = DEVICE_PAD2B;
728
else if (rominfo.peripherals & 2)
729
for(i = 0; i < MAX_INPUTS; i++)
730
config.input[i].padtype = DEVICE_PAD6B;
731
else
732
for(i = 0; i < MAX_INPUTS; i++)
733
config.input[i].padtype = DEVICE_PAD3B;
734
735
var.key = "multitap";
736
environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var);
737
if (!strcmp(var.value, "4-wayplay"))
738
input.system[0] = input.system[1] = SYSTEM_WAYPLAY;
739
else if (!strcmp(var.value, "teamplayer 1"))
740
input.system[0] = SYSTEM_TEAMPLAYER;
741
else if (!strcmp(var.value, "teamplayer 2"))
742
input.system[1] = SYSTEM_TEAMPLAYER;
743
else if (!strcmp(var.value, "teamplayer 1&2"))
744
input.system[0] = input.system[1] = SYSTEM_TEAMPLAYER;
745
746
var.key = "portb";
747
environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var);
748
if (!strcmp(var.value, "disabled"))
749
input.system[1] = NO_SYSTEM;
750
751
input_init();
752
}
753
754
/************************************
755
* libretro implementation
756
************************************/
757
unsigned retro_api_version(void) { return RETRO_API_VERSION; }
758
759
void retro_set_environment(retro_environment_t cb)
760
{
761
static const struct retro_variable vars[] = {
762
{ "system_hw", "System hardware; auto|sg-1000|mark-III|master system|master system II|game gear|mega drive / genesis" },
763
{ "region_detect", "System region; auto|ntsc-u|pal|ntsc-j" },
764
{ "force_dtack", "System lockups; enabled|disabled" },
765
{ "addr_error", "68k address error; enabled|disabled" },
766
{ "lock_on", "Cartridge lock-on; disabled|game genie|action replay (pro)|sonic & knuckles" },
767
{ "padtype", "Gamepad type; auto|6-buttons|3-buttons|2-buttons" },
768
{ "multitap", "Multi Tap; disabled|4-wayplay|teamplayer (port 1)|teamplayer (port 2)|teamplayer (both)" },
769
{ "portb", "Control Port 2; enabled|disabled" },
770
{ "ym2413", "Master System FM; auto|disabled|enabled" },
771
{ "dac_bits", "YM2612 DAC quantization; disabled|enabled" },
772
{ "blargg_ntsc_filter", "Blargg NTSC filter; disabled|monochrome|composite|svideo|rgb" },
773
{ "overscan", "Borders; disabled|top/bottom|left/right|full" },
774
{ "gg_extra", "Game Gear extended screen; disabled|enabled" },
775
{ "render", "Interlaced mode resolution; normal|double" },
776
{ NULL, NULL },
777
};
778
779
environ_cb = cb;
780
cb(RETRO_ENVIRONMENT_SET_VARIABLES, (void*)vars);
781
}
782
783
void retro_set_video_refresh(retro_video_refresh_t cb) { video_cb = cb; }
784
void retro_set_audio_sample(retro_audio_sample_t cb) { (void)cb; }
785
void retro_set_audio_sample_batch(retro_audio_sample_batch_t cb) { audio_cb = cb; }
786
void retro_set_input_poll(retro_input_poll_t cb) { input_poll_cb = cb; }
787
void retro_set_input_state(retro_input_state_t cb) { input_state_cb = cb; }
788
789
void retro_get_system_info(struct retro_system_info *info)
790
{
791
info->library_name = "Genesis Plus GX";
792
info->library_version = "v1.7.4";
793
info->valid_extensions = "mdx|md|smd|gen|bin|cue|iso|sms|gg|sg";
794
info->block_extract = false;
795
info->need_fullpath = true;
796
}
797
798
void retro_get_system_av_info(struct retro_system_av_info *info)
799
{
800
info->geometry.base_width = vwidth;
801
info->geometry.base_height = vheight;
802
info->geometry.max_width = 1024;
803
info->geometry.max_height = 512;
804
info->geometry.aspect_ratio = 4.0 / 3.0;
805
info->timing.fps = snd.frame_rate;
806
info->timing.sample_rate = 44100;
807
}
808
809
void retro_set_controller_port_device(unsigned port, unsigned device)
810
{
811
(void)port;
812
(void)device;
813
}
814
815
size_t retro_serialize_size(void) { return STATE_SIZE; }
816
817
bool retro_serialize(void *data, size_t size)
818
{
819
if (size != STATE_SIZE)
820
return FALSE;
821
822
state_save(data);
823
824
return TRUE;
825
}
826
827
bool retro_unserialize(const void *data, size_t size)
828
{
829
if (size != STATE_SIZE)
830
return FALSE;
831
832
if (!state_load((uint8_t*)data))
833
return FALSE;
834
835
return TRUE;
836
}
837
838
void retro_cheat_reset(void) {}
839
void retro_cheat_set(unsigned index, bool enabled, const char *code)
840
{
841
(void)index;
842
(void)enabled;
843
(void)code;
844
}
845
846
bool retro_load_game(const struct retro_game_info *info)
847
{
848
int i;
849
const char *dir;
850
#if defined(_WIN32)
851
char slash = '\\';
852
#else
853
char slash = '/';
854
#endif
855
856
extract_directory(g_rom_dir, info->path, sizeof(g_rom_dir));
857
858
if (!environ_cb(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &dir) || !dir)
859
{
860
fprintf(stderr, "[genplus]: Defaulting system directory to %s.\n", g_rom_dir);
861
dir = g_rom_dir;
862
}
863
864
snprintf(GG_ROM, sizeof(GG_ROM), "%s%cggenie.bin", dir, slash);
865
snprintf(AR_ROM, sizeof(AR_ROM), "%s%careplay.bin", dir, slash);
866
snprintf(SK_ROM, sizeof(SK_ROM), "%s%csk.bin", dir, slash);
867
snprintf(SK_UPMEM, sizeof(SK_UPMEM), "%s%cs2k.bin", dir, slash);
868
snprintf(CD_BIOS_EU, sizeof(CD_BIOS_EU), "%s%cbios_CD_E.bin", dir, slash);
869
snprintf(CD_BIOS_US, sizeof(CD_BIOS_US), "%s%cbios_CD_U.bin", dir, slash);
870
snprintf(CD_BIOS_JP, sizeof(CD_BIOS_JP), "%s%cbios_CD_J.bin", dir, slash);
871
snprintf(CD_BRAM_EU, sizeof(CD_BRAM_EU), "%s%cscd_E.brm", dir, slash);
872
snprintf(CD_BRAM_US, sizeof(CD_BRAM_US), "%s%cscd_U.brm", dir, slash);
873
snprintf(CD_BRAM_JP, sizeof(CD_BRAM_JP), "%s%cscd_J.brm", dir, slash);
874
snprintf(CART_BRAM, sizeof(CART_BRAM), "%s%ccart.brm", dir, slash);
875
fprintf(stderr, "Game Genie ROM should be located at: %s\n", GG_ROM);
876
fprintf(stderr, "Action Replay (Pro) ROM should be located at: %s\n", AR_ROM);
877
fprintf(stderr, "Sonic & Knuckles (2 MB) ROM should be located at: %s\n", SK_ROM);
878
fprintf(stderr, "Sonic & Knuckles UPMEM (256 KB) ROM should be located at: %s\n", SK_UPMEM);
879
fprintf(stderr, "Mega CD PAL BIOS should be located at: %s\n", CD_BIOS_EU);
880
fprintf(stderr, "Sega CD NTSC-U BIOS should be located at: %s\n", CD_BIOS_US);
881
fprintf(stderr, "Mega CD NTSC-J BIOS should be located at: %s\n", CD_BIOS_JP);
882
fprintf(stderr, "Mega CD PAL BRAM is located at: %s\n", CD_BRAM_EU);
883
fprintf(stderr, "Sega CD NTSC-U BRAM is located at: %s\n", CD_BRAM_US);
884
fprintf(stderr, "Mega CD NTSC-J BRAM is located at: %s\n", CD_BRAM_JP);
885
fprintf(stderr, "Mega CD RAM CART is located at: %s\n", CART_BRAM);
886
887
check_variables();
888
if (!load_rom((char *)info->path))
889
return false;
890
891
configure_controls();
892
893
audio_init(44100, vdp_pal ? pal_fps : ntsc_fps);
894
system_init();
895
system_reset();
896
897
if (system_hw == SYSTEM_MCD)
898
bram_load();
899
900
update_viewport();
901
902
return true;
903
}
904
905
bool retro_load_game_special(unsigned game_type, const struct retro_game_info *info, size_t num_info)
906
{
907
(void)game_type;
908
(void)info;
909
(void)num_info;
910
return FALSE;
911
}
912
913
void retro_unload_game(void)
914
{
915
if (system_hw == SYSTEM_MCD)
916
bram_save();
917
}
918
919
unsigned retro_get_region(void) { return vdp_pal ? RETRO_REGION_PAL : RETRO_REGION_NTSC; }
920
921
void *retro_get_memory_data(unsigned id)
922
{
923
if (!sram.on)
924
return NULL;
925
926
switch (id)
927
{
928
case RETRO_MEMORY_SAVE_RAM:
929
return sram.sram;
930
931
default:
932
return NULL;
933
}
934
}
935
936
size_t retro_get_memory_size(unsigned id)
937
{
938
if (!sram.on)
939
return 0;
940
941
switch (id)
942
{
943
case RETRO_MEMORY_SAVE_RAM:
944
return 0x10000;
945
946
default:
947
return 0;
948
}
949
}
950
951
void retro_init(void)
952
{
953
unsigned level, rgb565;
954
sms_ntsc = calloc(1, sizeof(sms_ntsc_t));
955
md_ntsc = calloc(1, sizeof(md_ntsc_t));
956
957
init_bitmap();
958
config_default();
959
960
level = 1;
961
environ_cb(RETRO_ENVIRONMENT_SET_PERFORMANCE_LEVEL, &level);
962
963
#ifdef FRONTEND_SUPPORTS_RGB565
964
rgb565 = RETRO_PIXEL_FORMAT_RGB565;
965
if(environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &rgb565))
966
fprintf(stderr, "Frontend supports RGB565 - will use that instead of XRGB1555.\n");
967
#endif
968
}
969
970
void retro_deinit(void)
971
{
972
audio_shutdown();
973
free(md_ntsc);
974
free(sms_ntsc);
975
}
976
977
void retro_reset(void) { system_reset(); }
978
979
void retro_run(void)
980
{
981
bool updated = false;
982
983
if (system_hw == SYSTEM_MCD)
984
system_frame_scd(0);
985
else if ((system_hw & SYSTEM_PBC) == SYSTEM_MD)
986
system_frame_gen(0);
987
else
988
system_frame_sms(0);
989
990
if (bitmap.viewport.changed & 1)
991
{
992
bitmap.viewport.changed &= ~1;
993
update_viewport();
994
}
995
996
video_cb(bitmap.data, vwidth, vheight, 1024 * 2);
997
audio_cb(soundbuffer, audio_update(soundbuffer));
998
999
environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated);
1000
if (updated)
1001
{
1002
check_variables();
1003
configure_controls();
1004
}
1005
}
1006
1007