diff --git a/Codes.xml b/Codes.xml
index 9970bdc..b3afc78 100644
--- a/Codes.xml
+++ b/Codes.xml
@@ -4658,4 +4658,61 @@
040eb024 60000000
+
+ misc
+ GCI Loader
+ sup39(サポミク)
+ 0.1
+ Nov 11, 2022
+
+ Execute Gecko code loaded from GCI file.
+ ::: warning
+ You will need to reset the game if you hotplug your memory card
+ :::
+
+
+
diff --git a/changelog.md b/changelog.md
index 1887ad3..bbebe17 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,4 +1,8 @@
# Changelog
+## Nov 11, 2022
+- Add GCI Loader (NTSC-J 1.0 only)
+- Support GCI as download format (NTSC-J 1.0 only)
+
## Nov 9, 2022
### Added 'Fast Piantissimo'
To make Piantissimo go as fast as he will in a level, you need to beat him with an in-game time under 25 seconds and grab his Shine. Or you could just use this code.
diff --git a/package.json b/package.json
index 9b2ff76..36b5eca 100644
--- a/package.json
+++ b/package.json
@@ -1,41 +1,41 @@
-{
- "name": "gctgenerator",
- "version": "3.0.1",
- "description": "Super Mario Sunshine Practice File Generator",
- "main": "index.js",
- "authors": {
- "name": "Matteias Collet",
- "email": "matteias.collet@bluewin.ch"
- },
- "repository": "https://github.com/BitPatty/gctGenerator/gctGenerator",
- "scripts": {
- "dev": "npm run codes:inject && npm run translations:compare && vuepress dev site",
- "build": "node ./scripts/inject_codes.js && npm run translations:compare && vuepress build site",
- "format": "prettier --write ./site/**/*{.md,.js,.json}",
- "translations:compare": "node ./scripts/compare_translations.js",
- "codes:inject": "node ./scripts/inject_codes.js && npm run format",
- "codes:clean": "node ./scripts/clean_codes.js && npm run format",
- "precommit": "npm run codes:clean && git add .",
- "serve": "serve ./site/.vuepress/dist"
- },
- "license": "Apache-2.0",
- "devDependencies": {
- "@sup39/markdown-it-attr": "1.2.2",
- "@sup39/markdown-it-inline-tag": "1.0.1",
- "@types/encoding-japanese": "^2.0.1",
- "@vuepress/plugin-back-to-top": "1.9.7",
- "@vuepress/plugin-medium-zoom": "1.9.7",
- "encoding-japanese": "^2.0.0",
- "jsdom": "20.0.2",
- "pre-commit": "1.2.2",
- "prettier": "2.7.1",
- "serve": "14.1.1",
- "vuepress": "1.9.7"
- },
- "dependencies": {
- "vuedraggable": "2.24.3"
- },
- "pre-commit": [
- "precommit"
- ]
-}
+{
+ "name": "gctgenerator",
+ "version": "3.0.1",
+ "description": "Super Mario Sunshine Practice File Generator",
+ "main": "index.js",
+ "authors": {
+ "name": "Matteias Collet",
+ "email": "matteias.collet@bluewin.ch"
+ },
+ "repository": "https://github.com/BitPatty/gctGenerator/gctGenerator",
+ "scripts": {
+ "dev": "npm run codes:inject && npm run translations:compare && vuepress dev site",
+ "build": "node ./scripts/inject_codes.js && npm run translations:compare && vuepress build site",
+ "format": "prettier --write ./site/**/*{.md,.js,.json}",
+ "translations:compare": "node ./scripts/compare_translations.js",
+ "codes:inject": "node ./scripts/inject_codes.js && npm run format",
+ "codes:clean": "node ./scripts/clean_codes.js && npm run format",
+ "precommit": "npm run codes:clean && git add .",
+ "serve": "serve ./site/.vuepress/dist"
+ },
+ "license": "Apache-2.0",
+ "devDependencies": {
+ "@sup39/markdown-it-attr": "1.2.2",
+ "@sup39/markdown-it-inline-tag": "1.0.1",
+ "@types/encoding-japanese": "^2.0.1",
+ "@vuepress/plugin-back-to-top": "1.9.7",
+ "@vuepress/plugin-medium-zoom": "1.9.7",
+ "encoding-japanese": "^2.0.0",
+ "jsdom": "20.0.2",
+ "pre-commit": "1.2.2",
+ "prettier": "2.7.1",
+ "serve": "14.1.1",
+ "vuepress": "1.9.7"
+ },
+ "dependencies": {
+ "vuedraggable": "2.24.3"
+ },
+ "pre-commit": [
+ "precommit"
+ ]
+}
diff --git a/site/.vuepress/components/DownloadButton.vue b/site/.vuepress/components/DownloadButton.vue
index 36e1a08..f9629a5 100644
--- a/site/.vuepress/components/DownloadButton.vue
+++ b/site/.vuepress/components/DownloadButton.vue
@@ -86,6 +86,9 @@ export default {
this.alertDolphinCodeSize(codeSize);
this.generateCheatManagerTXT(c, fileName);
break;
+ case 'gci':
+ this.generateGCI(c, fileName);
+ break;
}
},
alertGCTCodeSize(size) {
@@ -144,6 +147,35 @@ export default {
this.downloadFile(data, `${version}.txt`);
},
+ generateGCI(codes, version) {
+ if (!['GMSJ01'].includes(version)) {
+ alert('GCI format is not yet supported for versions other than GMSJ01');
+ return;
+ }
+ let code = '00D0C0DE00D0C0DE';
+ codes.forEach((c) => (code += c.source));
+ code += 'F000000000000000';
+
+ const blockCount = 7; // TODO
+ const gciSize = 0x40+0x2000*blockCount;
+ const padSize = 0xB040; // TODO
+ let rawData = new Uint8Array(gciSize);
+
+ for (let iD=padSize, iC=0; iD rawData[i] = e);
+ // file name
+ [...new TextEncoder().encode('gct')].forEach((e, i) => rawData[0x8+i] = e);
+ // block count
+ rawData[0x39] = blockCount;
+ // ff*6
+ for (let i=0x3A; i<0x40; i++) rawData[i] = 0xff;
+
+ this.downloadFile(rawData, `01-${version.slice(0, 4)}-gct.gci`);
+ },
downloadFile(data, filename) {
var file = new Blob([data], {
type: 'application/octet-stream',
diff --git a/site/.vuepress/components/codes/asm.js b/site/.vuepress/components/codes/asm.js
index 1d1b796..6117066 100644
--- a/site/.vuepress/components/codes/asm.js
+++ b/site/.vuepress/components/codes/asm.js
@@ -114,7 +114,10 @@ const makeInstXS = (op, op2) => (rA, rS, rB, Rc) => InstX(op, rA, rS, rB, op2, +
/** @type {(op: number) => InstM} */
const makeInstM = (op) => (rA, rS, SH, MB, ME, Rc) => InstM(op, rA, rS, SH, MB, ME, +Rc);
/** @type {(op: number) => InstI} */
-const makeInstI = (op) => (LL, LK, AA = 0) => InstI(op, LL >> 2, +AA, +LK);
+const makeInstI =
+ (op) =>
+ (LL, LK, AA = 0) =>
+ InstI(op, LL >> 2, +AA, +LK);
export const ASM = {
// store rT, rA, D
diff --git a/site/.vuepress/data/downloadFormats.json b/site/.vuepress/data/downloadFormats.json
index f0b6504..d4e2507 100644
--- a/site/.vuepress/data/downloadFormats.json
+++ b/site/.vuepress/data/downloadFormats.json
@@ -10,5 +10,9 @@
{
"target": "gcm",
"i18nKey": "generatorconfig.downloadformat.options.gcm"
+ },
+ {
+ "target": "gci",
+ "i18nKey": "generatorconfig.downloadformat.options.gci"
}
]
diff --git a/site/.vuepress/i18n/de-CH.json b/site/.vuepress/i18n/de-CH.json
index a89d742..94c1a3d 100644
--- a/site/.vuepress/i18n/de-CH.json
+++ b/site/.vuepress/i18n/de-CH.json
@@ -44,7 +44,8 @@
"options": {
"gct": "GCT",
"dolphin": "Dolphin INI",
- "gcm": "CheatManager TXT"
+ "gcm": "CheatManager TXT",
+ "gci": "GCI"
}
},
"categories": {
diff --git a/site/.vuepress/i18n/en-US.json b/site/.vuepress/i18n/en-US.json
index 81a767e..e5ed35f 100644
--- a/site/.vuepress/i18n/en-US.json
+++ b/site/.vuepress/i18n/en-US.json
@@ -44,7 +44,8 @@
"options": {
"gct": "GCT",
"dolphin": "Dolphin INI",
- "gcm": "CheatManager TXT"
+ "gcm": "CheatManager TXT",
+ "gci": "GCI"
}
},
"alert": {
diff --git a/site/.vuepress/i18n/fr-FR.json b/site/.vuepress/i18n/fr-FR.json
index 3800f79..de03677 100644
--- a/site/.vuepress/i18n/fr-FR.json
+++ b/site/.vuepress/i18n/fr-FR.json
@@ -29,7 +29,8 @@
"options": {
"gct": "GCT",
"dolphin": "Dolphin INI",
- "gcm": "CheatManager TXT"
+ "gcm": "CheatManager TXT",
+ "gci": "GCI"
}
}
},
diff --git a/site/.vuepress/i18n/ja-JP.json b/site/.vuepress/i18n/ja-JP.json
index 47727f0..f03d752 100644
--- a/site/.vuepress/i18n/ja-JP.json
+++ b/site/.vuepress/i18n/ja-JP.json
@@ -29,7 +29,8 @@
"options": {
"gct": "GCT",
"dolphin": "Dolphin INI",
- "gcm": "CheatManager TXT"
+ "gcm": "CheatManager TXT",
+ "gci": "GCI"
}
},
"alert": {