Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
Ajarmar committed Sep 27, 2020
2 parents f36eec7 + 575bf42 commit 164fb2e
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 8 deletions.
33 changes: 28 additions & 5 deletions src/com/dabomstew/pkrandom/ctr/NCCH.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

import com.dabomstew.pkrandom.FileFunctions;
import com.dabomstew.pkrandom.SysConstants;
import com.dabomstew.pkrandom.exceptions.EncryptedROMException;
import cuecompressors.BLZCoder;

import java.io.*;
Expand Down Expand Up @@ -82,7 +83,22 @@ public NCCH(String filename, long ncchStartingOffset, String productCode, String
} else {
writingEnabled = false;
}
readFileSystem();

// The below code handles things "wrong" with regards to encrypted ROMs. We just
// blindly treat the ROM as decrypted and try to parse all of its data, when we
// *should* be looking at the header of the ROM to determine if the ROM is encrypted.
// Unfortunately, many people have poorly-decrypted ROMs that do not properly set
// the bytes on the NCCH header, so we can't assume that the header is telling the
// truth. If we read the whole ROM without crashing, then it's probably decrypted.
try {
readFileSystem();
} catch (Exception ex) {
if (!this.isDecrypted()) {
throw new EncryptedROMException(ex);
} else {
throw ex;
}
}
}

public void reopenROM() throws IOException {
Expand All @@ -101,9 +117,6 @@ public void closeROM() throws IOException {
}

private void readFileSystem() throws IOException {
if (!this.isDecrypted()) {
return;
}
exefsOffset = ncchStartingOffset + FileFunctions.readLittleEndianIntFromFile(baseRom, ncchStartingOffset + 0x1A0) * media_unit_size;
romfsOffset = ncchStartingOffset + FileFunctions.readLittleEndianIntFromFile(baseRom, ncchStartingOffset + 0x1B0) * media_unit_size;
baseRom.seek(ncchStartingOffset + 0x20D);
Expand Down Expand Up @@ -589,11 +602,21 @@ private void writeRomfsFileToLayeredFS(RomfsFile file, String layeredFSRootPath)
}

public boolean isDecrypted() throws IOException {
// This is the way you're *supposed* to tell if a ROM is decrypted. Specifically, this
// is checking the noCrypto flag on the NCCH bitflags.
long ncchFlagOffset = ncchStartingOffset + 0x188;
byte[] ncchFlags = new byte[8];
baseRom.seek(ncchFlagOffset);
baseRom.readFully(ncchFlags);
return (ncchFlags[7] & 0x4) != 0;
if ((ncchFlags[7] & 0x4) != 0) {
return true;
}

// However, some poorly-decrypted ROMs don't set this flag. So our heuristic for detecting
// if they're decrypted is to check whether the battle CRO exists, since all 3DS Pokemon
// games and updates have this file. If the game is *really* encrypted, then the odds of us
// successfully extracting this exact name from the metadata tables is like one in a billion.
return romfsFiles != null && (romfsFiles.containsKey("DllBattle.cro") || romfsFiles.containsKey("Battle.cro"));
}

// Retrieves a decompressed version of .code (the game's executable).
Expand Down
2 changes: 1 addition & 1 deletion src/com/dabomstew/pkrandom/newgui/Bundle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ GUI.openedZIPfile=%s is a ZIP archive, not a ROM.\nYou should extract it and try
GUI.openedRARfile=%s is a RAR archive, not a ROM.\nYou should extract it and try to randomize the actual ROM file inside.
GUI.openedIPSfile=%s is an IPS patch, not a ROM.\nYou should apply it to a ROM first before trying to randomize the result.
GUI.unsupportedRom=Could not load %s - it's not a supported ROM.
GUI.encryptedRom=<html>Could not load %s as it claims to be an encrypted ROM.<br />Universal Pokemon Randomizer ZX does not currently support encrypted 3DS ROMs.<br/>If you believe your ROM is actually decrypted, please try decrypting your ROM with a different tool or try using a different ROM.
GUI.encryptedRom=<html>Could not load %s as it appears to be an encrypted ROM.<br />Universal Pokemon Randomizer ZX does not currently support encrypted 3DS ROMs.<br/>If you believe your ROM is actually decrypted, please try decrypting your ROM with a different tool or try using a different ROM.
GUI.romSupportPrefix=Support:
GUI.processFailed=There was an unhandled exception trying to process your ROM.\nA log file containing some details has been saved to %s.\nPlease include this file in any bug reports you do.
GUI.processFailedNoLog=There was an unhandled exception trying to process your ROM.
Expand Down
4 changes: 2 additions & 2 deletions src/com/dabomstew/pkrandom/newgui/NewRandomizerGUI.java
Original file line number Diff line number Diff line change
Expand Up @@ -656,7 +656,7 @@ private void loadROM() {
romLoaded = true;
} catch (EncryptedROMException ex) {
JOptionPane.showMessageDialog(mainPanel,
String.format(bundle.getString("GUI.encryptedRom"), ex.getMessage()));
String.format(bundle.getString("GUI.encryptedRom"), fh.getAbsolutePath()));
} catch (Exception ex) {
attemptToLogException(ex, "GUI.loadFailed", "GUI.loadFailedNoLog", null, null);
}
Expand Down Expand Up @@ -1087,7 +1087,7 @@ private void applyGameUpdateMenuItemActionPerformed() {
romHandler.loadGameUpdate(fh.getAbsolutePath());
} catch (EncryptedROMException ex) {
JOptionPane.showMessageDialog(mainPanel,
String.format(bundle.getString("GUI.encryptedRom"), ex.getMessage()));
String.format(bundle.getString("GUI.encryptedRom"), fh.getAbsolutePath()));
}
removeGameUpdateMenuItem.setVisible(true);
romNameLabel.setText(romHandler.getROMName() + " (" + romHandler.getGameUpdateVersion() + ")");
Expand Down

0 comments on commit 164fb2e

Please sign in to comment.