1 #ifdef CORETYPE_GAMBATTE
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"
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;
43 int regions_compatible(unsigned rom
, unsigned run
)
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
;
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;
72 for(size_t i
= 0; i
< 160 * 144; i
++)
73 norom_framebuffer
[i
] = 0xFF8080;
81 return ecore_callbacks
->get_time();
86 class myinput
: public gambatte::InputGetter
92 for(unsigned i
= 0; i
< 8; i
++) {
93 if(ecore_callbacks
->get_input(0, 1, i
))
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)
117 buffer
[idx
] |= (1 << ctrl
);
119 buffer
[idx
] &= ~(1 << ctrl
);
122 short system_read(const unsigned char* buffer
, unsigned idx
, unsigned ctrl
) throw()
125 if(idx
< 2 && ctrl
< 8)
126 y
= ((buffer
[idx
] >> ctrl
) & 1) ? 1 : 0;
130 size_t system_deserialize(unsigned char* buffer
, const char* textbuf
)
132 memset(buffer
, 0, 2);
134 if(read_button_value(textbuf
, ptr
))
136 if(read_button_value(textbuf
, ptr
))
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);
146 const char* button_symbols
= "ABsSrlud";
148 void system_display(const unsigned char* buffer
, unsigned idx
, char* buf
)
153 for(unsigned i
= 0; i
< 8; i
++)
154 buf
[i
] = ((buffer
[1] & (1 << i
)) != 0) ? button_symbols
[i
] : '-';
157 sprintf(buf
, "%c%c", ((buffer
[0] & 1) ? 'F' : '.'), ((buffer
[0] & 2) ? 'R' : '.'));
160 size_t system_serialize(const unsigned char* buffer
, char* textbuf
)
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
] : '.';
167 size_t len
= strlen(tmp
);
168 memcpy(textbuf
, tmp
, 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
;
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
;
210 int load_rom_common(core_romimage
* img
, unsigned flags
, uint64_t rtc_sec
, uint64_t rtc_subsec
,
213 const char* markup
= img
[0].markup
;
216 flags2
= atoi(markup
);
220 const unsigned char* data
= img
[0].data
;
221 size_t size
= img
[0].size
;
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
));
233 rtc_fixed_val
= rtc_sec
;
234 instance
->load(data
, size
, flags
);
236 romdata
.resize(size
);
237 memcpy(&romdata
[0], data
, size
);
238 internal_rom
= inttype
;
239 do_reset_flag
= false;
243 int load_rom_dmg(core_romimage
* img
, std::map
<std::string
, std::string
>& settings
, uint64_t rtc_sec
,
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
,
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
,
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
)
271 controller_set
_controllerconfig(std::map
<std::string
, std::string
>& settings
)
273 std::map
<std::string
, std::string
> _settings
= settings
;
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));
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
[] = {®ion_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 (®ion
== ®ion_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
,
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
,
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
,
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
[] = {
335 std::string
get_logical_button_name(unsigned lbid
) throw(std::bad_alloc
)
337 if(lbid
>= sizeof(buttonnames
) / sizeof(buttonnames
[0]))
339 return buttonnames
[lbid
];
342 std::string
get_core_identifier()
344 return "libgambatte "+gambatte::GB::version();
347 core_region
& core_get_region()
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
);
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()
386 init_norom_framebuffer();
388 int16_t soundbuf
[(SAMPLES_PER_FRAME
+ 63) / 32];
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;
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;
405 audioapi_submit_buffer(soundbuf
, emitted
/ 2, true, 32768);
406 ecore_callbacks
->timer_tick(samples_emitted
, 2097152);
410 framebuffer_info inf
;
411 inf
.type
= &_pixel_format_rgb32
;
412 inf
.mem
= const_cast<char*>(reinterpret_cast<const char*>(norom_framebuffer
));
414 inf
.physheight
= 144;
415 inf
.physstride
= 640;
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()
434 core_emulate_frame_nocore();
438 int16_t reset
= ecore_callbacks
->set_input(0, 0, 1, do_reset_flag
? 1 : 0);
441 messages
<< "GB(C) reset" << std::endl
;
443 do_reset_flag
= false;
445 uint32_t samplebuffer
[SAMPLES_PER_FRAME
+ 2064];
447 int16_t soundbuf
[(SAMPLES_PER_FRAME
+ 63) / 32 + 66];
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;
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;
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
;
475 framebuffer_info inf
;
476 inf
.type
= &_pixel_format_rgb32
;
477 inf
.mem
= const_cast<char*>(reinterpret_cast<const char*>(primary_framebuffer
));
479 inf
.physheight
= 144;
480 inf
.physstride
= 640;
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
;
502 auto g
= instance
->getSaveRam();
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();
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();
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
;
539 rom
.base
= 0x80000000;
540 rom
.size
= romdata
.size();
541 rom
.backing_ram
= (void*)&romdata
[0];
542 rom
.native_endian
= false;
544 rom
.iospace_rw
= NULL
;
547 vmas
.push_back(sram
);
548 vmas
.push_back(wram
);
550 vmas
.push_back(vram
);
551 vmas
.push_back(ioamhram
);
555 std::set
<std::string
> get_sram_set()
557 std::set
<std::string
> s
;
560 auto g
= instance
->getSaveRam();
567 std::map
<std::string
, std::vector
<char>> save_sram() throw(std::bad_alloc
)
569 std::map
<std::string
, std::vector
<char>> s
;
572 auto g
= instance
->getSaveRam();
573 s
["main"].resize(g
.second
);
574 memcpy(&s
["main"][0], g
.first
, g
.second
);
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
));
582 void load_sram(std::map
<std::string
, std::vector
<char>>& sram
) throw(std::bad_alloc
)
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();
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
));
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()
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
) {
618 instance
->saveState(cmp_save
);
621 function_ptr_command
<> cmp_save2(lsnes_cmd
, "do-cmp-save", "", "\n", []() throw(std::bad_alloc
, std::runtime_error
) {
625 instance
->saveState(x
, cmp_save
);
628 void core_serialize(std::vector
<char>& out
)
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
)
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
;
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
;