]> git.lizzy.rs Git - plan9front.git/blob - sys/src/games/gba/gba.c
audiohda: fix syntax error
[plan9front.git] / sys / src / games / gba / gba.c
1 #include <u.h>
2 #include <libc.h>
3 #include <thread.h>
4 #include <draw.h>
5 #include <keyboard.h>
6 #include "../eui.h"
7 #include "dat.h"
8 #include "fns.h"
9
10 int cpuhalt;
11 Image *tmp;
12 int backup;
13 int savefd, saveframes;
14 int clock;
15
16 char *biosfile = "/sys/games/lib/gbabios.bin";
17
18 void
19 writeback(void)
20 {
21         if(saveframes == 0)
22                 saveframes = 15;
23 }
24
25 void
26 flushback(void)
27 {
28         if(savefd >= 0)
29                 pwrite(savefd, back, nback, BACKTYPELEN);
30         saveframes = 0;
31 }
32
33 void
34 loadbios(void)
35 {
36         extern uchar bios[16384];
37
38         int fd;
39         
40         fd = open(biosfile, OREAD);
41         if(fd < 0)
42                 sysfatal("open: %r");
43         readn(fd, bios, 16384);
44         close(fd);
45 }
46
47 int
48 romtype(int *size)
49 {
50         u32int *p, n, v;
51         union {char a[4]; u32int u;} s1 = {"EEPR"}, s2 = {"SRAM"}, s3 = {"FLAS"};
52         
53         p = (u32int *) rom;
54         n = nrom / 4;
55         do{
56                 v = *p++;
57                 if(v == s1.u && memcmp(p - 1, "EEPROM_V", 8) == 0){
58                         print("backup type is either eeprom4 or eeprom64 -- can't detect which one\n");
59                         return NOBACK;
60                 }
61                 if(v == s2.u && memcmp(p - 1, "SRAM_V", 6) == 0){
62                         *size = 32*KB;
63                         return SRAM;
64                 }
65                 if(v == s3.u){
66                         if(memcmp(p - 1, "FLASH_V", 7) == 0 || memcmp(p - 1, "FLASH512_V", 10) == 0){
67                                 *size = 64*KB;
68                                 return FLASH;
69                         }
70                         if(memcmp(p - 1, "FLASH1M_V", 9) == 0){
71                                 *size = 128*KB;
72                                 return FLASH;
73                         }
74                 }
75         }while(--n);
76         return NOBACK;
77 }
78
79 int
80 parsetype(char *s, int *size)
81 {
82         if(strcmp(s, "eeprom4") == 0){
83                 *size = 512;
84                 return EEPROM;
85         }else if(strcmp(s, "eeprom64") == 0){
86                 *size = 8*KB;
87                 return EEPROM;
88         }else if(strcmp(s, "sram256") == 0){
89                 *size = 32*KB;
90                 return SRAM;
91         }else if(strcmp(s, "flash512") == 0){
92                 *size = 64*KB;
93                 return FLASH;
94         }else if(strcmp(s, "flash1024") == 0){
95                 *size = 128*KB;
96                 return FLASH;
97         }else
98                 return NOBACK;
99 }
100
101 void
102 typename(char *s, int type, int size)
103 {
104         char *st;
105         switch(type){
106         case EEPROM:
107                 st = "eeprom";
108                 break;
109         case FLASH:
110                 st = "flash";
111                 break;
112         case SRAM:
113                 st = "sram";
114                 break;
115         default:
116                 sysfatal("typestr: unknown type %d -- shouldn't happen", type);
117                 return;
118         }
119         snprint(s, BACKTYPELEN, "%s%d", st, size/128);
120 }
121
122 void
123 loadsave(char *file)
124 {
125         char *buf, *p;
126         char tstr[BACKTYPELEN];
127         int type, size;
128         
129         buf = emalloc(strlen(file) + 4);
130         strcpy(buf, file);
131         p = strrchr(buf, '.');
132         if(p == nil)
133                 p = buf + strlen(buf);
134         strcpy(p, ".sav");
135         savefd = open(buf, ORDWR);
136         if(savefd < 0){
137                 if(backup == NOBACK){
138                         backup = romtype(&nback);
139                         if(backup == NOBACK){
140                                 fprint(2, "failed to autodetect save format\n");
141                                 free(buf);
142                                 return;
143                         }
144                 }
145                 savefd = create(buf, OWRITE, 0664);
146                 if(savefd < 0){
147                         fprint(2, "create: %r");
148                         free(buf);
149                         return;
150                 }
151                 memset(tstr, 0, sizeof(tstr));
152                 typename(tstr, backup, nback);
153                 write(savefd, tstr, sizeof(tstr));
154                 back = emalloc(nback);
155                 memset(back, 0, nback);
156                 write(savefd, back, nback);
157                 free(buf);
158                 atexit(flushback);
159                 return;
160         }
161         readn(savefd, tstr, sizeof(tstr));
162         tstr[31] = 0;
163         type = parsetype(tstr, &size);
164         if(type == NOBACK || backup != NOBACK && (type != backup || nback != size))
165                 sysfatal("%s: invalid format", buf);
166         backup = type;
167         nback = size;
168         back = emalloc(nback);
169         readn(savefd, back, nback);
170         atexit(flushback);
171         free(buf);
172 }
173
174 void
175 loadrom(char *file)
176 {
177         int fd;
178         vlong sz;
179         
180         fd = open(file, OREAD);
181         if(fd < 0)
182                 sysfatal("open: %r");
183         sz = seek(fd, 0, 2);
184         if(sz <= 0 || sz > 32*1024*1024)
185                 sysfatal("invalid file size");
186         seek(fd, 0, 0);
187         nrom = sz;
188         rom = emalloc(nrom);
189         if(readn(fd, rom, sz) < sz)
190                 sysfatal("read: %r");
191         close(fd);
192         loadsave(file);
193         if(nrom == 32*KB*KB && backup == EEPROM)
194                 nrom -= 256;
195 }
196
197 void
198 flush(void)
199 {
200         int x;
201
202         flushmouse(1);
203         flushscreen();
204         flushaudio(audioout);
205
206         if(saveframes > 0 && --saveframes == 0)
207                 flushback();
208         
209         if((reg[KEYCNT] & 1<<14) != 0){
210                 x = reg[KEYCNT] & keys;
211                 if((reg[KEYCNT] & 1<<15) != 0){
212                         if(x == (reg[KEYCNT] & 0x3ff))
213                                 setif(IRQKEY);
214                 }else
215                         if(x != 0)
216                                 setif(IRQKEY);
217         }
218 }
219
220 void
221 usage(void)
222 {
223         fprint(2, "usage: %s [-a] [-s savetype] [-b biosfile] [-x scale] rom\n", argv0);
224         exits("usage");
225 }
226
227 void
228 threadmain(int argc, char **argv)
229 {
230         char *s;
231         int t;
232
233         ARGBEGIN {
234         case 'a':
235                 audioinit();
236                 break;
237         case 's':
238                 s = EARGF(usage());
239                 backup = parsetype(s, &nback);
240                 if(backup == NOBACK)
241                         sysfatal("unknown save type '%s'", s);
242                 break;
243         case 'b':
244                 biosfile = strdup(EARGF(usage()));
245                 break;
246         case 'x':
247                 fixscale = strtol(EARGF(usage()), nil, 0);
248                 break;
249         default:
250                 usage();
251         } ARGEND;
252         if(argc < 1)
253                 usage();
254
255         loadbios();
256         loadrom(argv[0]);
257         initemu(240, 160, 2, CHAN4(CIgnore, 1, CBlue, 5, CGreen, 5, CRed, 5), 1, nil);
258         regkey("b", 'z', 1<<1);
259         regkey("a", 'x', 1<<0);
260         regkey("l1", 'a', 1<<9);
261         regkey("r1", 's', 1<<8);
262         regkey("control", Kshift, 1<<2);
263         regkey("start", '\n', 1<<3);
264         regkey("up", Kup, 1<<6);
265         regkey("down", Kdown, 1<<7);
266         regkey("left", Kleft, 1<<5);
267         regkey("right", Kright, 1<<4);
268         eventinit();
269         memreset();
270         reset();
271         for(;;){
272                 if(savereq){
273                         savestate("gba.save");
274                         savereq = 0;
275                 }
276                 if(loadreq){
277                         loadstate("gba.save");
278                         loadreq = 0;
279                 }
280                 if(paused){
281                         qlock(&pauselock);
282                         qunlock(&pauselock);
283                 }
284                 if(dmaact)
285                         t = dmastep();
286                 else if(cpuhalt)
287                         t = 8;
288                 else
289                         t = step();
290                 clock += t;
291                 if((elist->time -= t) <= 0)
292                         popevent();
293         }
294 }