mirror of
https://github.com/RaySollium99/picodrive.git
synced 2025-09-05 07:17:45 -04:00
Merge from libretro/master:7ff457f for repo synchronization
This commit is contained in:
parent
45d0add214
commit
a5085db3ea
19 changed files with 1015 additions and 311 deletions
76
pico/cart.c
76
pico/cart.c
|
@ -738,65 +738,75 @@ static unsigned char *PicoCartAlloc(int filesize, int is_sms)
|
|||
return rom;
|
||||
}
|
||||
|
||||
int PicoCartLoad(pm_file *f,unsigned char **prom,unsigned int *psize,int is_sms)
|
||||
int PicoCartLoad(pm_file *f, const unsigned char *rom, unsigned int romsize,
|
||||
unsigned char **prom, unsigned int *psize, int is_sms)
|
||||
{
|
||||
unsigned char *rom;
|
||||
unsigned char *rom_data = NULL;
|
||||
int size, bytes_read;
|
||||
|
||||
if (f == NULL)
|
||||
if (!f && !rom)
|
||||
return 1;
|
||||
|
||||
size = f->size;
|
||||
if (!rom)
|
||||
size = f->size;
|
||||
else
|
||||
size = romsize;
|
||||
|
||||
if (size <= 0) return 1;
|
||||
size = (size+3)&~3; // Round up to a multiple of 4
|
||||
|
||||
// Allocate space for the rom plus padding
|
||||
rom = PicoCartAlloc(size, is_sms);
|
||||
if (rom == NULL) {
|
||||
rom_data = PicoCartAlloc(size, is_sms);
|
||||
if (rom_data == NULL) {
|
||||
elprintf(EL_STATUS, "out of memory (wanted %i)", size);
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (PicoCartLoadProgressCB != NULL)
|
||||
{
|
||||
// read ROM in blocks, just for fun
|
||||
int ret;
|
||||
unsigned char *p = rom;
|
||||
bytes_read=0;
|
||||
do
|
||||
if (!rom) {
|
||||
if (PicoCartLoadProgressCB != NULL)
|
||||
{
|
||||
int todo = size - bytes_read;
|
||||
if (todo > 256*1024) todo = 256*1024;
|
||||
ret = pm_read(p,todo,f);
|
||||
bytes_read += ret;
|
||||
p += ret;
|
||||
PicoCartLoadProgressCB(bytes_read * 100LL / size);
|
||||
// read ROM in blocks, just for fun
|
||||
int ret;
|
||||
unsigned char *p = rom_data;
|
||||
bytes_read=0;
|
||||
do
|
||||
{
|
||||
int todo = size - bytes_read;
|
||||
if (todo > 256*1024) todo = 256*1024;
|
||||
ret = pm_read(p,todo,f);
|
||||
bytes_read += ret;
|
||||
p += ret;
|
||||
PicoCartLoadProgressCB(bytes_read * 100LL / size);
|
||||
}
|
||||
while (ret > 0);
|
||||
}
|
||||
else
|
||||
bytes_read = pm_read(rom_data,size,f); // Load up the rom
|
||||
|
||||
if (bytes_read <= 0) {
|
||||
elprintf(EL_STATUS, "read failed");
|
||||
plat_munmap(rom_data, rom_alloc_size);
|
||||
return 3;
|
||||
}
|
||||
while (ret > 0);
|
||||
}
|
||||
else
|
||||
bytes_read = pm_read(rom,size,f); // Load up the rom
|
||||
if (bytes_read <= 0) {
|
||||
elprintf(EL_STATUS, "read failed");
|
||||
plat_munmap(rom, rom_alloc_size);
|
||||
return 3;
|
||||
}
|
||||
memcpy(rom_data, rom, romsize);
|
||||
|
||||
if (!is_sms)
|
||||
{
|
||||
// maybe we are loading MegaCD BIOS?
|
||||
if (!(PicoIn.AHW & PAHW_MCD) && size == 0x20000 && (!strncmp((char *)rom+0x124, "BOOT", 4) ||
|
||||
!strncmp((char *)rom+0x128, "BOOT", 4))) {
|
||||
if (!(PicoIn.AHW & PAHW_MCD) && size == 0x20000 && (!strncmp((char *)rom_data+0x124, "BOOT", 4) ||
|
||||
!strncmp((char *)rom_data+0x128, "BOOT", 4))) {
|
||||
PicoIn.AHW |= PAHW_MCD;
|
||||
}
|
||||
|
||||
// Check for SMD:
|
||||
if (size >= 0x4200 && (size&0x3fff) == 0x200 &&
|
||||
((rom[0x2280] == 'S' && rom[0x280] == 'E') || (rom[0x280] == 'S' && rom[0x2281] == 'E'))) {
|
||||
((rom_data[0x2280] == 'S' && rom_data[0x280] == 'E') || (rom_data[0x280] == 'S' && rom_data[0x2281] == 'E'))) {
|
||||
elprintf(EL_STATUS, "SMD format detected.");
|
||||
DecodeSmd(rom,size); size-=0x200; // Decode and byteswap SMD
|
||||
DecodeSmd(rom_data,size); size-=0x200; // Decode and byteswap SMD
|
||||
}
|
||||
else Byteswap(rom, rom, size); // Just byteswap
|
||||
else Byteswap(rom_data, rom_data, size); // Just byteswap
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -804,11 +814,11 @@ int PicoCartLoad(pm_file *f,unsigned char **prom,unsigned int *psize,int is_sms)
|
|||
elprintf(EL_STATUS, "SMD format detected.");
|
||||
// at least here it's not interleaved
|
||||
size -= 0x200;
|
||||
memmove(rom, rom + 0x200, size);
|
||||
memmove(rom_data, rom_data + 0x200, size);
|
||||
}
|
||||
}
|
||||
|
||||
if (prom) *prom = rom;
|
||||
if (prom) *prom = rom_data;
|
||||
if (psize) *psize = size;
|
||||
|
||||
return 0;
|
||||
|
|
140
pico/media.c
140
pico/media.c
|
@ -31,35 +31,50 @@ static void get_ext(const char *file, char *ext)
|
|||
strlwr_(ext);
|
||||
}
|
||||
|
||||
static int detect_media(const char *fname)
|
||||
static int detect_media(const char *fname, const unsigned char *rom, unsigned int romsize)
|
||||
{
|
||||
static const short sms_offsets[] = { 0x7ff0, 0x3ff0, 0x1ff0 };
|
||||
static const char *sms_exts[] = { "sms", "gg", "sg" };
|
||||
static const char *md_exts[] = { "gen", "smd", "md" };
|
||||
static const char *pico_exts[] = { "pco" };
|
||||
char buff0[512], buff[32];
|
||||
unsigned short *d16;
|
||||
pm_file *pmf;
|
||||
char ext[5];
|
||||
unsigned short *d16 = NULL;
|
||||
pm_file *pmf = NULL;
|
||||
const char *ext_ptr = NULL;
|
||||
char ext[8];
|
||||
int i;
|
||||
|
||||
get_ext(fname, ext);
|
||||
ext[0] = '\0';
|
||||
if ((ext_ptr = strrchr(fname, '.'))) {
|
||||
strncpy(ext, ext_ptr + 1, sizeof(ext));
|
||||
ext[sizeof(ext) - 1] = '\0';
|
||||
}
|
||||
|
||||
// detect wrong extensions
|
||||
if (!strcmp(ext, ".srm") || !strcmp(ext, "s.gz") || !strcmp(ext, ".mds")) // s.gz ~ .mds.gz
|
||||
if (!strcmp(ext, "srm") || !strcmp(ext, "gz")) // s.gz ~ .mds.gz
|
||||
return PM_BAD_DETECT;
|
||||
|
||||
/* don't believe in extensions, except .cue */
|
||||
if (strcasecmp(ext, ".cue") == 0 || strcasecmp(ext, ".chd") == 0)
|
||||
/* don't believe in extensions, except .cue and .chd */
|
||||
if (strcasecmp(ext, "cue") == 0 || strcasecmp(ext, "chd") == 0)
|
||||
return PM_CD;
|
||||
|
||||
pmf = pm_open(fname);
|
||||
if (pmf == NULL)
|
||||
return PM_BAD_DETECT;
|
||||
/* Open rom file, if required */
|
||||
if (!rom) {
|
||||
pmf = pm_open(fname);
|
||||
if (pmf == NULL)
|
||||
return PM_BAD_DETECT;
|
||||
romsize = pmf->size;
|
||||
}
|
||||
|
||||
if (pm_read(buff0, 512, pmf) != 512) {
|
||||
pm_close(pmf);
|
||||
return PM_BAD_DETECT;
|
||||
if (!rom) {
|
||||
if (pm_read(buff0, 512, pmf) != 512) {
|
||||
pm_close(pmf);
|
||||
return PM_BAD_DETECT;
|
||||
}
|
||||
} else {
|
||||
if (romsize < 512)
|
||||
return PM_BAD_DETECT;
|
||||
memcpy(buff0, rom, 512);
|
||||
}
|
||||
|
||||
if (strncasecmp("SEGADISCSYSTEM", buff0 + 0x00, 14) == 0 ||
|
||||
|
@ -69,32 +84,53 @@ static int detect_media(const char *fname)
|
|||
}
|
||||
|
||||
/* check for SMD evil */
|
||||
if (pmf->size >= 0x4200 && (pmf->size & 0x3fff) == 0x200) {
|
||||
if (pm_seek(pmf, sms_offsets[0] + 0x200, SEEK_SET) == sms_offsets[0] + 0x200 &&
|
||||
pm_read(buff, 16, pmf) == 16 &&
|
||||
strncmp("TMR SEGA", buff, 8) == 0)
|
||||
if (romsize >= 0x4200 && (romsize & 0x3fff) == 0x200) {
|
||||
buff[0] = '\0';
|
||||
|
||||
if (!rom) {
|
||||
if (pm_seek(pmf, sms_offsets[0] + 0x200, SEEK_SET) == sms_offsets[0] + 0x200)
|
||||
pm_read(buff, 16, pmf);
|
||||
} else {
|
||||
if (romsize >= sms_offsets[0] + 0x200 + 16)
|
||||
memcpy(buff, rom + sms_offsets[0] + 0x200, 16);
|
||||
}
|
||||
|
||||
if (strncmp("TMR SEGA", buff, 8) == 0)
|
||||
goto looks_like_sms;
|
||||
|
||||
/* could parse further but don't bother */
|
||||
goto extension_check;
|
||||
}
|
||||
|
||||
if (pm_seek(pmf, 0x100, SEEK_SET) == 0x100 && pm_read(buff, 16, pmf) == 16) {
|
||||
/* PICO header? Almost always appropriately marked */
|
||||
buff[16] = '\0';
|
||||
if (strstr(buff, " PICO "))
|
||||
goto looks_like_pico;
|
||||
/* MD header? Act as TMSS BIOS here */
|
||||
if (strncmp(buff, "SEGA", 4) == 0 || strncmp(buff, " SEG", 4) == 0)
|
||||
goto looks_like_md;
|
||||
/* fetch header info */
|
||||
memset(buff, '\0', 17);
|
||||
if (!rom) {
|
||||
if (pm_seek(pmf, 0x100, SEEK_SET) == 0x100)
|
||||
pm_read(buff, 16, pmf);
|
||||
} else {
|
||||
if (romsize >= 0x100 + 16)
|
||||
memcpy(buff, rom + 0x100, 16);
|
||||
}
|
||||
/* PICO header? Almost always appropriately marked */
|
||||
if (strstr(buff, " PICO "))
|
||||
goto looks_like_pico;
|
||||
/* MD header? Act as TMSS BIOS here */
|
||||
if (strncmp(buff, "SEGA", 4) == 0 || strncmp(buff, " SEG", 4) == 0)
|
||||
goto looks_like_md;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sms_offsets); i++) {
|
||||
if (pm_seek(pmf, sms_offsets[i], SEEK_SET) != sms_offsets[i])
|
||||
continue;
|
||||
if (!rom) {
|
||||
if (pm_seek(pmf, sms_offsets[i], SEEK_SET) != sms_offsets[i])
|
||||
continue;
|
||||
|
||||
if (pm_read(buff, 16, pmf) != 16)
|
||||
continue;
|
||||
if (pm_read(buff, 16, pmf) != 16)
|
||||
continue;
|
||||
} else {
|
||||
if (romsize < sms_offsets[i] + 16)
|
||||
continue;
|
||||
|
||||
memcpy(buff, rom + sms_offsets[i], 16);
|
||||
}
|
||||
|
||||
if (strncmp("TMR SEGA", buff, 8) == 0)
|
||||
goto looks_like_sms;
|
||||
|
@ -103,20 +139,20 @@ static int detect_media(const char *fname)
|
|||
extension_check:
|
||||
/* probably some headerless thing. Maybe check the extension after all. */
|
||||
for (i = 0; i < ARRAY_SIZE(md_exts); i++)
|
||||
if (strcasecmp(pmf->ext, md_exts[i]) == 0)
|
||||
if (strcasecmp(ext, md_exts[i]) == 0)
|
||||
goto looks_like_md;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sms_exts); i++)
|
||||
if (strcasecmp(pmf->ext, sms_exts[i]) == 0)
|
||||
if (strcasecmp(ext, sms_exts[i]) == 0)
|
||||
goto looks_like_sms;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(pico_exts); i++)
|
||||
if (strcasecmp(pmf->ext, pico_exts[i]) == 0)
|
||||
if (strcasecmp(ext, pico_exts[i]) == 0)
|
||||
goto looks_like_pico;
|
||||
|
||||
/* If everything else fails, make a guess on the reset vector */
|
||||
d16 = (unsigned short *)(buff0 + 4);
|
||||
if ((((d16[0] << 16) | d16[1]) & 0xffffff) >= pmf->size) {
|
||||
if ((((d16[0] << 16) | d16[1]) & 0xffffff) >= romsize) {
|
||||
lprintf("bad MD reset vector, assuming SMS\n");
|
||||
goto looks_like_sms;
|
||||
}
|
||||
|
@ -215,6 +251,7 @@ int PicoCdCheck(const char *fname_in, int *pregion)
|
|||
}
|
||||
|
||||
enum media_type_e PicoLoadMedia(const char *filename,
|
||||
const unsigned char *rom, unsigned int romsize,
|
||||
const char *carthw_cfg_fname,
|
||||
const char *(*get_bios_filename)(int *region, const char *cd_fname),
|
||||
void (*do_region_override)(const char *media_filename))
|
||||
|
@ -222,13 +259,13 @@ enum media_type_e PicoLoadMedia(const char *filename,
|
|||
const char *rom_fname = filename;
|
||||
enum media_type_e media_type;
|
||||
enum cd_track_type cd_img_type = CT_UNKNOWN;
|
||||
pm_file *rom_file = NULL;
|
||||
unsigned char *rom_data = NULL;
|
||||
unsigned int rom_size = 0;
|
||||
pm_file *rom = NULL;
|
||||
int cd_region = 0;
|
||||
int ret;
|
||||
|
||||
media_type = detect_media(filename);
|
||||
media_type = detect_media(filename, rom, romsize);
|
||||
if (media_type == PM_BAD_DETECT)
|
||||
goto out;
|
||||
|
||||
|
@ -267,14 +304,16 @@ enum media_type_e PicoLoadMedia(const char *filename,
|
|||
PicoIn.AHW = PAHW_PICO;
|
||||
}
|
||||
|
||||
rom = pm_open(rom_fname);
|
||||
if (rom == NULL) {
|
||||
lprintf("Failed to open ROM\n");
|
||||
media_type = PM_ERROR;
|
||||
goto out;
|
||||
if (!rom) {
|
||||
rom_file = pm_open(rom_fname);
|
||||
if (rom_file == NULL) {
|
||||
lprintf("Failed to open ROM\n");
|
||||
media_type = PM_ERROR;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
ret = PicoCartLoad(rom, &rom_data, &rom_size, (PicoIn.AHW & PAHW_SMS) ? 1 : 0);
|
||||
ret = PicoCartLoad(rom_file, rom, romsize, &rom_data, &rom_size, (PicoIn.AHW & PAHW_SMS) ? 1 : 0);
|
||||
if (ret != 0) {
|
||||
if (ret == 2) lprintf("Out of memory\n");
|
||||
else if (ret == 3) lprintf("Read failed\n");
|
||||
|
@ -314,10 +353,19 @@ enum media_type_e PicoLoadMedia(const char *filename,
|
|||
|
||||
// simple test for GG. Do this here since m.hardware is nulled in Insert
|
||||
if ((PicoIn.AHW & PAHW_SMS) && !PicoIn.hwSelect) {
|
||||
if (!strcmp(rom->ext,"gg")) {
|
||||
const char *ext = NULL;
|
||||
if (rom_file && rom_file->ext && (*rom_file->ext != '\0')) {
|
||||
ext = rom_file->ext;
|
||||
}
|
||||
else if ((ext = strrchr(filename, '.'))) {
|
||||
if (*(++ext) == '\0') {
|
||||
ext = NULL;
|
||||
}
|
||||
}
|
||||
if (ext && !strcmp(ext,"gg") && !PicoIn.hwSelect) {
|
||||
Pico.m.hardware |= PMS_HW_GG;
|
||||
lprintf("detected GG ROM\n");
|
||||
} else if (!strcmp(rom->ext,"sg")) {
|
||||
} else if (ext && !strcmp(ext,"sg")) {
|
||||
Pico.m.hardware |= PMS_HW_SG;
|
||||
lprintf("detected SG-1000 ROM\n");
|
||||
} else
|
||||
|
@ -340,8 +388,8 @@ enum media_type_e PicoLoadMedia(const char *filename,
|
|||
PicoSetInputDevice(0, PICO_INPUT_PAD_6BTN);
|
||||
|
||||
out:
|
||||
if (rom)
|
||||
pm_close(rom);
|
||||
if (rom_file)
|
||||
pm_close(rom_file);
|
||||
if (rom_data)
|
||||
free(rom_data);
|
||||
return media_type;
|
||||
|
|
|
@ -188,7 +188,8 @@ size_t pm_read(void *ptr, size_t bytes, pm_file *stream);
|
|||
size_t pm_read_audio(void *ptr, size_t bytes, pm_file *stream);
|
||||
int pm_seek(pm_file *stream, long offset, int whence);
|
||||
int pm_close(pm_file *fp);
|
||||
int PicoCartLoad(pm_file *f,unsigned char **prom,unsigned int *psize,int is_sms);
|
||||
int PicoCartLoad(pm_file *f, const unsigned char *rom, unsigned int romsize,
|
||||
unsigned char **prom, unsigned int *psize, int is_sms);
|
||||
int PicoCartInsert(unsigned char *rom, unsigned int romsize, const char *carthw_cfg);
|
||||
void PicoCartUnload(void);
|
||||
extern void (*PicoCartLoadProgressCB)(int percent);
|
||||
|
@ -299,6 +300,7 @@ typedef struct
|
|||
|
||||
|
||||
enum media_type_e PicoLoadMedia(const char *filename,
|
||||
const unsigned char *rom, unsigned int romsize,
|
||||
const char *carthw_cfg_fname,
|
||||
const char *(*get_bios_filename)(int *region, const char *cd_fname),
|
||||
void (*do_region_override)(const char *media_filename));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue