X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=pico%2Fcart.c;h=58a9a68f7f81cf6eae6c27ddbb57281eba6e95e9;hb=6311a3baf533d4a034e51dfe38e8cb213a1bf442;hp=b060079b4724538544375e8e0c5cebbe21004174;hpb=e743be2070a13d14cae39a55b815b62b0edb6776;p=picodrive.git diff --git a/pico/cart.c b/pico/cart.c index b060079..58a9a68 100644 --- a/pico/cart.c +++ b/pico/cart.c @@ -1,17 +1,16 @@ -// This is part of Pico Library - -// (c) Copyright 2004 Dave, All rights reserved. -// (c) Copyright 2006-2007, Grazvydas "notaz" Ignotas -// Free for non-commercial use. - -// For commercial use, separate licencing terms must be obtained. - +/* + * PicoDrive + * (c) Copyright Dave, 2004 + * (C) notaz, 2006-2010 + * + * This work is licensed under the terms of MAME license. + * See COPYING file in the top-level directory. + */ #include "pico_int.h" -#include "../zlib/zlib.h" #include "../cpu/debug.h" #include "../unzip/unzip.h" -#include "../unzip/unzip_stream.h" +#include static int rom_alloc_size; @@ -23,6 +22,8 @@ void (*PicoCartMemSetup)(void); void (*PicoCartLoadProgressCB)(int percent) = NULL; void (*PicoCDLoadProgressCB)(const char *fname, int percent) = NULL; // handled in Pico/cd/cd_file.c +int PicoGameLoaded; + static void PicoCartDetect(const char *carthw_cfg); /* cso struct */ @@ -48,7 +49,7 @@ typedef struct _cso_struct } cso_struct; -static int uncompress2(void *dest, int destLen, void *source, int sourceLen) +static int uncompress_buf(void *dest, int destLen, void *source, int sourceLen) { z_stream stream; int err; @@ -88,6 +89,16 @@ static const char *get_ext(const char *path) return ext; } +struct zip_file { + pm_file file; + ZIP *zip; + struct zipent *entry; + z_stream stream; + unsigned char inbuf[16384]; + long start; + unsigned int pos; +}; + pm_file *pm_open(const char *path) { pm_file *file = NULL; @@ -100,10 +111,10 @@ pm_file *pm_open(const char *path) ext = get_ext(path); if (strcasecmp(ext, "zip") == 0) { + struct zip_file *zfile = NULL; struct zipent *zipentry; - gzFile gzf = NULL; ZIP *zipfile; - int i; + int i, ret; zipfile = openzip(path); if (zipfile != NULL) @@ -125,25 +136,29 @@ pm_file *pm_open(const char *path) goto zip_failed; found_rom_zip: - /* try to convert to gzip stream, so we could use standard gzio functions from zlib */ - gzf = zip2gz(zipfile, zipentry); - if (gzf == NULL) goto zip_failed; - - 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; + zfile = calloc(1, sizeof(*zfile)); + if (zfile == NULL) + goto zip_failed; + ret = seekcompresszip(zipfile, zipentry); + if (ret != 0) + goto zip_failed; + ret = inflateInit2(&zfile->stream, -15); + if (ret != Z_OK) { + elprintf(EL_STATUS, "zip: inflateInit2 %d", ret); + goto zip_failed; + } + zfile->zip = zipfile; + zfile->entry = zipentry; + zfile->start = ftell(zipfile->fp); + zfile->file.file = zfile; + zfile->file.size = zipentry->uncompressed_size; + zfile->file.type = PMT_ZIP; + strncpy(zfile->file.ext, ext, sizeof(zfile->file.ext) - 1); + return &zfile->file; zip_failed: - if (gzf) { - gzclose(gzf); - zipfile->fp = NULL; // gzclose() closed it - } closezip(zipfile); + free(zfile); return NULL; } } @@ -155,7 +170,7 @@ zip_failed: if (f == NULL) goto cso_failed; -#ifndef __EPOC32__ +#ifdef __GP2X__ /* we use our own buffering */ setvbuf(f, NULL, _IONBF, 0); #endif @@ -225,7 +240,7 @@ cso_failed: strncpy(file->ext, ext, sizeof(file->ext) - 1); fseek(f, 0, SEEK_SET); -#ifndef __EPOC32__ // makes things worse on Symbian +#ifdef __GP2X__ if (file->size > 0x400000) /* we use our own buffering */ setvbuf(f, NULL, _IONBF, 0); @@ -244,13 +259,33 @@ size_t pm_read(void *ptr, size_t bytes, pm_file *stream) } else if (stream->type == PMT_ZIP) { - gzFile gf = stream->param; - int err; - ret = gzread(gf, ptr, bytes); - err = gzerror2(gf); - if (ret > 0 && (err == Z_DATA_ERROR || err == Z_STREAM_END)) - /* we must reset stream pointer or else next seek/read fails */ - gzrewind(gf); + struct zip_file *z = stream->file; + + if (z->entry->compression_method == 0) { + int ret = fread(ptr, 1, bytes, z->zip->fp); + z->pos += ret; + return ret; + } + + z->stream.next_out = ptr; + z->stream.avail_out = bytes; + while (z->stream.avail_out != 0) { + if (z->stream.avail_in == 0) { + z->stream.avail_in = fread(z->inbuf, 1, sizeof(z->inbuf), z->zip->fp); + if (z->stream.avail_in == 0) + break; + z->stream.next_in = z->inbuf; + } + ret = inflate(&z->stream, Z_NO_FLUSH); + if (ret == Z_STREAM_END) + break; + if (ret != Z_OK) { + elprintf(EL_STATUS, "zip: inflate: %d", ret); + return 0; + } + } + z->pos += bytes - z->stream.avail_out; + return bytes - z->stream.avail_out; } else if (stream->type == PMT_CSO) { @@ -291,7 +326,7 @@ size_t pm_read(void *ptr, size_t bytes, pm_file *stream) } cso->block_in_buff = block; } - rret = uncompress2(tmp_dst, 2048, cso->in_buff, read_len); + rret = uncompress_buf(tmp_dst, 2048, cso->in_buff, read_len); if (rret != 0) { elprintf(EL_STATUS, "cso: uncompress failed @ %08x with %i", read_pos, rret); break; @@ -329,12 +364,45 @@ int pm_seek(pm_file *stream, long offset, int whence) } else if (stream->type == PMT_ZIP) { - if (PicoMessage != NULL && offset > 6*1024*1024) { - long pos = gztell((gzFile) stream->param); - if (offset < pos || offset - pos > 6*1024*1024) - PicoMessage("Decompressing data..."); + struct zip_file *z = stream->file; + unsigned int pos = z->pos; + int ret; + + switch (whence) + { + case SEEK_CUR: pos += offset; break; + case SEEK_SET: pos = offset; break; + case SEEK_END: pos = stream->size - offset; break; + } + if (z->entry->compression_method == 0) { + ret = fseek(z->zip->fp, z->start + pos, SEEK_SET); + if (ret == 0) + return (z->pos = pos); + return -1; } - return gzseek((gzFile) stream->param, offset, whence); + offset = pos - z->pos; + if (pos < z->pos) { + // full decompress from the start + fseek(z->zip->fp, z->start, SEEK_SET); + z->stream.avail_in = 0; + z->stream.next_in = z->inbuf; + inflateReset(&z->stream); + z->pos = 0; + offset = pos; + } + + if (PicoIn.osdMessage != NULL && offset > 4 * 1024 * 1024) + PicoIn.osdMessage("Decompressing data..."); + + while (offset > 0) { + char buf[16 * 1024]; + size_t l = offset > sizeof(buf) ? sizeof(buf) : offset; + ret = pm_read(buf, l, stream); + if (ret != l) + break; + offset -= l; + } + return z->pos; } else if (stream->type == PMT_CSO) { @@ -363,10 +431,9 @@ int pm_close(pm_file *fp) } else if (fp->type == PMT_ZIP) { - ZIP *zipfile = fp->file; - gzclose((gzFile) fp->param); - zipfile->fp = NULL; // gzclose() closed it - closezip(zipfile); + struct zip_file *z = fp->file; + inflateEnd(&z->stream); + closezip(z->zip); } else if (fp->type == PMT_CSO) { @@ -502,16 +569,16 @@ int PicoCartLoad(pm_file *f,unsigned char **prom,unsigned int *psize,int is_sms) bytes_read = pm_read(rom,size,f); // Load up the rom if (bytes_read <= 0) { elprintf(EL_STATUS, "read failed"); - free(rom); + plat_munmap(rom, rom_alloc_size); return 3; } if (!is_sms) { // maybe we are loading MegaCD BIOS? - if (!(PicoAHW & PAHW_MCD) && size == 0x20000 && (!strncmp((char *)rom+0x124, "BOOT", 4) || + if (!(PicoIn.AHW & PAHW_MCD) && size == 0x20000 && (!strncmp((char *)rom+0x124, "BOOT", 4) || !strncmp((char *)rom+0x128, "BOOT", 4))) { - PicoAHW |= PAHW_MCD; + PicoIn.AHW |= PAHW_MCD; } // Check for SMD: @@ -550,9 +617,9 @@ int PicoCartInsert(unsigned char *rom, unsigned int romsize, const char *carthw_ Pico.rom=rom; Pico.romsize=romsize; - if (SRam.data) { - free(SRam.data); - SRam.data = NULL; + if (Pico.sv.data) { + free(Pico.sv.data); + Pico.sv.data = NULL; } if (PicoCartUnloadHook != NULL) { @@ -561,7 +628,7 @@ int PicoCartInsert(unsigned char *rom, unsigned int romsize, const char *carthw_ } pdb_cleanup(); - PicoAHW &= PAHW_MCD|PAHW_SMS; + PicoIn.AHW &= PAHW_MCD|PAHW_SMS; PicoCartMemSetup = NULL; PicoDmaHook = NULL; @@ -570,13 +637,13 @@ int PicoCartInsert(unsigned char *rom, unsigned int romsize, const char *carthw_ PicoLoadStateHook = NULL; carthw_chunks = NULL; - if (!(PicoAHW & (PAHW_MCD|PAHW_SMS))) + if (!(PicoIn.AHW & (PAHW_MCD|PAHW_SMS))) PicoCartDetect(carthw_cfg); // setup correct memory map for loaded ROM - switch (PicoAHW) { + switch (PicoIn.AHW) { default: - elprintf(EL_STATUS|EL_ANOMALY, "starting in unknown hw configuration: %x", PicoAHW); + elprintf(EL_STATUS|EL_ANOMALY, "starting in unknown hw configuration: %x", PicoIn.AHW); case 0: case PAHW_SVP: PicoMemSetup(); break; case PAHW_MCD: PicoMemSetupCD(); break; @@ -587,11 +654,12 @@ int PicoCartInsert(unsigned char *rom, unsigned int romsize, const char *carthw_ if (PicoCartMemSetup != NULL) PicoCartMemSetup(); - if (PicoAHW & PAHW_SMS) + if (PicoIn.AHW & PAHW_SMS) PicoPowerMS(); else PicoPower(); + PicoGameLoaded = 1; return 0; } @@ -613,7 +681,7 @@ void PicoCartUnload(void) PicoCartUnloadHook = NULL; } - if (PicoAHW & PAHW_32X) + if (PicoIn.AHW & PAHW_32X) PicoUnload32x(); if (Pico.rom != NULL) { @@ -621,6 +689,7 @@ void PicoCartUnload(void) plat_munmap(Pico.rom, rom_alloc_size); Pico.rom = NULL; } + PicoGameLoaded = 0; } static unsigned int rom_crc32(void) @@ -639,6 +708,8 @@ static int rom_strcmp(int rom_offset, const char *s1) { int i, len = strlen(s1); const char *s_rom = (const char *)Pico.rom; + if (rom_offset + len > Pico.romsize) + return 0; for (i = 0; i < len; i++) if (s1[i] != s_rom[(i + rom_offset) ^ 1]) return 1; @@ -705,21 +776,45 @@ static int is_expr(const char *expr, char **pr) return 1; } +#include "carthw_cfg.c" + static void parse_carthw(const char *carthw_cfg, int *fill_sram) { int line = 0, any_checks_passed = 0, skip_sect = 0; + const char *s, *builtin = builtin_carthw_cfg; int tmp, rom_crc = 0; char buff[256], *p, *r; FILE *f; f = fopen(carthw_cfg, "r"); - if (f == NULL) { + if (f == NULL) + f = fopen("pico/carthw.cfg", "r"); + if (f == NULL) elprintf(EL_STATUS, "couldn't open carthw.cfg!"); - return; - } - while ((p = fgets(buff, sizeof(buff), f))) + for (;;) { + if (f != NULL) { + p = fgets(buff, sizeof(buff), f); + if (p == NULL) + break; + } + else { + if (*builtin == 0) + break; + for (s = builtin; *s != 0 && *s != '\n'; s++) + ; + while (*s == '\n') + s++; + tmp = s - builtin; + if (tmp > sizeof(buff) - 1) + tmp = sizeof(buff) - 1; + memcpy(buff, builtin, tmp); + buff[tmp] = 0; + p = buff; + builtin = s; + } + line++; p = sskip(p); if (*p == 0 || *p == '#') @@ -823,6 +918,8 @@ static void parse_carthw(const char *carthw_cfg, int *fill_sram) carthw_realtec_startup(); else if (strcmp(p, "radica_mapper") == 0) carthw_radica_startup(); + else if (strcmp(p, "piersolar_mapper") == 0) + carthw_pier_startup(); else if (strcmp(p, "prot_lk3") == 0) carthw_prot_lk3_startup(); else { @@ -852,8 +949,8 @@ static void parse_carthw(const char *carthw_cfg, int *fill_sram) elprintf(EL_STATUS, "carthw:%d: bad sram_range: %08x - %08x", line, start, end); goto bad_nomsg; } - SRam.start = start; - SRam.end = end; + Pico.sv.start = start; + Pico.sv.end = end; continue; } else if (is_expr("prop", &p)) { @@ -862,15 +959,18 @@ static void parse_carthw(const char *carthw_cfg, int *fill_sram) rstrip(p); if (strcmp(p, "no_sram") == 0) - SRam.flags &= ~SRF_ENABLED; + Pico.sv.flags &= ~SRF_ENABLED; else if (strcmp(p, "no_eeprom") == 0) - SRam.flags &= ~SRF_EEPROM; + Pico.sv.flags &= ~SRF_EEPROM; else if (strcmp(p, "filled_sram") == 0) *fill_sram = 1; + else if (strcmp(p, "force_6btn") == 0) + PicoIn.quirks |= PQUIRK_FORCE_6BTN; else { elprintf(EL_STATUS, "carthw:%d: unsupported prop: %s", line, p); goto bad_nomsg; } + elprintf(EL_STATUS, "game prop: %s", p); continue; } else if (is_expr("eeprom_type", &p)) { @@ -882,8 +982,8 @@ static void parse_carthw(const char *carthw_cfg, int *fill_sram) type = strtoul(p, &r, 0); if (r == p || type < 0) goto bad; - SRam.eeprom_type = type; - SRam.flags |= SRF_EEPROM; + Pico.sv.eeprom_type = type; + Pico.sv.flags |= SRF_EEPROM; continue; } else if (is_expr("eeprom_lines", &p)) { @@ -898,9 +998,9 @@ static void parse_carthw(const char *carthw_cfg, int *fill_sram) sda_out < 0 || sda_out > 15) goto bad; - SRam.eeprom_bit_cl = scl; - SRam.eeprom_bit_in = sda_in; - SRam.eeprom_bit_out= sda_out; + Pico.sv.eeprom_bit_cl = scl; + Pico.sv.eeprom_bit_in = sda_in; + Pico.sv.eeprom_bit_out= sda_out; continue; } else if ((tmp = is_expr("prot_ro_value16", &p)) || is_expr("prot_rw_value16", &p)) { @@ -928,7 +1028,9 @@ no_checks: skip_sect = 1; continue; } - fclose(f); + + if (f != NULL) + fclose(f); } /* @@ -938,54 +1040,54 @@ static void PicoCartDetect(const char *carthw_cfg) { int fill_sram = 0; - memset(&SRam, 0, sizeof(SRam)); + memset(&Pico.sv, 0, sizeof(Pico.sv)); if (Pico.rom[0x1B1] == 'R' && Pico.rom[0x1B0] == 'A') { - SRam.start = rom_read32(0x1B4) & ~0xff000001; // align - SRam.end = (rom_read32(0x1B8) & ~0xff000000) | 1; + Pico.sv.start = rom_read32(0x1B4) & ~0xff000001; // align + Pico.sv.end = (rom_read32(0x1B8) & ~0xff000000) | 1; if (Pico.rom[0x1B2] & 0x40) // EEPROM - SRam.flags |= SRF_EEPROM; - SRam.flags |= SRF_ENABLED; + Pico.sv.flags |= SRF_EEPROM; + Pico.sv.flags |= SRF_ENABLED; } - if (SRam.end == 0 || SRam.start > SRam.end) + if (Pico.sv.end == 0 || Pico.sv.start > Pico.sv.end) { // some games may have bad headers, like S&K and Sonic3 // note: majority games use 0x200000 as starting address, but there are some which // use something else (0x300000 by HardBall '95). Luckily they have good headers. - SRam.start = 0x200000; - SRam.end = 0x203FFF; - SRam.flags |= SRF_ENABLED; + Pico.sv.start = 0x200000; + Pico.sv.end = 0x203FFF; + Pico.sv.flags |= SRF_ENABLED; } // set EEPROM defaults, in case it gets detected - SRam.eeprom_type = 0; // 7bit (24C01) - SRam.eeprom_bit_cl = 1; - SRam.eeprom_bit_in = 0; - SRam.eeprom_bit_out= 0; + Pico.sv.eeprom_type = 0; // 7bit (24C01) + Pico.sv.eeprom_bit_cl = 1; + Pico.sv.eeprom_bit_in = 0; + Pico.sv.eeprom_bit_out= 0; if (carthw_cfg != NULL) parse_carthw(carthw_cfg, &fill_sram); - if (SRam.flags & SRF_ENABLED) + if (Pico.sv.flags & SRF_ENABLED) { - if (SRam.flags & SRF_EEPROM) - SRam.size = 0x2000; + if (Pico.sv.flags & SRF_EEPROM) + Pico.sv.size = 0x2000; else - SRam.size = SRam.end - SRam.start + 1; + Pico.sv.size = Pico.sv.end - Pico.sv.start + 1; - SRam.data = calloc(SRam.size, 1); - if (SRam.data == NULL) - SRam.flags &= ~SRF_ENABLED; + Pico.sv.data = calloc(Pico.sv.size, 1); + if (Pico.sv.data == NULL) + Pico.sv.flags &= ~SRF_ENABLED; - if (SRam.eeprom_type == 1) // 1 == 0 in PD EEPROM code - SRam.eeprom_type = 0; + if (Pico.sv.eeprom_type == 1) // 1 == 0 in PD EEPROM code + Pico.sv.eeprom_type = 0; } - if ((SRam.flags & SRF_ENABLED) && fill_sram) + if ((Pico.sv.flags & SRF_ENABLED) && fill_sram) { elprintf(EL_STATUS, "SRAM fill"); - memset(SRam.data, 0xff, SRam.size); + memset(Pico.sv.data, 0xff, Pico.sv.size); } // Unusual region 'code' @@ -993,3 +1095,4 @@ static void PicoCartDetect(const char *carthw_cfg) *(int *) (Pico.rom + 0x1f0) = 0x20204520; } +// vim:shiftwidth=2:expandtab