1 /***************************************************************************
2 * Copyright (C) 2012-2013 by Ilari Liusvaara *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License version 2 as *
6 * published by the Free Software Foundation. *
8 * This program is distributed in the hope that it will be useful, *
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
11 * GNU General Public License version 2 for more details. *
13 * You should have received a copy of the GNU General Public License *
14 * version 2 along with this program; if not, write to the *
15 * Free Software Foundation, Inc., *
16 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
17 ***************************************************************************/
24 #include "core/audioapi.hpp"
25 #include "core/misc.hpp"
26 #include "core/command.hpp"
27 #include "core/controllerframe.hpp"
28 #include "core/dispatch.hpp"
29 #include "core/framebuffer.hpp"
30 #include "core/window.hpp"
31 #include "interface/callbacks.hpp"
32 #include "interface/cover.hpp"
33 #include "interface/romtype.hpp"
34 #include "library/pixfmt-rgb32.hpp"
35 #include "library/string.hpp"
36 #include "library/portfn.hpp"
37 #include "library/serialization.hpp"
38 #include "library/minmax.hpp"
39 #include "library/framebuffer.hpp"
41 #include "libgambatte/include/gambatte.h"
43 #define SAMPLES_PER_FRAME 35112
47 bool do_reset_flag
= false;
48 core_type
* internal_rom
= NULL
;
49 extern core_core_params _gambatte_core
;
52 gambatte::GB
* instance
;
53 unsigned frame_overflow
= 0;
54 std::vector
<unsigned char> romdata
;
55 uint32_t cover_fbmem
[480 * 432];
56 uint32_t primary_framebuffer
[160*144];
57 uint32_t accumulator_l
= 0;
58 uint32_t accumulator_r
= 0;
59 unsigned accumulator_s
= 0;
63 struct framebuffer_info cover_fbinfo
= {
64 &_pixel_format_rgb32
, //Format.
65 (char*)cover_fbmem
, //Memory.
66 480, 432, 1920, //Physical size.
67 480, 432, 1920, //Logical size.
73 #include "regions.inc"
75 core_setting_group gambatte_settings
;
82 return ecore_callbacks
->get_time();
87 class myinput
: public gambatte::InputGetter
93 for(unsigned i
= 0; i
< 8; i
++) {
94 if(ecore_callbacks
->get_input(0, 1, i
))
104 static bool done
= false;
108 instance
= new gambatte::GB
;
109 instance
->setInputGetter(&getinput
);
110 instance
->set_walltime_fn(walltime_fn
);
113 int load_rom_common(core_romimage
* img
, unsigned flags
, uint64_t rtc_sec
, uint64_t rtc_subsec
,
117 const char* markup
= img
[0].markup
;
120 flags2
= atoi(markup
);
124 const unsigned char* data
= img
[0].data
;
125 size_t size
= img
[0].size
;
129 memset(instance
, 0, sizeof(gambatte::GB
));
130 new(instance
) gambatte::GB
;
131 instance
->setInputGetter(&getinput
);
132 instance
->set_walltime_fn(walltime_fn
);
133 memset(primary_framebuffer
, 0, sizeof(primary_framebuffer
));
137 rtc_fixed_val
= rtc_sec
;
138 instance
->load(data
, size
, flags
);
140 romdata
.resize(size
);
141 memcpy(&romdata
[0], data
, size
);
142 internal_rom
= inttype
;
143 do_reset_flag
= false;
147 port_index_triple
t(unsigned p
, unsigned c
, unsigned i
, bool nl
)
157 controller_set
_controllerconfig(std::map
<std::string
, std::string
>& settings
)
159 std::map
<std::string
, std::string
> _settings
= settings
;
161 r
.ports
.push_back(&psystem
);
162 for(unsigned i
= 0; i
< 4; i
++)
163 r
.portindex
.indices
.push_back(t(0, 0, i
, false));
164 for(unsigned i
= 0; i
< 8; i
++)
165 r
.portindex
.indices
.push_back(t(0, 1, i
, true));
166 r
.portindex
.logical_map
.push_back(std::make_pair(0, 1));
167 r
.portindex
.pcid_map
.push_back(std::make_pair(0, 1));
171 std::pair
<uint64_t, uint64_t> gambatte_bus_map()
173 return std::make_pair(0, 0);
176 std::list
<core_vma_info
> get_VMAlist()
178 std::list
<core_vma_info
> vmas
;
184 core_vma_info ioamhram
;
187 auto g
= instance
->getSaveRam();
190 sram
.size
= g
.second
;
191 sram
.backing_ram
= g
.first
;
193 sram
.readonly
= false;
194 sram
.iospace_rw
= NULL
;
196 auto g2
= instance
->getWorkRam();
199 wram
.size
= g2
.second
;
200 wram
.backing_ram
= g2
.first
;
202 wram
.readonly
= false;
203 wram
.iospace_rw
= NULL
;
205 auto g3
= instance
->getVideoRam();
208 vram
.size
= g3
.second
;
209 vram
.backing_ram
= g3
.first
;
211 vram
.readonly
= false;
212 vram
.iospace_rw
= NULL
;
214 auto g4
= instance
->getIoRam();
215 ioamhram
.name
= "IOAMHRAM";
216 ioamhram
.base
= 0x18000;
217 ioamhram
.size
= g4
.second
;
218 ioamhram
.backing_ram
= g4
.first
;
219 ioamhram
.endian
= -1;
220 ioamhram
.readonly
= false;
221 ioamhram
.iospace_rw
= NULL
;
224 rom
.base
= 0x80000000;
225 rom
.size
= romdata
.size();
226 rom
.backing_ram
= (void*)&romdata
[0];
229 rom
.iospace_rw
= NULL
;
232 vmas
.push_back(sram
);
233 vmas
.push_back(wram
);
235 vmas
.push_back(vram
);
236 vmas
.push_back(ioamhram
);
240 std::set
<std::string
> srams()
242 std::set
<std::string
> s
;
245 auto g
= instance
->getSaveRam();
252 std::string
get_cartridge_name()
254 std::ostringstream name
;
255 if(romdata
.size() < 0x200)
257 for(unsigned i
= 0; i
< 16; i
++) {
258 if(romdata
[0x134 + i
])
259 name
<< (char)romdata
[0x134 + i
];
266 void redraw_cover_fbinfo()
268 for(size_t i
= 0; i
< sizeof(cover_fbmem
) / sizeof(cover_fbmem
[0]); i
++)
269 cover_fbmem
[i
] = 0x00000000;
270 std::string ident
= _gambatte_core
.core_identifier();
271 cover_render_string(cover_fbmem
, 0, 0, ident
, 0xFFFFFF, 0x00000, 480, 432, 1920, 4);
272 cover_render_string(cover_fbmem
, 0, 16, "Internal ROM name: " + get_cartridge_name(),
273 0xFFFFFF, 0x00000, 480, 432, 1920, 4);
275 for(auto i
: cover_information()) {
276 cover_render_string(cover_fbmem
, 0, y
, i
, 0xFFFFFF, 0x000000, 480, 432, 1920, 4);
281 core_core_params _gambatte_core
= {
282 .core_identifier
= []() -> std::string
{ return "libgambatte "+gambatte::GB::version(); },
283 .set_region
= [](core_region
& region
) -> bool { return (®ion
== ®ion_world
); },
284 .video_rate
= []() -> std::pair
<uint32_t, uint32_t> { return std::make_pair(262144, 4389); },
285 .audio_rate
= []() -> std::pair
<uint32_t, uint32_t> { return std::make_pair(32768, 1); },
287 .save_sram
= []() -> std::map
<std::string
, std::vector
<char>> {
288 std::map
<std::string
, std::vector
<char>> s
;
291 auto g
= instance
->getSaveRam();
292 s
["main"].resize(g
.second
);
293 memcpy(&s
["main"][0], g
.first
, g
.second
);
295 time_t timebase
= instance
->getRtcBase();
296 for(size_t i
= 0; i
< 8; i
++)
297 s
["rtc"][i
] = ((unsigned long long)timebase
>> (8 * i
));
300 .load_sram
= [](std::map
<std::string
, std::vector
<char>>& sram
) -> void {
303 std::vector
<char> x
= sram
.count("main") ? sram
["main"] : std::vector
<char>();
304 std::vector
<char> x2
= sram
.count("rtc") ? sram
["rtc"] : std::vector
<char>();
305 auto g
= instance
->getSaveRam();
307 if(x
.size() != g
.second
)
308 messages
<< "WARNING: SRAM 'main': Loaded " << x
.size()
309 << " bytes, but the SRAM is " << g
.second
<< "." << std::endl
;
310 memcpy(g
.first
, &x
[0], min(x
.size(), g
.second
));
314 for(size_t i
= 0; i
< 8 && i
< x2
.size(); i
++)
315 timebase
|= (unsigned long long)(unsigned char)x2
[i
] << (8 * i
);
316 instance
->setRtcBase(timebase
);
319 .serialize
= [](std::vector
<char>& out
) -> void {
321 throw std::runtime_error("Can't save without ROM");
322 instance
->saveState(out
);
323 size_t osize
= out
.size();
324 out
.resize(osize
+ 4 * sizeof(primary_framebuffer
) / sizeof(primary_framebuffer
[0]));
325 for(size_t i
= 0; i
< sizeof(primary_framebuffer
) / sizeof(primary_framebuffer
[0]); i
++)
326 write32ube(&out
[osize
+ 4 * i
], primary_framebuffer
[i
]);
327 out
.push_back(frame_overflow
>> 8);
328 out
.push_back(frame_overflow
);
330 .unserialize
= [](const char* in
, size_t insize
) -> void {
332 throw std::runtime_error("Can't load without ROM");
333 size_t foffset
= insize
- 2 - 4 * sizeof(primary_framebuffer
) /
334 sizeof(primary_framebuffer
[0]);
335 std::vector
<char> tmp
;
337 memcpy(&tmp
[0], in
, foffset
);
338 instance
->loadState(tmp
);
339 for(size_t i
= 0; i
< sizeof(primary_framebuffer
) / sizeof(primary_framebuffer
[0]); i
++)
340 primary_framebuffer
[i
] = read32ube(&in
[foffset
+ 4 * i
]);
342 unsigned x1
= (unsigned char)in
[insize
- 2];
343 unsigned x2
= (unsigned char)in
[insize
- 1];
344 frame_overflow
= x1
* 256 + x2
;
345 do_reset_flag
= false;
347 .get_region
= []() -> core_region
& { return region_world
; },
348 .power
= []() -> void {},
349 .unload_cartridge
= []() -> void {},
350 .get_scale_factors
= [](uint32_t width
, uint32_t height
) -> std::pair
<uint32_t, uint32_t> {
351 return std::make_pair(max(512 / width
, (uint32_t)1), max(448 / height
, (uint32_t)1));
353 .install_handler
= []() -> void { magic_flags
|= 2; },
354 .uninstall_handler
= []() -> void {},
355 .emulate
= []() -> void {
358 int16_t reset
= ecore_callbacks
->get_input(0, 0, 1);
361 messages
<< "GB(C) reset" << std::endl
;
363 do_reset_flag
= false;
365 uint32_t samplebuffer
[SAMPLES_PER_FRAME
+ 2064];
367 int16_t soundbuf
[(SAMPLES_PER_FRAME
+ 63) / 32 + 66];
369 unsigned samples_emitted
= SAMPLES_PER_FRAME
- frame_overflow
;
370 long ret
= instance
->runFor(primary_framebuffer
, 160, samplebuffer
, samples_emitted
);
371 for(unsigned i
= 0; i
< samples_emitted
; i
++) {
372 uint32_t l
= (int32_t)(int16_t)(samplebuffer
[i
]) + 32768;
373 uint32_t r
= (int32_t)(int16_t)(samplebuffer
[i
] >> 16) + 32768;
377 if((accumulator_s
& 63) == 0) {
378 int16_t l2
= (accumulator_l
>> 6) - 32768;
379 int16_t r2
= (accumulator_r
>> 6) - 32768;
380 soundbuf
[emitted
++] = l2
;
381 soundbuf
[emitted
++] = r2
;
382 information_dispatch::do_sample(l2
, r2
);
383 accumulator_l
= accumulator_r
= 0;
387 audioapi_submit_buffer(soundbuf
, emitted
/ 2, true, 32768);
388 ecore_callbacks
->timer_tick(samples_emitted
, 2097152);
389 frame_overflow
+= samples_emitted
;
390 if(frame_overflow
>= SAMPLES_PER_FRAME
) {
391 frame_overflow
-= SAMPLES_PER_FRAME
;
395 framebuffer_info inf
;
396 inf
.type
= &_pixel_format_rgb32
;
397 inf
.mem
= const_cast<char*>(reinterpret_cast<const char*>(primary_framebuffer
));
399 inf
.physheight
= 144;
400 inf
.physstride
= 640;
407 framebuffer_raw
ls(inf
);
408 ecore_callbacks
->output_frame(ls
, 262144, 4389);
410 .runtosave
= []() -> void {},
411 .get_pflag
= []() -> bool { return pflag
; },
412 .set_pflag
= [](bool _pflag
) -> void { pflag
= _pflag
; },
413 .request_reset
= [](long delay
, bool hard
) -> void { do_reset_flag
= true; },
414 .port_types
= port_types
,
415 .draw_cover
= []() -> framebuffer_raw
& {
416 static framebuffer_raw
x(cover_fbinfo
);
417 redraw_cover_fbinfo();
420 .get_core_shortname
= []() -> std::string
{ return "gambatte"+gambatte::GB::version(); },
421 .pre_emulate_frame
= [](controller_frame
& cf
) -> void {
422 cf
.axis3(0, 0, 1, do_reset_flag
? 1 : 0);
426 core_core
gambatte_core(_gambatte_core
);
428 core_type_params _type_dmg
= {
429 .iname
= "dmg", .hname
= "Game Boy", .id
= 1, .reset_support
= 1,
430 .load_rom
= [](core_romimage
* img
, std::map
<std::string
, std::string
>& settings
, uint64_t rtc_sec
,
431 uint64_t rtc_subsec
) -> int {
432 return load_rom_common(img
, gambatte::GB::FORCE_DMG
, rtc_sec
, rtc_subsec
, &type_dmg
);
434 .controllerconfig
= _controllerconfig
, .extensions
= "gb;dmg", .bios
= NULL
, .regions
= dmg_regions
,
435 .images
= dmg_images
, .settings
= &gambatte_settings
, .core
= &gambatte_core
,
436 .get_bus_map
= gambatte_bus_map
, .vma_list
= get_VMAlist
, .srams
= srams
438 core_type_params _type_gbc
= {
439 .iname
= "gbc", .hname
= "Game Boy Color", .id
= 0, .reset_support
= 1,
440 .load_rom
= [](core_romimage
* img
, std::map
<std::string
, std::string
>& settings
, uint64_t rtc_sec
,
441 uint64_t rtc_subsec
) -> int {
442 return load_rom_common(img
, 0, rtc_sec
, rtc_subsec
, &type_gbc
);
444 .controllerconfig
= _controllerconfig
, .extensions
= "gbc;cgb", .bios
= NULL
, .regions
= gbc_regions
,
445 .images
= gbc_images
, .settings
= &gambatte_settings
, .core
= &gambatte_core
,
446 .get_bus_map
= gambatte_bus_map
, .vma_list
= get_VMAlist
, .srams
= srams
448 core_type_params _type_gbca
= {
449 .iname
= "gbc_gba", .hname
= "Game Boy Color (GBA)", .id
= 2, .reset_support
= 1,
450 .load_rom
= [](core_romimage
* img
, std::map
<std::string
, std::string
>& settings
, uint64_t rtc_sec
,
451 uint64_t rtc_subsec
) -> int {
452 return load_rom_common(img
, gambatte::GB::GBA_CGB
, rtc_sec
, rtc_subsec
, &type_gbca
);
454 .controllerconfig
= _controllerconfig
, .extensions
= "", .bios
= NULL
, .regions
= gbca_regions
,
455 .images
= gbca_images
, .settings
= &gambatte_settings
, .core
= &gambatte_core
,
456 .get_bus_map
= gambatte_bus_map
, .vma_list
= get_VMAlist
, .srams
= srams
459 core_type
type_dmg(_type_dmg
);
460 core_type
type_gbc(_type_gbc
);
461 core_type
type_gbca(_type_gbca
);
463 std::vector
<char> cmp_save
;
465 function_ptr_command
<> cmp_save1(lsnes_cmd
, "set-cmp-save", "", "\n", []() throw(std::bad_alloc
,
466 std::runtime_error
) {
469 instance
->saveState(cmp_save
);
472 function_ptr_command
<> cmp_save2(lsnes_cmd
, "do-cmp-save", "", "\n", []() throw(std::bad_alloc
,
473 std::runtime_error
) {
477 instance
->saveState(x
, cmp_save
);