From 76edfe0a02c0667778f16b72c12faf86b368b41a Mon Sep 17 00:00:00 2001 From: Ash Monty Date: Sat, 6 Aug 2022 17:52:52 +0200 Subject: [PATCH 01/20] feat(docs): add search, minor style changes --- docs/common/errorList.json | 18 +++ docs/en-US/welcome.md | 76 +----------- public/assets/css/documentation.css | 172 +++++++++++++++------------- src/routes/docs.js | 17 ++- views/docs/docs.handlebars | 4 +- views/docs/search.handlebars | 73 +++++++++++- 6 files changed, 199 insertions(+), 161 deletions(-) create mode 100644 docs/common/errorList.json diff --git a/docs/common/errorList.json b/docs/common/errorList.json new file mode 100644 index 0000000..062ad12 --- /dev/null +++ b/docs/common/errorList.json @@ -0,0 +1,18 @@ +{ + "juxt": [ + "JXT-598-0000", + "JXT-598-0001", + "JXT-598-0002", + "JXT-598-0003", + "JXT-598-0009", + "JXT-598-0010", + "JXT-598-0011", + "JXT-598-0015", + "JXT-598-0020", + "JXT-598-1XXX", + "JXT-598-2XXX", + "JXT-598-3XXX", + "JXT-598-4XXX", + "JXT-598-5XXX" + ] +} diff --git a/docs/en-US/welcome.md b/docs/en-US/welcome.md index 7feaafd..a01686b 100644 --- a/docs/en-US/welcome.md +++ b/docs/en-US/welcome.md @@ -1,75 +1,5 @@ +# Welcome +Welcome to the official documentation for Pretendo Network. Here you'll be able to find installation instructions, error codes, and more. -# Other documentation - -We are a bunch of programmers spending our free time reverse engineering and coding game servers for 3ds and wiiu. - -We are a bunch of programmers spending our free time reverse engineering and coding game servers for 3ds and wiiu. - -We are a bunch of programmers spending our free time reverse engineering and coding game servers for 3ds and wiiu. - -```javascript -function returnTrue() { - class trueOrFalseObject { - constructor(trueOrFalse) { - this.trueOrFalse = trueOrFalse; - } - get trueOrFalse() { - return this.trueOrFalse(); - } - convertNumberToBoolean(trueOrFalse) { - if (convertStringToNumber(trueOrFalse) === 0) { - return true; - } else if (convertStringToNumber(trueOrFalse) == 1) { - return false; - } - } - convertStringToNumber(trueOrFalse) { - if (trueOrFalse === "true") { - return 0; - } else if (trueOrFalse === "false") { - return true * 69 - 1 - false * 69 * 420 - 69 + 2; - } - } - trueOrFalse() { - return this.convertNumberToBoolean(trueOrFalse); - } - } - - let objectWhichWeKnowIsTrue = new trueOrFalseObject("true"); - - function checkIfTrueOrFalse(objectToCheckIfTrueOrFalse) { - if (objectToCheckIfTrueOrFalse === objectWhichWeKnowIsTrue.trueOrFalse) { - return objectWhichWeKnowIsTrue.trueOrFalse; - console.log( - "Successfully checked if the object is true or false. Result: the object is true." - ); - // TODO: fix text not console logging - } else { - objectWhichWeKnowIsTrue = new trueOrFalseObject("false"); - if (objectToCheckIfTrueOrFalse === objectWhichWeKnowIsTrue.trueOrFalse) { - return objectWhichWeKnowIsTrue.trueOrFalse; - console.log( - "Successfully checked if the object is true or false. Result: the object is false." - ); - // TODO: fix text not console logging - } else { - // something went horribly wrong - } - objectWhichWeKnowIsTrue = new trueOrFalseObject("true"); - } - } - - const isTrueTrueOrFalse = checkIfTrueOrFalse("true"); - const isfalseTrueOrFalse = checkIfTrueOrFalse("false"); - - const trueOrFalseJSON = { - true: isTrueTrueOrFalse, - false: isfalseTrueOrFalse, - }; - - return trueOrFalseJSON.true -} - -console.log(returnTrue()) -``` +To begin, check out the quick links or take a look at the sidebar diff --git a/public/assets/css/documentation.css b/public/assets/css/documentation.css index 62be9d6..d62b808 100644 --- a/public/assets/css/documentation.css +++ b/public/assets/css/documentation.css @@ -1,31 +1,34 @@ html, -body { +body, +div.main-body { + height: 100%; background: var(--bg-shade-0); } + a.logo-link { margin: auto; margin-left: 36px; height: 40px; text-decoration: none; } + .docs-wrapper header { - width: calc(100% - 72px); - background: var(--bg-shade-0); - padding: 12px 36px; - margin: 18px 0; + box-sizing: border-box; + margin: 20px; + margin-left: 0; } -header a.logo-link { +.docs-wrapper header a.logo-link { display: none; } -header nav a:first-child { - margin-left: -24px; +.docs-wrapper header nav a:first-child { + margin-left: 0; } .docs-wrapper { display: grid; - grid-template-columns: repeat(2, fit-content(100%)); - grid-template-rows: repeat(2, fit-content(100%)); - height: 100vh; + grid-template-columns: fit-content(100%) auto; + grid-template-rows: fit-content(100%) auto; + height: 100%; } .docs-wrapper .sidebar { @@ -33,16 +36,15 @@ header nav a:first-child { flex-flow: column; align-items: center; width: clamp(270px, 30vw, 500px); - background: var(--bg-shade-0); - max-height: calc(100vh - 69px); overflow-y: scroll; + overflow-x: hidden; min-height: 100%; } .docs-wrapper .sidebar .section { display: flex; flex-flow: column; width: 200px; - margin-left: 138px; + margin-left: clamp(60px, 10vw, 138px); margin-bottom: 72px; } .docs-wrapper .sidebar .section:first-child { @@ -76,11 +78,11 @@ header nav a:first-child { } .docs-wrapper .content { - width: calc(100vw - clamp(270px, 30vw, 500px) - (72px * 2)); background: var(--bg-shade-1); padding: 72px; - max-height: calc(100vh - 69px - (72px * 2)); + max-height: 100%; overflow-y: scroll; + border-top-left-radius: 8px; } .docs-wrapper .content-inner { max-width: 900px; @@ -126,32 +128,100 @@ header nav a:first-child { margin-left: auto; } +.docs-wrapper .content .missing-in-locale-notice { + background: var(--bg-shade-2); + padding: 24px; + border-radius: 6px; +} + +.search .purple-card { + padding: 36px; +} +.search .purple-card h1 { + margin-top: 0; +} +.search .purple-card p { + margin-bottom: 2em; +} +.search .purple-card input::placeholder { + color: var(--text-shade-0); +} +.search .purple-card input:focus { + background-color: var(--bg-shade-4); + color: #fff; + transition: 200ms; + outline: none; +} + +.search .input-wrapper { + position: relative; + margin-top: 8px; +} +.search .input-wrapper .matches { + display: flex; + flex-flow: column; + font-size: 1rem; + background-color: var(--bg-shade-2); + border: none; + border-radius: 0 0 4px 4px; + max-height: 204px; + overflow-y: auto; + overflow-x: hidden; +} +.search .input-wrapper .matches * { + padding: 12px; + margin: 0; + text-decoration: none; + color: var(--text-shade-3); +} +.search .input-wrapper .matches a:hover { + background-color: var(--bg-shade-1); +} +.search input.has-matches { + border-radius: 4px 4px 0 0; +} + +/* +@media screen and (max-width: 1080px) { + .docs-wrapper .sidebar .section { + margin-left: 60px; + width: 184px; + } +} +*/ + /* Scrollbar styling 'cause it's fancy */ .docs-wrapper .sidebar::-webkit-scrollbar, .docs-wrapper .content::-webkit-scrollbar, -.docs-wrapper .content pre code::-webkit-scrollbar { +.docs-wrapper .content pre code::-webkit-scrollbar, +.search .input-wrapper .matches::-webkit-scrollbar { width: 12px; height: 12px; } .docs-wrapper .sidebar::-webkit-scrollbar-track, .docs-wrapper .content::-webkit-scrollbar-track, -.docs-wrapper .content pre code::-webkit-scrollbar-track { +.docs-wrapper .content pre code::-webkit-scrollbar-track, +.search .input-wrapper .matches::-webkit-scrollbar-track { background: none; } .docs-wrapper .sidebar::-webkit-scrollbar-thumb, .docs-wrapper .content::-webkit-scrollbar-thumb, -.docs-wrapper .content pre code::-webkit-scrollbar-thumb { +.docs-wrapper .content pre code::-webkit-scrollbar-thumb, +.search .input-wrapper .matches::-webkit-scrollbar-thumb { background-color: var(--text-shade-0); border-radius: 24px; - border: 3px solid var(--bg-shade-1); + border: 3px solid var(--bg-shade-0); } .docs-wrapper .content::-webkit-scrollbar-thumb { border: 3px solid var(--bg-shade-1); } -.docs-wrapper .content pre code::-webkit-scrollbar-thumb { - border: 3px solid var(--bg-shade-0); +.docs-wrapper .content pre code::-webkit-scrollbar-thumb, +.search .input-wrapper .matches::-webkit-scrollbar-thumb { + border: 3px solid var(--bg-shade-2); } -.docs-wrapper .sidebar { + +.docs-wrapper .sidebar, +.search .input-wrapper .matches { scrollbar-width: thin; scrollbar-color: var(--text-shade-0) var(--bg-shade-1); } @@ -163,59 +233,3 @@ header nav a:first-child { scrollbar-width: thin; scrollbar-color: var(--text-shade-0) var(--bg-shade-0); } -.docs-wrapper .content .missing-in-locale-notice { - background: var(--bg-shade-2); - padding: 24px; - border-radius: 6px; -} - - -.input-wrapper { - display: flex; - margin-top: 8px; -} - -.localization-form input { - appearance: none; - -webkit-appearance: none; - border: 0; - font-family: Poppins, Arial, Helvetica, sans-serif; - font-size: 1rem; - background-color: var(--bg-shade-3); - border: none; - border-radius: 4px 0 0 4px; - padding: 12px 24px; - color: var(--text-shade-1); - width: 20px; - flex: 2 10%; -} - -.search input::placeholder { - color: var(--text-shade-0); -} - -.search input:focus { - background-color: #fff; - color: var(--bg-shade-3); - transition: 200ms; - outline: none; -} - -.search button { - appearance: none; - -webkit-appearance: none; - border: 0; - font-family: Poppins, Arial, Helvetica, sans-serif; - font-size: 1rem; - color: var(--text-shade-3); - padding: 12px 36px; - background: var(--accent-shade-0); - cursor: pointer; -} - -@media screen and (max-width: 1080px) { - .docs-wrapper .sidebar .section { - margin-left: 60px; - width: 184px; - } -} diff --git a/src/routes/docs.js b/src/routes/docs.js index 4541988..26502ae 100644 --- a/src/routes/docs.js +++ b/src/routes/docs.js @@ -4,17 +4,26 @@ const router = new Router(); const fs = require('fs'); const path = require('path'); const { marked } = require('marked'); +const errorList = require('../../docs/common/errorList.json'); router.get('/', async (request, response) => { response.redirect('/docs/welcome'); }); router.get('/search', async (request, response) => { + const renderData = { + errorList: JSON.stringify(errorList), + currentPage: 'search', + }; + response.render('docs/search', renderData); +}); + +router.get('/install', async (request, response) => { const renderData = { - currentPage: request.params.slug + currentPage: 'install', }; - response.render('docs/search', renderData); + response.render('docs/install', renderData); }); router.get('/:slug', async (request, response, next) => { @@ -53,11 +62,9 @@ router.get('/:slug', async (request, response, next) => { renderData.content = content; // A boolean to show the quick links grid or not. - let showQuickLinks = false; if (pageName === 'welcome') { - showQuickLinks = true; + renderData.showQuickLinks = true; } - renderData.showQuickLinks = showQuickLinks; response.render('docs/docs', renderData); }); diff --git a/views/docs/docs.handlebars b/views/docs/docs.handlebars index fe91409..c18d337 100644 --- a/views/docs/docs.handlebars +++ b/views/docs/docs.handlebars @@ -40,7 +40,7 @@ {{#if showQuickLinks}}

