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>
23 #include <target-libsnes/libsnes.hpp>
25 #include <ui-libsnes/libsnes.hpp>
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
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;
72 extern const bool core_supports_dreset
= false;
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;
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)
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
)
120 snes_unload_cartridge();
121 bool r
= snes_load_cartridge_normal(img
[0].markup
, img
[0].data
, img
[0].size
);
123 internal_rom
= &type_snes
;
124 have_saved_this_frame
= false;
129 int load_rom_bsx(core_romimage
* img
, uint64_t secs
, uint64_t subsecs
)
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
);
136 internal_rom
= &type_bsx
;
137 have_saved_this_frame
= false;
142 int load_rom_bsxslotted(core_romimage
* img
, uint64_t secs
, uint64_t subsecs
)
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
);
149 internal_rom
= &type_bsxslotted
;
150 have_saved_this_frame
= false;
155 int load_rom_sgb(core_romimage
* img
, uint64_t secs
, uint64_t subsecs
)
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
);
162 internal_rom
= &type_sgb
;
163 have_saved_this_frame
= false;
168 int load_rom_sufamiturbo(core_romimage
* img
, uint64_t secs
, uint64_t subsecs
)
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
);
175 internal_rom
= &type_sufamiturbo
;
176 have_saved_this_frame
= false;
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
;
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
)
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...
258 if(id
== "bsx.psram")
260 if(id
== "program.rtc")
262 if(id
== "upd96050.ram")
264 if(id
== "program.ram")
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);
273 uint8_t snes_bus_iospace_rw(uint64_t offset
, uint8_t data
, bool write
)
276 SNES::bus
.write(offset
, data
);
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
))
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
)
302 i
.native_endian
= false;
303 i
.iospace_rw
= iospace_rw
;
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
)
316 i
.backing_ram
= memory
;
317 i
.readonly
= readonly
;
318 i
.native_endian
= native_endian
;
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
,
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);
339 if(delayreset_cycles_run
== delayreset_cycles_target
|| video_refresh_done
)
341 delayreset_cycles_run
++;
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();
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") {
359 std::string x
= msubase
+ ".msu";
360 messages
<< "MSU main data file: " << x
<< std::endl
;
363 if(r
= regex("(track)?(-([0-9])+\\.pcm)", _hint2
)) {
365 std::string x
= msubase
+ r
[2];
366 messages
<< "MSU track " << r
[3] << "': " << x
<< std::endl
;
369 std::string finalpath
= fwp
+ "/" + _hint2
;
370 return finalpath
.c_str();
375 return ecore_callbacks
->get_time();
380 return ecore_callbacks
->get_randomseed();
383 void videoRefresh(const uint32_t* data
, bool hires
, bool interlace
, bool overscan
)
386 last_interlace
= interlace
;
387 bool region
= (&core_get_region() == ®ion_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();
395 uint32_t g
= gcd(fps_n
, fps_d
);
399 framebuffer_info inf
;
400 inf
.type
= &_pixel_format_lrgb
;
401 inf
.mem
= const_cast<char*>(reinterpret_cast<const char*>(data
));
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;
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
);
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
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
)
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) {
448 if(js
&& index
== 0) {
450 offset
= js
->player1
.x
;
452 offset
= js
->player1
.y
;
454 if(js
&& js
->chained
&& index
== 1) {
456 offset
= js
->player2
.x
;
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)
471 snes_set_controller_port_device(true, type
);
473 snes_set_controller_port_device(false, p2only
? SNES_DEVICE_NONE
: type
);
478 void set_core_controller_system(unsigned port
) throw()
482 int get_button_id_none(unsigned controller
, unsigned lbid
) throw()
487 template<unsigned lim
>
488 int get_button_id_gamepad(unsigned controller
, unsigned lbid
) throw()
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;
513 int get_button_id_mouse(unsigned controller
, unsigned lbid
) throw()
518 case LOGICAL_BUTTON_L
: return SNES_DEVICE_ID_MOUSE_LEFT
;
519 case LOGICAL_BUTTON_R
: return SNES_DEVICE_ID_MOUSE_RIGHT
;
524 int get_button_id_superscope(unsigned controller
, unsigned lbid
) throw()
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
;
537 template<unsigned lim
>
538 int get_button_id_justifier(unsigned controller
, unsigned lbid
) throw()
543 case LOGICAL_BUTTON_START
: return SNES_DEVICE_ID_JUSTIFIER_START
;
544 case LOGICAL_BUTTON_TRIGGER
: return SNES_DEVICE_ID_JUSTIFIER_TRIGGER
;
549 void system_write(unsigned char* buffer
, unsigned idx
, unsigned ctrl
, short x
) throw()
555 buffer
[0] |= (1 << ctrl
);
557 buffer
[0] &= ~(1 << ctrl
);
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()
569 return (buffer
[0] >> ctrl
) ? 1 : 0;
571 return unserialize_short(buffer
+ 2 * ctrl
- 3);
575 size_t system_deserialize(unsigned char* buffer
, const char* textbuf
)
577 memset(buffer
, 0, 5);
579 if(read_button_value(textbuf
, ptr
))
581 if(read_button_value(textbuf
, ptr
))
583 short v
= read_axis_value(textbuf
, ptr
);
586 v
= read_axis_value(textbuf
, ptr
);
589 skip_rest_of_field(textbuf
, ptr
, false);
593 void system_display(const unsigned char* buffer
, unsigned idx
, char* buf
)
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
)
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));
609 sprintf(tmp
, "%c%c", ((buffer
[0] & 1) ? 'F' : '.'), ((buffer
[0] & 2) ? 'R' : '.'));
610 size_t len
= strlen(tmp
);
611 memcpy(textbuf
, tmp
, 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
;
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>;
633 set_core_controller
= set_core_controller_system
;
634 core_portgroup
.set_default(0, *this);
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>;
653 set_core_controller
= set_core_controller_X
<SNES_DEVICE_JOYPAD
, false>;
654 core_portgroup
.set_default(1, *this);
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>;
674 set_core_controller
= set_core_controller_X
<SNES_DEVICE_JOYPAD
, false>;
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>;
694 set_core_controller
= set_core_controller_X
<SNES_DEVICE_JUSTIFIER
, true>;
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>;
714 set_core_controller
= set_core_controller_X
<SNES_DEVICE_JUSTIFIERS
, true>;
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>;
733 set_core_controller
= set_core_controller_X
<SNES_DEVICE_MOUSE
, false>;
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>;
753 set_core_controller
= set_core_controller_X
<SNES_DEVICE_MULTITAP
, false>;
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>;
773 set_core_controller
= set_core_controller_X
<SNES_DEVICE_MULTITAP
, false>;
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>;
792 set_core_controller
= set_core_controller_X
<SNES_DEVICE_NONE
, false>;
793 core_portgroup
.set_default(2, *this);
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>;
813 set_core_controller
= set_core_controller_X
<SNES_DEVICE_SUPER_SCOPE
, true>;
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
++) {
835 t
.marks_nonlag
= true;
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
);
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
);
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
);
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);
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]))
898 return buttonnames
[lbid
];
901 void core_install_handler()
903 old
= SNES::interface
;
904 SNES::interface
= &my_interface_obj
;
908 std::string
get_core_default_port(unsigned port
)
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()
941 std::string
get_core_identifier()
943 std::ostringstream x
;
944 x
<< snes_library_id() << " (" << SNES::Info::Profile
<< " core)";
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
;
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
));
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
)
986 void core_unload_cartridge()
991 snes_unload_cartridge();
995 //Get the current video rate.
996 std::pair
<uint32_t, uint32_t> get_video_rate()
999 return std::make_pair(60, 1);
1001 if(snes_get_region())
1002 div
= last_interlace
? DURATION_PAL_FIELD
: DURATION_PAL_FRAME
;
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()
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
;
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
;
1026 memcpy(&x
[0], r
.data
, r
.size
);
1032 void load_sram(std::map
<std::string
, std::vector
<char>>& sram
) throw(std::bad_alloc
)
1034 std::set
<std::string
> used
;
1037 messages
<< "WARNING: SRAM '" << i
.first
<< ": Not found on cartridge." << std::endl
;
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
);
1053 messages
<< "WARNING: SRAM '" << savename
<< ": No data." << std::endl
;
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(®ion
== ®ion_auto
) SNES::config
.region
= SNES::System::Region::Autodetect
;
1063 else if(®ion
== ®ion_ntsc
) SNES::config
.region
= SNES::System::Region::NTSC
;
1064 else if(®ion
== ®ion_pal
) SNES::config
.region
= SNES::System::Region::PAL
;
1070 void core_serialize(std::vector
<char>& out
)
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
)
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;
1090 void core_request_reset(long delay
)
1092 do_reset_flag
= delay
;
1095 std::pair
<bool, uint32_t> core_emulate_cycles(uint32_t cycles
)
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
;
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;
1110 messages
<< "Delayresets not supported on this bsnes version (needs v084 or v085)"
1112 return std::make_pair(false, 0);
1116 void core_emulate_frame()
1118 static unsigned frame_modulus
= 0;
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;
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);
1141 information_dispatch::do_sample(0, 0);
1143 frame_modulus
%= 120;
1144 ecore_callbacks
->timer_tick(1, 60);
1148 bool was_delay_reset
= false;
1149 int16_t reset
= ecore_callbacks
->set_input(0, 0, 1, (do_reset_flag
>= 0) ? 1 : 0);
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
;
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
;
1163 SNES::cpu
.step_event
= nall::function
<bool()>();
1164 if(video_refresh_done
) {
1165 //Force the reset here.
1167 messages
<< "SNES reset (forced at " << delayreset_cycles_run
<< ")" << std::endl
;
1168 SNES::system
.reset();
1171 SNES::system
.reset();
1172 messages
<< "SNES reset (delayed " << delayreset_cycles_run
<< ")" << std::endl
;
1174 messages
<< "Delayresets not supported on this bsnes version (needs v084 or v085)"
1176 SNES::system
.reset();
1178 } else if(delay
== 0) {
1179 SNES::system
.reset();
1180 messages
<< "SNES reset" << std::endl
;
1186 if(!have_saved_this_frame
&& save_every_frame
&& !was_delay_reset
)
1187 SNES::system
.runtosave();
1189 have_saved_this_frame
= false;
1192 void core_runtosave()
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
;
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,
1218 create_region(ret
, "DSPPROM", 0xF0000000, reinterpret_cast<uint8_t*>(SNES::necdsp
.programROM
), 65536,
1220 create_region(ret
, "DSPDROM", 0xF0010000, reinterpret_cast<uint8_t*>(SNES::necdsp
.dataROM
), 4096,
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);
1249 std::pair
<uint32_t, uint32_t> get_scale_factors(uint32_t width
, uint32_t height
)
1251 uint32_t h
= 1, v
= 1;
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
;