X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=pico%2Fcart.c;h=8614a16266900f020d483a73c204bb6297ccf256;hb=87b0845f3733166b491ae236feb8bc2eb0fca2ec;hp=06b7917d9a80518ccf820ae4822f22a4629f124f;hpb=672ee5eee2dd9b70492b62290735fecb63396114;p=picodrive.git diff --git a/pico/cart.c b/pico/cart.c index 06b7917..8614a16 100644 --- a/pico/cart.c +++ b/pico/cart.c @@ -13,12 +13,12 @@ #include "../unzip/unzip_stream.h" -static char *rom_exts[] = { "bin", "gen", "smd", "iso" }; +static const char *rom_exts[] = { "bin", "gen", "smd", "iso", "sms", "gg", "sg" }; void (*PicoCartUnloadHook)(void) = NULL; void (*PicoCartLoadProgressCB)(int percent) = NULL; -void (*PicoCDLoadProgressCB)(int percent) = NULL; // handled in Pico/cd/cd_file.c +void (*PicoCDLoadProgressCB)(const char *fname, int percent) = NULL; // handled in Pico/cd/cd_file.c static void PicoCartDetect(void); @@ -71,18 +71,31 @@ static int uncompress2(void *dest, int destLen, void *source, int sourceLen) return inflateEnd(&stream); } +static const char *get_ext(const char *path) +{ + const char *ext; + if (strlen(path) < 4) + return ""; // no ext + + // allow 2 or 3 char extensions for now + ext = path + strlen(path) - 2; + if (ext[-1] != '.') ext--; + if (ext[-1] != '.') + return ""; + return ext; +} + pm_file *pm_open(const char *path) { pm_file *file = NULL; const char *ext; FILE *f; - if (path == NULL) return NULL; - - if (strlen(path) < 5) ext = NULL; // no ext - else ext = path + strlen(path) - 3; + if (path == NULL) + return NULL; - if (ext && strcasecmp(ext, "zip") == 0) + ext = get_ext(path); + if (strcasecmp(ext, "zip") == 0) { struct zipent *zipentry; gzFile gzf = NULL; @@ -90,18 +103,19 @@ pm_file *pm_open(const char *path) int i; zipfile = openzip(path); - if (zipfile != NULL) { /* search for suitable file (right extension or large enough file) */ while ((zipentry = readzip(zipfile)) != NULL) { - if (zipentry->uncompressed_size >= 128*1024) goto found_rom_zip; - if (strlen(zipentry->name) < 5) continue; + ext = get_ext(zipentry->name); + + if (zipentry->uncompressed_size >= 32*1024) + goto found_rom_zip; - ext = zipentry->name+strlen(zipentry->name)-3; for (i = 0; i < sizeof(rom_exts)/sizeof(rom_exts[0]); i++) - if (strcasecmp(ext, rom_exts[i]) == 0) goto found_rom_zip; + if (strcasecmp(ext, rom_exts[i]) == 0) + goto found_rom_zip; } /* zipfile given, but nothing found suitable for us inside */ @@ -112,12 +126,13 @@ found_rom_zip: gzf = zip2gz(zipfile, zipentry); if (gzf == NULL) goto zip_failed; - file = malloc(sizeof(*file)); + file = calloc(1, sizeof(*file)); if (file == NULL) goto zip_failed; file->file = zipfile; file->param = gzf; file->size = zipentry->uncompressed_size; file->type = PMT_ZIP; + strncpy(file->ext, ext, sizeof(file->ext) - 1); return file; zip_failed: @@ -129,7 +144,7 @@ zip_failed: return NULL; } } - else if (ext && strcasecmp(ext, "cso") == 0) + else if (strcasecmp(ext, "cso") == 0) { cso_struct *cso = NULL, *tmp = NULL; int size; @@ -176,7 +191,7 @@ zip_failed: cso->fpos_in = ftell(f); cso->fpos_out = 0; cso->block_in_buff = -1; - file = malloc(sizeof(*file)); + file = calloc(1, sizeof(*file)); if (file == NULL) goto cso_failed; file->file = f; file->param = cso; @@ -194,7 +209,7 @@ cso_failed: f = fopen(path, "rb"); if (f == NULL) return NULL; - file = malloc(sizeof(*file)); + file = calloc(1, sizeof(*file)); if (file == NULL) { fclose(f); return NULL; @@ -204,6 +219,7 @@ cso_failed: file->param = NULL; file->size = ftell(f); file->type = PMT_UNCOMPRESSED; + strncpy(file->ext, ext, sizeof(file->ext) - 1); fseek(f, 0, SEEK_SET); #ifndef __EPOC32__ // makes things worse on Symbian @@ -418,37 +434,51 @@ static unsigned char *cd_realloc(void *old, int filesize) return rom; } -static unsigned char *PicoCartAlloc(int filesize) +static unsigned char *PicoCartAlloc(int filesize, int is_sms) { int alloc_size; unsigned char *rom; - if (PicoAHW & PAHW_MCD) return cd_realloc(NULL, filesize); + if (PicoAHW & PAHW_MCD) + return cd_realloc(NULL, filesize); + + if (is_sms) { + // make size power of 2 for easier banking handling + int s = 0, tmp = filesize; + while ((tmp >>= 1) != 0) + s++; + if (filesize > (1 << s)) + s++; + alloc_size = 1 << s; + } + else { + // align to 512K for memhandlers + alloc_size = (filesize + 0x7ffff) & ~0x7ffff; + } - alloc_size=filesize+0x7ffff; - if((filesize&0x3fff)==0x200) alloc_size-=0x200; - alloc_size&=~0x7ffff; // use alloc size of multiples of 512K, so that memhandlers could be set up more efficiently - if((filesize&0x3fff)==0x200) alloc_size+=0x200; - else if(alloc_size-filesize < 4) alloc_size+=4; // padding for out-of-bound exec protection + if (alloc_size - filesize < 4) + alloc_size += 4; // padding for out-of-bound exec protection // Allocate space for the rom plus padding - rom=(unsigned char *)malloc(alloc_size); - if(rom) memset(rom+alloc_size-0x80000,0,0x80000); + rom = calloc(alloc_size, 1); return rom; } -int PicoCartLoad(pm_file *f,unsigned char **prom,unsigned int *psize) +int PicoCartLoad(pm_file *f,unsigned char **prom,unsigned int *psize,int is_sms) { - unsigned char *rom=NULL; int size, bytes_read; - if (f==NULL) return 1; + unsigned char *rom; + int size, bytes_read; + + if (f == NULL) + return 1; - size=f->size; + size = f->size; if (size <= 0) return 1; - size=(size+3)&~3; // Round up to a multiple of 4 + size = (size+3)&~3; // Round up to a multiple of 4 // Allocate space for the rom plus padding - rom=PicoCartAlloc(size); - if (rom==NULL) { + rom = PicoCartAlloc(size, is_sms); + if (rom == NULL) { elprintf(EL_STATUS, "out of memory (wanted %i)", size); return 2; } @@ -478,22 +508,35 @@ int PicoCartLoad(pm_file *f,unsigned char **prom,unsigned int *psize) return 3; } - // maybe we are loading MegaCD BIOS? - if (!(PicoAHW & PAHW_MCD) && size == 0x20000 && (!strncmp((char *)rom+0x124, "BOOT", 4) || - !strncmp((char *)rom+0x128, "BOOT", 4))) { - PicoAHW |= PAHW_MCD; - rom = cd_realloc(rom, size); - } + if (!is_sms) + { + // maybe we are loading MegaCD BIOS? + if (!(PicoAHW & PAHW_MCD) && size == 0x20000 && (!strncmp((char *)rom+0x124, "BOOT", 4) || + !strncmp((char *)rom+0x128, "BOOT", 4))) { + PicoAHW |= PAHW_MCD; + rom = cd_realloc(rom, size); + } - // Check for SMD: - if (size >= 0x4200 && (size&0x3fff)==0x200 && - ((rom[0x2280] == 'S' && rom[0x280] == 'E') || (rom[0x280] == 'S' && rom[0x2281] == 'E'))) { - DecodeSmd(rom,size); size-=0x200; // Decode and byteswap SMD + // Check for SMD: + if (size >= 0x4200 && (size&0x3fff) == 0x200 && + ((rom[0x2280] == 'S' && rom[0x280] == 'E') || (rom[0x280] == 'S' && rom[0x2281] == 'E'))) { + elprintf(EL_STATUS, "SMD format detected."); + DecodeSmd(rom,size); size-=0x200; // Decode and byteswap SMD + } + else Byteswap(rom,size); // Just byteswap + } + else + { + if (size >= 0x4200 && (size&0x3fff) == 0x200) { + elprintf(EL_STATUS, "SMD format detected."); + // at least here it's not interleaved + size -= 0x200; + memmove(rom, rom + 0x200, size); + } } - else Byteswap(rom,size); // Just byteswap - if (prom) *prom=rom; - if (psize) *psize=size; + if (prom) *prom = rom; + if (psize) *psize = size; return 0; } @@ -520,7 +563,7 @@ int PicoCartInsert(unsigned char *rom,unsigned int romsize) PicoCartUnloadHook = NULL; } - PicoAHW &= PAHW_MCD; + PicoAHW &= PAHW_MCD|PAHW_SMS; PicoMemResetHooks(); PicoDmaHook = NULL; @@ -531,7 +574,7 @@ int PicoCartInsert(unsigned char *rom,unsigned int romsize) PicoMemReset(); - if (!(PicoAHW & PAHW_MCD)) + if (!(PicoAHW & (PAHW_MCD|PAHW_SMS))) PicoCartDetect(); // setup correct memory map for loaded ROM @@ -543,15 +586,25 @@ int PicoCartInsert(unsigned char *rom,unsigned int romsize) case PAHW_SVP: PicoMemSetup(); break; case PAHW_MCD: PicoMemSetupCD(); break; case PAHW_PICO: PicoMemSetupPico(); break; + case PAHW_SMS: PicoMemSetupMS(); break; } PicoMemReset(); - PicoPower(); + if (PicoAHW & PAHW_SMS) + PicoPowerMS(); + else + PicoPower(); + return 0; } void PicoCartUnload(void) { + if (PicoCartUnloadHook != NULL) { + PicoCartUnloadHook(); + PicoCartUnloadHook = NULL; + } + if (Pico.rom != NULL) { SekFinishIdleDet(); free(Pico.rom);