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 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)
106 buffer
[idx
] |= (1 << ctrl
);
108 buffer
[idx
] &= ~(1 << ctrl
);
111 short system_read(const unsigned char* buffer
, unsigned idx
, unsigned ctrl
) throw()
114 if(idx
< 2 && ctrl
< 8)
115 y
= ((buffer
[idx
] >> ctrl
) & 1) ? 1 : 0;
119 size_t system_deserialize(unsigned char* buffer
, const char* textbuf
)
121 memset(buffer
, 0, 2);
123 if(read_button_value(textbuf
, ptr
))
125 if(read_button_value(textbuf
, ptr
))
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);
135 const char* button_symbols
= "ABsSrlud";
137 void system_display(const unsigned char* buffer
, unsigned idx
, char* buf
)
142 for(unsigned i
= 0; i
< 8; i
++)
143 buf
[i
] = ((buffer
[1] & (1 << i
)) != 0) ? button_symbols
[i
] : '-';
146 sprintf(buf
, "%c%c", ((buffer
[0] & 1) ? 'F' : '.'), ((buffer
[0] & 2) ? 'R' : '.'));
149 size_t system_serialize(const unsigned char* buffer
, char* textbuf
)
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
] : '.';
156 size_t len
= strlen(tmp
);
157 memcpy(textbuf
, tmp
, 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
;
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
;
199 int load_rom_common(core_romimage
* img
, unsigned flags
, uint64_t rtc_sec
, uint64_t rtc_subsec
,
202 const char* markup
= img
[0].markup
;
205 flags2
= atoi(markup
);
209 const unsigned char* data
= img
[0].data
;
210 size_t size
= img
[0].size
;
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
));
222 rtc_fixed_val
= rtc_sec
;
223 instance
->load(data
, size
, flags
);
225 romdata
.resize(size
);
226 memcpy(&romdata
[0], data
, size
);
227 internal_rom
= inttype
;
228 do_reset_flag
= false;
232 int load_rom_dmg(core_romimage
* img
, std::map
<std::string
, std::string
>& settings
, uint64_t rtc_sec
,
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
,
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
,
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
)
260 controller_set
_controllerconfig(std::map
<std::string
, std::string
>& settings
)
262 std::map
<std::string
, std::string
> _settings
= settings
;
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));
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
[] = {®ion_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 (®ion
== ®ion_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
[] = {
321 std::string
get_logical_button_name(unsigned lbid
) throw(std::bad_alloc
)
323 if(lbid
>= sizeof(buttonnames
) / sizeof(buttonnames
[0]))
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()
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
);
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()
384 init_norom_framebuffer();
386 int16_t soundbuf
[(SAMPLES_PER_FRAME
+ 63) / 32];
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;
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;
403 audioapi_submit_buffer(soundbuf
, emitted
/ 2, true, 32768);
404 ecore_callbacks
->timer_tick(samples_emitted
, 2097152);
408 framebuffer_info inf
;
409 inf
.type
= &_pixel_format_rgb32
;
410 inf
.mem
= const_cast<char*>(reinterpret_cast<const char*>(norom_framebuffer
));
412 inf
.physheight
= 144;
413 inf
.physstride
= 640;
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()
432 core_emulate_frame_nocore();
436 int16_t reset
= ecore_callbacks
->set_input(0, 0, 1, do_reset_flag
? 1 : 0);
439 messages
<< "GB(C) reset" << std::endl
;
441 do_reset_flag
= false;
443 uint32_t samplebuffer
[SAMPLES_PER_FRAME
+ 2064];
445 int16_t soundbuf
[(SAMPLES_PER_FRAME
+ 63) / 32 + 66];
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;
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;
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
;
473 framebuffer_info inf
;
474 inf
.type
= &_pixel_format_rgb32
;
475 inf
.mem
= const_cast<char*>(reinterpret_cast<const char*>(primary_framebuffer
));
477 inf
.physheight
= 144;
478 inf
.physstride
= 640;
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
;
500 auto g
= instance
->getSaveRam();
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();
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();
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
;
537 rom
.base
= 0x80000000;
538 rom
.size
= romdata
.size();
539 rom
.backing_ram
= (void*)&romdata
[0];
540 rom
.native_endian
= false;
542 rom
.iospace_rw
= NULL
;
545 vmas
.push_back(sram
);
546 vmas
.push_back(wram
);
548 vmas
.push_back(vram
);
549 vmas
.push_back(ioamhram
);
553 std::set
<std::string
> get_sram_set()
555 std::set
<std::string
> s
;
558 auto g
= instance
->getSaveRam();
565 std::map
<std::string
, std::vector
<char>> save_sram() throw(std::bad_alloc
)
567 std::map
<std::string
, std::vector
<char>> s
;
570 auto g
= instance
->getSaveRam();
571 s
["main"].resize(g
.second
);
572 memcpy(&s
["main"][0], g
.first
, g
.second
);
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
));
580 void load_sram(std::map
<std::string
, std::vector
<char>>& sram
) throw(std::bad_alloc
)
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();
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
));
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()
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
) {
616 instance
->saveState(cmp_save
);
619 function_ptr_command
<> cmp_save2(lsnes_cmd
, "do-cmp-save", "", "\n", []() throw(std::bad_alloc
, std::runtime_error
) {
623 instance
->saveState(x
, cmp_save
);
626 void core_serialize(std::vector
<char>& out
)
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
)
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
;
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
;