Revert "Refactor porttype_info into library/ (as port_type)"
[lsnes.git] / src / core / gambatte.cpp
blob6b3880c1256a43aadbc76e0712ca751d6798339c
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 "library/pixfmt-rgb32.hpp"
17 #include "library/string.hpp"
18 #include "library/serialization.hpp"
19 #include "library/minmax.hpp"
20 #include "library/framebuffer.hpp"
21 #define HAVE_CSTDINT
22 #include "libgambatte/include/gambatte.h"
24 #define SAMPLES_PER_FRAME 35112
26 #define LOGICAL_BUTTON_LEFT 0
27 #define LOGICAL_BUTTON_RIGHT 1
28 #define LOGICAL_BUTTON_UP 2
29 #define LOGICAL_BUTTON_DOWN 3
30 #define LOGICAL_BUTTON_A 4
31 #define LOGICAL_BUTTON_B 5
32 #define LOGICAL_BUTTON_SELECT 6
33 #define LOGICAL_BUTTON_START 7
35 const char* button_symbols = "ABsSrlud";
37 namespace
39 int regions_compatible(unsigned rom, unsigned run)
41 return 1;
44 unsigned header_fn(size_t r)
46 return 0;
49 unsigned int_pflag;
50 core_type* internal_rom = NULL;
51 extern core_type type_dmg;
52 extern core_type type_gbc;
53 extern core_type type_gbc_gba;
54 bool rtc_fixed;
55 time_t rtc_fixed_val;
56 gambatte::GB* instance;
57 unsigned frame_overflow = 0;
58 std::vector<unsigned char> romdata;
59 uint32_t primary_framebuffer[160*144];
60 uint32_t norom_framebuffer[160*144];
61 uint32_t accumulator_l = 0;
62 uint32_t accumulator_r = 0;
63 unsigned accumulator_s = 0;
65 void init_norom_framebuffer()
67 static bool done = false;
68 if(done)
69 return;
70 done = true;
71 for(size_t i = 0; i < 160 * 144; i++)
72 norom_framebuffer[i] = 0xFF8080;
75 time_t walltime_fn()
77 if(rtc_fixed)
78 return rtc_fixed_val;
79 if(ecore_callbacks)
80 return ecore_callbacks->get_time();
81 else
82 return time(0);
85 class myinput : public gambatte::InputGetter
87 public:
88 unsigned operator()()
90 unsigned v = 0;
91 for(unsigned i = 0; i < 8; i++) {
92 int_pflag = int_pflag ? int_pflag : 1;
93 if(ecore_callbacks->get_input(0, 0, i))
94 v |= (1 << i);
96 return v;
98 } getinput;
100 int load_rom_common(core_romimage* img, unsigned flags, uint64_t rtc_sec, uint64_t rtc_subsec,
101 core_type* inttype)
103 const char* markup = img[0].markup;
104 int flags2 = 0;
105 if(markup) {
106 flags2 = atoi(markup);
107 flags2 &= 4;
109 flags |= flags2;
110 const unsigned char* data = img[0].data;
111 size_t size = img[0].size;
113 //Reset it really.
114 instance->~GB();
115 memset(instance, 0, sizeof(gambatte::GB));
116 new(instance) gambatte::GB;
117 instance->setInputGetter(&getinput);
118 instance->set_walltime_fn(walltime_fn);
119 memset(primary_framebuffer, 0, sizeof(primary_framebuffer));
120 frame_overflow = 0;
122 rtc_fixed = true;
123 rtc_fixed_val = rtc_sec;
124 instance->load(data, size, flags);
125 rtc_fixed = false;
126 romdata.resize(size);
127 memcpy(&romdata[0], data, size);
128 internal_rom = inttype;
129 return 1;
132 int load_rom_dmg(core_romimage* img, uint64_t rtc_sec, uint64_t rtc_subsec)
134 return load_rom_common(img, gambatte::GB::FORCE_DMG, rtc_sec, rtc_subsec, &type_dmg);
137 int load_rom_gbc(core_romimage* img, uint64_t rtc_sec, uint64_t rtc_subsec)
139 return load_rom_common(img, 0, rtc_sec, rtc_subsec, &type_gbc);
142 int load_rom_gbc_gba(core_romimage* img, uint64_t rtc_sec, uint64_t rtc_subsec)
144 return load_rom_common(img, gambatte::GB::GBA_CGB, rtc_sec, rtc_subsec, &type_gbc_gba);
147 uint64_t magic[4] = {35112, 2097152, 16742706, 626688};
149 core_region region_world("world", "World", 0, 0, false, magic, regions_compatible);
150 core_romimage_info image_rom_dmg("rom", "Cartridge ROM", 1, header_fn);
151 core_romimage_info image_rom_gbc("rom", "Cartridge ROM", 1, header_fn);
152 core_romimage_info image_rom_gbca("rom", "Cartridge ROM", 1, header_fn);
153 core_type type_dmg("dmg", "Game Boy", 1, load_rom_dmg, "gb;dmg");
154 core_type type_gbc("gbc", "Game Boy Color", 0, load_rom_gbc, "gbc;cgb");
155 core_type type_gbc_gba("gbc_gba", "Game Boy Color (GBA)", 2, load_rom_gbc_gba, "");
156 core_type_region_bind bind_A(type_dmg, region_world);
157 core_type_region_bind bind_B(type_gbc, region_world);
158 core_type_region_bind bind_C(type_gbc_gba, region_world);
159 core_type_image_bind bind_D(type_dmg, image_rom_dmg, 0);
160 core_type_image_bind bind_E(type_gbc, image_rom_gbc, 0);
161 core_type_image_bind bind_F(type_gbc_gba, image_rom_gbca, 0);
162 core_sysregion sr1("gdmg", type_dmg, region_world);
163 core_sysregion sr2("ggbc", type_gbc, region_world);
164 core_sysregion sr3("ggbca", type_gbc_gba, region_world);
166 const char* buttonnames[] = {"left", "right", "up", "down", "A", "B", "select", "start"};
168 void _set_core_controller(unsigned port) throw() {}
170 int get_button_id_gamepad(unsigned controller, unsigned lbid) throw()
172 if(controller)
173 return -1;
174 if(lbid == LOGICAL_BUTTON_A) return 0;
175 if(lbid == LOGICAL_BUTTON_B) return 1;
176 if(lbid == LOGICAL_BUTTON_SELECT) return 2;
177 if(lbid == LOGICAL_BUTTON_START) return 3;
178 if(lbid == LOGICAL_BUTTON_RIGHT) return 4;
179 if(lbid == LOGICAL_BUTTON_LEFT) return 5;
180 if(lbid == LOGICAL_BUTTON_UP) return 6;
181 if(lbid == LOGICAL_BUTTON_DOWN) return 7;
182 return -1;
186 int get_button_id_none(unsigned controller, unsigned lbid) throw()
188 return -1;
191 struct porttype_gamepad : public porttype_info
193 porttype_gamepad() : porttype_info("gamepad", "Gamepad", 1, generic_port_size<1, 0, 8>())
195 write = generic_port_write<1, 0, 8>;
196 read = generic_port_read<1, 0, 8>;
197 display = generic_port_display<1, 0, 8, 0>;
198 serialize = generic_port_serialize<1, 0, 8, 0>;
199 deserialize = generic_port_deserialize<1, 0, 8>;
200 legal = generic_port_legal<1>;
201 deviceflags = generic_port_deviceflags<1, 1>;
202 button_id = get_button_id_gamepad;
203 ctrlname = "gamepad";
204 controllers = 1;
205 set_core_controller = _set_core_controller;
208 } gamepad;
210 struct porttype_none : public porttype_info
212 porttype_none() : porttype_info("none", "None", 0, generic_port_size<0, 0, 0>())
214 write = generic_port_write<0, 0, 0>;
215 read = generic_port_read<0, 0, 0>;
216 display = generic_port_display<0, 0, 0, 0>;
217 serialize = generic_port_serialize<0, 0, 0, 0>;
218 deserialize = generic_port_deserialize<0, 0, 0>;
219 legal = generic_port_legal<2>;
220 deviceflags = generic_port_deviceflags<0, 0>;
221 button_id = get_button_id_none;
222 ctrlname = "";
223 controllers = 0;
224 set_core_controller = _set_core_controller;
226 } none;
230 std::string get_logical_button_name(unsigned lbid) throw(std::bad_alloc)
232 if(lbid >= sizeof(buttonnames) / sizeof(buttonnames[0]))
233 return "";
234 return buttonnames[lbid];
237 uint32_t get_snes_cpu_rate() { return 0; }
238 uint32_t get_snes_apu_rate() { return 0; }
239 std::string get_core_identifier()
241 return "libgambatte "+gambatte::GB::version();
244 std::pair<unsigned, unsigned> get_core_logical_controller_limits()
246 return std::make_pair(1, 8);
249 bool get_core_need_analog()
251 return false;
254 std::string get_core_default_port(unsigned port)
256 return (port == 0) ? "gamepad" : "none";
259 core_region& core_get_region()
261 return region_world;
264 std::pair<uint32_t, uint32_t> get_video_rate()
266 return std::make_pair(262144, 4389);
269 std::pair<uint32_t, uint32_t> get_audio_rate()
271 return std::make_pair(32768, 1);
274 bool core_set_region(core_region& region)
276 return (&region == &region_world);
279 std::pair<bool, uint32_t> core_emulate_cycles(uint32_t cycles)
281 messages << "Delayed resets are not supported";
282 return std::make_pair(false, 0);
285 void core_runtosave()
289 void core_reset()
291 if(!internal_rom)
292 return;
293 instance->reset();
296 void do_basic_core_init()
298 instance = new gambatte::GB;
299 instance->setInputGetter(&getinput);
300 instance->set_walltime_fn(walltime_fn);
303 void core_power()
307 void core_unload_cartridge()
311 void set_preload_settings()
315 void core_install_handler()
319 void core_uninstall_handler()
323 void core_emulate_frame_nocore()
325 init_norom_framebuffer();
326 while(true) {
327 int16_t soundbuf[(SAMPLES_PER_FRAME + 63) / 32];
328 size_t emitted = 0;
329 unsigned samples_emitted = SAMPLES_PER_FRAME - frame_overflow;
330 for(unsigned i = 0; i < samples_emitted; i++) {
331 accumulator_l += 32768;
332 accumulator_r += 32768;
333 accumulator_s++;
334 if((accumulator_s & 63) == 0) {
335 int16_t l2 = (accumulator_l >> 6) - 32768;
336 int16_t r2 = (accumulator_r >> 6) - 32768;
337 soundbuf[emitted++] = l2;
338 soundbuf[emitted++] = r2;
339 information_dispatch::do_sample(l2, r2);
340 accumulator_l = accumulator_r = 0;
341 accumulator_s = 0;
344 audioapi_submit_buffer(soundbuf, emitted / 2, true, 32768);
345 ecore_callbacks->timer_tick(samples_emitted, 2097152);
346 frame_overflow = 0;
347 break;
349 framebuffer_info inf;
350 inf.type = &_pixel_format_rgb32;
351 inf.mem = const_cast<char*>(reinterpret_cast<const char*>(norom_framebuffer));
352 inf.physwidth = 160;
353 inf.physheight = 144;
354 inf.physstride = 640;
355 inf.width = 160;
356 inf.height = 144;
357 inf.stride = 640;
358 inf.offset_x = 0;
359 inf.offset_y = 0;
361 framebuffer_raw ls(inf);
362 ecore_callbacks->output_frame(ls, 262144, 4389);
364 void core_emulate_frame()
366 if(!internal_rom) {
367 core_emulate_frame_nocore();
368 return;
370 uint32_t samplebuffer[SAMPLES_PER_FRAME + 2064];
371 while(true) {
372 int16_t soundbuf[(SAMPLES_PER_FRAME + 63) / 32 + 66];
373 size_t emitted = 0;
374 unsigned samples_emitted = SAMPLES_PER_FRAME - frame_overflow;
375 long ret = instance->runFor(primary_framebuffer, 160, samplebuffer, samples_emitted);
376 for(unsigned i = 0; i < samples_emitted; i++) {
377 uint32_t l = (int32_t)(int16_t)(samplebuffer[i]) + 32768;
378 uint32_t r = (int32_t)(int16_t)(samplebuffer[i] >> 16) + 32768;
379 accumulator_l += l;
380 accumulator_r += r;
381 accumulator_s++;
382 if((accumulator_s & 63) == 0) {
383 int16_t l2 = (accumulator_l >> 6) - 32768;
384 int16_t r2 = (accumulator_r >> 6) - 32768;
385 soundbuf[emitted++] = l2;
386 soundbuf[emitted++] = r2;
387 information_dispatch::do_sample(l2, r2);
388 accumulator_l = accumulator_r = 0;
389 accumulator_s = 0;
392 audioapi_submit_buffer(soundbuf, emitted / 2, true, 32768);
393 ecore_callbacks->timer_tick(samples_emitted, 2097152);
394 frame_overflow += samples_emitted;
395 if(frame_overflow >= SAMPLES_PER_FRAME) {
396 frame_overflow -= SAMPLES_PER_FRAME;
397 break;
400 framebuffer_info inf;
401 inf.type = &_pixel_format_rgb32;
402 inf.mem = const_cast<char*>(reinterpret_cast<const char*>(primary_framebuffer));
403 inf.physwidth = 160;
404 inf.physheight = 144;
405 inf.physstride = 640;
406 inf.width = 160;
407 inf.height = 144;
408 inf.stride = 640;
409 inf.offset_x = 0;
410 inf.offset_y = 0;
412 framebuffer_raw ls(inf);
413 ecore_callbacks->output_frame(ls, 262144, 4389);
416 std::list<vma_info> get_vma_list()
418 std::list<vma_info> vmas;
419 if(!internal_rom)
420 return vmas;
421 vma_info sram;
422 vma_info wram;
423 vma_info vram;
424 vma_info ioamhram;
425 vma_info rom;
427 auto g = instance->getSaveRam();
428 sram.name = "SRAM";
429 sram.base = 0x20000;
430 sram.size = g.second;
431 sram.backing_ram = g.first;
432 sram.native_endian = false;
433 sram.readonly = false;
434 sram.iospace_rw = NULL;
436 auto g2 = instance->getWorkRam();
437 wram.name = "WRAM";
438 wram.base = 0;
439 wram.size = g2.second;
440 wram.backing_ram = g2.first;
441 wram.native_endian = false;
442 wram.readonly = false;
443 wram.iospace_rw = NULL;
445 auto g3 = instance->getVideoRam();
446 vram.name = "VRAM";
447 vram.base = 0x10000;
448 vram.size = g3.second;
449 vram.backing_ram = g3.first;
450 vram.native_endian = false;
451 vram.readonly = false;
452 vram.iospace_rw = NULL;
454 auto g4 = instance->getIoRam();
455 ioamhram.name = "IOAMHRAM";
456 ioamhram.base = 0x18000;
457 ioamhram.size = g4.second;
458 ioamhram.backing_ram = g4.first;
459 ioamhram.native_endian = false;
460 ioamhram.readonly = false;
461 ioamhram.iospace_rw = NULL;
463 rom.name = "ROM";
464 rom.base = 0x80000000;
465 rom.size = romdata.size();
466 rom.backing_ram = (void*)&romdata[0];
467 rom.native_endian = false;
468 rom.readonly = true;
469 rom.iospace_rw = NULL;
471 if(sram.size)
472 vmas.push_back(sram);
473 vmas.push_back(wram);
474 vmas.push_back(rom);
475 vmas.push_back(vram);
476 vmas.push_back(ioamhram);
477 return vmas;
480 std::set<std::string> get_sram_set()
482 std::set<std::string> s;
483 if(!internal_rom)
484 return s;
485 auto g = instance->getSaveRam();
486 if(g.second)
487 s.insert("main");
488 s.insert("rtc");
489 return s;
492 std::map<std::string, std::vector<char>> save_sram() throw(std::bad_alloc)
494 std::map<std::string, std::vector<char>> s;
495 if(!internal_rom)
496 return s;
497 auto g = instance->getSaveRam();
498 s["main"].resize(g.second);
499 memcpy(&s["main"][0], g.first, g.second);
500 s["rtc"].resize(8);
501 time_t timebase = instance->getRtcBase();
502 for(size_t i = 0; i < 8; i++)
503 s["rtc"][i] = ((unsigned long long)timebase >> (8 * i));
504 return s;
507 void load_sram(std::map<std::string, std::vector<char>>& sram) throw(std::bad_alloc)
509 if(!internal_rom)
510 return;
511 std::vector<char> x = sram.count("main") ? sram["main"] : std::vector<char>();
512 std::vector<char> x2 = sram.count("rtc") ? sram["rtc"] : std::vector<char>();
513 auto g = instance->getSaveRam();
514 if(x.size()) {
515 if(x.size() != g.second)
516 messages << "WARNING: SRAM 'main': Loaded " << x.size()
517 << " bytes, but the SRAM is " << g.second << "." << std::endl;
518 memcpy(g.first, &x[0], min(x.size(), g.second));
520 if(x2.size()) {
521 time_t timebase = 0;
522 for(size_t i = 0; i < 8 && i < x2.size(); i++)
523 timebase |= (unsigned long long)(unsigned char)x2[i] << (8 * i);
524 instance->setRtcBase(timebase);
528 unsigned core_get_poll_flag()
530 return int_pflag;
533 void core_set_poll_flag(unsigned pflag)
535 int_pflag = pflag;
539 std::vector<char> cmp_save;
541 function_ptr_command<> cmp_save1("set-cmp-save", "", "\n", []() throw(std::bad_alloc, std::runtime_error) {
542 if(!internal_rom)
543 return;
544 instance->saveState(cmp_save);
547 function_ptr_command<> cmp_save2("do-cmp-save", "", "\n", []() throw(std::bad_alloc, std::runtime_error) {
548 std::vector<char> x;
549 if(!internal_rom)
550 return;
551 instance->saveState(x, cmp_save);
554 void core_serialize(std::vector<char>& out)
556 if(!internal_rom)
557 throw std::runtime_error("Can't save without ROM");
558 instance->saveState(out);
559 size_t osize = out.size();
560 out.resize(osize + 4 * sizeof(primary_framebuffer) / sizeof(primary_framebuffer[0]));
561 for(size_t i = 0; i < sizeof(primary_framebuffer) / sizeof(primary_framebuffer[0]); i++)
562 write32ube(&out[osize + 4 * i], primary_framebuffer[i]);
563 out.push_back(frame_overflow >> 8);
564 out.push_back(frame_overflow);
567 void core_unserialize(const char* in, size_t insize)
569 if(!internal_rom)
570 throw std::runtime_error("Can't load without ROM");
571 size_t foffset = insize - 2 - 4 * sizeof(primary_framebuffer) / sizeof(primary_framebuffer[0]);
572 std::vector<char> tmp;
573 tmp.resize(foffset);
574 memcpy(&tmp[0], in, foffset);
575 instance->loadState(tmp);
576 for(size_t i = 0; i < sizeof(primary_framebuffer) / sizeof(primary_framebuffer[0]); i++)
577 primary_framebuffer[i] = read32ube(&in[foffset + 4 * i]);
579 unsigned x1 = (unsigned char)in[insize - 2];
580 unsigned x2 = (unsigned char)in[insize - 1];
581 frame_overflow = x1 * 256 + x2;
584 std::pair<uint32_t, uint32_t> get_scale_factors(uint32_t width, uint32_t height)
586 return std::make_pair(max(512 / width, (uint32_t)1), max(448 / height, (uint32_t)1));
589 std::pair<uint64_t, uint64_t> core_get_bus_map()
591 return std::make_pair(0, 0);
594 emucore_callbacks::~emucore_callbacks() throw() {}
596 struct emucore_callbacks* ecore_callbacks;
597 #endif