Namespace library port-controller stuff
[lsnes.git] / src / emulation / sky / sky.cpp
blob17210b14e830c794b88ad3128bfbf722f87e07cc
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/instance.hpp"
10 #include "core/messages.hpp"
11 #include "interface/romtype.hpp"
12 #include "interface/callbacks.hpp"
13 #include "library/framebuffer-pixfmt-rgb32.hpp"
15 namespace sky
17 bool pflag;
18 int cstyle = 0;
19 const unsigned iindexes[3][7] = {
20 {0, 1, 2, 3, 4, 5, 6},
21 {6, 7, 4, 5, 8, 3, 2},
22 {5, 4, 6, 7, 0, 3, 2}
25 struct interface_device_reg sky_registers[] = {
26 {NULL, NULL, NULL}
29 //Framebuffer.
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.
36 0, 0 //Offset.
39 struct instance corei;
41 portctrl::controller X4 = {"(system)", "(system)", {
42 {portctrl::button::TYPE_BUTTON, 'F', "framesync", true}
43 }};
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},
54 }};
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},
66 }};
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},
77 }};
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},
88 }};
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)
94 switch(idx) {
95 case 0:
96 switch(ctrl) {
97 case 0: if(x) buffer[0] |= 1; else buffer[0] &= ~1; break;
99 break;
100 case 1:
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)
131 switch(idx) {
132 case 0:
133 switch(ctrl) {
134 case 0: return (buffer[0] & 1) ? 1 : 0;
136 break;
137 case 1:
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;
163 break;
165 return 0;
167 size_t port_serialize(const portctrl::type* _this, const unsigned char* buffer, char* textbuf)
169 size_t ptr = 0;
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 portctrl::type* _this, unsigned char* buffer, const char* textbuf)
184 memset(buffer, 0, 2);
185 size_t ptr = 0;
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);
196 return ptr;
199 struct _psystem : public portctrl::type
201 _psystem() : portctrl::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 portctrl::index_triple t(unsigned p, unsigned c, unsigned i, bool nl)
213 portctrl::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 = &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;
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 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);
337 return x;
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)
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 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)
411 void c_debug_reset()
414 std::vector<std::string> c_get_trace_cpus()
416 std::vector<std::string> r;
417 return r;
419 } sky_core;