Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/genplus-gx/cinterface/cinterface.c
2 views
1
#include <stddef.h>
2
#include <stdarg.h>
3
#include <stdio.h>
4
#include "callbacks.h"
5
6
#ifdef _MSC_VER
7
#define snprintf _snprintf
8
#endif
9
10
#include "shared.h"
11
#include "libretro.h"
12
#include "state.h"
13
#include "genesis.h"
14
#include "md_ntsc.h"
15
#include "sms_ntsc.h"
16
#include "eeprom_i2c.h"
17
18
char GG_ROM[256] = "GG_ROM"; // game genie rom
19
char AR_ROM[256] = "AR_ROM"; // actin replay rom
20
char SK_ROM[256] = "SK_ROM"; // sanic and knuckles
21
char SK_UPMEM[256] = "SK_UPMEM"; // sanic and knuckles
22
char GG_BIOS[256] = "GG_BIOS"; // game gear bootrom
23
char CD_BIOS_EU[256] = "CD_BIOS_EU"; // cd bioses
24
char CD_BIOS_US[256] = "CD_BIOS_US";
25
char CD_BIOS_JP[256] = "CD_BIOS_JP";
26
char MS_BIOS_US[256] = "MS_BIOS_US"; // master system bioses
27
char MS_BIOS_EU[256] = "MS_BIOS_EU";
28
char MS_BIOS_JP[256] = "MS_BIOS_JP";
29
30
char romextension[4];
31
32
static uint32_t bitmap_data_[1024 * 512];
33
34
static int16 soundbuffer[4096];
35
static int nsamples;
36
37
int cinterface_render_bga = 1;
38
int cinterface_render_bgb = 1;
39
int cinterface_render_bgw = 1;
40
int cinterface_render_obj = 1;
41
uint8 cinterface_custom_backdrop = 0;
42
uint32 cinterface_custom_backdrop_color = 0xffff00ff; // pink
43
extern uint8 border;
44
45
#define GPGX_EX __declspec(dllexport)
46
47
static int vwidth;
48
static int vheight;
49
50
static uint8_t brm_format[0x40] =
51
{
52
0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x00,0x00,0x00,0x00,0x40,
53
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
54
0x53,0x45,0x47,0x41,0x5f,0x43,0x44,0x5f,0x52,0x4f,0x4d,0x00,0x01,0x00,0x00,0x00,
55
0x52,0x41,0x4d,0x5f,0x43,0x41,0x52,0x54,0x52,0x49,0x44,0x47,0x45,0x5f,0x5f,0x5f
56
};
57
58
extern void zap(void);
59
60
void (*biz_execcb)(unsigned addr) = NULL;
61
void (*biz_readcb)(unsigned addr) = NULL;
62
void (*biz_writecb)(unsigned addr) = NULL;
63
CDCallback biz_cdcallback = NULL;
64
unsigned biz_lastpc = 0;
65
66
static void update_viewport(void)
67
{
68
vwidth = bitmap.viewport.w + (bitmap.viewport.x * 2);
69
vheight = bitmap.viewport.h + (bitmap.viewport.y * 2);
70
71
if (config.ntsc)
72
{
73
if (reg[12] & 1)
74
vwidth = MD_NTSC_OUT_WIDTH(vwidth);
75
else
76
vwidth = SMS_NTSC_OUT_WIDTH(vwidth);
77
}
78
79
if (config.render && interlaced)
80
{
81
vheight = vheight * 2;
82
}
83
}
84
85
GPGX_EX void gpgx_get_video(int *w, int *h, int *pitch, void **buffer)
86
{
87
if (w)
88
*w = vwidth;
89
if (h)
90
*h = vheight;
91
if (pitch)
92
*pitch = bitmap.pitch;
93
if (buffer)
94
*buffer = bitmap.data;
95
}
96
97
GPGX_EX void gpgx_get_audio(int *n, void **buffer)
98
{
99
if (n)
100
*n = nsamples;
101
if (buffer)
102
*buffer = soundbuffer;
103
}
104
105
// this is most certainly wrong for interlacing
106
GPGX_EX void gpgx_get_fps(int *num, int *den)
107
{
108
if (vdp_pal)
109
{
110
if (num)
111
*num = 53203424;
112
if (den)
113
*den = 3420 * 313;
114
}
115
else
116
{
117
if (num)
118
*num = 53693175;
119
if (den)
120
*den = 3420 * 262;
121
}
122
}
123
124
GPGX_EX int gpgx_state_max_size(void)
125
{
126
// original state size, plus 64K sram or 16K ebram, plus 8K ibram or seeprom control structures
127
return STATE_SIZE + (64 + 8) * 1024;
128
}
129
130
GPGX_EX int gpgx_state_size(void *dest, int size)
131
{
132
int actual = 0;
133
if (size < gpgx_state_max_size())
134
return -1;
135
136
actual = state_save((unsigned char*) dest);
137
if (actual > size)
138
// fixme!
139
return -1;
140
return actual;
141
}
142
143
GPGX_EX int gpgx_state_save(void *dest, int size)
144
{
145
return state_save((unsigned char*) dest) == size;
146
}
147
148
GPGX_EX int gpgx_state_load(void *src, int size)
149
{
150
if (!size)
151
return 0;
152
153
if (state_load((unsigned char *) src) == size)
154
{
155
update_viewport();
156
return 1;
157
}
158
else
159
return 0;
160
}
161
162
void osd_input_update(void)
163
{
164
}
165
166
void (*input_callback_cb)(void);
167
168
void real_input_callback(void)
169
{
170
if (input_callback_cb)
171
input_callback_cb();
172
}
173
174
GPGX_EX void gpgx_set_input_callback(void (*fecb)(void))
175
{
176
input_callback_cb = fecb;
177
}
178
179
int (*load_archive_cb)(const char *filename, unsigned char *buffer, int maxsize);
180
181
// return 0 on failure, else actual loaded size
182
// extension, if not null, should be populated with the extension of the file loaded
183
// (up to 3 chars and null terminator, no more)
184
int load_archive(const char *filename, unsigned char *buffer, int maxsize, char *extension)
185
{
186
if (extension)
187
memcpy(extension, romextension, 4);
188
189
return load_archive_cb(filename, buffer, maxsize);
190
}
191
192
GPGX_EX int gpgx_get_control(t_input *dest, int bytes)
193
{
194
if (bytes != sizeof(t_input))
195
return 0;
196
memcpy(dest, &input, sizeof(t_input));
197
return 1;
198
}
199
200
GPGX_EX int gpgx_put_control(t_input *src, int bytes)
201
{
202
if (bytes != sizeof(t_input))
203
return 0;
204
memcpy(&input, src, sizeof(t_input));
205
return 1;
206
}
207
208
GPGX_EX void gpgx_advance(void)
209
{
210
if (system_hw == SYSTEM_MCD)
211
system_frame_scd(0);
212
else if ((system_hw & SYSTEM_PBC) == SYSTEM_MD)
213
system_frame_gen(0);
214
else
215
system_frame_sms(0);
216
217
if (bitmap.viewport.changed & 1)
218
{
219
bitmap.viewport.changed &= ~1;
220
update_viewport();
221
}
222
223
nsamples = audio_update(soundbuffer);
224
}
225
226
typedef struct
227
{
228
uint32 width; // in cells
229
uint32 height;
230
uint32 baseaddr;
231
} nametable_t;
232
233
typedef struct
234
{
235
uint8 *vram; // 64K vram
236
uint8 *patterncache; // every pattern, first normal, then hflip, vflip, bothflip
237
uint32 *colorcache; // 64 colors
238
nametable_t nta;
239
nametable_t ntb;
240
nametable_t ntw;
241
} vdpview_t;
242
243
244
extern uint8 bg_pattern_cache[];
245
extern uint32 pixel[];
246
247
GPGX_EX void gpgx_get_vdp_view(vdpview_t *view)
248
{
249
view->vram = vram;
250
view->patterncache = bg_pattern_cache;
251
view->colorcache = pixel + 0x40;
252
view->nta.width = 1 << (playfield_shift - 1);
253
view->ntb.width = 1 << (playfield_shift - 1);
254
view->nta.height = (playfield_row_mask + 1) >> 3;
255
view->ntb.height = (playfield_row_mask + 1) >> 3;
256
view->ntw.width = 1 << (5 + (reg[12] & 1));
257
view->ntw.height = 32;
258
view->nta.baseaddr = ntab;
259
view->ntb.baseaddr = ntbb;
260
view->ntw.baseaddr = ntwb;
261
}
262
263
// internal: computes sram size (no brams)
264
int saveramsize(void)
265
{
266
return sram_get_actual_size();
267
}
268
269
GPGX_EX void gpgx_clear_sram(void)
270
{
271
// clear sram
272
if (sram.on)
273
memset(sram.sram, 0xff, 0x10000);
274
275
if (cdd.loaded)
276
{
277
// clear and format bram
278
memset(scd.bram, 0, 0x2000);
279
brm_format[0x10] = brm_format[0x12] = brm_format[0x14] = brm_format[0x16] = 0x00;
280
brm_format[0x11] = brm_format[0x13] = brm_format[0x15] = brm_format[0x17] = (sizeof(scd.bram) / 64) - 3;
281
memcpy(scd.bram + 0x2000 - 0x40, brm_format, 0x40);
282
283
if (scd.cartridge.id)
284
{
285
// clear and format ebram
286
memset(scd.cartridge.area, 0x00, scd.cartridge.mask + 1);
287
brm_format[0x10] = brm_format[0x12] = brm_format[0x14] = brm_format[0x16] = (((scd.cartridge.mask + 1) / 64) - 3) >> 8;
288
brm_format[0x11] = brm_format[0x13] = brm_format[0x15] = brm_format[0x17] = (((scd.cartridge.mask + 1) / 64) - 3) & 0xff;
289
memcpy(scd.cartridge.area + scd.cartridge.mask + 1 - 0x40, brm_format, 0x40);
290
}
291
}
292
}
293
294
// a bit hacky:
295
// in order to present a single memory block to the frontend,
296
// we copy the bram bits next to the ebram bits
297
298
GPGX_EX void gpgx_sram_prepread(void)
299
{
300
if (!sram.on && cdd.loaded && scd.cartridge.id)
301
{
302
void *dest = scd.cartridge.area + scd.cartridge.mask + 1;
303
memcpy(dest, scd.bram, 0x2000);
304
}
305
}
306
307
GPGX_EX void gpgx_sram_commitwrite(void)
308
{
309
if (!sram.on && cdd.loaded && scd.cartridge.id)
310
{
311
void *src = scd.cartridge.area + scd.cartridge.mask + 1;
312
memcpy(scd.bram, src, 0x2000);
313
}
314
}
315
316
GPGX_EX void gpgx_poke_vram(int addr, uint8 val)
317
{
318
write_vram_byte(addr, val);
319
}
320
321
GPGX_EX void gpgx_flush_vram(void)
322
{
323
flush_vram_cache();
324
}
325
326
GPGX_EX const char* gpgx_get_memdom(int which, void **area, int *size)
327
{
328
if (!area || !size)
329
return NULL;
330
switch (which)
331
{
332
case 0:
333
*area = work_ram;
334
*size = 0x10000;
335
return "68K RAM";
336
case 1:
337
*area = zram;
338
*size = 0x2000;
339
return "Z80 RAM";
340
case 2:
341
if (!cdd.loaded)
342
{
343
*area = ext.md_cart.rom;
344
*size = ext.md_cart.romsize;
345
return "MD CART";
346
}
347
else if (scd.cartridge.id)
348
{
349
*area = scd.cartridge.area;
350
*size = scd.cartridge.mask + 1;
351
return "EBRAM";
352
}
353
else return NULL;
354
case 3:
355
if (cdd.loaded)
356
{
357
*area = scd.bootrom;
358
*size = 0x20000;
359
return "CD BOOT ROM";
360
}
361
else return NULL;
362
case 4:
363
if (cdd.loaded)
364
{
365
*area = scd.prg_ram;
366
*size = 0x80000;
367
return "CD PRG RAM";
368
}
369
else return NULL;
370
case 5:
371
if (cdd.loaded)
372
{
373
*area = scd.word_ram[0];
374
*size = 0x20000;
375
return "CD WORD RAM[0] (1M)";
376
}
377
else return NULL;
378
case 6:
379
if (cdd.loaded)
380
{
381
*area = scd.word_ram[1];
382
*size = 0x20000;
383
return "CD WORD RAM[1] (1M)";
384
}
385
else return NULL;
386
case 7:
387
if (cdd.loaded)
388
{
389
*area = scd.word_ram_2M;
390
*size = 0x40000;
391
return "CD WORD RAM (2M)";
392
}
393
else return NULL;
394
case 8:
395
if (cdd.loaded)
396
{
397
*area = scd.bram;
398
*size = 0x2000;
399
return "CD BRAM";
400
}
401
else return NULL;
402
case 9:
403
*area = boot_rom;
404
*size = 0x800;
405
return "BOOT ROM";
406
default:
407
return NULL;
408
case 10:
409
if (sram.on)
410
{
411
*area = sram.sram;
412
*size = saveramsize();
413
return "SRAM";
414
}
415
else return NULL;
416
case 11:
417
*area = cram;
418
*size = 128;
419
return "CRAM";
420
case 12:
421
*area = vsram;
422
*size = 128;
423
return "VSRAM";
424
case 13:
425
*area = vram;
426
*size = 65536;
427
return "VRAM";
428
}
429
}
430
431
GPGX_EX void gpgx_write_m68k_bus(unsigned addr, unsigned data)
432
{
433
unsigned char *base = m68k.memory_map[addr >> 16 & 0xff].base;
434
if (base)
435
base[addr & 0xffff ^ 1] = data;
436
}
437
438
GPGX_EX void gpgx_write_s68k_bus(unsigned addr, unsigned data)
439
{
440
unsigned char *base = s68k.memory_map[addr >> 16 & 0xff].base;
441
if (base)
442
base[addr & 0xffff ^ 1] = data;
443
}
444
GPGX_EX unsigned gpgx_peek_m68k_bus(unsigned addr)
445
{
446
unsigned char *base = m68k.memory_map[addr >> 16 & 0xff].base;
447
if (base)
448
return base[addr & 0xffff ^ 1];
449
else
450
return 0xff;
451
}
452
GPGX_EX unsigned gpgx_peek_s68k_bus(unsigned addr)
453
{
454
unsigned char *base = s68k.memory_map[addr >> 16 & 0xff].base;
455
if (base)
456
return base[addr & 0xffff ^ 1];
457
else
458
return 0xff;
459
}
460
461
GPGX_EX void gpgx_get_sram(void **area, int *size)
462
{
463
if (!area || !size)
464
return;
465
466
if (sram.on)
467
{
468
*area = sram.sram;
469
*size = saveramsize();
470
}
471
else if (scd.cartridge.id)
472
{
473
*area = scd.cartridge.area;
474
*size = scd.cartridge.mask + 1 + 0x2000;
475
}
476
else if (cdd.loaded)
477
{
478
*area = scd.bram;
479
*size = 0x2000;
480
}
481
else
482
{
483
if (area)
484
*area = NULL;
485
if (size)
486
*size = 0;
487
}
488
}
489
490
struct InitSettings
491
{
492
uint8_t Filter;
493
uint16_t LowPassRange;
494
int16_t LowFreq;
495
int16_t HighFreq;
496
int16_t LowGain;
497
int16_t MidGain;
498
int16_t HighGain;
499
uint32_t BackdropColor;
500
};
501
502
GPGX_EX int gpgx_init(const char *feromextension, int (*feload_archive_cb)(const char *filename, unsigned char *buffer, int maxsize), int sixbutton, char system_a, char system_b, int region, struct InitSettings *settings)
503
{
504
zap();
505
506
memset(&bitmap, 0, sizeof(bitmap));
507
memset(bitmap_data_, 0, sizeof(bitmap_data_));
508
509
strncpy(romextension, feromextension, 3);
510
romextension[3] = 0;
511
512
load_archive_cb = feload_archive_cb;
513
514
bitmap.width = 1024;
515
bitmap.height = 512;
516
bitmap.pitch = 1024 * 4;
517
bitmap.data = (uint8_t *)bitmap_data_;
518
519
/* sound options */
520
config.psg_preamp = 150;
521
config.fm_preamp= 100;
522
config.hq_fm = 1; /* high-quality resampling */
523
config.psgBoostNoise = 1;
524
config.filter = settings->Filter; //0; /* no filter */
525
config.lp_range = settings->LowPassRange; //0x9999; /* 0.6 in 16.16 fixed point */
526
config.low_freq = settings->LowFreq; //880;
527
config.high_freq = settings->HighFreq; //5000;
528
config.lg = settings->LowGain; //1.0;
529
config.mg = settings->MidGain; //1.0;
530
config.hg = settings->HighGain; //1.0;
531
config.dac_bits = 14; /* MAX DEPTH */
532
config.ym2413= 2; /* AUTO */
533
config.mono = 0; /* STEREO output */
534
535
/* system options */
536
config.system = 0; /* AUTO */
537
config.region_detect = region; // see loadrom.c
538
config.vdp_mode = 0; /* AUTO */
539
config.master_clock = 0; /* AUTO */
540
config.force_dtack = 0;
541
config.addr_error = 1;
542
config.bios = 0;
543
config.lock_on = 0;
544
545
/* video options */
546
config.overscan = 0;
547
config.gg_extra = 0;
548
config.ntsc = 0;
549
config.render = 0;
550
551
// set overall input system type
552
// usual is MD GAMEPAD or NONE
553
// TEAMPLAYER, WAYPLAY, ACTIVATOR, XEA1P, MOUSE need to be specified
554
// everything else is auto or master system only
555
// XEA1P is port 1 only
556
// WAYPLAY is both ports at same time only
557
input.system[0] = system_a;
558
input.system[1] = system_b;
559
560
cinterface_custom_backdrop_color = settings->BackdropColor;
561
562
// apparently, the only part of config.input used is the padtype identifier,
563
// and that's used only for choosing pad type when system_md
564
{
565
int i;
566
for (i = 0; i < MAX_INPUTS; i++)
567
config.input[i].padtype = sixbutton ? DEVICE_PAD6B : DEVICE_PAD3B;
568
}
569
570
if (!load_rom("PRIMARY_ROM"))
571
return 0;
572
573
audio_init(44100, 0);
574
system_init();
575
system_reset();
576
577
update_viewport();
578
gpgx_clear_sram();
579
580
return 1;
581
}
582
583
GPGX_EX void gpgx_reset(int hard)
584
{
585
if (hard)
586
system_reset();
587
else
588
gen_reset(0);
589
}
590
591
GPGX_EX void gpgx_set_mem_callback(void (*read)(unsigned), void (*write)(unsigned), void (*exec)(unsigned))
592
{
593
biz_readcb = read;
594
biz_writecb = write;
595
biz_execcb = exec;
596
}
597
598
GPGX_EX void gpgx_set_cd_callback(CDCallback cdcallback)
599
{
600
biz_cdcallback = cdcallback;
601
}
602
603
GPGX_EX void gpgx_set_draw_mask(int mask)
604
{
605
cinterface_render_bga = !!(mask & 1);
606
cinterface_render_bgb = !!(mask & 2);
607
cinterface_render_bgw = !!(mask & 4);
608
cinterface_render_obj = !!(mask & 8);
609
cinterface_custom_backdrop = !!(mask & 16);
610
if (cinterface_custom_backdrop)
611
color_update_m5(0, 0);
612
else
613
color_update_m5(0x00, *(uint16 *)&cram[border << 1]);
614
}
615
616
typedef struct
617
{
618
unsigned int value;
619
const char *name;
620
} gpregister_t;
621
622
GPGX_EX int gpgx_getmaxnumregs(void)
623
{
624
return 57;
625
}
626
627
GPGX_EX int gpgx_getregs(gpregister_t *regs)
628
{
629
int ret = 0;
630
631
// 22
632
#define MAKEREG(x) regs->name = "M68K " #x; regs->value = m68k_get_reg(M68K_REG_##x); regs++; ret++;
633
MAKEREG(D0);
634
MAKEREG(D1);
635
MAKEREG(D2);
636
MAKEREG(D3);
637
MAKEREG(D4);
638
MAKEREG(D5);
639
MAKEREG(D6);
640
MAKEREG(D7);
641
MAKEREG(A0);
642
MAKEREG(A1);
643
MAKEREG(A2);
644
MAKEREG(A3);
645
MAKEREG(A4);
646
MAKEREG(A5);
647
MAKEREG(A6);
648
MAKEREG(A7);
649
MAKEREG(PC);
650
MAKEREG(SR);
651
MAKEREG(SP);
652
MAKEREG(USP);
653
MAKEREG(ISP);
654
MAKEREG(IR);
655
#undef MAKEREG
656
657
(regs-6)->value = biz_lastpc; // during read/write callbacks, PC runs away due to prefetch. restore it.
658
659
// 13
660
#define MAKEREG(x) regs->name = "Z80 " #x; regs->value = Z80.x.d; regs++; ret++;
661
MAKEREG(pc);
662
MAKEREG(sp);
663
MAKEREG(af);
664
MAKEREG(bc);
665
MAKEREG(de);
666
MAKEREG(hl);
667
MAKEREG(ix);
668
MAKEREG(iy);
669
MAKEREG(wz);
670
MAKEREG(af2);
671
MAKEREG(bc2);
672
MAKEREG(de2);
673
MAKEREG(hl2);
674
#undef MAKEREG
675
676
// 22
677
if (system_hw == SYSTEM_MCD)
678
{
679
#define MAKEREG(x) regs->name = "S68K " #x; regs->value = s68k_get_reg(M68K_REG_##x); regs++; ret++;
680
MAKEREG(D0);
681
MAKEREG(D1);
682
MAKEREG(D2);
683
MAKEREG(D3);
684
MAKEREG(D4);
685
MAKEREG(D5);
686
MAKEREG(D6);
687
MAKEREG(D7);
688
MAKEREG(A0);
689
MAKEREG(A1);
690
MAKEREG(A2);
691
MAKEREG(A3);
692
MAKEREG(A4);
693
MAKEREG(A5);
694
MAKEREG(A6);
695
MAKEREG(A7);
696
MAKEREG(PC);
697
MAKEREG(SR);
698
MAKEREG(SP);
699
MAKEREG(USP);
700
MAKEREG(ISP);
701
MAKEREG(IR);
702
#undef MAKEREG
703
}
704
705
return ret;
706
}
707
708