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
59 const char* button_symbols
= "BYsSudlrAXLRTSTCUPFR";
61 port_type_group core_portgroup
;
62 unsigned core_userports
= 2;
66 bool pollflag_active
= true;
67 boolean_setting
allow_inconsistent_saves("allow-inconsistent-saves", false);
68 boolean_setting
save_every_frame("save-every-frame", false);
69 uint32_t norom_frame
[512 * 448];
70 bool have_saved_this_frame
= false;
71 int16_t blanksound
[1070] = {0};
72 int16_t soundbuf
[8192] = {0};
73 size_t soundbuf_fill
= 0;
74 unsigned index_count_table
[] = {12, 12, 12, 12};
75 unsigned index_count_table_sys
[] = {4};
77 void init_norom_frame()
79 static bool done
= false;
83 for(size_t i
= 0; i
< 512 * 448; i
++)
84 norom_frame
[i
] = 0x7C21F;
87 int regions_compatible(unsigned rom
, unsigned run
)
89 return (!rom
|| rom
== run
);
92 unsigned header_fn(size_t r
)
100 core_type
* internal_rom
= NULL
;
101 extern core_type type_snes
;
102 extern core_type type_bsx
;
103 extern core_type type_bsxslotted
;
104 extern core_type type_sufamiturbo
;
105 extern core_type type_sgb
;
107 int load_rom_snes(core_romimage
* img
, uint64_t secs
, uint64_t subsecs
)
110 snes_unload_cartridge();
111 bool r
= snes_load_cartridge_normal(img
[0].markup
, img
[0].data
, img
[0].size
);
113 internal_rom
= &type_snes
;
114 have_saved_this_frame
= false;
118 int load_rom_bsx(core_romimage
* img
, uint64_t secs
, uint64_t subsecs
)
121 snes_unload_cartridge();
122 bool r
= snes_load_cartridge_bsx(img
[0].markup
, img
[0].data
, img
[0].size
,
123 img
[1].markup
, img
[1].data
, img
[1].size
);
125 internal_rom
= &type_bsx
;
126 have_saved_this_frame
= false;
130 int load_rom_bsxslotted(core_romimage
* img
, uint64_t secs
, uint64_t subsecs
)
133 snes_unload_cartridge();
134 bool r
= snes_load_cartridge_bsx_slotted(img
[0].markup
, img
[0].data
, img
[0].size
,
135 img
[1].markup
, img
[1].data
, img
[1].size
);
137 internal_rom
= &type_bsxslotted
;
138 have_saved_this_frame
= false;
142 int load_rom_sgb(core_romimage
* img
, uint64_t secs
, uint64_t subsecs
)
145 snes_unload_cartridge();
146 bool r
= snes_load_cartridge_super_game_boy(img
[0].markup
, img
[0].data
, img
[0].size
,
147 img
[1].markup
, img
[1].data
, img
[1].size
);
149 internal_rom
= &type_sgb
;
150 have_saved_this_frame
= false;
154 int load_rom_sufamiturbo(core_romimage
* img
, uint64_t secs
, uint64_t subsecs
)
157 snes_unload_cartridge();
158 bool r
= snes_load_cartridge_sufami_turbo(img
[0].markup
, img
[0].data
, img
[0].size
,
159 img
[1].markup
, img
[1].data
, img
[1].size
, img
[2].markup
, img
[2].data
, img
[2].size
);
161 internal_rom
= &type_sufamiturbo
;
162 have_saved_this_frame
= false;
166 uint64_t ntsc_magic
[4] = {178683, 10738636, 16639264, 596096};
167 uint64_t pal_magic
[4] = {6448, 322445, 19997208, 266440};
169 core_region
region_auto("autodetect", "Autodetect", 1, 0, true, ntsc_magic
, regions_compatible
);
170 core_region
region_ntsc("ntsc", "NTSC", 0, 1, true, ntsc_magic
, regions_compatible
);
171 core_region
region_pal("pal", "PAL", 0, 2, true, pal_magic
, regions_compatible
);
172 core_romimage_info
image_snescart("rom", "Cartridge ROM", 1, header_fn
);
173 core_romimage_info
image_bsxbios("rom", "BS-X BIOS", 1, header_fn
);
174 core_romimage_info
image_bsxflash("bsx", "BS-X Flash", 2, header_fn
);
175 core_romimage_info
image_bsxsflash("bsx", "BS-X Flash", 2, header_fn
);
176 core_romimage_info
image_sgbbios("rom", "SGB BIOS", 1, header_fn
);
177 core_romimage_info
image_dmg("dmg", "DMG ROM", 2, header_fn
);
178 core_romimage_info
image_stbios("rom", "ST BIOS", 1, header_fn
);
179 core_romimage_info
image_stslota("slot-a", "ST Slot A ROM", 2, header_fn
);
180 core_romimage_info
image_stslotb("slot-b", "ST Slot B ROM", 2, header_fn
);
181 core_type
type_snes("snes", "SNES", 0, load_rom_snes
, "sfc;smc;swc;fig;ufo;sf2;gd3;gd7;dx2;mgd;mgh");
182 core_type
type_bsx("bsx", "BS-X (non-slotted)", 1, load_rom_bsx
, "bsx.sfc!bs");
183 core_type
type_bsxslotted("bsxslotted", "BS-X (slotted)", 2, load_rom_bsxslotted
, "bsxslotted.sfc!bss");
184 core_type
type_sufamiturbo("sufamiturbo", "Sufami Turbo", 3, load_rom_sufamiturbo
, "sufamiturbo.sfc!st");
185 core_type
type_sgb("sgb", "Super Game Boy", 4, load_rom_sgb
, "sgb.sfc!gb;dmg;sgb");
186 core_type_region_bind
bind_A(type_snes
, region_auto
);
187 core_type_region_bind
bind_B(type_snes
, region_ntsc
);
188 core_type_region_bind
bind_C(type_snes
, region_pal
);
189 core_type_region_bind
bind_D(type_bsx
, region_ntsc
);
190 core_type_region_bind
bind_E(type_bsxslotted
, region_ntsc
);
191 core_type_region_bind
bind_F(type_sufamiturbo
, region_ntsc
);
192 core_type_region_bind
bind_G(type_sgb
, region_auto
);
193 core_type_region_bind
bind_H(type_sgb
, region_ntsc
);
194 core_type_region_bind
bind_I(type_sgb
, region_pal
);
195 core_type_image_bind
bind_J(type_snes
, image_snescart
, 0);
196 core_type_image_bind
bind_K(type_bsx
, image_bsxbios
, 0);
197 core_type_image_bind
bind_L(type_bsx
, image_bsxflash
, 1);
198 core_type_image_bind
bind_M(type_bsxslotted
, image_bsxbios
, 0);
199 core_type_image_bind
bind_N(type_bsxslotted
, image_bsxsflash
, 1);
200 core_type_image_bind
bind_O(type_sufamiturbo
, image_stbios
, 0);
201 core_type_image_bind
bind_P(type_sufamiturbo
, image_stslota
, 1);
202 core_type_image_bind
bind_Q(type_sufamiturbo
, image_stslotb
, 2);
203 core_type_image_bind
bind_R(type_sgb
, image_sgbbios
, 0);
204 core_type_image_bind
bind_S(type_sgb
, image_dmg
, 1);
205 core_sysregion
sr1("snes_ntsc", type_snes
, region_ntsc
);
206 core_sysregion
sr2("snes_pal", type_snes
, region_pal
);
207 core_sysregion
sr3("bsx", type_bsx
, region_ntsc
);
208 core_sysregion
sr4("bsxslotted", type_bsxslotted
, region_ntsc
);
209 core_sysregion
sr5("sufamiturbo", type_sufamiturbo
, region_ntsc
);
210 core_sysregion
sr6("sgb_ntsc", type_sgb
, region_ntsc
);
211 core_sysregion
sr7("sgb_pal", type_sgb
, region_pal
);
213 bool last_hires
= false;
214 bool last_interlace
= false;
215 bool stepping_into_save
;
216 bool video_refresh_done
;
218 unsigned long long delayreset_cycles_run
;
219 unsigned long long delayreset_cycles_target
;
221 bool p1disable
= false;
222 std::map
<int16_t, std::pair
<uint64_t, uint64_t>> ptrmap
;
224 const char* buttonnames
[] = {
225 "left", "right", "up", "down", "A", "B", "X", "Y", "L", "R", "select", "start", "trigger",
226 "cursor", "turbo", "pause"
229 class my_interfaced
: public SNES::Interface
231 string
path(SNES::Cartridge::Slot slot
, const string
&hint
)
237 std::string
sram_name(const nall::string
& _id
, SNES::Cartridge::Slot slotname
)
239 std::string
id(_id
, _id
.length());
240 //Fixup name change by bsnes v087...
243 if(id
== "bsx.psram")
245 if(id
== "program.rtc")
247 if(id
== "upd96050.ram")
249 if(id
== "program.ram")
251 if(slotname
== SNES::Cartridge::Slot::SufamiTurboA
)
252 return "slota." + id
.substr(1);
253 if(slotname
== SNES::Cartridge::Slot::SufamiTurboB
)
254 return "slotb." + id
.substr(1);
258 uint8_t snes_bus_iospace_rw(uint64_t offset
, uint8_t data
, bool write
)
261 SNES::bus
.write(offset
, data
);
263 return SNES::bus
.read(offset
);
266 uint8_t ptrtable_iospace_rw(uint64_t offset
, uint8_t data
, bool write
)
268 uint16_t entry
= offset
>> 4;
269 if(!ptrmap
.count(entry
))
271 uint64_t val
= ((offset
& 15) < 8) ? ptrmap
[entry
].first
: ptrmap
[entry
].second
;
272 uint8_t byte
= offset
& 7;
273 //These things are always little-endian.
274 return (val
>> (8 * byte
));
277 void create_region(std::list
<vma_info
>& inf
, const std::string
& name
, uint64_t base
, uint64_t size
,
278 uint8_t (*iospace_rw
)(uint64_t offset
, uint8_t data
, bool write
)) throw(std::bad_alloc
)
287 i
.native_endian
= false;
288 i
.iospace_rw
= iospace_rw
;
292 void create_region(std::list
<vma_info
>& inf
, const std::string
& name
, uint64_t base
, uint8_t* memory
,
293 uint64_t size
, bool readonly
, bool native_endian
= false) throw(std::bad_alloc
)
301 i
.backing_ram
= memory
;
302 i
.readonly
= readonly
;
303 i
.native_endian
= native_endian
;
308 void create_region(std::list
<vma_info
>& inf
, const std::string
& name
, uint64_t base
,
309 SNES::MappedRAM
& memory
, bool readonly
, bool native_endian
= false) throw(std::bad_alloc
)
311 create_region(inf
, name
, base
, memory
.data(), memory
.size(), readonly
, native_endian
);
314 void map_internal(std::list
<vma_info
>& inf
, const std::string
& name
, uint16_t index
, void* memory
,
317 ptrmap
[index
] = std::make_pair(reinterpret_cast<uint64_t>(memory
), static_cast<uint64_t>(memsize
));
318 create_region(inf
, name
, 0x101000000 + index
* 0x1000000, reinterpret_cast<uint8_t*>(memory
),
319 memsize
, true, true);
324 if(delayreset_cycles_run
== delayreset_cycles_target
|| video_refresh_done
)
326 delayreset_cycles_run
++;
330 class my_interface
: public SNES::Interface
332 string
path(SNES::Cartridge::Slot slot
, const string
&hint
)
334 const char* _hint
= hint
;
335 std::string _hint2
= _hint
;
336 std::string fwp
= ecore_callbacks
->get_firmware_path();
338 std::string msubase
= ecore_callbacks
->get_base_path();
339 if(regex_match(".*\\.sfc", msubase
))
340 msubase
= msubase
.substr(0, msubase
.length() - 4);
342 if(_hint2
== "msu1.rom" || _hint2
== ".msu") {
344 std::string x
= msubase
+ ".msu";
345 messages
<< "MSU main data file: " << x
<< std::endl
;
348 if(r
= regex("(track)?(-([0-9])+\\.pcm)", _hint2
)) {
350 std::string x
= msubase
+ r
[2];
351 messages
<< "MSU track " << r
[3] << "': " << x
<< std::endl
;
354 std::string finalpath
= fwp
+ "/" + _hint2
;
355 return finalpath
.c_str();
360 return ecore_callbacks
->get_time();
365 return ecore_callbacks
->get_randomseed();
368 void videoRefresh(const uint32_t* data
, bool hires
, bool interlace
, bool overscan
)
371 last_interlace
= interlace
;
372 bool region
= (&core_get_region() == ®ion_pal
);
373 if(stepping_into_save
)
374 messages
<< "Got video refresh in runtosave, expect desyncs!" << std::endl
;
375 video_refresh_done
= true;
376 uint32_t fps_n
, fps_d
;
377 auto fps
= get_video_rate();
380 uint32_t g
= gcd(fps_n
, fps_d
);
384 framebuffer_info inf
;
385 inf
.type
= &_pixel_format_lrgb
;
386 inf
.mem
= const_cast<char*>(reinterpret_cast<const char*>(data
));
388 inf
.physheight
= 512;
389 inf
.physstride
= 2048;
390 inf
.width
= hires
? 512 : 256;
391 inf
.height
= (region
? 239 : 224) * (interlace
? 2 : 1);
392 inf
.stride
= interlace
? 2048 : 4096;
394 inf
.offset_y
= (region
? (overscan
? 9 : 1) : (overscan
? 16 : 9)) * 2;
396 framebuffer_raw
ls(inf
);
397 ecore_callbacks
->output_frame(ls
, fps_n
, fps_d
);
398 information_dispatch::do_raw_frame(data
, hires
, interlace
, overscan
, region
?
399 VIDEO_REGION_PAL
: VIDEO_REGION_NTSC
);
400 if(soundbuf_fill
> 0) {
401 auto hz
= get_audio_rate();
402 audioapi_submit_buffer(soundbuf
, soundbuf_fill
/ 2, true, 1.0 * hz
.first
/ hz
.second
);
407 void audioSample(int16_t l_sample
, int16_t r_sample
)
409 uint16_t _l
= l_sample
;
410 uint16_t _r
= r_sample
;
411 soundbuf
[soundbuf_fill
++] = l_sample
;
412 soundbuf
[soundbuf_fill
++] = r_sample
;
413 information_dispatch::do_sample(l_sample
, r_sample
);
414 //The SMP emits a sample every 768 ticks of its clock. Use this in order to keep track of
416 auto hz
= get_audio_rate();
417 ecore_callbacks
->timer_tick(hz
.second
, hz
.first
);
420 int16_t inputPoll(bool port
, SNES::Input::Device device
, unsigned index
, unsigned id
)
422 return ecore_callbacks
->get_input(port
? 2 : 1, index
, id
);
426 void set_core_controller_generic(unsigned port
, unsigned id
, bool p2only
)
431 snes_set_controller_port_device(true, id
);
433 snes_set_controller_port_device(false, p2only
? SNES_DEVICE_NONE
: id
);
438 void set_core_controller_none(unsigned port
) throw()
440 std::cerr
<< "Setting device " << port
<< " to NONE" << std::endl
;
441 set_core_controller_generic(port
- 1, SNES_DEVICE_NONE
, false);
444 void set_core_controller_gamepad(unsigned port
) throw()
446 std::cerr
<< "Setting device " << port
<< " to GAMEPAD" << std::endl
;
447 set_core_controller_generic(port
- 1, SNES_DEVICE_JOYPAD
, false);
450 void set_core_controller_mouse(unsigned port
) throw()
452 set_core_controller_generic(port
- 1, SNES_DEVICE_MOUSE
, false);
455 void set_core_controller_multitap(unsigned port
) throw()
457 set_core_controller_generic(port
- 1, SNES_DEVICE_MULTITAP
, false);
460 void set_core_controller_superscope(unsigned port
) throw()
462 set_core_controller_generic(port
- 1, SNES_DEVICE_SUPER_SCOPE
, true);
465 void set_core_controller_justifier(unsigned port
) throw()
467 set_core_controller_generic(port
- 1, SNES_DEVICE_JUSTIFIER
, true);
470 void set_core_controller_justifiers(unsigned port
) throw()
472 set_core_controller_generic(port
- 1, SNES_DEVICE_JUSTIFIERS
, true);
475 void set_core_controller_system(unsigned port
) throw()
479 int get_button_id_none(unsigned controller
, unsigned lbid
) throw()
484 int get_button_id_gamepad(unsigned controller
, unsigned lbid
) throw()
489 case LOGICAL_BUTTON_LEFT
: return SNES_DEVICE_ID_JOYPAD_LEFT
;
490 case LOGICAL_BUTTON_RIGHT
: return SNES_DEVICE_ID_JOYPAD_RIGHT
;
491 case LOGICAL_BUTTON_UP
: return SNES_DEVICE_ID_JOYPAD_UP
;
492 case LOGICAL_BUTTON_DOWN
: return SNES_DEVICE_ID_JOYPAD_DOWN
;
493 case LOGICAL_BUTTON_A
: return SNES_DEVICE_ID_JOYPAD_A
;
494 case LOGICAL_BUTTON_B
: return SNES_DEVICE_ID_JOYPAD_B
;
495 case LOGICAL_BUTTON_X
: return SNES_DEVICE_ID_JOYPAD_X
;
496 case LOGICAL_BUTTON_Y
: return SNES_DEVICE_ID_JOYPAD_Y
;
497 case LOGICAL_BUTTON_L
: return SNES_DEVICE_ID_JOYPAD_L
;
498 case LOGICAL_BUTTON_R
: return SNES_DEVICE_ID_JOYPAD_R
;
499 case LOGICAL_BUTTON_SELECT
: return SNES_DEVICE_ID_JOYPAD_SELECT
;
500 case LOGICAL_BUTTON_START
: return SNES_DEVICE_ID_JOYPAD_START
;
505 int get_button_id_mouse(unsigned controller
, unsigned lbid
) throw()
510 case LOGICAL_BUTTON_L
: return SNES_DEVICE_ID_MOUSE_LEFT
;
511 case LOGICAL_BUTTON_R
: return SNES_DEVICE_ID_MOUSE_RIGHT
;
516 int get_button_id_multitap(unsigned controller
, unsigned lbid
) throw()
521 case LOGICAL_BUTTON_LEFT
: return SNES_DEVICE_ID_JOYPAD_LEFT
;
522 case LOGICAL_BUTTON_RIGHT
: return SNES_DEVICE_ID_JOYPAD_RIGHT
;
523 case LOGICAL_BUTTON_UP
: return SNES_DEVICE_ID_JOYPAD_UP
;
524 case LOGICAL_BUTTON_DOWN
: return SNES_DEVICE_ID_JOYPAD_DOWN
;
525 case LOGICAL_BUTTON_A
: return SNES_DEVICE_ID_JOYPAD_A
;
526 case LOGICAL_BUTTON_B
: return SNES_DEVICE_ID_JOYPAD_B
;
527 case LOGICAL_BUTTON_X
: return SNES_DEVICE_ID_JOYPAD_X
;
528 case LOGICAL_BUTTON_Y
: return SNES_DEVICE_ID_JOYPAD_Y
;
529 case LOGICAL_BUTTON_L
: return SNES_DEVICE_ID_JOYPAD_L
;
530 case LOGICAL_BUTTON_R
: return SNES_DEVICE_ID_JOYPAD_R
;
531 case LOGICAL_BUTTON_SELECT
: return SNES_DEVICE_ID_JOYPAD_SELECT
;
532 case LOGICAL_BUTTON_START
: return SNES_DEVICE_ID_JOYPAD_START
;
537 int get_button_id_superscope(unsigned controller
, unsigned lbid
) throw()
542 case LOGICAL_BUTTON_TRIGGER
: return SNES_DEVICE_ID_SUPER_SCOPE_TRIGGER
;
543 case LOGICAL_BUTTON_CURSOR
: return SNES_DEVICE_ID_SUPER_SCOPE_CURSOR
;
544 case LOGICAL_BUTTON_TURBO
: return SNES_DEVICE_ID_SUPER_SCOPE_TURBO
;
545 case LOGICAL_BUTTON_PAUSE
: return SNES_DEVICE_ID_SUPER_SCOPE_PAUSE
;
550 int get_button_id_justifier(unsigned controller
, unsigned lbid
) throw()
555 case LOGICAL_BUTTON_START
: return SNES_DEVICE_ID_JUSTIFIER_START
;
556 case LOGICAL_BUTTON_TRIGGER
: return SNES_DEVICE_ID_JUSTIFIER_TRIGGER
;
561 int get_button_id_justifiers(unsigned controller
, unsigned lbid
) throw()
566 case LOGICAL_BUTTON_START
: return SNES_DEVICE_ID_JUSTIFIER_START
;
567 case LOGICAL_BUTTON_TRIGGER
: return SNES_DEVICE_ID_JUSTIFIER_TRIGGER
;
572 void system_write(unsigned char* buffer
, unsigned idx
, unsigned ctrl
, short x
) throw()
578 buffer
[0] |= (1 << ctrl
);
580 buffer
[0] &= ~(1 << ctrl
);
582 buffer
[2 * ctrl
- 3] = x
>> 8;
583 buffer
[2 * ctrl
- 2] = x
;
587 short system_read(const unsigned char* buffer
, unsigned idx
, unsigned ctrl
) throw()
592 return (buffer
[0] >> ctrl
) ? 1 : 0;
594 return unserialize_short(buffer
+ 2 * ctrl
- 3);
598 size_t system_deserialize(unsigned char* buffer
, const char* textbuf
)
600 memset(buffer
, 0, 5);
602 if(read_button_value(textbuf
, ptr
))
604 if(read_button_value(textbuf
, ptr
))
606 short v
= read_axis_value(textbuf
, ptr
);
609 v
= read_axis_value(textbuf
, ptr
);
612 skip_rest_of_field(textbuf
, ptr
, false);
616 void system_display(const unsigned char* buffer
, unsigned idx
, char* buf
)
621 sprintf(buf
, "%c%c %i %i", ((buffer
[0] & 1) ? 'F' : '.'), ((buffer
[0] & 2) ? 'R' : '.'),
622 unserialize_short(buffer
+ 1), unserialize_short(buffer
+ 3));
625 size_t system_serialize(const unsigned char* buffer
, char* textbuf
)
628 if(buffer
[1] || buffer
[2] || buffer
[3] || buffer
[4])
629 sprintf(tmp
, "%c%c %i %i", ((buffer
[0] & 1) ? 'F' : '.'), ((buffer
[0] & 2) ? 'R' : '.'),
630 unserialize_short(buffer
+ 1), unserialize_short(buffer
+ 3));
632 sprintf(tmp
, "%c%c", ((buffer
[0] & 1) ? 'F' : '.'), ((buffer
[0] & 2) ? 'R' : '.'));
633 size_t len
= strlen(tmp
);
634 memcpy(textbuf
, tmp
, len
);
638 struct porttype_system
: public port_type
640 porttype_system() : port_type(core_portgroup
, "<SYSTEM>", "<SYSTEM>", 9999, 5)
642 write
= system_write
;
644 display
= system_display
;
645 serialize
= system_serialize
;
646 deserialize
= system_deserialize
;
647 legal
= generic_port_legal
<0>;
648 deviceflags
= generic_port_deviceflags
<1, 1>;
649 button_id
= get_button_id_none
;
653 controller_indices
= index_count_table_sys
;
654 set_core_controller
= set_core_controller_system
;
655 core_portgroup
.set_default(0, *this);
659 struct porttype_gamepad
: public port_type
661 porttype_gamepad() : port_type(core_portgroup
, "gamepad", "Gamepad", 1, generic_port_size
<1, 0, 12>())
663 write
= generic_port_write
<1, 0, 12>;
664 read
= generic_port_read
<1, 0, 12>;
665 display
= generic_port_display
<1, 0, 12, 0>;
666 serialize
= generic_port_serialize
<1, 0, 12, 0>;
667 deserialize
= generic_port_deserialize
<1, 0, 12>;
668 legal
= generic_port_legal
<3>;
669 deviceflags
= generic_port_deviceflags
<1, 1>;
670 button_id
= get_button_id_gamepad
;
671 ctrlname
= "gamepad";
674 controller_indices
= index_count_table
;
675 set_core_controller
= set_core_controller_gamepad
;
676 core_portgroup
.set_default(1, *this);
680 struct porttype_justifier
: public port_type
682 porttype_justifier() : port_type(core_portgroup
, "justifier", "Justifier", 5,
683 generic_port_size
<1, 2, 2>())
685 write
= generic_port_write
<1, 2, 2>;
686 read
= generic_port_read
<1, 2, 2>;
687 display
= generic_port_display
<1, 2, 2, 12>;
688 serialize
= generic_port_serialize
<1, 2, 2, 12>;
689 deserialize
= generic_port_deserialize
<1, 2, 2>;
690 legal
= generic_port_legal
<2>;
691 deviceflags
= generic_port_deviceflags
<1, 3>;
692 button_id
= get_button_id_justifier
;
693 ctrlname
= "justifier";
696 controller_indices
= index_count_table
;
697 set_core_controller
= set_core_controller_justifier
;
701 struct porttype_justifiers
: public port_type
703 porttype_justifiers() : port_type(core_portgroup
, "justifiers", "2 Justifiers", 6,
704 generic_port_size
<2, 2, 2>())
706 write
= generic_port_write
<2, 2, 2>;
707 read
= generic_port_read
<2, 2, 2>;
708 display
= generic_port_display
<2, 2, 2, 0>;
709 serialize
= generic_port_serialize
<2, 2, 2, 12>;
710 deserialize
= generic_port_deserialize
<2, 2, 2>;
711 legal
= generic_port_legal
<2>;
712 deviceflags
= generic_port_deviceflags
<2, 3>;
713 button_id
= get_button_id_justifiers
;
714 ctrlname
= "justifier";
717 controller_indices
= index_count_table
;
718 set_core_controller
= set_core_controller_justifiers
;
722 struct porttype_mouse
: public port_type
724 porttype_mouse() : port_type(core_portgroup
, "mouse", "Mouse", 3, generic_port_size
<1, 2, 2>())
726 write
= generic_port_write
<1, 2, 2>;
727 read
= generic_port_read
<1, 2, 2>;
728 display
= generic_port_display
<1, 2, 2, 0>;
729 serialize
= generic_port_serialize
<1, 2, 2, 12>;
730 deserialize
= generic_port_deserialize
<1, 2, 2>;
731 legal
= generic_port_legal
<3>;
732 deviceflags
= generic_port_deviceflags
<1, 5>;
733 button_id
= get_button_id_mouse
;
737 controller_indices
= index_count_table
;
738 set_core_controller
= set_core_controller_mouse
;
742 struct porttype_multitap
: public port_type
744 porttype_multitap() : port_type(core_portgroup
, "multitap", "Multitap", 2,
745 generic_port_size
<4, 0, 12>())
747 write
= generic_port_write
<4, 0, 12>;
748 read
= generic_port_read
<4, 0, 12>;
749 display
= generic_port_display
<4, 0, 12, 0>;
750 serialize
= generic_port_serialize
<4, 0, 12, 0>;
751 deserialize
= generic_port_deserialize
<4, 0, 12>;
752 legal
= generic_port_legal
<3>;
753 deviceflags
= generic_port_deviceflags
<4, 1>;
754 button_id
= get_button_id_multitap
;
755 ctrlname
= "multitap";
759 controller_indices
= index_count_table
;
760 set_core_controller
= set_core_controller_multitap
;
764 struct porttype_none
: public port_type
766 porttype_none() : port_type(core_portgroup
, "none", "None", 0, generic_port_size
<0, 0, 0>())
768 write
= generic_port_write
<0, 0, 0>;
769 read
= generic_port_read
<0, 0, 0>;
770 display
= generic_port_display
<0, 0, 0, 0>;
771 serialize
= generic_port_serialize
<0, 0, 0, 0>;
772 deserialize
= generic_port_deserialize
<0, 0, 0>;
773 legal
= generic_port_legal
<3>;
774 deviceflags
= generic_port_deviceflags
<0, 0>;
775 button_id
= get_button_id_none
;
779 controller_indices
= index_count_table
;
780 set_core_controller
= set_core_controller_none
;
781 core_portgroup
.set_default(2, *this);
785 struct porttype_superscope
: public port_type
787 porttype_superscope() : port_type(core_portgroup
, "superscope", "Super Scope", 4,
788 generic_port_size
<1, 2, 4>())
790 write
= generic_port_write
<1, 2, 4>;
791 read
= generic_port_read
<1, 2, 4>;
792 display
= generic_port_display
<1, 2, 4, 0>;
793 serialize
= generic_port_serialize
<1, 2, 4, 14>;
794 deserialize
= generic_port_deserialize
<1, 2, 4>;
795 deviceflags
= generic_port_deviceflags
<1, 3>;
796 legal
= generic_port_legal
<2>;
797 button_id
= get_button_id_superscope
;
798 ctrlname
= "superscope";
801 controller_indices
= index_count_table
;
802 set_core_controller
= set_core_controller_superscope
;
806 my_interface my_interface_obj
;
807 SNES::Interface
* old
;
810 std::string
get_logical_button_name(unsigned lbid
) throw(std::bad_alloc
)
812 if(lbid
>= sizeof(buttonnames
) / sizeof(buttonnames
[0]))
814 return buttonnames
[lbid
];
817 void core_install_handler()
819 old
= SNES::interface
;
820 SNES::interface
= &my_interface_obj
;
824 std::string
get_core_default_port(unsigned port
)
832 void core_uninstall_handler()
834 SNES::interface
= old
;
837 uint32_t get_snes_cpu_rate()
839 return SNES::system
.cpu_frequency();
842 uint32_t get_snes_apu_rate()
844 return SNES::system
.apu_frequency();
847 std::pair
<unsigned, unsigned> get_core_logical_controller_limits()
849 return std::make_pair(8U, (unsigned)(sizeof(buttonnames
)/sizeof(buttonnames
[0])));
852 bool get_core_need_analog()
857 std::string
get_core_identifier()
859 std::ostringstream x
;
860 x
<< snes_library_id() << " (" << SNES::Info::Profile
<< " core)";
864 void do_basic_core_init()
866 static my_interfaced i
;
867 SNES::interface
= &i
;
870 std::set
<std::string
> get_sram_set()
872 std::set
<std::string
> r
;
875 for(unsigned i
= 0; i
< SNES::cartridge
.nvram
.size(); i
++) {
876 SNES::Cartridge::NonVolatileRAM
& s
= SNES::cartridge
.nvram
[i
];
877 r
.insert(sram_name(s
.id
, s
.slot
));
882 void set_preload_settings()
884 SNES::config
.random
= false;
885 SNES::config
.expansion_port
= SNES::System::ExpansionPortDevice::None
;
888 core_region
& core_get_region()
890 if(SNES::system
.region() == SNES::System::Region::PAL
)
902 void core_unload_cartridge()
907 snes_unload_cartridge();
911 //Get the current video rate.
912 std::pair
<uint32_t, uint32_t> get_video_rate()
915 return std::make_pair(60, 1);
917 if(snes_get_region())
918 div
= last_interlace
? DURATION_PAL_FIELD
: DURATION_PAL_FRAME
;
920 div
= last_interlace
? DURATION_NTSC_FIELD
: DURATION_NTSC_FRAME
;
921 return std::make_pair(get_snes_cpu_rate(), div
);
924 //Get the current audio rate.
925 std::pair
<uint32_t, uint32_t> get_audio_rate()
928 return std::make_pair(64081, 2);
929 return std::make_pair(get_snes_apu_rate(), static_cast<uint32_t>(768));
932 std::map
<std::string
, std::vector
<char>> save_sram() throw(std::bad_alloc
)
934 std::map
<std::string
, std::vector
<char>> out
;
937 for(unsigned i
= 0; i
< SNES::cartridge
.nvram
.size(); i
++) {
938 SNES::Cartridge::NonVolatileRAM
& r
= SNES::cartridge
.nvram
[i
];
939 std::string savename
= sram_name(r
.id
, r
.slot
);
942 memcpy(&x
[0], r
.data
, r
.size
);
948 void load_sram(std::map
<std::string
, std::vector
<char>>& sram
) throw(std::bad_alloc
)
950 std::set
<std::string
> used
;
953 messages
<< "WARNING: SRAM '" << i
.first
<< ": Not found on cartridge." << std::endl
;
958 for(unsigned i
= 0; i
< SNES::cartridge
.nvram
.size(); i
++) {
959 SNES::Cartridge::NonVolatileRAM
& r
= SNES::cartridge
.nvram
[i
];
960 std::string savename
= sram_name(r
.id
, r
.slot
);
961 if(sram
.count(savename
)) {
962 std::vector
<char>& x
= sram
[savename
];
963 if(r
.size
!= x
.size())
964 messages
<< "WARNING: SRAM '" << savename
<< "': Loaded " << x
.size()
965 << " bytes, but the SRAM is " << r
.size
<< "." << std::endl
;
966 memcpy(r
.data
, &x
[0], (r
.size
< x
.size()) ? r
.size
: x
.size());
967 used
.insert(savename
);
969 messages
<< "WARNING: SRAM '" << savename
<< ": No data." << std::endl
;
972 if(!used
.count(i
.first
))
973 messages
<< "WARNING: SRAM '" << i
.first
<< ": Not found on cartridge." << std::endl
;
976 bool core_set_region(core_region
& region
)
978 if(®ion
== ®ion_auto
) SNES::config
.region
= SNES::System::Region::Autodetect
;
979 else if(®ion
== ®ion_ntsc
) SNES::config
.region
= SNES::System::Region::NTSC
;
980 else if(®ion
== ®ion_pal
) SNES::config
.region
= SNES::System::Region::PAL
;
986 void core_serialize(std::vector
<char>& out
)
989 throw std::runtime_error("No ROM loaded");
990 serializer s
= SNES::system
.serialize();
991 out
.resize(s
.size());
992 memcpy(&out
[0], s
.data(), s
.size());
995 void core_unserialize(const char* in
, size_t insize
)
998 throw std::runtime_error("No ROM loaded");
999 serializer
s(reinterpret_cast<const uint8_t*>(in
), insize
);
1000 if(!SNES::system
.unserialize(s
))
1001 throw std::runtime_error("SNES core rejected savestate");
1002 have_saved_this_frame
= true;
1005 std::pair
<bool, uint32_t> core_emulate_cycles(uint32_t cycles
)
1008 return std::make_pair(false, 0);
1009 #ifdef BSNES_HAS_DEBUGGER
1010 messages
<< "Executing delayed reset... This can take some time!" << std::endl
;
1011 video_refresh_done
= false;
1012 delayreset_cycles_run
= 0;
1013 delayreset_cycles_target
= cycles
;
1014 SNES::cpu
.step_event
= delayreset_fn
;
1016 SNES::cpu
.step_event
= nall::function
<bool()>();
1017 return std::make_pair(!video_refresh_done
, delayreset_cycles_run
);
1018 have_saved_this_frame
= true;
1020 messages
<< "Delayresets not supported on this bsnes version (needs v084 or v085)"
1022 return std::make_pair(false, 0);
1026 void core_emulate_frame()
1028 static unsigned frame_modulus
= 0;
1031 framebuffer_info inf
;
1032 inf
.type
= &_pixel_format_lrgb
;
1033 inf
.mem
= const_cast<char*>(reinterpret_cast<const char*>(norom_frame
));
1034 inf
.physwidth
= 512;
1035 inf
.physheight
= 448;
1036 inf
.physstride
= 2048;
1043 framebuffer_raw
ls(inf
);
1044 ecore_callbacks
->output_frame(ls
, 60, 1);
1046 audioapi_submit_buffer(blanksound
, frame_modulus
? 534 : 535, true, 32040.5);
1047 for(unsigned i
= 0; i
< 534; i
++)
1048 information_dispatch::do_sample(0, 0);
1050 information_dispatch::do_sample(0, 0);
1052 frame_modulus
%= 120;
1053 ecore_callbacks
->timer_tick(1, 60);
1056 if(!have_saved_this_frame
&& save_every_frame
)
1057 SNES::system
.runtosave();
1059 have_saved_this_frame
= false;
1066 SNES::system
.reset();
1069 void core_runtosave()
1073 stepping_into_save
= true;
1074 if(!allow_inconsistent_saves
)
1075 SNES::system
.runtosave();
1076 have_saved_this_frame
= true;
1077 stepping_into_save
= false;
1080 std::list
<vma_info
> get_vma_list()
1082 std::list
<vma_info
> ret
;
1085 create_region(ret
, "WRAM", 0x007E0000, SNES::cpu
.wram
, 131072, false);
1086 create_region(ret
, "APURAM", 0x00000000, SNES::smp
.apuram
, 65536, false);
1087 create_region(ret
, "VRAM", 0x00010000, SNES::ppu
.vram
, 65536, false);
1088 create_region(ret
, "OAM", 0x00020000, SNES::ppu
.oam
, 544, false);
1089 create_region(ret
, "CGRAM", 0x00021000, SNES::ppu
.cgram
, 512, false);
1090 if(SNES::cartridge
.has_srtc()) create_region(ret
, "RTC", 0x00022000, SNES::srtc
.rtc
, 20, false);
1091 if(SNES::cartridge
.has_spc7110rtc()) create_region(ret
, "RTC", 0x00022000, SNES::spc7110
.rtc
, 20, false);
1092 if(SNES::cartridge
.has_necdsp()) {
1093 create_region(ret
, "DSPRAM", 0x00023000, reinterpret_cast<uint8_t*>(SNES::necdsp
.dataRAM
), 4096,
1095 create_region(ret
, "DSPPROM", 0xF0000000, reinterpret_cast<uint8_t*>(SNES::necdsp
.programROM
), 65536,
1097 create_region(ret
, "DSPDROM", 0xF0010000, reinterpret_cast<uint8_t*>(SNES::necdsp
.dataROM
), 4096,
1100 create_region(ret
, "SRAM", 0x10000000, SNES::cartridge
.ram
, false);
1101 create_region(ret
, "ROM", 0x80000000, SNES::cartridge
.rom
, true);
1102 create_region(ret
, "BUS", 0x1000000, 0x1000000, snes_bus_iospace_rw
);
1103 create_region(ret
, "PTRTABLE", 0x100000000, 0x100000, ptrtable_iospace_rw
);
1104 map_internal(ret
, "CPU_STATE", 0, &SNES::cpu
, sizeof(SNES::cpu
));
1105 map_internal(ret
, "PPU_STATE", 1, &SNES::ppu
, sizeof(SNES::ppu
));
1106 map_internal(ret
, "SMP_STATE", 2, &SNES::smp
, sizeof(SNES::smp
));
1107 map_internal(ret
, "DSP_STATE", 3, &SNES::dsp
, sizeof(SNES::dsp
));
1108 if(internal_rom
== &type_bsx
|| internal_rom
== &type_bsxslotted
) {
1109 create_region(ret
, "BSXFLASH", 0x90000000, SNES::bsxflash
.memory
, true);
1110 create_region(ret
, "BSX_RAM", 0x20000000, SNES::bsxcartridge
.sram
, false);
1111 create_region(ret
, "BSX_PRAM", 0x30000000, SNES::bsxcartridge
.psram
, false);
1113 if(internal_rom
== &type_sufamiturbo
) {
1114 create_region(ret
, "SLOTA_ROM", 0x90000000, SNES::sufamiturbo
.slotA
.rom
, true);
1115 create_region(ret
, "SLOTB_ROM", 0xA0000000, SNES::sufamiturbo
.slotB
.rom
, true);
1116 create_region(ret
, "SLOTA_RAM", 0x20000000, SNES::sufamiturbo
.slotA
.ram
, false);
1117 create_region(ret
, "SLOTB_RAM", 0x30000000, SNES::sufamiturbo
.slotB
.ram
, false);
1119 if(internal_rom
== &type_sgb
) {
1120 create_region(ret
, "GBROM", 0x90000000, GameBoy::cartridge
.romdata
, GameBoy::cartridge
.romsize
, true);
1121 create_region(ret
, "GBRAM", 0x20000000, GameBoy::cartridge
.ramdata
, GameBoy::cartridge
.ramsize
, false);
1126 std::pair
<uint32_t, uint32_t> get_scale_factors(uint32_t width
, uint32_t height
)
1128 uint32_t h
= 1, v
= 1;
1133 return std::make_pair(h
, v
);
1136 unsigned core_get_poll_flag()
1138 return pollflag_active
? (SNES::cpu
.controller_flag
? 1 : 0) : 2;
1141 void core_set_poll_flag(unsigned pflag
)
1143 SNES::cpu
.controller_flag
= (pflag
!= 0);
1144 pollflag_active
= (pflag
< 2);
1147 emucore_callbacks::~emucore_callbacks() throw()
1151 std::pair
<uint64_t, uint64_t> core_get_bus_map()
1153 return std::make_pair(0x1000000, 0x1000000);
1156 function_ptr_command
<arg_filename
> dump_core("dump-core", "No description available",
1157 "No description available\n",
1158 [](arg_filename args
) throw(std::bad_alloc
, std::runtime_error
) {
1159 std::vector
<char> out
;
1160 core_serialize(out
);
1161 std::ofstream
x(args
, std::ios_base::out
| std::ios_base::binary
);
1162 x
.write(&out
[0], out
.size());
1166 struct emucore_callbacks
* ecore_callbacks
;