SNES: New controller types gamepad16 and multitap16
[lsnes.git] / src / core / bsnes-legacy.cpp
blob298013a8e3ccbe4e0e06452555b380e5215f4ecc
1 #ifdef CORETYPE_BSNES
2 #include "lsnes.hpp"
3 #include <sstream>
4 #include <map>
5 #include <string>
6 #include <vector>
7 #include <fstream>
8 #include "core/audioapi.hpp"
9 #include "core/misc.hpp"
10 #include "core/emucore.hpp"
11 #include "core/command.hpp"
12 #include "core/controllerframe.hpp"
13 #include "core/dispatch.hpp"
14 #include "core/framebuffer.hpp"
15 #include "core/settings.hpp"
16 #include "core/window.hpp"
17 #include "library/pixfmt-lrgb.hpp"
18 #include "library/string.hpp"
19 #include "library/framebuffer.hpp"
20 #include <snes/snes.hpp>
21 #include <gameboy/gameboy.hpp>
22 #ifdef BSNES_V087
23 #include <target-libsnes/libsnes.hpp>
24 #else
25 #include <ui-libsnes/libsnes.hpp>
26 #endif
28 #define DURATION_NTSC_FRAME 357366
29 #define DURATION_NTSC_FIELD 357368
30 #define DURATION_PAL_FRAME 425568
31 #define DURATION_PAL_FIELD 425568
32 #define ROM_TYPE_NONE 0
33 #define ROM_TYPE_SNES 1
34 #define ROM_TYPE_BSX 2
35 #define ROM_TYPE_BSXSLOTTED 3
36 #define ROM_TYPE_SUFAMITURBO 4
37 #define ROM_TYPE_SGB 5
39 /**
40 * Logical button IDs.
42 #define LOGICAL_BUTTON_LEFT 0
43 #define LOGICAL_BUTTON_RIGHT 1
44 #define LOGICAL_BUTTON_UP 2
45 #define LOGICAL_BUTTON_DOWN 3
46 #define LOGICAL_BUTTON_A 4
47 #define LOGICAL_BUTTON_B 5
48 #define LOGICAL_BUTTON_X 6
49 #define LOGICAL_BUTTON_Y 7
50 #define LOGICAL_BUTTON_L 8
51 #define LOGICAL_BUTTON_R 9
52 #define LOGICAL_BUTTON_SELECT 10
53 #define LOGICAL_BUTTON_START 11
54 #define LOGICAL_BUTTON_TRIGGER 12
55 #define LOGICAL_BUTTON_CURSOR 13
56 #define LOGICAL_BUTTON_TURBO 14
57 #define LOGICAL_BUTTON_PAUSE 15
58 #define LOGICAL_BUTTON_EXT0 16
59 #define LOGICAL_BUTTON_EXT1 17
60 #define LOGICAL_BUTTON_EXT2 18
61 #define LOGICAL_BUTTON_EXT3 19
63 const char* button_symbols = "BYsSudlrAXLR0123TSTCUPFR";
64 const char* controller_names[] = {"(system)", "gamepad", "mouse", "superscope", "justifier", "gamepad16"};
66 port_type_group core_portgroup;
67 unsigned core_userports = 2;
68 extern const bool core_supports_reset = true;
69 #ifdef BSNES_HAS_DEBUGGER
70 extern const bool core_supports_dreset = true;
71 #else
72 extern const bool core_supports_dreset = false;
73 #endif
75 namespace
77 long do_reset_flag = -1;
78 bool pollflag_active = true;
79 boolean_setting allow_inconsistent_saves(lsnes_set, "allow-inconsistent-saves", false);
80 boolean_setting save_every_frame(lsnes_set, "save-every-frame", false);
81 uint32_t norom_frame[512 * 448];
82 bool have_saved_this_frame = false;
83 int16_t blanksound[1070] = {0};
84 int16_t soundbuf[8192] = {0};
85 size_t soundbuf_fill = 0;
87 void init_norom_frame()
89 static bool done = false;
90 if(done)
91 return;
92 done = true;
93 for(size_t i = 0; i < 512 * 448; i++)
94 norom_frame[i] = 0x7C21F;
97 int regions_compatible(unsigned rom, unsigned run)
99 return (!rom || rom == run);
102 unsigned header_fn(size_t r)
104 if((r % 1024) == 512)
105 return 512;
106 else
107 return 0;
110 core_type* internal_rom = NULL;
111 extern core_type type_snes;
112 extern core_type type_bsx;
113 extern core_type type_bsxslotted;
114 extern core_type type_sufamiturbo;
115 extern core_type type_sgb;
117 int load_rom_snes(core_romimage* img, uint64_t secs, uint64_t subsecs)
119 snes_term();
120 snes_unload_cartridge();
121 bool r = snes_load_cartridge_normal(img[0].markup, img[0].data, img[0].size);
122 if(r)
123 internal_rom = &type_snes;
124 have_saved_this_frame = false;
125 do_reset_flag = -1;
126 return r ? 0 : -1;
129 int load_rom_bsx(core_romimage* img, uint64_t secs, uint64_t subsecs)
131 snes_term();
132 snes_unload_cartridge();
133 bool r = snes_load_cartridge_bsx(img[0].markup, img[0].data, img[0].size,
134 img[1].markup, img[1].data, img[1].size);
135 if(r)
136 internal_rom = &type_bsx;
137 have_saved_this_frame = false;
138 do_reset_flag = -1;
139 return r ? 0 : -1;
142 int load_rom_bsxslotted(core_romimage* img, uint64_t secs, uint64_t subsecs)
144 snes_term();
145 snes_unload_cartridge();
146 bool r = snes_load_cartridge_bsx_slotted(img[0].markup, img[0].data, img[0].size,
147 img[1].markup, img[1].data, img[1].size);
148 if(r)
149 internal_rom = &type_bsxslotted;
150 have_saved_this_frame = false;
151 do_reset_flag = -1;
152 return r ? 0 : -1;
155 int load_rom_sgb(core_romimage* img, uint64_t secs, uint64_t subsecs)
157 snes_term();
158 snes_unload_cartridge();
159 bool r = snes_load_cartridge_super_game_boy(img[0].markup, img[0].data, img[0].size,
160 img[1].markup, img[1].data, img[1].size);
161 if(r)
162 internal_rom = &type_sgb;
163 have_saved_this_frame = false;
164 do_reset_flag = -1;
165 return r ? 0 : -1;
168 int load_rom_sufamiturbo(core_romimage* img, uint64_t secs, uint64_t subsecs)
170 snes_term();
171 snes_unload_cartridge();
172 bool r = snes_load_cartridge_sufami_turbo(img[0].markup, img[0].data, img[0].size,
173 img[1].markup, img[1].data, img[1].size, img[2].markup, img[2].data, img[2].size);
174 if(r)
175 internal_rom = &type_sufamiturbo;
176 have_saved_this_frame = false;
177 do_reset_flag = -1;
178 return r ? 0 : -1;
181 uint64_t ntsc_magic[4] = {178683, 10738636, 16639264, 596096};
182 uint64_t pal_magic[4] = {6448, 322445, 19997208, 266440};
184 core_region region_auto("autodetect", "Autodetect", 1, 0, true, ntsc_magic, regions_compatible);
185 core_region region_ntsc("ntsc", "NTSC", 0, 1, true, ntsc_magic, regions_compatible);
186 core_region region_pal("pal", "PAL", 0, 2, true, pal_magic, regions_compatible);
187 core_romimage_info image_snescart("rom", "Cartridge ROM", 1, header_fn);
188 core_romimage_info image_bsxbios("rom", "BS-X BIOS", 1, header_fn);
189 core_romimage_info image_bsxflash("bsx", "BS-X Flash", 2, header_fn);
190 core_romimage_info image_bsxsflash("bsx", "BS-X Flash", 2, header_fn);
191 core_romimage_info image_sgbbios("rom", "SGB BIOS", 1, header_fn);
192 core_romimage_info image_dmg("dmg", "DMG ROM", 2, header_fn);
193 core_romimage_info image_stbios("rom", "ST BIOS", 1, header_fn);
194 core_romimage_info image_stslota("slot-a", "ST Slot A ROM", 2, header_fn);
195 core_romimage_info image_stslotb("slot-b", "ST Slot B ROM", 2, header_fn);
196 core_type type_snes("snes", "SNES", 0, load_rom_snes, "sfc;smc;swc;fig;ufo;sf2;gd3;gd7;dx2;mgd;mgh");
197 core_type type_bsx("bsx", "BS-X (non-slotted)", 1, load_rom_bsx, "bsx.sfc!bs");
198 core_type type_bsxslotted("bsxslotted", "BS-X (slotted)", 2, load_rom_bsxslotted, "bsxslotted.sfc!bss");
199 core_type type_sufamiturbo("sufamiturbo", "Sufami Turbo", 3, load_rom_sufamiturbo, "sufamiturbo.sfc!st");
200 core_type type_sgb("sgb", "Super Game Boy", 4, load_rom_sgb, "sgb.sfc!gb;dmg;sgb");
201 core_type_region_bind bind_A(type_snes, region_auto);
202 core_type_region_bind bind_B(type_snes, region_ntsc);
203 core_type_region_bind bind_C(type_snes, region_pal);
204 core_type_region_bind bind_D(type_bsx, region_ntsc);
205 core_type_region_bind bind_E(type_bsxslotted, region_ntsc);
206 core_type_region_bind bind_F(type_sufamiturbo, region_ntsc);
207 core_type_region_bind bind_G(type_sgb, region_auto);
208 core_type_region_bind bind_H(type_sgb, region_ntsc);
209 core_type_region_bind bind_I(type_sgb, region_pal);
210 core_type_image_bind bind_J(type_snes, image_snescart, 0);
211 core_type_image_bind bind_K(type_bsx, image_bsxbios, 0);
212 core_type_image_bind bind_L(type_bsx, image_bsxflash, 1);
213 core_type_image_bind bind_M(type_bsxslotted, image_bsxbios, 0);
214 core_type_image_bind bind_N(type_bsxslotted, image_bsxsflash, 1);
215 core_type_image_bind bind_O(type_sufamiturbo, image_stbios, 0);
216 core_type_image_bind bind_P(type_sufamiturbo, image_stslota, 1);
217 core_type_image_bind bind_Q(type_sufamiturbo, image_stslotb, 2);
218 core_type_image_bind bind_R(type_sgb, image_sgbbios, 0);
219 core_type_image_bind bind_S(type_sgb, image_dmg, 1);
220 core_sysregion sr1("snes_ntsc", type_snes, region_ntsc);
221 core_sysregion sr2("snes_pal", type_snes, region_pal);
222 core_sysregion sr3("bsx", type_bsx, region_ntsc);
223 core_sysregion sr4("bsxslotted", type_bsxslotted, region_ntsc);
224 core_sysregion sr5("sufamiturbo", type_sufamiturbo, region_ntsc);
225 core_sysregion sr6("sgb_ntsc", type_sgb, region_ntsc);
226 core_sysregion sr7("sgb_pal", type_sgb, region_pal);
228 bool last_hires = false;
229 bool last_interlace = false;
230 bool stepping_into_save;
231 bool video_refresh_done;
232 //Delay reset.
233 unsigned long long delayreset_cycles_run;
234 unsigned long long delayreset_cycles_target;
236 bool p1disable = false;
237 std::map<int16_t, std::pair<uint64_t, uint64_t>> ptrmap;
239 const char* buttonnames[] = {
240 "left", "right", "up", "down", "A", "B", "X", "Y", "L", "R", "select", "start", "trigger",
241 "cursor", "turbo", "pause", "ext0", "ext1", "ext2", "ext3"
244 class my_interfaced : public SNES::Interface
246 string path(SNES::Cartridge::Slot slot, const string &hint)
248 return "./";
252 std::string sram_name(const nall::string& _id, SNES::Cartridge::Slot slotname)
254 std::string id(_id, _id.length());
255 //Fixup name change by bsnes v087...
256 if(id == "bsx.ram")
257 id = ".bss";
258 if(id == "bsx.psram")
259 id = ".bsp";
260 if(id == "program.rtc")
261 id = ".rtc";
262 if(id == "upd96050.ram")
263 id = ".dsp";
264 if(id == "program.ram")
265 id = ".srm";
266 if(slotname == SNES::Cartridge::Slot::SufamiTurboA)
267 return "slota." + id.substr(1);
268 if(slotname == SNES::Cartridge::Slot::SufamiTurboB)
269 return "slotb." + id.substr(1);
270 return id.substr(1);
273 uint8_t snes_bus_iospace_rw(uint64_t offset, uint8_t data, bool write)
275 if(write)
276 SNES::bus.write(offset, data);
277 else
278 return SNES::bus.read(offset);
281 uint8_t ptrtable_iospace_rw(uint64_t offset, uint8_t data, bool write)
283 uint16_t entry = offset >> 4;
284 if(!ptrmap.count(entry))
285 return 0;
286 uint64_t val = ((offset & 15) < 8) ? ptrmap[entry].first : ptrmap[entry].second;
287 uint8_t byte = offset & 7;
288 //These things are always little-endian.
289 return (val >> (8 * byte));
292 void create_region(std::list<vma_info>& inf, const std::string& name, uint64_t base, uint64_t size,
293 uint8_t (*iospace_rw)(uint64_t offset, uint8_t data, bool write)) throw(std::bad_alloc)
295 if(size == 0)
296 return;
297 vma_info i;
298 i.name = name;
299 i.base = base;
300 i.size = size;
301 i.readonly = false;
302 i.native_endian = false;
303 i.iospace_rw = iospace_rw;
304 inf.push_back(i);
307 void create_region(std::list<vma_info>& inf, const std::string& name, uint64_t base, uint8_t* memory,
308 uint64_t size, bool readonly, bool native_endian = false) throw(std::bad_alloc)
310 if(size == 0)
311 return;
312 vma_info i;
313 i.name = name;
314 i.base = base;
315 i.size = size;
316 i.backing_ram = memory;
317 i.readonly = readonly;
318 i.native_endian = native_endian;
319 i.iospace_rw = NULL;
320 inf.push_back(i);
323 void create_region(std::list<vma_info>& inf, const std::string& name, uint64_t base,
324 SNES::MappedRAM& memory, bool readonly, bool native_endian = false) throw(std::bad_alloc)
326 create_region(inf, name, base, memory.data(), memory.size(), readonly, native_endian);
329 void map_internal(std::list<vma_info>& inf, const std::string& name, uint16_t index, void* memory,
330 size_t memsize)
332 ptrmap[index] = std::make_pair(reinterpret_cast<uint64_t>(memory), static_cast<uint64_t>(memsize));
333 create_region(inf, name, 0x101000000 + index * 0x1000000, reinterpret_cast<uint8_t*>(memory),
334 memsize, true, true);
337 bool delayreset_fn()
339 if(delayreset_cycles_run == delayreset_cycles_target || video_refresh_done)
340 return true;
341 delayreset_cycles_run++;
342 return false;
345 class my_interface : public SNES::Interface
347 string path(SNES::Cartridge::Slot slot, const string &hint)
349 const char* _hint = hint;
350 std::string _hint2 = _hint;
351 std::string fwp = ecore_callbacks->get_firmware_path();
352 regex_results r;
353 std::string msubase = ecore_callbacks->get_base_path();
354 if(regex_match(".*\\.sfc", msubase))
355 msubase = msubase.substr(0, msubase.length() - 4);
357 if(_hint2 == "msu1.rom" || _hint2 == ".msu") {
358 //MSU-1 main ROM.
359 std::string x = msubase + ".msu";
360 messages << "MSU main data file: " << x << std::endl;
361 return x.c_str();
363 if(r = regex("(track)?(-([0-9])+\\.pcm)", _hint2)) {
364 //MSU track.
365 std::string x = msubase + r[2];
366 messages << "MSU track " << r[3] << "': " << x << std::endl;
367 return x.c_str();
369 std::string finalpath = fwp + "/" + _hint2;
370 return finalpath.c_str();
373 time_t currentTime()
375 return ecore_callbacks->get_time();
378 time_t randomSeed()
380 return ecore_callbacks->get_randomseed();
383 void videoRefresh(const uint32_t* data, bool hires, bool interlace, bool overscan)
385 last_hires = hires;
386 last_interlace = interlace;
387 bool region = (&core_get_region() == &region_pal);
388 if(stepping_into_save)
389 messages << "Got video refresh in runtosave, expect desyncs!" << std::endl;
390 video_refresh_done = true;
391 uint32_t fps_n, fps_d;
392 auto fps = get_video_rate();
393 fps_n = fps.first;
394 fps_d = fps.second;
395 uint32_t g = gcd(fps_n, fps_d);
396 fps_n /= g;
397 fps_d /= g;
399 framebuffer_info inf;
400 inf.type = &_pixel_format_lrgb;
401 inf.mem = const_cast<char*>(reinterpret_cast<const char*>(data));
402 inf.physwidth = 512;
403 inf.physheight = 512;
404 inf.physstride = 2048;
405 inf.width = hires ? 512 : 256;
406 inf.height = (region ? 239 : 224) * (interlace ? 2 : 1);
407 inf.stride = interlace ? 2048 : 4096;
408 inf.offset_x = 0;
409 inf.offset_y = (region ? (overscan ? 9 : 1) : (overscan ? 16 : 9)) * 2;
411 framebuffer_raw ls(inf);
412 ecore_callbacks->output_frame(ls, fps_n, fps_d);
413 information_dispatch::do_raw_frame(data, hires, interlace, overscan, region ?
414 VIDEO_REGION_PAL : VIDEO_REGION_NTSC);
415 if(soundbuf_fill > 0) {
416 auto hz = get_audio_rate();
417 audioapi_submit_buffer(soundbuf, soundbuf_fill / 2, true, 1.0 * hz.first / hz.second);
418 soundbuf_fill = 0;
422 void audioSample(int16_t l_sample, int16_t r_sample)
424 uint16_t _l = l_sample;
425 uint16_t _r = r_sample;
426 soundbuf[soundbuf_fill++] = l_sample;
427 soundbuf[soundbuf_fill++] = r_sample;
428 information_dispatch::do_sample(l_sample, r_sample);
429 //The SMP emits a sample every 768 ticks of its clock. Use this in order to keep track of
430 //time.
431 auto hz = get_audio_rate();
432 ecore_callbacks->timer_tick(hz.second, hz.first);
435 int16_t inputPoll(bool port, SNES::Input::Device device, unsigned index, unsigned id)
437 int16_t offset = 0;
438 //The superscope/justifier handling is nuts.
439 if(port && SNES::input.port2) {
440 SNES::SuperScope* ss = dynamic_cast<SNES::SuperScope*>(SNES::input.port2);
441 SNES::Justifier* js = dynamic_cast<SNES::Justifier*>(SNES::input.port2);
442 if(ss && index == 0) {
443 if(id == 0)
444 offset = ss->x;
445 if(id == 1)
446 offset = ss->y;
448 if(js && index == 0) {
449 if(id == 0)
450 offset = js->player1.x;
451 if(id == 1)
452 offset = js->player1.y;
454 if(js && js->chained && index == 1) {
455 if(id == 0)
456 offset = js->player2.x;
457 if(id == 1)
458 offset = js->player2.y;
461 return ecore_callbacks->get_input(port ? 2 : 1, index, id) - offset;
465 template<int type, bool p2only>
466 void set_core_controller_X(unsigned port) throw()
468 if(port != 1 && port != 2)
469 return;
470 if(port == 2)
471 snes_set_controller_port_device(true, type);
472 if(port == 1) {
473 snes_set_controller_port_device(false, p2only ? SNES_DEVICE_NONE : type);
474 p1disable = p2only;
478 void set_core_controller_system(unsigned port) throw()
482 int get_button_id_none(unsigned controller, unsigned lbid) throw()
484 return -1;
487 template<unsigned lim>
488 int get_button_id_gamepad(unsigned controller, unsigned lbid) throw()
490 if(controller > lim)
491 return -1;
492 switch(lbid) {
493 case LOGICAL_BUTTON_LEFT: return SNES_DEVICE_ID_JOYPAD_LEFT;
494 case LOGICAL_BUTTON_RIGHT: return SNES_DEVICE_ID_JOYPAD_RIGHT;
495 case LOGICAL_BUTTON_UP: return SNES_DEVICE_ID_JOYPAD_UP;
496 case LOGICAL_BUTTON_DOWN: return SNES_DEVICE_ID_JOYPAD_DOWN;
497 case LOGICAL_BUTTON_A: return SNES_DEVICE_ID_JOYPAD_A;
498 case LOGICAL_BUTTON_B: return SNES_DEVICE_ID_JOYPAD_B;
499 case LOGICAL_BUTTON_X: return SNES_DEVICE_ID_JOYPAD_X;
500 case LOGICAL_BUTTON_Y: return SNES_DEVICE_ID_JOYPAD_Y;
501 case LOGICAL_BUTTON_L: return SNES_DEVICE_ID_JOYPAD_L;
502 case LOGICAL_BUTTON_R: return SNES_DEVICE_ID_JOYPAD_R;
503 case LOGICAL_BUTTON_SELECT: return SNES_DEVICE_ID_JOYPAD_SELECT;
504 case LOGICAL_BUTTON_START: return SNES_DEVICE_ID_JOYPAD_START;
505 case LOGICAL_BUTTON_EXT0: return 12;
506 case LOGICAL_BUTTON_EXT1: return 13;
507 case LOGICAL_BUTTON_EXT2: return 14;
508 case LOGICAL_BUTTON_EXT3: return 15;
509 default: return -1;
513 int get_button_id_mouse(unsigned controller, unsigned lbid) throw()
515 if(controller > 0)
516 return -1;
517 switch(lbid) {
518 case LOGICAL_BUTTON_L: return SNES_DEVICE_ID_MOUSE_LEFT;
519 case LOGICAL_BUTTON_R: return SNES_DEVICE_ID_MOUSE_RIGHT;
520 default: return -1;
524 int get_button_id_superscope(unsigned controller, unsigned lbid) throw()
526 if(controller > 0)
527 return -1;
528 switch(lbid) {
529 case LOGICAL_BUTTON_TRIGGER: return SNES_DEVICE_ID_SUPER_SCOPE_TRIGGER;
530 case LOGICAL_BUTTON_CURSOR: return SNES_DEVICE_ID_SUPER_SCOPE_CURSOR;
531 case LOGICAL_BUTTON_TURBO: return SNES_DEVICE_ID_SUPER_SCOPE_TURBO;
532 case LOGICAL_BUTTON_PAUSE: return SNES_DEVICE_ID_SUPER_SCOPE_PAUSE;
533 default: return -1;
537 template<unsigned lim>
538 int get_button_id_justifier(unsigned controller, unsigned lbid) throw()
540 if(controller > lim)
541 return -1;
542 switch(lbid) {
543 case LOGICAL_BUTTON_START: return SNES_DEVICE_ID_JUSTIFIER_START;
544 case LOGICAL_BUTTON_TRIGGER: return SNES_DEVICE_ID_JUSTIFIER_TRIGGER;
545 default: return -1;
549 void system_write(unsigned char* buffer, unsigned idx, unsigned ctrl, short x) throw()
551 if(idx)
552 return;
553 if(ctrl < 2)
554 if(x)
555 buffer[0] |= (1 << ctrl);
556 else
557 buffer[0] &= ~(1 << ctrl);
558 else if(ctrl < 4) {
559 buffer[2 * ctrl - 3] = x >> 8;
560 buffer[2 * ctrl - 2] = x;
564 short system_read(const unsigned char* buffer, unsigned idx, unsigned ctrl) throw()
566 if(idx)
567 return 0;
568 if(ctrl < 2)
569 return (buffer[0] >> ctrl) ? 1 : 0;
570 else if(ctrl < 4)
571 return unserialize_short(buffer + 2 * ctrl - 3);
572 return 0;
575 size_t system_deserialize(unsigned char* buffer, const char* textbuf)
577 memset(buffer, 0, 5);
578 size_t ptr = 0;
579 if(read_button_value(textbuf, ptr))
580 buffer[0] |= 1;
581 if(read_button_value(textbuf, ptr))
582 buffer[0] |= 2;
583 short v = read_axis_value(textbuf, ptr);
584 buffer[1] = v >> 8;
585 buffer[2] = v;
586 v = read_axis_value(textbuf, ptr);
587 buffer[3] = v >> 8;
588 buffer[4] = v;
589 skip_rest_of_field(textbuf, ptr, false);
590 return ptr;
593 void system_display(const unsigned char* buffer, unsigned idx, char* buf)
595 if(idx)
596 sprintf(buf, "");
597 else
598 sprintf(buf, "%c%c %i %i", ((buffer[0] & 1) ? 'F' : '.'), ((buffer[0] & 2) ? 'R' : '.'),
599 unserialize_short(buffer + 1), unserialize_short(buffer + 3));
602 size_t system_serialize(const unsigned char* buffer, char* textbuf)
604 char tmp[128];
605 if(buffer[1] || buffer[2] || buffer[3] || buffer[4])
606 sprintf(tmp, "%c%c %i %i", ((buffer[0] & 1) ? 'F' : '.'), ((buffer[0] & 2) ? 'R' : '.'),
607 unserialize_short(buffer + 1), unserialize_short(buffer + 3));
608 else
609 sprintf(tmp, "%c%c", ((buffer[0] & 1) ? 'F' : '.'), ((buffer[0] & 2) ? 'R' : '.'));
610 size_t len = strlen(tmp);
611 memcpy(textbuf, tmp, len);
612 return len;
615 struct port_index_map build_indices(std::vector<port_type*> types);
617 struct porttype_system : public port_type
619 porttype_system() : port_type(core_portgroup, "<SYSTEM>", "<SYSTEM>", 9999, 5)
621 write = system_write;
622 read = system_read;
623 display = system_display;
624 serialize = system_serialize;
625 deserialize = system_deserialize;
626 legal = generic_port_legal<0>;
627 deviceflags = generic_port_deviceflags<1, 1>;
628 button_id = get_button_id_none;
629 construct_map = build_indices;
630 used_indices = generic_used_indices<1, 4>;
631 controller_name = generic_controller_name<1, 0>;
632 controllers = 1;
633 set_core_controller = set_core_controller_system;
634 core_portgroup.set_default(0, *this);
636 } psystem;
638 struct porttype_gamepad : public port_type
640 porttype_gamepad() : port_type(core_portgroup, "gamepad", "Gamepad", 1, generic_port_size<1, 0, 12>())
642 write = generic_port_write<1, 0, 12>;
643 read = generic_port_read<1, 0, 12>;
644 display = generic_port_display<1, 0, 12, 0>;
645 serialize = generic_port_serialize<1, 0, 12, 0>;
646 deserialize = generic_port_deserialize<1, 0, 12>;
647 legal = generic_port_legal<3>;
648 deviceflags = generic_port_deviceflags<1, 1>;
649 button_id = get_button_id_gamepad<0>;
650 used_indices = generic_used_indices<1, 12>;
651 controller_name = generic_controller_name<1, 1>;
652 controllers = 1;
653 set_core_controller = set_core_controller_X<SNES_DEVICE_JOYPAD, false>;
654 core_portgroup.set_default(1, *this);
656 } gamepad;
658 struct porttype_gamepad16 : public port_type
660 porttype_gamepad16() : port_type(core_portgroup, "gamepad16", "Gamepad (16-button)", 1,
661 generic_port_size<1, 0, 16>())
663 write = generic_port_write<1, 0, 16>;
664 read = generic_port_read<1, 0, 16>;
665 display = generic_port_display<1, 0, 16, 0>;
666 serialize = generic_port_serialize<1, 0, 16, 0>;
667 deserialize = generic_port_deserialize<1, 0, 16>;
668 legal = generic_port_legal<3>;
669 deviceflags = generic_port_deviceflags<1, 1>;
670 button_id = get_button_id_gamepad<0>;
671 used_indices = generic_used_indices<1, 16>;
672 controller_name = generic_controller_name<1, 5>;
673 controllers = 1;
674 set_core_controller = set_core_controller_X<SNES_DEVICE_JOYPAD, false>;
676 } gamepad16;
678 struct porttype_justifier : public port_type
680 porttype_justifier() : port_type(core_portgroup, "justifier", "Justifier", 5,
681 generic_port_size<1, 2, 2>())
683 write = generic_port_write<1, 2, 2>;
684 read = generic_port_read<1, 2, 2>;
685 display = generic_port_display<1, 2, 2, 12>;
686 serialize = generic_port_serialize<1, 2, 2, 16>;
687 deserialize = generic_port_deserialize<1, 2, 2>;
688 legal = generic_port_legal<2>;
689 deviceflags = generic_port_deviceflags<1, 3>;
690 button_id = get_button_id_justifier<0>;
691 used_indices = generic_used_indices<1, 4>;
692 controller_name = generic_controller_name<1, 4>;
693 controllers = 1;
694 set_core_controller = set_core_controller_X<SNES_DEVICE_JUSTIFIER, true>;
696 } justifier;
698 struct porttype_justifiers : public port_type
700 porttype_justifiers() : port_type(core_portgroup, "justifiers", "2 Justifiers", 6,
701 generic_port_size<2, 2, 2>())
703 write = generic_port_write<2, 2, 2>;
704 read = generic_port_read<2, 2, 2>;
705 display = generic_port_display<2, 2, 2, 12>;
706 serialize = generic_port_serialize<2, 2, 2, 16>;
707 deserialize = generic_port_deserialize<2, 2, 2>;
708 legal = generic_port_legal<2>;
709 deviceflags = generic_port_deviceflags<2, 3>;
710 button_id = get_button_id_justifier<1>;
711 used_indices = generic_used_indices<2, 4>;
712 controller_name = generic_controller_name<2, 4>;
713 controllers = 2;
714 set_core_controller = set_core_controller_X<SNES_DEVICE_JUSTIFIERS, true>;
716 } justifiers;
718 struct porttype_mouse : public port_type
720 porttype_mouse() : port_type(core_portgroup, "mouse", "Mouse", 3, generic_port_size<1, 2, 2>())
722 write = generic_port_write<1, 2, 2>;
723 read = generic_port_read<1, 2, 2>;
724 display = generic_port_display<1, 2, 2, 10>;
725 serialize = generic_port_serialize<1, 2, 2, 10>;
726 deserialize = generic_port_deserialize<1, 2, 2>;
727 legal = generic_port_legal<3>;
728 deviceflags = generic_port_deviceflags<1, 5>;
729 button_id = get_button_id_mouse;
730 used_indices = generic_used_indices<1, 4>;
731 controller_name = generic_controller_name<1, 2>;
732 controllers = 1;
733 set_core_controller = set_core_controller_X<SNES_DEVICE_MOUSE, false>;
735 } mouse;
737 struct porttype_multitap : public port_type
739 porttype_multitap() : port_type(core_portgroup, "multitap", "Multitap", 2,
740 generic_port_size<4, 0, 12>())
742 write = generic_port_write<4, 0, 12>;
743 read = generic_port_read<4, 0, 12>;
744 display = generic_port_display<4, 0, 12, 0>;
745 serialize = generic_port_serialize<4, 0, 12, 0>;
746 deserialize = generic_port_deserialize<4, 0, 12>;
747 legal = generic_port_legal<3>;
748 deviceflags = generic_port_deviceflags<4, 1>;
749 button_id = get_button_id_gamepad<3>;
750 used_indices = generic_used_indices<4, 12>;
751 controller_name = generic_controller_name<4, 1>;
752 controllers = 4;
753 set_core_controller = set_core_controller_X<SNES_DEVICE_MULTITAP, false>;
755 } multitap;
757 struct porttype_multitap16 : public port_type
759 porttype_multitap16() : port_type(core_portgroup, "multitap16", "Multitap (16-button)", 2,
760 generic_port_size<4, 0, 16>())
762 write = generic_port_write<4, 0, 16>;
763 read = generic_port_read<4, 0, 16>;
764 display = generic_port_display<4, 0, 16, 0>;
765 serialize = generic_port_serialize<4, 0, 16, 0>;
766 deserialize = generic_port_deserialize<4, 0, 16>;
767 legal = generic_port_legal<3>;
768 deviceflags = generic_port_deviceflags<4, 1>;
769 button_id = get_button_id_gamepad<3>;
770 used_indices = generic_used_indices<4, 16>;
771 controller_name = generic_controller_name<4, 5>;
772 controllers = 4;
773 set_core_controller = set_core_controller_X<SNES_DEVICE_MULTITAP, false>;
775 } multitap16;
777 struct porttype_none : public port_type
779 porttype_none() : port_type(core_portgroup, "none", "None", 0, generic_port_size<0, 0, 0>())
781 write = generic_port_write<0, 0, 0>;
782 read = generic_port_read<0, 0, 0>;
783 display = generic_port_display<0, 0, 0, 0>;
784 serialize = generic_port_serialize<0, 0, 0, 0>;
785 deserialize = generic_port_deserialize<0, 0, 0>;
786 legal = generic_port_legal<3>;
787 deviceflags = generic_port_deviceflags<0, 0>;
788 button_id = get_button_id_none;
789 used_indices = generic_used_indices<0, 0>;
790 controller_name = generic_controller_name<0, 1>;
791 controllers = 0;
792 set_core_controller = set_core_controller_X<SNES_DEVICE_NONE, false>;
793 core_portgroup.set_default(2, *this);
795 } none;
797 struct porttype_superscope : public port_type
799 porttype_superscope() : port_type(core_portgroup, "superscope", "Super Scope", 4,
800 generic_port_size<1, 2, 4>())
802 write = generic_port_write<1, 2, 4>;
803 read = generic_port_read<1, 2, 4>;
804 display = generic_port_display<1, 2, 4, 18>;
805 serialize = generic_port_serialize<1, 2, 4, 18>;
806 deserialize = generic_port_deserialize<1, 2, 4>;
807 deviceflags = generic_port_deviceflags<1, 3>;
808 legal = generic_port_legal<2>;
809 button_id = get_button_id_superscope;
810 used_indices = generic_used_indices<1, 6>;
811 controller_name = generic_controller_name<1, 3>;
812 controllers = 1;
813 set_core_controller = set_core_controller_X<SNES_DEVICE_SUPER_SCOPE, true>;
815 } superscope;
817 template<unsigned x, unsigned y>
818 void fill_map_partial(std::vector<port_index_triple>& map, unsigned port)
820 unsigned sidx = port ? (port * 48 - 44) : 0;
821 for(unsigned i = 0; i < 48; i++) {
822 map[i + sidx].valid = (i / 12 < x) && (i % 12 < y);
823 map[i + sidx].port = port;
824 map[i + sidx].controller = i / 12;
825 map[i + sidx].control = i % 12;
826 map[i + sidx].marks_nonlag = (port != 0);
828 for(unsigned i = 0; i < x; i++)
829 for(unsigned j = 12; j < y; j++) {
830 port_index_triple t;
831 t.valid = true;
832 t.port = port;
833 t.controller = i;
834 t.control = j;
835 t.marks_nonlag = true;
836 map.push_back(t);
840 void fill_map_port(std::vector<port_index_triple>& map, port_type& ptype, unsigned port)
842 if(&ptype == &psystem)
843 fill_map_partial<1, 4>(map, port);
844 if(&ptype == &none)
845 fill_map_partial<0, 0>(map, port);
846 if(&ptype == &gamepad)
847 fill_map_partial<1, 12>(map, port);
848 if(&ptype == &gamepad16)
849 fill_map_partial<1, 16>(map, port);
850 if(&ptype == &multitap)
851 fill_map_partial<4, 12>(map, port);
852 if(&ptype == &multitap16)
853 fill_map_partial<4, 16>(map, port);
854 if(&ptype == &mouse)
855 fill_map_partial<1, 4>(map, port);
856 if(&ptype == &superscope)
857 fill_map_partial<1, 6>(map, port);
858 if(&ptype == &justifier)
859 fill_map_partial<1, 4>(map, port);
860 if(&ptype == &justifiers)
861 fill_map_partial<2, 4>(map, port);
864 struct port_index_map build_indices(std::vector<port_type*> types)
866 struct port_index_map i;
867 i.indices.resize(100);
868 fill_map_port(i.indices, *types[0], 0);
869 fill_map_port(i.indices, *types[1], 1);
870 fill_map_port(i.indices, *types[2], 2);
871 i.logical_map.resize(types[1]->controllers + types[2]->controllers);
872 if(types[1] == &multitap || types[1] == &multitap16) {
873 i.logical_map[0] = std::make_pair(1, 0);
874 for(size_t j = 0; j < types[2]->controllers; j++)
875 i.logical_map[j + 1] = std::make_pair(2U, j);
876 for(size_t j = 1; j < types[1]->controllers; j++)
877 i.logical_map[j + types[2]->controllers] = std::make_pair(1U, j);
878 } else {
879 for(size_t j = 0; j < types[1]->controllers; j++)
880 i.logical_map[j] = std::make_pair(1, j);
881 for(size_t j = 0; j < types[2]->controllers; j++)
882 i.logical_map[j + types[1]->controllers] = std::make_pair(2U, j);
884 i.pcid_map.resize(8);
885 for(size_t j = 0; j < 8; j++)
886 i.pcid_map[j] = std::make_pair(j / 4 + 1, j % 4);
887 return i;
890 my_interface my_interface_obj;
891 SNES::Interface* old;
894 std::string get_logical_button_name(unsigned lbid) throw(std::bad_alloc)
896 if(lbid >= sizeof(buttonnames) / sizeof(buttonnames[0]))
897 return "";
898 return buttonnames[lbid];
901 void core_install_handler()
903 old = SNES::interface;
904 SNES::interface = &my_interface_obj;
905 SNES::system.init();
908 std::string get_core_default_port(unsigned port)
910 if(port == 0)
911 return "gamepad";
912 else
913 return "none";
916 void core_uninstall_handler()
918 SNES::interface = old;
921 uint32_t get_snes_cpu_rate()
923 return SNES::system.cpu_frequency();
926 uint32_t get_snes_apu_rate()
928 return SNES::system.apu_frequency();
931 std::pair<unsigned, unsigned> get_core_logical_controller_limits()
933 return std::make_pair(8U, (unsigned)(sizeof(buttonnames)/sizeof(buttonnames[0])));
936 bool get_core_need_analog()
938 return true;
941 std::string get_core_identifier()
943 std::ostringstream x;
944 x << snes_library_id() << " (" << SNES::Info::Profile << " core)";
945 return x.str();
948 void do_basic_core_init()
950 static my_interfaced i;
951 SNES::interface = &i;
954 std::set<std::string> get_sram_set()
956 std::set<std::string> r;
957 if(!internal_rom)
958 return r;
959 for(unsigned i = 0; i < SNES::cartridge.nvram.size(); i++) {
960 SNES::Cartridge::NonVolatileRAM& s = SNES::cartridge.nvram[i];
961 r.insert(sram_name(s.id, s.slot));
963 return r;
966 void set_preload_settings()
968 SNES::config.random = false;
969 SNES::config.expansion_port = SNES::System::ExpansionPortDevice::None;
972 core_region& core_get_region()
974 if(SNES::system.region() == SNES::System::Region::PAL)
975 return region_pal;
976 else
977 return region_ntsc;
980 void core_power()
982 if(internal_rom)
983 snes_power();
986 void core_unload_cartridge()
988 if(!internal_rom)
989 return;
990 snes_term();
991 snes_unload_cartridge();
992 internal_rom = NULL;
995 //Get the current video rate.
996 std::pair<uint32_t, uint32_t> get_video_rate()
998 if(!internal_rom)
999 return std::make_pair(60, 1);
1000 uint32_t div;
1001 if(snes_get_region())
1002 div = last_interlace ? DURATION_PAL_FIELD : DURATION_PAL_FRAME;
1003 else
1004 div = last_interlace ? DURATION_NTSC_FIELD : DURATION_NTSC_FRAME;
1005 return std::make_pair(get_snes_cpu_rate(), div);
1008 //Get the current audio rate.
1009 std::pair<uint32_t, uint32_t> get_audio_rate()
1011 if(!internal_rom)
1012 return std::make_pair(64081, 2);
1013 return std::make_pair(get_snes_apu_rate(), static_cast<uint32_t>(768));
1016 std::map<std::string, std::vector<char>> save_sram() throw(std::bad_alloc)
1018 std::map<std::string, std::vector<char>> out;
1019 if(!internal_rom)
1020 return out;
1021 for(unsigned i = 0; i < SNES::cartridge.nvram.size(); i++) {
1022 SNES::Cartridge::NonVolatileRAM& r = SNES::cartridge.nvram[i];
1023 std::string savename = sram_name(r.id, r.slot);
1024 std::vector<char> x;
1025 x.resize(r.size);
1026 memcpy(&x[0], r.data, r.size);
1027 out[savename] = x;
1029 return out;
1032 void load_sram(std::map<std::string, std::vector<char>>& sram) throw(std::bad_alloc)
1034 std::set<std::string> used;
1035 if(!internal_rom) {
1036 for(auto i : sram)
1037 messages << "WARNING: SRAM '" << i.first << ": Not found on cartridge." << std::endl;
1038 return;
1040 if(sram.empty())
1041 return;
1042 for(unsigned i = 0; i < SNES::cartridge.nvram.size(); i++) {
1043 SNES::Cartridge::NonVolatileRAM& r = SNES::cartridge.nvram[i];
1044 std::string savename = sram_name(r.id, r.slot);
1045 if(sram.count(savename)) {
1046 std::vector<char>& x = sram[savename];
1047 if(r.size != x.size())
1048 messages << "WARNING: SRAM '" << savename << "': Loaded " << x.size()
1049 << " bytes, but the SRAM is " << r.size << "." << std::endl;
1050 memcpy(r.data, &x[0], (r.size < x.size()) ? r.size : x.size());
1051 used.insert(savename);
1052 } else
1053 messages << "WARNING: SRAM '" << savename << ": No data." << std::endl;
1055 for(auto i : sram)
1056 if(!used.count(i.first))
1057 messages << "WARNING: SRAM '" << i.first << ": Not found on cartridge." << std::endl;
1060 bool core_set_region(core_region& region)
1062 if(&region == &region_auto) SNES::config.region = SNES::System::Region::Autodetect;
1063 else if(&region == &region_ntsc) SNES::config.region = SNES::System::Region::NTSC;
1064 else if(&region == &region_pal) SNES::config.region = SNES::System::Region::PAL;
1065 else
1066 return false;
1067 return true;
1070 void core_serialize(std::vector<char>& out)
1072 if(!internal_rom)
1073 throw std::runtime_error("No ROM loaded");
1074 serializer s = SNES::system.serialize();
1075 out.resize(s.size());
1076 memcpy(&out[0], s.data(), s.size());
1079 void core_unserialize(const char* in, size_t insize)
1081 if(!internal_rom)
1082 throw std::runtime_error("No ROM loaded");
1083 serializer s(reinterpret_cast<const uint8_t*>(in), insize);
1084 if(!SNES::system.unserialize(s))
1085 throw std::runtime_error("SNES core rejected savestate");
1086 have_saved_this_frame = true;
1087 do_reset_flag = -1;
1090 void core_request_reset(long delay)
1092 do_reset_flag = delay;
1095 std::pair<bool, uint32_t> core_emulate_cycles(uint32_t cycles)
1097 if(!internal_rom)
1098 return std::make_pair(false, 0);
1099 #ifdef BSNES_HAS_DEBUGGER
1100 messages << "Executing delayed reset... This can take some time!" << std::endl;
1101 video_refresh_done = false;
1102 delayreset_cycles_run = 0;
1103 delayreset_cycles_target = cycles;
1104 SNES::cpu.step_event = delayreset_fn;
1105 SNES::system.run();
1106 SNES::cpu.step_event = nall::function<bool()>();
1107 return std::make_pair(!video_refresh_done, delayreset_cycles_run);
1108 have_saved_this_frame = true;
1109 #else
1110 messages << "Delayresets not supported on this bsnes version (needs v084 or v085)"
1111 << std::endl;
1112 return std::make_pair(false, 0);
1113 #endif
1116 void core_emulate_frame()
1118 static unsigned frame_modulus = 0;
1119 if(!internal_rom) {
1120 do_reset_flag = -1;
1121 init_norom_frame();
1122 framebuffer_info inf;
1123 inf.type = &_pixel_format_lrgb;
1124 inf.mem = const_cast<char*>(reinterpret_cast<const char*>(norom_frame));
1125 inf.physwidth = 512;
1126 inf.physheight = 448;
1127 inf.physstride = 2048;
1128 inf.width = 512;
1129 inf.height = 448;
1130 inf.stride = 2048;
1131 inf.offset_x = 0;
1132 inf.offset_y = 0;
1134 framebuffer_raw ls(inf);
1135 ecore_callbacks->output_frame(ls, 60, 1);
1137 audioapi_submit_buffer(blanksound, frame_modulus ? 534 : 535, true, 32040.5);
1138 for(unsigned i = 0; i < 534; i++)
1139 information_dispatch::do_sample(0, 0);
1140 if(!frame_modulus)
1141 information_dispatch::do_sample(0, 0);
1142 frame_modulus++;
1143 frame_modulus %= 120;
1144 ecore_callbacks->timer_tick(1, 60);
1145 return;
1148 bool was_delay_reset = false;
1149 int16_t reset = ecore_callbacks->set_input(0, 0, 1, (do_reset_flag >= 0) ? 1 : 0);
1150 if(reset) {
1151 long hi = ecore_callbacks->set_input(0, 0, 2, do_reset_flag / 10000);
1152 long lo = ecore_callbacks->set_input(0, 0, 3, do_reset_flag % 10000);
1153 long delay = 10000 * hi + lo;
1154 if(delay > 0) {
1155 was_delay_reset = true;
1156 #ifdef BSNES_HAS_DEBUGGER
1157 messages << "Executing delayed reset... This can take some time!" << std::endl;
1158 video_refresh_done = false;
1159 delayreset_cycles_run = 0;
1160 delayreset_cycles_target = delay;
1161 SNES::cpu.step_event = delayreset_fn;
1162 SNES::system.run();
1163 SNES::cpu.step_event = nall::function<bool()>();
1164 if(video_refresh_done) {
1165 //Force the reset here.
1166 do_reset_flag = -1;
1167 messages << "SNES reset (forced at " << delayreset_cycles_run << ")" << std::endl;
1168 SNES::system.reset();
1169 return;
1171 SNES::system.reset();
1172 messages << "SNES reset (delayed " << delayreset_cycles_run << ")" << std::endl;
1173 #else
1174 messages << "Delayresets not supported on this bsnes version (needs v084 or v085)"
1175 << std::endl;
1176 SNES::system.reset();
1177 #endif
1178 } else if(delay == 0) {
1179 SNES::system.reset();
1180 messages << "SNES reset" << std::endl;
1183 do_reset_flag = -1;
1186 if(!have_saved_this_frame && save_every_frame && !was_delay_reset)
1187 SNES::system.runtosave();
1188 SNES::system.run();
1189 have_saved_this_frame = false;
1192 void core_runtosave()
1194 if(!internal_rom)
1195 return;
1196 stepping_into_save = true;
1197 if(!allow_inconsistent_saves)
1198 SNES::system.runtosave();
1199 have_saved_this_frame = true;
1200 stepping_into_save = false;
1203 std::list<vma_info> get_vma_list()
1205 std::list<vma_info> ret;
1206 if(!internal_rom)
1207 return ret;
1208 create_region(ret, "WRAM", 0x007E0000, SNES::cpu.wram, 131072, false);
1209 create_region(ret, "APURAM", 0x00000000, SNES::smp.apuram, 65536, false);
1210 create_region(ret, "VRAM", 0x00010000, SNES::ppu.vram, 65536, false);
1211 create_region(ret, "OAM", 0x00020000, SNES::ppu.oam, 544, false);
1212 create_region(ret, "CGRAM", 0x00021000, SNES::ppu.cgram, 512, false);
1213 if(SNES::cartridge.has_srtc()) create_region(ret, "RTC", 0x00022000, SNES::srtc.rtc, 20, false);
1214 if(SNES::cartridge.has_spc7110rtc()) create_region(ret, "RTC", 0x00022000, SNES::spc7110.rtc, 20, false);
1215 if(SNES::cartridge.has_necdsp()) {
1216 create_region(ret, "DSPRAM", 0x00023000, reinterpret_cast<uint8_t*>(SNES::necdsp.dataRAM), 4096,
1217 false, true);
1218 create_region(ret, "DSPPROM", 0xF0000000, reinterpret_cast<uint8_t*>(SNES::necdsp.programROM), 65536,
1219 true, true);
1220 create_region(ret, "DSPDROM", 0xF0010000, reinterpret_cast<uint8_t*>(SNES::necdsp.dataROM), 4096,
1221 true, true);
1223 create_region(ret, "SRAM", 0x10000000, SNES::cartridge.ram, false);
1224 create_region(ret, "ROM", 0x80000000, SNES::cartridge.rom, true);
1225 create_region(ret, "BUS", 0x1000000, 0x1000000, snes_bus_iospace_rw);
1226 create_region(ret, "PTRTABLE", 0x100000000, 0x100000, ptrtable_iospace_rw);
1227 map_internal(ret, "CPU_STATE", 0, &SNES::cpu, sizeof(SNES::cpu));
1228 map_internal(ret, "PPU_STATE", 1, &SNES::ppu, sizeof(SNES::ppu));
1229 map_internal(ret, "SMP_STATE", 2, &SNES::smp, sizeof(SNES::smp));
1230 map_internal(ret, "DSP_STATE", 3, &SNES::dsp, sizeof(SNES::dsp));
1231 if(internal_rom == &type_bsx || internal_rom == &type_bsxslotted) {
1232 create_region(ret, "BSXFLASH", 0x90000000, SNES::bsxflash.memory, true);
1233 create_region(ret, "BSX_RAM", 0x20000000, SNES::bsxcartridge.sram, false);
1234 create_region(ret, "BSX_PRAM", 0x30000000, SNES::bsxcartridge.psram, false);
1236 if(internal_rom == &type_sufamiturbo) {
1237 create_region(ret, "SLOTA_ROM", 0x90000000, SNES::sufamiturbo.slotA.rom, true);
1238 create_region(ret, "SLOTB_ROM", 0xA0000000, SNES::sufamiturbo.slotB.rom, true);
1239 create_region(ret, "SLOTA_RAM", 0x20000000, SNES::sufamiturbo.slotA.ram, false);
1240 create_region(ret, "SLOTB_RAM", 0x30000000, SNES::sufamiturbo.slotB.ram, false);
1242 if(internal_rom == &type_sgb) {
1243 create_region(ret, "GBROM", 0x90000000, GameBoy::cartridge.romdata, GameBoy::cartridge.romsize, true);
1244 create_region(ret, "GBRAM", 0x20000000, GameBoy::cartridge.ramdata, GameBoy::cartridge.ramsize, false);
1246 return ret;
1249 std::pair<uint32_t, uint32_t> get_scale_factors(uint32_t width, uint32_t height)
1251 uint32_t h = 1, v = 1;
1252 if(width < 400)
1253 h = 2;
1254 if(height < 400)
1255 v = 2;
1256 return std::make_pair(h, v);
1259 unsigned core_get_poll_flag()
1261 return pollflag_active ? (SNES::cpu.controller_flag ? 1 : 0) : 2;
1264 void core_set_poll_flag(unsigned pflag)
1266 SNES::cpu.controller_flag = (pflag != 0);
1267 pollflag_active = (pflag < 2);
1270 emucore_callbacks::~emucore_callbacks() throw()
1274 std::pair<uint64_t, uint64_t> core_get_bus_map()
1276 return std::make_pair(0x1000000, 0x1000000);
1279 function_ptr_command<arg_filename> dump_core(lsnes_cmd, "dump-core", "No description available",
1280 "No description available\n",
1281 [](arg_filename args) throw(std::bad_alloc, std::runtime_error) {
1282 std::vector<char> out;
1283 core_serialize(out);
1284 std::ofstream x(args, std::ios_base::out | std::ios_base::binary);
1285 x.write(&out[0], out.size());
1289 struct emucore_callbacks* ecore_callbacks;
1290 #endif