mirror of
https://github.com/GerbilSoft/rom-properties.git
synced 2025-06-18 11:35:38 -04:00
[libromdata] GameBoyAdvance: Added external title screen images using my new RPDB subdomain.
Example URL: https://rpdb.gerbilsoft.com/gba/title/E/ASOE78.png I spent a good while taking screenshots of the vast majority of retail GBA games. There's probably a few missing, especially GBA Video titles. Next is DMG, which will be a bit more difficult: - Game IDs weren't present in the header prior to CGB, and early CGB titles don't have them. We'll need to use the title. - Some games have the same title in multiple regions. We'll need to use the region byte for this, though it only distinguishes between JP and non-JP. - SGB-enhanced games that don't also support CGB will have the SGB border. Should we also take SGB screenshots of CGB+SGB games, and non-SGB screenshots of SGB games? [rp-download] Added support for the gba/ cache key.
This commit is contained in:
parent
390e8f14c9
commit
346dad0faa
@ -20,6 +20,8 @@ The configuration file is located at:
|
||||
* https://art.gametdb.com/ - Box, cover, and media scans for Nintendo
|
||||
GameCube, Wii, Wii U, DS, and 3DS games.
|
||||
* https://amiibo.life/ - Images of Nintendo amiibo products.
|
||||
* https://rpdb.gerbilsoft.com/ - Title screen images of Nintendo
|
||||
Game Boy Advance games.
|
||||
|
||||
## Security features
|
||||
|
||||
|
@ -22,6 +22,7 @@ using std::vector;
|
||||
namespace LibRomData {
|
||||
|
||||
ROMDATA_IMPL(GameBoyAdvance)
|
||||
ROMDATA_IMPL_IMG(GameBoyAdvance)
|
||||
|
||||
class GameBoyAdvancePrivate : public RomDataPrivate
|
||||
{
|
||||
@ -245,6 +246,68 @@ const char *const *GameBoyAdvance::supportedMimeTypes_static(void)
|
||||
return mimeTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a bitfield of image types this class can retrieve.
|
||||
* @return Bitfield of supported image types. (ImageTypesBF)
|
||||
*/
|
||||
uint32_t GameBoyAdvance::supportedImageTypes_static(void)
|
||||
{
|
||||
return IMGBF_EXT_TITLE_SCREEN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of all available image sizes for the specified image type.
|
||||
* @param imageType Image type.
|
||||
* @return Vector of available image sizes, or empty vector if no images are available.
|
||||
*/
|
||||
vector<RomData::ImageSizeDef> GameBoyAdvance::supportedImageSizes_static(ImageType imageType)
|
||||
{
|
||||
ASSERT_supportedImageSizes(imageType);
|
||||
|
||||
switch (imageType) {
|
||||
case IMG_EXT_TITLE_SCREEN: {
|
||||
static const ImageSizeDef sz_EXT_TITLE_SCREEN[] = {
|
||||
{nullptr, 240, 160, 0},
|
||||
};
|
||||
return vector<ImageSizeDef>(sz_EXT_TITLE_SCREEN,
|
||||
sz_EXT_TITLE_SCREEN + ARRAY_SIZE(sz_EXT_TITLE_SCREEN));
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Unsupported image type.
|
||||
return vector<ImageSizeDef>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get image processing flags.
|
||||
*
|
||||
* These specify post-processing operations for images,
|
||||
* e.g. applying transparency masks.
|
||||
*
|
||||
* @param imageType Image type.
|
||||
* @return Bitfield of ImageProcessingBF operations to perform.
|
||||
*/
|
||||
uint32_t GameBoyAdvance::imgpf(ImageType imageType) const
|
||||
{
|
||||
ASSERT_imgpf(imageType);
|
||||
|
||||
uint32_t ret = 0;
|
||||
switch (imageType) {
|
||||
case IMG_EXT_TITLE_SCREEN:
|
||||
// Use nearest-neighbor scaling when resizing.
|
||||
ret = IMGPF_RESCALE_NEAREST;
|
||||
break;
|
||||
|
||||
default:
|
||||
// GameTDB's Nintendo DS cover scans have alpha transparency.
|
||||
// Hence, no image processing is required.
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load field data.
|
||||
* Called by RomData::fields() if the field data hasn't been loaded yet.
|
||||
@ -361,4 +424,98 @@ int GameBoyAdvance::loadFieldData(void)
|
||||
return static_cast<int>(d->fields->count());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of URLs for an external image type.
|
||||
*
|
||||
* A thumbnail size may be requested from the shell.
|
||||
* If the subclass supports multiple sizes, it should
|
||||
* try to get the size that most closely matches the
|
||||
* requested size.
|
||||
*
|
||||
* @param imageType [in] Image type.
|
||||
* @param pExtURLs [out] Output vector.
|
||||
* @param size [in,opt] Requested image size. This may be a requested
|
||||
* thumbnail size in pixels, or an ImageSizeType
|
||||
* enum value.
|
||||
* @return 0 on success; negative POSIX error code on error.
|
||||
*/
|
||||
int GameBoyAdvance::extURLs(ImageType imageType, vector<ExtURL> *pExtURLs, int size) const
|
||||
{
|
||||
ASSERT_extURLs(imageType, pExtURLs);
|
||||
pExtURLs->clear();
|
||||
|
||||
// Check for GBA ROMs that don't have external images.
|
||||
RP_D(const GameBoyAdvance);
|
||||
if (!d->isValid || d->romType < 0) {
|
||||
// ROM image isn't valid.
|
||||
return -EIO;
|
||||
} else if (!memcmp(d->romHeader.id4, "AGBJ", 4) ||
|
||||
!memcmp(d->romHeader.id4, " ", 4))
|
||||
{
|
||||
// This is a prototype.
|
||||
// No external images are available.
|
||||
// TODO: CRC32-based images?
|
||||
return -ENOENT;
|
||||
} else if (d->romType == GameBoyAdvancePrivate::ROM_NDS_EXP) {
|
||||
// This is a Nintendo DS expansion cartridge.
|
||||
// No external images are available.
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
// NOTE: We only have one size for GBA right now.
|
||||
RP_UNUSED(size);
|
||||
vector<ImageSizeDef> sizeDefs = supportedImageSizes(imageType);
|
||||
assert(sizeDefs.size() == 1);
|
||||
if (sizeDefs.empty()) {
|
||||
// No image sizes.
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
// NOTE: RPDB's title screen database only has one size.
|
||||
// There's no need to check image sizes, but we need to
|
||||
// get the image size for the extURLs struct.
|
||||
|
||||
// Determine the image type name.
|
||||
const char *imageTypeName;
|
||||
const char *ext;
|
||||
switch (imageType) {
|
||||
case IMG_EXT_TITLE_SCREEN:
|
||||
imageTypeName = "title";
|
||||
ext = ".png";
|
||||
break;
|
||||
default:
|
||||
// Unsupported image type.
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
// Game ID. (RPDB uses ID6 for Game Boy Advance.)
|
||||
// The ID6 cannot have non-printable characters.
|
||||
char id6[7];
|
||||
for (int i = ARRAY_SIZE(d->romHeader.id6)-1; i >= 0; i--) {
|
||||
if (!ISPRINT(d->romHeader.id6[i])) {
|
||||
// Non-printable character found.
|
||||
return -ENOENT;
|
||||
}
|
||||
id6[i] = d->romHeader.id6[i];
|
||||
}
|
||||
// NULL-terminated ID6 is needed for the
|
||||
// RPDB URL functions.
|
||||
id6[6] = 0;
|
||||
|
||||
// Region code is id6[3].
|
||||
const char region_code[2] = {id6[3], '\0'};
|
||||
|
||||
// Add the URLs.
|
||||
pExtURLs->resize(1);
|
||||
auto extURL_iter = pExtURLs->begin();
|
||||
extURL_iter->url = d->getURL_RPDB("gba", imageTypeName, region_code, id6, ext);
|
||||
extURL_iter->cache_key = d->getCacheKey_RPDB("gba", imageTypeName, region_code, id6, ext);
|
||||
extURL_iter->width = sizeDefs[0].width;
|
||||
extURL_iter->height = sizeDefs[0].height;
|
||||
extURL_iter->high_res = (sizeDefs[0].index >= 2);
|
||||
|
||||
// All URLs added.
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ROM Properties Page shell extension. (libromdata) *
|
||||
* GameBoyAdvance.hpp: Nintendo Game Boy Advance ROM reader. *
|
||||
* *
|
||||
* Copyright (c) 2016-2018 by David Korth. *
|
||||
* Copyright (c) 2016-2020 by David Korth. *
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later *
|
||||
***************************************************************************/
|
||||
|
||||
@ -14,6 +14,9 @@
|
||||
namespace LibRomData {
|
||||
|
||||
ROMDATA_DECL_BEGIN(GameBoyAdvance)
|
||||
ROMDATA_DECL_IMGSUPPORT()
|
||||
ROMDATA_DECL_IMGPF()
|
||||
ROMDATA_DECL_IMGEXT()
|
||||
ROMDATA_DECL_END()
|
||||
|
||||
}
|
||||
|
@ -246,7 +246,7 @@ const RomDataFactoryPrivate::RomDataFns RomDataFactoryPrivate::romDataFns_magic[
|
||||
|
||||
// Handhelds
|
||||
GetRomDataFns_addr(DMG, ATTR_HAS_METADATA, 0x104, 0xCEED6666),
|
||||
GetRomDataFns_addr(GameBoyAdvance, ATTR_NONE, 0x04, 0x24FFAE51),
|
||||
GetRomDataFns_addr(GameBoyAdvance, ATTR_HAS_THUMBNAIL, 0x04, 0x24FFAE51),
|
||||
GetRomDataFns_addr(Lynx, ATTR_NONE, 0, 'LYNX'),
|
||||
GetRomDataFns_addr(NGPC, ATTR_HAS_METADATA, 12, ' SNK'),
|
||||
GetRomDataFns_addr(Nintendo3DSFirm, ATTR_NONE, 0, 'FIRM'),
|
||||
|
@ -104,6 +104,44 @@ string RomDataPrivate::getCacheKey_GameTDB(
|
||||
system, type, region, gameID, ext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the RPDB URL for a given game.
|
||||
* @param system System name.
|
||||
* @param type Image type.
|
||||
* @param region Region name.
|
||||
* @param gameID Game ID.
|
||||
* @param ext File extension, e.g. ".png" or ".jpg".
|
||||
* TODO: PAL multi-region selection?
|
||||
* @return RPDB URL.
|
||||
*/
|
||||
string RomDataPrivate::getURL_RPDB(
|
||||
const char *system, const char *type,
|
||||
const char *region, const char *gameID,
|
||||
const char *ext)
|
||||
{
|
||||
return rp_sprintf("https://rpdb.gerbilsoft.com/%s/%s/%s/%s%s",
|
||||
system, type, region, gameID, ext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the RPDB cache key for a given game.
|
||||
* @param system System name.
|
||||
* @param type Image type.
|
||||
* @param region Region name.
|
||||
* @param gameID Game ID.
|
||||
* @param ext File extension, e.g. ".png" or ".jpg".
|
||||
* TODO: PAL multi-region selection?
|
||||
* @return RPDB cache key.
|
||||
*/
|
||||
string RomDataPrivate::getCacheKey_RPDB(
|
||||
const char *system, const char *type,
|
||||
const char *region, const char *gameID,
|
||||
const char *ext)
|
||||
{
|
||||
return rp_sprintf("%s/%s/%s/%s%s",
|
||||
system, type, region, gameID, ext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Select the best size for an image.
|
||||
* @param sizeDefs Image size definitions.
|
||||
|
@ -98,6 +98,36 @@ class RomDataPrivate
|
||||
const char *region, const char *gameID,
|
||||
const char *ext);
|
||||
|
||||
/**
|
||||
* Get the RPDB URL for a given game.
|
||||
* @param system System name.
|
||||
* @param type Image type.
|
||||
* @param region Region name.
|
||||
* @param gameID Game ID.
|
||||
* @param ext File extension, e.g. ".png" or ".jpg".
|
||||
* TODO: PAL multi-region selection?
|
||||
* @return RPDB URL.
|
||||
*/
|
||||
static std::string getURL_RPDB(
|
||||
const char *system, const char *type,
|
||||
const char *region, const char *gameID,
|
||||
const char *ext);
|
||||
|
||||
/**
|
||||
* Get the RPDB cache key for a given game.
|
||||
* @param system System name.
|
||||
* @param type Image type.
|
||||
* @param region Region name.
|
||||
* @param gameID Game ID.
|
||||
* @param ext File extension, e.g. ".png" or ".jpg".
|
||||
* TODO: PAL multi-region selection?
|
||||
* @return RPDB cache key.
|
||||
*/
|
||||
static std::string getCacheKey_RPDB(
|
||||
const char *system, const char *type,
|
||||
const char *region, const char *gameID,
|
||||
const char *ext);
|
||||
|
||||
/**
|
||||
* Select the best size for an image.
|
||||
* @param sizeDefs Image size definitions.
|
||||
|
@ -342,6 +342,7 @@ int RP_C_API _tmain(int argc, TCHAR *argv[])
|
||||
SCMP_SYS(recvfrom), // getaddrinfo() (32-bit only?)
|
||||
|
||||
// cURL and OpenSSL
|
||||
SCMP_SYS(bind), // getaddrinfo() [curl_thread_create_thunk(), curl-7.68.0]
|
||||
#ifdef __SNR_getrandom
|
||||
SCMP_SYS(getrandom),
|
||||
#endif /* __SNR_getrandom */
|
||||
@ -406,6 +407,7 @@ int RP_C_API _tmain(int argc, TCHAR *argv[])
|
||||
// - 3ds: https://art.gametdb.com/3ds/[key]
|
||||
// - ds: https://art.gametdb.com/3ds/[key]
|
||||
// - amiibo: https://amiibo.life/[key]/image
|
||||
// - gba: https://rpdb.gerbilsoft.com/gba/[key]
|
||||
const TCHAR *slash_pos = _tcschr(cache_key, _T('/'));
|
||||
if (slash_pos == nullptr || slash_pos == cache_key ||
|
||||
slash_pos[1] == '\0')
|
||||
@ -463,6 +465,10 @@ int RP_C_API _tmain(int argc, TCHAR *argv[])
|
||||
_sntprintf(full_url, _countof(full_url),
|
||||
_T("https://amiibo.life/nfc/%.*s/image"),
|
||||
static_cast<int>(filename_len), slash_pos+1);
|
||||
} else if (prefix_len == 3 && !_tcsncmp(cache_key, _T("gba"), 3)) {
|
||||
// Game Boy Advance
|
||||
_sntprintf(full_url, _countof(full_url),
|
||||
_T("https://rpdb.gerbilsoft.com/%s"), cache_key);
|
||||
} else {
|
||||
// Prefix is not supported.
|
||||
SHOW_ERROR(_T("Cache key '%s' has an unsupported prefix."), cache_key);
|
||||
|
Loading…
Reference in New Issue
Block a user