Make the SNES rate specials methods
[lsnes.git] / src / core / gambatte.cpp
blob3e881b97636f2393ed44ddccb5897414a86f77c5
1 #ifdef CORETYPE_GAMBATTE
2 #include "lsnes.hpp"
3 #include <sstream>
4 #include <iostream>
5 #include <map>
6 #include <string>
7 #include <vector>
8 #include "core/audioapi.hpp"
9 #include "core/misc.hpp"
10 #include "core/emucore.hpp"
11 #include "core/command.hpp"
12 #include "core/controllerframe.hpp"
13 #include "core/dispatch.hpp"
14 #include "core/framebuffer.hpp"
15 #include "core/window.hpp"
16 #include "interface/romtype.hpp"
17 #include "library/pixfmt-rgb32.hpp"
18 #include "library/string.hpp"
19 #include "library/portfn.hpp"
20 #include "library/serialization.hpp"
21 #include "library/minmax.hpp"
22 #include "library/framebuffer.hpp"
23 #define HAVE_CSTDINT
24 #include "libgambatte/include/gambatte.h"
26 #define SAMPLES_PER_FRAME 35112
28 #define LOGICAL_BUTTON_LEFT 0
29 #define LOGICAL_BUTTON_RIGHT 1
30 #define LOGICAL_BUTTON_UP 2
31 #define LOGICAL_BUTTON_DOWN 3
32 #define LOGICAL_BUTTON_A 4
33 #define LOGICAL_BUTTON_B 5
34 #define LOGICAL_BUTTON_SELECT 6
35 #define LOGICAL_BUTTON_START 7
37 unsigned core_userports = 0;
38 extern const bool core_supports_reset = true;
39 extern const bool core_supports_dreset = false;
41 namespace
43 int regions_compatible(unsigned rom, unsigned run)
45 return 1;
48 bool do_reset_flag = false;
49 core_type* internal_rom = NULL;
50 extern core_type type_dmg;
51 extern core_type type_gbc;
52 extern core_type type_gbc_gba;
53 bool rtc_fixed;
54 time_t rtc_fixed_val;
55 gambatte::GB* instance;
56 unsigned frame_overflow = 0;
57 std::vector<unsigned char> romdata;
58 uint32_t primary_framebuffer[160*144];
59 uint32_t norom_framebuffer[160*144];
60 uint32_t accumulator_l = 0;
61 uint32_t accumulator_r = 0;
62 unsigned accumulator_s = 0;
64 core_setting_group gambatte_settings;
66 void init_norom_framebuffer()
68 static bool done = false;
69 if(done)
70 return;
71 done = true;
72 for(size_t i = 0; i < 160 * 144; i++)
73 norom_framebuffer[i] = 0xFF8080;
76 time_t walltime_fn()
78 if(rtc_fixed)
79 return rtc_fixed_val;
80 if(ecore_callbacks)
81 return ecore_callbacks->get_time();
82 else
83 return time(0);
86 class myinput : public gambatte::InputGetter
88 public:
89 unsigned operator()()
91 unsigned v = 0;
92 for(unsigned i = 0; i < 8; i++) {
93 if(ecore_callbacks->get_input(0, 1, i))
94 v |= (1 << i);
96 return v;
98 } getinput;
100 std::pair<uint32_t, uint32_t> get_video_rate()
102 return std::make_pair(262144, 4389);
105 std::pair<uint32_t, uint32_t> get_audio_rate()
107 return std::make_pair(32768, 1);
111 const char* buttonnames[] = {"left", "right", "up", "down", "A", "B", "select", "start"};
113 void system_write(unsigned char* buffer, unsigned idx, unsigned ctrl, short x) throw()
115 if(idx < 2 && ctrl < 8)
116 if(x)
117 buffer[idx] |= (1 << ctrl);
118 else
119 buffer[idx] &= ~(1 << ctrl);
122 short system_read(const unsigned char* buffer, unsigned idx, unsigned ctrl) throw()
124 short y = 0;
125 if(idx < 2 && ctrl < 8)
126 y = ((buffer[idx] >> ctrl) & 1) ? 1 : 0;
127 return y;
130 size_t system_deserialize(unsigned char* buffer, const char* textbuf)
132 memset(buffer, 0, 2);
133 size_t ptr = 0;
134 if(read_button_value(textbuf, ptr))
135 buffer[0] |= 1;
136 if(read_button_value(textbuf, ptr))
137 buffer[0] |= 2;
138 skip_rest_of_field(textbuf, ptr, true);
139 for(unsigned i = 0; i < 8; i++)
140 if(read_button_value(textbuf, ptr))
141 buffer[1] |= (1 << i);
142 skip_rest_of_field(textbuf, ptr, false);
143 return ptr;
146 const char* button_symbols = "ABsSrlud";
148 void system_display(const unsigned char* buffer, unsigned idx, char* buf)
150 if(idx > 1)
151 sprintf(buf, "");
152 else if(idx == 1) {
153 for(unsigned i = 0; i < 8; i++)
154 buf[i] = ((buffer[1] & (1 << i)) != 0) ? button_symbols[i] : '-';
155 buf[8] = '\0';
156 } else
157 sprintf(buf, "%c%c", ((buffer[0] & 1) ? 'F' : '.'), ((buffer[0] & 2) ? 'R' : '.'));
160 size_t system_serialize(const unsigned char* buffer, char* textbuf)
162 char tmp[128];
163 sprintf(tmp, "%c%c|", ((buffer[0] & 1) ? 'F' : '.'), ((buffer[0] & 2) ? 'R' : '.'));
164 for(unsigned i = 0; i < 8; i++)
165 tmp[i + 3] = ((buffer[1] & (1 << i)) != 0) ? button_symbols[i] : '.';
166 tmp[11] = 0;
167 size_t len = strlen(tmp);
168 memcpy(textbuf, tmp, len);
169 return len;
172 unsigned _used_indices(unsigned c)
174 return c ? ((c == 1) ? 8 : 0) : 2;
177 port_controller_button gamepad_A = {port_controller_button::TYPE_BUTTON, "A"};
178 port_controller_button gamepad_B = {port_controller_button::TYPE_BUTTON, "B"};
179 port_controller_button gamepad_s = {port_controller_button::TYPE_BUTTON, "select"};
180 port_controller_button gamepad_S = {port_controller_button::TYPE_BUTTON, "start"};
181 port_controller_button gamepad_u = {port_controller_button::TYPE_BUTTON, "up"};
182 port_controller_button gamepad_d = {port_controller_button::TYPE_BUTTON, "down"};
183 port_controller_button gamepad_l = {port_controller_button::TYPE_BUTTON, "left"};
184 port_controller_button gamepad_r = {port_controller_button::TYPE_BUTTON, "right"};
185 port_controller_button* gamepad_buttons[] = {
186 &gamepad_A, &gamepad_B, &gamepad_s, &gamepad_S,
187 &gamepad_r, &gamepad_l, &gamepad_u, &gamepad_d
189 port_controller_button* none_buttons[] = {};
190 port_controller system_controller = {"system", "system", 0, none_buttons};
191 port_controller gb_buttons = {"gb", "gamepad", 8, gamepad_buttons};
192 port_controller* gambatte_controllers[] = {&system_controller, &gb_buttons};
193 port_controller_set _controller_info = {2, gambatte_controllers};
195 struct porttype_system : public port_type
197 porttype_system() : port_type("<SYSTEM>", "<SYSTEM>", 9999, 2)
199 write = system_write;
200 read = system_read;
201 display = system_display;
202 serialize = system_serialize;
203 deserialize = system_deserialize;
204 legal = generic_port_legal<1>;
205 used_indices = _used_indices;
206 controller_info = &_controller_info;
208 } psystem;
210 int load_rom_common(core_romimage* img, unsigned flags, uint64_t rtc_sec, uint64_t rtc_subsec,
211 core_type* inttype)
213 const char* markup = img[0].markup;
214 int flags2 = 0;
215 if(markup) {
216 flags2 = atoi(markup);
217 flags2 &= 4;
219 flags |= flags2;
220 const unsigned char* data = img[0].data;
221 size_t size = img[0].size;
223 //Reset it really.
224 instance->~GB();
225 memset(instance, 0, sizeof(gambatte::GB));
226 new(instance) gambatte::GB;
227 instance->setInputGetter(&getinput);
228 instance->set_walltime_fn(walltime_fn);
229 memset(primary_framebuffer, 0, sizeof(primary_framebuffer));
230 frame_overflow = 0;
232 rtc_fixed = true;
233 rtc_fixed_val = rtc_sec;
234 instance->load(data, size, flags);
235 rtc_fixed = false;
236 romdata.resize(size);
237 memcpy(&romdata[0], data, size);
238 internal_rom = inttype;
239 do_reset_flag = false;
240 return 1;
243 int load_rom_dmg(core_romimage* img, std::map<std::string, std::string>& settings, uint64_t rtc_sec,
244 uint64_t rtc_subsec)
246 return load_rom_common(img, gambatte::GB::FORCE_DMG, rtc_sec, rtc_subsec, &type_dmg);
249 int load_rom_gbc(core_romimage* img, std::map<std::string, std::string>& settings, uint64_t rtc_sec,
250 uint64_t rtc_subsec)
252 return load_rom_common(img, 0, rtc_sec, rtc_subsec, &type_gbc);
255 int load_rom_gbc_gba(core_romimage* img, std::map<std::string, std::string>& settings, uint64_t rtc_sec,
256 uint64_t rtc_subsec)
258 return load_rom_common(img, gambatte::GB::GBA_CGB, rtc_sec, rtc_subsec, &type_gbc_gba);
261 port_index_triple t(unsigned p, unsigned c, unsigned i, bool nl)
263 port_index_triple x;
264 x.port = p;
265 x.controller = c;
266 x.control = i;
267 x.marks_nonlag = nl;
268 return x;
271 controller_set _controllerconfig(std::map<std::string, std::string>& settings)
273 std::map<std::string, std::string> _settings = settings;
274 controller_set r;
275 r.ports.push_back(&psystem);
276 for(unsigned i = 0; i < 4; i++)
277 r.portindex.indices.push_back(t(0, 0, i, false));
278 for(unsigned i = 0; i < 8; i++)
279 r.portindex.indices.push_back(t(0, 1, i, true));
280 r.portindex.logical_map.push_back(std::make_pair(0, 1));
281 r.portindex.pcid_map.push_back(std::make_pair(0, 1));
282 return r;
286 unsigned world_compatible[] = {0, UINT_MAX};
287 core_region_params _region_world = {
288 "world", "World", 1, 0, false, {35112, 2097152, 16742706, 626688}, world_compatible
290 core_romimage_info_params _image_rom = {
291 "rom", "Cartridge ROM", 1, 0, 0
294 core_region region_world(_region_world);
295 core_romimage_info image_rom_dmg(_image_rom);
296 core_romimage_info image_rom_gbc(_image_rom);
297 core_romimage_info image_rom_gbca(_image_rom);
298 core_region* regions_gambatte[] = {&region_world, NULL};
299 core_romimage_info* dmg_images[] = {&image_rom_dmg, NULL};
300 core_romimage_info* gbc_images[] = {&image_rom_gbc, NULL};
301 core_romimage_info* gbca_images[] = {&image_rom_gbca, NULL};
303 bool core_set_region(core_region& region)
305 return (&region == &region_world);
308 core_type_params _type_dmg = {
309 "dmg", "Game Boy", 1, 1, load_rom_dmg, _controllerconfig, "gb;dmg", NULL,
310 regions_gambatte, dmg_images, &gambatte_settings, core_set_region, get_video_rate, get_audio_rate,
311 NULL
313 core_type_params _type_gbc = {
314 "gbc", "Game Boy Color", 0, 1, load_rom_gbc, _controllerconfig, "gbc;cgb", NULL,
315 regions_gambatte, gbc_images, &gambatte_settings, core_set_region, get_video_rate, get_audio_rate,
316 NULL
318 core_type_params _type_gbc_gba = {
319 "gbc_gba", "Game Boy Color (GBA)", 2, 1, load_rom_gbc_gba, _controllerconfig, "", NULL,
320 regions_gambatte, gbca_images, &gambatte_settings, core_set_region, get_video_rate, get_audio_rate,
321 NULL
323 core_type type_dmg(_type_dmg);
324 core_type type_gbc(_type_gbc);
325 core_type type_gbc_gba(_type_gbc_gba);
326 core_sysregion sr1("gdmg", type_dmg, region_world);
327 core_sysregion sr2("ggbc", type_gbc, region_world);
328 core_sysregion sr3("ggbca", type_gbc_gba, region_world);
331 port_type* core_port_types[] = {
332 &psystem, NULL
335 std::string get_logical_button_name(unsigned lbid) throw(std::bad_alloc)
337 if(lbid >= sizeof(buttonnames) / sizeof(buttonnames[0]))
338 return "";
339 return buttonnames[lbid];
342 std::string get_core_identifier()
344 return "libgambatte "+gambatte::GB::version();
347 core_region& core_get_region()
349 return region_world;
352 void core_runtosave()
356 void do_basic_core_init()
358 instance = new gambatte::GB;
359 instance->setInputGetter(&getinput);
360 instance->set_walltime_fn(walltime_fn);
363 void core_power()
367 void core_unload_cartridge()
371 void set_preload_settings()
375 void core_install_handler()
379 void core_uninstall_handler()
383 void core_emulate_frame_nocore()
385 do_reset_flag = -1;
386 init_norom_framebuffer();
387 while(true) {
388 int16_t soundbuf[(SAMPLES_PER_FRAME + 63) / 32];
389 size_t emitted = 0;
390 unsigned samples_emitted = SAMPLES_PER_FRAME - frame_overflow;
391 for(unsigned i = 0; i < samples_emitted; i++) {
392 accumulator_l += 32768;
393 accumulator_r += 32768;
394 accumulator_s++;
395 if((accumulator_s & 63) == 0) {
396 int16_t l2 = (accumulator_l >> 6) - 32768;
397 int16_t r2 = (accumulator_r >> 6) - 32768;
398 soundbuf[emitted++] = l2;
399 soundbuf[emitted++] = r2;
400 information_dispatch::do_sample(l2, r2);
401 accumulator_l = accumulator_r = 0;
402 accumulator_s = 0;
405 audioapi_submit_buffer(soundbuf, emitted / 2, true, 32768);
406 ecore_callbacks->timer_tick(samples_emitted, 2097152);
407 frame_overflow = 0;
408 break;
410 framebuffer_info inf;
411 inf.type = &_pixel_format_rgb32;
412 inf.mem = const_cast<char*>(reinterpret_cast<const char*>(norom_framebuffer));
413 inf.physwidth = 160;
414 inf.physheight = 144;
415 inf.physstride = 640;
416 inf.width = 160;
417 inf.height = 144;
418 inf.stride = 640;
419 inf.offset_x = 0;
420 inf.offset_y = 0;
422 framebuffer_raw ls(inf);
423 ecore_callbacks->output_frame(ls, 262144, 4389);
426 void core_request_reset(long delay)
428 do_reset_flag = true;
431 void core_emulate_frame()
433 if(!internal_rom) {
434 core_emulate_frame_nocore();
435 return;
438 int16_t reset = ecore_callbacks->set_input(0, 0, 1, do_reset_flag ? 1 : 0);
439 if(reset) {
440 instance->reset();
441 messages << "GB(C) reset" << std::endl;
443 do_reset_flag = false;
445 uint32_t samplebuffer[SAMPLES_PER_FRAME + 2064];
446 while(true) {
447 int16_t soundbuf[(SAMPLES_PER_FRAME + 63) / 32 + 66];
448 size_t emitted = 0;
449 unsigned samples_emitted = SAMPLES_PER_FRAME - frame_overflow;
450 long ret = instance->runFor(primary_framebuffer, 160, samplebuffer, samples_emitted);
451 for(unsigned i = 0; i < samples_emitted; i++) {
452 uint32_t l = (int32_t)(int16_t)(samplebuffer[i]) + 32768;
453 uint32_t r = (int32_t)(int16_t)(samplebuffer[i] >> 16) + 32768;
454 accumulator_l += l;
455 accumulator_r += r;
456 accumulator_s++;
457 if((accumulator_s & 63) == 0) {
458 int16_t l2 = (accumulator_l >> 6) - 32768;
459 int16_t r2 = (accumulator_r >> 6) - 32768;
460 soundbuf[emitted++] = l2;
461 soundbuf[emitted++] = r2;
462 information_dispatch::do_sample(l2, r2);
463 accumulator_l = accumulator_r = 0;
464 accumulator_s = 0;
467 audioapi_submit_buffer(soundbuf, emitted / 2, true, 32768);
468 ecore_callbacks->timer_tick(samples_emitted, 2097152);
469 frame_overflow += samples_emitted;
470 if(frame_overflow >= SAMPLES_PER_FRAME) {
471 frame_overflow -= SAMPLES_PER_FRAME;
472 break;
475 framebuffer_info inf;
476 inf.type = &_pixel_format_rgb32;
477 inf.mem = const_cast<char*>(reinterpret_cast<const char*>(primary_framebuffer));
478 inf.physwidth = 160;
479 inf.physheight = 144;
480 inf.physstride = 640;
481 inf.width = 160;
482 inf.height = 144;
483 inf.stride = 640;
484 inf.offset_x = 0;
485 inf.offset_y = 0;
487 framebuffer_raw ls(inf);
488 ecore_callbacks->output_frame(ls, 262144, 4389);
491 std::list<vma_info> get_vma_list()
493 std::list<vma_info> vmas;
494 if(!internal_rom)
495 return vmas;
496 vma_info sram;
497 vma_info wram;
498 vma_info vram;
499 vma_info ioamhram;
500 vma_info rom;
502 auto g = instance->getSaveRam();
503 sram.name = "SRAM";
504 sram.base = 0x20000;
505 sram.size = g.second;
506 sram.backing_ram = g.first;
507 sram.native_endian = false;
508 sram.readonly = false;
509 sram.iospace_rw = NULL;
511 auto g2 = instance->getWorkRam();
512 wram.name = "WRAM";
513 wram.base = 0;
514 wram.size = g2.second;
515 wram.backing_ram = g2.first;
516 wram.native_endian = false;
517 wram.readonly = false;
518 wram.iospace_rw = NULL;
520 auto g3 = instance->getVideoRam();
521 vram.name = "VRAM";
522 vram.base = 0x10000;
523 vram.size = g3.second;
524 vram.backing_ram = g3.first;
525 vram.native_endian = false;
526 vram.readonly = false;
527 vram.iospace_rw = NULL;
529 auto g4 = instance->getIoRam();
530 ioamhram.name = "IOAMHRAM";
531 ioamhram.base = 0x18000;
532 ioamhram.size = g4.second;
533 ioamhram.backing_ram = g4.first;
534 ioamhram.native_endian = false;
535 ioamhram.readonly = false;
536 ioamhram.iospace_rw = NULL;
538 rom.name = "ROM";
539 rom.base = 0x80000000;
540 rom.size = romdata.size();
541 rom.backing_ram = (void*)&romdata[0];
542 rom.native_endian = false;
543 rom.readonly = true;
544 rom.iospace_rw = NULL;
546 if(sram.size)
547 vmas.push_back(sram);
548 vmas.push_back(wram);
549 vmas.push_back(rom);
550 vmas.push_back(vram);
551 vmas.push_back(ioamhram);
552 return vmas;
555 std::set<std::string> get_sram_set()
557 std::set<std::string> s;
558 if(!internal_rom)
559 return s;
560 auto g = instance->getSaveRam();
561 if(g.second)
562 s.insert("main");
563 s.insert("rtc");
564 return s;
567 std::map<std::string, std::vector<char>> save_sram() throw(std::bad_alloc)
569 std::map<std::string, std::vector<char>> s;
570 if(!internal_rom)
571 return s;
572 auto g = instance->getSaveRam();
573 s["main"].resize(g.second);
574 memcpy(&s["main"][0], g.first, g.second);
575 s["rtc"].resize(8);
576 time_t timebase = instance->getRtcBase();
577 for(size_t i = 0; i < 8; i++)
578 s["rtc"][i] = ((unsigned long long)timebase >> (8 * i));
579 return s;
582 void load_sram(std::map<std::string, std::vector<char>>& sram) throw(std::bad_alloc)
584 if(!internal_rom)
585 return;
586 std::vector<char> x = sram.count("main") ? sram["main"] : std::vector<char>();
587 std::vector<char> x2 = sram.count("rtc") ? sram["rtc"] : std::vector<char>();
588 auto g = instance->getSaveRam();
589 if(x.size()) {
590 if(x.size() != g.second)
591 messages << "WARNING: SRAM 'main': Loaded " << x.size()
592 << " bytes, but the SRAM is " << g.second << "." << std::endl;
593 memcpy(g.first, &x[0], min(x.size(), g.second));
595 if(x2.size()) {
596 time_t timebase = 0;
597 for(size_t i = 0; i < 8 && i < x2.size(); i++)
598 timebase |= (unsigned long long)(unsigned char)x2[i] << (8 * i);
599 instance->setRtcBase(timebase);
603 unsigned core_get_poll_flag()
605 return 2;
608 void core_set_poll_flag(unsigned pflag)
613 std::vector<char> cmp_save;
615 function_ptr_command<> cmp_save1(lsnes_cmd, "set-cmp-save", "", "\n", []() throw(std::bad_alloc, std::runtime_error) {
616 if(!internal_rom)
617 return;
618 instance->saveState(cmp_save);
621 function_ptr_command<> cmp_save2(lsnes_cmd, "do-cmp-save", "", "\n", []() throw(std::bad_alloc, std::runtime_error) {
622 std::vector<char> x;
623 if(!internal_rom)
624 return;
625 instance->saveState(x, cmp_save);
628 void core_serialize(std::vector<char>& out)
630 if(!internal_rom)
631 throw std::runtime_error("Can't save without ROM");
632 instance->saveState(out);
633 size_t osize = out.size();
634 out.resize(osize + 4 * sizeof(primary_framebuffer) / sizeof(primary_framebuffer[0]));
635 for(size_t i = 0; i < sizeof(primary_framebuffer) / sizeof(primary_framebuffer[0]); i++)
636 write32ube(&out[osize + 4 * i], primary_framebuffer[i]);
637 out.push_back(frame_overflow >> 8);
638 out.push_back(frame_overflow);
641 void core_unserialize(const char* in, size_t insize)
643 if(!internal_rom)
644 throw std::runtime_error("Can't load without ROM");
645 size_t foffset = insize - 2 - 4 * sizeof(primary_framebuffer) / sizeof(primary_framebuffer[0]);
646 std::vector<char> tmp;
647 tmp.resize(foffset);
648 memcpy(&tmp[0], in, foffset);
649 instance->loadState(tmp);
650 for(size_t i = 0; i < sizeof(primary_framebuffer) / sizeof(primary_framebuffer[0]); i++)
651 primary_framebuffer[i] = read32ube(&in[foffset + 4 * i]);
653 unsigned x1 = (unsigned char)in[insize - 2];
654 unsigned x2 = (unsigned char)in[insize - 1];
655 frame_overflow = x1 * 256 + x2;
656 do_reset_flag = false;
659 std::pair<uint32_t, uint32_t> get_scale_factors(uint32_t width, uint32_t height)
661 return std::make_pair(max(512 / width, (uint32_t)1), max(448 / height, (uint32_t)1));
664 std::pair<uint64_t, uint64_t> core_get_bus_map()
666 return std::make_pair(0, 0);
669 emucore_callbacks::~emucore_callbacks() throw() {}
671 struct emucore_callbacks* ecore_callbacks;
672 #endif