JSON-based controller descriptions
[lsnes.git] / src / emulation / sky / sky.cpp
blob8c470008e2997e800bde662998ce6132c20eb60d
1 #include "state.hpp"
2 #include "romimage.hpp"
3 #include "framebuffer.hpp"
4 #include "instance.hpp"
5 #include "logic.hpp"
6 #include "demo.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"
14 namespace sky
16 bool pflag;
17 int cstyle = 0;
18 const unsigned iindexes[3][7] = {
19 {0, 1, 2, 3, 4, 5, 6},
20 {6, 7, 4, 5, 8, 3, 2},
21 {5, 4, 6, 7, 0, 3, 2}
24 struct interface_device_reg sky_registers[] = {
25 {NULL, NULL, NULL}
28 //Framebuffer.
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.
35 0, 0 //Offset.
38 struct instance corei;
40 port_controller X4 = {"(system)", "(system)", {
41 {port_controller_button::TYPE_BUTTON, 'F', "framesync", true}
42 }};
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},
53 }};
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},
65 }};
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},
76 }};
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},
87 }};
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)
93 switch(idx) {
94 case 0:
95 switch(ctrl) {
96 case 0: if(x) buffer[0] |= 1; else buffer[0] &= ~1; break;
98 break;
99 case 1:
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)
130 switch(idx) {
131 case 0:
132 switch(ctrl) {
133 case 0: return (buffer[0] & 1) ? 1 : 0;
135 break;
136 case 1:
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;
162 break;
164 return 0;
166 size_t port_serialize(const port_type* _this, const unsigned char* buffer, char* textbuf)
168 size_t ptr = 0;
169 short tmp;
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' : '.';
179 textbuf[ptr] = '\0';
180 return ptr;
182 size_t port_deserialize(const port_type* _this, unsigned char* buffer, const char* textbuf)
184 memset(buffer, 0, 2);
185 size_t ptr = 0;
186 short tmp;
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)
203 write = port_write;
204 read = port_read;
205 serialize = port_serialize;
206 deserialize = port_deserialize;
207 controller_info = &X2;
209 } psystem;
211 port_index_triple t(unsigned p, unsigned c, unsigned i, bool nl)
213 port_index_triple x;
214 x.valid = true;
215 x.port = p;
216 x.controller = c;
217 x.control = i;
218 return x;
221 void controller_magic()
223 if(magic_flags & 1) {
224 X2.controllers[1] = A8;
225 cstyle = 1;
226 } else if(magic_flags & 2) {
227 X2.controllers[1] = B8;
228 cstyle = 2;
229 } else if(magic_flags & 4) {
230 X2.controllers[1] = C8;
231 cstyle = 2;
232 } else {
233 cstyle = 0;
237 struct _sky_core : public core_core, public core_type, public core_region, public core_sysregion
239 _sky_core()
240 : core_core({&psystem},{}),
241 core_type({{
242 .iname = "sky",
243 .hname = "Sky",
244 .id = 3522,
245 .sysname = "Sky",
246 .bios = NULL,
247 .regions = {this},
248 .images = {{"rom", "skyroads.zip", .mandatory = 1, .pass_mode = 1, .headersize = 0,
249 .extensions = "sky"}},
250 .settings = {},
251 .core = this,
252 }}),
253 core_region({{
254 .iname = "world",
255 .hname = "World",
256 .priority = 0,
257 .handle = 0,
258 .multi = false,
259 .framemagic = {656250, 18227},
260 .compatible_runs = {0}
261 }}),
262 core_sysregion("sky", *this, *this) { hide(); }
264 std::string c_core_identifier() { return "Sky"; }
265 bool c_set_region(core_region& region) { return (&region == 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;
272 sram.resize(32);
273 memcpy(&sram[0], corei.state.sram, 32);
274 r["sram"] = sram;
275 return r;
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);
280 else
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; }
296 void c_power() {}
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() {}
303 void c_emulate() {
304 uint16_t x = 0;
305 for(unsigned i = 0; i < 7; i++)
306 if(ecore_callbacks->get_input(0, 1, iindexes[cstyle][i]))
307 x |= (1 << i);
308 pflag = true;
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;
320 inf.offset_x = 0;
321 inf.offset_y = 0;
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();
328 int16_t sbuf[2668];
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);
337 return x;
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)
346 controller_magic();
347 const unsigned char* _filename = images[0].data;
348 size_t size = images[0].size;
349 std::string filename(_filename, _filename + size);
350 try {
351 load_rom(corei, filename);
352 } catch(std::exception& e) {
353 messages << e.what();
354 return -1;
356 rom_boot_vector(corei);
357 return 0;
359 controller_set t_controllerconfig(std::map<std::string, std::string>& settings)
361 controller_magic();
362 controller_set r;
363 r.ports.push_back(&psystem);
364 r.logical_map.push_back(std::make_pair(0, 1));
365 return r;
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;
371 core_vma_info ram;
372 ram.name = "RAM";
373 ram.backing_ram = corei.state.as_ram().first;
374 ram.size = 131072;
375 ram.base = 0;
376 ram.endian = 0;
377 ram.volatile_flag = true;
378 r.push_back(ram);
379 core_vma_info wram;
380 wram.name = "WRAM";
381 wram.backing_ram = corei.state.as_ram().first + 131072;
382 wram.size = corei.state.as_ram().second - 131072 - 32;
383 wram.base = 131072;
384 wram.endian = 0;
385 wram.volatile_flag = true;
386 r.push_back(wram);
387 core_vma_info sram;
388 sram.name = "SRAM";
389 sram.backing_ram = corei.state.as_ram().first + corei.state.as_ram().second - 32;
390 sram.size = 32;
391 sram.base = corei.state.as_ram().second - 32;
392 sram.endian = 0;
393 sram.volatile_flag = false;
394 r.push_back(sram);
395 return r;
397 std::set<std::string> c_srams()
399 std::set<std::string> r;
400 r.insert("sram");
401 return r;
403 unsigned c_action_flags(unsigned id) { return 0; }
404 int c_reset_action(bool hard) { return -1; }
405 } sky_core;