Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libsnes/bsnes/target-libsnes/libsnes.cpp
2 views
1
#include "libsnes.hpp"
2
#include <snes/snes.hpp>
3
4
#include <nall/snes/cartridge.hpp>
5
#include <nall/gameboy/cartridge.hpp>
6
7
#include <queue>
8
9
#include <Windows.h>
10
11
using namespace nall;
12
13
struct Interface : public SNES::Interface {
14
typedef SNES::Interface BaseType;
15
16
snes_video_refresh_t pvideo_refresh;
17
snes_audio_sample_t paudio_sample;
18
snes_input_poll_t pinput_poll;
19
snes_input_state_t pinput_state;
20
snes_input_notify_t pinput_notify;
21
snes_path_request_t ppath_request;
22
snes_allocSharedMemory_t pallocSharedMemory;
23
snes_freeSharedMemory_t pfreeSharedMemory;
24
snes_trace_t ptrace;
25
string basename;
26
uint32_t *buffer;
27
uint32_t *palette;
28
29
SnesCartridge cart;
30
31
//zero 11-sep-2012
32
time_t randomSeed() { return 0; }
33
34
//zero 26-sep-2012
35
std::queue<nall::string> messages;
36
37
//zero 17-oct-2012
38
int backdropColor;
39
int getBackdropColor()
40
{
41
return backdropColor;
42
}
43
44
void videoRefresh(const uint32_t *data, bool hires, bool interlace, bool overscan) {
45
unsigned width = hires ? 512 : 256;
46
unsigned height = overscan ? 239 : 224;
47
unsigned pitch = 1024 >> interlace;
48
if(interlace) height <<= 1;
49
data += 9 * 1024; //skip front porch
50
51
for(unsigned y = 0; y < height; y++) {
52
const uint32_t *sp = data + y * pitch;
53
uint32_t *dp = buffer + y * pitch;
54
for(unsigned x = 0; x < width; x++) {
55
*dp++ = palette[*sp++];
56
}
57
}
58
59
if(pvideo_refresh) pvideo_refresh(buffer, width, height);
60
if(pinput_poll) pinput_poll();
61
}
62
63
void audioSample(int16_t left, int16_t right) {
64
if(paudio_sample) return paudio_sample(left, right);
65
}
66
67
//zero 27-sep-2012
68
snes_scanlineStart_t pScanlineStart;
69
void scanlineStart(int line)
70
{
71
if(pScanlineStart) pScanlineStart((int)line);
72
}
73
74
int16_t inputPoll(bool port, SNES::Input::Device device, unsigned index, unsigned id) {
75
if(pinput_state) return pinput_state(port?1:0, (unsigned)device, index, id);
76
return 0;
77
}
78
79
void inputNotify(int index) {
80
if (pinput_notify) pinput_notify(index);
81
}
82
83
void message(const string &text) {
84
messages.push(text);
85
}
86
87
void cpuTrace(const char *msg) {
88
if (ptrace)
89
ptrace((const char *)msg);
90
}
91
92
string path(SNES::Cartridge::Slot slot, const string &hint)
93
{
94
if(ppath_request)
95
{
96
const char* path = ppath_request((int)slot, (const char*)hint);
97
return path;
98
}
99
return { basename, hint };
100
}
101
102
103
//zero 23-dec-2012
104
void* allocSharedMemory(const char* memtype, size_t amt, int initialByte = -1)
105
{
106
void* ret;
107
//if pallocSharedMemory isnt set up yet, we're going to have serious problems
108
ret = pallocSharedMemory(memtype,amt);
109
if(initialByte != -1)
110
{
111
for(unsigned i = 0; i < amt; i++) ((uint8*)ret)[i] = (uint8)initialByte;
112
}
113
return ret;
114
}
115
void freeSharedMemory(void* ptr)
116
{
117
if(!pfreeSharedMemory) return; //??
118
pfreeSharedMemory(ptr);
119
}
120
121
Interface() :
122
pvideo_refresh(0),
123
paudio_sample(0),
124
pinput_poll(0),
125
pinput_state(0),
126
pinput_notify(0),
127
ppath_request(0),
128
pScanlineStart(0),
129
pallocSharedMemory(0),
130
pfreeSharedMemory(0),
131
backdropColor(-1),
132
ptrace(0),
133
cart(nullptr, 0)
134
{
135
buffer = new uint32_t[512 * 480];
136
palette = new uint32_t[16 * 32768];
137
memset(&cdlInfo,0,sizeof(cdlInfo));
138
}
139
140
~Interface() {
141
delete[] buffer;
142
delete[] palette;
143
}
144
};
145
146
void pwrap_init();
147
Interface *iface = nullptr;
148
namespace SNES {
149
SNES::Interface *interface()
150
{
151
if(iface != nullptr) return iface;
152
iface = new ::Interface();
153
pwrap_init();
154
return iface;
155
}
156
}
157
158
const char* snes_library_id(void) {
159
static string version = {"bsnes v", Version};
160
return version;
161
}
162
163
unsigned snes_library_revision_major(void) {
164
return 1;
165
}
166
167
unsigned snes_library_revision_minor(void) {
168
return 3;
169
}
170
171
void snes_set_allocSharedMemory(snes_allocSharedMemory_t cb)
172
{
173
iface->pallocSharedMemory = cb;
174
}
175
void snes_set_freeSharedMemory(snes_freeSharedMemory_t cb)
176
{
177
iface->pfreeSharedMemory = cb;
178
}
179
180
void snes_set_video_refresh(snes_video_refresh_t video_refresh) {
181
iface->pvideo_refresh = video_refresh;
182
}
183
184
void snes_set_color_lut(uint32_t * colors) {
185
for (int i = 0; i < 16 * 32768; i++)
186
iface->palette[i] = colors[i];
187
}
188
189
void snes_set_audio_sample(snes_audio_sample_t audio_sample) {
190
iface->paudio_sample = audio_sample;
191
}
192
193
void snes_set_input_poll(snes_input_poll_t input_poll) {
194
iface->pinput_poll = input_poll;
195
}
196
197
void snes_set_input_state(snes_input_state_t input_state) {
198
iface->pinput_state = input_state;
199
}
200
201
void snes_set_input_notify(snes_input_notify_t input_notify) {
202
iface->pinput_notify = input_notify;
203
}
204
205
void snes_set_path_request(snes_path_request_t path_request)
206
{
207
iface->ppath_request = path_request;
208
}
209
210
void snes_set_controller_port_device(bool port, unsigned device) {
211
SNES::input.connect(port, (SNES::Input::Device)device);
212
}
213
214
void snes_set_cartridge_basename(const char *basename) {
215
iface->basename = basename;
216
}
217
218
template<typename T> inline void reconstruct(T* t) {
219
t->~T();
220
memset(t,0,sizeof(*t));
221
new(t) T();
222
}
223
224
void snes_init(void) {
225
226
//force everything to get initialized, even though it probably already is
227
SNES::interface();
228
229
//zero 01-sep-2014 - this is too slow. made rewind totally boring. made other edits to firmware chips to preserve their roms instead
230
//zero 22-may-2014 - why not this too, for the sake of completeness?
231
//reconstruct(&SNES::cartridge);
232
233
//zero 01-dec-2012 - due to systematic variable initialization fails in bsnes components, these reconstructions are necessary,
234
//and the previous comment here which called this paranoid has been removed.
235
reconstruct(&SNES::icd2);
236
reconstruct(&SNES::nss);
237
reconstruct(&SNES::superfx);
238
reconstruct(&SNES::sa1);
239
reconstruct(&SNES::necdsp);
240
reconstruct(&SNES::hitachidsp);
241
reconstruct(&SNES::armdsp);
242
reconstruct(&SNES::bsxsatellaview);
243
reconstruct(&SNES::bsxcartridge);
244
reconstruct(&SNES::bsxflash);
245
reconstruct(&SNES::srtc); SNES::srtc.initialize();
246
reconstruct(&SNES::sdd1);
247
reconstruct(&SNES::spc7110); SNES::spc7110.initialize();
248
reconstruct(&SNES::obc1);
249
reconstruct(&SNES::msu1);
250
reconstruct(&SNES::link);
251
reconstruct(&SNES::video);
252
reconstruct(&SNES::audio);
253
254
//zero 01-dec-2012 - forgot to do all these. massive desync chaos!
255
//remove these to make it easier to find initialization fails in the component power-ons / constructors / etc.
256
//or just forget about it. this snes_init gets called paranoidly frequently by bizhawk, so things should stay zeroed correctly
257
reconstruct(&SNES::cpu); SNES::cpu.initialize();
258
reconstruct(&SNES::smp); SNES::smp.initialize();
259
reconstruct(&SNES::dsp);
260
reconstruct(&SNES::ppu);
261
SNES::ppu.initialize();
262
SNES::system.init();
263
264
//zero 26-aug-2013 - yup. still more
265
reconstruct(&GameBoy::cpu); GameBoy::cpu.initialize();
266
267
SNES::input.connect(SNES::Controller::Port1, SNES::Input::Device::Joypad);
268
SNES::input.connect(SNES::Controller::Port2, SNES::Input::Device::Joypad);
269
}
270
271
void snes_term(void) {
272
SNES::system.term();
273
}
274
275
void snes_power(void) {
276
SNES::system.power();
277
}
278
279
void snes_reset(void) {
280
SNES::system.reset();
281
}
282
283
void snes_run(void) {
284
SNES::system.run();
285
}
286
287
unsigned snes_serialize_size(void) {
288
return SNES::system.serialize_size();
289
}
290
291
bool snes_serialize(uint8_t *data, unsigned size) {
292
SNES::system.runtosave();
293
serializer s = SNES::system.serialize();
294
if(s.size() > size) return false;
295
memcpy(data, s.data(), s.size());
296
return true;
297
}
298
299
bool snes_unserialize(const uint8_t *data, unsigned size) {
300
serializer s(data, size);
301
return SNES::system.unserialize(s);
302
}
303
304
struct CheatList {
305
bool enable;
306
string code;
307
CheatList() : enable(false) {}
308
};
309
310
static linear_vector<CheatList> cheatList;
311
312
void snes_cheat_reset(void) {
313
cheatList.reset();
314
GameBoy::cheat.reset();
315
GameBoy::cheat.synchronize();
316
SNES::cheat.reset();
317
SNES::cheat.synchronize();
318
}
319
320
void snes_cheat_set(unsigned index, bool enable, const char *code) {
321
cheatList[index].enable = enable;
322
cheatList[index].code = code;
323
lstring list;
324
for(unsigned n = 0; n < cheatList.size(); n++) {
325
if(cheatList[n].enable) list.append(cheatList[n].code);
326
}
327
328
if(SNES::cartridge.mode() == SNES::Cartridge::Mode::SuperGameBoy) {
329
GameBoy::cheat.reset();
330
for(auto &code : list) {
331
lstring codelist;
332
codelist.split("+", code);
333
for(auto &part : codelist) {
334
unsigned addr, data, comp;
335
if(GameBoy::Cheat::decode(part, addr, data, comp)) {
336
GameBoy::cheat.append({ addr, data, comp });
337
}
338
}
339
}
340
GameBoy::cheat.synchronize();
341
return;
342
}
343
344
SNES::cheat.reset();
345
for(auto &code : list) {
346
lstring codelist;
347
codelist.split("+", code);
348
for(auto &part : codelist) {
349
unsigned addr, data;
350
if(SNES::Cheat::decode(part, addr, data)) {
351
SNES::cheat.append({ addr, data });
352
}
353
}
354
}
355
SNES::cheat.synchronize();
356
}
357
358
//zero 21-sep-2012
359
void snes_set_scanlineStart(snes_scanlineStart_t cb)
360
{
361
iface->pScanlineStart = cb;
362
}
363
364
//zero 03-sep-2012
365
bool snes_check_cartridge(const uint8_t *rom_data, unsigned rom_size)
366
{
367
//tries to determine whether this rom is a snes rom - BUT THIS TRIES TO ACCEPT EVERYTHING! so we cant really use it
368
SnesCartridge temp(rom_data, rom_size);
369
return temp.type != SnesCartridge::TypeUnknown && temp.type != SnesCartridge::TypeGameBoy;
370
}
371
372
//zero 05-sep-2012
373
int snes_peek_logical_register(int reg)
374
{
375
switch(reg)
376
{
377
//$2105
378
//zero 17-may-2014 TODO - enable these for other profiles
379
#if !defined(PROFILE_PERFORMANCE) && !defined(PROFILE_ACCURACY)
380
case SNES_REG_BG_MODE: return SNES::ppu.regs.bg_mode;
381
case SNES_REG_BG3_PRIORITY: return SNES::ppu.regs.bg3_priority;
382
case SNES_REG_BG1_TILESIZE: return SNES::ppu.regs.bg_tilesize[SNES::PPU::BG1];
383
case SNES_REG_BG2_TILESIZE: return SNES::ppu.regs.bg_tilesize[SNES::PPU::BG2];
384
case SNES_REG_BG3_TILESIZE: return SNES::ppu.regs.bg_tilesize[SNES::PPU::BG3];
385
case SNES_REG_BG4_TILESIZE: return SNES::ppu.regs.bg_tilesize[SNES::PPU::BG4];
386
387
//$2107
388
case SNES_REG_BG1_SCADDR: return SNES::ppu.regs.bg_scaddr[SNES::PPU::BG1]>>9;
389
case SNES_REG_BG1_SCSIZE: return SNES::ppu.regs.bg_scsize[SNES::PPU::BG1];
390
//$2108
391
case SNES_REG_BG2_SCADDR: return SNES::ppu.regs.bg_scaddr[SNES::PPU::BG2]>>9;
392
case SNES_REG_BG2_SCSIZE: return SNES::ppu.regs.bg_scsize[SNES::PPU::BG2];
393
//$2109
394
case SNES_REG_BG3_SCADDR: return SNES::ppu.regs.bg_scaddr[SNES::PPU::BG3]>>9;
395
case SNES_REG_BG3_SCSIZE: return SNES::ppu.regs.bg_scsize[SNES::PPU::BG3];
396
//$210A
397
case SNES_REG_BG4_SCADDR: return SNES::ppu.regs.bg_scaddr[SNES::PPU::BG4]>>9;
398
case SNES_REG_BG4_SCSIZE: return SNES::ppu.regs.bg_scsize[SNES::PPU::BG4];
399
//$210B
400
case SNES_REG_BG1_TDADDR: return SNES::ppu.regs.bg_tdaddr[SNES::PPU::BG1]>>13;
401
case SNES_REG_BG2_TDADDR: return SNES::ppu.regs.bg_tdaddr[SNES::PPU::BG2]>>13;
402
//$210C
403
case SNES_REG_BG3_TDADDR: return SNES::ppu.regs.bg_tdaddr[SNES::PPU::BG3]>>13;
404
case SNES_REG_BG4_TDADDR: return SNES::ppu.regs.bg_tdaddr[SNES::PPU::BG4]>>13;
405
//$2133 SETINI
406
case SNES_REG_SETINI_MODE7_EXTBG: return SNES::ppu.regs.mode7_extbg?1:0;
407
case SNES_REG_SETINI_HIRES: return SNES::ppu.regs.pseudo_hires?1:0;
408
case SNES_REG_SETINI_OVERSCAN: return SNES::ppu.regs.overscan?1:0;
409
case SNES_REG_SETINI_OBJ_INTERLACE: return SNES::ppu.regs.oam_interlace?1:0;
410
case SNES_REG_SETINI_SCREEN_INTERLACE: return SNES::ppu.regs.interlace?1:0;
411
//$2130 CGWSEL
412
case SNES_REG_CGWSEL_COLORMASK: return SNES::ppu.regs.color_mask;
413
case SNES_REG_CGWSEL_COLORSUBMASK: return SNES::ppu.regs.colorsub_mask;
414
case SNES_REG_CGWSEL_ADDSUBMODE: return SNES::ppu.regs.addsub_mode?1:0;
415
case SNES_REG_CGWSEL_DIRECTCOLOR: return SNES::ppu.regs.direct_color?1:0;
416
//$2101 OBSEL
417
case SNES_REG_OBSEL_NAMEBASE: return SNES::ppu.regs.oam_tdaddr>>14;
418
case SNES_REG_OBSEL_NAMESEL: return SNES::ppu.regs.oam_nameselect;
419
case SNES_REG_OBSEL_SIZE: return SNES::ppu.regs.oam_basesize;
420
//$2131 CGADSUB
421
//enum { BG1 = 0, BG2 = 1, BG3 = 2, BG4 = 3, OAM = 4, BACK = 5, COL = 5 };
422
case SNES_REG_CGADSUB_MODE: return SNES::ppu.regs.color_mode;
423
case SNES_REG_CGADSUB_HALF: return SNES::ppu.regs.color_halve;
424
case SNES_REG_CGADSUB_BG4: return SNES::ppu.regs.color_enabled[3];
425
case SNES_REG_CGADSUB_BG3: return SNES::ppu.regs.color_enabled[2];
426
case SNES_REG_CGADSUB_BG2: return SNES::ppu.regs.color_enabled[1];
427
case SNES_REG_CGADSUB_BG1: return SNES::ppu.regs.color_enabled[0];
428
case SNES_REG_CGADSUB_OBJ: return SNES::ppu.regs.color_enabled[4];
429
case SNES_REG_CGADSUB_BACKDROP: return SNES::ppu.regs.color_enabled[5];
430
//$212C TM
431
case SNES_REG_TM_BG1: return SNES::ppu.regs.bg_enabled[0];
432
case SNES_REG_TM_BG2: return SNES::ppu.regs.bg_enabled[1];
433
case SNES_REG_TM_BG3: return SNES::ppu.regs.bg_enabled[2];
434
case SNES_REG_TM_BG4: return SNES::ppu.regs.bg_enabled[3];
435
case SNES_REG_TM_OBJ: return SNES::ppu.regs.bg_enabled[4];
436
//$212D TM
437
case SNES_REG_TS_BG1: return SNES::ppu.regs.bgsub_enabled[0];
438
case SNES_REG_TS_BG2: return SNES::ppu.regs.bgsub_enabled[1];
439
case SNES_REG_TS_BG3: return SNES::ppu.regs.bgsub_enabled[2];
440
case SNES_REG_TS_BG4: return SNES::ppu.regs.bgsub_enabled[3];
441
case SNES_REG_TS_OBJ: return SNES::ppu.regs.bgsub_enabled[4];
442
//Mode7 regs
443
case SNES_REG_M7SEL_REPEAT: return SNES::ppu.regs.mode7_repeat;
444
case SNES_REG_M7SEL_HFLIP: return SNES::ppu.regs.mode7_vflip;
445
case SNES_REG_M7SEL_VFLIP: return SNES::ppu.regs.mode7_hflip;
446
case SNES_REG_M7A: return SNES::ppu.regs.m7a;
447
case SNES_REG_M7B: return SNES::ppu.regs.m7b;
448
case SNES_REG_M7C: return SNES::ppu.regs.m7c;
449
case SNES_REG_M7D: return SNES::ppu.regs.m7d;
450
case SNES_REG_M7X: return SNES::ppu.regs.m7x;
451
case SNES_REG_M7Y: return SNES::ppu.regs.m7y;
452
//BG scroll regs
453
case SNES_REG_BG1HOFS: return SNES::ppu.regs.bg_hofs[0] & 0x3FF;
454
case SNES_REG_BG1VOFS: return SNES::ppu.regs.bg_vofs[0] & 0x3FF;
455
case SNES_REG_BG2HOFS: return SNES::ppu.regs.bg_hofs[1] & 0x3FF;
456
case SNES_REG_BG2VOFS: return SNES::ppu.regs.bg_vofs[1] & 0x3FF;
457
case SNES_REG_BG3HOFS: return SNES::ppu.regs.bg_hofs[2] & 0x3FF;
458
case SNES_REG_BG3VOFS: return SNES::ppu.regs.bg_vofs[2] & 0x3FF;
459
case SNES_REG_BG4HOFS: return SNES::ppu.regs.bg_hofs[3] & 0x3FF;
460
case SNES_REG_BG4VOFS: return SNES::ppu.regs.bg_vofs[3] & 0x3FF;
461
case SNES_REG_M7HOFS: return SNES::ppu.regs.m7_hofs & 0x1FFF; //rememebr to make these signed with <<19>>19
462
case SNES_REG_M7VOFS: return SNES::ppu.regs.m7_vofs & 0x1FFF; //rememebr to make these signed with <<19>>19
463
#endif
464
465
}
466
return 0;
467
}
468
469
bool snes_load_cartridge_normal(
470
const char *rom_xml, const uint8_t *rom_data, unsigned rom_size
471
) {
472
snes_cheat_reset();
473
if(rom_data) SNES::cartridge.rom.copy(rom_data, rom_size);
474
iface->cart = SnesCartridge(rom_data, rom_size);
475
string xmlrom = (rom_xml && *rom_xml) ? string(rom_xml) : iface->cart.markup;
476
SNES::cartridge.load(SNES::Cartridge::Mode::Normal, { xmlrom });
477
SNES::system.power();
478
return true;
479
}
480
481
bool snes_load_cartridge_bsx_slotted(
482
const char *rom_xml, const uint8_t *rom_data, unsigned rom_size,
483
const char *bsx_xml, const uint8_t *bsx_data, unsigned bsx_size
484
) {
485
snes_cheat_reset();
486
if(rom_data) SNES::cartridge.rom.copy(rom_data, rom_size);
487
iface->cart = SnesCartridge(rom_data, rom_size);
488
string xmlrom = (rom_xml && *rom_xml) ? string(rom_xml) : iface->cart.markup;
489
if(bsx_data) SNES::bsxflash.memory.copy(bsx_data, bsx_size);
490
string xmlbsx = (bsx_xml && *bsx_xml) ? string(bsx_xml) : SnesCartridge(bsx_data, bsx_size).markup;
491
SNES::cartridge.load(SNES::Cartridge::Mode::BsxSlotted, xmlrom);
492
SNES::system.power();
493
return true;
494
}
495
496
bool snes_load_cartridge_bsx(
497
const char *rom_xml, const uint8_t *rom_data, unsigned rom_size,
498
const char *bsx_xml, const uint8_t *bsx_data, unsigned bsx_size
499
) {
500
snes_cheat_reset();
501
if(rom_data) SNES::cartridge.rom.copy(rom_data, rom_size);
502
iface->cart = SnesCartridge(rom_data, rom_size);
503
string xmlrom = (rom_xml && *rom_xml) ? string(rom_xml) : iface->cart.markup;
504
if(bsx_data) SNES::bsxflash.memory.copy(bsx_data, bsx_size);
505
string xmlbsx = (bsx_xml && *bsx_xml) ? string(bsx_xml) : SnesCartridge(bsx_data, bsx_size).markup;
506
SNES::cartridge.load(SNES::Cartridge::Mode::Bsx, xmlrom);
507
SNES::system.power();
508
return true;
509
}
510
511
bool snes_load_cartridge_sufami_turbo(
512
const char *rom_xml, const uint8_t *rom_data, unsigned rom_size,
513
const char *sta_xml, const uint8_t *sta_data, unsigned sta_size,
514
const char *stb_xml, const uint8_t *stb_data, unsigned stb_size
515
) {
516
snes_cheat_reset();
517
if(rom_data) SNES::cartridge.rom.copy(rom_data, rom_size);
518
iface->cart = SnesCartridge(rom_data, rom_size);
519
string xmlrom = (rom_xml && *rom_xml) ? string(rom_xml) : iface->cart.markup;
520
if(sta_data) SNES::sufamiturbo.slotA.rom.copy(sta_data, sta_size);
521
string xmlsta = (sta_xml && *sta_xml) ? string(sta_xml) : SnesCartridge(sta_data, sta_size).markup;
522
if(stb_data) SNES::sufamiturbo.slotB.rom.copy(stb_data, stb_size);
523
string xmlstb = (stb_xml && *stb_xml) ? string(stb_xml) : SnesCartridge(stb_data, stb_size).markup;
524
SNES::cartridge.load(SNES::Cartridge::Mode::SufamiTurbo, xmlrom);
525
SNES::system.power();
526
return true;
527
}
528
529
bool snes_load_cartridge_super_game_boy(
530
const char *rom_xml, const uint8_t *rom_data, unsigned rom_size,
531
const char *dmg_xml, const uint8_t *dmg_data, unsigned dmg_size
532
) {
533
snes_cheat_reset();
534
if(rom_data) SNES::cartridge.rom.copy(rom_data, rom_size);
535
iface->cart = SnesCartridge(rom_data, rom_size);
536
string xmlrom = (rom_xml && *rom_xml) ? string(rom_xml) : iface->cart.markup;
537
if(dmg_data) {
538
//GameBoyCartridge needs to modify dmg_data (for MMM01 emulation); so copy data
539
uint8_t *data = new uint8_t[dmg_size];
540
memcpy(data, dmg_data, dmg_size);
541
string xmldmg = (dmg_xml && *dmg_xml) ? string(dmg_xml) : GameBoyCartridge(data, dmg_size).markup;
542
GameBoy::cartridge.load(GameBoy::System::Revision::SuperGameBoy, xmldmg, data, dmg_size);
543
delete[] data;
544
}
545
SNES::cartridge.load(SNES::Cartridge::Mode::SuperGameBoy, xmlrom);
546
SNES::system.power();
547
return true;
548
}
549
550
void snes_unload_cartridge(void) {
551
SNES::cartridge.unload();
552
}
553
554
bool snes_get_region(void) {
555
return SNES::system.region() == SNES::System::Region::NTSC ? 0 : 1;
556
}
557
558
char snes_get_mapper(void) {
559
return iface->cart.mapper;
560
}
561
562
uint8_t* snes_get_memory_data(unsigned id) {
563
if(SNES::cartridge.loaded() == false) return 0;
564
565
switch(id) {
566
case SNES_MEMORY_CARTRIDGE_RAM:
567
return SNES::cartridge.ram.data();
568
case SNES_MEMORY_CARTRIDGE_RTC:
569
if(SNES::cartridge.has_srtc()) return SNES::srtc.rtc;
570
if(SNES::cartridge.has_spc7110rtc()) return SNES::spc7110.rtc;
571
return 0;
572
case SNES_MEMORY_BSX_RAM:
573
if(SNES::cartridge.mode() != SNES::Cartridge::Mode::Bsx) break;
574
return SNES::bsxcartridge.sram.data();
575
case SNES_MEMORY_BSX_PRAM:
576
if(SNES::cartridge.mode() != SNES::Cartridge::Mode::Bsx) break;
577
return SNES::bsxcartridge.psram.data();
578
case SNES_MEMORY_SUFAMI_TURBO_A_RAM:
579
if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SufamiTurbo) break;
580
return SNES::sufamiturbo.slotA.ram.data();
581
case SNES_MEMORY_SUFAMI_TURBO_B_RAM:
582
if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SufamiTurbo) break;
583
return SNES::sufamiturbo.slotB.ram.data();
584
case SNES_MEMORY_GAME_BOY_CARTRAM:
585
if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SuperGameBoy) break;
586
return GameBoy::cartridge.ramdata;
587
//case SNES_MEMORY_GAME_BOY_RTC:
588
// if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SuperGameBoy) break;
589
// return GameBoy::cartridge.rtcdata;
590
case SNES_MEMORY_GAME_BOY_WRAM:
591
if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SuperGameBoy) break;
592
return GameBoy::cpu.wram;
593
case SNES_MEMORY_GAME_BOY_HRAM:
594
if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SuperGameBoy) break;
595
return GameBoy::cpu.hram;
596
597
case SNES_MEMORY_WRAM:
598
return SNES::cpu.wram;
599
case SNES_MEMORY_APURAM:
600
return SNES::smp.apuram;
601
case SNES_MEMORY_VRAM:
602
return SNES::ppu.vram;
603
case SNES_MEMORY_OAM:
604
return SNES::ppu.oam;
605
case SNES_MEMORY_CGRAM:
606
return SNES::ppu.cgram;
607
608
case SNES_MEMORY_CARTRIDGE_ROM:
609
return SNES::cartridge.rom.data();
610
}
611
612
return 0;
613
}
614
615
const char* snes_get_memory_id_name(unsigned id) {
616
if(SNES::cartridge.loaded() == false) return nullptr;
617
618
switch(id) {
619
case SNES_MEMORY_CARTRIDGE_RAM:
620
return "CARTRIDGE_RAM";
621
case SNES_MEMORY_CARTRIDGE_RTC:
622
if(SNES::cartridge.has_srtc()) return "RTC";
623
if(SNES::cartridge.has_spc7110rtc()) return "SPC7110_RTC";
624
return nullptr;
625
case SNES_MEMORY_BSX_RAM:
626
if(SNES::cartridge.mode() != SNES::Cartridge::Mode::Bsx) break;
627
return "BSX_SRAM";
628
case SNES_MEMORY_BSX_PRAM:
629
if(SNES::cartridge.mode() != SNES::Cartridge::Mode::Bsx) break;
630
return "BSX_PSRAM";
631
case SNES_MEMORY_SUFAMI_TURBO_A_RAM:
632
if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SufamiTurbo) break;
633
return "SUFAMI_SLOTARAM";
634
case SNES_MEMORY_SUFAMI_TURBO_B_RAM:
635
if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SufamiTurbo) break;
636
return "SUFAMI_SLOTBRAM";
637
case SNES_MEMORY_GAME_BOY_CARTRAM:
638
if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SuperGameBoy) break;
639
//return GameBoy::cartridge.ramdata;
640
return "SGB_CARTRAM";
641
//case SNES_MEMORY_GAME_BOY_RTC:
642
// if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SuperGameBoy) break;
643
// return GameBoy::cartridge.rtcdata;
644
case SNES_MEMORY_GAME_BOY_WRAM:
645
if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SuperGameBoy) break;
646
//see notes in SetupMemoryDomains in bizhawk
647
return "SGB_WRAM";
648
case SNES_MEMORY_GAME_BOY_HRAM:
649
if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SuperGameBoy) break;
650
return "SGB_HRAM";
651
652
case SNES_MEMORY_WRAM:
653
//return SNES::cpu.wram;
654
return "WRAM";
655
case SNES_MEMORY_APURAM:
656
//return SNES::smp.apuram;
657
return "APURAM";
658
case SNES_MEMORY_VRAM:
659
return "VRAM";
660
case SNES_MEMORY_OAM:
661
return "OAM";
662
case SNES_MEMORY_CGRAM:
663
return "CGRAM";
664
665
case SNES_MEMORY_CARTRIDGE_ROM:
666
return "CARTRIDGE_ROM";
667
}
668
669
return nullptr;
670
}
671
672
unsigned snes_get_memory_size(unsigned id) {
673
if(SNES::cartridge.loaded() == false) return 0;
674
unsigned size = 0;
675
676
switch(id) {
677
case SNES_MEMORY_CARTRIDGE_RAM:
678
size = SNES::cartridge.ram.size();
679
break;
680
case SNES_MEMORY_CARTRIDGE_RTC:
681
if(SNES::cartridge.has_srtc() || SNES::cartridge.has_spc7110rtc()) size = 20;
682
break;
683
case SNES_MEMORY_BSX_RAM:
684
if(SNES::cartridge.mode() != SNES::Cartridge::Mode::Bsx) break;
685
size = SNES::bsxcartridge.sram.size();
686
break;
687
case SNES_MEMORY_BSX_PRAM:
688
if(SNES::cartridge.mode() != SNES::Cartridge::Mode::Bsx) break;
689
size = SNES::bsxcartridge.psram.size();
690
break;
691
case SNES_MEMORY_SUFAMI_TURBO_A_RAM:
692
if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SufamiTurbo) break;
693
size = SNES::sufamiturbo.slotA.ram.size();
694
break;
695
case SNES_MEMORY_SUFAMI_TURBO_B_RAM:
696
if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SufamiTurbo) break;
697
size = SNES::sufamiturbo.slotB.ram.size();
698
break;
699
case SNES_MEMORY_GAME_BOY_CARTRAM:
700
if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SuperGameBoy) break;
701
size = GameBoy::cartridge.ramsize;
702
break;
703
//case SNES_MEMORY_GAME_BOY_RTC:
704
// if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SuperGameBoy) break;
705
// size = GameBoy::cartridge.rtcsize;
706
// break;
707
case SNES_MEMORY_GAME_BOY_WRAM:
708
if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SuperGameBoy) break;
709
//see notes in SetupMemoryDomains in bizhawk
710
size = 32768;
711
break;
712
case SNES_MEMORY_GAME_BOY_HRAM:
713
if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SuperGameBoy) break;
714
size = 128;
715
break;
716
717
case SNES_MEMORY_WRAM:
718
size = 128 * 1024;
719
break;
720
case SNES_MEMORY_APURAM:
721
size = 64 * 1024;
722
break;
723
case SNES_MEMORY_VRAM:
724
size = 64 * 1024;
725
break;
726
case SNES_MEMORY_OAM:
727
size = 544;
728
break;
729
case SNES_MEMORY_CGRAM:
730
size = 512;
731
break;
732
733
case SNES_MEMORY_CARTRIDGE_ROM:
734
size = SNES::cartridge.rom.size();
735
break;
736
}
737
738
if(size == -1U) size = 0;
739
return size;
740
}
741
742
uint8_t bus_read(unsigned addr) {
743
return SNES::bus.read(addr);
744
}
745
void bus_write(unsigned addr, uint8_t val) {
746
SNES::bus.write(addr, val);
747
}
748
749
int snes_poll_message()
750
{
751
if(iface->messages.empty()) return -1;
752
return iface->messages.front().length();
753
}
754
void snes_dequeue_message(char* buffer)
755
{
756
int len = iface->messages.front().length();
757
memcpy(buffer,(const char*)iface->messages.front(),len);
758
iface->messages.pop();
759
}
760
761
void snes_set_backdropColor(int color)
762
{
763
iface->backdropColor = color;
764
}
765
766
void snes_set_trace_callback(snes_trace_t callback)
767
{
768
if (callback)
769
{
770
iface->wanttrace = true;
771
iface->ptrace = callback;
772
}
773
else
774
{
775
iface->wanttrace = false;
776
iface->ptrace = 0;
777
}
778
}
779