X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=pico%2Fcart.c;h=25a847d40a6b70acd5d2136cfafc0a81f3a799da;hb=925254c3fe875acc5d36cb9e5ac2a64851f011f6;hp=067b4227551c8385bba3d08c3dc371529139be06;hpb=000f53350cb0d6540310d8c4b02eb034c9662f0d;p=picodrive.git diff --git a/pico/cart.c b/pico/cart.c index 067b422..25a847d 100644 --- a/pico/cart.c +++ b/pico/cart.c @@ -1,18 +1,20 @@ -// 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" +static int rom_alloc_size; static const char *rom_exts[] = { "bin", "gen", "smd", "iso", "sms", "gg", "sg" }; void (*PicoCartUnloadHook)(void); @@ -21,7 +23,9 @@ void (*PicoCartMemSetup)(void); void (*PicoCartLoadProgressCB)(int percent) = NULL; void (*PicoCDLoadProgressCB)(const char *fname, int percent) = NULL; // handled in Pico/cd/cd_file.c -static void PicoCartDetect(void); +int PicoGameLoaded; + +static void PicoCartDetect(const char *carthw_cfg); /* cso struct */ typedef struct _cso_struct @@ -46,7 +50,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; @@ -96,6 +100,7 @@ pm_file *pm_open(const char *path) return NULL; ext = get_ext(path); +#ifndef NO_ZLIB if (strcasecmp(ext, "zip") == 0) { struct zipent *zipentry; @@ -145,7 +150,9 @@ zip_failed: return NULL; } } - else if (strcasecmp(ext, "cso") == 0) + else +#endif + if (strcasecmp(ext, "cso") == 0) { cso_struct *cso = NULL, *tmp = NULL; int size; @@ -153,7 +160,7 @@ zip_failed: if (f == NULL) goto cso_failed; -#ifndef __EPOC32__ +#ifdef __GP2X__ /* we use our own buffering */ setvbuf(f, NULL, _IONBF, 0); #endif @@ -223,7 +230,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); @@ -240,6 +247,7 @@ size_t pm_read(void *ptr, size_t bytes, pm_file *stream) { ret = fread(ptr, 1, bytes, stream->file); } +#ifndef NO_ZLIB else if (stream->type == PMT_ZIP) { gzFile gf = stream->param; @@ -250,6 +258,7 @@ size_t pm_read(void *ptr, size_t bytes, pm_file *stream) /* we must reset stream pointer or else next seek/read fails */ gzrewind(gf); } +#endif else if (stream->type == PMT_CSO) { cso_struct *cso = stream->param; @@ -289,7 +298,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; @@ -325,6 +334,7 @@ int pm_seek(pm_file *stream, long offset, int whence) fseek(stream->file, offset, whence); return ftell(stream->file); } +#ifndef NO_ZLIB else if (stream->type == PMT_ZIP) { if (PicoMessage != NULL && offset > 6*1024*1024) { @@ -334,6 +344,7 @@ int pm_seek(pm_file *stream, long offset, int whence) } return gzseek((gzFile) stream->param, offset, whence); } +#endif else if (stream->type == PMT_CSO) { cso_struct *cso = stream->param; @@ -359,6 +370,7 @@ int pm_close(pm_file *fp) { fclose(fp->file); } +#ifndef NO_ZLIB else if (fp->type == PMT_ZIP) { ZIP *zipfile = fp->file; @@ -366,6 +378,7 @@ int pm_close(pm_file *fp) zipfile->fp = NULL; // gzclose() closed it closezip(zipfile); } +#endif else if (fp->type == PMT_CSO) { free(fp->param); @@ -378,23 +391,21 @@ int pm_close(pm_file *fp) return ret; } - -static void Byteswap(unsigned char *data,int len) +// byteswap, data needs to be int aligned, src can match dst +void Byteswap(void *dst, const void *src, int len) { - int i=0; - - if (len<2) return; // Too short + const unsigned int *ps = src; + unsigned int *pd = dst; + int i, m; - do - { - unsigned short *pd=(unsigned short *)(data+i); - int value=*pd; // Get 2 bytes + if (len < 2) + return; - value=(value<<8)|(value>>8); // Byteswap it - *pd=(unsigned short)value; // Put 2b ytes - i+=2; + m = 0x00ff00ff; + for (i = 0; i < len / 4; i++) { + unsigned int t = ps[i]; + pd[i] = ((t & m) << 8) | ((t & ~m) >> 8); } - while (i+2<=len); } // Interleve a 16k block and byteswap @@ -427,22 +438,10 @@ static int DecodeSmd(unsigned char *data,int len) return 0; } -static unsigned char *cd_realloc(void *old, int filesize) -{ - unsigned char *rom; - rom=realloc(old, sizeof(mcd_state)); - if (rom) memset(rom+0x20000, 0, sizeof(mcd_state)-0x20000); - return rom; -} - 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 (is_sms) { // make size power of 2 for easier banking handling int s = 0, tmp = filesize; @@ -450,18 +449,27 @@ static unsigned char *PicoCartAlloc(int filesize, int is_sms) s++; if (filesize > (1 << s)) s++; - alloc_size = 1 << s; + rom_alloc_size = 1 << s; + // be sure we can cover all address space + if (rom_alloc_size < 0x10000) + rom_alloc_size = 0x10000; } else { + // make alloc size at least sizeof(mcd_state), + // in case we want to switch to CD mode + if (filesize < sizeof(mcd_state)) + filesize = sizeof(mcd_state); + // align to 512K for memhandlers - alloc_size = (filesize + 0x7ffff) & ~0x7ffff; + rom_alloc_size = (filesize + 0x7ffff) & ~0x7ffff; } - if (alloc_size - filesize < 4) - alloc_size += 4; // padding for out-of-bound exec protection + if (rom_alloc_size - filesize < 4) + rom_alloc_size += 4; // padding for out-of-bound exec protection // Allocate space for the rom plus padding - rom = calloc(alloc_size, 1); + // use special address for 32x dynarec + rom = plat_mmap(0x02000000, rom_alloc_size, 0, 0); return rom; } @@ -515,7 +523,6 @@ int PicoCartLoad(pm_file *f,unsigned char **prom,unsigned int *psize,int is_sms) 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: @@ -524,7 +531,7 @@ int PicoCartLoad(pm_file *f,unsigned char **prom,unsigned int *psize,int is_sms) elprintf(EL_STATUS, "SMD format detected."); DecodeSmd(rom,size); size-=0x200; // Decode and byteswap SMD } - else Byteswap(rom,size); // Just byteswap + else Byteswap(rom, rom, size); // Just byteswap } else { @@ -543,7 +550,7 @@ int PicoCartLoad(pm_file *f,unsigned char **prom,unsigned int *psize,int is_sms) } // Insert a cartridge: -int PicoCartInsert(unsigned char *rom,unsigned int romsize) +int PicoCartInsert(unsigned char *rom, unsigned int romsize, const char *carthw_cfg) { // notaz: add a 68k "jump one op back" opcode to the end of ROM. // This will hang the emu, but will prevent nasty crashes. @@ -563,6 +570,7 @@ int PicoCartInsert(unsigned char *rom,unsigned int romsize) PicoCartUnloadHook(); PicoCartUnloadHook = NULL; } + pdb_cleanup(); PicoAHW &= PAHW_MCD|PAHW_SMS; @@ -574,7 +582,7 @@ int PicoCartInsert(unsigned char *rom,unsigned int romsize) carthw_chunks = NULL; if (!(PicoAHW & (PAHW_MCD|PAHW_SMS))) - PicoCartDetect(); + PicoCartDetect(carthw_cfg); // setup correct memory map for loaded ROM switch (PicoAHW) { @@ -595,6 +603,18 @@ int PicoCartInsert(unsigned char *rom,unsigned int romsize) else PicoPower(); + PicoGameLoaded = 1; + return 0; +} + +int PicoCartResize(int newsize) +{ + void *tmp = plat_mremap(Pico.rom, rom_alloc_size, newsize); + if (tmp == NULL) + return -1; + + Pico.rom = tmp; + rom_alloc_size = newsize; return 0; } @@ -605,11 +625,15 @@ void PicoCartUnload(void) PicoCartUnloadHook = NULL; } + if (PicoAHW & PAHW_32X) + PicoUnload32x(); + if (Pico.rom != NULL) { SekFinishIdleDet(); - free(Pico.rom); - Pico.rom=NULL; + plat_munmap(Pico.rom, rom_alloc_size); + Pico.rom = NULL; } + PicoGameLoaded = 0; } static unsigned int rom_crc32(void) @@ -618,9 +642,9 @@ static unsigned int rom_crc32(void) elprintf(EL_STATUS, "caclulating CRC32.."); // have to unbyteswap for calculation.. - Byteswap(Pico.rom, Pico.romsize); + Byteswap(Pico.rom, Pico.rom, Pico.romsize); crc = crc32(0, Pico.rom, Pico.romsize); - Byteswap(Pico.rom, Pico.romsize); + Byteswap(Pico.rom, Pico.rom, Pico.romsize); return crc; } @@ -628,6 +652,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; @@ -694,21 +720,45 @@ static int is_expr(const char *expr, char **pr) return 1; } -static void parse_carthw(int *fill_sram) +#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) { - elprintf(EL_STATUS, "couldn't open carthw.txt!"); - return; - } + f = fopen(carthw_cfg, "r"); + if (f == NULL) + f = fopen("pico/carthw.cfg", "r"); + if (f == NULL) + elprintf(EL_STATUS, "couldn't open carthw.cfg!"); - 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 == '#') @@ -812,6 +862,8 @@ static void parse_carthw(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 { @@ -856,10 +908,13 @@ static void parse_carthw(int *fill_sram) SRam.flags &= ~SRF_EEPROM; else if (strcmp(p, "filled_sram") == 0) *fill_sram = 1; + else if (strcmp(p, "force_6btn") == 0) + PicoQuirks |= 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)) { @@ -917,13 +972,15 @@ no_checks: skip_sect = 1; continue; } - fclose(f); + + if (f != NULL) + fclose(f); } /* * various cart-specific things, which can't be handled by generic code */ -static void PicoCartDetect(void) +static void PicoCartDetect(const char *carthw_cfg) { int fill_sram = 0; @@ -953,7 +1010,8 @@ static void PicoCartDetect(void) SRam.eeprom_bit_in = 0; SRam.eeprom_bit_out= 0; - parse_carthw(&fill_sram); + if (carthw_cfg != NULL) + parse_carthw(carthw_cfg, &fill_sram); if (SRam.flags & SRF_ENABLED) { @@ -981,3 +1039,4 @@ static void PicoCartDetect(void) *(int *) (Pico.rom + 0x1f0) = 0x20204520; } +// vim:shiftwidth=2:expandtab