A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 316 lines 7.3 kB view raw
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" 10#include "loader.h" 11 12/* From http://www.semis.demon.co.uk/Gameboy/Gbspec.txt (4/17/2007) 13 * Cartridge type: 14 * 0 - ROM ONLY 12 - ROM+MBC3+RAM 15 * 1 - ROM+MBC1 13 - ROM+MBC3+RAM+BATT 16 * 2 - ROM+MBC1+RAM 19 - ROM+MBC5 17 * 3 - ROM+MBC1+RAM+BATT 1A - ROM+MBC5+RAM 18 * 5 - ROM+MBC2 1B - ROM+MBC5+RAM+BATT 19 * 6 - ROM+MBC2+BATTERY 1C - ROM+MBC5+RUMBLE 20 * 8 - ROM+RAM 1D - ROM+MBC5+RUMBLE+SRAM 21 * 9 - ROM+RAM+BATTERY 1E - ROM+MBC5+RUMBLE+SRAM+BATT 22 * B - ROM+MMM01 1F - Pocket Camera 23 * C - ROM+MMM01+SRAM FD - Bandai TAMA5 24 * D - ROM+MMM01+SRAM+BATT FE - Hudson HuC-3 25 * F - ROM+MBC3+TIMER+BATT FF - Hudson HuC-1 26 * 10 - ROM+MBC3+TIMER+RAM+BATT 27 * 11 - ROM+MBC3 28 */ 29 30static const int mbc_table[256] = 31{ 32 MBC_NONE, 33 MBC_MBC1, 34 MBC_MBC1, 35 MBC_MBC1 | MBC_BAT, 36 0, 37 MBC_MBC2, 38 MBC_MBC2 | MBC_BAT, 39 0, 40 0, 41 MBC_BAT, 42 0, 43 0, 44 0, 45 MBC_BAT, 46 0, 47 MBC_MBC3 | MBC_BAT | MBC_RTC, 48 MBC_MBC3 | MBC_BAT | MBC_RTC, 49 MBC_MBC3, 50 MBC_MBC3, 51 MBC_MBC3 | MBC_BAT, 52 0, 53 0, 54 0, 55 0, 56 0, 57 MBC_MBC5, 58 MBC_MBC5, 59 MBC_MBC5 | MBC_BAT, 60 MBC_RUMBLE, 61 MBC_RUMBLE, 62 MBC_RUMBLE | MBC_BAT, 63 0, 64 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66 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, 70 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71 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, 75 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76 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, 0, 0, 80 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81 MBC_HUC3, 82 MBC_HUC1 83}; 84 85static const unsigned short romsize_table[56] = 86{ 87 2, 4, 8, 16, 32, 64, 128, 256, 88 512, 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, 0, 0, 0, 0, 93 0, 0, 0, 0, 128, 128, 128, 0 94 /* 0, 0, 0, 0, 72, 80, 96 -- actual values but bad to use these! */ 95}; 96 97/* Ram size should be no larger then 16 banks 1Mbit */ 98static const unsigned char ramsize_table[5] = 99{ 100 0, 1, 1, 4, 16 101}; 102 103static const char *romfile; 104static char sramfile[500]; 105static char rtcfile[500]; 106static char snfile[500]; 107static char saveprefix[500]; 108 109static int forcebatt, nobatt; 110static int forcedmg; 111 112static int memfill = -1, memrand = -1; 113 114static void initmem(void *mem, int size) 115{ 116 char *p = mem; 117 if (memrand >= 0) 118 { 119 srand(memrand ? memrand : -6 ); /* time(0)); */ 120 while(size--) *(p++) = rand(); 121 } 122 else if (memfill >= 0) 123 memset(p, memfill, size); 124} 125 126static byte *loadfile(int fd, int *len) 127{ 128 byte *d; 129 130 *len=lseek(fd,0,SEEK_END); 131 d=malloc((*len)*sizeof(char)+64); 132 if(d==0) 133 { 134 die("Not enough memory"); 135 return 0; 136 } 137 lseek(fd,0,SEEK_SET); 138 139 read(fd, d, *len); 140 141 return d; 142} 143 144static int rom_load(void) 145{ 146 int fd; 147 byte c, *data, *header; 148 int len = 0, rlen; 149 150 fd = open(romfile, O_RDONLY); 151 152 if (fd<0) 153 { 154 die("cannot open rom file %s", romfile); 155 return 1; 156 } 157 158 data = loadfile(fd, &len); 159 close(fd); 160 if(data==0) 161 { 162 die("Not Enough Memory"); 163 return 1; 164 } 165 header = data; /* no zip. = decompress(data, &len); */ 166 167 memcpy(rom.name, header+0x0134, 16); 168 if (rom.name[14] & 0x80) rom.name[14] = 0; 169 if (rom.name[15] & 0x80) rom.name[15] = 0; 170 rom.name[16] = 0; 171 172 c = header[0x0147]; 173 mbc.type = mbc_table[c]&(MBC_MBC1|MBC_MBC2|MBC_MBC3|MBC_MBC5|MBC_RUMBLE|MBC_HUC1|MBC_HUC3); 174 mbc.batt = ((mbc_table[c]&MBC_BAT) && !nobatt) || forcebatt; 175 rtc.batt = mbc_table[c]&MBC_RTC; 176 177 if(header[0x0148]<10 || (header[0x0148]>51 && header[0x0148]<55)) 178 mbc.romsize = romsize_table[header[0x0148]]; 179 else 180 { 181 die("unknown ROM size %02X\n", header[0x0148]); 182 return 1; 183 } 184 185 if(header[0x0149]<5) 186 mbc.ramsize = ramsize_table[header[0x0149]]; 187 else 188 { 189 die("unknown SRAM size %02X\n", header[0x0149]); 190 return 1; 191 } 192 193 rlen = 16384 * mbc.romsize; 194 rom.bank = (void *) data; /* realloc(data, rlen); */ 195 if (rlen > len) memset(rom.bank[0]+len, 0xff, rlen - len); 196 197 /* This is the size of the ram on the cartridge 198 * See http://www.semis.demon.co.uk/Gameboy/Gbspec.txt 199 * for a full description. (8192*number of banks) 200 */ 201 ram.sbank = malloc(8192 * mbc.ramsize); 202 if(ram.sbank==0 && mbc.ramsize!=0) 203 { 204 die("Not enough Memory"); 205 return 1; 206 } 207 208 /* ram.ibank = malloc(4096*8); */ 209 210 initmem(ram.sbank, 8192 * mbc.ramsize); 211 initmem(ram.ibank, 4096 * 8); 212 213 mbc.rombank = 1; 214 mbc.rambank = 0; 215 216 c = header[0x0143]; 217 hw.cgb = ((c == 0x80) || (c == 0xc0)) && !forcedmg; 218 219 return 0; 220} 221 222static int sram_load(void) 223{ 224 int fd; 225 226 if (!mbc.batt || !*sramfile) return -1; 227 228 /* Consider sram loaded at this point, even if file doesn't exist */ 229 ram.loaded = 1; 230 231 fd = open(sramfile, O_RDONLY); 232 if (fd<0) return -1; 233 read(fd,ram.sbank, 8192*mbc.ramsize); 234 close(fd); 235 236 return 0; 237} 238 239 240static int sram_save(void) 241{ 242 int fd; 243 244 /* If we crash before we ever loaded sram, DO NOT SAVE! */ 245 if (!mbc.batt || !ram.loaded || !mbc.ramsize) 246 return -1; 247 fd = open(sramfile, O_WRONLY|O_CREAT|O_TRUNC, 0666); 248 if (fd<0) return -1; 249 write(fd,ram.sbank, 8192*mbc.ramsize); 250 close(fd); 251 252 return 0; 253} 254 255static void rtc_save(void) 256{ 257 int fd; 258 if (!rtc.batt) return; 259 if ((fd = open(rtcfile, O_WRONLY|O_CREAT|O_TRUNC, 0666))<0) return; 260 rtc_save_internal(fd); 261 close(fd); 262} 263 264static void rtc_load(void) 265{ 266 int fd; 267 if (!rtc.batt) return; 268 if ((fd = open(rtcfile, O_RDONLY))<0) return; 269 rtc_load_internal(fd); 270 close(fd); 271} 272 273void sn_save(void) 274{ 275 int fd; 276 if ((fd = open(snfile, O_WRONLY | O_CREAT, 0666)) < 0) 277 return; 278 savestate(fd); 279 close(fd); 280} 281 282void sn_load(void) 283{ 284 int fd; 285 if ((fd = open(snfile, O_RDONLY, 0666)) < 0) 286 return; 287 loadstate(fd); 288 close(fd); 289} 290 291void cleanup(void) 292{ 293 sram_save(); 294 rtc_save(); 295 /* IDEA - if error, write emergency savestate..? */ 296} 297 298void loader_init(const char *s) 299{ 300 romfile = s; 301 if(rom_load()) 302 return; 303 304 snprintf(saveprefix, 499, "%s/%s", savedir, rom.name); 305 306 strcpy(sramfile, saveprefix); 307 strcat(sramfile, ".sav"); 308 309 strcpy(rtcfile, saveprefix); 310 strcat(rtcfile, ".rtc"); 311 strcpy(snfile, saveprefix); 312 strcat(snfile, ".sn"); 313 314 sram_load(); 315 rtc_load(); 316}