9 #include "core/audioapi.hpp"
10 #include "core/misc.hpp"
11 #include "core/emucore.hpp"
12 #include "core/command.hpp"
13 #include "core/controllerframe.hpp"
14 #include "core/dispatch.hpp"
15 #include "core/framebuffer.hpp"
16 #include "core/settings.hpp"
17 #include "core/window.hpp"
18 #include "interface/setting.hpp"
19 #include "library/pixfmt-lrgb.hpp"
20 #include "library/string.hpp"
21 #include "library/portfn.hpp"
22 #include "library/framebuffer.hpp"
23 #include "library/luabase.hpp"
24 #include "lua/internal.hpp"
25 #include <snes/snes.hpp>
26 #include <gameboy/gameboy.hpp>
28 #include <target-libsnes/libsnes.hpp>
30 #include <ui-libsnes/libsnes.hpp>
33 #define DURATION_NTSC_FRAME 357366
34 #define DURATION_NTSC_FIELD 357368
35 #define DURATION_PAL_FRAME 425568
36 #define DURATION_PAL_FIELD 425568
37 #define ROM_TYPE_NONE 0
38 #define ROM_TYPE_SNES 1
39 #define ROM_TYPE_BSX 2
40 #define ROM_TYPE_BSXSLOTTED 3
41 #define ROM_TYPE_SUFAMITURBO 4
42 #define ROM_TYPE_SGB 5
44 void snesdbg_on_break();
45 void snesdbg_on_trace();
49 bool p1disable
= false;
50 long do_reset_flag
= -1;
51 bool pollflag_active
= true;
52 boolean_setting
allow_inconsistent_saves(lsnes_set
, "allow-inconsistent-saves", false);
53 boolean_setting
save_every_frame(lsnes_set
, "save-every-frame", false);
54 uint32_t norom_frame
[512 * 448];
55 bool have_saved_this_frame
= false;
56 int16_t blanksound
[1070] = {0};
57 int16_t soundbuf
[8192] = {0};
58 size_t soundbuf_fill
= 0;
59 bool last_hires
= false;
60 bool last_interlace
= false;
61 uint64_t trace_counter
;
62 std::ofstream trace_output
;
63 bool trace_output_enable
;
66 core_setting_group bsnes_settings
;
67 core_setting
setting_port1(bsnes_settings
, "port1", "Port 1 Type", "gamepad");
68 core_setting
setting_port2(bsnes_settings
, "port2", "Port 2 Type", "none");
71 /////////////////// SYSTEM CONTROLLER ///////////////////
72 const char* system_name
= "(system)";
73 port_controller_button
* system_button_info
[] = {};
74 port_controller system_controller
= {"(system)", "system", 0, system_button_info
};
76 ////////////////// NONE CONTROLLER ///////////////////
77 const char* none_buttons
= "";
79 ////////////////// GAMEPAD(16) CONTROLLER ///////////////////
80 const char* gamepad_buttons
= "BYsSudlrAXLR0123";
81 port_controller_button gamepad_btn_B
= {port_controller_button::TYPE_BUTTON
, "B"};
82 port_controller_button gamepad_btn_Y
= {port_controller_button::TYPE_BUTTON
, "Y"};
83 port_controller_button gamepad_btn_s
= {port_controller_button::TYPE_BUTTON
, "select"};
84 port_controller_button gamepad_btn_S
= {port_controller_button::TYPE_BUTTON
, "start"};
85 port_controller_button gamepad_btn_u
= {port_controller_button::TYPE_BUTTON
, "up"};
86 port_controller_button gamepad_btn_d
= {port_controller_button::TYPE_BUTTON
, "down"};
87 port_controller_button gamepad_btn_l
= {port_controller_button::TYPE_BUTTON
, "left"};
88 port_controller_button gamepad_btn_r
= {port_controller_button::TYPE_BUTTON
, "right"};
89 port_controller_button gamepad_btn_A
= {port_controller_button::TYPE_BUTTON
, "A"};
90 port_controller_button gamepad_btn_X
= {port_controller_button::TYPE_BUTTON
, "X"};
91 port_controller_button gamepad_btn_L
= {port_controller_button::TYPE_BUTTON
, "L"};
92 port_controller_button gamepad_btn_R
= {port_controller_button::TYPE_BUTTON
, "R"};
93 port_controller_button gamepad_btn_0
= {port_controller_button::TYPE_BUTTON
, "ext0"};
94 port_controller_button gamepad_btn_1
= {port_controller_button::TYPE_BUTTON
, "ext1"};
95 port_controller_button gamepad_btn_2
= {port_controller_button::TYPE_BUTTON
, "ext2"};
96 port_controller_button gamepad_btn_3
= {port_controller_button::TYPE_BUTTON
, "ext3"};
97 port_controller_button
* gamepad_button_info
[] = {
98 &gamepad_btn_B
, &gamepad_btn_Y
, &gamepad_btn_s
, &gamepad_btn_S
,
99 &gamepad_btn_u
, &gamepad_btn_d
, &gamepad_btn_l
, &gamepad_btn_r
,
100 &gamepad_btn_A
, &gamepad_btn_X
, &gamepad_btn_L
, &gamepad_btn_R
,
101 &gamepad_btn_0
, &gamepad_btn_1
, &gamepad_btn_2
, &gamepad_btn_3
103 port_controller gamepad_controller
= {"gamepad", "gamepad", 12, gamepad_button_info
};
104 port_controller gamepad16_controller
= {"gamepad", "gamepad16", 16, gamepad_button_info
};
106 ////////////////// MOUSE CONTROLLER ///////////////////
107 const char* mouse_buttons
= "LR";
108 port_controller_button mouse_axis_x
= {port_controller_button::TYPE_RAXIS
, "xaxis"};
109 port_controller_button mouse_axis_y
= {port_controller_button::TYPE_RAXIS
, "yaxis"};
110 port_controller_button mouse_btn_L
= {port_controller_button::TYPE_BUTTON
, "L"};
111 port_controller_button mouse_btn_R
= {port_controller_button::TYPE_BUTTON
, "R"};
112 port_controller_button
* mouse_button_info
[] = {
113 &mouse_axis_x
, &mouse_axis_y
, &mouse_btn_L
, &mouse_btn_R
115 port_controller mouse_controller
= {"mouse", "mouse", 4, mouse_button_info
};
117 ////////////////// SUPERSCOPE CONTROLLER ///////////////////
118 const char* superscope_buttons
= "TCUP";
119 port_controller_button superscope_axis_x
= {port_controller_button::TYPE_AXIS
, "xaxis"};
120 port_controller_button superscope_axis_y
= {port_controller_button::TYPE_AXIS
, "yaxis"};
121 port_controller_button superscope_btn_T
= {port_controller_button::TYPE_BUTTON
, "trigger"};
122 port_controller_button superscope_btn_C
= {port_controller_button::TYPE_BUTTON
, "cursor"};
123 port_controller_button superscope_btn_U
= {port_controller_button::TYPE_BUTTON
, "turbo"};
124 port_controller_button superscope_btn_P
= {port_controller_button::TYPE_BUTTON
, "Pause"};
125 port_controller_button
* superscope_button_info
[] = {
126 &superscope_axis_x
, &superscope_axis_y
, &superscope_btn_T
, &superscope_btn_C
, &superscope_btn_U
,
129 port_controller superscope_controller
= {"superscope", "superscope", 6, superscope_button_info
};
131 ////////////////// JUSTIFIER CONTROLLER ///////////////////
132 const char* justifier_buttons
= "TS";
133 port_controller_button justifier_axis_x
= {port_controller_button::TYPE_AXIS
, "xaxis"};
134 port_controller_button justifier_axis_y
= {port_controller_button::TYPE_AXIS
, "yaxis"};
135 port_controller_button justifier_btn_T
= {port_controller_button::TYPE_BUTTON
, "trigger"};
136 port_controller_button justifier_btn_S
= {port_controller_button::TYPE_BUTTON
, "start"};
137 port_controller_button
* justifier_button_info
[] = {
138 &justifier_axis_x
, &justifier_axis_y
, &justifier_btn_T
, &gamepad_btn_S
140 port_controller justifier_controller
= {"justifier", "justifier", 4, justifier_button_info
};
142 ////////////////// SYSTEM PORT ///////////////////
143 port_controller
* system_controllers
[] = {&system_controller
};
144 port_controller_set system_port
= {1, system_controllers
};
146 struct porttype_system
: public port_type
148 porttype_system() : port_type("<SYSTEM>", "<SYSTEM>", 9999, 5)
150 write
= [](unsigned char* buffer
, unsigned idx
, unsigned ctrl
, short x
) -> void {
155 buffer
[0] |= (1 << ctrl
);
157 buffer
[0] &= ~(1 << ctrl
);
159 buffer
[2 * ctrl
- 3] = x
>> 8;
160 buffer
[2 * ctrl
- 2] = x
;
163 read
= [](const unsigned char* buffer
, unsigned idx
, unsigned ctrl
) -> short {
167 return (buffer
[0] >> ctrl
) ? 1 : 0;
169 return unserialize_short(buffer
+ 2 * ctrl
- 3);
172 display
= [](const unsigned char* buffer
, unsigned idx
, char* buf
) -> void {
173 char x1
= ((buffer
[0] & 1) ? 'F' : '-');
174 char x2
= ((buffer
[0] & 2) ? 'R' : '-');
178 sprintf(buf
, "%c%c %i %i", x1
, x2
, unserialize_short(buffer
+ 1),
179 unserialize_short(buffer
+ 3));
181 serialize
= [](const unsigned char* buffer
, char* textbuf
) -> size_t {
182 char x1
= ((buffer
[0] & 1) ? 'F' : '.');
183 char x2
= ((buffer
[0] & 2) ? 'R' : '.');
185 if(buffer
[1] || buffer
[2] || buffer
[3] || buffer
[4])
186 sprintf(tmp
, "%c%c %i %i", x1
, x2
, unserialize_short(buffer
+ 1),
187 unserialize_short(buffer
+ 3));
189 sprintf(tmp
, "%c%c", x1
, x2
);
190 size_t len
= strlen(tmp
);
191 memcpy(textbuf
, tmp
, len
);
194 deserialize
= [](unsigned char* buffer
, const char* textbuf
) -> size_t {
195 memset(buffer
, 0, 5);
197 if(read_button_value(textbuf
, ptr
))
199 if(read_button_value(textbuf
, ptr
))
201 short v
= read_axis_value(textbuf
, ptr
);
204 v
= read_axis_value(textbuf
, ptr
);
207 skip_rest_of_field(textbuf
, ptr
, false);
210 legal
= generic_port_legal
<1>;
211 controller_info
= &system_port
;
212 used_indices
= generic_used_indices
<1, 4>;
216 ////////////////// NONE PORT ///////////////////
217 port_controller
* none_controllers
[] = {};
218 port_controller_set none_port
= {0, none_controllers
};
220 struct porttype_none
: public port_type
222 porttype_none() : port_type("none", "None", 0, generic_port_size
<0, 0, 0>())
224 write
= generic_port_write
<0, 0, 0>;
225 read
= generic_port_read
<0, 0, 0>;
226 display
= generic_port_display
<0, 0, 0, &none_buttons
>;
227 serialize
= generic_port_serialize
<0, 0, 0, &none_buttons
>;
228 deserialize
= generic_port_deserialize
<0, 0, 0>;
229 legal
= generic_port_legal
<6>;
230 controller_info
= &none_port
;
231 used_indices
= generic_used_indices
<0, 0>;
235 core_setting_value
setting_port1_none(setting_port1
, "none", "None", 0);
236 core_setting_value
setting_port2_none(setting_port2
, "none", "None", 0);
238 ////////////////// GAMEPAD(16) PORT ///////////////////
239 port_controller
* gamepad_controllers
[] = {&gamepad_controller
};
240 port_controller
* gamepad16_controllers
[] = {&gamepad16_controller
};
241 port_controller_set gamepad_port
= {1, gamepad_controllers
};
242 port_controller_set gamepad16_port
= {1, gamepad16_controllers
};
244 struct porttype_gamepad
: public port_type
246 porttype_gamepad() : port_type("gamepad", "Gamepad", 1, generic_port_size
<1, 0, 12>())
248 write
= generic_port_write
<1, 0, 12>;
249 read
= generic_port_read
<1, 0, 12>;
250 display
= generic_port_display
<1, 0, 12, &gamepad_buttons
>;
251 serialize
= generic_port_serialize
<1, 0, 12, &gamepad_buttons
>;
252 deserialize
= generic_port_deserialize
<1, 0, 12>;
253 legal
= generic_port_legal
<6>;
254 controller_info
= &gamepad_port
;
255 used_indices
= generic_used_indices
<1, 12>;
259 struct porttype_gamepad16
: public port_type
261 porttype_gamepad16() : port_type("gamepad16", "Gamepad (16-button)", 1,
262 generic_port_size
<1, 0, 16>())
264 write
= generic_port_write
<1, 0, 16>;
265 read
= generic_port_read
<1, 0, 16>;
266 display
= generic_port_display
<1, 0, 16, &gamepad_buttons
>;
267 serialize
= generic_port_serialize
<1, 0, 16, &gamepad_buttons
>;
268 deserialize
= generic_port_deserialize
<1, 0, 16>;
269 legal
= generic_port_legal
<6>;
270 controller_info
= &gamepad16_port
;
271 used_indices
= generic_used_indices
<1, 16>;
275 core_setting_value
setting_port2_gamepad(setting_port2
, "gamepad", "Gamepad", 1);
276 core_setting_value
setting_port1_gamepad(setting_port1
, "gamepad", "Gamepad", 1);
277 core_setting_value
setting_port1_gamepad16(setting_port1
, "gamepad16", "Gamepad (16-button)", 2);
278 core_setting_value
setting_port2_gamepad16(setting_port2
, "gamepad16", "Gamepad (16-button)", 2);
280 ////////////////// MULTITAP(16) PORT ///////////////////
281 port_controller
* multitap_controllers
[] = {
282 &gamepad_controller
, &gamepad_controller
, &gamepad_controller
, &gamepad_controller
284 port_controller
* multitap16_controllers
[] = {
285 &gamepad16_controller
, &gamepad16_controller
, &gamepad16_controller
, &gamepad16_controller
287 port_controller_set multitap_port
= {4, multitap_controllers
};
288 port_controller_set multitap16_port
= {4, multitap16_controllers
};
290 struct porttype_multitap
: public port_type
292 porttype_multitap() : port_type("multitap", "Multitap", 2,
293 generic_port_size
<4, 0, 12>())
295 write
= generic_port_write
<4, 0, 12>;
296 read
= generic_port_read
<4, 0, 12>;
297 display
= generic_port_display
<4, 0, 12, &gamepad_buttons
>;
298 serialize
= generic_port_serialize
<4, 0, 12, &gamepad_buttons
>;
299 deserialize
= generic_port_deserialize
<4, 0, 12>;
300 legal
= generic_port_legal
<6>;
301 controller_info
= &multitap_port
;
302 used_indices
= generic_used_indices
<4, 12>;
306 struct porttype_multitap16
: public port_type
308 porttype_multitap16() : port_type("multitap16", "Multitap (16-button)", 2,
309 generic_port_size
<4, 0, 16>())
311 write
= generic_port_write
<4, 0, 16>;
312 read
= generic_port_read
<4, 0, 16>;
313 display
= generic_port_display
<4, 0, 16, &gamepad_buttons
>;
314 serialize
= generic_port_serialize
<4, 0, 16, &gamepad_buttons
>;
315 deserialize
= generic_port_deserialize
<4, 0, 16>;
316 legal
= generic_port_legal
<6>;
317 controller_info
= &multitap16_port
;
318 used_indices
= generic_used_indices
<4, 16>;
322 core_setting_value
setting_port2_multitap(setting_port2
, "multitap", "Multitap", 3);
323 core_setting_value
setting_port1_multitap(setting_port1
, "multitap", "Multitap", 3);
324 core_setting_value
setting_port2_multitap16(setting_port2
, "multitap16", "Multitap (16-button)", 4);
325 core_setting_value
setting_port1_multitap16(setting_port1
, "multitap16", "Multitap (16-button)", 4);
327 ////////////////// MOUSE PORT ///////////////////
328 port_controller
* mouse_controllers
[] = {&mouse_controller
};
329 port_controller_set mouse_port
= {1, mouse_controllers
};
331 struct porttype_mouse
: public port_type
333 porttype_mouse() : port_type("mouse", "Mouse", 3, generic_port_size
<1, 2, 2>())
335 write
= generic_port_write
<1, 2, 2>;
336 read
= generic_port_read
<1, 2, 2>;
337 display
= generic_port_display
<1, 2, 2, &mouse_buttons
>;
338 serialize
= generic_port_serialize
<1, 2, 2, &mouse_buttons
>;
339 deserialize
= generic_port_deserialize
<1, 2, 2>;
340 legal
= generic_port_legal
<6>;
341 controller_info
= &mouse_port
;
342 used_indices
= generic_used_indices
<1, 4>;
346 core_setting_value
setting_port2_mouse(setting_port2
, "mouse", "Mouse", 5);
347 core_setting_value
setting_port1_mouse(setting_port1
, "mouse", "Mouse", 5);
349 ////////////////// SUPERSCOPE PORT ///////////////////
350 port_controller
* superscope_controllers
[] = {&superscope_controller
};
351 port_controller_set superscope_port
= {1, superscope_controllers
};
353 struct porttype_superscope
: public port_type
355 porttype_superscope() : port_type("superscope", "Super Scope", 4,
356 generic_port_size
<1, 2, 4>())
358 write
= generic_port_write
<1, 2, 4>;
359 read
= generic_port_read
<1, 2, 4>;
360 display
= generic_port_display
<1, 2, 4, &superscope_buttons
>;
361 serialize
= generic_port_serialize
<1, 2, 4, &superscope_buttons
>;
362 deserialize
= generic_port_deserialize
<1, 2, 4>;
363 legal
= generic_port_legal
<4>;
364 controller_info
= &superscope_port
;
365 used_indices
= generic_used_indices
<1, 6>;
369 core_setting_value
setting_port2_superscope(setting_port2
, "superscope", "Super Scope", 8);
371 ////////////////// JUSTIFIER PORT ///////////////////
372 port_controller
* justifier_controllers
[] = {&justifier_controller
};
373 port_controller_set justifier_port
= {1, justifier_controllers
};
375 struct porttype_justifier
: public port_type
377 porttype_justifier() : port_type("justifier", "Justifier", 5,
378 generic_port_size
<1, 2, 2>())
380 write
= generic_port_write
<1, 2, 2>;
381 read
= generic_port_read
<1, 2, 2>;
382 display
= generic_port_display
<1, 2, 2, &justifier_buttons
>;
383 serialize
= generic_port_serialize
<1, 2, 2, &justifier_buttons
>;
384 deserialize
= generic_port_deserialize
<1, 2, 2>;
385 legal
= generic_port_legal
<4>;
386 controller_info
= &justifier_port
;
387 used_indices
= generic_used_indices
<1, 4>;
391 core_setting_value
setting_port2_justifier(setting_port2
, "justifier", "Justifier", 6);
393 ////////////////// JUSTIFIERS PORT ///////////////////
394 port_controller
* justifiers_controllers
[] = {&justifier_controller
, &justifier_controller
};
395 port_controller_set justifiers_port
= {2, justifiers_controllers
};
397 struct porttype_justifiers
: public port_type
399 porttype_justifiers() : port_type("justifiers", "2 Justifiers", 6,
400 generic_port_size
<2, 2, 2>())
402 write
= generic_port_write
<2, 2, 2>;
403 read
= generic_port_read
<2, 2, 2>;
404 display
= generic_port_display
<2, 2, 2, &justifier_buttons
>;
405 serialize
= generic_port_serialize
<2, 2, 2, &justifier_buttons
>;
406 deserialize
= generic_port_deserialize
<2, 2, 2>;
407 legal
= generic_port_legal
<4>;
408 controller_info
= &justifiers_port
;
409 used_indices
= generic_used_indices
<2, 4>;
413 core_setting_value
setting_port2_justifiers(setting_port2
, "justifiers", "2 Justifiers", 7);
415 ////////////////// PORTS COMMON ///////////////////
416 port_type
* index_to_ptype
[] = {
417 &none
, &gamepad
, &gamepad16
, &multitap
, &multitap16
, &mouse
, &justifier
, &justifiers
, &superscope
419 unsigned index_to_bsnes_type
[] = {
420 SNES_DEVICE_NONE
, SNES_DEVICE_JOYPAD
, SNES_DEVICE_JOYPAD
, SNES_DEVICE_MULTITAP
, SNES_DEVICE_MULTITAP
,
421 SNES_DEVICE_MOUSE
, SNES_DEVICE_JUSTIFIER
, SNES_DEVICE_JUSTIFIERS
, SNES_DEVICE_SUPER_SCOPE
431 class my_interfaced
: public SNES::Interface
433 string
path(SNES::Cartridge::Slot slot
, const string
&hint
)
441 static bool done
= false;
445 static my_interfaced i
;
446 SNES::interface
= &i
;
449 void init_norom_frame()
451 static bool done
= false;
455 for(size_t i
= 0; i
< 512 * 448; i
++)
456 norom_frame
[i
] = 0x7C21F;
459 core_type
* internal_rom
= NULL
;
460 extern core_type type_snes
;
461 extern core_type type_bsx
;
462 extern core_type type_bsxslotted
;
463 extern core_type type_sufamiturbo
;
464 extern core_type type_sgb
;
466 template<bool(*T
)(const char*,const unsigned char*, unsigned)>
467 bool load_rom_X1(core_romimage
* img
)
469 return T(img
[0].markup
, img
[0].data
, img
[0].size
);
472 template<bool(*T
)(const char*,const unsigned char*, unsigned, const char*,const unsigned char*, unsigned)>
473 bool load_rom_X2(core_romimage
* img
)
475 return T(img
[0].markup
, img
[0].data
, img
[0].size
,
476 img
[1].markup
, img
[1].data
, img
[1].size
);
479 template<bool(*T
)(const char*,const unsigned char*, unsigned, const char*,const unsigned char*, unsigned,
480 const char*,const unsigned char*, unsigned)>
481 bool load_rom_X3(core_romimage
* img
)
483 return T(img
[0].markup
, img
[0].data
, img
[0].size
,
484 img
[1].markup
, img
[1].data
, img
[1].size
,
485 img
[2].markup
, img
[2].data
, img
[2].size
);
489 template<core_type
* ctype
>
490 int load_rom(core_romimage
* img
, std::map
<std::string
, std::string
>& settings
, uint64_t secs
,
491 uint64_t subsecs
, bool(*fun
)(core_romimage
*))
493 std::map
<std::string
, std::string
> _settings
= settings
;
494 bsnes_settings
.fill_defaults(_settings
);
495 signed type1
= setting_port1
.ivalue_to_index(_settings
[setting_port1
.iname
]);
496 signed type2
= setting_port2
.ivalue_to_index(_settings
[setting_port2
.iname
]);
500 snes_unload_cartridge();
501 SNES::config
.random
= false;
502 SNES::config
.expansion_port
= SNES::System::ExpansionPortDevice::None
;
505 internal_rom
= ctype
;
506 snes_set_controller_port_device(false, index_to_bsnes_type
[type1
]);
507 snes_set_controller_port_device(true, index_to_bsnes_type
[type2
]);
508 have_saved_this_frame
= false;
513 std::pair
<uint64_t, uint64_t> bsnes_get_bus_map()
515 return std::make_pair(0x1000000, 0x1000000);
518 port_index_triple
t(unsigned p
, unsigned c
, unsigned i
, bool nl
)
528 void push_port_indices(std::vector
<port_index_triple
>& tab
, unsigned p
, port_type
& pt
)
530 unsigned ctrls
= pt
.controller_info
->controller_count
;
531 for(unsigned i
= 0; i
< ctrls
; i
++)
532 for(unsigned j
= 0; j
< pt
.controller_info
->controllers
[i
]->button_count
; j
++)
533 tab
.push_back(t(p
, i
, j
, true));
536 controller_set
_controllerconfig(std::map
<std::string
, std::string
>& settings
)
538 std::map
<std::string
, std::string
> _settings
= settings
;
539 bsnes_settings
.fill_defaults(_settings
);
540 signed type1
= setting_port1
.ivalue_to_index(_settings
[setting_port1
.iname
]);
541 signed type2
= setting_port2
.ivalue_to_index(_settings
[setting_port2
.iname
]);
543 r
.ports
.push_back(&psystem
);
544 r
.ports
.push_back(index_to_ptype
[type1
]);
545 r
.ports
.push_back(index_to_ptype
[type2
]);
546 unsigned p1controllers
= r
.ports
[1]->controller_info
->controller_count
;
547 unsigned p2controllers
= r
.ports
[2]->controller_info
->controller_count
;
548 for(unsigned i
= 0; i
< 4; i
++)
549 r
.portindex
.indices
.push_back(t(0, 0, i
, false));
550 push_port_indices(r
.portindex
.indices
, 1, *r
.ports
[1]);
551 push_port_indices(r
.portindex
.indices
, 2, *r
.ports
[2]);
552 r
.portindex
.logical_map
.resize(p1controllers
+ p2controllers
);
553 if(p1controllers
== 4) {
554 r
.portindex
.logical_map
[0] = std::make_pair(1, 0);
555 for(size_t j
= 0; j
< p2controllers
; j
++)
556 r
.portindex
.logical_map
[j
+ 1] = std::make_pair(2U, j
);
557 for(size_t j
= 1; j
< p1controllers
; j
++)
558 r
.portindex
.logical_map
[j
+ p2controllers
] = std::make_pair(1U, j
);
560 for(size_t j
= 0; j
< p1controllers
; j
++)
561 r
.portindex
.logical_map
[j
] = std::make_pair(1, j
);
562 for(size_t j
= 0; j
< p2controllers
; j
++)
563 r
.portindex
.logical_map
[j
+ p1controllers
] = std::make_pair(2U, j
);
565 for(unsigned i
= 0; i
< 8; i
++)
566 r
.portindex
.pcid_map
.push_back(std::make_pair(i
/ 4 + 1, i
% 4));
570 unsigned auto_compatible
[] = {0, 1, 2, UINT_MAX
};
571 unsigned ntsc_compatible
[] = {1, UINT_MAX
};
572 unsigned pal_compatible
[] = {2, UINT_MAX
};
573 struct core_region_params _region_auto
= {
574 "autodetect", "Autodetect", 1, 0, true, {178683, 10738636, 16639264, 596096}, auto_compatible
576 struct core_region_params _region_ntsc
= {
577 "ntsc", "NTSC", 0, 1, false, {178683, 10738636, 16639264, 596096}, ntsc_compatible
579 struct core_region_params _region_pal
= {
580 "pal", "PAL", 0, 2, false, {6448, 322445, 19997208, 266440}, pal_compatible
582 struct core_romimage_info_params _image_snescart
= {
583 "rom", "Cartridge ROM", 1, 0, 512
585 struct core_romimage_info_params _image_bsxbios
= {
586 "rom", "BS-X BIOS", 1, 0, 512
588 struct core_romimage_info_params _image_bsxflash
= {
589 "bsx", "BS-X Flash", 2, 0, 512
591 struct core_romimage_info_params _image_bsxsflash
= {
592 "bsx", "BS-X Flash", 2, 0, 512
594 struct core_romimage_info_params _image_sgbbios
= {
595 "rom", "SGB BIOS", 1, 0, 512
597 struct core_romimage_info_params _image_dmg
= {
598 "dmg", "DMG ROM", 2, 0, 512
600 struct core_romimage_info_params _image_stbios
= {
601 "rom", "ST BIOS", 1, 0, 512
603 struct core_romimage_info_params _image_stslota
= {
604 "slot-a", "ST SLOT A ROM", 2, 0, 512
606 struct core_romimage_info_params _image_stslotb
= {
607 "slot-b", "ST SLOT B ROM", 2, 0, 512
610 core_region
region_auto(_region_auto
);
611 core_region
region_ntsc(_region_ntsc
);
612 core_region
region_pal(_region_pal
);
613 core_region
* _all_regions
[] = {®ion_auto
, ®ion_ntsc
, ®ion_pal
, NULL
};
614 core_region
* _ntsconly
[] = {®ion_ntsc
, NULL
};
615 core_romimage_info
image_snescart(_image_snescart
);
616 core_romimage_info
image_bsxbios(_image_bsxbios
);
617 core_romimage_info
image_bsxflash(_image_bsxflash
);
618 core_romimage_info
image_bsxsflash(_image_bsxsflash
);
619 core_romimage_info
image_sgbbios(_image_sgbbios
);
620 core_romimage_info
image_dmg(_image_dmg
);
621 core_romimage_info
image_stbios(_image_stbios
);
622 core_romimage_info
image_stslota(_image_stslota
);
623 core_romimage_info
image_stslotb(_image_stslotb
);
624 core_romimage_info
* snes_images
[] = {&image_snescart
, NULL
};
625 core_romimage_info
* bsx_images
[] = {&image_bsxbios
, &image_bsxflash
, NULL
};
626 core_romimage_info
* bsxs_images
[] = {&image_bsxbios
, &image_bsxsflash
, NULL
};
627 core_romimage_info
* sgb_images
[] = {&image_sgbbios
, &image_dmg
, NULL
};
628 core_romimage_info
* st_images
[] = {&image_stbios
, &image_stslota
, &image_stslotb
, NULL
};
630 #ifdef BSNES_HAS_DEBUGGER
631 #define BSNES_RESET_LEVEL 2
633 #define BSNES_RESET_LEVEL 1
636 std::string
sram_name(const nall::string
& _id
, SNES::Cartridge::Slot slotname
)
638 std::string
id(_id
, _id
.length());
639 //Fixup name change by bsnes v087...
642 if(id
== "bsx.psram")
644 if(id
== "program.rtc")
646 if(id
== "upd96050.ram")
648 if(id
== "program.ram")
650 if(slotname
== SNES::Cartridge::Slot::SufamiTurboA
)
651 return "slota." + id
.substr(1);
652 if(slotname
== SNES::Cartridge::Slot::SufamiTurboB
)
653 return "slotb." + id
.substr(1);
657 core_core_params _bsnes_core
= {
659 []() -> std::string
{
660 return (stringfmt() << snes_library_id() << " (" << SNES::Info::Profile
<< " core)").str();
663 [](core_region
& region
) -> bool {
664 if(®ion
== ®ion_auto
)
665 SNES::config
.region
= SNES::System::Region::Autodetect
;
666 else if(®ion
== ®ion_ntsc
)
667 SNES::config
.region
= SNES::System::Region::NTSC
;
668 else if(®ion
== ®ion_pal
)
669 SNES::config
.region
= SNES::System::Region::PAL
;
675 []() -> std::pair
<uint32_t, uint32_t> {
677 return std::make_pair(60, 1);
679 if(SNES::system
.region() == SNES::System::Region::PAL
)
680 div
= last_interlace
? DURATION_PAL_FIELD
: DURATION_PAL_FRAME
;
682 div
= last_interlace
? DURATION_NTSC_FIELD
: DURATION_NTSC_FRAME
;
683 return std::make_pair(SNES::system
.cpu_frequency(), div
);
686 []() -> std::pair
<uint32_t, uint32_t> {
688 return std::make_pair(64081, 2);
689 return std::make_pair(SNES::system
.apu_frequency(), static_cast<uint32_t>(768));
691 //Get SNES CPU/APU rate.
692 []() -> std::pair
<uint32_t, uint32_t> {
693 return std::make_pair(SNES::system
.cpu_frequency(), SNES::system
.apu_frequency());
696 []() -> std::map
<std::string
, std::vector
<char>> {
697 std::map
<std::string
, std::vector
<char>> out
;
700 for(unsigned i
= 0; i
< SNES::cartridge
.nvram
.size(); i
++) {
701 SNES::Cartridge::NonVolatileRAM
& r
= SNES::cartridge
.nvram
[i
];
702 std::string savename
= sram_name(r
.id
, r
.slot
);
705 memcpy(&x
[0], r
.data
, r
.size
);
711 [](std::map
<std::string
, std::vector
<char>>& sram
) -> void {
712 std::set
<std::string
> used
;
715 messages
<< "WARNING: SRAM '" << i
.first
<< ": Not found on cartridge."
721 for(unsigned i
= 0; i
< SNES::cartridge
.nvram
.size(); i
++) {
722 SNES::Cartridge::NonVolatileRAM
& r
= SNES::cartridge
.nvram
[i
];
723 std::string savename
= sram_name(r
.id
, r
.slot
);
724 if(sram
.count(savename
)) {
725 std::vector
<char>& x
= sram
[savename
];
726 if(r
.size
!= x
.size())
727 messages
<< "WARNING: SRAM '" << savename
<< "': Loaded " << x
.size()
728 << " bytes, but the SRAM is " << r
.size
<< "." << std::endl
;
729 memcpy(r
.data
, &x
[0], (r
.size
< x
.size()) ? r
.size
: x
.size());
730 used
.insert(savename
);
732 messages
<< "WARNING: SRAM '" << savename
<< ": No data." << std::endl
;
735 if(!used
.count(i
.first
))
736 messages
<< "WARNING: SRAM '" << i
.first
<< ": Not found on cartridge."
740 [](std::vector
<char>& out
) -> void {
742 throw std::runtime_error("No ROM loaded");
743 serializer s
= SNES::system
.serialize();
744 out
.resize(s
.size());
745 memcpy(&out
[0], s
.data(), s
.size());
748 [](const char* in
, size_t insize
) -> void {
750 throw std::runtime_error("No ROM loaded");
751 serializer
s(reinterpret_cast<const uint8_t*>(in
), insize
);
752 if(!SNES::system
.unserialize(s
))
753 throw std::runtime_error("SNES core rejected savestate");
754 have_saved_this_frame
= true;
758 []() -> core_region
& {
759 return (SNES::system
.region() == SNES::System::Region::PAL
) ? region_pal
: region_ntsc
;
763 if(internal_rom
) snes_power();
765 //Unload the cartridge.
767 if(!internal_rom
) return;
769 snes_unload_cartridge();
773 [](uint32_t width
, uint32_t height
) -> std::pair
<uint32_t, uint32_t> {
774 return std::make_pair((width
< 400) ? 2 : 1, (height
< 400) ? 2 : 1);
778 core_core
bsnes_core(_bsnes_core
);
780 core_type_params _type_snes
= {
781 "snes", "SNES", 0, BSNES_RESET_LEVEL
,
782 [](core_romimage
* img
, std::map
<std::string
, std::string
>& settings
, uint64_t secs
,
783 uint64_t subsecs
) -> int {
784 return load_rom
<&type_snes
>(img
, settings
, secs
, subsecs
,
785 load_rom_X1
<snes_load_cartridge_normal
>);
787 _controllerconfig
, "sfc;smc;swc;fig;ufo;sf2;gd3;gd7;dx2;mgd;mgh", NULL
, _all_regions
, snes_images
,
788 &bsnes_settings
, &bsnes_core
, bsnes_get_bus_map
790 core_type_params _type_bsx
= {
791 "bsx", "BS-X (non-slotted)", 1, BSNES_RESET_LEVEL
,
792 [](core_romimage
* img
, std::map
<std::string
, std::string
>& settings
, uint64_t secs
,
793 uint64_t subsecs
) -> int {
794 return load_rom
<&type_bsx
>(img
, settings
, secs
, subsecs
,
795 load_rom_X2
<snes_load_cartridge_bsx
>);
797 _controllerconfig
, "bs", "bsx.sfc", _ntsconly
, bsx_images
, &bsnes_settings
, &bsnes_core
,
800 core_type_params _type_bsxslotted
= {
801 "bsxslotted", "BS-X (slotted)", 2, BSNES_RESET_LEVEL
,
802 [](core_romimage
* img
, std::map
<std::string
, std::string
>& settings
,
803 uint64_t secs
, uint64_t subsecs
) -> int {
804 return load_rom
<&type_bsxslotted
>(img
, settings
, secs
, subsecs
,
805 load_rom_X2
<snes_load_cartridge_bsx_slotted
>);
807 _controllerconfig
, "bss", "bsxslotted.sfc", _ntsconly
, bsxs_images
, &bsnes_settings
, &bsnes_core
,
810 core_type_params _type_sufamiturbo
= {
811 "sufamiturbo", "Sufami Turbo", 3, BSNES_RESET_LEVEL
,
812 [](core_romimage
* img
, std::map
<std::string
, std::string
>& settings
, uint64_t secs
,
813 uint64_t subsecs
) -> int {
814 return load_rom
<&type_sufamiturbo
>(img
, settings
, secs
, subsecs
,
815 load_rom_X3
<snes_load_cartridge_sufami_turbo
>);
817 _controllerconfig
, "st", "sufamiturbo.sfc", _ntsconly
, bsxs_images
, &bsnes_settings
, &bsnes_core
,
820 core_type_params _type_sgb
= {
821 "sgb", "Super Game Boy", 4, BSNES_RESET_LEVEL
,
822 [](core_romimage
* img
, std::map
<std::string
, std::string
>& settings
, uint64_t secs
,
823 uint64_t subsecs
) -> int
825 return load_rom
<&type_sgb
>(img
, settings
, secs
, subsecs
,
826 load_rom_X2
<snes_load_cartridge_super_game_boy
>);
828 _controllerconfig
, "gb;dmg;sgb", "sgb.sfc", _all_regions
, sgb_images
, &bsnes_settings
, &bsnes_core
,
832 core_type
type_snes(_type_snes
);
833 core_type
type_bsx(_type_bsx
);
834 core_type
type_bsxslotted(_type_bsxslotted
);
835 core_type
type_sufamiturbo(_type_sufamiturbo
);
836 core_type
type_sgb(_type_sgb
);
837 core_sysregion
sr1("snes_ntsc", type_snes
, region_ntsc
);
838 core_sysregion
sr2("snes_pal", type_snes
, region_pal
);
839 core_sysregion
sr3("bsx", type_bsx
, region_ntsc
);
840 core_sysregion
sr4("bsxslotted", type_bsxslotted
, region_ntsc
);
841 core_sysregion
sr5("sufamiturbo", type_sufamiturbo
, region_ntsc
);
842 core_sysregion
sr6("sgb_ntsc", type_sgb
, region_ntsc
);
843 core_sysregion
sr7("sgb_pal", type_sgb
, region_pal
);
845 bool stepping_into_save
;
846 bool video_refresh_done
;
848 unsigned long long delayreset_cycles_run
;
849 unsigned long long delayreset_cycles_target
;
851 std::map
<int16_t, std::pair
<uint64_t, uint64_t>> ptrmap
;
853 uint8_t snes_bus_iospace_rw(uint64_t offset
, uint8_t data
, bool write
)
856 SNES::bus
.write(offset
, data
);
858 return SNES::bus
.read(offset
);
861 uint8_t ptrtable_iospace_rw(uint64_t offset
, uint8_t data
, bool write
)
863 uint16_t entry
= offset
>> 4;
864 if(!ptrmap
.count(entry
))
866 uint64_t val
= ((offset
& 15) < 8) ? ptrmap
[entry
].first
: ptrmap
[entry
].second
;
867 uint8_t byte
= offset
& 7;
868 //These things are always little-endian.
869 return (val
>> (8 * byte
));
872 void create_region(std::list
<vma_info
>& inf
, const std::string
& name
, uint64_t base
, uint64_t size
,
873 uint8_t (*iospace_rw
)(uint64_t offset
, uint8_t data
, bool write
)) throw(std::bad_alloc
)
882 i
.native_endian
= false;
883 i
.iospace_rw
= iospace_rw
;
887 void create_region(std::list
<vma_info
>& inf
, const std::string
& name
, uint64_t base
, uint8_t* memory
,
888 uint64_t size
, bool readonly
, bool native_endian
= false) throw(std::bad_alloc
)
896 i
.backing_ram
= memory
;
897 i
.readonly
= readonly
;
898 i
.native_endian
= native_endian
;
903 void create_region(std::list
<vma_info
>& inf
, const std::string
& name
, uint64_t base
,
904 SNES::MappedRAM
& memory
, bool readonly
, bool native_endian
= false) throw(std::bad_alloc
)
906 create_region(inf
, name
, base
, memory
.data(), memory
.size(), readonly
, native_endian
);
909 void map_internal(std::list
<vma_info
>& inf
, const std::string
& name
, uint16_t index
, void* memory
,
912 ptrmap
[index
] = std::make_pair(reinterpret_cast<uint64_t>(memory
), static_cast<uint64_t>(memsize
));
913 create_region(inf
, name
, 0x101000000 + index
* 0x1000000, reinterpret_cast<uint8_t*>(memory
),
914 memsize
, true, true);
919 return (trace_counter
|| !!trace_output_enable
);
922 bool forced_hook
= false;
926 if(trace_counter
&& !--trace_counter
) {
927 //Trace counter did transition 1->0. Call the hook.
930 if(trace_output_enable
) {
932 SNES::cpu
.disassemble_opcode(buffer
, SNES::cpu
.regs
.pc
);
933 trace_output
<< buffer
<< std::endl
;
938 void update_trace_hook_state()
942 #ifdef BSNES_HAS_DEBUGGER
944 SNES::cpu
.step_event
= nall::function
<bool()>();
946 SNES::cpu
.step_event
= trace_fn
;
952 trace_fn(); //Call this also.
953 if(delayreset_cycles_run
== delayreset_cycles_target
|| video_refresh_done
)
955 delayreset_cycles_run
++;
959 class my_interface
: public SNES::Interface
961 string
path(SNES::Cartridge::Slot slot
, const string
&hint
)
963 const char* _hint
= hint
;
964 std::string _hint2
= _hint
;
965 std::string fwp
= ecore_callbacks
->get_firmware_path();
967 std::string msubase
= ecore_callbacks
->get_base_path();
968 if(regex_match(".*\\.sfc", msubase
))
969 msubase
= msubase
.substr(0, msubase
.length() - 4);
971 if(_hint2
== "msu1.rom" || _hint2
== ".msu") {
973 std::string x
= msubase
+ ".msu";
974 messages
<< "MSU main data file: " << x
<< std::endl
;
977 if(r
= regex("(track)?(-([0-9])+\\.pcm)", _hint2
)) {
979 std::string x
= msubase
+ r
[2];
980 messages
<< "MSU track " << r
[3] << "': " << x
<< std::endl
;
983 std::string finalpath
= fwp
+ "/" + _hint2
;
984 return finalpath
.c_str();
989 return ecore_callbacks
->get_time();
994 return ecore_callbacks
->get_randomseed();
997 void videoRefresh(const uint32_t* data
, bool hires
, bool interlace
, bool overscan
)
1000 last_interlace
= interlace
;
1001 bool region
= (SNES::system
.region() == SNES::System::Region::PAL
);
1002 if(stepping_into_save
)
1003 messages
<< "Got video refresh in runtosave, expect desyncs!" << std::endl
;
1004 video_refresh_done
= true;
1005 uint32_t fps_n
, fps_d
;
1006 auto fps
= _bsnes_core
.video_rate();
1009 uint32_t g
= gcd(fps_n
, fps_d
);
1013 framebuffer_info inf
;
1014 inf
.type
= &_pixel_format_lrgb
;
1015 inf
.mem
= const_cast<char*>(reinterpret_cast<const char*>(data
));
1016 inf
.physwidth
= 512;
1017 inf
.physheight
= 512;
1018 inf
.physstride
= 2048;
1019 inf
.width
= hires
? 512 : 256;
1020 inf
.height
= (region
? 239 : 224) * (interlace
? 2 : 1);
1021 inf
.stride
= interlace
? 2048 : 4096;
1023 inf
.offset_y
= (region
? (overscan
? 9 : 1) : (overscan
? 16 : 9)) * 2;
1025 framebuffer_raw
ls(inf
);
1026 ecore_callbacks
->output_frame(ls
, fps_n
, fps_d
);
1027 information_dispatch::do_raw_frame(data
, hires
, interlace
, overscan
, region
?
1028 VIDEO_REGION_PAL
: VIDEO_REGION_NTSC
);
1029 if(soundbuf_fill
> 0) {
1030 auto freq
= SNES::system
.apu_frequency();
1031 audioapi_submit_buffer(soundbuf
, soundbuf_fill
/ 2, true, freq
/ 768.0);
1036 void audioSample(int16_t l_sample
, int16_t r_sample
)
1038 uint16_t _l
= l_sample
;
1039 uint16_t _r
= r_sample
;
1040 soundbuf
[soundbuf_fill
++] = l_sample
;
1041 soundbuf
[soundbuf_fill
++] = r_sample
;
1042 information_dispatch::do_sample(l_sample
, r_sample
);
1043 //The SMP emits a sample every 768 ticks of its clock. Use this in order to keep track of
1045 ecore_callbacks
->timer_tick(768, SNES::system
.apu_frequency());
1048 int16_t inputPoll(bool port
, SNES::Input::Device device
, unsigned index
, unsigned id
)
1051 //The superscope/justifier handling is nuts.
1052 if(port
&& SNES::input
.port2
) {
1053 SNES::SuperScope
* ss
= dynamic_cast<SNES::SuperScope
*>(SNES::input
.port2
);
1054 SNES::Justifier
* js
= dynamic_cast<SNES::Justifier
*>(SNES::input
.port2
);
1055 if(ss
&& index
== 0) {
1061 if(js
&& index
== 0) {
1063 offset
= js
->player1
.x
;
1065 offset
= js
->player1
.y
;
1067 if(js
&& js
->chained
&& index
== 1) {
1069 offset
= js
->player2
.x
;
1071 offset
= js
->player2
.y
;
1074 return ecore_callbacks
->get_input(port
? 2 : 1, index
, id
) - offset
;
1078 my_interface my_interface_obj
;
1079 SNES::Interface
* old
;
1082 core_core
* emulator_core
= &bsnes_core
;
1084 port_type
* core_port_types
[] = {
1085 &psystem
, &none
, &gamepad
, &gamepad16
, &multitap
, &multitap16
, &mouse
, &justifier
, &justifiers
,
1089 void core_install_handler()
1092 old
= SNES::interface
;
1093 SNES::interface
= &my_interface_obj
;
1094 SNES::system
.init();
1097 void core_uninstall_handler()
1099 SNES::interface
= old
;
1102 std::set
<std::string
> get_sram_set()
1104 std::set
<std::string
> r
;
1107 for(unsigned i
= 0; i
< SNES::cartridge
.nvram
.size(); i
++) {
1108 SNES::Cartridge::NonVolatileRAM
& s
= SNES::cartridge
.nvram
[i
];
1109 r
.insert(sram_name(s
.id
, s
.slot
));
1114 void core_request_reset(long delay
)
1116 do_reset_flag
= delay
;
1119 void core_emulate_frame()
1121 static unsigned frame_modulus
= 0;
1125 framebuffer_info inf
;
1126 inf
.type
= &_pixel_format_lrgb
;
1127 inf
.mem
= const_cast<char*>(reinterpret_cast<const char*>(norom_frame
));
1128 inf
.physwidth
= 512;
1129 inf
.physheight
= 448;
1130 inf
.physstride
= 2048;
1137 framebuffer_raw
ls(inf
);
1138 ecore_callbacks
->output_frame(ls
, 60, 1);
1140 audioapi_submit_buffer(blanksound
, frame_modulus
? 534 : 535, true, 32040.5);
1141 for(unsigned i
= 0; i
< 534; i
++)
1142 information_dispatch::do_sample(0, 0);
1144 information_dispatch::do_sample(0, 0);
1146 frame_modulus
%= 120;
1147 ecore_callbacks
->timer_tick(1, 60);
1151 bool was_delay_reset
= false;
1152 int16_t reset
= ecore_callbacks
->set_input(0, 0, 1, (do_reset_flag
>= 0) ? 1 : 0);
1154 long hi
= ecore_callbacks
->set_input(0, 0, 2, do_reset_flag
/ 10000);
1155 long lo
= ecore_callbacks
->set_input(0, 0, 3, do_reset_flag
% 10000);
1156 long delay
= 10000 * hi
+ lo
;
1158 was_delay_reset
= true;
1159 #ifdef BSNES_HAS_DEBUGGER
1160 messages
<< "Executing delayed reset... This can take some time!" << std::endl
;
1161 video_refresh_done
= false;
1162 delayreset_cycles_run
= 0;
1163 delayreset_cycles_target
= delay
;
1165 SNES::cpu
.step_event
= delayreset_fn
;
1168 if(SNES::scheduler
.exit_reason() == SNES::Scheduler::ExitReason::DebuggerEvent
&&
1169 SNES::debugger
.break_event
== SNES::Debugger::BreakEvent::BreakpointHit
) {
1173 SNES::cpu
.step_event
= nall::function
<bool()>();
1174 forced_hook
= false;
1175 if(video_refresh_done
) {
1176 //Force the reset here.
1178 messages
<< "SNES reset (forced at " << delayreset_cycles_run
<< ")" << std::endl
;
1179 SNES::system
.reset();
1182 SNES::system
.reset();
1183 messages
<< "SNES reset (delayed " << delayreset_cycles_run
<< ")" << std::endl
;
1185 messages
<< "Delayresets not supported on this bsnes version (needs v084 or v085)"
1187 SNES::system
.reset();
1189 } else if(delay
== 0) {
1190 SNES::system
.reset();
1191 messages
<< "SNES reset" << std::endl
;
1197 if(!have_saved_this_frame
&& save_every_frame
&& !was_delay_reset
)
1198 SNES::system
.runtosave();
1199 #ifdef BSNES_HAS_DEBUGGER
1201 SNES::cpu
.step_event
= trace_fn
;
1205 if(SNES::scheduler
.exit_reason() == SNES::Scheduler::ExitReason::DebuggerEvent
&&
1206 SNES::debugger
.break_event
== SNES::Debugger::BreakEvent::BreakpointHit
) {
1210 #ifdef BSNES_HAS_DEBUGGER
1211 SNES::cpu
.step_event
= nall::function
<bool()>();
1213 have_saved_this_frame
= false;
1216 void core_runtosave()
1220 stepping_into_save
= true;
1221 if(!allow_inconsistent_saves
)
1222 SNES::system
.runtosave();
1223 have_saved_this_frame
= true;
1224 stepping_into_save
= false;
1227 std::list
<vma_info
> get_vma_list()
1229 std::list
<vma_info
> ret
;
1232 create_region(ret
, "WRAM", 0x007E0000, SNES::cpu
.wram
, 131072, false);
1233 create_region(ret
, "APURAM", 0x00000000, SNES::smp
.apuram
, 65536, false);
1234 create_region(ret
, "VRAM", 0x00010000, SNES::ppu
.vram
, 65536, false);
1235 create_region(ret
, "OAM", 0x00020000, SNES::ppu
.oam
, 544, false);
1236 create_region(ret
, "CGRAM", 0x00021000, SNES::ppu
.cgram
, 512, false);
1237 if(SNES::cartridge
.has_srtc()) create_region(ret
, "RTC", 0x00022000, SNES::srtc
.rtc
, 20, false);
1238 if(SNES::cartridge
.has_spc7110rtc()) create_region(ret
, "RTC", 0x00022000, SNES::spc7110
.rtc
, 20, false);
1239 if(SNES::cartridge
.has_necdsp()) {
1240 create_region(ret
, "DSPRAM", 0x00023000, reinterpret_cast<uint8_t*>(SNES::necdsp
.dataRAM
), 4096,
1242 create_region(ret
, "DSPPROM", 0xF0000000, reinterpret_cast<uint8_t*>(SNES::necdsp
.programROM
), 65536,
1244 create_region(ret
, "DSPDROM", 0xF0010000, reinterpret_cast<uint8_t*>(SNES::necdsp
.dataROM
), 4096,
1247 create_region(ret
, "SRAM", 0x10000000, SNES::cartridge
.ram
, false);
1248 create_region(ret
, "ROM", 0x80000000, SNES::cartridge
.rom
, true);
1249 create_region(ret
, "BUS", 0x1000000, 0x1000000, snes_bus_iospace_rw
);
1250 create_region(ret
, "PTRTABLE", 0x100000000, 0x100000, ptrtable_iospace_rw
);
1251 map_internal(ret
, "CPU_STATE", 0, &SNES::cpu
, sizeof(SNES::cpu
));
1252 map_internal(ret
, "PPU_STATE", 1, &SNES::ppu
, sizeof(SNES::ppu
));
1253 map_internal(ret
, "SMP_STATE", 2, &SNES::smp
, sizeof(SNES::smp
));
1254 map_internal(ret
, "DSP_STATE", 3, &SNES::dsp
, sizeof(SNES::dsp
));
1255 if(internal_rom
== &type_bsx
|| internal_rom
== &type_bsxslotted
) {
1256 create_region(ret
, "BSXFLASH", 0x90000000, SNES::bsxflash
.memory
, true);
1257 create_region(ret
, "BSX_RAM", 0x20000000, SNES::bsxcartridge
.sram
, false);
1258 create_region(ret
, "BSX_PRAM", 0x30000000, SNES::bsxcartridge
.psram
, false);
1260 if(internal_rom
== &type_sufamiturbo
) {
1261 create_region(ret
, "SLOTA_ROM", 0x90000000, SNES::sufamiturbo
.slotA
.rom
, true);
1262 create_region(ret
, "SLOTB_ROM", 0xA0000000, SNES::sufamiturbo
.slotB
.rom
, true);
1263 create_region(ret
, "SLOTA_RAM", 0x20000000, SNES::sufamiturbo
.slotA
.ram
, false);
1264 create_region(ret
, "SLOTB_RAM", 0x30000000, SNES::sufamiturbo
.slotB
.ram
, false);
1266 if(internal_rom
== &type_sgb
) {
1267 create_region(ret
, "GBROM", 0x90000000, GameBoy::cartridge
.romdata
, GameBoy::cartridge
.romsize
, true);
1268 create_region(ret
, "GBRAM", 0x20000000, GameBoy::cartridge
.ramdata
, GameBoy::cartridge
.ramsize
, false);
1273 unsigned core_get_poll_flag()
1275 return pollflag_active
? (SNES::cpu
.controller_flag
? 1 : 0) : 2;
1278 void core_set_poll_flag(unsigned pflag
)
1280 SNES::cpu
.controller_flag
= (pflag
!= 0);
1281 pollflag_active
= (pflag
< 2);
1284 emucore_callbacks::~emucore_callbacks() throw()
1288 function_ptr_command
<arg_filename
> dump_core(lsnes_cmd
, "dump-core", "No description available",
1289 "No description available\n",
1290 [](arg_filename args
) throw(std::bad_alloc
, std::runtime_error
) {
1291 std::vector
<char> out
;
1292 _bsnes_core
.serialize(out
);
1293 std::ofstream
x(args
, std::ios_base::out
| std::ios_base::binary
);
1294 x
.write(&out
[0], out
.size());
1297 function_ptr_luafun
lua_memory_readreg(LS
, "memory.getregister", [](lua_state
& L
, const std::string
& fname
) -> int {
1298 std::string r
= L
.get_string(1, fname
.c_str());
1299 auto& c
= SNES::cpu
.regs
;
1300 auto& c2
= SNES::cpu
;
1301 if(r
== "pbpc") L
.pushnumber((unsigned)c
.pc
);
1302 else if(r
== "pb") L
.pushnumber((unsigned)c
.pc
>> 16);
1303 else if(r
== "pc") L
.pushnumber((unsigned)c
.pc
& 0xFFFF);
1304 else if(r
== "r0") L
.pushnumber((unsigned)c
.r
[0]);
1305 else if(r
== "r1") L
.pushnumber((unsigned)c
.r
[1]);
1306 else if(r
== "r2") L
.pushnumber((unsigned)c
.r
[2]);
1307 else if(r
== "r3") L
.pushnumber((unsigned)c
.r
[3]);
1308 else if(r
== "r4") L
.pushnumber((unsigned)c
.r
[4]);
1309 else if(r
== "r5") L
.pushnumber((unsigned)c
.r
[5]);
1310 else if(r
== "a") L
.pushnumber((unsigned)c
.a
);
1311 else if(r
== "x") L
.pushnumber((unsigned)c
.x
);
1312 else if(r
== "y") L
.pushnumber((unsigned)c
.y
);
1313 else if(r
== "z") L
.pushnumber((unsigned)c
.z
);
1314 else if(r
== "s") L
.pushnumber((unsigned)c
.s
);
1315 else if(r
== "d") L
.pushnumber((unsigned)c
.d
);
1316 else if(r
== "db") L
.pushnumber((unsigned)c
.db
);
1317 else if(r
== "p") L
.pushnumber((unsigned)c
.p
);
1318 else if(r
== "p_n") L
.pushboolean(c
.p
.n
);
1319 else if(r
== "p_v") L
.pushboolean(c
.p
.v
);
1320 else if(r
== "p_m") L
.pushboolean(c
.p
.m
);
1321 else if(r
== "p_x") L
.pushboolean(c
.p
.x
);
1322 else if(r
== "p_d") L
.pushboolean(c
.p
.d
);
1323 else if(r
== "p_i") L
.pushboolean(c
.p
.i
);
1324 else if(r
== "p_z") L
.pushboolean(c
.p
.z
);
1325 else if(r
== "p_c") L
.pushboolean(c
.p
.c
);
1326 else if(r
== "e") L
.pushboolean(c
.e
);
1327 else if(r
== "irq") L
.pushboolean(c
.irq
);
1328 else if(r
== "wai") L
.pushboolean(c
.wai
);
1329 else if(r
== "mdr") L
.pushnumber((unsigned)c
.mdr
);
1330 else if(r
== "vector") L
.pushnumber((unsigned)c
.vector
);
1331 else if(r
== "aa") L
.pushnumber((unsigned)c2
.aa
);
1332 else if(r
== "rd") L
.pushnumber((unsigned)c2
.rd
);
1333 else if(r
== "sp") L
.pushnumber((unsigned)c2
.sp
);
1334 else if(r
== "dp") L
.pushnumber((unsigned)c2
.dp
);
1339 #ifdef BSNES_HAS_DEBUGGER
1341 char snes_debug_cb_keys
[SNES::Debugger::Breakpoints
];
1342 char snes_debug_cb_trace
;
1344 void snesdbg_execute_callback(char& cb
, signed r
)
1346 LS
.pushlightuserdata(&cb
);
1347 LS
.gettable(LUA_REGISTRYINDEX
);
1349 if(LS
.type(-2) == LUA_TFUNCTION
) {
1350 int s
= LS
.pcall(1, 0, 0);
1354 messages
<< "Can't execute debug callback" << std::endl
;
1357 if(lua_requests_repaint
) {
1358 lua_requests_repaint
= false;
1359 lsnes_cmd
.invoke("repaint");
1363 void snesdbg_on_break()
1365 signed r
= SNES::debugger
.breakpoint_hit
;
1366 snesdbg_execute_callback(snes_debug_cb_keys
[r
], r
);
1369 void snesdbg_on_trace()
1371 snesdbg_execute_callback(snes_debug_cb_trace
, -1);
1374 void snesdbg_set_callback(lua_state
& L
, char& cb
)
1376 L
.pushlightuserdata(&cb
);
1378 L
.settable(LUA_REGISTRYINDEX
);
1381 bool snesdbg_get_bp_enabled(lua_state
& L
)
1384 L
.getfield(-1, "addr");
1385 r
= (L
.type(-1) == LUA_TNUMBER
);
1390 uint32_t snesdbg_get_bp_addr(lua_state
& L
)
1393 L
.getfield(-1, "addr");
1394 if(L
.type(-1) == LUA_TNUMBER
)
1395 r
= static_cast<uint32_t>(L
.tonumber(-1));
1400 uint32_t snesdbg_get_bp_data(lua_state
& L
)
1403 L
.getfield(-1, "data");
1404 if(L
.type(-1) == LUA_TNUMBER
)
1405 r
= static_cast<signed>(L
.tonumber(-1));
1410 SNES::Debugger::Breakpoint::Mode
snesdbg_get_bp_mode(lua_state
& L
)
1412 SNES::Debugger::Breakpoint::Mode r
= SNES::Debugger::Breakpoint::Mode::Exec
;
1413 L
.getfield(-1, "mode");
1414 if(L
.type(-1) == LUA_TSTRING
&& !strcmp(L
.tostring(-1), "e"))
1415 r
= SNES::Debugger::Breakpoint::Mode::Exec
;
1416 if(L
.type(-1) == LUA_TSTRING
&& !strcmp(L
.tostring(-1), "x"))
1417 r
= SNES::Debugger::Breakpoint::Mode::Exec
;
1418 if(L
.type(-1) == LUA_TSTRING
&& !strcmp(L
.tostring(-1), "exec"))
1419 r
= SNES::Debugger::Breakpoint::Mode::Exec
;
1420 if(L
.type(-1) == LUA_TSTRING
&& !strcmp(L
.tostring(-1), "r"))
1421 r
= SNES::Debugger::Breakpoint::Mode::Read
;
1422 if(L
.type(-1) == LUA_TSTRING
&& !strcmp(L
.tostring(-1), "read"))
1423 r
= SNES::Debugger::Breakpoint::Mode::Read
;
1424 if(L
.type(-1) == LUA_TSTRING
&& !strcmp(L
.tostring(-1), "w"))
1425 r
= SNES::Debugger::Breakpoint::Mode::Write
;
1426 if(L
.type(-1) == LUA_TSTRING
&& !strcmp(L
.tostring(-1), "write"))
1427 r
= SNES::Debugger::Breakpoint::Mode::Write
;
1432 SNES::Debugger::Breakpoint::Source
snesdbg_get_bp_source(lua_state
& L
)
1434 SNES::Debugger::Breakpoint::Source r
= SNES::Debugger::Breakpoint::Source::CPUBus
;
1435 L
.getfield(-1, "source");
1436 if(L
.type(-1) == LUA_TSTRING
&& !strcmp(L
.tostring(-1), "cpubus"))
1437 r
= SNES::Debugger::Breakpoint::Source::CPUBus
;
1438 if(L
.type(-1) == LUA_TSTRING
&& !strcmp(L
.tostring(-1), "apuram"))
1439 r
= SNES::Debugger::Breakpoint::Source::APURAM
;
1440 if(L
.type(-1) == LUA_TSTRING
&& !strcmp(L
.tostring(-1), "vram"))
1441 r
= SNES::Debugger::Breakpoint::Source::VRAM
;
1442 if(L
.type(-1) == LUA_TSTRING
&& !strcmp(L
.tostring(-1), "oam"))
1443 r
= SNES::Debugger::Breakpoint::Source::OAM
;
1444 if(L
.type(-1) == LUA_TSTRING
&& !strcmp(L
.tostring(-1), "cgram"))
1445 r
= SNES::Debugger::Breakpoint::Source::CGRAM
;
1450 void snesdbg_get_bp_callback(lua_state
& L
)
1452 L
.getfield(-1, "callback");
1457 function_ptr_luafun
lua_memory_setdebug(LS
, "memory.setdebug", [](lua_state
& L
, const std::string
& fname
) -> int {
1458 unsigned r
= L
.get_numeric_argument
<unsigned>(1, fname
.c_str());
1459 if(r
>= SNES::Debugger::Breakpoints
) {
1460 L
.pushstring("Bad breakpoint number");
1464 if(L
.type(2) == LUA_TNIL
) {
1466 SNES::debugger
.breakpoint
[r
].enabled
= false;
1468 } else if(L
.type(2) == LUA_TTABLE
) {
1470 auto& x
= SNES::debugger
.breakpoint
[r
];
1471 x
.enabled
= snesdbg_get_bp_enabled(L
);
1472 x
.addr
= snesdbg_get_bp_addr(L
);
1473 x
.data
= snesdbg_get_bp_data(L
);
1474 x
.mode
= snesdbg_get_bp_mode(L
);
1475 x
.source
= snesdbg_get_bp_source(L
);
1476 snesdbg_get_bp_callback(L
);
1477 snesdbg_set_callback(L
, snes_debug_cb_keys
[r
]);
1481 L
.pushstring("Expected argument 2 to memory.setdebug to be nil or table");
1487 function_ptr_luafun
lua_memory_setstep(LS
, "memory.setstep", [](lua_state
& L
, const std::string
& fname
) -> int {
1488 uint64_t r
= L
.get_numeric_argument
<uint64_t>(1, fname
.c_str());
1490 snesdbg_set_callback(L
, snes_debug_cb_trace
);
1492 update_trace_hook_state();
1497 void snesdbg_settrace(std::string r
)
1499 if(trace_output_enable
)
1500 messages
<< "------- End of trace -----" << std::endl
;
1501 trace_output
.close();
1502 trace_output_enable
= false;
1504 trace_output
.close();
1505 trace_output
.open(r
);
1507 trace_output_enable
= true;
1508 messages
<< "------- Start of trace -----" << std::endl
;
1510 messages
<< "Can't open " << r
<< std::endl
;
1512 update_trace_hook_state();
1515 function_ptr_luafun
lua_memory_settrace(LS
, "memory.settrace", [](lua_state
& L
, const std::string
& fname
) -> int {
1516 std::string r
= L
.get_string(1, fname
.c_str());
1517 snesdbg_settrace(r
);
1520 function_ptr_command
<const std::string
&> start_trace(lsnes_cmd
, "set-trace", "No description available",
1521 "No description available\n",
1522 [](const std::string
& r
) throw(std::bad_alloc
, std::runtime_error
) {
1523 snesdbg_settrace(r
);
1527 void snesdbg_on_break() {}
1528 void snesdbg_on_trace() {}
1531 struct emucore_callbacks
* ecore_callbacks
;