NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript==
// @name Retro Enhanced
// @namespace https://github.com/miagui
// @version 1.4.5
// @description Additional functionality for retro gaming related sites.
// @author Miagui
// @match *://retroachievements.org/*
// @license MIT
// @updateURL https://openuserjs.org/meta/Miagui/Retro_Enhanced.meta.js
// @downloadURL https://openuserjs.org/install/Miagui/Retro_Enhanced.user.js
// @grant GM_xmlhttpRequest
// @grant GM_log
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_listValues
// @grant GM_deleteValue
// @connect archive.org
// @connect the-eye.eu
// @connect raw.githubusercontent.com
// @connect sheets.googleapis.com
// @connect emuparadise.me
// @connect speedrun.com
// @connect myrient.erista.me
// @require http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js
// ==/UserScript==
(async function () {
var pageWithParams = (location.pathname + location.search).substr(1);
var page = location.pathname;
var loggedUser = $(".brand-top strong > a").text();
var sectionName = window.location.hash.slice(1);
// Configs
var enableSpeedrun = await GM_getValue("enableSpeedrun", false);
var enableRomSearch = await GM_getValue("enableRomSearch", true);
var enableCustomBG = await GM_getValue("enableCustomBG", true);
var enableGameplayVideo = await GM_getValue("enableGameplayVideo", true);
var enableEmuparadise = await GM_getValue("enableEmuparadise", false);
var prioritizeEmuparadise = await GM_getValue("prioritizeEmuparadise", false);
var enableGlassEffect = await await GM_getValue("enableGlassEffect", true);
const RAConsole = {
ARCADE: "Arcade",
SNES: "SNES/Super Famicom",
NES: "NES/Famicom",
GAMEBOY: "Game Boy",
GAMEBOYCOLOR: "Game Boy Color",
GAMEBOYADVANCE: "Game Boy Advance",
NINTENDO64: "Nintendo 64",
GAMECUBE: "GameCube",
NINTENDODS: "Nintendo DS",
NINTENDODSI: "Nintendo DSi",
ATARI2600: "Atari 2600",
ATARI7800: "Atari 7800",
ATARIJAGUAR: "Atari Jaguar",
ATARIJAGUARCD: "Atari Jaguar CD",
ATARILYNX: "Atari Lynx",
PCENGINE: "PC Engine/TurboGrafx-16",
PCENGINECD: "PC Engine CD/TurboGrafx-CD",
MASTERSYSTEM: "Master System",
GAMEGEAR: "Game Gear",
MEGADRIVE: "Genesis/Mega Drive",
SEGA32X: "32X",
SEGACD: "Sega CD",
SATURN: "Saturn",
DREAMCAST: "Dreamcast",
PS1: "PlayStation",
PS2: "PlayStation 2",
PSP: "PlayStation Portable",
P3DO: "3DO Interactive Multiplayer",
NEOGEOCD: "Neo Geo CD",
NEOGEOPOCKET: "Neo Geo Pocket",
POKEMINI: "Pokemon Mini",
VIRTUALBOY: "Virtual Boy",
SG1000: "SG-1000",
COLECO: "ColecoVision",
MSX: "MSX",
WII: "Wii",
WONDERSWAN: "WonderSwan",
VECTREX: "Vectrex",
NEC8800: "PC-8000/8800",
APPLEII: "Apple II",
PCFX: "PC-FX",
ARDUBOY: "Arduboy",
ARCADIA: "Arcadia 2001",
FAIRCHILD: "Fairchild Channel F",
MAGNAVOXODYSSEY2: "Magnavox Odyssey 2",
INTELLIVISION: "Intellivision",
INTERTONVC4000: "Interton VC 4000",
MEGADUCK: "Mega Duck",
WATARA: "Watara Supervision",
ZEEBO: "Zeebo"
};
const SRConsole = {
PC: "8gej2n93",
APPLEII: "w89ryw6l",
ATARI2600: "o0644863",
ARCADE: "vm9vn63k",
NEC8800: "7g6mw8er",
COLECOVISION: "wxeo8d6r",
COMMODORE64: "gz9qox60",
MSX: "jm950z6o",
NES: "jm95z9ol",
MSX2: "83exkk6l",
MASTERSYSTEM: "83exwk6l",
ATARI7800: "gde33gek",
FAMICOMDISKSYSTEM: "mr6k409z",
PCENGINE: "5negxk6y",
MEGADRIVE: "mr6k0ezw",
GAMEBOY: "n5683oev",
NEOGEOAES: "mx6p4w63",
GAMEGEAR: "w89r3w9l",
SNES: "83exk6l5",
PHILIPSCDI: "w89rjw6l",
SEGACD: "31670d9q",
PANASONIC3D0: "8gejmne3",
NEOGEOCD: "kz9w7mep",
PCFX: "p36n8568",
PS1: "wxeod9rn",
SEGA32X: "kz9wrn6p",
SEGASATURN: "lq60l642",
VIRTUALBOY: "7g6mk8er",
NINTENDO64: "w89rwelk",
GAMEBOYCOLOR: "gde3g9k1",
NEOGEOPOCKETCOLOR: "7m6ydw6p",
TURBOGRAFX16CD: "p36nlxe8",
DREAMCAST: "v06d394z",
WONDERSWAN: "vm9v8n63",
PLAYSTATION2: "n5e17e27",
WONDERSWANCOLOUR: "n568kz6v",
GAMEBOYADVANCE: "3167d6q2",
GAMECUBE: "4p9z06rn",
POKÉMONMINI: "vm9vr1e3",
NINTENDODS: "7g6m8erk",
PLAYSTATIONPORTABLE: "5negk9y7",
WII: "v06dk3e4"
}
const archiveCollectionDict = {
[RAConsole.SATURN]: {
name: "Redump Sega Saturn 2018",
url: "https://archive.org/download/SegaSaturn2018July10"
},
[RAConsole.DREAMCAST]: {
name: "CHD-ZSTD - Sega Dreamcast (Redump)",
url: "https://archive.org/download/dc-chd-zstd-redump/dc-chd-zstd"
},
[RAConsole.SEGACD]: {
name: "Redump Sega Mega CD & Sega CD",
url: "https://archive.org/download/redump.sega_megacd-segacd"
},
[RAConsole.NEOGEOCD]: {
name: "[REDUMP] Disc Image Collection: SNK - Neo Geo CD",
url: "https://archive.org/download/redump.ngcd.revival"
},
[RAConsole.ATARI2600]: {
name: "No-Intro Atari 2600",
url: "https://archive.org/download/nointro2600atarii"
},
[RAConsole.NINTENDODS]: {
name: "No-Intro Nintendo DS Decrypted",
url: "https://archive.org/download/noIntroNintendoDsDecrypted2019Jun30"
},
[RAConsole.APPLEII]: {
name: "Apple 2 TOSEC 2012",
url: "https://archive.org/details/Apple_2_TOSEC_2012_04_23"
}
};
const myrientCollectionDict = {
// CDs and DVDs files
[RAConsole.PS1]: {
name: "chd_psx",
urls: [
"https://myrient.erista.me/files/Internet%20Archive/chadmaster/chd_psx/CHD-PSX-USA/",
"https://myrient.erista.me/files/Internet%20Archive/chadmaster/chd_psx_eur/CHD-PSX-EUR/",
"https://myrient.erista.me/files/Internet%20Archive/chadmaster/chd_psx_jap/CHD-PSX-JAP/",
"https://myrient.erista.me/files/Internet%20Archive/chadmaster/chd_psx_jap_p2/CHD-PSX-JAP/",
"https://myrient.erista.me/files/Internet%20Archive/chadmaster/chd_psx_misc/CHD-PSX-Misc/"
]
},
[RAConsole.PSP]: {
name: "psp-chd-zstd-redump",
urls: [
"https://myrient.erista.me/files/Internet%20Archive/chadmaster/psp-chd-zstd-redump-part1/psp-chd-zstd/",
"https://myrient.erista.me/files/Internet%20Archive/chadmaster/psp-chd-zstd-redump-part2/psp-chd-zstd/",
]
},
[RAConsole.PS2]: {
name: "Sony - PlayStation 2",
urls: [
"https://myrient.erista.me/files/Redump/Sony%20-%20PlayStation%202/"
]
},
[RAConsole.SATURN]: {
name: "chd_saturn",
urls: ["https://myrient.erista.me/files/Internet%20Archive/chadmaster/chd_saturn/CHD-Saturn/USA/",
"https://myrient.erista.me/files/Internet%20Archive/chadmaster/chd_saturn/CHD-Saturn/Japan/",
"https://myrient.erista.me/files/Internet%20Archive/chadmaster/chd_saturn/CHD-Saturn/Europe/"
]
},
[RAConsole.DREAMCAST]: {
name: "dc-chd-zstd",
urls: ["https://myrient.erista.me/files/Internet%20Archive/chadmaster/dc-chd-zstd-redump/dc-chd-zstd/"]
},
[RAConsole.GAMECUBE]: {
name: "Nintendo - GameCube - NKit RVZ [zstd-19-128k]",
urls: ["https://myrient.erista.me/files/Redump/Nintendo%20-%20GameCube%20-%20NKit%20RVZ%20%5Bzstd-19-128k%5D/"]
},
[RAConsole.WII]: {
name: "Nintendo - Wii - NKit RVZ [zstd-19-128k]",
urls: ["https://myrient.erista.me/files/Redump/Nintendo%20-%20Wii%20-%20NKit%20RVZ%20%5Bzstd-19-128k%5D/"]
},
[RAConsole.SEGACD]: {
name: "chd_segacd",
urls: [
"https://myrient.erista.me/files/Internet%20Archive/chadmaster/chd_segacd/CHD-SegaCD-NTSC/",
"https://myrient.erista.me/files/Internet%20Archive/chadmaster/chd_segacd/CHD-MegaCD-NTSCJ/",
"https://myrient.erista.me/files/Internet%20Archive/chadmaster/chd_segacd/CHD-MegaCD-PAL/",
]
},
[RAConsole.P3DO]: {
name: "3do-chd-zstd",
urls: ["https://myrient.erista.me/files/Internet%20Archive/chadmaster/3do-chd-zstd-redump/3do-chd-zstd/"]
},
[RAConsole.ATARIJAGUARCD]: {
name: "jagcd-chd-zstd",
urls: ["https://myrient.erista.me/files/Internet%20Archive/chadmaster/jagcd-chd-zstd/jagcd-chd-zstd/"]
},
[RAConsole.NEOGEOCD]: {
name: "ngcd-chd-zstd",
urls: ["https://myrient.erista.me/files/Internet%20Archive/chadmaster/ngcd-chd-zstd-redump/ngcd-chd-zstd/"]
},
[RAConsole.PCENGINECD]: {
name: "pcecd-chd-zstd",
urls: ["https://myrient.erista.me/files/Internet%20Archive/chadmaster/pcecd-chd-zstd-redump/pcecd-chd-zstd/"]
},
[RAConsole.PCFX]: {
name: "PC-FX",
urls: ["https://myrient.erista.me/files/Redump/NEC%20-%20PC-FX%20%26%20PC-FXGA/"]
},
// Cartridge roms
[RAConsole.ARDUBOY]: {
name: "Arduboy",
urls: ["https://myrient.erista.me/files/No-Intro/Arduboy%20Inc%20-%20Arduboy/"]
},
[RAConsole.ATARI2600]: {
name: "Atari - 2600",
urls: ["https://myrient.erista.me/files/No-Intro/Atari%20-%202600/"]
},
[RAConsole.ATARI7800]: {
name: "Atari - 7800",
urls: ["https://myrient.erista.me/files/No-Intro/Atari%20-%207800/"]
},
[RAConsole.ATARIJAGUAR]: {
name: "Atari - Jaguar (ROM)",
urls: ["https://myrient.erista.me/files/No-Intro/Atari%20-%20Jaguar%20%28ROM%29/"]
},
[RAConsole.ATARILYNX]: {
name: "Atari - Lynx (LYX)",
urls: ["https://myrient.erista.me/files/No-Intro/Atari%20-%20Lynx%20%28LYX%29/"]
},
[RAConsole.WONDERSWAN]: {
name: "Wonderswan",
urls: ["https://myrient.erista.me/files/No-Intro/Bandai%20-%20WonderSwan/",
"https://myrient.erista.me/files/No-Intro/Bandai%20-%20WonderSwan%20Color/"
]
},
[RAConsole.COLECO]: {
name: "Coleco - ColecoVision",
urls: ["https://myrient.erista.me/files/No-Intro/Coleco%20-%20ColecoVision/",
]
},
[RAConsole.ARCADIA]: {
name: "Emerson - Arcadia 2001",
urls: ["https://myrient.erista.me/files/No-Intro/Emerson%20-%20Arcadia%202001/"]
},
[RAConsole.FAIRCHILD]: {
name: "https://myrient.erista.me/files/No-Intro/Fairchild%20-%20Channel%20F/",
urls: ["Fairchild - Channel F"]
},
[RAConsole.VECTREX]: {
name: "GCE - Vectrex",
urls: ["https://myrient.erista.me/files/No-Intro/GCE%20-%20Vectrex/"]
},
[RAConsole.MAGNAVOXODYSSEY2]: {
name: "Magnavox - Odyssey 2",
urls: ["https://myrient.erista.me/files/No-Intro/Magnavox%20-%20Odyssey%202/"]
},
[RAConsole.INTELLIVISION]: {
name: "Mattel - Intellivision",
urls: ["https://myrient.erista.me/files/No-Intro/Mattel%20-%20Intellivision/"]
},
[RAConsole.INTERTONVC4000]: {
name: "Interton - VC 4000",
urls: ["https://myrient.erista.me/files/No-Intro/Interton%20-%20VC%204000/"]
},
[RAConsole.MEGADUCK]: {
name: "Welback - Mega Duck",
urls: ["https://myrient.erista.me/files/No-Intro/Welback%20-%20Mega%20Duck/"]
},
[RAConsole.MSX]: {
name: "Microsoft - MSX",
urls: ["https://myrient.erista.me/files/No-Intro/Microsoft%20-%20MSX/",
"https://myrient.erista.me/files/No-Intro/Microsoft%20-%20MSX2/"
]
},
[RAConsole.NEC8800]: {
name: "Neo Kobe - NEC PC-8801 (2016-02-25)",
urls: ["https://ia801307.us.archive.org/view_archive.php?archive=/35/items/Neo_Kobe_NEC_PC-8001_2016-02-25/Neo%20Kobe%20-%20NEC%20PC-8001%20%282016-02-25%29.zip",
"https://ia801305.us.archive.org/view_archive.php?archive=/32/items/Neo_Kobe_NEC_PC-8801_2016-02-25/Neo%20Kobe%20-%20NEC%20PC-8801%20%282016-02-25%29.zip"
]
},
[RAConsole.PCENGINE]: {
name: "NEC - PC Engine SuperGrafx",
urls: ["https://myrient.erista.me/files/No-Intro/NEC%20-%20PC%20Engine%20-%20TurboGrafx-16/",
"https://myrient.erista.me/files/No-Intro/NEC%20-%20PC%20Engine%20SuperGrafx/"
]
},
[RAConsole.NES]: {
name: "Nintendo - Nintendo Entertainment System (Headered)",
urls: ["https://myrient.erista.me/files/No-Intro/Nintendo%20-%20Nintendo%20Entertainment%20System%20%28Headered%29/",
"https://myrient.erista.me/files/No-Intro/Nintendo%20-%20Family%20Computer%20Disk%20System%20%28FDS%29/",
"https://myrient.erista.me/files/No-Intro/Nintendo%20-%20Nintendo%20Entertainment%20System%20%28Headered%29%20%28Private%29/"
]
},
[RAConsole.GAMEBOY]: {
name: "Nintendo - Game Boy",
urls: ["https://myrient.erista.me/files/No-Intro/Nintendo%20-%20Game%20Boy/"]
},
[RAConsole.GAMEBOYADVANCE]: {
name: "Nintendo - Game Boy Advance",
urls: ["https://myrient.erista.me/files/No-Intro/Nintendo%20-%20Game%20Boy%20Advance/"]
},
[RAConsole.GAMEBOYCOLOR]: {
name: "Nintendo - Game Boy Color",
urls: ["https://myrient.erista.me/files/No-Intro/Nintendo%20-%20Game%20Boy%20Color/"]
},
[RAConsole.NINTENDO64]: {
name: "Nintendo - Nintendo 64 (BigEndian)",
urls: ["https://myrient.erista.me/files/No-Intro/Nintendo%20-%20Nintendo%2064%20%28BigEndian%29/"]
},
[RAConsole.NINTENDODS]: {
name: "Nintendo - Nintendo DS (Decrypted)",
urls: ["https://myrient.erista.me/files/No-Intro/Nintendo%20-%20Nintendo%20DS%20%28Decrypted%29/"]
},
[RAConsole.NINTENDODSI]: {
name: "Nintendo - Nintendo DSi (Digital)",
urls: ["https://myrient.erista.me/files/No-Intro/Nintendo%20-%20Nintendo%20DSi%20%28Digital%29/"]
},
[RAConsole.POKEMINI]: {
name: "Nintendo - Pokemon Mini",
urls: ["https://myrient.erista.me/files/No-Intro/Nintendo%20-%20Pokemon%20Mini/"]
},
[RAConsole.SNES]: {
name: "Nintendo - Super Nintendo Entertainment System",
urls: ["https://myrient.erista.me/files/No-Intro/Nintendo%20-%20Super%20Nintendo%20Entertainment%20System/",
"https://myrient.erista.me/files/No-Intro/Nintendo%20-%20Super%20Nintendo%20Entertainment%20System%20%28Private%29/"
]
},
[RAConsole.VIRTUALBOY]: {
name: "Nintendo - Virtual Boy",
urls: ["https://myrient.erista.me/files/No-Intro/Nintendo%20-%20Virtual%20Boy/"]
},
[RAConsole.NEOGEOPOCKET]: {
name: "SNK - NeoGeo Pocket Color",
urls: ["https://myrient.erista.me/files/No-Intro/SNK%20-%20NeoGeo%20Pocket%20Color/",
"https://myrient.erista.me/files/No-Intro/SNK%20-%20NeoGeo%20Pocket/"
]
},
[RAConsole.SEGA32X]: {
name: "Sega - 32X",
urls: ["https://myrient.erista.me/files/No-Intro/Sega%20-%2032X/"]
},
[RAConsole.GAMEGEAR]: {
name: "Sega - Game Gear",
urls: ["https://myrient.erista.me/files/No-Intro/Sega%20-%20Game%20Gear/"]
},
[RAConsole.MASTERSYSTEM]: {
name: "Sega - Master System - Mark III",
urls: ["https://myrient.erista.me/files/No-Intro/Sega%20-%20Master%20System%20-%20Mark%20III/"]
},
[RAConsole.MEGADRIVE]: {
name: "Sega - Mega Drive - Genesis",
urls: ["https://myrient.erista.me/files/No-Intro/Sega%20-%20Mega%20Drive%20-%20Genesis/",
"https://myrient.erista.me/files/No-Intro/Sega%20-%20Mega%20Drive%20-%20Genesis%20%28Private%29/"
]
},
[RAConsole.SG1000]: {
name: "Sega - SG-1000",
urls: ["https://myrient.erista.me/files/No-Intro/Sega%20-%20SG-1000/"]
},
[RAConsole.WATARA]: {
name: "Watara - Supervision",
urls: ["https://myrient.erista.me/files/No-Intro/Watara%20-%20Supervision/"]
},
[RAConsole.ZEEBO]: {
name: "Zeebo - Zeebo",
urls: ["https://myrient.erista.me/files/No-Intro/Zeebo%20-%20Zeebo/"]
},
// [RAConsole.]: {
// name: "",
// urls: [""]
// },
// TODO: Missing Amstrad CPC, Apple II, Elektor TV Games Computer, Uzebox, WASM4
// TODO: Find better source for PC88?
};
// GM_log(enableSpeedrun)
// GM_log(enableRomSearch)
// GM_log(enableCustomBG)
// GM_log(page)
// GM_log(sectionName)
if (page == "/settings") {
(function () {
let id = setInterval(function () {
if ($('#app').length) {
clearInterval(id);
$('.with-sidebar article > div > div').children().eq(2).after("<div id='enhanced-settings' class='p-6 text-card-foreground rounded-lg border border-embed-highlight bg-embed shadow-sm w-full'></div>")
let settingsDiv = $("#enhanced-settings");
settingsDiv.append("<h3 class='pb-2 border-b-0 text-2xl font-semibold leading-none tracking-tight'>Retro Enhanced</h3>")
settingsDiv.append(`<div class="flex flex-col gap-5 @xl:hidden">
<div class="flex gap-1">
<input id="enhanced-romsearch" type="checkbox" ${enableRomSearch ? "checked='checked'" : ""}>
<div class='pl-1 text-menu-link'>Enable ROMs search</div>
</div>
<div class="flex gap-1">
<input id="enhanced-epromsearch" type="checkbox" ${enableEmuparadise ? "checked='checked'" : ""}>
<div class='pl-1 text-menu-link'>Add Emuparadise to ROMs search <div style="font-size: 0.8em; color:rgb(185, 185, 185);">(for Chrome users: <a href="https://experienceleague.adobe.com/docs/target/using/experiences/vec/troubleshoot-composer/mixed-content.html?lang=en#task_FF297A08F66E47A588C14FD67C037B3A">enable this</a>; for all browsers: must click on "Add Exception and Get my File!" for the first time)</div></div>
</div>
<div class="flex gap-1">
<input id="enhanced-prioritize_ep" type="checkbox" ${prioritizeEmuparadise ? "checked='checked'" : ""}>
<div class='pl-1 text-menu-link'>Prioritize Emuparadise for ROMs search <div style="font-size: 0.8em; color:rgb(185, 185, 185);">(must have "Add Emuparadise to ROMs search" enabled)</div></div>
</div>
<div class="flex gap-1">
<input id="enhanced-speedrun" type="checkbox" ${enableSpeedrun ? "checked='checked'" : ""}>
<div class='pl-1 text-menu-link'>Enable Speedrun.com stats</div>
</div>
<div class="flex gap-1">
<input id="enhanced-gameplayvideo" type="checkbox" ${enableGameplayVideo ? "checked='checked'" : ""}>
<div class='pl-1 text-menu-link'>Enable gameplay video on the game page</div>
</div>
<div class="flex gap-1">
<input id="enhanced-custombg" type="checkbox" ${enableCustomBG ? "checked='checked'" : ""}>
<div class='pl-1 text-menu-link'>Enable custom game page background</div>
</div>
<div class="flex gap-1">
<input id="enhanced-glassEffect" type="checkbox" ${enableGlassEffect ? "checked='checked'" : ""}>
<div class='pl-1 text-menu-link'>Enable glass background effect</div>
</div>
</div>`)
}
}, 100);
})();
$(document).on('change', '#enhanced-romsearch', function () {
GM_setValue("enableRomSearch", $("#enhanced-romsearch").is(":checked"))
})
$(document).on('change', '#enhanced-epromsearch', function () {
GM_setValue("enableEmuparadise", $("#enhanced-epromsearch").is(":checked"))
})
$(document).on('change', '#enhanced-prioritize_ep', function () {
GM_setValue("prioritizeEmuparadise", $("#enhanced-prioritize_ep").is(":checked"))
})
$(document).on('change', '#enhanced-speedrun', function () {
GM_setValue("enableSpeedrun", $("#enhanced-speedrun").is(":checked"))
})
$(document).on('change', '#enhanced-custombg', function () {
GM_setValue("enableCustomBG", $("#enhanced-custombg").is(":checked"))
})
$(document).on('change', '#enhanced-gameplayvideo', function () {
GM_setValue("enableGameplayVideo", $("#enhanced-gameplayvideo").is(":checked"))
})
$(document).on('change', '#enhanced-glassEffect', function () {
GM_setValue("enableGlassEffect", $("#enhanced-glassEffect").is(":checked"))
})
}
// =========================================
// Game Set Page
// =========================================
// Regex: game/13918
else if (page.match(/game\/[0-9]/g) != null ||
page == "/gameInfo.php") {
// General
var console = $(".navpath").children().eq(1).text(); //
var game = $(".navpath").children().eq(2).text(); //
var gameId = /([^\/]+)\/?$/g.exec($("meta[property='og:url']").attr("content"))[0]; //
var points = $("#achievement .TrueRatio").eq(0).prev().text();
var icon = $("#achievement div:eq(2) > img").attr("src")
var tag = "";
var gameImg = $("#achievement img[alt=\"In-game screenshot\"]").attr("src");
var rgxTag = /\~(.*?)\~/g;
// GM_log("Icon:" + icon)
// Check for tags
if (game.match(rgxTag) != undefined) {
tag = rgxTag.exec(game)[1];
game = game.replace(game.match(rgxTag) + " ", "");
}
// GM_log(gameId)
var isAvailable = false;
var collection = {
name: "",
url: ""
};
var results = [];
var resultsDlcs = [];
// Speedrun.com API resources
var srRoot = "https://www.speedrun.com/api/v1/";
var srLogo = "";
var srVideoUrl = "";
var srGamelink = "";
var srGameId = "";
var srRuns = [];
// GM_log(game)
// GM_log(console)
// Avoid unwanted exceptions for hubs pages.
if (console == "") return
// =========================================
// Divs Insertion
// =========================================
// Set custom background
if (gameImg != "https://media.retroachievements.org/Images/000002.png" && enableCustomBG) {
$("body").append(`<style>
body:before {
content: "";
position: fixed;
width : 110%;
height: 110%;
background: inherit;
background-size: cover;
z-index: -1;
overflow: hidden;
filter : blur(8px);
-moz-filter : blur(8px);
-webkit-filter: blur(8px);
-o-filter : blur(8px);
}
</style>`);
$("body").css({
"background-image": `url(${gameImg})`,
"background-attachment": "fixed",
"background-size": "90%",
"background-position": "center",
"background-repeat": "no-repeat"
})
}
// Change to glass background
if (enableGlassEffect) {
$(":root").attr("style", "--box-bg-color: rgba(35, 35, 35, 0.95);")
$("#leftcontainer").attr("style", "background: var(--box-bg-color);")
$("#rightcontainer").attr("style", "background: var(--box-bg-color);")
}
// Change top nav to body color
$(".brand-top").addClass("bg-body")
// Change header background to transparent
// $(".brand-top + nav").removeClass("bg-body")
// Prepare divs
$("aside > .gamealts").first().before("<div id='romsdl'></div>")
$("aside > .gamealts").first().before("<div id='speedruncom'></div>")
var divRoms = $("#romsdl");
var divSpeedruncom = $("#speedruncom");
divRoms.css("margin-top", "1em")
divSpeedruncom.css("margin", "1em 0em");
if (enableGameplayVideo || enableSpeedrun) getSpeedruns(game)
// =========================================
// Rom Search
// =========================================
if (enableRomSearch) {
// Verify if system is available
for (const prop in RAConsole) {
if (RAConsole.hasOwnProperty(prop)) {
const element = RAConsole[prop];
if (element == console) isAvailable = true;
}
}
if ((isAvailable && tag == "") || (console == RAConsole.ARCADE && tag != "")) {
var promise;
// Deprecated feature to find roms for hacks and homebrews.
// if (tag != "" && console != RAConsole.ARCADE) {
// promise = searchCustom();
// collection.name = "Custom";
// }
// Search through Emuparadise
if (enableEmuparadise && prioritizeEmuparadise) {
collection.name = "Emuparadise";
collection.url = "https://www.emuparadise.me/roms-isos-games.php"
promise = searchEmuparadise();
} else {
// resolve the promise so the function don't stop working
promise = Promise.resolve()
}
// Search through Myrient
promise.then(() => {
if (results.length == 0) {
if (console == RAConsole.ARCADE) {
collection.name = "FB Neo Nightly";
collection.url = "https://archive.org/download/2020_01_06_fbn";
return searchArcade();
}
if (myrientCollectionDict[console]) {
const entry = myrientCollectionDict[console];
collection.name = entry.name;
collection.url = entry.urls[0];
// GM_log(collection)
const urls = Array.isArray(entry.urls) ? entry.urls : [entry.urls];
return chainSearchMyrient(urls)
} else {
collection.name = "No-Intro 2016"
collection.url = "https://archive.org/download/No-Intro-Collection_2016-01-03_Fixed"
return searchNoIntro2016();
}
// exit if already has results
} else return;
})
.then(() => {
if (enableEmuparadise && results.length == 0) {
collection.name = "Emuparadise";
collection.url = "https://www.emuparadise.me/roms-isos-games.php"
return searchEmuparadise();
}
})
.then(() => {
if (console == RAConsole.PSP)
return searchArchiveDlc("https://archive.org/download/PSP-DLC/%5BNo-Intro%5D%20PSP%20DLC/")
})
.then(() => {
// GM_log(results);
if (results.length > 0) createDownloads()
if (resultsDlcs.length > 0) createDlcs()
})
} else {
// divRoms.append("<b>Searching roms for this system not supported.</b>");
GM_log("Searching roms for this system not supported.")
}
}
// =========================================
// Create Content to the Page
// =========================================
function createDownloads() {
divRoms.append("<h3>ROMs</h3>");
// divRoms.append(`<b>Found ${results.length} related result(s)`)
divRoms.append(``);
for (var i = 0; i < results.length; i++) {
// GM_log("pow: " + results[i].url)
let dlLink = (results[i].url).replace(/ /g, "%20");
// GM_log("plim: " + dlLink)
divRoms.append("<a class='dl-links' href=" + dlLink + ">" + removeExt(results[i].name) + "</a>");
}
// GM_log(collection.name)
// GM_log(collection.url)
if (collection.url != "") divRoms.append(`<div style="margin-top:1em;">From <a href="${collection.url}">${collection.name}</a></div>`);
$(".dl-links").css("display", "block");
}
function createDlcs() {
divRoms.append(`<h3 style="margin-top: 1em;">DLCs</h3>`);
//divRoms.append(`<b>Found ${resultsDlcs.length} related result(s)`)
divRoms.append(``);
for (var i = 0; i < resultsDlcs.length; i++) {
let dlLink = (resultsDlcs[i].url).replace(/ /g, "%20");
divRoms.append("<a class='dl-links' href=" + dlLink + ">" + removeExt(resultsDlcs[i].name) + "</a>");
}
if (collection.url != "") divRoms.append(`<div style="margin-top:1em;">From <a href=https://archive.org/download/PSP-DLC/%5BNo-Intro%5D%20PSP%20DLC>PSP-DLC (No-Intro)</a></div>`);
$(".dl-links").css("display", "block");
}
function createSpeedrun() {
divSpeedruncom.append("<h3>World Records</h3>");
// divSpeedruncom.append(`<a href=${srGamelink}>
// <img style="display: block; width: 100%; object-fit: cover; margin: 1em 0em 1em 0em"
// src=${srLogo}></img>
// </a>`)
// GM_log(srRuns)
// GM_log(srRuns.length)
if (srRuns.length > 0) {
srRuns.forEach((runsData) => {
// GM_log(runsData.link)
divSpeedruncom.append(`<div><a href=${runsData.link}>${runsData.category}:</a> ${runsData.time} by ${runsData.runner}</div>`)
});
} else {
divSpeedruncom.append("<div>Couldn't find this game on Speedrun.com</div>")
}
}
function createVideo() {
if (srVideoUrl != "")
GM_log("Creating video with URL: " + srVideoUrl)
$("#achievement").children().eq(3)
.after($(`<iframe style="display: block; width: 100%; height:315px; padding-bottom: 1em"
src="${srVideoUrl}"
allowfullscreen="allowfullscreen"
autoplay="false">
</iframe>`));
}
function getSrConsoleId(consoleName) {
if (consoleName == RAConsole.ATARI2600) {
return SRConsole.ATARI2600;
} else if (consoleName == RAConsole.ATARI7800) {
return SRConsole.ATARI7800;
} else if (consoleName == RAConsole.APPLEII) {
return SRConsole.APPLEII;
} else if (consoleName == RAConsole.ARCADE) {
return SRConsole.ARCADE;
} else if (consoleName == RAConsole.COLECO) {
return SRConsole.COLECOVISION;
} else if (consoleName == RAConsole.DREAMCAST) {
return SRConsole.DREAMCAST;
} else if (consoleName == RAConsole.GAMEBOY) {
return SRConsole.GAMEBOY;
} else if (consoleName == RAConsole.GAMEBOYADVANCE) {
return SRConsole.GAMEBOYADVANCE;
} else if (consoleName == RAConsole.GAMEBOYCOLOR) {
return SRConsole.GAMEBOYCOLOR;
} else if (consoleName == RAConsole.MEGADRIVE) {
return SRConsole.MEGADRIVE;
} else if (consoleName == RAConsole.GAMEGEAR) {
return SRConsole.GAMEGEAR;
} else if (consoleName == RAConsole.NINTENDO64) {
return SRConsole.NINTENDO64;
} else if (consoleName == RAConsole.SATURN) {
return SRConsole.SEGASATURN;
} else if (consoleName == RAConsole.MASTERSYSTEM) {
return SRConsole.MASTERSYSTEM;
} else if (consoleName == RAConsole.NINTENDODS) {
return SRConsole.NINTENDODS;
} else if (consoleName == RAConsole.NEC8800) {
return SRConsole.NEC8800;
} else if (consoleName == RAConsole.NEOGEOPOCKET) {
return SRConsole.NEOGEOPOCKETCOLOR;
} else if (consoleName == RAConsole.NES) {
return SRConsole.NES;
} else if (consoleName == RAConsole.P3DO) {
return SRConsole.PANASONIC3D0;
} else if (consoleName == RAConsole.PCENGINE) {
return SRConsole.PCENGINE;
} else if (consoleName == RAConsole.POKEMINI) {
return SRConsole.POKÉMONMINI;
} else if (consoleName == RAConsole.PS1) {
return SRConsole.PS1;
} else if (consoleName == RAConsole.PSP) {
return SRConsole.PLAYSTATIONPORTABLE
} else if (consoleName == RAConsole.SEGA32X) {
return SRConsole.SEGA32X;
} else if (consoleName == RAConsole.SEGACD) {
return SRConsole.SEGACD;
} else if (consoleName == RAConsole.SG1000) {
return SRConsole.MASTERSYSTEM;
} else if (consoleName == RAConsole.SNES) {
return SRConsole.SNES;
} else if (consoleName == RAConsole.VIRTUALBOY) {
return SRConsole.VIRTUALBOY;
} else return "";
}
function getSpeedruns(gameName) {
var consoleId = getSrConsoleId(console);
var srSearchUrl = encodeURI(srRoot + "games?name=" + gameName + "&platform=" + consoleId)
// Games
// GM_log(srSearchUrl)
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: "GET",
url: srSearchUrl,
onload: function (gamesResponse) {
let gamesData = JSON.parse(gamesResponse.response).data
// GM_log("Games: " + gamesData)
if (gamesData.length > 0) {
srGamelink = gamesData[0].weblink;
srGameId = gamesData[0].id;
// srLogo = gamesData[0].assets.logo.uri; don't work as of now, possibly due to API changes on Speedrun.com
resolve(gamesData[0].links[3].uri);
} else {
throw `Couldn't find this game on Speedrun.com (${srSearchUrl}).`;
}
}
})
})
.then((link) => {
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: "GET",
url: link,
onload: function (response) {
let categoriesData = JSON.parse(response.response).data
resolve(categoriesData)
}
})
})
}, err => {
throw (err)
})
.then((categories) => {
// GM_log("Categories: " + categories)
let totalRuns = 0;
return Promise.all(categories.map(category => {
// Runs
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: "GET",
url: srRoot + `runs?game=${srGameId}&category=${category.id}&status=verified`,
onload: function (runsResponse) {
let runsData = JSON.parse(runsResponse.response).data[0];
if (runsData != undefined && runsData.status.status != "rejected") {
// Pick a eligible speedrun video and use it as the video showcase on the page
// GM_log(runsData.videos)
if (srVideoUrl == "" && runsData.videos)
srVideoUrl = toEmbedUrl(runsData.videos.links[0].uri);
// GM_log(isVideoUrl(runsData.videos.links[0].uri))
// if (isVideoUrl(runsData.videos.links[0].uri))
totalRuns++;
}
resolve(runsData)
}
})
})
.then((runsData) => {
if (runsData == undefined) return false;
// TODO: Resolve useless request if user is a guest.
let isGuest = runsData.players[0].rel == "guest" ? true : false;
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: "GET",
url: srRoot + "users/" + runsData.players[0].id,
onload: function (userRes) {
userData = JSON.parse(userRes.response).data
srRuns.push({
category: category.name,
time: parseIso8601(runsData.times.primary),
runner: isGuest ? runsData.players[0].name : userData.names.international,
link: runsData.videos ? runsData.videos.links[0].uri : ""
})
// GM_log(srRuns.length)
// GM_log(totalRuns)
resolve(true)
}
})
})
})
}))
.then(() => {
// GM_log("Last step from promises")
// GM_log(srRuns)
if (enableSpeedrun) createSpeedrun();
if (enableGameplayVideo) createVideo();
})
})
}
// =========================================
// Archives.org (Arcade) Function
// =========================================
function searchArcade() {
var mainDir = "//archive.org/download/2020_01_06_fbn/roms/arcade.zip/arcade%2F";
var datDir = "https://raw.githubusercontent.com/libretro/FBNeo/master/dats/FinalBurn%20Neo%20(ClrMame%20Pro%20XML%2C%20Arcade%20only).dat";
return new Promise((resolve, reject) => {
// Find content in .dat file from FB Neo repo.
GM_xmlhttpRequest({
method: "GET",
url: datDir,
onload: function (response) {
// GM_log(response);
var xmlDoc = $.parseXML(response.responseText);
// Refined search
$(xmlDoc).find("game").each(function (index) {
let name = $(this).find("description").text();
if (tag == "" && name.toLowerCase().includes("hack")) return;
if (tag == "Hack" && !name.toLowerCase().includes("hack")) return;
if (refinedCompare(name, game)) {
results.push({
name: name,
url: mainDir + $(this).attr('name') + ".zip"
});
}
})
// Normal search
if (results.length == 0) {
$(xmlDoc).find("game").each(function (index) {
let name = $(this).find("description").text();
if (tag == "" && name.toLowerCase().includes("hack")) return;
if (tag == "Hack" && !name.toLowerCase().includes("hack")) return;
if (compare(name, game)) {
results.push({
name: name,
url: mainDir + $(this).attr('name') + ".zip"
});
}
})
}
resolve(true);
}
})
});
}
// =========================================
// Myrient Function
// =========================================
function chainSearchMyrient(urls) {
let promise = searchMyrient(urls[0]);
for (let i = 1; i < urls.length; i++) {
promise = promise.then(() => {
if (results.length === 0) {
return searchMyrient(urls[i]);
}
});
}
return promise;
}
// Almost the same as Archive.org, lol
function searchMyrient(mainDir) {
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: "GET",
url: mainDir,
onload: function (response) {
// GM_log(response.responseText);
// Refined search
$(response.responseText).find(`td`).children(":first-child").each(function (index) {
let title = /([^\/]+)\/?$/g.exec($(this).text())[1];
// GM_log(title)
// GM_log($(this).attr('href'))
if (refinedCompare(title, game)) {
// Check if the mainDir link doesn't end with /
let fullUrl = mainDir.endsWith("/") ?
`${mainDir}${$(this).attr('href')}` : `${mainDir}/${$(this).attr('href')}`
// GM_log(mainDir.endsWith("/"))
results.push({
name: title,
url: fullUrl
});
}
});
// Normal search
if (results.length == 0) {
$(response.responseText).find(`td`).children(":first-child").each(function (index) {
let title = /([^\/]+)\/?$/g.exec($(this).text())[1];
if (compare(title, game)) {
// Check if the mainDir link doesn't end with /
let fullUrl = mainDir.endsWith("/") ?
`${mainDir}${$(this).attr('href')}` : `${mainDir}/${$(this).attr('href')}`
// GM_log(mainDir.endsWith("/"))
results.push({
name: title,
url: fullUrl
});
}
});
}
return resolve(true);
}
})
});
}
// =========================================
// Archives.org (No Intro 2016) Function
// =========================================
function searchNoIntro2016() {
var mainDir = "https://archive.org/download/No-Intro-Collection_2016-01-03_Fixed/";
var consoleDir = "";
var secondaryConsoleDir = "";
if (console == RAConsole.SNES) {
consoleDir = "Nintendo - Super Nintendo Entertainment System";
}
if (console == RAConsole.NES) {
consoleDir = "Nintendo - Nintendo Entertainment System";
}
if (console == RAConsole.GAMEBOY) {
consoleDir = "Nintendo - Game Boy";
}
if (console == RAConsole.GAMEBOYCOLOR) {
consoleDir = "Nintendo - Game Boy Color";
}
if (console == RAConsole.GAMEBOYADVANCE) {
consoleDir = "Nintendo - Game Boy Advance";
}
if (console == RAConsole.NINTENDO64) {
consoleDir = "Nintendo - Nintendo 64";
}
if (console == RAConsole.ATARI7800) {
consoleDir = "Atari - 7800";
}
if (console == RAConsole.PCENGINE) {
consoleDir = "NEC - PC Engine - TurboGrafx 16";
}
if (console == RAConsole.MEGADRIVE) {
consoleDir = "Sega - Mega Drive - Genesis";
}
if (console == RAConsole.MASTERSYSTEM) {
consoleDir = "Sega - Master System - Mark III";
}
if (console == RAConsole.GAMEGEAR) {
consoleDir = "Sega - Game Gear";
}
if (console == RAConsole.NEOGEOPOCKET) {
consoleDir = "SNK - Neo Geo Pocket";
secondaryConsoleDir = "SNK - Neo Geo Pocket Color";
}
if (console == RAConsole.POKEMINI) {
consoleDir = "Nintendo - Pokemon Mini";
}
if (console == RAConsole.VIRTUALBOY) {
consoleDir = "Nintendo - Virtual Boy.zip";
}
if (console == RAConsole.SG1000) {
consoleDir = "Sega - SG-1000";
}
if (console == RAConsole.COLECO) {
consoleDir = "Coleco - ColecoVision";
}
if (console == RAConsole.MSX) {
consoleDir = "Microsoft - MSX";
secondaryConsoleDir = "Microsoft - MSX 2";
}
if (console == RAConsole.WONDERSWAN) {
consoleDir = "Bandai - WonderSwan Color";
secondaryConsoleDir = "Bandai - WonderSwan Color"
}
if (console == RAConsole.VECTREX) {
consoleDir = "GCE - Vectrex";
}
consoleDir = consoleDir.replace(/ /g, "%20").concat(".zip/");
secondaryConsoleDir = secondaryConsoleDir.replace(/ /g, "%20").concat(".zip/");
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: "GET",
url: mainDir + consoleDir,
onload: function (response) {
// GM_log(response);
// Refined search
$(response.responseText).find(`td`).children(":first-child").each(function (index) {
if (refinedCompare($(this).text(), game)) {
results.push({
name: $(this).text(),
url: $(this).attr('href')
});
}
});
// Normal search
if (results.length == 0) {
$(response.responseText).find(`td`).children(":first-child").each(function (index) {
if (compare($(this).text(), game)) {
results.push({
name: $(this).text(),
url: $(this).attr('href')
});
}
});
}
resolve(true);
}
})
})
.then(() => {
if (secondaryConsoleDir != "") {
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: "GET",
url: mainDir + secondaryConsoleDir,
onload: function (response) {
// GM_log(response);
// Refined search
$(response.responseText).find(`td`).children(":first-child").each(function (index) {
if (refinedCompare($(this).text(), game)) {
results.push({
name: $(this).text(),
url: $(this).attr('href')
});
}
});
// Normal search
if (results.length == 0) {
$(response.responseText).find(`td`).children(":first-child").each(function (index) {
if (compare($(this).text(), game)) {
results.push({
name: $(this).text(),
url: $(this).attr('href')
});
}
});
}
resolve(true);
}
})
})
}
})
}
// =========================================
// Archives.org (Generic) Function
// =========================================
function searchArchive(mainDir) {
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: "GET",
url: mainDir,
onload: function (response) {
// GM_log(response.responseText);
// Refined search
$(response.responseText).find(`td`).children(":first-child").each(function (index) {
let title = /([^\/]+)\/?$/g.exec($(this).text())[1];
// Check in case link is already the full url
let fullUrl = $(this).attr('href').startsWith("//archive.org/download/") ?
$(this).attr('href') : `${mainDir}/${$(this).attr('href')}`
// GM_log($(this).attr('href'))
if (refinedCompare(title, game)) {
results.push({
name: title,
url: fullUrl
});
}
});
// Normal search
if (results.length == 0) {
$(response.responseText).find(`td`).children(":first-child").each(function (index) {
let title = /([^\/]+)\/?$/g.exec($(this).text())[1];
let fullUrl = $(this).attr('href').startsWith("//archive.org/download/") ?
$(this).attr('href') : `${mainDir}/${$(this).attr('href')}`
// GM_log($(this).attr('href'))
if (compare(title, game)) {
results.push({
name: title,
url: fullUrl
});
}
});
}
return resolve(true);
}
})
});
}
// =========================================
// Archives.org (DLC) Function
// =========================================
function searchArchiveDlc(mainDir) {
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: "GET",
url: mainDir,
onload: function (response) {
// GM_log(response);
// Refined search
$(response.responseText).find(`td`).children(":first-child").each(function (index) {
let title = /([^\/]+)\/?$/g.exec($(this).text())[1];
// Check in case link is already the full url
let fullUrl = $(this).attr('href').startsWith("//archive.org/download/") ?
$(this).attr('href') : `${mainDir}/${$(this).attr('href')}`
// GM_log($(this).attr('href'))
if (refinedCompare(title, game)) {
resultsDlcs.push({
name: title,
url: fullUrl
});
}
});
// Normal search
if (resultsDlcs.length == 0) {
$(response.responseText).find(`td`).children(":first-child").each(function (index) {
let title = /([^\/]+)\/?$/g.exec($(this).text())[1];
let fullUrl = $(this).attr('href').startsWith("//archive.org/download/") ?
$(this).attr('href') : `${mainDir}/${$(this).attr('href')}`
// GM_log($(this).attr('href'))
if (compare(title, game)) {
resultsDlcs.push({
name: title,
url: fullUrl
});
}
});
}
return resolve(true);
}
})
});
}
// =========================================
// Emuparadise Function
// =========================================
function searchEmuparadise() {
var mainDir = "https://www.emuparadise.me/";
var consoleUrl;
if (console == RAConsole.SNES) {
consoleUrl = "Super_Nintendo_Entertainment_System_(SNES)_ROMs/List-All-Titles/5";
}
if (console == RAConsole.NES) {
consoleUrl = "Nintendo_Entertainment_System_ROMs/List-All-Titles/13";
}
if (console == RAConsole.GAMEBOY) {
consoleUrl = "Nintendo_Game_Boy_ROMs/List-All-Titles/12";
}
if (console == RAConsole.GAMEBOYCOLOR) {
consoleUrl = "Nintendo_Game_Boy_Color_ROMs/List-All-Titles/11";
}
if (console == RAConsole.GAMEBOYADVANCE) {
consoleUrl = "Nintendo_Gameboy_Advance_ROMs/List-All-Titles/31";
}
if (console == RAConsole.NINTENDO64) {
consoleUrl = "Nintendo_64_ROMs/List-All-Titles/9";
}
if (console == RAConsole.GAMECUBE) {
consoleUrl = "Nintendo_Gamecube_ISOs/List-All-Titles/42"
}
if (console == RAConsole.NINTENDODS) {
consoleUrl = "Nintendo_DS_ROMs/List-All-Titles/32";
}
if (console == RAConsole.MEGADRIVE) {
consoleUrl = "Sega_Genesis_-_Sega_Megadrive_ROMs/List-All-Titles/6";
}
if (console == RAConsole.MASTERSYSTEM) {
consoleUrl = "Sega_Master_System_ROMs/List-All-Titles/15";
}
if (console == RAConsole.SEGA32X) {
consoleUrl = "Sega_32X_ROMs/61";
}
if (console == RAConsole.SATURN) {
consoleUrl = "Sega_Saturn_ISOs/List-All-Titles/3"
}
if (console == RAConsole.SEGACD) {
consoleUrl = "Sega_CD_ISOs/List-All-Titles/10";
}
if (console == RAConsole.GAMEGEAR) {
consoleUrl = "Sega_Game_Gear_ROMs/List-All-Titles/14";
}
if (console == RAConsole.NEOGEOPOCKET) {
consoleUrl = "Neo_Geo_Pocket_-_Neo_Geo_Pocket_Color_(NGPx)_ROMs/38";
}
if (console == RAConsole.ATARI2600) {
consoleUrl = "Atari_2600_ROMs/List-All-Titles/49"
}
if (console == RAConsole.ATARI7800) {
consoleUrl = "Atari_7800_ROMs/47"
}
if (console == RAConsole.PCENGINE) {
consoleUrl = "PC_Engine_-_TurboGrafx16_ROMs/List-All-Titles/16";
}
if (console == RAConsole.APPLEII) {
consoleUrl = "Apple_][_ROMs/List-All-Titles/24";
}
if (console == RAConsole.PS1) {
consoleUrl = "Sony_Playstation_ISOs/List-All-Titles/2";
}
if (console == RAConsole.PS2) {
consoleUrl = "Sony_Playstation_2_ISOs/List-All-Titles/41";
}
if (console == RAConsole.PSP) {
consoleUrl = "PSP_ISOs/List-All-Titles/44";
}
if (console == RAConsole.P3DO) {
consoleUrl = "Panasonic_3DO_(3DO_Interactive_Multiplayer)_ISOs/List-All-Titles/20";
}
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: "GET",
url: mainDir + consoleUrl,
onload: function (response) {
// GM_log(response);
// Refined search
$(response.responseText).find(`.index.gamelist`).each(function (index) {
let epGameId = /([^\/]+)\/?$/g.exec($(this).attr('href'))[0];
// GM_log($(this).text())
if (refinedCompare($(this).text(), game)) {
results.push({
name: $(this).text(),
url: `https://www.emuparadise.me/roms/get-download.php?gid=${epGameId}&test=true`
});
}
});
// Normal search
if (results.length == 0) {
$(response.responseText).find(`.index.gamelist`).each(function (index) {
let epGameId = /([^\/]+)\/?$/g.exec($(this).attr('href'))[0];
// GM_log($(this).text())
if (compare($(this).text(), game)) {
results.push({
name: $(this).text(),
url: `https://www.emuparadise.me/roms/get-download.php?gid=${epGameId}&test=true`
});
}
});
}
return resolve(true);
}
})
});
}
// =========================================
// Utility Functions
// =========================================
async function trySearchUrls(urls) {
for (let url of urls) {
const result = await searchArchive(url);
if (results.length > 0) return result;
}
return null;
}
function refinedCompare(a, b) {
let str1 = simplify_title(a);
let str2 = simplify_title(b);
// GM_log("*Str 1: " + str1)
// GM_log("*Str 2: " + str2)
// GM_log(str1 == str2)
if (str1 == str2)
return true;
else
return false;
}
function compare(a, b) {
// GM_log(a)
let str1 = simplify_title(a);
let str2 = simplify_title(b);
// GM_log("Str 1: " + str1)
// GM_log("Str 2: " + str2)
// GM_log(str1.includes(str2))
if (str1.includes(str2))
return true;
else
return false;
}
// Remove unnecessary characters and region headering
function simplify_title(str) {
// Dreamcast TOSEC set puts versioning into the filename
if (console == RAConsole.DREAMCAST)
str = str.replace(/v[0-9].[0-9]{3}/gs, "")
return str
.replace(/\.(zip|7z)$/,"")
.replace(/^The /g, '')
.replace(", The", '')
.replace(/'s/gs, '')
.replace('&', 'and')
.replace(/:|-| |\.|!|\?|\/|'/gs, '')
.replace(/(\r\n|\n|\r)/gs, "") // remove line breaks
.split('|')[0]
.replace(',', "")
// remove headers (old)
// .replace(/\([\w\s]+\)/gs, "")
// .replace(/\[[\w\s]+\]/gs, "")
// remove headers (everything inside parenthesis)
.replace(/\(.+\)/gs, "")
.replace(/\[.+\]/gs, "")
.toLowerCase()
}
function removeExt(str) {
return str.replace(/\.(zip|7z|chd)$/,"");
}
function parseIso8601(time) {
var parsed = "";
let regex = /(-)?P(?:([.,\d]+)Y)?(?:([.,\d]+)M)?(?:([.,\d]+)W)?(?:([.,\d]+)D)?T(?:([.,\d]+)H)?(?:([.,\d]+)M)?(?:([.,\d]+)S)?/;
let groups = regex.exec(time);
if (groups[6] != undefined) parsed = parsed.concat(`${groups[6]}h `)
if (groups[7] != undefined) parsed = parsed.concat(`${groups[7]}m `)
if (groups[8] != undefined) parsed = parsed.concat(`${groups[8]}s `)
return parsed;
}
function isVideoUrl(url) {
return (url.includes("www.youtu") || url.includes("www.twitch.tv"))
}
function toEmbedUrl(url) {
if (url.includes("twitch") || url.includes("youtu")) {
// GM_log(url);
// https://regex101.com/r/jmV6qH/1
var regexYoutube = /(?:https?:\/{2})?(?:w{3}\.)?youtu(?:be)?\.(?:com|be)(?:\/watch\?v=|\/)?([^\s&]+)/;
// https://regex101.com/r/0RofWZ/1
var regexTwitch = /(?:https?:\/{2})?www\.twitch\.tv\/(:?[\S]+\/)?([\]?)?\/([\d]+)/;
if (url.match(regexYoutube) != undefined) {
return "https://www.youtube.com/embed/" + url.match(regexYoutube)[1];
} else if (url.match(regexTwitch) != undefined) {
return "https://player.twitch.tv/?video=" + url.match(regexTwitch)[2] + "&parent=retroachievements.org&autoplay=false";
}
}
return "";
}
}
})();