mirror of
https://github.com/libretro/RetroArch
synced 2025-01-30 21:32:45 +00:00
Merge pull request #9521 from Jamiras/segacd_cheevos
(cheevos) support for Sega CD/Saturn; reduce hash calls to server
This commit is contained in:
commit
38fe58e746
@ -1068,7 +1068,9 @@ static void rcheevos_unlock_cb(unsigned id, void* userdata)
|
||||
#ifndef CHEEVOS_DONT_DEACTIVATE
|
||||
cheevo->active &= ~*(unsigned*)userdata;
|
||||
#endif
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "cheevo %u deactivated: %s\n", id, cheevo->info->title);
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "cheevo %u deactivated (%s): %s\n", id,
|
||||
(*(unsigned*)userdata) == RCHEEVOS_ACTIVE_HARDCORE ? "hardcore" : "softcore",
|
||||
cheevo->info->title);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1099,8 +1101,9 @@ typedef struct
|
||||
char url[256];
|
||||
char badge_basepath[PATH_MAX_LENGTH];
|
||||
char badge_fullpath[PATH_MAX_LENGTH];
|
||||
unsigned char last_hash[16];
|
||||
unsigned char hash[16];
|
||||
bool round;
|
||||
unsigned ext_hash;
|
||||
unsigned gameid;
|
||||
unsigned i;
|
||||
unsigned j;
|
||||
@ -1133,14 +1136,14 @@ typedef struct
|
||||
enum
|
||||
{
|
||||
/* Negative values because CORO_SUB generates positive values */
|
||||
RCHEEVOS_SNES_MD5 = -1,
|
||||
RCHEEVOS_GENESIS_MD5 = -2,
|
||||
RCHEEVOS_GENERIC_MD5 = -1,
|
||||
RCHEEVOS_SNES_MD5 = -2,
|
||||
RCHEEVOS_LYNX_MD5 = -3,
|
||||
RCHEEVOS_NES_MD5 = -4,
|
||||
RCHEEVOS_GENERIC_MD5 = -5,
|
||||
RCHEEVOS_FILENAME_MD5 = -6,
|
||||
RCHEEVOS_PSX_MD5 = -5,
|
||||
RCHEEVOS_ARCADE_MD5 = -6,
|
||||
RCHEEVOS_EVAL_MD5 = -7,
|
||||
RCHEEVOS_FILL_MD5 = -8,
|
||||
RCHEEVOS_SEGACD_MD5 = -8,
|
||||
RCHEEVOS_GET_GAMEID = -9,
|
||||
RCHEEVOS_GET_CHEEVOS = -10,
|
||||
RCHEEVOS_GET_BADGES = -11,
|
||||
@ -1148,8 +1151,7 @@ enum
|
||||
RCHEEVOS_HTTP_GET = -13,
|
||||
RCHEEVOS_DEACTIVATE = -14,
|
||||
RCHEEVOS_PLAYING = -15,
|
||||
RCHEEVOS_DELAY = -16,
|
||||
RCHEEVOS_PSX_MD5 = -17
|
||||
RCHEEVOS_DELAY = -16
|
||||
};
|
||||
|
||||
static int rcheevos_iterate(rcheevos_coro_t* coro)
|
||||
@ -1166,21 +1168,6 @@ static int rcheevos_iterate(rcheevos_coro_t* coro)
|
||||
char* scan = NULL;
|
||||
char buffer[2048];
|
||||
|
||||
static const uint32_t genesis_exts[] =
|
||||
{
|
||||
0x0b888feeU, /* mdx */
|
||||
0x005978b6U, /* md */
|
||||
0x0b88aa89U, /* smd */
|
||||
0x0b88767fU, /* gen */
|
||||
0x0b8861beU, /* bin */
|
||||
0x0b886782U, /* cue */
|
||||
0x0b8880d0U, /* iso */
|
||||
0x0b88aa98U, /* sms */
|
||||
0x005977f3U, /* gg */
|
||||
0x0059797fU, /* sg */
|
||||
0
|
||||
};
|
||||
|
||||
static const uint32_t snes_exts[] =
|
||||
{
|
||||
0x0b88aa88U, /* smc */
|
||||
@ -1194,6 +1181,12 @@ static int rcheevos_iterate(rcheevos_coro_t* coro)
|
||||
0
|
||||
};
|
||||
|
||||
static const uint32_t nes_exts[] =
|
||||
{
|
||||
0x0b88944bU, /* nes */
|
||||
0
|
||||
};
|
||||
|
||||
static const uint32_t lynx_exts[] =
|
||||
{
|
||||
0x0b888cf7U, /* lnx */
|
||||
@ -1211,15 +1204,29 @@ static int rcheevos_iterate(rcheevos_coro_t* coro)
|
||||
0
|
||||
};
|
||||
|
||||
static const uint32_t segacd_exts[] =
|
||||
{
|
||||
0x0b886782U, /* cue */
|
||||
0x0b8880d0U, /* iso */
|
||||
0x0b8865d4U, /* chd */
|
||||
0
|
||||
};
|
||||
|
||||
static const uint32_t arcade_exts[] =
|
||||
{
|
||||
0x0b88c7d8U, /* zip */
|
||||
0
|
||||
};
|
||||
|
||||
static rcheevos_finder_t finders[] =
|
||||
{
|
||||
{RCHEEVOS_SNES_MD5, "SNES (discards header)", snes_exts},
|
||||
{RCHEEVOS_GENESIS_MD5, "Genesis (6Mb padding)", genesis_exts},
|
||||
{RCHEEVOS_LYNX_MD5, "Atari Lynx (discards header)", lynx_exts},
|
||||
{RCHEEVOS_NES_MD5, "NES (discards header)", NULL},
|
||||
{RCHEEVOS_NES_MD5, "NES (discards header)", nes_exts},
|
||||
{RCHEEVOS_PSX_MD5, "Playstation (main executable)", psx_exts},
|
||||
{RCHEEVOS_GENERIC_MD5, "Generic (plain content)", NULL},
|
||||
{RCHEEVOS_FILENAME_MD5, "Generic (filename)", NULL}
|
||||
{RCHEEVOS_SEGACD_MD5, "Sega CD/Saturn (first sector)", segacd_exts},
|
||||
{RCHEEVOS_ARCADE_MD5, "Arcade (filename)", arcade_exts},
|
||||
{RCHEEVOS_GENERIC_MD5, "Generic (plain content)", NULL}
|
||||
};
|
||||
|
||||
CORO_ENTER();
|
||||
@ -1286,14 +1293,44 @@ static int rcheevos_iterate(rcheevos_coro_t* coro)
|
||||
CHEEVOS_FREE(coro->stream);
|
||||
}
|
||||
|
||||
/* Use the supported extensions as a hint
|
||||
* to what method we should use. */
|
||||
core_get_system_info(&coro->sysinfo);
|
||||
|
||||
/* Use the selected file's extension to determine which method to use */
|
||||
for (coro->i = 0; coro->i < ARRAY_SIZE(finders); coro->i++)
|
||||
{
|
||||
if (finders[coro->i].ext_hashes)
|
||||
{
|
||||
for (coro->j = 0; finders[coro->i].ext_hashes[coro->j]; coro->j++)
|
||||
{
|
||||
if (finders[coro->i].ext_hashes[coro->j] == coro->ext_hash)
|
||||
{
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "testing %s\n", finders[coro->i].name);
|
||||
CORO_GOSUB(finders[coro->i].label);
|
||||
|
||||
if (coro->gameid != 0)
|
||||
goto found;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Use the extensions supported by the core as a hint to what method we should use. */
|
||||
core_get_system_info(&coro->sysinfo);
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "no method for file extension, trying core supported extensions: %s\n", coro->sysinfo.valid_extensions);
|
||||
for (coro->i = 0; coro->i < ARRAY_SIZE(finders); coro->i++)
|
||||
{
|
||||
if (finders[coro->i].ext_hashes)
|
||||
{
|
||||
for (coro->j = 0; finders[coro->i].ext_hashes[coro->j]; coro->j++)
|
||||
{
|
||||
if (finders[coro->i].ext_hashes[coro->j] == coro->ext_hash)
|
||||
break;
|
||||
}
|
||||
|
||||
/* did we already check this one? */
|
||||
if (finders[coro->i].ext_hashes[coro->j] == coro->ext_hash)
|
||||
continue;
|
||||
|
||||
coro->ext = coro->sysinfo.valid_extensions;
|
||||
|
||||
while (coro->ext)
|
||||
@ -1316,13 +1353,7 @@ static int rcheevos_iterate(rcheevos_coro_t* coro)
|
||||
{
|
||||
if (finders[coro->i].ext_hashes[coro->j] == hash)
|
||||
{
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "testing %s\n",
|
||||
finders[coro->i].name);
|
||||
|
||||
/*
|
||||
* Inputs: CHEEVOS_VAR_INFO
|
||||
* Outputs: CHEEVOS_VAR_GAMEID, the game was found if it's different from 0
|
||||
*/
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "testing %s\n", finders[coro->i].name);
|
||||
CORO_GOSUB(finders[coro->i].label);
|
||||
|
||||
if (coro->gameid != 0)
|
||||
@ -1336,18 +1367,13 @@ static int rcheevos_iterate(rcheevos_coro_t* coro)
|
||||
}
|
||||
}
|
||||
|
||||
/* Try hashing methods not specifically tied to a file extension */
|
||||
for (coro->i = 0; coro->i < ARRAY_SIZE(finders); coro->i++)
|
||||
{
|
||||
if (finders[coro->i].ext_hashes)
|
||||
continue;
|
||||
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "testing %s\n",
|
||||
finders[coro->i].name);
|
||||
|
||||
/*
|
||||
* Inputs: CHEEVOS_VAR_INFO
|
||||
* Outputs: CHEEVOS_VAR_GAMEID
|
||||
*/
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "testing %s\n", finders[coro->i].name);
|
||||
CORO_GOSUB(finders[coro->i].label);
|
||||
|
||||
if (coro->gameid != 0)
|
||||
@ -1450,11 +1476,12 @@ found:
|
||||
CORO_GOSUB(RCHEEVOS_GET_BADGES);
|
||||
CORO_STOP();
|
||||
|
||||
/**************************************************************************
|
||||
* Info Tries to identify a SNES game
|
||||
* Input CHEEVOS_VAR_INFO the content info
|
||||
* Output CHEEVOS_VAR_GAMEID the Retro Achievements game ID, or 0 if not found
|
||||
*************************************************************************/
|
||||
|
||||
/**************************************************************************
|
||||
* Info Tries to identify a SNES game
|
||||
* Input CHEEVOS_VAR_INFO the content info
|
||||
* Output CHEEVOS_VAR_GAMEID the Retro Achievements game ID, or 0 if not found
|
||||
*************************************************************************/
|
||||
CORO_SUB(RCHEEVOS_SNES_MD5)
|
||||
MD5_Init(&coro->md5);
|
||||
|
||||
@ -1462,6 +1489,7 @@ found:
|
||||
Unheadered files fall back to RCHEEVOS_GENERIC_MD5. */
|
||||
if (coro->len < 0x2000 || coro->len % 0x2000 != snes_header_len)
|
||||
{
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "could not locate SNES header\n", coro->gameid);
|
||||
coro->gameid = 0;
|
||||
CORO_RET();
|
||||
}
|
||||
@ -1474,41 +1502,12 @@ found:
|
||||
|
||||
CORO_GOTO(RCHEEVOS_GET_GAMEID);
|
||||
|
||||
/**************************************************************************
|
||||
* Info Tries to identify a Genesis game
|
||||
* Input CHEEVOS_VAR_INFO the content info
|
||||
* Output CHEEVOS_VAR_GAMEID the Retro Achievements game ID, or 0 if not found
|
||||
*************************************************************************/
|
||||
CORO_SUB(RCHEEVOS_GENESIS_MD5)
|
||||
|
||||
MD5_Init(&coro->md5);
|
||||
|
||||
coro->offset = 0;
|
||||
coro->count = 0;
|
||||
CORO_GOSUB(RCHEEVOS_EVAL_MD5);
|
||||
|
||||
if (coro->count == 0)
|
||||
{
|
||||
MD5_Final(coro->hash, &coro->md5);
|
||||
coro->gameid = 0;
|
||||
CORO_RET();
|
||||
}
|
||||
|
||||
if (coro->count < CHEEVOS_MB(6))
|
||||
{
|
||||
coro->offset = 0;
|
||||
coro->count = CHEEVOS_MB(6) - coro->count;
|
||||
CORO_GOSUB(RCHEEVOS_FILL_MD5);
|
||||
}
|
||||
|
||||
MD5_Final(coro->hash, &coro->md5);
|
||||
CORO_GOTO(RCHEEVOS_GET_GAMEID);
|
||||
|
||||
/**************************************************************************
|
||||
* Info Tries to identify an Atari Lynx game
|
||||
* Input CHEEVOS_VAR_INFO the content info
|
||||
* Output CHEEVOS_VAR_GAMEID the Retro Achievements game ID, or 0 if not found
|
||||
*************************************************************************/
|
||||
/**************************************************************************
|
||||
* Info Tries to identify an Atari Lynx game
|
||||
* Input CHEEVOS_VAR_INFO the content info
|
||||
* Output CHEEVOS_VAR_GAMEID the Retro Achievements game ID, or 0 if not found
|
||||
*************************************************************************/
|
||||
CORO_SUB(RCHEEVOS_LYNX_MD5)
|
||||
|
||||
/* Checks for the existence of a headered Lynx file.
|
||||
@ -1516,6 +1515,7 @@ found:
|
||||
if (coro->len <= (unsigned)lynx_header_len ||
|
||||
memcmp("LYNX", (void *)coro->data, 5) != 0)
|
||||
{
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "could not locate LYNX header\n", coro->gameid);
|
||||
coro->gameid = 0;
|
||||
CORO_RET();
|
||||
}
|
||||
@ -1528,11 +1528,12 @@ found:
|
||||
MD5_Final(coro->hash, &coro->md5);
|
||||
CORO_GOTO(RCHEEVOS_GET_GAMEID);
|
||||
|
||||
/**************************************************************************
|
||||
* Info Tries to identify a NES game
|
||||
* Input CHEEVOS_VAR_INFO the content info
|
||||
* Output CHEEVOS_VAR_GAMEID the Retro Achievements game ID, or 0 if not found
|
||||
*************************************************************************/
|
||||
|
||||
/**************************************************************************
|
||||
* Info Tries to identify a NES game
|
||||
* Input CHEEVOS_VAR_INFO the content info
|
||||
* Output CHEEVOS_VAR_GAMEID the Retro Achievements game ID, or 0 if not found
|
||||
*************************************************************************/
|
||||
CORO_SUB(RCHEEVOS_NES_MD5)
|
||||
|
||||
/* Checks for the existence of a headered NES file.
|
||||
@ -1552,6 +1553,7 @@ found:
|
||||
|| coro->header.id[3] != 0x1a)
|
||||
{
|
||||
coro->gameid = 0;
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "could not locate NES header\n", coro->gameid);
|
||||
CORO_RET();
|
||||
}
|
||||
|
||||
@ -1564,6 +1566,57 @@ found:
|
||||
CORO_GOTO(RCHEEVOS_GET_GAMEID);
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* Info Tries to identify a Sega CD game
|
||||
* Input CHEEVOS_VAR_INFO the content info
|
||||
* Output CHEEVOS_VAR_GAMEID the Retro Achievements game ID, or 0 if not found
|
||||
*************************************************************************/
|
||||
CORO_SUB(RCHEEVOS_SEGACD_MD5)
|
||||
{
|
||||
/* ignore bin files less than 16MB - they're probably a ROM, not a CD */
|
||||
if (coro->ext_hash == 0x0b8861beU && coro->len < CHEEVOS_MB(16))
|
||||
{
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "ignoring small BIN file - assuming not CD\n", coro->gameid);
|
||||
coro->gameid = 0;
|
||||
CORO_RET();
|
||||
}
|
||||
|
||||
MD5_Init(&coro->md5);
|
||||
|
||||
/* find the data track - it should be the first one */
|
||||
coro->stream = cdfs_open_data_track(coro->path);
|
||||
if (coro->stream)
|
||||
{
|
||||
/* open the raw CD */
|
||||
if (cdfs_open_file(&coro->cdfp, coro->stream, NULL))
|
||||
{
|
||||
coro->count = 512;
|
||||
free(coro->data);
|
||||
coro->data = (uint8_t*)malloc(coro->count);
|
||||
cdfs_read_file(&coro->cdfp, coro->data, coro->count);
|
||||
coro->len = coro->count;
|
||||
|
||||
CORO_GOSUB(RCHEEVOS_EVAL_MD5);
|
||||
MD5_Final(coro->hash, &coro->md5);
|
||||
|
||||
cdfs_close_file(&coro->cdfp);
|
||||
|
||||
intfstream_close(coro->stream);
|
||||
CHEEVOS_FREE(coro->stream);
|
||||
|
||||
CORO_GOTO(RCHEEVOS_GET_GAMEID);
|
||||
}
|
||||
|
||||
intfstream_close(coro->stream);
|
||||
CHEEVOS_FREE(coro->stream);
|
||||
}
|
||||
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "could not open CD\n", coro->gameid);
|
||||
coro->gameid = 0;
|
||||
CORO_RET();
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* Info Tries to identify a Playstation game
|
||||
* Input CHEEVOS_VAR_INFO the content info
|
||||
@ -1706,20 +1759,26 @@ found:
|
||||
}
|
||||
}
|
||||
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "could not locate primary executable\n", coro->gameid);
|
||||
|
||||
intfstream_close(coro->stream);
|
||||
CHEEVOS_FREE(coro->stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "could not open CD\n", coro->gameid);
|
||||
}
|
||||
|
||||
coro->gameid = 0;
|
||||
CORO_RET();
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* Info Tries to identify a "generic" game
|
||||
* Input CHEEVOS_VAR_INFO the content info
|
||||
* Output CHEEVOS_VAR_GAMEID the Retro Achievements game ID, or 0 if not found
|
||||
*************************************************************************/
|
||||
/**************************************************************************
|
||||
* Info Tries to identify a game by examining the entire file (no special processing)
|
||||
* Input CHEEVOS_VAR_INFO the content info
|
||||
* Output CHEEVOS_VAR_GAMEID the Retro Achievements game ID, or 0 if not found
|
||||
*************************************************************************/
|
||||
CORO_SUB(RCHEEVOS_GENERIC_MD5)
|
||||
|
||||
MD5_Init(&coro->md5);
|
||||
@ -1735,12 +1794,14 @@ found:
|
||||
|
||||
CORO_GOTO(RCHEEVOS_GET_GAMEID);
|
||||
|
||||
/**************************************************************************
|
||||
* Info Tries to identify a game based on its filename (with no extension)
|
||||
* Input CHEEVOS_VAR_INFO the content info
|
||||
* Output CHEEVOS_VAR_GAMEID the Retro Achievements game ID, or 0 if not found
|
||||
*************************************************************************/
|
||||
CORO_SUB(RCHEEVOS_FILENAME_MD5)
|
||||
|
||||
/**************************************************************************
|
||||
* Info Tries to identify an arcade game based on its filename (with no extension).
|
||||
* An arcade game "rom" is a zip file containing many ROMs.
|
||||
* Input CHEEVOS_VAR_INFO the content info
|
||||
* Output CHEEVOS_VAR_GAMEID the Retro Achievements game ID, or 0 if not found
|
||||
*************************************************************************/
|
||||
CORO_SUB(RCHEEVOS_ARCADE_MD5)
|
||||
if (!string_is_empty(coro->path))
|
||||
{
|
||||
char base_noext[PATH_MAX_LENGTH];
|
||||
@ -1754,11 +1815,12 @@ found:
|
||||
}
|
||||
CORO_RET();
|
||||
|
||||
/**************************************************************************
|
||||
* Info Evaluates the CHEEVOS_VAR_MD5 hash
|
||||
* Inputs CHEEVOS_VAR_INFO, CHEEVOS_VAR_OFFSET, CHEEVOS_VAR_COUNT
|
||||
* Outputs CHEEVOS_VAR_MD5, CHEEVOS_VAR_COUNT
|
||||
*************************************************************************/
|
||||
|
||||
/**************************************************************************
|
||||
* Info Evaluates the CHEEVOS_VAR_MD5 hash
|
||||
* Inputs CHEEVOS_VAR_INFO, CHEEVOS_VAR_OFFSET, CHEEVOS_VAR_COUNT
|
||||
* Outputs CHEEVOS_VAR_MD5, CHEEVOS_VAR_COUNT
|
||||
*************************************************************************/
|
||||
CORO_SUB(RCHEEVOS_EVAL_MD5)
|
||||
|
||||
if (coro->count == 0)
|
||||
@ -1776,40 +1838,24 @@ found:
|
||||
coro->count);
|
||||
CORO_RET();
|
||||
|
||||
/**************************************************************************
|
||||
* Info Updates the CHEEVOS_VAR_MD5 hash with a repeated value
|
||||
* Inputs CHEEVOS_VAR_OFFSET, CHEEVOS_VAR_COUNT
|
||||
* Outputs CHEEVOS_VAR_MD5
|
||||
*************************************************************************/
|
||||
CORO_SUB(RCHEEVOS_FILL_MD5)
|
||||
|
||||
{
|
||||
char buffer[4096];
|
||||
|
||||
while (coro->count > 0)
|
||||
{
|
||||
size_t len = sizeof(buffer);
|
||||
|
||||
if (len > coro->count)
|
||||
len = coro->count;
|
||||
|
||||
memset((void*)buffer, coro->offset, len);
|
||||
MD5_Update(&coro->md5, (void*)buffer, len);
|
||||
coro->count -= len;
|
||||
}
|
||||
}
|
||||
|
||||
CORO_RET();
|
||||
|
||||
/**************************************************************************
|
||||
* Info Gets the achievements from Retro Achievements
|
||||
* Inputs coro->hash
|
||||
* Outputs CHEEVOS_VAR_GAMEID
|
||||
*************************************************************************/
|
||||
/**************************************************************************
|
||||
* Info Gets the achievements from Retro Achievements
|
||||
* Inputs coro->hash
|
||||
* Outputs CHEEVOS_VAR_GAMEID
|
||||
*************************************************************************/
|
||||
CORO_SUB(RCHEEVOS_GET_GAMEID)
|
||||
|
||||
{
|
||||
int size;
|
||||
|
||||
if (memcmp(coro->last_hash, coro->hash, sizeof(coro->hash)) == 0)
|
||||
{
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "hash did not change, returning %u\n", coro->gameid);
|
||||
CORO_RET();
|
||||
}
|
||||
memcpy(coro->last_hash, coro->hash, sizeof(coro->hash));
|
||||
|
||||
size = rc_url_get_gameid(coro->url, sizeof(coro->url), coro->hash);
|
||||
|
||||
if (size < 0)
|
||||
@ -1818,6 +1864,11 @@ found:
|
||||
CORO_RET();
|
||||
}
|
||||
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "checking %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
|
||||
coro->hash[0], coro->hash[1], coro->hash[2], coro->hash[3],
|
||||
coro->hash[4], coro->hash[5], coro->hash[6], coro->hash[7],
|
||||
coro->hash[8], coro->hash[9], coro->hash[10], coro->hash[11],
|
||||
coro->hash[12], coro->hash[13], coro->hash[14], coro->hash[15]);
|
||||
rcheevos_log_url(RCHEEVOS_TAG "rc_url_get_gameid: %s\n", coro->url);
|
||||
CORO_GOSUB(RCHEEVOS_HTTP_GET);
|
||||
|
||||
@ -1831,11 +1882,12 @@ found:
|
||||
CORO_RET();
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* Info Gets the achievements from Retro Achievements
|
||||
* Inputs CHEEVOS_VAR_GAMEID
|
||||
* Outputs CHEEVOS_VAR_JSON
|
||||
*************************************************************************/
|
||||
|
||||
/**************************************************************************
|
||||
* Info Gets the achievements from Retro Achievements
|
||||
* Inputs CHEEVOS_VAR_GAMEID
|
||||
* Outputs CHEEVOS_VAR_JSON
|
||||
*************************************************************************/
|
||||
CORO_SUB(RCHEEVOS_GET_CHEEVOS)
|
||||
{
|
||||
int ret;
|
||||
@ -1863,11 +1915,12 @@ found:
|
||||
CORO_RET();
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* Info Gets the achievements from Retro Achievements
|
||||
* Inputs CHEEVOS_VAR_GAMEID
|
||||
* Outputs CHEEVOS_VAR_JSON
|
||||
*************************************************************************/
|
||||
|
||||
/**************************************************************************
|
||||
* Info Gets the achievements from Retro Achievements
|
||||
* Inputs CHEEVOS_VAR_GAMEID
|
||||
* Outputs CHEEVOS_VAR_JSON
|
||||
*************************************************************************/
|
||||
CORO_SUB(RCHEEVOS_GET_BADGES)
|
||||
|
||||
badges_ctx = new_badges_ctx;
|
||||
@ -1958,9 +2011,10 @@ found:
|
||||
|
||||
CORO_RET();
|
||||
|
||||
/**************************************************************************
|
||||
* Info Logs in the user at Retro Achievements
|
||||
*************************************************************************/
|
||||
|
||||
/**************************************************************************
|
||||
* Info Logs in the user at Retro Achievements
|
||||
*************************************************************************/
|
||||
CORO_SUB(RCHEEVOS_LOGIN)
|
||||
{
|
||||
const char* username;
|
||||
@ -2050,9 +2104,10 @@ found:
|
||||
CORO_RET();
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* Info Pauses execution for five seconds
|
||||
*************************************************************************/
|
||||
|
||||
/**************************************************************************
|
||||
* Info Pauses execution for five seconds
|
||||
*************************************************************************/
|
||||
CORO_SUB(RCHEEVOS_DELAY)
|
||||
|
||||
{
|
||||
@ -2068,11 +2123,12 @@ found:
|
||||
|
||||
CORO_RET();
|
||||
|
||||
/**************************************************************************
|
||||
* Info Makes a HTTP GET request
|
||||
* Inputs CHEEVOS_VAR_URL
|
||||
* Outputs CHEEVOS_VAR_JSON
|
||||
*************************************************************************/
|
||||
|
||||
/**************************************************************************
|
||||
* Info Makes a HTTP GET request
|
||||
* Inputs CHEEVOS_VAR_URL
|
||||
* Outputs CHEEVOS_VAR_JSON
|
||||
*************************************************************************/
|
||||
CORO_SUB(RCHEEVOS_HTTP_GET)
|
||||
|
||||
for (coro->k = 0; coro->k < 5; coro->k++)
|
||||
@ -2143,11 +2199,12 @@ found:
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "Couldn't connect to server after 5 tries\n");
|
||||
CORO_RET();
|
||||
|
||||
/**************************************************************************
|
||||
* Info Deactivates the achievements already awarded
|
||||
* Inputs CHEEVOS_VAR_GAMEID
|
||||
* Outputs
|
||||
*************************************************************************/
|
||||
|
||||
/**************************************************************************
|
||||
* Info Deactivates the achievements already awarded
|
||||
* Inputs CHEEVOS_VAR_GAMEID
|
||||
* Outputs
|
||||
*************************************************************************/
|
||||
CORO_SUB(RCHEEVOS_DEACTIVATE)
|
||||
|
||||
CORO_GOSUB(RCHEEVOS_LOGIN);
|
||||
@ -2155,6 +2212,7 @@ found:
|
||||
int ret;
|
||||
unsigned mode;
|
||||
|
||||
/* Two calls - one for softcore and one for hardcore */
|
||||
for (coro->i = 0; coro->i < 2; coro->i++)
|
||||
{
|
||||
ret = rc_url_get_unlock_list(coro->url, sizeof(coro->url), coro->settings->arrays.cheevos_username, rcheevos_locals.token, coro->gameid, coro->i);
|
||||
@ -2181,11 +2239,12 @@ found:
|
||||
|
||||
CORO_RET();
|
||||
|
||||
/**************************************************************************
|
||||
* Info Posts the "playing" activity to Retro Achievements
|
||||
* Inputs CHEEVOS_VAR_GAMEID
|
||||
* Outputs
|
||||
*************************************************************************/
|
||||
|
||||
/**************************************************************************
|
||||
* Info Posts the "playing" activity to Retro Achievements
|
||||
* Inputs CHEEVOS_VAR_GAMEID
|
||||
* Outputs
|
||||
*************************************************************************/
|
||||
CORO_SUB(RCHEEVOS_PLAYING)
|
||||
|
||||
snprintf(
|
||||
@ -2208,7 +2267,6 @@ found:
|
||||
else
|
||||
CHEEVOS_ERR(RCHEEVOS_TAG "error posting playing activity\n");
|
||||
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "posted playing activity\n");
|
||||
CORO_RET();
|
||||
|
||||
CORO_LEAVE();
|
||||
@ -2248,7 +2306,8 @@ bool rcheevos_load(const void *data)
|
||||
{
|
||||
retro_task_t *task;
|
||||
const struct retro_game_info *info = NULL;
|
||||
rcheevos_coro_t *coro = NULL;
|
||||
rcheevos_coro_t *coro = NULL;
|
||||
char buffer[32];
|
||||
|
||||
rcheevos_loaded = false;
|
||||
rcheevos_hardcore_paused = false;
|
||||
@ -2299,6 +2358,12 @@ bool rcheevos_load(const void *data)
|
||||
coro->path = strdup(info->path);
|
||||
}
|
||||
|
||||
strncpy(buffer, path_get_extension(info->path), sizeof(buffer));
|
||||
buffer[sizeof(buffer) - 1] = '\0';
|
||||
string_to_lower(buffer);
|
||||
coro->ext_hash = rcheevos_djb2(buffer, strlen(buffer));
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "ext_hash %08x ('%s')\n", coro->ext_hash, buffer);
|
||||
|
||||
task->handler = rcheevos_task_handler;
|
||||
task->state = (void*)coro;
|
||||
task->mute = true;
|
||||
|
@ -151,7 +151,7 @@ static int cdfs_find_file(cdfs_file_t* file, const char* path)
|
||||
|
||||
int cdfs_open_file(cdfs_file_t* file, intfstream_t* stream, const char* path)
|
||||
{
|
||||
if (!file || !stream || !path)
|
||||
if (!file || !stream)
|
||||
return 0;
|
||||
|
||||
memset(file, 0, sizeof(*file));
|
||||
@ -160,16 +160,28 @@ int cdfs_open_file(cdfs_file_t* file, intfstream_t* stream, const char* path)
|
||||
cdfs_determine_sector_size(file);
|
||||
|
||||
file->current_sector = -1;
|
||||
file->first_sector = cdfs_find_file(file, path);
|
||||
if (path != NULL)
|
||||
{
|
||||
file->first_sector = cdfs_find_file(file, path);
|
||||
}
|
||||
else if (file->stream_sector_size)
|
||||
{
|
||||
file->first_sector = 0;
|
||||
file->size = (intfstream_get_size(file->stream) / file->stream_sector_size) * 2048;
|
||||
}
|
||||
else
|
||||
{
|
||||
file->first_sector = -1;
|
||||
}
|
||||
|
||||
return (file->first_sector > 0);
|
||||
return (file->first_sector >= 0);
|
||||
}
|
||||
|
||||
int64_t cdfs_read_file(cdfs_file_t* file, void* buffer, uint64_t len)
|
||||
{
|
||||
int bytes_read = 0;
|
||||
|
||||
if (!file || !file->first_sector || !buffer)
|
||||
if (!file || file->first_sector < 0 || !buffer)
|
||||
return 0;
|
||||
|
||||
if (len > file->size - file->pos)
|
||||
@ -240,13 +252,13 @@ void cdfs_close_file(cdfs_file_t* file)
|
||||
if (file)
|
||||
{
|
||||
/* not really anything to do here, just clear out the first_sector so read() won't do anything */
|
||||
file->first_sector = 0;
|
||||
file->first_sector = -1;
|
||||
}
|
||||
}
|
||||
|
||||
int64_t cdfs_get_size(cdfs_file_t* file)
|
||||
{
|
||||
if (!file || !file->first_sector)
|
||||
if (!file || file->first_sector < 0)
|
||||
return 0;
|
||||
|
||||
return file->size;
|
||||
@ -254,7 +266,7 @@ int64_t cdfs_get_size(cdfs_file_t* file)
|
||||
|
||||
int64_t cdfs_tell(cdfs_file_t* file)
|
||||
{
|
||||
if (!file || !file->first_sector)
|
||||
if (!file || file->first_sector < 0)
|
||||
return -1;
|
||||
|
||||
return file->pos;
|
||||
@ -265,7 +277,7 @@ int64_t cdfs_seek(cdfs_file_t* file, int64_t offset, int whence)
|
||||
int64_t new_pos;
|
||||
int new_sector;
|
||||
|
||||
if (!file || !file->first_sector)
|
||||
if (!file || file->first_sector < 0)
|
||||
return -1;
|
||||
|
||||
switch (whence)
|
||||
@ -459,8 +471,8 @@ intfstream_t* cdfs_open_data_track(const char* path)
|
||||
return intfstream_open_chd_track(path, RETRO_VFS_FILE_ACCESS_READ, RETRO_VFS_FILE_ACCESS_HINT_NONE, 1);
|
||||
}
|
||||
|
||||
/* unsupported file type */
|
||||
return NULL;
|
||||
/* unsupported file type - try opening as a raw track */
|
||||
return cdfs_open_raw_track(path);
|
||||
}
|
||||
|
||||
intfstream_t* cdfs_open_raw_track(const char* path)
|
||||
|
@ -45,6 +45,10 @@ typedef struct cdfs_file_t
|
||||
uint8_t sector_buffer[2048];
|
||||
} cdfs_file_t;
|
||||
|
||||
/* opens the specified file within the CD or virtual CD.
|
||||
* if path is NULL, will open the raw CD (useful for reading CD without having to worry about sector sizes,
|
||||
* headers, or checksum data)
|
||||
*/
|
||||
int cdfs_open_file(cdfs_file_t* file, intfstream_t* stream, const char* path);
|
||||
|
||||
void cdfs_close_file(cdfs_file_t* file);
|
||||
|
Loading…
x
Reference in New Issue
Block a user