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