mirror of
https://github.com/rommapp/romm.git
synced 2026-02-18 00:27:41 +01:00
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
1496 lines
38 KiB
Python
1496 lines
38 KiB
Python
import json
|
|
from datetime import datetime
|
|
from typing import Any, NotRequired, TypedDict
|
|
|
|
import httpx
|
|
import pydash
|
|
from fastapi import HTTPException, status
|
|
|
|
from config import DEV_MODE, HASHEOUS_API_ENABLED
|
|
from logger.logger import log
|
|
from models.rom import RomFile
|
|
from utils import get_version
|
|
from utils.context import ctx_httpx_client
|
|
|
|
from .base_handler import BaseRom, MetadataHandler
|
|
from .base_handler import UniversalPlatformSlug as UPS
|
|
from .igdb_handler import (
|
|
IGDB_AGE_RATINGS,
|
|
IGDBMetadata,
|
|
IGDBMetadataPlatform,
|
|
)
|
|
from .ra_handler import RAMetadata
|
|
|
|
|
|
class HasheousMetadata(TypedDict):
|
|
tosec_match: bool
|
|
mame_arcade_match: bool
|
|
mame_mess_match: bool
|
|
nointro_match: bool
|
|
redump_match: bool
|
|
whdload_match: bool
|
|
ra_match: bool
|
|
fbneo_match: bool
|
|
puredos_match: bool
|
|
|
|
|
|
class HasheousPlatform(TypedDict):
|
|
slug: str
|
|
hasheous_id: int | None
|
|
name: NotRequired[str]
|
|
igdb_id: NotRequired[int | None]
|
|
tgdb_id: NotRequired[int | None]
|
|
ra_id: NotRequired[int | None]
|
|
|
|
|
|
class HasheousRom(BaseRom):
|
|
hasheous_id: int | None
|
|
igdb_id: NotRequired[int | None]
|
|
slug: NotRequired[str]
|
|
igdb_metadata: NotRequired[IGDBMetadata]
|
|
ra_id: NotRequired[int | None]
|
|
ra_metadata: NotRequired[RAMetadata]
|
|
tgdb_id: NotRequired[int | None]
|
|
hasheous_metadata: NotRequired[HasheousMetadata]
|
|
|
|
|
|
ACCEPTABLE_FILE_EXTENSIONS_BY_PLATFORM_SLUG = {UPS.DC: ["bin", "chd", "cue"]}
|
|
|
|
|
|
def extract_metadata_from_igdb_rom(rom: dict[str, Any]) -> IGDBMetadata:
|
|
return IGDBMetadata(
|
|
{
|
|
"youtube_video_id": (
|
|
list(rom["videos"].values())[0]["video_id"]
|
|
if rom.get("videos")
|
|
else None
|
|
),
|
|
"total_rating": str(round(rom.get("total_rating", 0.0), 2)),
|
|
"aggregated_rating": str(round(rom.get("aggregated_rating", 0.0), 2)),
|
|
"first_release_date": (
|
|
int(
|
|
datetime.fromisoformat(
|
|
rom["first_release_date"].replace("Z", "+00:00")
|
|
).timestamp()
|
|
)
|
|
if rom.get("first_release_date")
|
|
else None
|
|
),
|
|
"genres": pydash.map_(rom.get("genres", {}), "name"),
|
|
"franchises": pydash.compact(
|
|
[rom.get("franchise.name", None)]
|
|
+ pydash.map_(rom.get("franchises", {}), "name")
|
|
),
|
|
"alternative_names": pydash.map_(rom.get("alternative_names", {}), "name"),
|
|
"collections": pydash.map_(rom.get("collections", {}), "name"),
|
|
"game_modes": pydash.map_(rom.get("game_modes", {}), "name"),
|
|
"companies": pydash.compact(
|
|
pydash.map_(rom.get("involved_companies", {}), "company.name")
|
|
),
|
|
"platforms": [
|
|
IGDBMetadataPlatform(igdb_id=p.get("id", ""), name=p.get("name", ""))
|
|
for p in pydash.map_(rom.get("platforms", {}))
|
|
],
|
|
"age_ratings": [
|
|
IGDB_AGE_RATINGS[r]
|
|
for r in pydash.map_(rom.get("age_ratings", {}), "rating_category")
|
|
if r in IGDB_AGE_RATINGS
|
|
],
|
|
"expansions": [],
|
|
"dlcs": [],
|
|
"ports": [],
|
|
"remakes": [],
|
|
"remasters": [],
|
|
"similar_games": [],
|
|
"expanded_games": [],
|
|
}
|
|
)
|
|
|
|
|
|
class HasheousHandler(MetadataHandler):
|
|
def __init__(self) -> None:
|
|
self.BASE_URL = (
|
|
"https://beta.hasheous.org/api/v1"
|
|
if DEV_MODE
|
|
else "https://hasheous.org/api/v1"
|
|
)
|
|
self.healthcheck_endpoint = f"{self.BASE_URL}/HealthCheck"
|
|
self.platform_endpoint = f"{self.BASE_URL}/Lookup/Platforms"
|
|
self.games_endpoint = f"{self.BASE_URL}/Lookup/ByHash"
|
|
self.proxy_igdb_game_endpoint = f"{self.BASE_URL}/MetadataProxy/IGDB/Game"
|
|
self.proxy_igdb_cover_endpoint = f"{self.BASE_URL}/MetadataProxy/IGDB/Cover"
|
|
self.proxy_ra_game_endpoint = f"{self.BASE_URL}/MetadataProxy/RA/Game"
|
|
self.app_api_key = (
|
|
"UUvh9ef_CddMM4xXO1iqxl9FqEt764v33LU-UiGFc0P34odXjMP9M6MTeE4JZRxZ"
|
|
if DEV_MODE
|
|
else "JNoFBA-jEh4HbxuxEHM6MVzydKoAXs9eCcp2dvcg5LRCnpp312voiWmjuaIssSzS"
|
|
)
|
|
|
|
@classmethod
|
|
def is_enabled(cls) -> bool:
|
|
"""Return whether this metadata handler is enabled."""
|
|
return HASHEOUS_API_ENABLED
|
|
|
|
async def heartbeat(self) -> bool:
|
|
if not self.is_enabled():
|
|
return False
|
|
|
|
httpx_client = ctx_httpx_client.get()
|
|
try:
|
|
response = await httpx_client.get(self.healthcheck_endpoint)
|
|
response.raise_for_status()
|
|
except Exception as e:
|
|
log.error("Error checking Hasheous API: %s", e)
|
|
return False
|
|
|
|
return bool(response)
|
|
|
|
async def _request(
|
|
self,
|
|
url: str,
|
|
method: str = "POST",
|
|
params: dict | None = None,
|
|
data: dict | None = None,
|
|
) -> dict:
|
|
httpx_client = ctx_httpx_client.get()
|
|
|
|
# Normalize method to uppercase
|
|
method = method.upper()
|
|
if method not in ["GET", "POST"]:
|
|
raise ValueError(f"Unsupported HTTP method: {method}")
|
|
|
|
try:
|
|
log.debug(
|
|
"API request: Method=%s, URL=%s, Params=%s, Data=%s",
|
|
method,
|
|
url,
|
|
params,
|
|
data,
|
|
)
|
|
|
|
# Prepare request kwargs
|
|
request_kwargs = {
|
|
"url": url,
|
|
"params": params,
|
|
"headers": {
|
|
"Content-Type": "application/json-patch+json",
|
|
"User-Agent": f"RomM/{get_version()}",
|
|
"X-Client-API-Key": self.app_api_key,
|
|
},
|
|
"timeout": 120,
|
|
}
|
|
|
|
# Add method-specific parameters
|
|
if method == "POST":
|
|
request_kwargs["json"] = data
|
|
|
|
res = await httpx_client.request(method, **request_kwargs)
|
|
res.raise_for_status()
|
|
return res.json()
|
|
except httpx.HTTPStatusError as exc:
|
|
# Check if its a 404 error
|
|
if exc.response.status_code == status.HTTP_404_NOT_FOUND:
|
|
log.debug("Game not found in Hasheous API")
|
|
return {}
|
|
|
|
log.error(
|
|
"Hasheous API returned an error: %s %s",
|
|
exc.response.status_code,
|
|
exc.response.text,
|
|
)
|
|
pass
|
|
except httpx.NetworkError as exc:
|
|
log.critical("Connection error: can't connect to Hasheous")
|
|
raise HTTPException(
|
|
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
|
detail="Can't connect to Hasheous, check your internet connection",
|
|
) from exc
|
|
except json.decoder.JSONDecodeError as exc:
|
|
# Log the error and return an empty dict if the response is not valid JSON
|
|
log.error(exc)
|
|
return {}
|
|
except httpx.TimeoutException:
|
|
pass
|
|
|
|
return {}
|
|
|
|
def get_platform(self, slug: str) -> HasheousPlatform:
|
|
if slug not in HASHEOUS_PLATFORM_LIST:
|
|
return HasheousPlatform(hasheous_id=None, slug=slug)
|
|
|
|
platform = HASHEOUS_PLATFORM_LIST[UPS(slug)]
|
|
return HasheousPlatform(
|
|
hasheous_id=platform["id"],
|
|
slug=slug,
|
|
name=platform["name"],
|
|
igdb_id=platform["igdb_id"],
|
|
tgdb_id=platform["tgdb_id"],
|
|
ra_id=platform["ra_id"],
|
|
)
|
|
|
|
async def lookup_rom(self, platform_slug: str, files: list[RomFile]) -> HasheousRom:
|
|
fallback_rom = HasheousRom(
|
|
hasheous_id=None, igdb_id=None, tgdb_id=None, ra_id=None
|
|
)
|
|
|
|
if not self.is_enabled():
|
|
return fallback_rom
|
|
|
|
filtered_files = [
|
|
file
|
|
for file in files
|
|
if file.file_size_bytes > 0
|
|
and file.is_top_level
|
|
and (
|
|
UPS(platform_slug) not in ACCEPTABLE_FILE_EXTENSIONS_BY_PLATFORM_SLUG
|
|
or file.file_extension
|
|
in ACCEPTABLE_FILE_EXTENSIONS_BY_PLATFORM_SLUG[UPS(platform_slug)]
|
|
)
|
|
]
|
|
|
|
# Select the largest file by size, as it is most likely to be the main ROM file.
|
|
# This increases the accuracy of metadata lookups, since the largest file is
|
|
# expected to have the correct and complete hash values for external services.
|
|
first_file = max(filtered_files, key=lambda f: f.file_size_bytes, default=None)
|
|
if first_file is None:
|
|
return fallback_rom
|
|
|
|
md5_hash = first_file.md5_hash
|
|
sha1_hash = first_file.sha1_hash
|
|
crc_hash = first_file.crc_hash
|
|
|
|
if not (md5_hash or sha1_hash or crc_hash):
|
|
log.warning(
|
|
"No hashes provided for Hasheous lookup. "
|
|
"At least one of md5_hash, sha1_hash, or crc_hash is required."
|
|
)
|
|
return fallback_rom
|
|
|
|
data = {}
|
|
if md5_hash:
|
|
data["mD5"] = md5_hash
|
|
if sha1_hash:
|
|
data["shA1"] = sha1_hash
|
|
if crc_hash:
|
|
data["crc"] = crc_hash
|
|
|
|
hasheous_game = await self._request(
|
|
self.games_endpoint,
|
|
params={
|
|
"returnAllSources": "true",
|
|
"returnFields": "Signatures, Metadata, Attributes",
|
|
},
|
|
data=data,
|
|
)
|
|
|
|
if not hasheous_game:
|
|
return fallback_rom
|
|
|
|
metadata = hasheous_game.get("metadata", [])
|
|
attributes = hasheous_game.get("attributes", [])
|
|
signatures = hasheous_game.get("signatures", {}).keys()
|
|
|
|
igdb_id = None
|
|
tgdb_id = None
|
|
ra_id = None
|
|
|
|
for meta in metadata:
|
|
if meta["source"] == "IGDB":
|
|
try:
|
|
# TEMP: Hasheous is slowly replacing slugs with IDs
|
|
igdb_id = int(meta["immutableId"])
|
|
except (ValueError, TypeError):
|
|
log.debug(
|
|
f"Found an IGDB slug instead of an ID: {meta['immutableId']}"
|
|
)
|
|
pass
|
|
elif meta["source"] == "TheGamesDB":
|
|
tgdb_id = meta["immutableId"]
|
|
elif meta["source"] == "RetroAchievements":
|
|
ra_id = meta["immutableId"]
|
|
|
|
url_cover = ""
|
|
for attr in attributes:
|
|
if attr["attributeName"] == "Logo":
|
|
url_cover = f"https://hasheous.org{attr['link']}"
|
|
break
|
|
|
|
return HasheousRom(
|
|
hasheous_id=hasheous_game["id"],
|
|
name=hasheous_game.get("name", ""),
|
|
igdb_id=int(igdb_id) if igdb_id else None,
|
|
tgdb_id=int(tgdb_id) if tgdb_id else None,
|
|
ra_id=int(ra_id) if ra_id else None,
|
|
url_cover=url_cover,
|
|
hasheous_metadata=HasheousMetadata(
|
|
tosec_match="TOSEC" in signatures,
|
|
mame_arcade_match="MAMEArcade" in signatures,
|
|
mame_mess_match="MAMEMess" in signatures,
|
|
nointro_match="NoIntros" in signatures,
|
|
redump_match="Redump" in signatures,
|
|
whdload_match="WHDLoad" in signatures,
|
|
ra_match="RetroAchievements" in signatures,
|
|
fbneo_match="FBNeo" in signatures,
|
|
puredos_match="PureDOS" in signatures,
|
|
),
|
|
)
|
|
|
|
async def get_igdb_game(self, hasheous_rom: HasheousRom) -> HasheousRom:
|
|
if not self.is_enabled():
|
|
return hasheous_rom
|
|
|
|
igdb_id = hasheous_rom.get("igdb_id", None)
|
|
|
|
if igdb_id is None:
|
|
log.info("No IGDB ID provided for Hasheous IGDB game lookup.")
|
|
return hasheous_rom
|
|
|
|
igdb_game = await self._request(
|
|
self.proxy_igdb_game_endpoint,
|
|
params={
|
|
"Id": igdb_id,
|
|
"expandColumns": "age_ratings, alternative_names, collections, cover, dlcs, expanded_games, franchise, franchises, game_modes, genres, involved_companies, platforms, ports, remakes, screenshots, similar_games, videos",
|
|
},
|
|
method="GET",
|
|
)
|
|
|
|
if not igdb_game:
|
|
log.debug(f"No Hasheous game found for IGDB ID {igdb_id}.")
|
|
return hasheous_rom
|
|
|
|
return HasheousRom(
|
|
{
|
|
**hasheous_rom,
|
|
"slug": igdb_game.get("slug") or hasheous_rom.get("slug") or "",
|
|
"name": igdb_game.get("name") or hasheous_rom.get("name") or "",
|
|
"summary": igdb_game.get("summary", ""),
|
|
"url_cover": self.normalize_cover_url(
|
|
pydash.get(igdb_game, "cover.url", "")
|
|
).replace("t_thumb", "t_1080p")
|
|
or hasheous_rom.get("url_cover", ""),
|
|
"url_screenshots": [
|
|
self.normalize_cover_url(s.get("url", "")).replace(
|
|
"t_thumb", "t_720p"
|
|
)
|
|
for s in pydash.get(igdb_game, "screenshots", {}).values()
|
|
]
|
|
or hasheous_rom.get("url_screenshots", []),
|
|
"igdb_metadata": extract_metadata_from_igdb_rom(igdb_game),
|
|
}
|
|
)
|
|
|
|
async def get_ra_game(self, hasheous_rom: HasheousRom) -> HasheousRom:
|
|
if not self.is_enabled():
|
|
return hasheous_rom
|
|
|
|
ra_id = hasheous_rom.get("ra_id", None)
|
|
|
|
if ra_id is None:
|
|
log.info("No RA ID provided for Hasheous RA game lookup.")
|
|
return hasheous_rom
|
|
|
|
ra_game = await self._request(
|
|
self.proxy_ra_game_endpoint,
|
|
params={"Id": ra_id},
|
|
method="GET",
|
|
)
|
|
|
|
if not ra_game:
|
|
log.debug(f"No Hasheous game found for RA ID {ra_id}.")
|
|
return hasheous_rom
|
|
|
|
return hasheous_rom
|
|
|
|
|
|
class SlugToHasheousId(TypedDict):
|
|
id: int
|
|
name: str
|
|
igdb_id: int | None
|
|
igdb_slug: str | None
|
|
tgdb_id: int | None
|
|
ra_id: int | None
|
|
|
|
|
|
HASHEOUS_PLATFORM_LIST: dict[UPS, SlugToHasheousId] = {
|
|
UPS._3DO: {
|
|
"id": 161825,
|
|
"igdb_id": 50,
|
|
"igdb_slug": "3do",
|
|
"name": "3DO Interactive Multiplayer",
|
|
"ra_id": 43,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.N3DS: {
|
|
"id": 62,
|
|
"igdb_id": 37,
|
|
"igdb_slug": "3ds",
|
|
"name": "Nintendo 3DS",
|
|
"ra_id": 62,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.N64DD: {
|
|
"id": 65,
|
|
"igdb_id": 416,
|
|
"igdb_slug": "64dd",
|
|
"name": "Nintendo 64DD",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.ACORN_ARCHIMEDES: {
|
|
"id": 24,
|
|
"igdb_id": 116,
|
|
"igdb_slug": "acorn-archimedes",
|
|
"name": "Acorn Archimedes",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.ACORN_ELECTRON: {
|
|
"id": 25,
|
|
"igdb_id": 134,
|
|
"igdb_slug": "acorn-electron",
|
|
"name": "Acorn Electron",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.ACPC: {
|
|
"id": 28,
|
|
"igdb_id": 25,
|
|
"igdb_slug": "acpc",
|
|
"name": "Amstrad CPC",
|
|
"ra_id": 37,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.ACTION_MAX: {
|
|
"id": 232983,
|
|
"igdb_id": None,
|
|
"igdb_slug": "",
|
|
"name": "Action Max",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.ADVENTURE_VISION: {
|
|
"id": 234388,
|
|
"igdb_id": None,
|
|
"igdb_slug": "",
|
|
"name": "Entex Adventure Vision",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.ALTAIR_8800: {
|
|
"id": 234456,
|
|
"igdb_id": None,
|
|
"igdb_slug": "",
|
|
"name": "MITS Altair 8800",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.AMIGA: {
|
|
"id": 3,
|
|
"igdb_id": 16,
|
|
"igdb_slug": "amiga",
|
|
"name": "Commodore Amiga",
|
|
"ra_id": 35,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.AMIGA_CD32: {
|
|
"id": 161823,
|
|
"igdb_id": 114,
|
|
"igdb_slug": "amiga-cd32",
|
|
"name": "Commodore CD32",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.AMSTRAD_GX4000: {
|
|
"id": 61540,
|
|
"igdb_id": 506,
|
|
"igdb_slug": "amstrad-gx4000",
|
|
"name": "Amstrad GX4000",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.AMSTRAD_PCW: {
|
|
"id": 29,
|
|
"igdb_id": 154,
|
|
"igdb_slug": "amstrad-pcw",
|
|
"name": "Amstrad PCW",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.APF: {
|
|
"id": 61738,
|
|
"igdb_id": None,
|
|
"igdb_slug": "",
|
|
"name": "APF Imagination Machine",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.APPLE: {
|
|
"id": 61885,
|
|
"igdb_id": None,
|
|
"igdb_slug": "",
|
|
"name": "Apple I",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.APPLE_IIGS: {
|
|
"id": 21,
|
|
"igdb_id": 115,
|
|
"igdb_slug": "apple-iigs",
|
|
"name": "Apple IIGS",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.APPLE_LISA: {
|
|
"id": 69659,
|
|
"igdb_id": None,
|
|
"igdb_slug": "",
|
|
"name": "Apple Lisa",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.APPLE_PIPPIN: {
|
|
"id": 22,
|
|
"igdb_id": 476,
|
|
"igdb_slug": "apple-pippin",
|
|
"name": "Apple Pippin",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.APPLEII: {
|
|
"id": 20,
|
|
"igdb_id": 75,
|
|
"igdb_slug": "appleii",
|
|
"name": "Apple II",
|
|
"ra_id": 38,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.APPLEIII: {
|
|
"id": 63154,
|
|
"igdb_id": None,
|
|
"igdb_slug": "",
|
|
"name": "Apple III",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.ARCADE: {
|
|
"id": 178,
|
|
"igdb_id": 52,
|
|
"igdb_slug": "arcade",
|
|
"name": "Arcade",
|
|
"ra_id": 27,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.ARDUBOY: {
|
|
"id": 244294,
|
|
"igdb_id": 438,
|
|
"igdb_slug": "arduboy",
|
|
"name": "Arduboy",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.ASTROCADE: {
|
|
"id": 31,
|
|
"igdb_id": 91,
|
|
"igdb_slug": "astrocade",
|
|
"name": "Bally Astrocade",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.ATARI_ST: {
|
|
"id": 15,
|
|
"igdb_id": 63,
|
|
"igdb_slug": "atari-st",
|
|
"name": "Atari ST/STE",
|
|
"ra_id": 36,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.ATARI2600: {
|
|
"id": 12,
|
|
"igdb_id": 59,
|
|
"igdb_slug": "atari2600",
|
|
"name": "Atari 2600",
|
|
"ra_id": 25,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.ATARI5200: {
|
|
"id": 17,
|
|
"igdb_id": 66,
|
|
"igdb_slug": "atari5200",
|
|
"name": "Atari 5200",
|
|
"ra_id": 50,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.ATARI7800: {
|
|
"id": 16,
|
|
"igdb_id": 60,
|
|
"igdb_slug": "atari7800",
|
|
"name": "Atari 7800",
|
|
"ra_id": 51,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.ATARI8BIT: {
|
|
"id": 18,
|
|
"igdb_id": 65,
|
|
"igdb_slug": "atari8bit",
|
|
"name": "Atari 8-bit",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.ATOM: {
|
|
"id": 55099,
|
|
"igdb_id": None,
|
|
"igdb_slug": "",
|
|
"name": "Acorn Atom",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.BBCMICRO: {
|
|
"id": 26,
|
|
"igdb_id": 69,
|
|
"igdb_slug": "bbcmicro",
|
|
"name": "BBC Micro",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.BEENA: {
|
|
"id": 82,
|
|
"igdb_id": None,
|
|
"igdb_slug": "",
|
|
"name": "Sega Advanced Pico Beena",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.BIT_90: {
|
|
"id": 97614,
|
|
"igdb_id": None,
|
|
"igdb_slug": "",
|
|
"name": "Bit Corporation BIT 90",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.C_PLUS_4: {
|
|
"id": 7,
|
|
"igdb_id": 94,
|
|
"igdb_slug": "c-plus-4",
|
|
"name": "Commodore Plus/4",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.C128: {
|
|
"id": 8,
|
|
"igdb_id": None,
|
|
"igdb_slug": "",
|
|
"name": "Commodore 128",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.C16: {
|
|
"id": 6,
|
|
"igdb_id": 93,
|
|
"igdb_slug": "c16",
|
|
"name": "Commodore 16",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.C64: {
|
|
"id": 5,
|
|
"igdb_id": 15,
|
|
"igdb_slug": "c64",
|
|
"name": "Commodore MAX",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.CAMPUTERS_LYNX: {
|
|
"id": 97720,
|
|
"igdb_id": None,
|
|
"igdb_slug": "",
|
|
"name": "Camputers Lynx",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.CASIO_CFX_9850: {
|
|
"id": 97839,
|
|
"igdb_id": None,
|
|
"igdb_slug": "",
|
|
"name": "Casio CFX-9850",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.CASIO_FP_1000: {
|
|
"id": 98757,
|
|
"igdb_id": None,
|
|
"igdb_slug": "",
|
|
"name": "Casio FP-1000 & FP-1100",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.CASIO_LOOPY: {
|
|
"id": 37,
|
|
"igdb_id": 380,
|
|
"igdb_slug": "casio-loopy",
|
|
"name": "Casio Loopy",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.CASIO_PB_1000: {
|
|
"id": 98771,
|
|
"igdb_id": None,
|
|
"igdb_slug": "",
|
|
"name": "Casio PB-1000",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.CASIO_PV_1000: {
|
|
"id": 98793,
|
|
"igdb_id": None,
|
|
"igdb_slug": "",
|
|
"name": "Casio PV-1000",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.CASIO_PV_2000: {
|
|
"id": 98811,
|
|
"igdb_id": None,
|
|
"igdb_slug": "",
|
|
"name": "Casio PV-2000",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.COLECOVISION: {
|
|
"id": 39,
|
|
"igdb_id": 68,
|
|
"igdb_slug": "colecovision",
|
|
"name": "ColecoVision",
|
|
"ra_id": 44,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.COMMANDER_X16: {
|
|
"id": 54769,
|
|
"igdb_id": None,
|
|
"igdb_slug": "",
|
|
"name": "8-Bit Productions Commander X16",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.COMMODORE_CDTV: {
|
|
"id": 9,
|
|
"igdb_id": 158,
|
|
"igdb_slug": "commodore-cdtv",
|
|
"name": "Commodore CDTV",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.CPET: {
|
|
"id": 10,
|
|
"igdb_id": 90,
|
|
"igdb_slug": "cpet",
|
|
"name": "Commodore PET",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.DC: {
|
|
"id": 54694,
|
|
"igdb_id": 23,
|
|
"igdb_slug": "dc",
|
|
"name": "Sega Dreamcast",
|
|
"ra_id": 40,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.DOS: {
|
|
"id": 233075,
|
|
"igdb_id": 13,
|
|
"igdb_slug": "dos",
|
|
"name": "Microsoft DOS",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.EXCALIBUR_64: {
|
|
"id": 97612,
|
|
"igdb_id": None,
|
|
"igdb_slug": "",
|
|
"name": "BGR Computers Excalibur 64",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.FAIRCHILD_CHANNEL_F: {
|
|
"id": 43,
|
|
"igdb_id": 127,
|
|
"igdb_slug": "fairchild-channel-f",
|
|
"name": "Fairchild Channel F",
|
|
"ra_id": 57,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.FDS: {
|
|
"id": 54692,
|
|
"igdb_id": 51,
|
|
"igdb_slug": "fds",
|
|
"name": "Nintendo Famicom Disk System",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.FM_TOWNS: {
|
|
"id": 238902,
|
|
"igdb_id": 118,
|
|
"igdb_slug": "fm-towns",
|
|
"name": "Fujitsu - FM Towns",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.GAMATE: {
|
|
"id": 97616,
|
|
"igdb_id": 378,
|
|
"igdb_slug": "gamate",
|
|
"name": "Bit Corporation Gamate",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.GAMEGEAR: {
|
|
"id": 84,
|
|
"igdb_id": 35,
|
|
"igdb_slug": "gamegear",
|
|
"name": "Sega Game Gear",
|
|
"ra_id": 15,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.GB: {
|
|
"id": 70,
|
|
"igdb_id": 33,
|
|
"igdb_slug": "gb",
|
|
"name": "Nintendo GameBoy",
|
|
"ra_id": 4,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.GBA: {
|
|
"id": 71,
|
|
"igdb_id": 24,
|
|
"igdb_slug": "gba",
|
|
"name": "Nintendo Game Boy Advance",
|
|
"ra_id": 5,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.GBC: {
|
|
"id": 72,
|
|
"igdb_id": 22,
|
|
"igdb_slug": "gbc",
|
|
"name": "Nintendo Game Boy Color",
|
|
"ra_id": 6,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.GENESIS: {
|
|
"id": 86,
|
|
"igdb_id": 29,
|
|
"igdb_slug": "genesis-slash-megadrive",
|
|
"name": "Sega Mega Drive / Genesis",
|
|
"ra_id": 1,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.INTELLIVISION: {
|
|
"id": 52,
|
|
"igdb_id": 67,
|
|
"igdb_slug": "intellivision",
|
|
"name": "Mattel Intellivision",
|
|
"ra_id": 45,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.JAGUAR: {
|
|
"id": 13,
|
|
"igdb_id": 62,
|
|
"igdb_slug": "jaguar",
|
|
"name": "Atari Jaguar",
|
|
"ra_id": 17,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.LINUX: {
|
|
"id": 233076,
|
|
"igdb_id": 3,
|
|
"igdb_slug": "linux",
|
|
"name": "Linux",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.LYNX: {
|
|
"id": 14,
|
|
"igdb_id": 61,
|
|
"igdb_slug": "lynx",
|
|
"name": "Atari Lynx",
|
|
"ra_id": 13,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.MAC: {
|
|
"id": 30,
|
|
"igdb_id": 14,
|
|
"igdb_slug": "mac",
|
|
"name": "Apple Mac",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.AQUARIUS: {
|
|
"id": 51,
|
|
"igdb_id": None,
|
|
"igdb_slug": "",
|
|
"name": "Mattel Aquarius",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.MICROBEE: {
|
|
"id": 69714,
|
|
"igdb_id": None,
|
|
"igdb_slug": "",
|
|
"name": "Applied Technology MicroBee",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.MSX: {
|
|
"id": 53,
|
|
"igdb_id": 27,
|
|
"igdb_slug": "msx",
|
|
"name": "MSX",
|
|
"ra_id": 29,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.MSX2: {
|
|
"id": 54,
|
|
"igdb_id": 53,
|
|
"igdb_slug": "msx2",
|
|
"name": "MSX 2",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.MULTIVISION: {
|
|
"id": 52922,
|
|
"igdb_id": None,
|
|
"igdb_slug": "",
|
|
"name": "Tsukuda Original Othello Multivision",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.N64: {
|
|
"id": 64,
|
|
"igdb_id": 4,
|
|
"igdb_slug": "n64",
|
|
"name": "Nintendo 64",
|
|
"ra_id": 2,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.NDS: {
|
|
"id": 66,
|
|
"igdb_id": 20,
|
|
"igdb_slug": "nds",
|
|
"name": "Nintendo DS",
|
|
"ra_id": 18,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.NEC_PC_6000_SERIES: {
|
|
"id": 58,
|
|
"igdb_id": 157,
|
|
"igdb_slug": "nec-pc-6000-series",
|
|
"name": "NEC PC-6000",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.NEO_GEO_CD: {
|
|
"id": 161829,
|
|
"igdb_id": 136,
|
|
"igdb_slug": "neo-geo-cd",
|
|
"name": "Neo Geo CD",
|
|
"ra_id": 56,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.NEO_GEO_POCKET: {
|
|
"id": 97,
|
|
"igdb_id": 119,
|
|
"igdb_slug": "neo-geo-pocket",
|
|
"name": "Neo Geo Pocket",
|
|
"ra_id": 14,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.NEO_GEO_POCKET_COLOR: {
|
|
"id": 98,
|
|
"igdb_id": 120,
|
|
"igdb_slug": "neo-geo-pocket-color",
|
|
"name": "Neo Geo Pocket Color",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.NEOGEOAES: {
|
|
"id": 96,
|
|
"igdb_id": 80,
|
|
"igdb_slug": "neogeoaes",
|
|
"name": "Neo Geo",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.NES: {
|
|
"id": 68,
|
|
"igdb_id": 18,
|
|
"igdb_slug": "nes",
|
|
"name": "Nintendo Entertainment System",
|
|
"ra_id": 7,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.NEW_NINTENDON3DS: {
|
|
"id": 63,
|
|
"igdb_id": 137,
|
|
"igdb_slug": "new-nintendo-3ds",
|
|
"name": "Nintendo New 3DS",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.NGC: {
|
|
"id": 73,
|
|
"igdb_id": 21,
|
|
"igdb_slug": "ngc",
|
|
"name": "Nintendo GameCube",
|
|
"ra_id": 16,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.NINTENDO_DSI: {
|
|
"id": 67,
|
|
"igdb_id": 159,
|
|
"igdb_slug": "nintendo-dsi",
|
|
"name": "Nintendo DSi",
|
|
"ra_id": 78,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.ODYSSEY: {
|
|
"id": 48,
|
|
"igdb_id": 88,
|
|
"igdb_slug": "odyssey--1",
|
|
"name": "Magnavox Odyssey",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.ODYSSEY_2: {
|
|
"id": 49,
|
|
"igdb_id": 133,
|
|
"igdb_slug": "odyssey-2-slash-videopac-g7000",
|
|
"name": "Magnavox Odyssey 2",
|
|
"ra_id": 23,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.PC_8800_SERIES: {
|
|
"id": 57,
|
|
"igdb_id": 125,
|
|
"igdb_slug": "pc-8800-series",
|
|
"name": "NEC PC-8800",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.PC_9800_SERIES: {
|
|
"id": 59,
|
|
"igdb_id": 149,
|
|
"igdb_slug": "pc-9800-series",
|
|
"name": "NEC PC-9000",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.PC_JR: {
|
|
"id": 233269,
|
|
"igdb_id": None,
|
|
"igdb_slug": "",
|
|
"name": "IBM PCjr",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.PHILIPS_CD_I: {
|
|
"id": 161827,
|
|
"igdb_id": 117,
|
|
"igdb_slug": "philips-cd-i",
|
|
"name": "Philips CD-i",
|
|
"ra_id": 42,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.POCKET_CHALLENGE_V2: {
|
|
"id": 97550,
|
|
"igdb_id": None,
|
|
"igdb_slug": "",
|
|
"name": "Benesse Pocket Challenge V2",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.POCKET_CHALLENGE_W: {
|
|
"id": 97577,
|
|
"igdb_id": None,
|
|
"igdb_slug": "",
|
|
"name": "Benesse Pocket Challenge W",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.POCKETSTATION: {
|
|
"id": 103,
|
|
"igdb_id": 441,
|
|
"igdb_slug": "pocketstation",
|
|
"name": "Sony PocketStation",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.POKEMON_MINI: {
|
|
"id": 244733,
|
|
"igdb_id": 166,
|
|
"igdb_slug": "pokemon-mini",
|
|
"name": "Nintendo Pokemon Mini",
|
|
"ra_id": 24,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.PS2: {
|
|
"id": 101,
|
|
"igdb_id": 8,
|
|
"igdb_slug": "ps2",
|
|
"name": "Sony PlayStation 2",
|
|
"ra_id": 21,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.PS3: {
|
|
"id": 161830,
|
|
"igdb_id": 9,
|
|
"igdb_slug": "ps3",
|
|
"name": "Sony Playstation 3",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.PS4: {
|
|
"id": 232986,
|
|
"igdb_id": 48,
|
|
"igdb_slug": "ps4--1",
|
|
"name": "Sony Playstation 4",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.PS5: {
|
|
"id": 232987,
|
|
"igdb_id": 167,
|
|
"igdb_slug": "ps5",
|
|
"name": "Sony Playstation 5",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.PSP: {
|
|
"id": 161831,
|
|
"igdb_id": 38,
|
|
"igdb_slug": "psp",
|
|
"name": "Sony Playstation Portable",
|
|
"ra_id": 41,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.PSVITA: {
|
|
"id": 102,
|
|
"igdb_id": 46,
|
|
"igdb_slug": "psvita",
|
|
"name": "Sony PlayStation Vita",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.PSX: {
|
|
"id": 100,
|
|
"igdb_id": 7,
|
|
"igdb_slug": "ps",
|
|
"name": "Sony PlayStation",
|
|
"ra_id": 12,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.RCA_STUDIO_II: {
|
|
"id": 234745,
|
|
"igdb_id": None,
|
|
"igdb_slug": "",
|
|
"name": "RCA Studio II",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.SATURN: {
|
|
"id": 54695,
|
|
"igdb_id": 32,
|
|
"igdb_slug": "saturn",
|
|
"name": "Sega Saturn",
|
|
"ra_id": 39,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.SC3000: {
|
|
"id": 52165,
|
|
"igdb_id": None,
|
|
"igdb_slug": "",
|
|
"name": "Sega Computer 3000",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.SEGA_PICO: {
|
|
"id": 81,
|
|
"igdb_id": 339,
|
|
"igdb_slug": "sega-pico",
|
|
"name": "Sega Pico",
|
|
"ra_id": 68,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.SEGA32: {
|
|
"id": 80,
|
|
"igdb_id": 30,
|
|
"igdb_slug": "sega32",
|
|
"name": "Sega 32X",
|
|
"ra_id": 10,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.SEGACD: {
|
|
"id": 161828,
|
|
"igdb_id": None,
|
|
"igdb_slug": "",
|
|
"name": "Sega Mega CD / Sega CD",
|
|
"ra_id": 9,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.SERIES_X_S: {
|
|
"id": 232984,
|
|
"igdb_id": 169,
|
|
"igdb_slug": "series-x-s",
|
|
"name": "Microsoft Xbox Series X",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.SFAM: {
|
|
"id": 233081,
|
|
"igdb_id": 58,
|
|
"igdb_slug": "sfam",
|
|
"name": "Super Famicom",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.SG1000: {
|
|
"id": 244470,
|
|
"igdb_id": 84,
|
|
"igdb_slug": "sg1000",
|
|
"name": "SG-1000",
|
|
"ra_id": 33,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.SHARP_X68000: {
|
|
"id": 90,
|
|
"igdb_id": 121,
|
|
"igdb_slug": "sharp-x68000",
|
|
"name": "Sharp X68000",
|
|
"ra_id": 52,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.SINCLAIR_QL: {
|
|
"id": 92,
|
|
"igdb_id": 406,
|
|
"igdb_slug": "sinclair-ql",
|
|
"name": "Sinclair QL",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.SMS: {
|
|
"id": 85,
|
|
"igdb_id": 64,
|
|
"igdb_slug": "sms",
|
|
"name": "Sega Master System",
|
|
"ra_id": 11,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.SNES: {
|
|
"id": 74,
|
|
"igdb_id": 19,
|
|
"igdb_slug": "snes",
|
|
"name": "Super Nintendo Entertainment System",
|
|
"ra_id": 3,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.SUPER_VISION_8000: {
|
|
"id": 97267,
|
|
"igdb_id": None,
|
|
"igdb_slug": "",
|
|
"name": "Bandai Super Vision 8000",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.SWITCH: {
|
|
"id": 233067,
|
|
"igdb_id": 130,
|
|
"igdb_slug": "switch",
|
|
"name": "Nintendo Switch",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.TG16: {
|
|
"id": 245372,
|
|
"igdb_id": 86,
|
|
"igdb_slug": "turbografx16--1",
|
|
"name": "TurboGrafx-16/PC Engine",
|
|
"ra_id": 8,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.TI_82: {
|
|
"id": 47973,
|
|
"igdb_id": None,
|
|
"igdb_slug": "",
|
|
"name": "Texas Instruments TI-82",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.TI_83: {
|
|
"id": 243852,
|
|
"igdb_id": None,
|
|
"igdb_slug": "",
|
|
"name": "Texas Instruments TI-83",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.TRS_80: {
|
|
"id": 105,
|
|
"igdb_id": 126,
|
|
"igdb_slug": "trs-80",
|
|
"name": "Tandy/RadioShack TRS-80",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.TRS_80_COLOR_COMPUTER: {
|
|
"id": 106,
|
|
"igdb_id": 151,
|
|
"igdb_slug": "trs-80-color-computer",
|
|
"name": "Tandy/RadioShack TRS-80 Color Computer",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.TURBOGRAFX_CD: {
|
|
"id": 247350,
|
|
"igdb_id": 150,
|
|
"igdb_slug": "turbografx-16-slash-pc-engine-cd",
|
|
"name": "Turbografx-16/PC Engine CD",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.VECTREX: {
|
|
"id": 45,
|
|
"igdb_id": 70,
|
|
"igdb_slug": "vectrex",
|
|
"name": "Vectrex",
|
|
"ra_id": 46,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.VIC_20: {
|
|
"id": 4,
|
|
"igdb_id": 71,
|
|
"igdb_slug": "vic-20",
|
|
"name": "Commodore VIC20",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.VIRTUALBOY: {
|
|
"id": 75,
|
|
"igdb_id": 87,
|
|
"igdb_slug": "virtualboy",
|
|
"name": "Nintendo Virtual Boy",
|
|
"ra_id": 28,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.SUPERVISION: {
|
|
"id": 244828,
|
|
"igdb_id": 415,
|
|
"igdb_slug": "watara-slash-quickshot-supervision",
|
|
"name": "Watara Supervision",
|
|
"ra_id": 63,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.WII: {
|
|
"id": 76,
|
|
"igdb_id": 5,
|
|
"igdb_slug": "wii",
|
|
"name": "Nintendo Wii",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.WIIU: {
|
|
"id": 77,
|
|
"igdb_id": 41,
|
|
"igdb_slug": "wiiu",
|
|
"name": "Nintendo WiiU",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.WIN: {
|
|
"id": 233074,
|
|
"igdb_id": 6,
|
|
"igdb_slug": "win",
|
|
"name": "Microsoft Windows",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.WONDERSWAN: {
|
|
"id": 34,
|
|
"igdb_id": 57,
|
|
"igdb_slug": "wonderswan",
|
|
"name": "Bandai WonderSwan",
|
|
"ra_id": 53,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.WONDERSWAN_COLOR: {
|
|
"id": 35,
|
|
"igdb_id": 123,
|
|
"igdb_slug": "wonderswan-color",
|
|
"name": "Bandai WonderSwan Color",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.X1: {
|
|
"id": 89,
|
|
"igdb_id": 77,
|
|
"igdb_slug": "x1",
|
|
"name": "Sharp X1",
|
|
"ra_id": 64,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.XBOX: {
|
|
"id": 54696,
|
|
"igdb_id": 11,
|
|
"igdb_slug": "xbox",
|
|
"name": "Microsoft Xbox",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.XBOX360: {
|
|
"id": 54697,
|
|
"igdb_id": 12,
|
|
"igdb_slug": "xbox360",
|
|
"name": "Microsoft Xbox 360",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.XBOXONE: {
|
|
"id": 161824,
|
|
"igdb_id": 49,
|
|
"igdb_slug": "xboxone",
|
|
"name": "Microsoft Xbox One",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.Z88: {
|
|
"id": 97718,
|
|
"igdb_id": None,
|
|
"igdb_slug": "",
|
|
"name": "Cambridge Computer Z88",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.ZX80: {
|
|
"id": 232985,
|
|
"igdb_id": None,
|
|
"igdb_slug": "",
|
|
"name": "Sinclair ZX80",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.ZX81: {
|
|
"id": 94,
|
|
"igdb_id": 373,
|
|
"igdb_slug": "sinclair-zx81",
|
|
"name": "Sinclair ZX81",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
UPS.ZXS: {
|
|
"id": 93,
|
|
"igdb_id": 26,
|
|
"igdb_slug": "zxs",
|
|
"name": "Sinclair ZX Spectrum",
|
|
"ra_id": None,
|
|
"tgdb_id": None,
|
|
},
|
|
}
|