display-framerate and mappings options in gconf
[drnoksnes] / platform / hgw.cpp
1 #include <stdio.h>
2 #include <hgw/hgw.h>
3
4 #include "platform.h"
5 #include "hgw.h"
6 #include "snes9x.h"
7
8 #define DIE(format, ...) do { \
9                 fprintf(stderr, "Died at %s:%d: ", __FILE__, __LINE__ ); \
10                 fprintf(stderr, format "\n", ## __VA_ARGS__); \
11                 abort(); \
12         } while (0);
13
14
15 bool hgwLaunched;
16 static HgwContext *hgw;
17
18 static void createActionMappingsOnly();
19 static void parseGConfKeyMappings();
20
21 void HgwInit()
22 {
23         // hildon-games-wrapper sets this env variable for itself.
24         char* service = getenv("HGW_EXEC_SERVICE");
25         
26         if (!service) {
27                 // Not launched from hildon-games-wrapper
28                 hgwLaunched = false;
29                 return;
30         }
31         
32         hgw = hgw_context_init();
33         
34         if (!hgw) {
35                 fprintf(stderr, "Error opening hgw context\n");
36                 hgwLaunched = false;
37         }
38         
39         hgwLaunched = true;
40         printf("Loading in HGW mode\n");
41 }
42
43 void HgwDeinit()
44 {
45         if (!hgwLaunched) return;
46
47         hgw_context_destroy(hgw,
48                 (Config.snapshotSave ? HGW_BYE_PAUSED : HGW_BYE_INACTIVE));
49
50         hgw = 0;
51 }
52
53 void HgwConfig()
54 {
55         if (!hgwLaunched) return;
56         
57         Config.fullscreen = true;
58         
59         char romFile[PATH_MAX + 1];
60         if (hgw_conf_request_string(hgw, kGConfRomFile, romFile) == HGW_ERR_NONE) {
61                 S9xSetRomFile(romFile);
62         } else {
63                 hgw_context_destroy(hgw, HGW_BYE_INACTIVE);
64                 DIE("No Rom in Gconf!");
65         }
66
67         char no_audio = FALSE;
68         if (hgw_conf_request_bool(hgw, kGConfDisableAudio, &no_audio) == HGW_ERR_NONE) {
69                 Config.enableAudio = no_audio ? false : true;
70         }
71
72         char turbo = FALSE;
73         if (hgw_conf_request_bool(hgw, kGConfTurboMode, &turbo) == HGW_ERR_NONE) {
74                 Settings.TurboMode = turbo ? TRUE : FALSE;
75         }
76
77         int frameskip = 0;
78         if (hgw_conf_request_int(hgw, kGConfFrameskip, &frameskip) == HGW_ERR_NONE) {
79                 Settings.SkipFrames = (frameskip > 0 ? frameskip : AUTO_FRAMERATE);
80         }
81
82         char transparency = FALSE;
83         if (hgw_conf_request_bool(hgw, kGConfTransparency, &transparency) == HGW_ERR_NONE) {
84                 Settings.Transparency = transparency ? TRUE : FALSE;
85         }
86         
87         char displayFramerate = FALSE;
88         if (hgw_conf_request_bool(hgw, kGConfDisplayFramerate, &displayFramerate) == HGW_ERR_NONE) {
89                 Settings.DisplayFrameRate = displayFramerate ? TRUE : FALSE;
90         }
91
92         int speedhacks = 0;
93         if (hgw_conf_request_int(hgw, kGConfFrameskip, &speedhacks) == HGW_ERR_NONE) {
94                 if (speedhacks <= 0) {
95                         Settings.HacksEnabled = FALSE;
96                         Settings.HacksFilter = FALSE;
97                 } else if (speedhacks == 1) {
98                         Settings.HacksEnabled = TRUE;
99                         Settings.HacksFilter = TRUE;
100                 } else {
101                         Settings.HacksEnabled = TRUE;
102                         Settings.HacksFilter = FALSE;
103                 }
104         }
105
106         int mappings = 0;
107         if (hgw_conf_request_int(hgw, kGConfMapping, &mappings) == HGW_ERR_NONE) {
108                 switch (mappings) {
109                         case 0:
110                                 // Do nothing, leave mappings as is.
111                                 break;
112                         case 1: // Keys
113                                 parseGConfKeyMappings();
114                                 break;
115                         case 2: // Touchscreen
116                                 Config.touchscreenInput = true;
117                                 createActionMappingsOnly();
118                                 break;
119                         case 3: // Touchscreen + keys
120                                 Config.touchscreenInput = true;
121                                 parseGConfKeyMappings();
122                                 break;
123                         case 4: // Mouse
124                                 Settings.Mouse = TRUE;
125                                 Settings.ControllerOption = SNES_MOUSE_SWAPPED;
126                                 break;
127                         case 5: // Mouse + keys
128                                 Settings.Mouse = TRUE;
129                                 Settings.ControllerOption = SNES_MOUSE;
130                                 parseGConfKeyMappings();
131                                 break;
132                 }
133         }
134
135         HgwStartCommand cmd = hgw_context_get_start_command(hgw);
136         switch (cmd) {
137                 default:
138                 case HGW_COMM_NONE:     // called from libosso
139                 case HGW_COMM_CONT:
140                         Config.snapshotLoad = true;
141                         Config.snapshotSave = true;
142                         break;
143                 case HGW_COMM_RESTART:
144                         Config.snapshotLoad = false;
145                         Config.snapshotSave = true;
146                         break;
147                 case HGW_COMM_QUIT:
148                         // hum, what?
149                         Config.snapshotLoad = false;
150                         Config.snapshotSave = false;
151                         Config.quitting = true;
152                         break;
153         }
154 }
155
156 void HgwPollEvents()
157 {
158         if (!hgwLaunched) return;
159         
160         HgwMessage msg;
161         HgwMessageFlags flags = HGW_MSG_FLAG_NONE;
162         
163         if ( hgw_msg_check_incoming(hgw, &msg, flags) == HGW_ERR_COMMUNICATION ) {
164                 // Message Incoming, process msg
165                 
166                 switch (msg.type) {
167                         case HGW_MSG_TYPE_CBREQ:
168                                 switch (msg.e_val) {
169                                         case HGW_CB_QUIT:
170                                         case HGW_CB_EXIT:
171                                                 Config.quitting = true;
172                                                 break;
173                                 }
174                                 break;
175                         case HGW_MSG_TYPE_DEVSTATE:
176                                 switch (msg.e_val) {
177                                         case HGW_DEVICE_STATE_SHUTDOWN:
178                                                 Config.quitting = true; // try to quit gracefully
179                                                 break;
180                                 }
181                                 break;
182                         default:
183                                 // do nothing
184                                 break;
185                 }
186                 
187                 hgw_msg_free_data(&msg);
188         }
189 }
190
191 // For now, please keep this in sync with ../gui/controls.c
192 typedef struct ButtonEntry {
193         char * gconf_key;
194         unsigned long mask;
195         bool is_action;
196 } ButtonEntry;
197 #define BUTTON_INITIALIZER(button, name) \
198         { kGConfKeysPath "/" name, SNES_##button##_MASK, false }
199 #define ACTION_INITIALIZER(action, name) \
200         { kGConfKeysPath "/" name, kAction##action, true }
201 #define BUTTON_LAST     \
202         { 0 }
203 static const ButtonEntry buttons[] = {
204         BUTTON_INITIALIZER(A, "a"),
205         BUTTON_INITIALIZER(B, "b"),
206         BUTTON_INITIALIZER(X, "x"),
207         BUTTON_INITIALIZER(Y, "y"),
208         BUTTON_INITIALIZER(TL, "l"),
209         BUTTON_INITIALIZER(TR, "r"),
210         BUTTON_INITIALIZER(START, "start"),
211         BUTTON_INITIALIZER(SELECT, "select"),
212         BUTTON_INITIALIZER(UP, "up"),
213         BUTTON_INITIALIZER(DOWN, "down"),
214         BUTTON_INITIALIZER(LEFT, "left"),
215         BUTTON_INITIALIZER(RIGHT, "right"),
216         ACTION_INITIALIZER(Quit, "quit"),
217         ACTION_INITIALIZER(ToggleFullscreen, "fullscreen"),
218         BUTTON_LAST
219 };
220
221 static void createActionMappingsOnly()
222 {
223         // Discard any other mapping
224         ZeroMemory(Config.joypad1Mapping, sizeof(Config.joypad1Mapping));
225         ZeroMemory(Config.action, sizeof(Config.action));
226         
227         // Map quit to fullscreen and escape
228         Config.action[72] = kActionQuit;
229         Config.action[9] = kActionQuit;
230 }
231
232 static void parseGConfKeyMappings()
233 {
234         // Discard any other mapping
235         ZeroMemory(Config.joypad1Mapping, sizeof(Config.joypad1Mapping));
236         ZeroMemory(Config.action, sizeof(Config.action));
237
238         // If the user does not map fullscreen or quit
239         bool quit_mapped = false;
240
241         printf("Hgw: Using gconf key mappings\n");
242
243         int i, scancode;
244         for (i = 0; buttons[i].gconf_key; i++) {
245                 if (hgw_conf_request_int(hgw, buttons[i].gconf_key, &scancode) == HGW_ERR_NONE) {
246                         if (scancode <= 0 || scancode > 255) continue;
247
248                         if (buttons[i].is_action) {
249                                 Config.action[scancode] |= buttons[i].mask;
250                                 if (buttons[i].mask & (kActionQuit | kActionToggleFullscreen)) {
251                                         quit_mapped = true;
252                                 }
253                         } else {
254                                 Config.joypad1Mapping[scancode] |= buttons[i].mask;
255                         }
256                 }
257         }
258
259         // Safeguards
260         if (!quit_mapped) {
261                 // Newbie user won't know how to quit game.
262                 if (!Config.joypad1Mapping[72] && !Config.action[72]) {
263                         // Fullscreen key is not mapped, map
264                         Config.action[72] = kActionQuit;
265                         quit_mapped = true;
266                 }
267                 if (!quit_mapped && !Config.joypad1Mapping[9] && !Config.action[9]) {
268                         // Escape key is not mapped, map
269                         // But only if we couldn't map quit to fullscreen. Some people
270                         // actually want Quit not to be mapped.
271                         Config.action[9] = kActionQuit;
272                         quit_mapped = true;
273                 }
274                 if (!quit_mapped) {
275                         // Force mapping of fullscreen to Quit if can't map anywhere else.
276                         Config.joypad1Mapping[72] = 0;
277                         Config.action[72] = kActionQuit;
278                 }
279         }
280 }
281