4fbc36ac36e487b553448bbce2a3170a16cbe047
[libpicofe.git] / config_file.c
1 /*
2  * (C) GraÅžvydas "notaz" Ignotas, 2011-2012
3  *
4  * This work is licensed under the terms of any of these licenses
5  * (at your option):
6  *  - GNU GPL, version 2 or later.
7  *  - GNU LGPL, version 2.1 or later.
8  * See the COPYING file in the top-level directory.
9  */
10
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include "input.h"
15 #include "menu.h"
16 #include "config_file.h"
17 #include "lprintf.h"
18
19 #define array_size(x) (sizeof(x) / sizeof(x[0]))
20
21 static char *mystrip(char *str)
22 {
23         int i, len;
24
25         len = strlen(str);
26         for (i = 0; i < len; i++)
27                 if (str[i] != ' ') break;
28         if (i > 0) memmove(str, str + i, len - i + 1);
29
30         len = strlen(str);
31         for (i = len - 1; i >= 0; i--)
32                 if (str[i] != ' ' && str[i] != '\r' && str[i] != '\n') break;
33         str[i+1] = 0;
34
35         return str;
36 }
37
38 static void get_line(char *d, size_t size, const char *s)
39 {
40         const char *pe;
41         size_t len;
42
43         for (pe = s; *pe != '\r' && *pe != '\n' && *pe != 0; pe++)
44                 ;
45         len = pe - s;
46         if (len > size - 1)
47                 len = size - 1;
48         strncpy(d, s, len);
49         d[len] = 0;
50
51         mystrip(d);
52 }
53
54 void config_write_keys(FILE *f)
55 {
56         int d;
57
58         for (d = 0; d < IN_MAX_DEVS; d++)
59         {
60                 const int *binds = in_get_dev_binds(d);
61                 const char *name = in_get_dev_name(d, 0, 0);
62                 int k, count = 0;
63
64                 if (binds == NULL || name == NULL)
65                         continue;
66
67                 fprintf(f, "binddev = %s\n", name);
68                 in_get_config(d, IN_CFG_BIND_COUNT, &count);
69
70                 for (k = 0; k < count; k++)
71                 {
72                         int i, kbinds, mask;
73                         char act[32];
74
75                         act[0] = act[31] = 0;
76                         name = in_get_key_name(d, k);
77
78                         kbinds = binds[IN_BIND_OFFS(k, IN_BINDTYPE_PLAYER12)];
79                         for (i = 0; kbinds && me_ctrl_actions[i].name != NULL; i++) {
80                                 mask = me_ctrl_actions[i].mask;
81                                 if (mask & kbinds) {
82                                         strncpy(act, me_ctrl_actions[i].name, 31);
83                                         fprintf(f, "bind %s = player1 %s\n", name, mystrip(act));
84                                         kbinds &= ~mask;
85                                 }
86                                 mask = me_ctrl_actions[i].mask << 16;
87                                 if (mask & kbinds) {
88                                         strncpy(act, me_ctrl_actions[i].name, 31);
89                                         fprintf(f, "bind %s = player2 %s\n", name, mystrip(act));
90                                         kbinds &= ~mask;
91                                 }
92                         }
93
94                         kbinds = binds[IN_BIND_OFFS(k, IN_BINDTYPE_EMU)];
95                         for (i = 0; kbinds && emuctrl_actions[i].name != NULL; i++) {
96                                 mask = emuctrl_actions[i].mask;
97                                 if (mask & kbinds) {
98                                         strncpy(act, emuctrl_actions[i].name, 31);
99                                         fprintf(f, "bind %s = %s\n", name, mystrip(act));
100                                         kbinds &= ~mask;
101                                 }
102                         }
103                 }
104
105 #ifdef ANALOG_BINDS
106                 for (k = 0; k < array_size(in_adev); k++)
107                 {
108                         if (in_adev[k] == d)
109                                 fprintf(f, "bind_analog = %d\n", k);
110                 }
111 #endif
112         }
113 }
114
115 static int parse_bind_val(const char *val, int *type)
116 {
117         int i;
118
119         *type = IN_BINDTYPE_NONE;
120         if (val[0] == 0)
121                 return 0;
122         
123         if (strncasecmp(val, "player", 6) == 0)
124         {
125                 int player, shift = 0;
126                 player = atoi(val + 6) - 1;
127
128                 if ((unsigned int)player > 1)
129                         return -1;
130                 if (player == 1)
131                         shift = 16;
132
133                 *type = IN_BINDTYPE_PLAYER12;
134                 for (i = 0; me_ctrl_actions[i].name != NULL; i++) {
135                         if (strncasecmp(me_ctrl_actions[i].name, val + 8, strlen(val + 8)) == 0)
136                                 return me_ctrl_actions[i].mask << shift;
137                 }
138         }
139         for (i = 0; emuctrl_actions[i].name != NULL; i++) {
140                 if (strncasecmp(emuctrl_actions[i].name, val, strlen(val)) == 0) {
141                         *type = IN_BINDTYPE_EMU;
142                         return emuctrl_actions[i].mask;
143                 }
144         }
145
146         return -1;
147 }
148
149 void config_read_keys(const char *cfg)
150 {
151         char dev[256], key[128], *act;
152         const char *p;
153         int bind, bindtype;
154         int dev_id;
155
156         p = cfg;
157         while (p != NULL && (p = strstr(p, "binddev = ")) != NULL) {
158                 p += 10;
159
160                 get_line(dev, sizeof(dev), p);
161                 dev_id = in_config_parse_dev(dev);
162                 if (dev_id < 0) {
163                         printf("input: can't handle dev: %s\n", dev);
164                         continue;
165                 }
166
167                 in_unbind_all(dev_id, -1, -1);
168                 while ((p = strstr(p, "bind"))) {
169                         if (strncmp(p, "binddev = ", 10) == 0)
170                                 break;
171
172 #ifdef ANALOG_BINDS
173                         if (strncmp(p, "bind_analog", 11) == 0) {
174                                 int ret = sscanf(p, "bind_analog = %d", &bind);
175                                 p += 11;
176                                 if (ret != 1) {
177                                         printf("input: parse error: %16s..\n", p);
178                                         continue;
179                                 }
180                                 if ((unsigned int)bind >= array_size(in_adev)) {
181                                         printf("input: analog id %d out of range\n", bind);
182                                         continue;
183                                 }
184                                 in_adev[bind] = dev_id;
185                                 continue;
186                         }
187 #endif
188
189                         p += 4;
190                         if (*p != ' ') {
191                                 printf("input: parse error: %16s..\n", p);
192                                 continue;
193                         }
194
195                         get_line(key, sizeof(key), p);
196                         act = strchr(key, '=');
197                         if (act == NULL) {
198                                 printf("parse failed: %16s..\n", p);
199                                 continue;
200                         }
201                         *act = 0;
202                         act++;
203                         mystrip(key);
204                         mystrip(act);
205
206                         bind = parse_bind_val(act, &bindtype);
207                         if (bind != -1 && bind != 0) {
208                                 //printf("bind #%d '%s' %08x (%s)\n", dev_id, key, bind, act);
209                                 in_config_bind_key(dev_id, key, bind, bindtype);
210                         }
211                         else
212                                 lprintf("config: unhandled action \"%s\"\n", act);
213                 }
214         }
215         in_clean_binds();
216 }