Remove do_basic_core_init (do equivalent tasks on demand)
[lsnes.git] / src / core / bsnes-legacy.cpp
blob3064ad836655613302fa96de4b89c6e0339d67f1
1 #ifdef CORETYPE_BSNES
2 #include "lsnes.hpp"
3 #include <sstream>
4 #include <map>
5 #include <string>
6 #include <vector>
7 #include <fstream>
8 #include <climits>
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>
27 #ifdef BSNES_V087
28 #include <target-libsnes/libsnes.hpp>
29 #else
30 #include <ui-libsnes/libsnes.hpp>
31 #endif
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();
47 namespace
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,
127 &superscope_btn_P
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 {
151 if(idx)
152 return;
153 if(ctrl < 2)
154 if(x)
155 buffer[0] |= (1 << ctrl);
156 else
157 buffer[0] &= ~(1 << ctrl);
158 else if(ctrl < 4) {
159 buffer[2 * ctrl - 3] = x >> 8;
160 buffer[2 * ctrl - 2] = x;
163 read = [](const unsigned char* buffer, unsigned idx, unsigned ctrl) -> short {
164 if(idx)
165 return 0;
166 if(ctrl < 2)
167 return (buffer[0] >> ctrl) ? 1 : 0;
168 else if(ctrl < 4)
169 return unserialize_short(buffer + 2 * ctrl - 3);
170 return 0;
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' : '-');
175 if(idx)
176 sprintf(buf, "");
177 else
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' : '.');
184 char tmp[128];
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));
188 else
189 sprintf(tmp, "%c%c", x1, x2);
190 size_t len = strlen(tmp);
191 memcpy(textbuf, tmp, len);
192 return len;
194 deserialize = [](unsigned char* buffer, const char* textbuf) -> size_t {
195 memset(buffer, 0, 5);
196 size_t ptr = 0;
197 if(read_button_value(textbuf, ptr))
198 buffer[0] |= 1;
199 if(read_button_value(textbuf, ptr))
200 buffer[0] |= 2;
201 short v = read_axis_value(textbuf, ptr);
202 buffer[1] = v >> 8;
203 buffer[2] = v;
204 v = read_axis_value(textbuf, ptr);
205 buffer[3] = v >> 8;
206 buffer[4] = v;
207 skip_rest_of_field(textbuf, ptr, false);
208 return ptr;
210 legal = generic_port_legal<1>;
211 controller_info = &system_port;
212 used_indices = generic_used_indices<1, 4>;
214 } psystem;
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>;
233 } none;
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>;
257 } gamepad;
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>;
273 } gamepad16;
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>;
304 } multitap;
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>;
320 } multitap16;
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>;
344 } mouse;
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>;
367 } superscope;
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>;
389 } justifier;
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>;
411 } justifiers;
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)
435 return "./";
439 void basic_init()
441 static bool done = false;
442 if(done)
443 return;
444 done = true;
445 static my_interfaced i;
446 SNES::interface = &i;
449 void init_norom_frame()
451 static bool done = false;
452 if(done)
453 return;
454 done = true;
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]);
498 basic_init();
499 snes_term();
500 snes_unload_cartridge();
501 SNES::config.random = false;
502 SNES::config.expansion_port = SNES::System::ExpansionPortDevice::None;
503 bool r = fun(img);
504 if(r)
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;
509 do_reset_flag = -1;
510 return r ? 0 : -1;
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)
520 port_index_triple x;
521 x.port = p;
522 x.controller = c;
523 x.control = i;
524 x.marks_nonlag = nl;
525 return x;
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]);
542 controller_set r;
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);
559 } else {
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));
567 return r;
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[] = {&region_auto, &region_ntsc, &region_pal, NULL};
614 core_region* _ntsconly[] = {&region_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
632 #else
633 #define BSNES_RESET_LEVEL 1
634 #endif
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...
640 if(id == "bsx.ram")
641 id = ".bss";
642 if(id == "bsx.psram")
643 id = ".bsp";
644 if(id == "program.rtc")
645 id = ".rtc";
646 if(id == "upd96050.ram")
647 id = ".dsp";
648 if(id == "program.ram")
649 id = ".srm";
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);
654 return id.substr(1);
657 core_core_params _bsnes_core = {
658 //Identify core.
659 []() -> std::string {
660 return (stringfmt() << snes_library_id() << " (" << SNES::Info::Profile << " core)").str();
662 //Set region.
663 [](core_region& region) -> bool {
664 if(&region == &region_auto)
665 SNES::config.region = SNES::System::Region::Autodetect;
666 else if(&region == &region_ntsc)
667 SNES::config.region = SNES::System::Region::NTSC;
668 else if(&region == &region_pal)
669 SNES::config.region = SNES::System::Region::PAL;
670 else
671 return false;
672 return true;
674 //Get video rate
675 []() -> std::pair<uint32_t, uint32_t> {
676 if(!internal_rom)
677 return std::make_pair(60, 1);
678 uint32_t div;
679 if(SNES::system.region() == SNES::System::Region::PAL)
680 div = last_interlace ? DURATION_PAL_FIELD : DURATION_PAL_FRAME;
681 else
682 div = last_interlace ? DURATION_NTSC_FIELD : DURATION_NTSC_FRAME;
683 return std::make_pair(SNES::system.cpu_frequency(), div);
685 //Get audio rate
686 []() -> std::pair<uint32_t, uint32_t> {
687 if(!internal_rom)
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());
695 //Store SRAM.
696 []() -> std::map<std::string, std::vector<char>> {
697 std::map<std::string, std::vector<char>> out;
698 if(!internal_rom)
699 return 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);
703 std::vector<char> x;
704 x.resize(r.size);
705 memcpy(&x[0], r.data, r.size);
706 out[savename] = x;
708 return out;
710 //Load SRAM.
711 [](std::map<std::string, std::vector<char>>& sram) -> void {
712 std::set<std::string> used;
713 if(!internal_rom) {
714 for(auto i : sram)
715 messages << "WARNING: SRAM '" << i.first << ": Not found on cartridge."
716 << std::endl;
717 return;
719 if(sram.empty())
720 return;
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);
731 } else
732 messages << "WARNING: SRAM '" << savename << ": No data." << std::endl;
734 for(auto i : sram)
735 if(!used.count(i.first))
736 messages << "WARNING: SRAM '" << i.first << ": Not found on cartridge."
737 << std::endl;
739 //Serialize core.
740 [](std::vector<char>& out) -> void {
741 if(!internal_rom)
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());
747 //Unserialize core.
748 [](const char* in, size_t insize) -> void {
749 if(!internal_rom)
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;
755 do_reset_flag = -1;
757 //Get region.
758 []() -> core_region& {
759 return (SNES::system.region() == SNES::System::Region::PAL) ? region_pal : region_ntsc;
761 //Power the core.
762 []() -> void {
763 if(internal_rom) snes_power();
765 //Unload the cartridge.
766 []() -> void {
767 if(!internal_rom) return;
768 snes_term();
769 snes_unload_cartridge();
770 internal_rom = NULL;
772 //Get scale factors.
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,
798 bsnes_get_bus_map
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,
808 bsnes_get_bus_map
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,
818 bsnes_get_bus_map
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,
829 bsnes_get_bus_map
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;
847 //Delay reset.
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)
855 if(write)
856 SNES::bus.write(offset, data);
857 else
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))
865 return 0;
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)
875 if(size == 0)
876 return;
877 vma_info i;
878 i.name = name;
879 i.base = base;
880 i.size = size;
881 i.readonly = false;
882 i.native_endian = false;
883 i.iospace_rw = iospace_rw;
884 inf.push_back(i);
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)
890 if(size == 0)
891 return;
892 vma_info i;
893 i.name = name;
894 i.base = base;
895 i.size = size;
896 i.backing_ram = memory;
897 i.readonly = readonly;
898 i.native_endian = native_endian;
899 i.iospace_rw = NULL;
900 inf.push_back(i);
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,
910 size_t memsize)
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);
917 bool trace_enabled()
919 return (trace_counter || !!trace_output_enable);
922 bool forced_hook = false;
924 bool trace_fn()
926 if(trace_counter && !--trace_counter) {
927 //Trace counter did transition 1->0. Call the hook.
928 snesdbg_on_trace();
930 if(trace_output_enable) {
931 char buffer[1024];
932 SNES::cpu.disassemble_opcode(buffer, SNES::cpu.regs.pc);
933 trace_output << buffer << std::endl;
935 return false;
938 void update_trace_hook_state()
940 if(forced_hook)
941 return;
942 #ifdef BSNES_HAS_DEBUGGER
943 if(!trace_enabled())
944 SNES::cpu.step_event = nall::function<bool()>();
945 else
946 SNES::cpu.step_event = trace_fn;
947 #endif
950 bool delayreset_fn()
952 trace_fn(); //Call this also.
953 if(delayreset_cycles_run == delayreset_cycles_target || video_refresh_done)
954 return true;
955 delayreset_cycles_run++;
956 return false;
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();
966 regex_results r;
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") {
972 //MSU-1 main ROM.
973 std::string x = msubase + ".msu";
974 messages << "MSU main data file: " << x << std::endl;
975 return x.c_str();
977 if(r = regex("(track)?(-([0-9])+\\.pcm)", _hint2)) {
978 //MSU track.
979 std::string x = msubase + r[2];
980 messages << "MSU track " << r[3] << "': " << x << std::endl;
981 return x.c_str();
983 std::string finalpath = fwp + "/" + _hint2;
984 return finalpath.c_str();
987 time_t currentTime()
989 return ecore_callbacks->get_time();
992 time_t randomSeed()
994 return ecore_callbacks->get_randomseed();
997 void videoRefresh(const uint32_t* data, bool hires, bool interlace, bool overscan)
999 last_hires = hires;
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();
1007 fps_n = fps.first;
1008 fps_d = fps.second;
1009 uint32_t g = gcd(fps_n, fps_d);
1010 fps_n /= g;
1011 fps_d /= g;
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;
1022 inf.offset_x = 0;
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);
1032 soundbuf_fill = 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
1044 //time.
1045 ecore_callbacks->timer_tick(768, SNES::system.apu_frequency());
1048 int16_t inputPoll(bool port, SNES::Input::Device device, unsigned index, unsigned id)
1050 int16_t offset = 0;
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) {
1056 if(id == 0)
1057 offset = ss->x;
1058 if(id == 1)
1059 offset = ss->y;
1061 if(js && index == 0) {
1062 if(id == 0)
1063 offset = js->player1.x;
1064 if(id == 1)
1065 offset = js->player1.y;
1067 if(js && js->chained && index == 1) {
1068 if(id == 0)
1069 offset = js->player2.x;
1070 if(id == 1)
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,
1086 &superscope, NULL
1089 void core_install_handler()
1091 basic_init();
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;
1105 if(!internal_rom)
1106 return 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));
1111 return r;
1114 void core_request_reset(long delay)
1116 do_reset_flag = delay;
1119 void core_emulate_frame()
1121 static unsigned frame_modulus = 0;
1122 if(!internal_rom) {
1123 do_reset_flag = -1;
1124 init_norom_frame();
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;
1131 inf.width = 512;
1132 inf.height = 448;
1133 inf.stride = 2048;
1134 inf.offset_x = 0;
1135 inf.offset_y = 0;
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);
1143 if(!frame_modulus)
1144 information_dispatch::do_sample(0, 0);
1145 frame_modulus++;
1146 frame_modulus %= 120;
1147 ecore_callbacks->timer_tick(1, 60);
1148 return;
1151 bool was_delay_reset = false;
1152 int16_t reset = ecore_callbacks->set_input(0, 0, 1, (do_reset_flag >= 0) ? 1 : 0);
1153 if(reset) {
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;
1157 if(delay > 0) {
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;
1164 forced_hook = true;
1165 SNES::cpu.step_event = delayreset_fn;
1166 again:
1167 SNES::system.run();
1168 if(SNES::scheduler.exit_reason() == SNES::Scheduler::ExitReason::DebuggerEvent &&
1169 SNES::debugger.break_event == SNES::Debugger::BreakEvent::BreakpointHit) {
1170 snesdbg_on_break();
1171 goto again;
1173 SNES::cpu.step_event = nall::function<bool()>();
1174 forced_hook = false;
1175 if(video_refresh_done) {
1176 //Force the reset here.
1177 do_reset_flag = -1;
1178 messages << "SNES reset (forced at " << delayreset_cycles_run << ")" << std::endl;
1179 SNES::system.reset();
1180 return;
1182 SNES::system.reset();
1183 messages << "SNES reset (delayed " << delayreset_cycles_run << ")" << std::endl;
1184 #else
1185 messages << "Delayresets not supported on this bsnes version (needs v084 or v085)"
1186 << std::endl;
1187 SNES::system.reset();
1188 #endif
1189 } else if(delay == 0) {
1190 SNES::system.reset();
1191 messages << "SNES reset" << std::endl;
1194 do_reset_flag = -1;
1197 if(!have_saved_this_frame && save_every_frame && !was_delay_reset)
1198 SNES::system.runtosave();
1199 #ifdef BSNES_HAS_DEBUGGER
1200 if(trace_enabled())
1201 SNES::cpu.step_event = trace_fn;
1202 #endif
1203 again2:
1204 SNES::system.run();
1205 if(SNES::scheduler.exit_reason() == SNES::Scheduler::ExitReason::DebuggerEvent &&
1206 SNES::debugger.break_event == SNES::Debugger::BreakEvent::BreakpointHit) {
1207 snesdbg_on_break();
1208 goto again2;
1210 #ifdef BSNES_HAS_DEBUGGER
1211 SNES::cpu.step_event = nall::function<bool()>();
1212 #endif
1213 have_saved_this_frame = false;
1216 void core_runtosave()
1218 if(!internal_rom)
1219 return;
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;
1230 if(!internal_rom)
1231 return 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,
1241 false, true);
1242 create_region(ret, "DSPPROM", 0xF0000000, reinterpret_cast<uint8_t*>(SNES::necdsp.programROM), 65536,
1243 true, true);
1244 create_region(ret, "DSPDROM", 0xF0010000, reinterpret_cast<uint8_t*>(SNES::necdsp.dataROM), 4096,
1245 true, true);
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);
1270 return ret;
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);
1335 else L.pushnil();
1336 return 1;
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);
1348 LS.pushnumber(r);
1349 if(LS.type(-2) == LUA_TFUNCTION) {
1350 int s = LS.pcall(1, 0, 0);
1351 if(s)
1352 LS.pop(1);
1353 } else {
1354 messages << "Can't execute debug callback" << std::endl;
1355 LS.pop(2);
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);
1377 L.pushvalue(-2);
1378 L.settable(LUA_REGISTRYINDEX);
1381 bool snesdbg_get_bp_enabled(lua_state& L)
1383 bool r;
1384 L.getfield(-1, "addr");
1385 r = (L.type(-1) == LUA_TNUMBER);
1386 L.pop(1);
1387 return r;
1390 uint32_t snesdbg_get_bp_addr(lua_state& L)
1392 uint32_t r = 0;
1393 L.getfield(-1, "addr");
1394 if(L.type(-1) == LUA_TNUMBER)
1395 r = static_cast<uint32_t>(L.tonumber(-1));
1396 L.pop(1);
1397 return r;
1400 uint32_t snesdbg_get_bp_data(lua_state& L)
1402 signed r = -1;
1403 L.getfield(-1, "data");
1404 if(L.type(-1) == LUA_TNUMBER)
1405 r = static_cast<signed>(L.tonumber(-1));
1406 L.pop(1);
1407 return r;
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;
1428 L.pop(1);
1429 return r;
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;
1446 L.pop(1);
1447 return r;
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");
1461 L.error();
1462 return 0;
1464 if(L.type(2) == LUA_TNIL) {
1465 //Clear breakpoint.
1466 SNES::debugger.breakpoint[r].enabled = false;
1467 return 0;
1468 } else if(L.type(2) == LUA_TTABLE) {
1469 L.pushvalue(2);
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]);
1478 L.pop(2);
1479 return 0;
1480 } else {
1481 L.pushstring("Expected argument 2 to memory.setdebug to be nil or table");
1482 L.error();
1483 return 0;
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());
1489 L.pushvalue(2);
1490 snesdbg_set_callback(L, snes_debug_cb_trace);
1491 trace_counter = r;
1492 update_trace_hook_state();
1493 L.pop(1);
1494 return 0;
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;
1503 if(r != "") {
1504 trace_output.close();
1505 trace_output.open(r);
1506 if(trace_output) {
1507 trace_output_enable = true;
1508 messages << "------- Start of trace -----" << std::endl;
1509 } else
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);
1526 #else
1527 void snesdbg_on_break() {}
1528 void snesdbg_on_trace() {}
1529 #endif
1531 struct emucore_callbacks* ecore_callbacks;
1532 #endif