2 #include "romimage.hpp"
3 #include "framebuffer.hpp"
4 #include "instance.hpp"
7 #include "core/dispatch.hpp"
8 #include "core/audioapi.hpp"
9 #include "core/instance.hpp"
10 #include "core/messages.hpp"
11 #include "interface/romtype.hpp"
12 #include "interface/callbacks.hpp"
13 #include "library/framebuffer-pixfmt-rgb32.hpp"
19 const unsigned iindexes
[3][7] = {
20 {0, 1, 2, 3, 4, 5, 6},
21 {6, 7, 4, 5, 8, 3, 2},
25 struct interface_device_reg sky_registers
[] = {
30 uint32_t cover_fbmem
[320*200];
31 struct framebuffer::info cover_fbinfo
= {
32 &framebuffer::pixfmt_rgb32
, //Format.
33 (char*)cover_fbmem
, //Memory.
34 320, 200, 1280, //Physical size.
35 320, 200, 1280, //Logical size.
39 struct instance corei
;
41 portctrl::controller X4
= {"(system)", "(system)", {
42 {portctrl::button::TYPE_BUTTON
, 'F', "framesync", true}
44 portctrl::controller X8
= {"sky", "sky", {
45 {portctrl::button::TYPE_BUTTON
, 'L', "left", true},
46 {portctrl::button::TYPE_BUTTON
, 'R', "right", true},
47 {portctrl::button::TYPE_BUTTON
, 'A', "up", true},
48 {portctrl::button::TYPE_BUTTON
, 'D', "down", true},
49 {portctrl::button::TYPE_BUTTON
, 'J', "A", true},
50 {portctrl::button::TYPE_BUTTON
, 'S', "start", true},
51 {portctrl::button::TYPE_BUTTON
, 's', "select", true},
52 {portctrl::button::TYPE_NULL
, '\0', "", true},
53 {portctrl::button::TYPE_NULL
, '\0', "", true},
56 portctrl::controller A8
= {"gamepad", "sky", {
57 {portctrl::button::TYPE_NULL
, '\0', "", false},
58 {portctrl::button::TYPE_NULL
, '\0', "", false},
59 {portctrl::button::TYPE_BUTTON
, 's', "select", false},
60 {portctrl::button::TYPE_BUTTON
, 'S', "start", false},
61 {portctrl::button::TYPE_BUTTON
, 'A', "up", false},
62 {portctrl::button::TYPE_BUTTON
, 'D', "down", false},
63 {portctrl::button::TYPE_BUTTON
, 'L', "left", false},
64 {portctrl::button::TYPE_BUTTON
, 'R', "right", false},
65 {portctrl::button::TYPE_BUTTON
, 'J', "A", false},
67 portctrl::controller B8
= {"gb", "sky", {
68 {portctrl::button::TYPE_BUTTON
, 'J', "A", false},
69 {portctrl::button::TYPE_NULL
, '\0', "", false},
70 {portctrl::button::TYPE_BUTTON
, 's', "select", false},
71 {portctrl::button::TYPE_BUTTON
, 'S', "start", false},
72 {portctrl::button::TYPE_BUTTON
, 'R', "right", false},
73 {portctrl::button::TYPE_BUTTON
, 'L', "left", false},
74 {portctrl::button::TYPE_BUTTON
, 'A', "up", false},
75 {portctrl::button::TYPE_BUTTON
, 'D', "down", false},
76 {portctrl::button::TYPE_NULL
, '\0', "", false},
78 portctrl::controller C8
= {"gba", "sky", {
79 {portctrl::button::TYPE_BUTTON
, 'J', "A", false},
80 {portctrl::button::TYPE_NULL
, '\0', "", false},
81 {portctrl::button::TYPE_BUTTON
, 's', "select", false},
82 {portctrl::button::TYPE_BUTTON
, 'S', "start", false},
83 {portctrl::button::TYPE_BUTTON
, 'R', "right", false},
84 {portctrl::button::TYPE_BUTTON
, 'L', "left", false},
85 {portctrl::button::TYPE_BUTTON
, 'A', "up", false},
86 {portctrl::button::TYPE_BUTTON
, 'D', "down", false},
87 {portctrl::button::TYPE_NULL
, '\0', "", false},
90 portctrl::controller_set X2
= {"sky", "sky", "sky", {X4
, X8
},{0}};
92 void port_write(const portctrl::type
* _this
, unsigned char* buffer
, unsigned idx
, unsigned ctrl
, short x
)
97 case 0: if(x
) buffer
[0] |= 1; else buffer
[0] &= ~1; break;
101 switch(256 * cstyle
+ ctrl
) {
102 case 0: if(x
) buffer
[0] |= 2; else buffer
[0] &= ~2; break;
103 case 1: if(x
) buffer
[0] |= 4; else buffer
[0] &= ~4; break;
104 case 2: if(x
) buffer
[0] |= 8; else buffer
[0] &= ~8; break;
105 case 3: if(x
) buffer
[0] |= 16; else buffer
[0] &= ~16; break;
106 case 4: if(x
) buffer
[0] |= 32; else buffer
[0] &= ~32; break;
107 case 5: if(x
) buffer
[0] |= 64; else buffer
[0] &= ~64; break;
108 case 6: if(x
) buffer
[0] |= 128; else buffer
[0] &= ~128; break;
110 case 258: if(x
) buffer
[0] |= 128; else buffer
[0] &= ~128; break;
111 case 259: if(x
) buffer
[0] |= 64; else buffer
[0] &= ~64; break;
112 case 260: if(x
) buffer
[0] |= 8; else buffer
[0] &= ~8; break;
113 case 261: if(x
) buffer
[0] |= 16; else buffer
[0] &= ~16; break;
114 case 262: if(x
) buffer
[0] |= 2; else buffer
[0] &= ~2; break;
115 case 263: if(x
) buffer
[0] |= 4; else buffer
[0] &= ~4; break;
116 case 264: if(x
) buffer
[0] |= 32; else buffer
[0] &= ~32; break;
118 case 512: if(x
) buffer
[0] |= 32; else buffer
[0] &= ~32; break;
119 case 514: if(x
) buffer
[0] |= 128; else buffer
[0] &= ~128; break;
120 case 515: if(x
) buffer
[0] |= 64; else buffer
[0] &= ~64; break;
121 case 516: if(x
) buffer
[0] |= 4; else buffer
[0] &= ~4; break;
122 case 517: if(x
) buffer
[0] |= 2; else buffer
[0] &= ~2; break;
123 case 518: if(x
) buffer
[0] |= 8; else buffer
[0] &= ~8; break;
124 case 519: if(x
) buffer
[0] |= 16; else buffer
[0] &= ~16; break;
129 short port_read(const portctrl::type
* _this
, const unsigned char* buffer
, unsigned idx
, unsigned ctrl
)
134 case 0: return (buffer
[0] & 1) ? 1 : 0;
138 switch(256 * cstyle
+ ctrl
) {
139 case 0: return (buffer
[0] & 2) ? 1 : 0;
140 case 1: return (buffer
[0] & 4) ? 1 : 0;
141 case 2: return (buffer
[0] & 8) ? 1 : 0;
142 case 3: return (buffer
[0] & 16) ? 1 : 0;
143 case 4: return (buffer
[0] & 32) ? 1 : 0;
144 case 5: return (buffer
[0] & 64) ? 1 : 0;
145 case 6: return (buffer
[0] & 128) ? 1 : 0;
147 case 258: return (buffer
[0] & 128) ? 1 : 0;
148 case 259: return (buffer
[0] & 64) ? 1 : 0;
149 case 260: return (buffer
[0] & 8) ? 1 : 0;
150 case 261: return (buffer
[0] & 16) ? 1 : 0;
151 case 262: return (buffer
[0] & 2) ? 1 : 0;
152 case 263: return (buffer
[0] & 4) ? 1 : 0;
153 case 264: return (buffer
[0] & 32) ? 1 : 0;
155 case 512: return (buffer
[0] & 32) ? 1 : 0;
156 case 514: return (buffer
[0] & 128) ? 1 : 0;
157 case 515: return (buffer
[0] & 64) ? 1 : 0;
158 case 516: return (buffer
[0] & 4) ? 1 : 0;
159 case 517: return (buffer
[0] & 2) ? 1 : 0;
160 case 518: return (buffer
[0] & 8) ? 1 : 0;
161 case 519: return (buffer
[0] & 16) ? 1 : 0;
167 size_t port_serialize(const portctrl::type
* _this
, const unsigned char* buffer
, char* textbuf
)
170 textbuf
[ptr
++] = (buffer
[0] & 1) ? 'F' : '.';
171 textbuf
[ptr
++] = '|';
172 textbuf
[ptr
++] = (buffer
[0] & 2) ? 'L' : '.';
173 textbuf
[ptr
++] = (buffer
[0] & 4) ? 'R' : '.';
174 textbuf
[ptr
++] = (buffer
[0] & 8) ? 'A' : '.';
175 textbuf
[ptr
++] = (buffer
[0] & 16) ? 'D' : '.';
176 textbuf
[ptr
++] = (buffer
[0] & 32) ? 'J' : '.';
177 textbuf
[ptr
++] = (buffer
[0] & 64) ? 'S' : '.';
178 textbuf
[ptr
++] = (buffer
[0] & 128) ? 's' : '.';
182 size_t port_deserialize(const portctrl::type
* _this
, unsigned char* buffer
, const char* textbuf
)
184 memset(buffer
, 0, 2);
186 if(portctrl::read_button_value(textbuf
, ptr
)) buffer
[0] |= 1;
187 portctrl::skip_rest_of_field(textbuf
, ptr
, true);
188 if(portctrl::read_button_value(textbuf
, ptr
)) buffer
[0] |= 2;
189 if(portctrl::read_button_value(textbuf
, ptr
)) buffer
[0] |= 4;
190 if(portctrl::read_button_value(textbuf
, ptr
)) buffer
[0] |= 8;
191 if(portctrl::read_button_value(textbuf
, ptr
)) buffer
[0] |= 16;
192 if(portctrl::read_button_value(textbuf
, ptr
)) buffer
[0] |= 32;
193 if(portctrl::read_button_value(textbuf
, ptr
)) buffer
[0] |= 64;
194 if(portctrl::read_button_value(textbuf
, ptr
)) buffer
[0] |= 128;
195 portctrl::skip_rest_of_field(textbuf
, ptr
, false);
199 struct _psystem
: public portctrl::type
201 _psystem() : portctrl::type("system", "system", 1)
205 serialize
= port_serialize
;
206 deserialize
= port_deserialize
;
207 controller_info
= &X2
;
211 portctrl::index_triple
t(unsigned p
, unsigned c
, unsigned i
, bool nl
)
213 portctrl::index_triple x
;
221 void controller_magic()
223 if(magic_flags
& 1) {
224 X2
.controllers
[1] = A8
;
226 } else if(magic_flags
& 2) {
227 X2
.controllers
[1] = B8
;
229 } else if(magic_flags
& 4) {
230 X2
.controllers
[1] = C8
;
237 struct _sky_core
: public core_core
, public core_type
, public core_region
, public core_sysregion
240 : core_core({&psystem
},{}),
248 .images
= {{"rom", "skyroads.zip", .mandatory
= 1, .pass_mode
= 1, .headersize
= 0,
249 .extensions
= "sky"}},
259 .framemagic
= {656250, 18227},
260 .compatible_runs
= {0}
262 core_sysregion("sky", *this, *this) { hide(); }
264 std::string
c_core_identifier() { return "Sky"; }
265 bool c_set_region(core_region
& region
) { return (®ion
== this); }
266 std::pair
<uint32_t, uint32_t> c_video_rate() { return std::make_pair(656250, 18227); }
267 double c_get_PAR() { return 5.0/6; }
268 std::pair
<uint32_t, uint32_t> c_audio_rate() { return std::make_pair(48000, 1); }
269 std::map
<std::string
, std::vector
<char>> c_save_sram() throw(std::bad_alloc
) {
270 std::map
<std::string
, std::vector
<char>> r
;
271 std::vector
<char> sram
;
273 memcpy(&sram
[0], corei
.state
.sram
, 32);
277 void c_load_sram(std::map
<std::string
, std::vector
<char>>& sram
) throw(std::bad_alloc
) {
278 if(sram
.count("sram") && sram
["sram"].size() == 32)
279 memcpy(corei
.state
.sram
, &sram
["sram"][0], 32);
281 memset(corei
.state
.sram
, 0, 32);
283 void c_serialize(std::vector
<char>& out
) {
284 auto wram
= corei
.state
.as_ram();
285 out
.resize(wram
.second
);
286 memcpy(&out
[0], wram
.first
, wram
.second
);
288 void c_unserialize(const char* in
, size_t insize
) {
289 auto wram
= corei
.state
.as_ram();
290 if(insize
!= wram
.second
)
291 throw std::runtime_error("Save is of wrong size");
292 memcpy(wram
.first
, in
, wram
.second
);
293 handle_loadstate(corei
);
295 core_region
& c_get_region() { return *this; }
297 void c_unload_cartridge() {}
298 std::pair
<uint32_t, uint32_t> c_get_scale_factors(uint32_t w
, uint32_t h
) {
299 return std::make_pair(FB_WIDTH
/ w
, FB_HEIGHT
/ h
);
301 void c_install_handler() {}
302 void c_uninstall_handler() {}
305 for(unsigned i
= 0; i
< 7; i
++)
306 if(ecore_callbacks
->get_input(0, 1, iindexes
[cstyle
][i
]))
309 simulate_frame(corei
, x
);
310 uint32_t* fb
= corei
.get_framebuffer();
311 framebuffer::info inf
;
312 inf
.type
= &framebuffer::pixfmt_rgb32
;
313 inf
.mem
= const_cast<char*>(reinterpret_cast<const char*>(fb
));
314 inf
.physwidth
= FB_WIDTH
;
315 inf
.physheight
= FB_HEIGHT
;
316 inf
.physstride
= 4 * FB_WIDTH
;
317 inf
.width
= FB_WIDTH
;
318 inf
.height
= FB_HEIGHT
;
319 inf
.stride
= 4 * FB_WIDTH
;
323 framebuffer::raw
ls(inf
);
324 ecore_callbacks
->output_frame(ls
, 656250, 18227);
325 ecore_callbacks
->timer_tick(18227, 656250);
326 size_t samples
= 1333;
327 samples
+= corei
.extrasamples();
329 fetch_sfx(corei
, sbuf
, samples
);
330 CORE().audio
->submit_buffer(sbuf
, samples
, true, 48000);
332 void c_runtosave() {}
333 bool c_get_pflag() { return pflag
; }
334 void c_set_pflag(bool _pflag
) { pflag
= _pflag
; }
335 framebuffer::raw
& c_draw_cover() {
336 static framebuffer::raw
x(cover_fbinfo
);
339 std::string
c_get_core_shortname() { return "sky"; }
340 void c_pre_emulate_frame(portctrl::frame
& cf
) {}
341 void c_execute_action(unsigned id
, const std::vector
<interface_action_paramval
>& p
) {}
342 const interface_device_reg
* c_get_registers() { return sky_registers
; }
343 int t_load_rom(core_romimage
* images
, std::map
<std::string
, std::string
>& settings
,
344 uint64_t rtc_sec
, uint64_t rtc_subsec
)
347 const unsigned char* _filename
= images
[0].data
;
348 size_t size
= images
[0].size
;
349 std::string
filename(_filename
, _filename
+ size
);
351 load_rom(corei
, filename
);
352 } catch(std::exception
& e
) {
353 messages
<< e
.what();
356 rom_boot_vector(corei
);
359 controller_set
t_controllerconfig(std::map
<std::string
, std::string
>& settings
)
363 r
.ports
.push_back(&psystem
);
364 r
.logical_map
.push_back(std::make_pair(0, 1));
367 std::pair
<uint64_t, uint64_t> c_get_bus_map() { return std::make_pair(0, 0); }
368 std::list
<core_vma_info
> c_vma_list()
370 std::list
<core_vma_info
> r
;
373 ram
.backing_ram
= corei
.state
.as_ram().first
;
377 ram
.volatile_flag
= true;
381 wram
.backing_ram
= corei
.state
.as_ram().first
+ 131072;
382 wram
.size
= corei
.state
.as_ram().second
- 131072 - 32;
385 wram
.volatile_flag
= true;
389 sram
.backing_ram
= corei
.state
.as_ram().first
+ corei
.state
.as_ram().second
- 32;
391 sram
.base
= corei
.state
.as_ram().second
- 32;
393 sram
.volatile_flag
= false;
397 std::set
<std::string
> c_srams()
399 std::set
<std::string
> r
;
403 unsigned c_action_flags(unsigned id
) { return 0; }
404 int c_reset_action(bool hard
) { return -1; }
405 void c_set_debug_flags(uint64_t addr
, unsigned int sflags
, unsigned int cflags
)
408 void c_set_cheat(uint64_t addr
, uint64_t value
, bool set
)
414 std::vector
<std::string
> c_get_trace_cpus()
416 std::vector
<std::string
> r
;