X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=pico%2Fcart.c;h=a5c563d63db55163a956a590eb92b4610dda4024;hb=f9020f359ce58d56770c55d0ddb5fbb386cf2346;hp=5eb89c953b6d06b40838dcc429b0c51b6ae65072;hpb=45f2f245f51ef0c0d37df3c998595c132bfcaffa;p=picodrive.git diff --git a/pico/cart.c b/pico/cart.c index 5eb89c9..a5c563d 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 @@ -153,7 +157,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 +227,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); @@ -378,23 +382,21 @@ int pm_close(pm_file *fp) return ret; } - -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 +429,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 +440,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 +514,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 +522,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 +541,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 +561,7 @@ int PicoCartInsert(unsigned char *rom,unsigned int romsize) PicoCartUnloadHook(); PicoCartUnloadHook = NULL; } + pdb_cleanup(); PicoAHW &= PAHW_MCD|PAHW_SMS; @@ -574,7 +573,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 +594,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,17 +616,35 @@ 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) +{ + unsigned int crc; + elprintf(EL_STATUS, "caclulating CRC32.."); + + // have to unbyteswap for calculation.. + Byteswap(Pico.rom, Pico.rom, Pico.romsize); + crc = crc32(0, Pico.rom, Pico.romsize); + Byteswap(Pico.rom, Pico.rom, Pico.romsize); + return crc; } 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; @@ -643,6 +672,30 @@ static void rstrip(char *s) *p = 0; } +static int parse_3_vals(char *p, int *val0, int *val1, int *val2) +{ + char *r; + *val0 = strtoul(p, &r, 0); + if (r == p) + goto bad; + p = sskip(r); + if (*p++ != ',') + goto bad; + *val1 = strtoul(p, &r, 0); + if (r == p) + goto bad; + p = sskip(r); + if (*p++ != ',') + goto bad; + *val2 = strtoul(p, &r, 0); + if (r == p) + goto bad; + + return 1; +bad: + return 0; +} + static int is_expr(const char *expr, char **pr) { int len = strlen(expr); @@ -658,20 +711,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 == '#') @@ -739,6 +817,21 @@ static void parse_carthw(int *fill_sram) skip_sect = 1; continue; } + else if (is_expr("check_crc32", &p)) + { + unsigned int crc; + crc = strtoul(p, &r, 0); + if (r == p) + goto bad; + + if (rom_crc == 0) + rom_crc = rom_crc32(); + if (crc == rom_crc) + any_checks_passed = 1; + else + skip_sect = 1; + continue; + } /* now time for actions */ if (is_expr("hw", &p)) { @@ -750,12 +843,20 @@ static void parse_carthw(int *fill_sram) PicoSVPStartup(); else if (strcmp(p, "pico") == 0) PicoInitPico(); + else if (strcmp(p, "prot") == 0) + carthw_sprot_startup(); + else if (strcmp(p, "ssf2_mapper") == 0) + carthw_ssf2_startup(); else if (strcmp(p, "x_in_1_mapper") == 0) carthw_Xin1_startup(); else if (strcmp(p, "realtec_mapper") == 0) 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 { elprintf(EL_STATUS, "carthw:%d: unsupported mapper: %s", line, p); skip_sect = 1; @@ -798,10 +899,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)) { @@ -823,20 +927,10 @@ static void parse_carthw(int *fill_sram) goto no_checks; rstrip(p); - scl = strtoul(p, &r, 0); - if (r == p || scl < 0 || scl > 15) - goto bad; - p = sskip(r); - if (*p++ != ',') + if (!parse_3_vals(p, &scl, &sda_in, &sda_out)) goto bad; - sda_in = strtoul(p, &r, 0); - if (r == p || sda_in < 0 || sda_in > 15) - goto bad; - p = sskip(r); - if (*p++ != ',') - goto bad; - sda_out = strtoul(p, &r, 0); - if (r == p || sda_out < 0 || sda_out > 15) + if (scl < 0 || scl > 15 || sda_in < 0 || sda_in > 15 || + sda_out < 0 || sda_out > 15) goto bad; SRam.eeprom_bit_cl = scl; @@ -844,6 +938,18 @@ static void parse_carthw(int *fill_sram) SRam.eeprom_bit_out= sda_out; continue; } + else if ((tmp = is_expr("prot_ro_value16", &p)) || is_expr("prot_rw_value16", &p)) { + int addr, mask, val; + if (!any_checks_passed) + goto no_checks; + rstrip(p); + + if (!parse_3_vals(p, &addr, &mask, &val)) + goto bad; + + carthw_sprot_new_location(addr, mask, val, tmp ? 1 : 0); + continue; + } bad: @@ -857,17 +963,17 @@ 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, csum; - - csum = rom_read32(0x18c) & 0xffff; + int fill_sram = 0; memset(&SRam, 0, sizeof(SRam)); if (Pico.rom[0x1B1] == 'R' && Pico.rom[0x1B0] == 'A') @@ -895,7 +1001,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) { @@ -923,3 +1030,4 @@ static void PicoCartDetect(void) *(int *) (Pico.rom + 0x1f0) = 0x20204520; } +// vim:shiftwidth=2:expandtab