{{ localeHelper locale "docs" "quickLinks" "header" }}

+ + diff --git a/views/docs/install.handlebars b/views/docs/install.handlebars index f19aa67..d36a766 100644 --- a/views/docs/install.handlebars +++ b/views/docs/install.handlebars @@ -27,7 +27,12 @@ - {{> header}} +
+ + {{> header}} +
{{> docs-sidebar}} @@ -59,6 +64,8 @@ + + diff --git a/views/docs/search.handlebars b/views/docs/search.handlebars index 7476fcd..339a4a2 100644 --- a/views/docs/search.handlebars +++ b/views/docs/search.handlebars @@ -27,7 +27,12 @@ - {{> header}} +
+ + {{> header}} +
{{> docs-sidebar}} @@ -48,6 +53,8 @@ + + diff --git a/views/partials/docs-sidebar.handlebars b/views/partials/docs-sidebar.handlebars index 82b45ea..c0f31b2 100644 --- a/views/partials/docs-sidebar.handlebars +++ b/views/partials/docs-sidebar.handlebars @@ -6,6 +6,14 @@ Search +
+
Install
+ Wii U + 3DS + Cemu + Citra +
+
Error codes - Juxt
JXT-598-0000 From 6fd28ae86e55415a3681c2a6b2f2cca134fb3f1f Mon Sep 17 00:00:00 2001 From: Ash Monty Date: Mon, 8 Aug 2022 00:02:03 +0200 Subject: [PATCH 06/20] fix(docs): platform images on firefox --- public/assets/css/documentation.css | 11 ++++++++--- src/database.js | 4 ++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/public/assets/css/documentation.css b/public/assets/css/documentation.css index b8410f0..4d7aa73 100644 --- a/public/assets/css/documentation.css +++ b/public/assets/css/documentation.css @@ -243,10 +243,9 @@ button#openSidebar { } .platform-grid a img { - width: 100%; - max-width: 216px; + width: 180px; + max-width: 100%; height: auto; - max-height: 184px; } .platform-grid a span { margin-top: auto; @@ -342,6 +341,12 @@ button#openSidebar { } } +@media screen and (max-width: 360px) { + .docs-wrapper .content { + padding: 24px; + } +} + /* Scrollbar styling 'cause it's fancy */ .docs-wrapper .sidebar::-webkit-scrollbar, .docs-wrapper .content::-webkit-scrollbar, diff --git a/src/database.js b/src/database.js index b54a1ed..5a25802 100644 --- a/src/database.js +++ b/src/database.js @@ -7,7 +7,7 @@ const { uri, database, options } = accountServerConfig; let accountServerDBConnection; let PNID; -async function connect() { +async function connect() {/* accountServerDBConnection = await mongoose.createConnection(`${uri}/${database}`, options); accountServerDBConnection.on('error', console.error.bind(console, 'Mongoose connection error:')); accountServerDBConnection.on('close', () => { @@ -18,7 +18,7 @@ async function connect() { PNID = accountServerDBConnection.model('PNID', PNIDSchema); - module.exports.PNID = PNID; + module.exports.PNID = PNID;*/ } module.exports = { From e8855fe87c990d297f6d427fb40f4482857cc8ef Mon Sep 17 00:00:00 2001 From: Ash Monty Date: Mon, 8 Aug 2022 00:16:33 +0200 Subject: [PATCH 07/20] style: fix wonky platform select button im dumb --- public/assets/css/documentation.css | 1 + 1 file changed, 1 insertion(+) diff --git a/public/assets/css/documentation.css b/public/assets/css/documentation.css index 4d7aa73..80af3b9 100644 --- a/public/assets/css/documentation.css +++ b/public/assets/css/documentation.css @@ -322,6 +322,7 @@ button#openSidebar { .docs-wrapper .content .quick-links-grid, .platform-grid { grid-template-columns: 1fr; + grid-auto-rows: 1fr; } } From e673289cae8e359da9522565c4787b84a7989521 Mon Sep 17 00:00:00 2001 From: Ash Monty Date: Sun, 14 Aug 2022 10:24:22 +0200 Subject: [PATCH 08/20] fix: remove accidental commenting-out of code --- src/database.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/database.js b/src/database.js index 5a25802..b54a1ed 100644 --- a/src/database.js +++ b/src/database.js @@ -7,7 +7,7 @@ const { uri, database, options } = accountServerConfig; let accountServerDBConnection; let PNID; -async function connect() {/* +async function connect() { accountServerDBConnection = await mongoose.createConnection(`${uri}/${database}`, options); accountServerDBConnection.on('error', console.error.bind(console, 'Mongoose connection error:')); accountServerDBConnection.on('close', () => { @@ -18,7 +18,7 @@ async function connect() {/* PNID = accountServerDBConnection.model('PNID', PNIDSchema); - module.exports.PNID = PNID;*/ + module.exports.PNID = PNID; } module.exports = { From 94060b8f53fbc25017b4c827830a9084dffb2902 Mon Sep 17 00:00:00 2001 From: Ash Monty Date: Mon, 15 Aug 2022 10:46:18 +0200 Subject: [PATCH 09/20] locales(docs): convert to POSIX-style --- docs/{en-US => en_US}/install/citra.md | 0 docs/{en-US => en_US}/install/wiiu.md | 0 docs/{en-US => en_US}/installing-juxt.md | 0 docs/{en-US => en_US}/welcome.md | 0 docs/{it-IT => it_IT}/welcome.md | 0 src/routes/docs.js | 4 ++-- 6 files changed, 2 insertions(+), 2 deletions(-) rename docs/{en-US => en_US}/install/citra.md (100%) rename docs/{en-US => en_US}/install/wiiu.md (100%) rename docs/{en-US => en_US}/installing-juxt.md (100%) rename docs/{en-US => en_US}/welcome.md (100%) rename docs/{it-IT => it_IT}/welcome.md (100%) diff --git a/docs/en-US/install/citra.md b/docs/en_US/install/citra.md similarity index 100% rename from docs/en-US/install/citra.md rename to docs/en_US/install/citra.md diff --git a/docs/en-US/install/wiiu.md b/docs/en_US/install/wiiu.md similarity index 100% rename from docs/en-US/install/wiiu.md rename to docs/en_US/install/wiiu.md diff --git a/docs/en-US/installing-juxt.md b/docs/en_US/installing-juxt.md similarity index 100% rename from docs/en-US/installing-juxt.md rename to docs/en_US/installing-juxt.md diff --git a/docs/en-US/welcome.md b/docs/en_US/welcome.md similarity index 100% rename from docs/en-US/welcome.md rename to docs/en_US/welcome.md diff --git a/docs/it-IT/welcome.md b/docs/it_IT/welcome.md similarity index 100% rename from docs/it-IT/welcome.md rename to docs/it_IT/welcome.md diff --git a/src/routes/docs.js b/src/routes/docs.js index d02b0c6..8201d76 100644 --- a/src/routes/docs.js +++ b/src/routes/docs.js @@ -28,8 +28,8 @@ router.get('/install', async (request, response) => { function getRawDocs(locale, subpath, pageName) { - const localePath = path.join(__dirname, '../../docs', locale, subpath, `${pageName}.md`); - const defaultPath = path.join(__dirname, '../../docs', 'en-US', subpath, `${pageName}.md`); + const localePath = path.join(__dirname, '../../docs', locale.replace('-', '_'), subpath, `${pageName}.md`); + const defaultPath = path.join(__dirname, '../../docs', 'en_US', subpath, `${pageName}.md`); if (fs.existsSync(localePath)) { return { From ef1af44f8b37aecbda211d4a19de50545c0f0bdb Mon Sep 17 00:00:00 2001 From: Ash Monty Date: Mon, 15 Aug 2022 15:33:40 +0200 Subject: [PATCH 10/20] fix: border radius on content when sidebar is open --- public/assets/css/documentation.css | 3 +++ public/assets/js/docssidebarhandler.js | 2 ++ 2 files changed, 5 insertions(+) diff --git a/public/assets/css/documentation.css b/public/assets/css/documentation.css index 80af3b9..c43cf5b 100644 --- a/public/assets/css/documentation.css +++ b/public/assets/css/documentation.css @@ -313,6 +313,9 @@ button#openSidebar { grid-column: 2 / span 1; grid-row: 2 / span 1; } + .docs-wrapper .content.open-sidebar { + border-top-left-radius: 8px; + } .docs-wrapper .content-inner { max-width: none; } diff --git a/public/assets/js/docssidebarhandler.js b/public/assets/js/docssidebarhandler.js index c8eca65..b602fc4 100644 --- a/public/assets/js/docssidebarhandler.js +++ b/public/assets/js/docssidebarhandler.js @@ -1,5 +1,7 @@ const openSidebarBtn = document.querySelector('#openSidebar'); +const content = document.querySelector('div.content'); openSidebarBtn.addEventListener('click', function() { const sidebar = document.querySelector('.sidebar'); sidebar.classList.toggle('open'); + content.classList.toggle('open-sidebar'); }); From 760dfb7a07a2ba96de037d4a0d04466ef7c1ecf6 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Fri, 19 Aug 2022 21:21:30 -0400 Subject: [PATCH 11/20] Added Cemu and 3DS docs. Wii U needs updating --- docs/en_US/install/3ds.md | 33 +++++++++++++ docs/en_US/install/cemu.md | 44 ++++++++++++++++++ docs/en_US/install/citra.md | 6 +++ docs/en_US/install/wiiu.md | 28 +++++++---- docs/en_US/welcome.md | 5 -- .../images/docs/download-account-files.png | Bin 0 -> 24727 bytes 6 files changed, 101 insertions(+), 15 deletions(-) create mode 100644 docs/en_US/install/3ds.md create mode 100644 docs/en_US/install/cemu.md delete mode 100644 docs/en_US/welcome.md create mode 100644 public/assets/images/docs/download-account-files.png diff --git a/docs/en_US/install/3ds.md b/docs/en_US/install/3ds.md new file mode 100644 index 0000000..8a84707 --- /dev/null +++ b/docs/en_US/install/3ds.md @@ -0,0 +1,33 @@ +
+ Note! +
+ Pretendo Network is currently in closed beta! The servers are only accessible to testers. To become a tester, upgrade your PNID here +
+ +
This Guide may be missing some info or incomplete.
+ +# 3DS/2DS Family + +In this guide you will learn how to setup a PNID from Scratch on a 3DS. + +
+ ℹ️ This guide assumes that you have a Homebrewed System, if you don't please follow this guide on how to homebrew your system first. +
+ +## Download +Nimbus [Github](https://github.com/PretendoNetwork/nimbus/releases) + + +## Usage +1. Extract to the root of your SD card +2. Ensure Game Patching is enabled in Luma (hold SELECT at boot to enter Luma settings) +3. Run the Nimbus homebrew and select the network you wish to use (Nintendo Network, or Pretendo Network) + +## How does it work? +Nimbus will create a 2nd local account set to the `test` NASC environment. The IPS patches will set the `test` NASC environment URLs to point to Pretendo. You may freely switch between Pretendo and Nintendo. Your selected mode will persist between reboots. + +## 2nd local account? +You may have thought to yourself; _"2nd local account? What's that? I thought the 3DS only had one account?"_ And you'd be half right. The 3DS only _normally_ supports one account, and you may only have one account active at a time. However Nintendo implemented support for multiple local accounts on the 3DS/2DS which remains unused on all retail units. On a normal retail unit only one local account is ever made, which is set to the `prod` NASC environment. Local accounts may be set to `prod`, `test` or `dev`. Nimbus makes use of this unused feature to create sandboxed local accounts with different environments + +## Can I connect my PNID? +Currently connecting a PNID is not officially supported, though some users have reported it working just fine. \ No newline at end of file diff --git a/docs/en_US/install/cemu.md b/docs/en_US/install/cemu.md new file mode 100644 index 0000000..c6db5e7 --- /dev/null +++ b/docs/en_US/install/cemu.md @@ -0,0 +1,44 @@ +
+ Note! +
+ Pretendo Network is currently in closed beta! The servers are only accessible to testers. To become a tester, upgrade your PNID here +
+ +
This Guide may be missing some info or incomplete.
+ +# Cemu + +
+ Cemu support is experimental! + Cemu does not currently have a (working) way of redriecting to custom servers. Because of this, we must hook into the Cemu process and patch parts of the program memory, much like how our Wii U patch works. This is not officially supported by Cemu or it's developers, and may have issues or fail to work entirely. +
+ +## Online files +Cemu requires the use of several files obtained via dumping from real hardware. You may use those files if you have a physical Wii U, they will work just fine. If you _don't_ have a real Wii U navigate to [your account page](/account) and select `Download account files` + +
+ +## Setup Cemu for online +After obtaining the files needed for online play refer to the official [Cemu Online Play](https://cemu.cfw.guide/online-play.html) guide + +
+ Note! If you downloaded the account files from your Pretendo Network account you may skip the steps on the Cemu guide which dumps them from a console. However these files will not work on Nintendo Network. For compatibility with both servers, use files dumped from a real console +
+ +## Installing Pretendo +Once you have Cemu setup for online play navigate to our [Cemu Patcher](https://github.com/PretendoNetwork/cemu-patcher) repository. To build from scratch, clone the repository and open in Visual Studio and build the solution. To download the latest pre-built release, head to the [releases](https://github.com/PretendoNetwork/cemu-patcher/releases) page and download the latest `cemuhook.dll` + +Place `cemuhook.dll` in the same folder as `Cemu.exe` and run Cemu. Cemu should automatically detect `cemuhook.dll` and load it. You may now go online with Pretendo! + +## The patch doesn't seem to work? +Due to the experimental state of Cemu support, our patch may fail to load at times. This could be caused by changes in Cemu, your systems anti-virus, bugs in our programming, and more. We are looking into more stable patches. If the hook fails to load, try renaming `cemuhook.dll` to `dbghelp.dll` and restarting Cemu. If this does not work, you may need to contact a developer. Please be patient as we try to figure out the cause of the issue and any potential solutions + +
+ Please be warned that in some cases the patch fails for completely unknown reasons. There have been cases where different users on the same operating system, using the same Cemu version, playing the same game, experience different results. In these cases there is not much to do besides trying a different machine or Cemu version. +
+ +## What about Cemuhook by Rajkosto? +You may have noticed that Cemu automatically searches for loads DLL files named `cemuhook.dll`. This is intended for use with Cemuhook developed by Rajkosto. We hijack the DLL name in order to get Cemu to load our hook automatically. If you would like to still use Cemuhook by Rajkosto with Pretendo, name the Cemuhook by Rajkosto DLL to `true_cemuhook.dll` while keeping the Pretendo hook named `cemuhook.dll`. Our patcher will look for a DLL named `true_cemuhook.dll` and load it automatically. This is not officially supported by Rajkosto and may cause issues. Use at your own risk. + +## Wine/Linux support? +The Pretendo patches do work under wine. Rename `cemuhook.dll` to `dbghelp.dll` and place `dbghelp.dll` in the same folder as `Cemu.exe`. Run `winecfg` and navigate to `Libraries` and make sure `dbghelp` is added to the override list. Select it and click `Edit` and ensure the override is set to `Native then Builtin`. Wine should now allow your local `dbghelp.dll` override the built-in DLL \ No newline at end of file diff --git a/docs/en_US/install/citra.md b/docs/en_US/install/citra.md index 092db32..2f7cffd 100644 --- a/docs/en_US/install/citra.md +++ b/docs/en_US/install/citra.md @@ -1,3 +1,9 @@ +
+ Note! +
+ Pretendo Network is currently in closed beta! The servers are only accessible to testers. To become a tester, upgrade your PNID here +
+ # Citra At the moment Citra does not support true online play, so it doesn't work with Pretendo. Moreover, it shows no sign of supporting true play in the future. diff --git a/docs/en_US/install/wiiu.md b/docs/en_US/install/wiiu.md index 3cadcc5..046e338 100644 --- a/docs/en_US/install/wiiu.md +++ b/docs/en_US/install/wiiu.md @@ -1,16 +1,24 @@ +
+ Note! +
+ Pretendo Network is currently in closed beta! The servers are only accessible to testers. To become a tester, upgrade your PNID here +
+ +
This Guide may be missing some info or incomplete.
+ # Wii U -This guide assumes your Wii U can already run Homebrew. If not, you can [follow this guide](https://wiiu.hacks.guide/) and come back here when you're done. -
-guide lol + ℹ️ This guide assumes that you have a Homebrewed System, if you don't please follow this guide on how to homebrew your system first.
-
-guide lol -
- -
-guide lol -
+# Environment +There are several homebrew environments for the Wii U, all with pros and cons. We have several patches for multiple environments to try and accommodate as many users as possible. Each patch has a slightly different feature set. See below for a table of patches and their feature sets +| Name | GitHub Branch | Environment | NoSSL | URL Patches | Inkay | Exploit Fixes | +| ------ | ------------- | ----------- | ----- | ----------- | ----- | ------------- | +| Nimble | main | HBL | ✅ | ✅ | ❌ | ❌ | +| Nimble | new_patch | HBL | ✅ | ✅ | ✅ | ✅ | +| Nimble | tiramisu | Tiramisu | ✅ | ✅ | ❌ | ❌ | +| Inkay | main | HBL+WUPS | ❌ | ❌ | ✅ | ❌ | +| Inkay | devel | Aroma | ❌ | ❌ | ✅ | ❌ | diff --git a/docs/en_US/welcome.md b/docs/en_US/welcome.md deleted file mode 100644 index a01686b..0000000 --- a/docs/en_US/welcome.md +++ /dev/null @@ -1,5 +0,0 @@ -# Welcome - -Welcome to the official documentation for Pretendo Network. Here you'll be able to find installation instructions, error codes, and more. - -To begin, check out the quick links or take a look at the sidebar diff --git a/public/assets/images/docs/download-account-files.png b/public/assets/images/docs/download-account-files.png new file mode 100644 index 0000000000000000000000000000000000000000..12fccfa0dfd74208ddf3ed9936470579e4bec1f1 GIT binary patch literal 24727 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 literal 0 HcmV?d00001 From 1c46914bc72f5bd65aba94c762080ec27cf5e985 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Fri, 19 Aug 2022 21:21:54 -0400 Subject: [PATCH 12/20] Made welcome page into own view --- src/routes/docs.js | 86 +++++++++-------------------- src/util.js | 44 +++++++++++++++ views/docs/docs.handlebars | 21 ------- views/docs/welcome.handlebars | 100 ++++++++++++++++++++++++++++++++++ 4 files changed, 170 insertions(+), 81 deletions(-) create mode 100644 views/docs/welcome.handlebars diff --git a/src/routes/docs.js b/src/routes/docs.js index 8201d76..58fef96 100644 --- a/src/routes/docs.js +++ b/src/routes/docs.js @@ -1,15 +1,29 @@ const { Router } = require('express'); const router = new Router(); +const util = require('../util'); -const fs = require('fs'); -const path = require('path'); -const { marked } = require('marked'); const errorList = require('../../docs/common/errorList.json'); router.get('/', async (request, response) => { response.redirect('/docs/welcome'); }); +router.get('/welcome', async (request, response) => { + const renderData = { + currentPage: 'welcome', + }; + + response.render('docs/welcome', renderData); +}); + +router.get('/install', async (request, response) => { + const renderData = { + currentPage: 'install', + }; + + response.render('docs/install', renderData); +}); + router.get('/search', async (request, response) => { const renderData = { errorList: JSON.stringify(errorList), @@ -18,53 +32,6 @@ router.get('/search', async (request, response) => { response.render('docs/search', renderData); }); -router.get('/install', async (request, response) => { - const renderData = { - currentPage: 'install', - }; - - response.render('docs/install', renderData); -}); - -function getRawDocs(locale, subpath, pageName) { - - const localePath = path.join(__dirname, '../../docs', locale.replace('-', '_'), subpath, `${pageName}.md`); - const defaultPath = path.join(__dirname, '../../docs', 'en_US', subpath, `${pageName}.md`); - - if (fs.existsSync(localePath)) { - return { - content: parseDocs(fs.readFileSync(localePath, 'utf8')), - MDLocale: locale, - }; - } else if (fs.existsSync(defaultPath)) { - return { - content: parseDocs(fs.readFileSync(defaultPath, 'utf8')), - MDLocale: 'en-US' - }; - } else { - return { - content: null, - MDLocale: null - }; - } -} - -function parseDocs(rawDocs) { - if (rawDocs) { - let markedContent = marked(rawDocs); - markedContent = markedContent.replaceAll(/\[yt-iframe\]\(.{11}\)/g, (match) => { - const videoIDRegex = /(?<=\[yt-iframe\]\().*(?=\))/g; - const videoID = match.match(videoIDRegex)[0]; - return `
`; - }); - - const htmlContent = marked.parse(markedContent); - return htmlContent; - } else { - return null; - } -} - router.get('/:page', async (request, response, next) => { const renderData = {}; @@ -72,7 +39,7 @@ router.get('/:page', async (request, response, next) => { const pageName = request.params.page; renderData.currentPage = pageName; - const { content, MDLocale } = getRawDocs(locale, '', pageName); + const { content, MDLocale } = util.getRawDocs(locale, '', pageName); if (content) { renderData.content = content; } else { @@ -80,27 +47,26 @@ router.get('/:page', async (request, response, next) => { } renderData.missingInLocale = locale !== MDLocale; - // A boolean to show the quick links grid or not. - if (pageName === 'welcome') { - renderData.showQuickLinks = true; - } - response.render('docs/docs', renderData); }); -router.get('/:subpath/:page', async (request, response, next) => { - const renderData = {}; +router.get('/:subpath/:page', async (request, response, next) => { const locale = response.locals.localeString; const pageName = request.params.page; const subpath = request.params.subpath; - renderData.currentPage = `${subpath}/${pageName}`; - const { content, MDLocale } = getRawDocs(locale, subpath, pageName); + const renderData = { + currentPage: `${subpath}/${pageName}` + }; + + const { content, MDLocale } = util.getRawDocs(locale, subpath, pageName); + if (content) { renderData.content = content; } else { return next(); } + renderData.missingInLocale = locale !== MDLocale; response.render('docs/docs', renderData); diff --git a/src/util.js b/src/util.js index 6e01ea2..7e068c9 100644 --- a/src/util.js +++ b/src/util.js @@ -1,12 +1,15 @@ +const path = require('path'); const fs = require('fs-extra'); const got = require('got'); const crypto = require('crypto'); const Stripe = require('stripe'); +const { marked } = require('marked'); const mailer = require('./mailer'); const database = require('./database'); const logger = require('./logger'); const config = require('../config.json'); + const stripe = new Stripe(config.stripe.secret_key); function fullUrl(request) { @@ -25,6 +28,45 @@ function getLocale(region, language) { return require(`${__dirname}/../locales/US_en.json`); } +function getRawDocs(locale, subpath, pageName) { + + const localePath = path.join(__dirname, '../docs', locale.replace('-', '_'), subpath, `${pageName}.md`); + const defaultPath = path.join(__dirname, '../docs', 'en_US', subpath, `${pageName}.md`); + + if (fs.existsSync(localePath)) { + return { + content: parseDocs(fs.readFileSync(localePath, 'utf8')), + MDLocale: locale, + }; + } else if (fs.existsSync(defaultPath)) { + return { + content: parseDocs(fs.readFileSync(defaultPath, 'utf8')), + MDLocale: 'en-US' + }; + } + + return { + content: null, + MDLocale: null + }; +} + +function parseDocs(rawDocs) { + if (!rawDocs) { + return null; + } + + let markedContent = marked(rawDocs); + markedContent = markedContent.replaceAll(/\[yt-iframe\]\(.{11}\)/g, (match) => { + const videoIDRegex = /(?<=\[yt-iframe\]\().*(?=\))/g; + const videoID = match.match(videoIDRegex)[0]; + return `
`; + }); + + const htmlContent = marked.parse(markedContent); + return htmlContent; +} + function apiGetRequest(path, headers) { return got.get(`https://api.pretendo.cc${path}`, { responseType: 'json', @@ -338,6 +380,8 @@ async function handleStripeEvent(event) { module.exports = { fullUrl, getLocale, + getRawDocs, + parseDocs, apiGetRequest, apiPostGetRequest, apiDeleteGetRequest, diff --git a/views/docs/docs.handlebars b/views/docs/docs.handlebars index fd05392..19eed2b 100644 --- a/views/docs/docs.handlebars +++ b/views/docs/docs.handlebars @@ -42,27 +42,6 @@

