mirror of
https://github.com/orangeglo/gbnp.git
synced 2026-08-20 07:34:22 -05:00
Clean up ig rom hack a bit, disable map download when selected
This commit is contained in:
@@ -13,7 +13,7 @@
|
||||
<body>
|
||||
<h1>GAME BOY Nintendo Power ROM Builder</h1>
|
||||
<div class='text-container'>
|
||||
This tool can build the data necessary to flash new games to a <a href="https://en.wikipedia.org/wiki/Nintendo_Power_(cartridge)">Nintendo Power Game Boy cart</a>, as well as the <a href="">insideGadgets Power Cart</a>. The menu can have up to seven roms, or a total of 896KB of game data. For flashing, I recommend the <a href="https://www.gbxcart.com/">GBxCart</a>.
|
||||
This tool can build the data necessary to flash new games to a <a href="https://en.wikipedia.org/wiki/Nintendo_Power_(cartridge)">Nintendo Power Game Boy cart</a>, as well as the <a href="https://shop.insidegadgets.com/product/gameboy-1mb-128kb-sram-power-cart-multi-game-and-multi-save/">insideGadgets Power Cart</a>. The menu can have up to seven roms, or a total of 896KB of game data. For flashing, I recommend the <a href="https://www.gbxcart.com/">GBxCart</a>.
|
||||
</div>
|
||||
<noscript>
|
||||
Looks like you have JS disabled. This tool needs javascript to function!
|
||||
@@ -134,7 +134,7 @@
|
||||
<section>
|
||||
<a class='download-link' :download="filename + '.gb'" :href="downloadEnabled ? romData : null" type="application/octet-stream" v-on:click="downloadRomFile" :class="{ disabled: !downloadEnabled }">Download GB File</a>
|
||||
/
|
||||
<a class='download-link' :download="filename + '.map'" :href="downloadEnabled ? mapData : null" type="application/octet-stream" v-on:click="downloadMapFile" :class="{ disabled: !downloadEnabled }">Download MAP File</a>
|
||||
<a class='download-link' :download="filename + '.map'" :href="downloadEnabled && mapEnabled ? mapData : null" type="application/octet-stream" v-on:click="downloadMapFile" :class="{ disabled: (!downloadEnabled || !mapEnabled) }">Download MAP File</a>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -81,13 +81,15 @@ let app = new Vue({
|
||||
downloadEnabled: function() {
|
||||
return this.menu.present() && !this.romOverflow;
|
||||
},
|
||||
mapEnabled: function() {
|
||||
return this.cartType == 0;
|
||||
},
|
||||
romOverflow: function() { return this.processor.romOverflow(); }
|
||||
},
|
||||
watch: {
|
||||
fontIndex: function() {
|
||||
for (let i = 0; i < this.roms.length; i++) { this.roms[i].updateBitmap(this.fontIndex); }
|
||||
},
|
||||
disableCGB: function() { this.processor.disableCGB = this.disableCGB; },
|
||||
forceDMG: function() { this.processor.forceDMG = this.forceDMG; },
|
||||
cartType: function() { this.processor.cartType = this.cartType; }
|
||||
},
|
||||
@@ -137,8 +139,10 @@ let app = new Vue({
|
||||
this.processor.roms = this.roms;
|
||||
},
|
||||
downloadMapFile: function(e) {
|
||||
if (this.mapData) { URL.revokeObjectURL(this.mapData) }
|
||||
this.mapData = URL.createObjectURL(new Blob([this.processor.mapData()]));
|
||||
if (this.cartType == 0) { // regular power cart only
|
||||
if (this.mapData) { URL.revokeObjectURL(this.mapData) }
|
||||
this.mapData = URL.createObjectURL(new Blob([this.processor.mapData()]));
|
||||
}
|
||||
},
|
||||
downloadRomFile: function(e) {
|
||||
if (this.romData) { URL.revokeObjectURL(this.romData) }
|
||||
|
||||
140
script/gbnp.js
140
script/gbnp.js
@@ -13,7 +13,6 @@ const BITMAP_PREVIEW_BYTES = [
|
||||
[0x66, 0x66, 0x66, 0xFF], // dark grey
|
||||
[0x00, 0x00, 0x00, 0xFF] // black
|
||||
]
|
||||
const IG_POWER_CART_HACK = [0x3E, 0x01, 0xEA, 0x00, 0x20, 0xF0, 0xFD, 0x01, 0x00, 0x20, 0x4F, 0x0A, 0xEA, 0x00, 0x60];
|
||||
const FONTS = [
|
||||
{ style: 'normal 8px Gameboy', y: 7 },
|
||||
{ style: 'normal 8px PokemonGB', y: 7 },
|
||||
@@ -304,26 +303,7 @@ class Processor {
|
||||
|
||||
// apply iG power cart hack
|
||||
if (this.cartType == 1) {
|
||||
romFile.seek(0x130E); // For CGB+
|
||||
romFile.writeBytes([0xC3, 0x00, 0x1F]); // Jump to 0x1F00
|
||||
|
||||
romFile.seek(0x140F); // For DMG/Pocket
|
||||
romFile.writeBytes([0xC3, 0x00, 0x1F]); // Jump to 0x1F00
|
||||
|
||||
|
||||
// Set rom bank, ram enabled/disabled, 8KB/32KB locked and ram bank
|
||||
romFile.seek(0x1F00);
|
||||
romFile.writeBytes([0x3e, 0x01, 0xea, 0x00, 0x20, // Set 0x2000, 1
|
||||
0xf0, 0xfd, 0x01, 0x00, 0x22, 0x4f, 0x0a, 0xea, 0x00, 0x40, 0x3e, 0x00, 0xea, 0x00, 0x40, // Ram bank set bit 1+. 8KB/32KB locking = bit 0
|
||||
0xf0, 0xfd, 0x01, 0x00, 0x21, 0x4f, 0x0a, 0xea, 0x00, 0x00, // Ram enable/disable
|
||||
0xf0, 0xfd, 0x01, 0x00, 0x20, 0x4f, 0x0a, 0xea, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); // Rom bank and restart GB
|
||||
|
||||
|
||||
// Patch out any writes to 0x0000-0x1000
|
||||
romFile.seek(0x0DDF);
|
||||
romFile.writeBytes([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
|
||||
romFile.seek(0x0E22);
|
||||
romFile.writeBytes([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
|
||||
this.patchRomHeaderForIG(romFile);
|
||||
}
|
||||
|
||||
// apply dmg menu hack
|
||||
@@ -348,10 +328,10 @@ class Processor {
|
||||
romFile.seek(romFileIndex + i * 512);
|
||||
romFile.writeByte(0xFF);
|
||||
}
|
||||
|
||||
|
||||
let romOffset = 8;
|
||||
let ramOffset = 0;
|
||||
|
||||
|
||||
// used in loop for iG power cart hack
|
||||
let iGOffsets = { rom: 8, ram: 0 };
|
||||
|
||||
for (let i = 0; i < this.roms.length; i++) {
|
||||
const rom = this.roms[i];
|
||||
@@ -381,50 +361,10 @@ class Processor {
|
||||
romFile.writeBytes(rom.bitmapBuffer);
|
||||
|
||||
romFileIndex += 512
|
||||
}
|
||||
|
||||
// apply iG power cart hack
|
||||
if (this.cartType == 1) {
|
||||
// Set rom bank start
|
||||
romFile.seek(0x2001 + i);
|
||||
if (rom.typeByte >= 1 && rom.typeByte <= 3) {// MBC1 enabled, setting bank 0 = bank 1
|
||||
romFile.writeByte(romOffset | 0x01);
|
||||
}
|
||||
else {
|
||||
romFile.writeByte(romOffset);
|
||||
}
|
||||
romOffset += Math.trunc(rom.paddedRomSizeKB() / 16);
|
||||
|
||||
|
||||
// Set ram state
|
||||
romFile.seek(0x2101 + i);
|
||||
if (rom.ramByte > 0) {
|
||||
romFile.writeByte(1); // Ram enabled
|
||||
}
|
||||
else {
|
||||
romFile.writeByte(0); // Ram disabled
|
||||
}
|
||||
|
||||
// Set ram bank info
|
||||
romFile.seek(0x2201 + i);
|
||||
|
||||
// Ram offset and if we are 8KB or 32KB locked
|
||||
if (rom.ramByte == 2) { // 8KB
|
||||
romFile.writeByte(ramOffset); // 8KB locked
|
||||
}
|
||||
else if (rom.ramByte == 3) { // 32KB
|
||||
romFile.writeByte(ramOffset | 0x01); // 32KB locked
|
||||
}
|
||||
else {
|
||||
romFile.writeByte(0);
|
||||
}
|
||||
|
||||
// Increment ram offset after
|
||||
if (rom.ramByte == 2) { // 8KB
|
||||
ramOffset += 2;
|
||||
}
|
||||
else if (rom.ramByte == 3) { // 32KB
|
||||
ramOffset += 8;
|
||||
// apply iG power cart hack
|
||||
if (this.cartType == 1) {
|
||||
this.patchBankInfoForIG(rom, romFile, iGOffsets, i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -437,6 +377,70 @@ class Processor {
|
||||
return new Uint8Array(romBuffer);
|
||||
}
|
||||
|
||||
patchRomHeaderForIG(romFile) {
|
||||
romFile.seek(0x130E); // For CGB+
|
||||
romFile.writeBytes([0xC3, 0x00, 0x1F]); // Jump to 0x1F00
|
||||
|
||||
romFile.seek(0x140F); // For DMG/Pocket
|
||||
romFile.writeBytes([0xC3, 0x00, 0x1F]); // Jump to 0x1F00
|
||||
|
||||
// Set rom bank, ram enabled/disabled, 8KB/32KB locked and ram bank
|
||||
romFile.seek(0x1F00);
|
||||
romFile.writeBytes([0x3e, 0x01, 0xea, 0x00, 0x20, // Set 0x2000, 1
|
||||
0xf0, 0xfd, 0x01, 0x00, 0x22, 0x4f, 0x0a, 0xea, 0x00, 0x40, 0x3e, 0x00, 0xea, 0x00, 0x40, // Ram bank set bit 1+. 8KB/32KB locking = bit 0
|
||||
0xf0, 0xfd, 0x01, 0x00, 0x21, 0x4f, 0x0a, 0xea, 0x00, 0x00, // Ram enable/disable
|
||||
0xf0, 0xfd, 0x01, 0x00, 0x20, 0x4f, 0x0a, 0xea, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); // Rom bank and restart GB
|
||||
|
||||
// Patch out any writes to 0x0000-0x1000
|
||||
romFile.seek(0x0DDF);
|
||||
romFile.writeBytes([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
|
||||
romFile.seek(0x0E22);
|
||||
romFile.writeBytes([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
|
||||
}
|
||||
|
||||
patchBankInfoForIG(rom, romFile, offsets, i) {
|
||||
// Set rom bank start
|
||||
romFile.seek(0x2001 + i);
|
||||
if (rom.typeByte >= 1 && rom.typeByte <= 3) {// MBC1 enabled, setting bank 0 = bank 1
|
||||
romFile.writeByte(offsets.rom | 0x01);
|
||||
}
|
||||
else {
|
||||
romFile.writeByte(offsets.rom);
|
||||
}
|
||||
offsets.rom += Math.trunc(rom.paddedRomSizeKB() / 16);
|
||||
|
||||
// Set ram state
|
||||
romFile.seek(0x2101 + i);
|
||||
if (rom.ramByte > 0) {
|
||||
romFile.writeByte(1); // Ram enabled
|
||||
}
|
||||
else {
|
||||
romFile.writeByte(0); // Ram disabled
|
||||
}
|
||||
|
||||
// Set ram bank info
|
||||
romFile.seek(0x2201 + i);
|
||||
|
||||
// Ram offset and if we are 8KB or 32KB locked
|
||||
if (rom.ramByte == 2) { // 8KB
|
||||
romFile.writeByte(offsets.ram); // 8KB locked
|
||||
}
|
||||
else if (rom.ramByte == 3) { // 32KB
|
||||
romFile.writeByte(offsets.ram | 0x01); // 32KB locked
|
||||
}
|
||||
else {
|
||||
romFile.writeByte(0);
|
||||
}
|
||||
|
||||
// Increment ram offset after
|
||||
if (rom.ramByte == 2) { // 8KB
|
||||
offsets.ram += 2;
|
||||
}
|
||||
else if (rom.ramByte == 3) { // 32KB
|
||||
offsets.ram += 8;
|
||||
}
|
||||
}
|
||||
|
||||
parseMenuData(menuBuffer, fontIndex) {
|
||||
this.roms = [];
|
||||
const menuFile = new FileSeeker(menuBuffer);
|
||||
|
||||
Reference in New Issue
Block a user