-
Star
(125)
You must be signed in to star a gist -
Fork
(32)
You must be signed in to fork a gist
-
-
Save Eptun/3fdcc84552e75e452731cd4621c535e9 to your computer and use it in GitHub Desktop.
| // ==UserScript== | |
| // @name EmuParadise Download Workaround - 1.1.1 | |
| // @version 1.1.2 | |
| // @description Replaces the download button link with a working one | |
| // @author Eptun | |
| // @match https://www.emuparadise.me/*/*/* | |
| // @require http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js | |
| // @grant none | |
| // ==/UserScript== | |
| (function() { | |
| 'use strict'; | |
| var id = ((document.URL).split("/"))[5]; | |
| $(".download-link").prepend(`<a target="_blank" href="/roms/get-download.php?gid=`+id+`&test=true" title="Download using the workaround script">Download using the workaround script</a><br><br>`); | |
| })(); |
Eptun
@Eptun I loved your workaround! As a recomendation from a Web Developer.
- Use the "location" object from the global window object. This will allow you to build the full URL path. location.origin should give to you the "https://www.emuparadaise.com" text.
- Then append the id variable at the end of this new generated text and save it to a new variable to use it in the anchor a HTML element.
- Finally add the anchor the attribute of download to force the Save as behaviour as @ReclusiveEagle mentioned.
Note: The 3rd step must be manually applied if the user is using Google Chrome. Firefox works with this method automatically.
If anything that I said was difficult I will attach the code for you!
// ==UserScript==
// @name EmuParadise Download Workaround - 1.1.1
// @version 1.1.2
// @description Replaces the download button link with a working one
// @author Eptun
// @match https://www.emuparadise.me/*/*/*
// @require http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js
// @grant none
// ==/UserScript==
(function () {
"use strict";
/** The style class from the download button */
const DOWNLOAD_BUTTON_CLASS = "download-link";
/** The game id from the `emuparadise` servers */
const id = document.URL.substring(document.URL.lastIndexOf("/") + 1);
/** The link to follow when the generated button is clicked */
const href = `${location.origin}/roms/get-download.php?gid=${id}&test=true`;
/** The original download link container */
const DownloadLinkContainer = document.body.querySelector(
`.${DOWNLOAD_BUTTON_CLASS}`
);
/** The original link */
const DownloadLink = DownloadLinkContainer.querySelector("a");
/** The original text in the link */
const text = DownloadLink.innerText;
/** The original link extra text */
const extra = DownloadLinkContainer.innerText.substring(
text.length,
DownloadLinkContainer.innerText.length
);
// Modifies the text in the original link
DownloadLink.innerText = `${text} [Ignore]`;
/** The generated download link */
const WorkaroundLink = document.createElement("a");
WorkaroundLink.target = "_blank";
WorkaroundLink.href = href;
WorkaroundLink.download = text;
WorkaroundLink.title = "The link using the workaround script";
WorkaroundLink.innerText = `${text} [Repaired]`;
/** The new link container */
const WorkaroundLinkContainer = document.createElement("div");
WorkaroundLinkContainer.classList.add(DOWNLOAD_BUTTON_CLASS);
WorkaroundLinkContainer.appendChild(WorkaroundLink);
WorkaroundLinkContainer.append(extra);
// Appends the new generated link before the original link
DownloadLinkContainer.insertAdjacentElement(
"beforebegin",
WorkaroundLinkContainer
);
// Removes the original link
DownloadLinkContainer.remove();
})();User
You don't need to install any add-on!
- Open the
Developers Toolsfrom the browser (ussually clickingF12) - Then find a tab called
consoleand click it. - This tab will open a text field below it, there you should paste only the code then hit enter.
- If done properly the link should be replaced with a version with an extra text
[Repaired]. That link is the one that should be clicked. - If the link is not working is because the browser is blocking it. Try
Firefoxor if you want to use the one that blocked the link, follow the steps from @ReclusiveEagle.
Note This method should be applied just once, if at any step you feel something failed to you, reload the page and start over. Plus this method will only look for the first download link in the page. Those games that contains multple "links", those are just dead ends. Just try this method ignoring those extra "zombie links".
I made the following code improvement using Cursor AI with some improvements for my personal use case that is working in 2026:
Updated fork of this script for how EmuParadise works in 2026. Same core idea (/roms/get-download.php?gid=ID&test=true), expanded for current page layout and CDN.
**What changed from the original (v1.1.2):**
- **No jQuery** — removed `@require`; vanilla JS only.
- **No extra link only** — hooks existing download buttons instead of only prepending one (multi-file games like Dreamcast CDI/GDI still work).
- **One-click from the game page** — ISO sections no longer need the intermediate `…-download` page; token URL is fetched in the background.
- **ISO vs ROM** — ROM sections still use your original `gid + test=true` flow; ISO sections use signed `token`/`isoid` URLs when present.
- **Premium wait removed** — skips the “Your download will start in N seconds” screen on `get-download.php` (`link-placeholder` countdown).
- **Official CDN** — downloads go through `dl*.m***.se` (not old mirror IPs).
- **Broader `@match`** — `*://www.emuparadise.me/*` and mobile subdomain; `@run-at document-start` for timer bypass.
**Still the same as your script for:** N Roms. — `get-download.php?gid={id from URL}&test=true`.
Tested: DC, Saturn, N ROM sections with Tampermonkey.
**v1.9.0** — community fork based on Eptun 1.1.2 + current EP HTML/page structure (2026).
// ==UserScript==
// @name EmuParadise Download Workaround
// @version 1.9.0
// @description 1-click download: ISO token flow + classic ROM (gid & test=true)
// @author Eptun, infval, community
// @match *://www.emuparadise.me/*
// @match *://m.emuparadise.me/*
// @grant none
// @run-at document-start
// ==/UserScript==
(function () {
"use strict";
const IS_GET_DOWNLOAD = /\/roms\/get-download\.php/i.test(location.pathname);
function isIntermediatePagePath(path = location.pathname) {
return /\/\d+-download(?:-\d+)?$/i.test(path.replace(/\/$/, ""));
}
function isGameDownloadHref(href) {
return /\/\d+-download(?:-\d+)?(?:\?|#|$)/i.test(href || "");
}
function isClassicRomSection() {
return /_ROMs(?:\/|$)/i.test(location.pathname);
}
const IS_INTERMEDIATE = isIntermediatePagePath();
try {
window.is_premium = true;
} catch (_) {
/* ignore */
}
function patchCountdownTimers() {
if (!IS_GET_DOWNLOAD) return;
const shrink = (delay) =>
typeof delay === "number" && delay >= 200 && delay <= 120000 ? 0 : delay;
const origTimeout = window.setTimeout;
const origInterval = window.setInterval;
window.setTimeout = function (fn, delay, ...args) {
return origTimeout.call(window, fn, shrink(delay), ...args);
};
window.setInterval = function (fn, delay, ...args) {
return origInterval.call(window, fn, shrink(delay), ...args);
};
}
patchCountdownTimers();
function ensureDownloadCookies() {
const opts = "path=/; domain=.emuparadise.me; SameSite=Lax; max-age=86400";
if (!document.cookie.includes("refexception=1")) {
document.cookie = `refexception=1; ${opts}`;
}
if (!document.cookie.includes("epdprefs=ephttpdownload")) {
document.cookie = `epdprefs=ephttpdownload; ${opts}`;
}
}
function absUrl(href) {
if (!href) return "";
if (/^https?:\/\//i.test(href)) return href;
return location.origin + href;
}
function gameIdFromPage() {
if (typeof window.gid !== "undefined" && window.gid) {
return String(window.gid);
}
const parts = location.pathname.replace(/\/$/, "").split("/");
const last = parts[parts.length - 1];
if (/^\d+$/.test(last)) return last;
return parts[5] || "";
}
function classicGetDownloadUrl(gid) {
return absUrl(
`/roms/get-download.php?gid=${encodeURIComponent(gid)}&test=true`
);
}
function clearAllTimers() {
for (let i = 1; i < 50000; i++) {
clearTimeout(i);
clearInterval(i);
}
}
function findMprdUrl(root) {
const scope = root || document;
const selectors = [
'a.link-placeholder[href*="mprd.se"]',
'a[href*="dl"][href*="mprd.se"]',
'a[href*="mprd.se/"]',
"#download-link[href*='mprd.se']",
];
for (const sel of selectors) {
const el = scope.querySelector(sel);
if (el?.href && !el.href.includes("get-new-premium")) return el.href;
}
const parts = [];
if (scope.documentElement?.innerHTML) parts.push(scope.documentElement.innerHTML);
for (const s of scope.querySelectorAll?.("script") || []) {
if (s.textContent) parts.push(s.textContent);
}
const m = parts.join("\n").match(/https?:\/\/dl\d*\.mprd\.se\/[^"'\\\s<>)]+/i);
return m ? m[0] : null;
}
function redirectToMprd(url) {
if (!url || !/mprd\.se/i.test(url)) return false;
location.replace(url);
return true;
}
function triggerFileDownload(url) {
const a = document.createElement("a");
a.href = url;
a.rel = "noreferrer";
a.style.display = "none";
document.body.appendChild(a);
a.click();
a.remove();
}
function htmlLooksUnavailable(html) {
return /unavailable|removed for now|unfor?tunately this file|no longer offering/i.test(
html
);
}
function parseGetDownloadUrl(html) {
const unescaped = html.replace(/&/g, "&");
const byId =
unescaped.match(
/id=["']download-link["'][^>]*href=["']([^"']+)["']/i
) ||
unescaped.match(
/href=["'](\/roms\/get-download\.php[^"']+)["'][^>]*id=["']download-link["']/i
);
if (byId?.[1]) return absUrl(byId[1].replace(/&/g, "&"));
const loose = unescaped.match(/\/roms\/get-download\.php\?[^"'\\s<>]+/i);
return loose ? absUrl(loose[0].replace(/&/g, "&")) : null;
}
async function fetchGetDownloadUrl(intermediateHref) {
const res = await fetch(absUrl(intermediateHref), {
credentials: "include",
});
if (!res.ok) throw new Error(`Intermediate page HTTP ${res.status}`);
const html = await res.text();
if (htmlLooksUnavailable(html)) return null;
return parseGetDownloadUrl(html);
}
async function tryFetchMprdFromGetDownload(getDownloadUrl) {
try {
const res = await fetch(getDownloadUrl, {
credentials: "include",
redirect: "follow",
});
if (res.url && /mprd\.se/i.test(res.url)) {
triggerFileDownload(res.url);
return true;
}
const body = await res.text();
if (htmlLooksUnavailable(body)) return false;
const m = body.match(/https?:\/\/dl\d*\.mprd\.se\/[^"'\\\s<>)]+/i);
if (m) {
triggerFileDownload(m[0]);
return true;
}
} catch (_) {
/* fall through */
}
return false;
}
function downloadViaHiddenIframe(getDownloadUrl) {
const iframe = document.createElement("iframe");
iframe.style.cssText =
"position:fixed;width:0;height:0;border:0;opacity:0;pointer-events:none";
iframe.src = getDownloadUrl;
document.documentElement.appendChild(iframe);
setTimeout(() => iframe.remove(), 120000);
}
async function startGetDownload(getDownloadUrl, label) {
ensureDownloadCookies();
epStatus(`Preparing ${label || "download"}…`);
if (await tryFetchMprdFromGetDownload(getDownloadUrl)) {
epStatus("Download started.", false, 3000);
return;
}
downloadViaHiddenIframe(getDownloadUrl);
epStatus("Download started.", false, 3000);
}
async function directDownloadFromGamePage(intermediateHref, label) {
let getUrl = null;
try {
getUrl = await fetchGetDownloadUrl(intermediateHref);
} catch (_) {
/* try classic fallback */
}
if (!getUrl) {
const gid = gameIdFromPage();
if (gid && /^\d+$/.test(gid)) {
getUrl = classicGetDownloadUrl(gid);
}
}
if (!getUrl) {
epStatus("Could not resolve download URL — opening download page.", true);
location.assign(absUrl(intermediateHref));
return;
}
await startGetDownload(getUrl, label);
}
async function directDownloadClassic(label) {
const gid = gameIdFromPage();
if (!gid || !/^\d+$/.test(gid)) {
epStatus("Could not read game ID from this page.", true);
return;
}
await startGetDownload(classicGetDownloadUrl(gid), label);
}
let statusEl = null;
function epStatus(msg, isError, hideMs) {
const container = document.querySelector(".download-link");
if (!container) return;
if (!statusEl) {
statusEl = document.createElement("p");
statusEl.id = "ep-dl-status";
statusEl.style.cssText =
"font-size:12px;color:#fa0;margin:8px 0;line-height:1.4;";
container.prepend(statusEl);
}
statusEl.style.color = isError ? "#f88" : "#fa0";
statusEl.textContent = msg;
if (hideMs) {
setTimeout(() => {
if (statusEl) statusEl.textContent = "";
}, hideMs);
}
}
function isLikelyGameDownloadAnchor(a) {
const href = a.getAttribute("href") || "";
const title = a.getAttribute("title") || "";
const text = (a.textContent || "").trim();
if (/get-new-premium|\/Emulators|#download/i.test(href)) return false;
if (/^Download\s/i.test(title) || /^Download\s/i.test(text)) return true;
if (/get-download\.php/i.test(href)) return true;
return false;
}
function hookDownloadClick(a, handler) {
if (a.dataset.epDirect) return false;
a.dataset.epDirect = "1";
a.addEventListener(
"click",
(e) => {
e.preventDefault();
e.stopImmediatePropagation();
handler().catch((err) => {
epStatus(`Failed: ${err.message}`, true);
});
},
true
);
return true;
}
function setupGamePageDirectDownload() {
if (IS_INTERMEDIATE || IS_GET_DOWNLOAD) return;
const container = document.querySelector(".download-link");
if (!container || container.dataset.epDirectSetup) return;
container.dataset.epDirectSetup = "1";
let hooked = 0;
const gid = gameIdFromPage();
container.querySelectorAll("a[href]").forEach((a) => {
const href = a.getAttribute("href") || a.href;
if (isGameDownloadHref(href)) {
if (
hookDownloadClick(a, () => {
const label = (a.textContent || "").trim();
return directDownloadFromGamePage(href, label);
})
) {
hooked++;
}
return;
}
if (isLikelyGameDownloadAnchor(a)) {
if (
hookDownloadClick(a, () => {
const label = (a.textContent || "").trim();
return directDownloadClassic(label);
})
) {
hooked++;
}
}
});
const needsClassicLink =
hooked === 0 ||
isClassicRomSection() ||
htmlLooksUnavailable(container.textContent || "");
if (needsClassicLink && gid && !document.getElementById("ep-classic-download")) {
const wrap = document.createElement("div");
wrap.style.marginBottom = "8px";
const a = document.createElement("a");
a.id = "ep-classic-download";
a.href = classicGetDownloadUrl(gid);
a.textContent = "Download using workaround (1-click)";
a.title = "Classic EP workaround: get-download.php?gid&test=true";
a.style.color = "#a5d414";
a.style.fontSize = "16px";
hookDownloadClick(a, () => directDownloadClassic(a.textContent));
wrap.appendChild(a);
wrap.appendChild(document.createElement("br"));
container.prepend(wrap);
hooked++;
}
if (hooked && !document.getElementById("ep-direct-hint")) {
const hint = document.createElement("p");
hint.id = "ep-direct-hint";
hint.style.cssText =
"font-size:12px;color:#8a8;margin:0 0 8px;line-height:1.4;";
hint.textContent =
"Direct download enabled — click a link to start without leaving this page.";
container.prepend(hint);
}
}
async function tryFetchMprdRedirect(getDownloadUrl) {
try {
const res = await fetch(getDownloadUrl, {
credentials: "include",
redirect: "follow",
});
if (res.url && /mprd\.se/i.test(res.url)) {
location.assign(res.url);
return true;
}
} catch (_) {
/* fall through */
}
return false;
}
function hijackLinkPlaceholder() {
const el = document.querySelector("a.link-placeholder");
if (!el) return false;
clearAllTimers();
const href = el.getAttribute("href") || el.href || "";
if (/mprd\.se/i.test(href) && !href.includes("get-new-premium")) {
return redirectToMprd(el.href);
}
const scraped = findMprdUrl(document);
if (scraped) return redirectToMprd(scraped);
if (!el.dataset.epWatch) {
el.dataset.epWatch = "1";
const obs = new MutationObserver(() => {
clearAllTimers();
const h = el.href || el.getAttribute("href") || "";
if (/mprd\.se/i.test(h)) {
obs.disconnect();
redirectToMprd(h);
return;
}
const u = findMprdUrl(document);
if (u) {
obs.disconnect();
redirectToMprd(u);
}
});
obs.observe(el, { attributes: true, attributeFilter: ["href"] });
obs.observe(document.documentElement, { childList: true, subtree: true });
}
if (/will start in \d+ second/i.test(el.textContent || "")) {
el.textContent = "Starting your download now…";
}
return true;
}
function skipPremiumWaitPage() {
if (!IS_GET_DOWNLOAD) return false;
clearAllTimers();
if (redirectToMprd(findMprdUrl(document))) return true;
if (hijackLinkPlaceholder()) return true;
const meta = document.querySelector('meta[http-equiv="refresh" i]');
if (meta?.content) {
const m = meta.content.match(/url=([^;]+)/i);
if (m?.[1]) {
const u = m[1].trim().replace(/^['"]|['"]$/g, "");
if (/mprd\.se/i.test(u)) return redirectToMprd(u);
}
}
return true;
}
function hidePreparingBanner() {
for (const h of document.querySelectorAll("h2")) {
if (/preparing your download/i.test(h.textContent || "")) {
h.style.display = "none";
}
}
}
function setupInstantDownloadLink() {
if (!IS_INTERMEDIATE) return;
const link = document.getElementById("download-link");
if (!link || link.dataset.epInstant) return;
if (!(link.getAttribute("href") || "").includes("get-download.php")) return;
link.dataset.epInstant = "1";
hidePreparingBanner();
const attach = () => {
const target = document.getElementById("download-link");
if (!target || target.dataset.epHooked) return;
target.dataset.epHooked = "1";
const fresh = target.cloneNode(true);
target.parentNode?.replaceChild(fresh, target);
fresh.addEventListener(
"click",
async (e) => {
e.preventDefault();
e.stopImmediatePropagation();
ensureDownloadCookies();
if (await tryFetchMprdRedirect(fresh.href)) return;
location.assign(fresh.href);
},
true
);
};
if (typeof window.jQuery !== "undefined") {
window.jQuery(attach);
} else {
setTimeout(attach, 300);
}
}
function onReady() {
ensureDownloadCookies();
skipPremiumWaitPage();
hidePreparingBanner();
setupGamePageDirectDownload();
setupInstantDownloadLink();
if (IS_GET_DOWNLOAD) {
hijackLinkPlaceholder();
let n = 0;
const burst = setInterval(() => {
n++;
clearAllTimers();
if (redirectToMprd(findMprdUrl(document)) || hijackLinkPlaceholder()) {
clearInterval(burst);
} else if (n > 30) {
clearInterval(burst);
}
}, 100);
}
}
ensureDownloadCookies();
if (IS_GET_DOWNLOAD) skipPremiumWaitPage();
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", onReady, { once: true });
} else {
onReady();
}
})();
I made the following code improvement using Cursor AI with some improvements for my personal use case that is working in 2026:
Updated fork of this script for how EmuParadise works in 2026. Same core idea (
/roms/get-download.php?gid=ID&test=true), expanded for current page layout and CDN.**What changed from the original (v1.1.2):** - **No jQuery** — removed `@require`; vanilla JS only. - **No extra link only** — hooks existing download buttons instead of only prepending one (multi-file games like Dreamcast CDI/GDI still work). - **One-click from the game page** — ISO sections no longer need the intermediate `…-download` page; token URL is fetched in the background. - **ISO vs ROM** — ROM sections still use your original `gid + test=true` flow; ISO sections use signed `token`/`isoid` URLs when present. - **Premium wait removed** — skips the “Your download will start in N seconds” screen on `get-download.php` (`link-placeholder` countdown). - **Official CDN** — downloads go through `dl*.m***.se` (not old mirror IPs). - **Broader `@match`** — `*://www.emuparadise.me/*` and mobile subdomain; `@run-at document-start` for timer bypass. **Still the same as your script for:** N Roms. — `get-download.php?gid={id from URL}&test=true`. Tested: DC, Saturn, N ROM sections with Tampermonkey. **v1.9.0** — community fork based on Eptun 1.1.2 + current EP HTML/page structure (2026).// ==UserScript== // @name EmuParadise Download Workaround // @version 1.9.0 // @description 1-click download: ISO token flow + classic ROM (gid & test=true) // @author Eptun, infval, community // @match *://www.emuparadise.me/* // @match *://m.emuparadise.me/* // @grant none // @run-at document-start // ==/UserScript== (function () { "use strict"; const IS_GET_DOWNLOAD = /\/roms\/get-download\.php/i.test(location.pathname); function isIntermediatePagePath(path = location.pathname) { return /\/\d+-download(?:-\d+)?$/i.test(path.replace(/\/$/, "")); } function isGameDownloadHref(href) { return /\/\d+-download(?:-\d+)?(?:\?|#|$)/i.test(href || ""); } function isClassicRomSection() { return /_ROMs(?:\/|$)/i.test(location.pathname); } const IS_INTERMEDIATE = isIntermediatePagePath(); try { window.is_premium = true; } catch (_) { /* ignore */ } function patchCountdownTimers() { if (!IS_GET_DOWNLOAD) return; const shrink = (delay) => typeof delay === "number" && delay >= 200 && delay <= 120000 ? 0 : delay; const origTimeout = window.setTimeout; const origInterval = window.setInterval; window.setTimeout = function (fn, delay, ...args) { return origTimeout.call(window, fn, shrink(delay), ...args); }; window.setInterval = function (fn, delay, ...args) { return origInterval.call(window, fn, shrink(delay), ...args); }; } patchCountdownTimers(); function ensureDownloadCookies() { const opts = "path=/; domain=.emuparadise.me; SameSite=Lax; max-age=86400"; if (!document.cookie.includes("refexception=1")) { document.cookie = `refexception=1; ${opts}`; } if (!document.cookie.includes("epdprefs=ephttpdownload")) { document.cookie = `epdprefs=ephttpdownload; ${opts}`; } } function absUrl(href) { if (!href) return ""; if (/^https?:\/\//i.test(href)) return href; return location.origin + href; } function gameIdFromPage() { if (typeof window.gid !== "undefined" && window.gid) { return String(window.gid); } const parts = location.pathname.replace(/\/$/, "").split("/"); const last = parts[parts.length - 1]; if (/^\d+$/.test(last)) return last; return parts[5] || ""; } function classicGetDownloadUrl(gid) { return absUrl( `/roms/get-download.php?gid=${encodeURIComponent(gid)}&test=true` ); } function clearAllTimers() { for (let i = 1; i < 50000; i++) { clearTimeout(i); clearInterval(i); } } function findMprdUrl(root) { const scope = root || document; const selectors = [ 'a.link-placeholder[href*="mprd.se"]', 'a[href*="dl"][href*="mprd.se"]', 'a[href*="mprd.se/"]', "#download-link[href*='mprd.se']", ]; for (const sel of selectors) { const el = scope.querySelector(sel); if (el?.href && !el.href.includes("get-new-premium")) return el.href; } const parts = []; if (scope.documentElement?.innerHTML) parts.push(scope.documentElement.innerHTML); for (const s of scope.querySelectorAll?.("script") || []) { if (s.textContent) parts.push(s.textContent); } const m = parts.join("\n").match(/https?:\/\/dl\d*\.mprd\.se\/[^"'\\\s<>)]+/i); return m ? m[0] : null; } function redirectToMprd(url) { if (!url || !/mprd\.se/i.test(url)) return false; location.replace(url); return true; } function triggerFileDownload(url) { const a = document.createElement("a"); a.href = url; a.rel = "noreferrer"; a.style.display = "none"; document.body.appendChild(a); a.click(); a.remove(); } function htmlLooksUnavailable(html) { return /unavailable|removed for now|unfor?tunately this file|no longer offering/i.test( html ); } function parseGetDownloadUrl(html) { const unescaped = html.replace(/&/g, "&"); const byId = unescaped.match( /id=["']download-link["'][^>]*href=["']([^"']+)["']/i ) || unescaped.match( /href=["'](\/roms\/get-download\.php[^"']+)["'][^>]*id=["']download-link["']/i ); if (byId?.[1]) return absUrl(byId[1].replace(/&/g, "&")); const loose = unescaped.match(/\/roms\/get-download\.php\?[^"'\\s<>]+/i); return loose ? absUrl(loose[0].replace(/&/g, "&")) : null; } async function fetchGetDownloadUrl(intermediateHref) { const res = await fetch(absUrl(intermediateHref), { credentials: "include", }); if (!res.ok) throw new Error(`Intermediate page HTTP ${res.status}`); const html = await res.text(); if (htmlLooksUnavailable(html)) return null; return parseGetDownloadUrl(html); } async function tryFetchMprdFromGetDownload(getDownloadUrl) { try { const res = await fetch(getDownloadUrl, { credentials: "include", redirect: "follow", }); if (res.url && /mprd\.se/i.test(res.url)) { triggerFileDownload(res.url); return true; } const body = await res.text(); if (htmlLooksUnavailable(body)) return false; const m = body.match(/https?:\/\/dl\d*\.mprd\.se\/[^"'\\\s<>)]+/i); if (m) { triggerFileDownload(m[0]); return true; } } catch (_) { /* fall through */ } return false; } function downloadViaHiddenIframe(getDownloadUrl) { const iframe = document.createElement("iframe"); iframe.style.cssText = "position:fixed;width:0;height:0;border:0;opacity:0;pointer-events:none"; iframe.src = getDownloadUrl; document.documentElement.appendChild(iframe); setTimeout(() => iframe.remove(), 120000); } async function startGetDownload(getDownloadUrl, label) { ensureDownloadCookies(); epStatus(`Preparing ${label || "download"}…`); if (await tryFetchMprdFromGetDownload(getDownloadUrl)) { epStatus("Download started.", false, 3000); return; } downloadViaHiddenIframe(getDownloadUrl); epStatus("Download started.", false, 3000); } async function directDownloadFromGamePage(intermediateHref, label) { let getUrl = null; try { getUrl = await fetchGetDownloadUrl(intermediateHref); } catch (_) { /* try classic fallback */ } if (!getUrl) { const gid = gameIdFromPage(); if (gid && /^\d+$/.test(gid)) { getUrl = classicGetDownloadUrl(gid); } } if (!getUrl) { epStatus("Could not resolve download URL — opening download page.", true); location.assign(absUrl(intermediateHref)); return; } await startGetDownload(getUrl, label); } async function directDownloadClassic(label) { const gid = gameIdFromPage(); if (!gid || !/^\d+$/.test(gid)) { epStatus("Could not read game ID from this page.", true); return; } await startGetDownload(classicGetDownloadUrl(gid), label); } let statusEl = null; function epStatus(msg, isError, hideMs) { const container = document.querySelector(".download-link"); if (!container) return; if (!statusEl) { statusEl = document.createElement("p"); statusEl.id = "ep-dl-status"; statusEl.style.cssText = "font-size:12px;color:#fa0;margin:8px 0;line-height:1.4;"; container.prepend(statusEl); } statusEl.style.color = isError ? "#f88" : "#fa0"; statusEl.textContent = msg; if (hideMs) { setTimeout(() => { if (statusEl) statusEl.textContent = ""; }, hideMs); } } function isLikelyGameDownloadAnchor(a) { const href = a.getAttribute("href") || ""; const title = a.getAttribute("title") || ""; const text = (a.textContent || "").trim(); if (/get-new-premium|\/Emulators|#download/i.test(href)) return false; if (/^Download\s/i.test(title) || /^Download\s/i.test(text)) return true; if (/get-download\.php/i.test(href)) return true; return false; } function hookDownloadClick(a, handler) { if (a.dataset.epDirect) return false; a.dataset.epDirect = "1"; a.addEventListener( "click", (e) => { e.preventDefault(); e.stopImmediatePropagation(); handler().catch((err) => { epStatus(`Failed: ${err.message}`, true); }); }, true ); return true; } function setupGamePageDirectDownload() { if (IS_INTERMEDIATE || IS_GET_DOWNLOAD) return; const container = document.querySelector(".download-link"); if (!container || container.dataset.epDirectSetup) return; container.dataset.epDirectSetup = "1"; let hooked = 0; const gid = gameIdFromPage(); container.querySelectorAll("a[href]").forEach((a) => { const href = a.getAttribute("href") || a.href; if (isGameDownloadHref(href)) { if ( hookDownloadClick(a, () => { const label = (a.textContent || "").trim(); return directDownloadFromGamePage(href, label); }) ) { hooked++; } return; } if (isLikelyGameDownloadAnchor(a)) { if ( hookDownloadClick(a, () => { const label = (a.textContent || "").trim(); return directDownloadClassic(label); }) ) { hooked++; } } }); const needsClassicLink = hooked === 0 || isClassicRomSection() || htmlLooksUnavailable(container.textContent || ""); if (needsClassicLink && gid && !document.getElementById("ep-classic-download")) { const wrap = document.createElement("div"); wrap.style.marginBottom = "8px"; const a = document.createElement("a"); a.id = "ep-classic-download"; a.href = classicGetDownloadUrl(gid); a.textContent = "Download using workaround (1-click)"; a.title = "Classic EP workaround: get-download.php?gid&test=true"; a.style.color = "#a5d414"; a.style.fontSize = "16px"; hookDownloadClick(a, () => directDownloadClassic(a.textContent)); wrap.appendChild(a); wrap.appendChild(document.createElement("br")); container.prepend(wrap); hooked++; } if (hooked && !document.getElementById("ep-direct-hint")) { const hint = document.createElement("p"); hint.id = "ep-direct-hint"; hint.style.cssText = "font-size:12px;color:#8a8;margin:0 0 8px;line-height:1.4;"; hint.textContent = "Direct download enabled — click a link to start without leaving this page."; container.prepend(hint); } } async function tryFetchMprdRedirect(getDownloadUrl) { try { const res = await fetch(getDownloadUrl, { credentials: "include", redirect: "follow", }); if (res.url && /mprd\.se/i.test(res.url)) { location.assign(res.url); return true; } } catch (_) { /* fall through */ } return false; } function hijackLinkPlaceholder() { const el = document.querySelector("a.link-placeholder"); if (!el) return false; clearAllTimers(); const href = el.getAttribute("href") || el.href || ""; if (/mprd\.se/i.test(href) && !href.includes("get-new-premium")) { return redirectToMprd(el.href); } const scraped = findMprdUrl(document); if (scraped) return redirectToMprd(scraped); if (!el.dataset.epWatch) { el.dataset.epWatch = "1"; const obs = new MutationObserver(() => { clearAllTimers(); const h = el.href || el.getAttribute("href") || ""; if (/mprd\.se/i.test(h)) { obs.disconnect(); redirectToMprd(h); return; } const u = findMprdUrl(document); if (u) { obs.disconnect(); redirectToMprd(u); } }); obs.observe(el, { attributes: true, attributeFilter: ["href"] }); obs.observe(document.documentElement, { childList: true, subtree: true }); } if (/will start in \d+ second/i.test(el.textContent || "")) { el.textContent = "Starting your download now…"; } return true; } function skipPremiumWaitPage() { if (!IS_GET_DOWNLOAD) return false; clearAllTimers(); if (redirectToMprd(findMprdUrl(document))) return true; if (hijackLinkPlaceholder()) return true; const meta = document.querySelector('meta[http-equiv="refresh" i]'); if (meta?.content) { const m = meta.content.match(/url=([^;]+)/i); if (m?.[1]) { const u = m[1].trim().replace(/^['"]|['"]$/g, ""); if (/mprd\.se/i.test(u)) return redirectToMprd(u); } } return true; } function hidePreparingBanner() { for (const h of document.querySelectorAll("h2")) { if (/preparing your download/i.test(h.textContent || "")) { h.style.display = "none"; } } } function setupInstantDownloadLink() { if (!IS_INTERMEDIATE) return; const link = document.getElementById("download-link"); if (!link || link.dataset.epInstant) return; if (!(link.getAttribute("href") || "").includes("get-download.php")) return; link.dataset.epInstant = "1"; hidePreparingBanner(); const attach = () => { const target = document.getElementById("download-link"); if (!target || target.dataset.epHooked) return; target.dataset.epHooked = "1"; const fresh = target.cloneNode(true); target.parentNode?.replaceChild(fresh, target); fresh.addEventListener( "click", async (e) => { e.preventDefault(); e.stopImmediatePropagation(); ensureDownloadCookies(); if (await tryFetchMprdRedirect(fresh.href)) return; location.assign(fresh.href); }, true ); }; if (typeof window.jQuery !== "undefined") { window.jQuery(attach); } else { setTimeout(attach, 300); } } function onReady() { ensureDownloadCookies(); skipPremiumWaitPage(); hidePreparingBanner(); setupGamePageDirectDownload(); setupInstantDownloadLink(); if (IS_GET_DOWNLOAD) { hijackLinkPlaceholder(); let n = 0; const burst = setInterval(() => { n++; clearAllTimers(); if (redirectToMprd(findMprdUrl(document)) || hijackLinkPlaceholder()) { clearInterval(burst); } else if (n > 30) { clearInterval(burst); } }, 100); } } ensureDownloadCookies(); if (IS_GET_DOWNLOAD) skipPremiumWaitPage(); if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", onReady, { once: true }); } else { onReady(); } })();
Based on your update, I updated my version of the UserScript for the benefit of others; with more time, I might even be able to re-write it so that it works in browsers older than Chrome 80, Firefox 74, Safari 13.1, or Opera 67, for the benefit of those who hang on to Windows XP: https://greasyfork.org/en/scripts/407947-emuparadise-download-workaround
The major change I made was to define each regular expression at the top and then use it, because each regular-expression "literal" is actually an invocation of the new RegExp constructor; I realize that this is a micro-optimization, though.
If I click the workaround link it gets stuck on a blank page, if I select save content as... then the download gets stuck on 100% but never really finishes. Could be an issue due to me using opera GX but I haven't had an issue with it before so something could've changed will try with chrome.