{{ localeHelper locale "docs" "missingInLocale" }}

{{/if}} - {{#if showQuickLinks}} -

{{ localeHelper locale "docs" "quickLinks" "header" }}

- - {{/if}} - {{{ content }}}
diff --git a/views/docs/welcome.handlebars b/views/docs/welcome.handlebars new file mode 100644 index 0000000..cb1583d --- /dev/null +++ b/views/docs/welcome.handlebars @@ -0,0 +1,100 @@ + + +
+ + + + + + + Pretendo + + + + + +
+ + {{> header}} +
+ + {{> docs-sidebar}} + +
+
+

{{ localeHelper locale "docs" "quickLinks" "header" }}

+ + +

Welcome

+

Welcome to the official documentation for Pretendo Network. Here you'll be able to find installation instructions, error + codes, and more.

+

To begin, check out the quick links or take a look at the sidebar

+
+
+
+ + + + + + + \ No newline at end of file From 748bb31901f0cccc813120aaea5e35ad449957cb Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Fri, 19 Aug 2022 21:22:04 -0400 Subject: [PATCH 13/20] Removed beans --- views/partials/docs-sidebar.handlebars | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/views/partials/docs-sidebar.handlebars b/views/partials/docs-sidebar.handlebars index c0f31b2..2cf3c9e 100644 --- a/views/partials/docs-sidebar.handlebars +++ b/views/partials/docs-sidebar.handlebars @@ -31,20 +31,6 @@ JXT-598-4XXX JXT-598-5XXX - -