Remove export for core_set_region, there's no such function anymore
[lsnes.git] / src / core / gambatte.cpp
blob9f009c07bb71abef1d06195891a62ea2f31d54c2
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 const char* buttonnames[] = {"left", "right", "up", "down", "A", "B", "select", "start"};
102 void system_write(unsigned char* buffer, unsigned idx, unsigned ctrl, short x) throw()
104 if(idx < 2 && ctrl < 8)
105 if(x)
106 buffer[idx] |= (1 << ctrl);
107 else
108 buffer[idx] &= ~(1 << ctrl);
111 short system_read(const unsigned char* buffer, unsigned idx, unsigned ctrl) throw()
113 short y = 0;
114 if(idx < 2 && ctrl < 8)
115 y = ((buffer[idx] >> ctrl) & 1) ? 1 : 0;
116 return y;
119 size_t system_deserialize(unsigned char* buffer, const char* textbuf)
121 memset(buffer, 0, 2);
122 size_t ptr = 0;
123 if(read_button_value(textbuf, ptr))
124 buffer[0] |= 1;
125 if(read_button_value(textbuf, ptr))
126 buffer[0] |= 2;
127 skip_rest_of_field(textbuf, ptr, true);
128 for(unsigned i = 0; i < 8; i++)
129 if(read_button_value(textbuf, ptr))
130 buffer[1] |= (1 << i);
131 skip_rest_of_field(textbuf, ptr, false);
132 return ptr;
135 const char* button_symbols = "ABsSrlud";
137 void system_display(const unsigned char* buffer, unsigned idx, char* buf)
139 if(idx > 1)
140 sprintf(buf, "");
141 else if(idx == 1) {
142 for(unsigned i = 0; i < 8; i++)
143 buf[i] = ((buffer[1] & (1 << i)) != 0) ? button_symbols[i] : '-';
144 buf[8] = '\0';
145 } else
146 sprintf(buf, "%c%c", ((buffer[0] & 1) ? 'F' : '.'), ((buffer[0] & 2) ? 'R' : '.'));
149 size_t system_serialize(const unsigned char* buffer, char* textbuf)
151 char tmp[128];
152 sprintf(tmp, "%c%c|", ((buffer[0] & 1) ? 'F' : '.'), ((buffer[0] & 2) ? 'R' : '.'));
153 for(unsigned i = 0; i < 8; i++)
154 tmp[i + 3] = ((buffer[1] & (1 << i)) != 0) ? button_symbols[i] : '.';
155 tmp[11] = 0;
156 size_t len = strlen(tmp);
157 memcpy(textbuf, tmp, len);
158 return len;
161 unsigned _used_indices(unsigned c)
163 return c ? ((c == 1) ? 8 : 0) : 2;
166 port_controller_button gamepad_A = {port_controller_button::TYPE_BUTTON, "A"};
167 port_controller_button gamepad_B = {port_controller_button::TYPE_BUTTON, "B"};
168 port_controller_button gamepad_s = {port_controller_button::TYPE_BUTTON, "select"};
169 port_controller_button gamepad_S = {port_controller_button::TYPE_BUTTON, "start"};
170 port_controller_button gamepad_u = {port_controller_button::TYPE_BUTTON, "up"};
171 port_controller_button gamepad_d = {port_controller_button::TYPE_BUTTON, "down"};
172 port_controller_button gamepad_l = {port_controller_button::TYPE_BUTTON, "left"};
173 port_controller_button gamepad_r = {port_controller_button::TYPE_BUTTON, "right"};
174 port_controller_button* gamepad_buttons[] = {
175 &gamepad_A, &gamepad_B, &gamepad_s, &gamepad_S,
176 &gamepad_r, &gamepad_l, &gamepad_u, &gamepad_d
178 port_controller_button* none_buttons[] = {};
179 port_controller system_controller = {"system", "system", 0, none_buttons};
180 port_controller gb_buttons = {"gb", "gamepad", 8, gamepad_buttons};
181 port_controller* gambatte_controllers[] = {&system_controller, &gb_buttons};
182 port_controller_set _controller_info = {2, gambatte_controllers};
184 struct porttype_system : public port_type
186 porttype_system() : port_type("<SYSTEM>", "<SYSTEM>", 9999, 2)
188 write = system_write;
189 read = system_read;
190 display = system_display;
191 serialize = system_serialize;
192 deserialize = system_deserialize;
193 legal = generic_port_legal<1>;
194 used_indices = _used_indices;
195 controller_info = &_controller_info;
197 } psystem;
199 int load_rom_common(core_romimage* img, unsigned flags, uint64_t rtc_sec, uint64_t rtc_subsec,
200 core_type* inttype)
202 const char* markup = img[0].markup;
203 int flags2 = 0;
204 if(markup) {
205 flags2 = atoi(markup);
206 flags2 &= 4;
208 flags |= flags2;
209 const unsigned char* data = img[0].data;
210 size_t size = img[0].size;
212 //Reset it really.
213 instance->~GB();
214 memset(instance, 0, sizeof(gambatte::GB));
215 new(instance) gambatte::GB;
216 instance->setInputGetter(&getinput);
217 instance->set_walltime_fn(walltime_fn);
218 memset(primary_framebuffer, 0, sizeof(primary_framebuffer));
219 frame_overflow = 0;
221 rtc_fixed = true;
222 rtc_fixed_val = rtc_sec;
223 instance->load(data, size, flags);
224 rtc_fixed = false;
225 romdata.resize(size);
226 memcpy(&romdata[0], data, size);
227 internal_rom = inttype;
228 do_reset_flag = false;
229 return 1;
232 int load_rom_dmg(core_romimage* img, std::map<std::string, std::string>& settings, uint64_t rtc_sec,
233 uint64_t rtc_subsec)
235 return load_rom_common(img, gambatte::GB::FORCE_DMG, rtc_sec, rtc_subsec, &type_dmg);
238 int load_rom_gbc(core_romimage* img, std::map<std::string, std::string>& settings, uint64_t rtc_sec,
239 uint64_t rtc_subsec)
241 return load_rom_common(img, 0, rtc_sec, rtc_subsec, &type_gbc);
244 int load_rom_gbc_gba(core_romimage* img, std::map<std::string, std::string>& settings, uint64_t rtc_sec,
245 uint64_t rtc_subsec)
247 return load_rom_common(img, gambatte::GB::GBA_CGB, rtc_sec, rtc_subsec, &type_gbc_gba);
250 port_index_triple t(unsigned p, unsigned c, unsigned i, bool nl)
252 port_index_triple x;
253 x.port = p;
254 x.controller = c;
255 x.control = i;
256 x.marks_nonlag = nl;
257 return x;
260 controller_set _controllerconfig(std::map<std::string, std::string>& settings)
262 std::map<std::string, std::string> _settings = settings;
263 controller_set r;
264 r.ports.push_back(&psystem);
265 for(unsigned i = 0; i < 4; i++)
266 r.portindex.indices.push_back(t(0, 0, i, false));
267 for(unsigned i = 0; i < 8; i++)
268 r.portindex.indices.push_back(t(0, 1, i, true));
269 r.portindex.logical_map.push_back(std::make_pair(0, 1));
270 r.portindex.pcid_map.push_back(std::make_pair(0, 1));
271 return r;
275 unsigned world_compatible[] = {0, UINT_MAX};
276 core_region_params _region_world = {
277 "world", "World", 1, 0, false, {35112, 2097152, 16742706, 626688}, world_compatible
279 core_romimage_info_params _image_rom = {
280 "rom", "Cartridge ROM", 1, 0, 0
283 core_region region_world(_region_world);
284 core_romimage_info image_rom_dmg(_image_rom);
285 core_romimage_info image_rom_gbc(_image_rom);
286 core_romimage_info image_rom_gbca(_image_rom);
287 core_region* regions_gambatte[] = {&region_world, NULL};
288 core_romimage_info* dmg_images[] = {&image_rom_dmg, NULL};
289 core_romimage_info* gbc_images[] = {&image_rom_gbc, NULL};
290 core_romimage_info* gbca_images[] = {&image_rom_gbca, NULL};
292 bool core_set_region(core_region& region)
294 return (&region == &region_world);
297 core_type_params _type_dmg = {
298 "dmg", "Game Boy", 1, 1, load_rom_dmg, _controllerconfig, "gb;dmg", NULL,
299 regions_gambatte, dmg_images, &gambatte_settings, core_set_region
301 core_type_params _type_gbc = {
302 "gbc", "Game Boy Color", 0, 1, load_rom_gbc, _controllerconfig, "gbc;cgb", NULL,
303 regions_gambatte, gbc_images, &gambatte_settings, core_set_region
305 core_type_params _type_gbc_gba = {
306 "gbc_gba", "Game Boy Color (GBA)", 2, 1, load_rom_gbc_gba, _controllerconfig, "", NULL,
307 regions_gambatte, gbca_images, &gambatte_settings, core_set_region
309 core_type type_dmg(_type_dmg);
310 core_type type_gbc(_type_gbc);
311 core_type type_gbc_gba(_type_gbc_gba);
312 core_sysregion sr1("gdmg", type_dmg, region_world);
313 core_sysregion sr2("ggbc", type_gbc, region_world);
314 core_sysregion sr3("ggbca", type_gbc_gba, region_world);
317 port_type* core_port_types[] = {
318 &psystem, NULL
321 std::string get_logical_button_name(unsigned lbid) throw(std::bad_alloc)
323 if(lbid >= sizeof(buttonnames) / sizeof(buttonnames[0]))
324 return "";
325 return buttonnames[lbid];
328 uint32_t get_snes_cpu_rate() { return 0; }
329 uint32_t get_snes_apu_rate() { return 0; }
330 std::string get_core_identifier()
332 return "libgambatte "+gambatte::GB::version();
335 core_region& core_get_region()
337 return region_world;
340 std::pair<uint32_t, uint32_t> get_video_rate()
342 return std::make_pair(262144, 4389);
345 std::pair<uint32_t, uint32_t> get_audio_rate()
347 return std::make_pair(32768, 1);
350 void core_runtosave()
354 void do_basic_core_init()
356 instance = new gambatte::GB;
357 instance->setInputGetter(&getinput);
358 instance->set_walltime_fn(walltime_fn);
361 void core_power()
365 void core_unload_cartridge()
369 void set_preload_settings()
373 void core_install_handler()
377 void core_uninstall_handler()
381 void core_emulate_frame_nocore()
383 do_reset_flag = -1;
384 init_norom_framebuffer();
385 while(true) {
386 int16_t soundbuf[(SAMPLES_PER_FRAME + 63) / 32];
387 size_t emitted = 0;
388 unsigned samples_emitted = SAMPLES_PER_FRAME - frame_overflow;
389 for(unsigned i = 0; i < samples_emitted; i++) {
390 accumulator_l += 32768;
391 accumulator_r += 32768;
392 accumulator_s++;
393 if((accumulator_s & 63) == 0) {
394 int16_t l2 = (accumulator_l >> 6) - 32768;
395 int16_t r2 = (accumulator_r >> 6) - 32768;
396 soundbuf[emitted++] = l2;
397 soundbuf[emitted++] = r2;
398 information_dispatch::do_sample(l2, r2);
399 accumulator_l = accumulator_r = 0;
400 accumulator_s = 0;
403 audioapi_submit_buffer(soundbuf, emitted / 2, true, 32768);
404 ecore_callbacks->timer_tick(samples_emitted, 2097152);
405 frame_overflow = 0;
406 break;
408 framebuffer_info inf;
409 inf.type = &_pixel_format_rgb32;
410 inf.mem = const_cast<char*>(reinterpret_cast<const char*>(norom_framebuffer));
411 inf.physwidth = 160;
412 inf.physheight = 144;
413 inf.physstride = 640;
414 inf.width = 160;
415 inf.height = 144;
416 inf.stride = 640;
417 inf.offset_x = 0;
418 inf.offset_y = 0;
420 framebuffer_raw ls(inf);
421 ecore_callbacks->output_frame(ls, 262144, 4389);
424 void core_request_reset(long delay)
426 do_reset_flag = true;
429 void core_emulate_frame()
431 if(!internal_rom) {
432 core_emulate_frame_nocore();
433 return;
436 int16_t reset = ecore_callbacks->set_input(0, 0, 1, do_reset_flag ? 1 : 0);
437 if(reset) {
438 instance->reset();
439 messages << "GB(C) reset" << std::endl;
441 do_reset_flag = false;
443 uint32_t samplebuffer[SAMPLES_PER_FRAME + 2064];
444 while(true) {
445 int16_t soundbuf[(SAMPLES_PER_FRAME + 63) / 32 + 66];
446 size_t emitted = 0;
447 unsigned samples_emitted = SAMPLES_PER_FRAME - frame_overflow;
448 long ret = instance->runFor(primary_framebuffer, 160, samplebuffer, samples_emitted);
449 for(unsigned i = 0; i < samples_emitted; i++) {
450 uint32_t l = (int32_t)(int16_t)(samplebuffer[i]) + 32768;
451 uint32_t r = (int32_t)(int16_t)(samplebuffer[i] >> 16) + 32768;
452 accumulator_l += l;
453 accumulator_r += r;
454 accumulator_s++;
455 if((accumulator_s & 63) == 0) {
456 int16_t l2 = (accumulator_l >> 6) - 32768;
457 int16_t r2 = (accumulator_r >> 6) - 32768;
458 soundbuf[emitted++] = l2;
459 soundbuf[emitted++] = r2;
460 information_dispatch::do_sample(l2, r2);
461 accumulator_l = accumulator_r = 0;
462 accumulator_s = 0;
465 audioapi_submit_buffer(soundbuf, emitted / 2, true, 32768);
466 ecore_callbacks->timer_tick(samples_emitted, 2097152);
467 frame_overflow += samples_emitted;
468 if(frame_overflow >= SAMPLES_PER_FRAME) {
469 frame_overflow -= SAMPLES_PER_FRAME;
470 break;
473 framebuffer_info inf;
474 inf.type = &_pixel_format_rgb32;
475 inf.mem = const_cast<char*>(reinterpret_cast<const char*>(primary_framebuffer));
476 inf.physwidth = 160;
477 inf.physheight = 144;
478 inf.physstride = 640;
479 inf.width = 160;
480 inf.height = 144;
481 inf.stride = 640;
482 inf.offset_x = 0;
483 inf.offset_y = 0;
485 framebuffer_raw ls(inf);
486 ecore_callbacks->output_frame(ls, 262144, 4389);
489 std::list<vma_info> get_vma_list()
491 std::list<vma_info> vmas;
492 if(!internal_rom)
493 return vmas;
494 vma_info sram;
495 vma_info wram;
496 vma_info vram;
497 vma_info ioamhram;
498 vma_info rom;
500 auto g = instance->getSaveRam();
501 sram.name = "SRAM";
502 sram.base = 0x20000;
503 sram.size = g.second;
504 sram.backing_ram = g.first;
505 sram.native_endian = false;
506 sram.readonly = false;
507 sram.iospace_rw = NULL;
509 auto g2 = instance->getWorkRam();
510 wram.name = "WRAM";
511 wram.base = 0;
512 wram.size = g2.second;
513 wram.backing_ram = g2.first;
514 wram.native_endian = false;
515 wram.readonly = false;
516 wram.iospace_rw = NULL;
518 auto g3 = instance->getVideoRam();
519 vram.name = "VRAM";
520 vram.base = 0x10000;
521 vram.size = g3.second;
522 vram.backing_ram = g3.first;
523 vram.native_endian = false;
524 vram.readonly = false;
525 vram.iospace_rw = NULL;
527 auto g4 = instance->getIoRam();
528 ioamhram.name = "IOAMHRAM";
529 ioamhram.base = 0x18000;
530 ioamhram.size = g4.second;
531 ioamhram.backing_ram = g4.first;
532 ioamhram.native_endian = false;
533 ioamhram.readonly = false;
534 ioamhram.iospace_rw = NULL;
536 rom.name = "ROM";
537 rom.base = 0x80000000;
538 rom.size = romdata.size();
539 rom.backing_ram = (void*)&romdata[0];
540 rom.native_endian = false;
541 rom.readonly = true;
542 rom.iospace_rw = NULL;
544 if(sram.size)
545 vmas.push_back(sram);
546 vmas.push_back(wram);
547 vmas.push_back(rom);
548 vmas.push_back(vram);
549 vmas.push_back(ioamhram);
550 return vmas;
553 std::set<std::string> get_sram_set()
555 std::set<std::string> s;
556 if(!internal_rom)
557 return s;
558 auto g = instance->getSaveRam();
559 if(g.second)
560 s.insert("main");
561 s.insert("rtc");
562 return s;
565 std::map<std::string, std::vector<char>> save_sram() throw(std::bad_alloc)
567 std::map<std::string, std::vector<char>> s;
568 if(!internal_rom)
569 return s;
570 auto g = instance->getSaveRam();
571 s["main"].resize(g.second);
572 memcpy(&s["main"][0], g.first, g.second);
573 s["rtc"].resize(8);
574 time_t timebase = instance->getRtcBase();
575 for(size_t i = 0; i < 8; i++)
576 s["rtc"][i] = ((unsigned long long)timebase >> (8 * i));
577 return s;
580 void load_sram(std::map<std::string, std::vector<char>>& sram) throw(std::bad_alloc)
582 if(!internal_rom)
583 return;
584 std::vector<char> x = sram.count("main") ? sram["main"] : std::vector<char>();
585 std::vector<char> x2 = sram.count("rtc") ? sram["rtc"] : std::vector<char>();
586 auto g = instance->getSaveRam();
587 if(x.size()) {
588 if(x.size() != g.second)
589 messages << "WARNING: SRAM 'main': Loaded " << x.size()
590 << " bytes, but the SRAM is " << g.second << "." << std::endl;
591 memcpy(g.first, &x[0], min(x.size(), g.second));
593 if(x2.size()) {
594 time_t timebase = 0;
595 for(size_t i = 0; i < 8 && i < x2.size(); i++)
596 timebase |= (unsigned long long)(unsigned char)x2[i] << (8 * i);
597 instance->setRtcBase(timebase);
601 unsigned core_get_poll_flag()
603 return 2;
606 void core_set_poll_flag(unsigned pflag)
611 std::vector<char> cmp_save;
613 function_ptr_command<> cmp_save1(lsnes_cmd, "set-cmp-save", "", "\n", []() throw(std::bad_alloc, std::runtime_error) {
614 if(!internal_rom)
615 return;
616 instance->saveState(cmp_save);
619 function_ptr_command<> cmp_save2(lsnes_cmd, "do-cmp-save", "", "\n", []() throw(std::bad_alloc, std::runtime_error) {
620 std::vector<char> x;
621 if(!internal_rom)
622 return;
623 instance->saveState(x, cmp_save);
626 void core_serialize(std::vector<char>& out)
628 if(!internal_rom)
629 throw std::runtime_error("Can't save without ROM");
630 instance->saveState(out);
631 size_t osize = out.size();
632 out.resize(osize + 4 * sizeof(primary_framebuffer) / sizeof(primary_framebuffer[0]));
633 for(size_t i = 0; i < sizeof(primary_framebuffer) / sizeof(primary_framebuffer[0]); i++)
634 write32ube(&out[osize + 4 * i], primary_framebuffer[i]);
635 out.push_back(frame_overflow >> 8);
636 out.push_back(frame_overflow);
639 void core_unserialize(const char* in, size_t insize)
641 if(!internal_rom)
642 throw std::runtime_error("Can't load without ROM");
643 size_t foffset = insize - 2 - 4 * sizeof(primary_framebuffer) / sizeof(primary_framebuffer[0]);
644 std::vector<char> tmp;
645 tmp.resize(foffset);
646 memcpy(&tmp[0], in, foffset);
647 instance->loadState(tmp);
648 for(size_t i = 0; i < sizeof(primary_framebuffer) / sizeof(primary_framebuffer[0]); i++)
649 primary_framebuffer[i] = read32ube(&in[foffset + 4 * i]);
651 unsigned x1 = (unsigned char)in[insize - 2];
652 unsigned x2 = (unsigned char)in[insize - 1];
653 frame_overflow = x1 * 256 + x2;
654 do_reset_flag = false;
657 std::pair<uint32_t, uint32_t> get_scale_factors(uint32_t width, uint32_t height)
659 return std::make_pair(max(512 / width, (uint32_t)1), max(448 / height, (uint32_t)1));
662 std::pair<uint64_t, uint64_t> core_get_bus_map()
664 return std::make_pair(0, 0);
667 emucore_callbacks::~emucore_callbacks() throw() {}
669 struct emucore_callbacks* ecore_callbacks;
670 #endif