[libromdata] PlayStationDisc: Added external cover images using RPDB.

The images are mirrored from the following GitHub repositories:
* https://github.com/xlenore/psx-covers
* https://github.com/xlenore/ps2-covers

Fixes #371: PlayStation 1 and 2 covers
Rpeorted by @DankRank.

TODO: Add PlayStationDisc to rp-config.
This commit is contained in:
David Korth 2022-12-27 19:36:18 -05:00
parent 49aea33f67
commit a6a1c98dc4
6 changed files with 176 additions and 2 deletions

View File

@ -55,12 +55,18 @@ or deleted.
* Nintendo Game Boy Color
* Nintendo Game Boy Advance
* Sega Mega Drive / Genesis, Sega CD, 32X, Pico
* Sony PlayStation 1 and 2
* Super NES
* WonderSwan (Color)
The RPDB domain is also used by rp-config's update checker to determine if
a newer version of rom-properties is available.
PlayStation 1 and 2 cover art is mirrored from the following GitHub repositories:
* https://github.com/xlenore/psx-covers
* https://github.com/xlenore/ps2-covers
### ROM Information Used
The following information is used as the lookup key in order to retrieve
@ -77,6 +83,7 @@ images from the online databases:
* amiibo: 64-bit amiibo ID (e.g. `00000000-00000002`)
* Neo Geo Pocket (Color): Game ID (e.g. `NEOP0001`). For certain games
with invalid IDs (e.g. homebrew), the game title is also used.
* PlayStation 1 and 2: Game ID (e.g. `SLUS-20718`)
* Sega Mega Drive and related: Serial number (e.g. `GM 00001009-00`)
and region code.
* Super NES: Game title and region code (e.g. `SNS-SUPER MARIOWORLD-USA`),

View File

@ -2,6 +2,14 @@
## v2.2 (released 2023/??/??)
* New features:
* PlayStationDisc: Added external cover images using RPDB, mirrored from
the following GitHub repositories:
* https://github.com/xlenore/psx-covers
* https://github.com/xlenore/ps2-covers
* Fixes #371: PlayStation 1 and 2 covers
* Reported by @DankRank.
* Bug fixes:
* WiiWAD: Add application/x-doom-wad for compatibility with some systems that
assume all .wad files are Doom WADs.

View File

