Make open() posix compliant api-wise. A few calls (those with O_CREAT) need the addit...
[kugel-rb.git] / apps / plugins / rockboy / loader.c
blobe92b7d0a7edee10cb3a8e2b73e8c185ba10f93ef
1 #include "rockmacros.h"
2 #include "defs.h"
3 #include "regs.h"
4 #include "mem.h"
5 #include "hw.h"
6 #include "lcd-gb.h"
7 #include "rtc-gb.h"
8 #include "save.h"
9 #include "sound.h"
11 /* From http://www.semis.demon.co.uk/Gameboy/Gbspec.txt (4/17/2007)
12 * Cartridge type:
13 * 0 - ROM ONLY 12 - ROM+MBC3+RAM
14 * 1 - ROM+MBC1 13 - ROM+MBC3+RAM+BATT
15 * 2 - ROM+MBC1+RAM 19 - ROM+MBC5
16 * 3 - ROM+MBC1+RAM+BATT 1A - ROM+MBC5+RAM
17 * 5 - ROM+MBC2 1B - ROM+MBC5+RAM+BATT
18 * 6 - ROM+MBC2+BATTERY 1C - ROM+MBC5+RUMBLE
19 * 8 - ROM+RAM 1D - ROM+MBC5+RUMBLE+SRAM
20 * 9 - ROM+RAM+BATTERY 1E - ROM+MBC5+RUMBLE+SRAM+BATT
21 * B - ROM+MMM01 1F - Pocket Camera
22 * C - ROM+MMM01+SRAM FD - Bandai TAMA5
23 * D - ROM+MMM01+SRAM+BATT FE - Hudson HuC-3
24 * F - ROM+MBC3+TIMER+BATT FF - Hudson HuC-1
25 * 10 - ROM+MBC3+TIMER+RAM+BATT
26 * 11 - ROM+MBC3
29 static const int mbc_table[256] =
31 MBC_NONE,
32 MBC_MBC1,
33 MBC_MBC1,
34 MBC_MBC1 | MBC_BAT,
36 MBC_MBC2,
37 MBC_MBC2 | MBC_BAT,
40 MBC_BAT,
44 MBC_BAT,
45 0,
46 MBC_MBC3 | MBC_BAT | MBC_RTC,
47 MBC_MBC3 | MBC_BAT | MBC_RTC,
48 MBC_MBC3,
49 MBC_MBC3,
50 MBC_MBC3 | MBC_BAT,
52 0,
53 0,
54 0,
56 MBC_MBC5,
57 MBC_MBC5,
58 MBC_MBC5 | MBC_BAT,
59 MBC_RUMBLE,
60 MBC_RUMBLE,
61 MBC_RUMBLE | MBC_BAT,
63 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
64 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
66 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
67 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
68 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
69 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
71 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
72 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
73 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
74 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
76 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
77 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
78 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
79 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
80 MBC_HUC3,
81 MBC_HUC1
84 static const unsigned short romsize_table[56] =
86 2, 4, 8, 16, 32, 64, 128, 256,
87 512, 0, 0, 0, 0, 0, 0, 0,
88 0, 0, 0, 0, 0, 0, 0, 0,
89 0, 0, 0, 0, 0, 0, 0, 0,
90 0, 0, 0, 0, 0, 0, 0, 0,
91 0, 0, 0, 0, 0, 0, 0, 0,
92 0, 0, 0, 0, 128, 128, 128, 0
93 /* 0, 0, 0, 0, 72, 80, 96 -- actual values but bad to use these! */
96 /* Ram size should be no larger then 16 banks 1Mbit */
97 static const unsigned char ramsize_table[5] =
99 0, 1, 1, 4, 16
102 static const char *romfile;
103 static char sramfile[500];
104 static char rtcfile[500];
105 static char saveprefix[500];
107 static int forcebatt, nobatt;
108 static int forcedmg;
110 static int memfill = -1, memrand = -1;
112 static void initmem(void *mem, int size)
114 char *p = mem;
115 if (memrand >= 0)
117 srand(memrand ? memrand : -6 ); /* time(0)); */
118 while(size--) *(p++) = rand();
120 else if (memfill >= 0)
121 memset(p, memfill, size);
124 static byte *loadfile(int fd, int *len)
126 int c;
127 byte *d;
129 *len=lseek(fd,0,SEEK_END);
130 d=malloc((*len)*sizeof(char)+64);
131 if(d==0)
133 die("Not enough memory");
134 return 0;
136 lseek(fd,0,SEEK_SET);
138 c = read(fd, d, *len);
140 return d;
143 static int rom_load(void)
145 int fd;
146 byte c, *data, *header;
147 int len = 0, rlen;
149 fd = open(romfile, O_RDONLY);
151 if (fd<0)
153 die("cannot open rom file %s", romfile);
154 return 1;
157 data = loadfile(fd, &len);
158 close(fd);
159 if(data==0)
161 die("Not Enough Memory");
162 return 1;
164 header = data; /* no zip. = decompress(data, &len); */
166 memcpy(rom.name, header+0x0134, 16);
167 if (rom.name[14] & 0x80) rom.name[14] = 0;
168 if (rom.name[15] & 0x80) rom.name[15] = 0;
169 rom.name[16] = 0;
171 c = header[0x0147];
172 mbc.type = mbc_table[c]&(MBC_MBC1|MBC_MBC2|MBC_MBC3|MBC_MBC5|MBC_RUMBLE|MBC_HUC1|MBC_HUC3);
173 mbc.batt = ((mbc_table[c]&MBC_BAT) && !nobatt) || forcebatt;
174 rtc.batt = mbc_table[c]&MBC_RTC;
176 if(header[0x0148]<10 || (header[0x0148]>51 && header[0x0148]<55))
177 mbc.romsize = romsize_table[header[0x0148]];
178 else
180 die("unknown ROM size %02X\n", header[0x0148]);
181 return 1;
184 if(header[0x0149]<5)
185 mbc.ramsize = ramsize_table[header[0x0149]];
186 else
188 die("unknown SRAM size %02X\n", header[0x0149]);
189 return 1;
192 rlen = 16384 * mbc.romsize;
193 rom.bank = (void *) data; /* realloc(data, rlen); */
194 if (rlen > len) memset(rom.bank[0]+len, 0xff, rlen - len);
196 /* This is the size of the ram on the cartridge
197 * See http://www.semis.demon.co.uk/Gameboy/Gbspec.txt
198 * for a full description. (8192*number of banks)
200 ram.sbank = malloc(8192 * mbc.ramsize);
201 if(ram.sbank==0 && mbc.ramsize!=0)
203 die("Not enough Memory");
204 return 1;
207 /* ram.ibank = malloc(4096*8); */
209 initmem(ram.sbank, 8192 * mbc.ramsize);
210 initmem(ram.ibank, 4096 * 8);
212 mbc.rombank = 1;
213 mbc.rambank = 0;
215 c = header[0x0143];
216 hw.cgb = ((c == 0x80) || (c == 0xc0)) && !forcedmg;
218 return 0;
221 static int sram_load(void)
223 int fd;
224 char meow[500];
226 if (!mbc.batt || !*sramfile) return -1;
228 /* Consider sram loaded at this point, even if file doesn't exist */
229 ram.loaded = 1;
231 fd = open(sramfile, O_RDONLY);
232 snprintf(meow,499,"Opening %s %d",sramfile,fd);
233 rb->splash(HZ*2, meow);
234 if (fd<0) return -1;
235 snprintf(meow,499,"Loading savedata from %s",sramfile);
236 rb->splash(HZ*2, meow);
237 read(fd,ram.sbank, 8192*mbc.ramsize);
238 close(fd);
240 return 0;
244 static int sram_save(void)
246 int fd;
247 char meow[500];
249 /* If we crash before we ever loaded sram, DO NOT SAVE! */
250 if (!mbc.batt || !ram.loaded || !mbc.ramsize)
251 return -1;
252 fd = open(sramfile, O_WRONLY|O_CREAT|O_TRUNC, 0666);
253 if (fd<0) return -1;
254 snprintf(meow,499,"Saving savedata to %s",sramfile);
255 rb->splash(HZ*2, meow);
256 write(fd,ram.sbank, 8192*mbc.ramsize);
257 close(fd);
259 return 0;
262 static void rtc_save(void)
264 int fd;
265 if (!rtc.batt) return;
266 if ((fd = open(rtcfile, O_WRONLY|O_CREAT|O_TRUNC, 0666))<0) return;
267 rtc_save_internal(fd);
268 close(fd);
271 static void rtc_load(void)
273 int fd;
274 if (!rtc.batt) return;
275 if ((fd = open(rtcfile, O_RDONLY))<0) return;
276 rtc_load_internal(fd);
277 close(fd);
280 void cleanup(void)
282 sram_save();
283 rtc_save();
284 /* IDEA - if error, write emergency savestate..? */
287 void loader_init(const char *s)
289 romfile = s;
290 if(rom_load())
291 return;
292 rb->splash(HZ/2, rom.name);
294 snprintf(saveprefix, 499, "%s/%s", savedir, rom.name);
296 strcpy(sramfile, saveprefix);
297 strcat(sramfile, ".sav");
299 strcpy(rtcfile, saveprefix);
300 strcat(rtcfile, ".rtc");
302 sram_load();
303 rtc_load();