e85dde4b2d209da16fb1f3cc20b66d97d957b237
[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
16 bool hgwLaunched;
17 static HgwContext *hgw;
18
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 ? true : false;
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         int speedhacks = 0;
88         if (hgw_conf_request_int(hgw, kGConfFrameskip, &speedhacks) == HGW_ERR_NONE) {
89                 if (speedhacks <= 0) {
90                         Settings.HacksEnabled = FALSE;
91                         Settings.HacksFilter = FALSE;
92                 } else if (speedhacks == 1) {
93                         Settings.HacksEnabled = TRUE;
94                         Settings.HacksFilter = TRUE;
95                 } else {
96                         Settings.HacksEnabled = TRUE;
97                         Settings.HacksFilter = FALSE;
98                 }
99         }
100
101         int mappings = 0;
102         if (hgw_conf_request_int(hgw, kGConfMapping, &mappings) == HGW_ERR_NONE) {
103                 switch (mappings) {
104                         case 1:
105                                 parseGConfKeyMappings();
106                                 break;
107                 }
108         }
109
110         HgwStartCommand cmd = hgw_context_get_start_command(hgw);
111         switch (cmd) {
112                 default:
113                 case HGW_COMM_NONE:     // called from libosso
114                 case HGW_COMM_CONT:
115                         Config.snapshotLoad = true;
116                         Config.snapshotSave = true;
117                         break;
118                 case HGW_COMM_RESTART:
119                         Config.snapshotLoad = false;
120                         Config.snapshotSave = true;
121                         break;
122                 case HGW_COMM_QUIT:
123                         // hum, what?
124                         Config.snapshotLoad = false;
125                         Config.snapshotSave = false;
126                         Config.quitting = true;
127                         break;
128         }
129 }
130
131 void HgwPollEvents()
132 {
133         if (!hgwLaunched) return;
134         
135         HgwMessage msg;
136         HgwMessageFlags flags = HGW_MSG_FLAG_NONE;
137         
138         if ( hgw_msg_check_incoming(hgw, &msg, flags) == HGW_ERR_COMMUNICATION ) {
139                 // Message Incoming, process msg
140                 
141                 switch (msg.type) {
142                         case HGW_MSG_TYPE_CBREQ:
143                                 switch (msg.e_val) {
144                                         case HGW_CB_QUIT:
145                                         case HGW_CB_EXIT:
146                                                 Config.quitting = true;
147                                                 break;
148                                 }
149                                 break;
150                         case HGW_MSG_TYPE_DEVSTATE:
151                                 switch (msg.e_val) {
152                                         case HGW_DEVICE_STATE_SHUTDOWN:
153                                                 Config.quitting = true; // try to quit gracefully
154                                                 break;
155                                 }
156                                 break;
157                         default:
158                                 // do nothing
159                                 break;
160                 }
161                 
162                 hgw_msg_free_data(&msg);
163         }
164 }
165
166 // For now, please keep this in sync with ../gui/controls.c
167 typedef struct ButtonEntry {
168         char * gconf_key;
169         unsigned long mask;
170         bool is_action;
171 } ButtonEntry;
172 #define BUTTON_INITIALIZER(button, name) \
173         { kGConfKeysPath "/" name, SNES_##button##_MASK, false }
174 #define ACTION_INITIALIZER(action, name) \
175         { kGConfKeysPath "/" name, kAction##action, true }
176 #define BUTTON_LAST     \
177         { 0 }
178 static const ButtonEntry buttons[] = {
179         BUTTON_INITIALIZER(A, "a"),
180         BUTTON_INITIALIZER(B, "b"),
181         BUTTON_INITIALIZER(X, "x"),
182         BUTTON_INITIALIZER(Y, "y"),
183         BUTTON_INITIALIZER(TL, "l"),
184         BUTTON_INITIALIZER(TR, "r"),
185         BUTTON_INITIALIZER(START, "start"),
186         BUTTON_INITIALIZER(SELECT, "select"),
187         BUTTON_INITIALIZER(UP, "up"),
188         BUTTON_INITIALIZER(DOWN, "down"),
189         BUTTON_INITIALIZER(LEFT, "left"),
190         BUTTON_INITIALIZER(RIGHT, "right"),
191         ACTION_INITIALIZER(Quit, "quit"),
192         ACTION_INITIALIZER(ToggleFullscreen, "fullscreen"),
193         BUTTON_LAST
194 };
195
196 static void parseGConfKeyMappings()
197 {
198         // Discard any other mapping
199         ZeroMemory(Config.joypad1Mapping, sizeof(Config.joypad1Mapping));
200         ZeroMemory(Config.action, sizeof(Config.action));
201
202         // If the user does not map fullscreen or quit
203         bool quit_mapped = false;
204
205         printf("Hgw: Using gconf key mappings\n");
206
207         int i, scancode;
208         for (i = 0; buttons[i].gconf_key; i++) {
209                 if (hgw_conf_request_int(hgw, buttons[i].gconf_key, &scancode) == HGW_ERR_NONE) {
210                         if (scancode < 0) scancode = 0;
211                         else if (scancode > 255) scancode = 0;
212
213                         if (buttons[i].is_action) {
214                                 Config.action[scancode] = buttons[i].mask;
215                                 if (buttons[i].mask & (kActionQuit | kActionToggleFullscreen)) {
216                                         quit_mapped = true;
217                                 }
218                         } else {
219                                 Config.joypad1Mapping[scancode] = buttons[i].mask;
220                         }
221                 }
222         }
223
224         // Safeguards
225         if (!quit_mapped) {
226                 // Newbie user won't know how to quit game.
227                 if (!Config.joypad1Mapping[72] && !Config.action[72]) {
228                         // Fullscreen key is not mapped, map
229                         Config.action[72] = kActionQuit;
230                         quit_mapped = true;
231                 }
232                 if (!quit_mapped && !Config.joypad1Mapping[9] && !Config.action[9]) {
233                         // Escape key is not mapped, map
234                         // But only if we couldn't map quit to fullscreen. Some people
235                         // actually want Quit not to be mapped.
236                         Config.action[9] = kActionQuit;
237                         quit_mapped = true;
238                 }
239                 if (!quit_mapped) {
240                         // Force mapping of fullscreen to Quit if can't map anywhere else.
241                         Config.joypad1Mapping[72] = 0;
242                         Config.action[72] = kActionQuit;
243                 }
244         }
245 }
246