@ -120,7 +120,7 @@ button.
| Sega Dreamcast | Yes | Yes | Media | No |
| Sega Dreamcast Saves | Yes | Yes | Icon, Banner | No |
| Sega Saturn | Yes | Yes | N/A | No |
| Sony PlayStation Discs | Yes | No | N/A | No |
| Sony PlayStation Discs | Yes | No | N/A | Covers |
| Sony PlayStation EXEs | Yes | No | N/A | N/A |
| Sony PlayStation Saves | Yes | Yes | Icon | N/A |
| Sony PlayStation 2 Discs | Yes | Yes | N/A | No |
@ -388,3 +388,5 @@ https://github.com/GerbilSoft/rom-properties/issues
* [Vulkan SDK for Android](https://arm-software.github.io/vulkan-sdk/_a_s_t_c.html)
for the ASTC file format header.
* [NEZ Plug](http://nezplug.sourceforge.net/) for basic GBR specifications.
* [xlenore](https://github.com/xlenore) for the PlayStation 1 and 2 cover art
repository.

View File

@ -7,6 +7,8 @@
***************************************************************************/
#include "stdafx.h"
#include "librpbase/config.librpbase.h"
#include "PlayStationDisc.hpp"
#include "ps2_structs.h"
@ -109,6 +111,7 @@ class PlayStationDiscPrivate final : public RomDataPrivate
};
ROMDATA_IMPL(PlayStationDisc)
ROMDATA_IMPL_IMG(PlayStationDisc)
/** PlayStationDiscPrivate **/
@ -614,6 +617,49 @@ const char *PlayStationDisc::systemName(unsigned int type) const
return nullptr;
}
/**
* Get a bitfield of image types this class can retrieve.
* @return Bitfield of supported image types. (ImageTypesBF)
*/
uint32_t PlayStationDisc::supportedImageTypes_static(void)
{
#ifdef HAVE_JPEG
return IMGBF_EXT_COVER;
#else /* !HAVE_JPEG */
return 0;
#endif /* HAVE_JPEG */
}
/**
* 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> PlayStationDisc::supportedImageSizes_static(ImageType imageType)
{
ASSERT_supportedImageSizes(imageType);
switch (imageType) {
#ifdef HAVE_JPEG
case IMG_EXT_COVER: {
// xlenore PS1 cover art images are 500x500.
// xlenore PS2 cover art images are 512x736.
// TODO: Non-static version that indicates this.
static const ImageSizeDef sz_EXT_COVER[] = {
{nullptr, 500, 500, 0},
};
return vector<ImageSizeDef>(sz_EXT_COVER,
sz_EXT_COVER + ARRAY_SIZE(sz_EXT_COVER));
}
#endif /* HAVE_JPEG */
default:
break;
}
// Unsupported image type.
return vector<ImageSizeDef>();
}
/**
* Load field data.
* Called by RomData::fields() if the field data hasn't been loaded yet.
@ -817,4 +863,109 @@ int PlayStationDisc::loadMetaData(void)
return static_cast<int>(d->metaData->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 PlayStationDisc::extURLs(ImageType imageType, vector<ExtURL> *pExtURLs, int size) const
{
ASSERT_extURLs(imageType, pExtURLs);
pExtURLs->clear();
RP_D(const PlayStationDisc);
if (!d->isValid || (int)d->consoleType < 0) {
// Disc image isn't valid.
return -EIO;
}
// Get the disc serial number. (boot filename)
if (d->boot_filename.empty() || d->boot_filename == "PSX.EXE") {
// No boot filename, or it's the default filename.
return -ENOENT;
}
// System ID
static const char sys_tbl[][4] = {
"ps1", "ps2"
};
if (d->consoleType >= PlayStationDiscPrivate::ConsoleType::Max)
return -ENOENT;
const char *const sys = sys_tbl[(int)d->consoleType];
// Game ID format: SLUS-20718
// Boot filename format: SLUS_207.18
// Using the first part as the region code.
string gameID = d->boot_filename;
string region_code;
size_t pos = gameID.find('_');
if (pos != string::npos) {
region_code = gameID.substr(0, pos);
gameID[pos] = '-';
} else if (d->boot_filename.size() > 4) {
// No underscore. Use the first four characters as the region.
region_code = gameID.substr(0, 4);
} else {
// Too short to be a game ID.
return -ENOENT;
}
// Remove the dot.
pos = gameID.rfind('.');
if (pos != string::npos) {
gameID.erase(pos, 1);
}
// NOTE: We only have one size for MegaDrive right now.
// TODO: Determine the actual image size.
RP_UNUSED(size);
vector<ImageSizeDef> sizeDefs = supportedImageSizes(imageType);
assert(sizeDefs.size() == 1);
if (sizeDefs.empty()) {
// No image sizes.
return -ENOENT;
}
// NOTE: RPDB's cover 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) {
#ifdef HAVE_JPEG
case IMG_EXT_COVER:
imageTypeName = "cover";
ext = ".jpg";
break;
#endif /* HAVE_JPEG */
default:
// Unsupported image type.
return -ENOENT;
}
// Add the URLs.
pExtURLs->resize(1);
auto extURL_iter = pExtURLs->begin();
extURL_iter->url = d->getURL_RPDB(sys, imageTypeName, region_code.c_str(), gameID.c_str(), ext);
extURL_iter->cache_key = d->getCacheKey_RPDB(sys, imageTypeName, region_code.c_str(), gameID.c_str(), 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;
}
}

View File

@ -27,6 +27,8 @@ ROMDATA_DECL_CLOSE()
const ISO_Primary_Volume_Descriptor *pvd);
ROMDATA_DECL_METADATA()
ROMDATA_DECL_IMGSUPPORT()
ROMDATA_DECL_IMGEXT()
ROMDATA_DECL_END()
}

View File

@ -480,6 +480,8 @@ int RP_C_API _tmain(int argc, TCHAR *argv[])
// - cbmII: https://rpdb.gerbilsoft.com/cbmII/[key]
// - vic20: https://rpdb.gerbilsoft.com/vic20/[key]
// - plus4: https://rpdb.gerbilsoft.com/plus4/[key]
// - ps1: https://rpdb.gerbilsoft.com/ps1/[key]
// - ps2: https://rpdb.gerbilsoft.com/ps2/[key]
// - sys: https://rpdb.gerbilsoft.com/sys/[key] [system info, e.g. update version]
const TCHAR *slash_pos = _tcschr(cache_key, _T('/'));
if (slash_pos == nullptr || slash_pos == cache_key ||
@ -579,7 +581,9 @@ int RP_C_API _tmain(int argc, TCHAR *argv[])
if (!_tcsncmp(cache_key, _T("gba"), 3) ||
!_tcsncmp(cache_key, _T("mcd"), 3) ||
!_tcsncmp(cache_key, _T("32x"), 3) ||
!_tcsncmp(cache_key, _T("c64"), 3))
!_tcsncmp(cache_key, _T("c64"), 3) ||
!_tcsncmp(cache_key, _T("ps1"), 3) ||
!_tcsncmp(cache_key, _T("ps2"), 3))
{
ok = true;
}