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/window.hpp"
10 #include "interface/romtype.hpp"
11 #include "interface/callbacks.hpp"
12 #include "library/pixfmt-rgb32.hpp"
18 const unsigned iindexes
[3][7] = {
19 {0, 1, 2, 3, 4, 5, 6},
20 {6, 7, 4, 5, 8, 3, 2},
24 struct interface_device_reg sky_registers
[] = {
29 uint32_t cover_fbmem
[320*200];
30 struct framebuffer_info cover_fbinfo
= {
31 &_pixel_format_rgb32
, //Format.
32 (char*)cover_fbmem
, //Memory.
33 320, 200, 1280, //Physical size.
34 320, 200, 1280, //Logical size.
38 struct instance corei
;
40 port_controller X4
= {"(system)", "(system)", {
41 {port_controller_button::TYPE_BUTTON
, 'F', "framesync", true}
43 port_controller X8
= {"sky", "sky", {
44 {port_controller_button::TYPE_BUTTON
, 'L', "left", true},
45 {port_controller_button::TYPE_BUTTON
, 'R', "right", true},
46 {port_controller_button::TYPE_BUTTON
, 'A', "up", true},
47 {port_controller_button::TYPE_BUTTON
, 'D', "down", true},
48 {port_controller_button::TYPE_BUTTON
, 'J', "A", true},
49 {port_controller_button::TYPE_BUTTON
, 'S', "start", true},
50 {port_controller_button::TYPE_BUTTON
, 's', "select", true},
51 {port_controller_button::TYPE_NULL
, '\0', "", true},
52 {port_controller_button::TYPE_NULL
, '\0', "", true},
55 port_controller A8
= {"gamepad", "sky", {
56 {port_controller_button::TYPE_NULL
, '\0', "", false},
57 {port_controller_button::TYPE_NULL
, '\0', "", false},
58 {port_controller_button::TYPE_BUTTON
, 's', "select", false},
59 {port_controller_button::TYPE_BUTTON
, 'S', "start", false},
60 {port_controller_button::TYPE_BUTTON
, 'A', "up", false},
61 {port_controller_button::TYPE_BUTTON
, 'D', "down", false},
62 {port_controller_button::TYPE_BUTTON
, 'L', "left", false},
63 {port_controller_button::TYPE_BUTTON
, 'R', "right", false},
64 {port_controller_button::TYPE_BUTTON
, 'J', "A", false},
66 port_controller B8
= {"gb", "sky", {
67 {port_controller_button::TYPE_BUTTON
, 'J', "A", false},
68 {port_controller_button::TYPE_NULL
, '\0', "", false},
69 {port_controller_button::TYPE_BUTTON
, 's', "select", false},
70 {port_controller_button::TYPE_BUTTON
, 'S', "start", false},
71 {port_controller_button::TYPE_BUTTON
, 'R', "right", false},
72 {port_controller_button::TYPE_BUTTON
, 'L', "left", false},
73 {port_controller_button::TYPE_BUTTON
, 'A', "up", false},
74 {port_controller_button::TYPE_BUTTON
, 'D', "down", false},
75 {port_controller_button::TYPE_NULL
, '\0', "", false},
77 port_controller C8
= {"gba", "sky", {
78 {port_controller_button::TYPE_BUTTON
, 'J', "A", false},
79 {port_controller_button::TYPE_NULL
, '\0', "", false},
80 {port_controller_button::TYPE_BUTTON
, 's', "select", false},
81 {port_controller_button::TYPE_BUTTON
, 'S', "start", false},
82 {port_controller_button::TYPE_BUTTON
, 'R', "right", false},
83 {port_controller_button::TYPE_BUTTON
, 'L', "left", false},
84 {port_controller_button::TYPE_BUTTON
, 'A', "up", false},
85 {port_controller_button::TYPE_BUTTON
, 'D', "down", false},
86 {port_controller_button::TYPE_NULL
, '\0', "", false},
89 port_controller_set X2
= {"sky", "sky", "sky", {X4
, X8
},{0}};
91 void port_write(const port_type
* _this
, unsigned char* buffer
, unsigned idx
, unsigned ctrl
, short x
)
96 case 0: if(x
) buffer
[0] |= 1; else buffer
[0] &= ~1; break;
100 switch(256 * cstyle
+ ctrl
) {
101 case 0: if(x
) buffer
[0] |= 2; else buffer
[0] &= ~2; break;
102 case 1: if(x
) buffer
[0] |= 4; else buffer
[0] &= ~4; break;
103 case 2: if(x
) buffer
[0] |= 8; else buffer
[0] &= ~8; break;
104 case 3: if(x
) buffer
[0] |= 16; else buffer
[0] &= ~16; break;
105 case 4: if(x
) buffer
[0] |= 32; else buffer
[0] &= ~32; break;
106 case 5: if(x
) buffer
[0] |= 64; else buffer
[0] &= ~64; break;
107 case 6: if(x
) buffer
[0] |= 128; else buffer
[0] &= ~128; break;
109 case 258: if(x
) buffer
[0] |= 128; else buffer
[0] &= ~128; break;
110 case 259: if(x
) buffer
[0] |= 64; else buffer
[0] &= ~64; break;
111 case 260: if(x
) buffer
[0] |= 8; else buffer
[0] &= ~8; break;
112 case 261: if(x
) buffer
[0] |= 16; else buffer
[0] &= ~16; break;
113 case 262: if(x
) buffer
[0] |= 2; else buffer
[0] &= ~2; break;
114 case 263: if(x
) buffer
[0] |= 4; else buffer
[0] &= ~4; break;
115 case 264: if(x
) buffer
[0] |= 32; else buffer
[0] &= ~32; break;
117 case 512: if(x
) buffer
[0] |= 32; else buffer
[0] &= ~32; break;
118 case 514: if(x
) buffer
[0] |= 128; else buffer
[0] &= ~128; break;
119 case 515: if(x
) buffer
[0] |= 64; else buffer
[0] &= ~64; break;
120 case 516: if(x
) buffer
[0] |= 4; else buffer
[0] &= ~4; break;
121 case 517: if(x
) buffer
[0] |= 2; else buffer
[0] &= ~2; break;
122 case 518: if(x
) buffer
[0] |= 8; else buffer
[0] &= ~8; break;
123 case 519: if(x
) buffer
[0] |= 16; else buffer
[0] &= ~16; break;
128 short port_read(const port_type
* _this
, const unsigned char* buffer
, unsigned idx
, unsigned ctrl
)
133 case 0: return (buffer
[0] & 1) ? 1 : 0;
137 switch(256 * cstyle
+ ctrl
) {
138 case 0: return (buffer
[0] & 2) ? 1 : 0;
139 case 1: return (buffer
[0] & 4) ? 1 : 0;
140 case 2: return (buffer
[0] & 8) ? 1 : 0;
141 case 3: return (buffer
[0] & 16) ? 1 : 0;
142 case 4: return (buffer
[0] & 32) ? 1 : 0;
143 case 5: return (buffer
[0] & 64) ? 1 : 0;
144 case 6: return (buffer
[0] & 128) ? 1 : 0;
146 case 258: return (buffer
[0] & 128) ? 1 : 0;
147 case 259: return (buffer
[0] & 64) ? 1 : 0;
148 case 260: return (buffer
[0] & 8) ? 1 : 0;
149 case 261: return (buffer
[0] & 16) ? 1 : 0;
150 case 262: return (buffer
[0] & 2) ? 1 : 0;
151 case 263: return (buffer
[0] & 4) ? 1 : 0;
152 case 264: return (buffer
[0] & 32) ? 1 : 0;
154 case 512: return (buffer
[0] & 32) ? 1 : 0;
155 case 514: return (buffer
[0] & 128) ? 1 : 0;
156 case 515: return (buffer
[0] & 64) ? 1 : 0;
157 case 516: return (buffer
[0] & 4) ? 1 : 0;
158 case 517: return (buffer
[0] & 2) ? 1 : 0;
159 case 518: return (buffer
[0] & 8) ? 1 : 0;
160 case 519: return (buffer
[0] & 16) ? 1 : 0;
166 size_t port_serialize(const port_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 port_type
* _this
, unsigned char* buffer
, const char* textbuf
)
184 memset(buffer
, 0, 2);
187 if(read_button_value(textbuf
, ptr
)) buffer
[0] |= 1;
188 skip_rest_of_field(textbuf
, ptr
, true);
189 if(read_button_value(textbuf
, ptr
)) buffer
[0] |= 2;
190 if(read_button_value(textbuf
, ptr
)) buffer
[0] |= 4;
191 if(read_button_value(textbuf
, ptr
)) buffer
[0] |= 8;
192 if(read_button_value(textbuf
, ptr
)) buffer
[0] |= 16;
193 if(read_button_value(textbuf
, ptr
)) buffer
[0] |= 32;
194 if(read_button_value(textbuf
, ptr
)) buffer
[0] |= 64;
195 if(read_button_value(textbuf
, ptr
)) buffer
[0] |= 128;
196 skip_rest_of_field(textbuf
, ptr
, false);
199 struct _psystem
: public port_type
201 _psystem() : port_type("system", "system", 1)
205 serialize
= port_serialize
;
206 deserialize
= port_deserialize
;
207 controller_info
= &X2
;
211 port_index_triple
t(unsigned p
, unsigned c
, unsigned i
, bool nl
)
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
= &_pixel_format_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 audioapi_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(controller_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; }