ESRPatchJava/src/main/java/esrpatchjava/ESRPatch.java

303 lines
6.7 KiB
Java

/*
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package esrpatchjava;
import java.io.*;
import java.util.Arrays;
import java.util.List;
import javax.swing.*;
public class ESRPatch {
public static final int LBA_SIZE = 2048;
public static final int PATCH_OK = 0;
public static final int ALREADY_PATCHED = 1;
public static final int ERROR_PATCHING = 2;
public static final int NOT_UDF_ISO = 3;
public static final int NOT_PATCHED = 4;
private static RandomAccessFile iso;
private static final byte[] buffer = new byte[LBA_SIZE];
public static int apply(String fileName) {
byte[] b;
int desc_crc, desc_crc_len, tag_checksum;
try {
iso = new RandomAccessFile(fileName, "rw");
// Checks if image is a UDF ISO
if(!isUDFISO()) {
iso.close();
return NOT_UDF_ISO;
}
// Checks if image is already patched
if(isAlreadyPatched()) {
iso.close();
return ALREADY_PATCHED;
}
// Backups LBA 34 into 14
iso.seek(34 * LBA_SIZE);
iso.read(buffer);
iso.seek(14 * LBA_SIZE);
iso.write(buffer);
// Backups LBA 50 into 15
iso.seek(50 * LBA_SIZE);
iso.read(buffer);
iso.seek(15 * LBA_SIZE);
iso.write(buffer);
// Updates LBA 34
iso.seek(34 * LBA_SIZE);
iso.read(buffer);
// Updates new referenced LBA: Now it points to a DVD_VIDEO structure
buffer[0xBC] = (byte) 0x80;
buffer[0xBD] = (byte) 0x00;
// Calculates new checksums
desc_crc_len = (((int)buffer[11] & 0xFF) << 8 & 0xFF00)+ ((int) buffer[10] & 0xFF);
b = new byte[desc_crc_len];
System.arraycopy(buffer, 16, b, 0, desc_crc_len);
desc_crc = CRC.CRC16CCITT(b);
buffer[8] = (byte) (desc_crc & 0xFF);
buffer[9] = (byte) ((desc_crc >> 8) & 0xFF);
tag_checksum = 0;
for(int i = 0; i < 16; i++) {
if(i != 4) {
tag_checksum += buffer[i];
}
}
buffer[4] = (byte) tag_checksum;
// Save modified LBA
iso.seek(34 * LBA_SIZE);
iso.write(buffer);
// Updates LBA 50
iso.seek(50 * LBA_SIZE);
iso.read(buffer);
// Updates new referenced LBA: Now it points to a DVD_VIDEO structure
buffer[0xBC] = (byte) 0x80;
buffer[0xBD] = (byte) 0x00;
// Calculates new checksums
desc_crc_len = (((int)buffer[11] & 0xFF) << 8 & 0xFF00)+ ((int) buffer[10] & 0xFF);
b = new byte[desc_crc_len];
System.arraycopy(buffer, 16, b, 0, desc_crc_len);
desc_crc = CRC.CRC16CCITT(b);
buffer[8] = (byte) (desc_crc & 0xFF);
buffer[9] = (byte) ((desc_crc >> 8) & 0xFF);
tag_checksum = 0;
for(int i = 0; i < 16; i++) {
if(i != 4) {
tag_checksum += buffer[i];
}
}
buffer[4] = (byte) tag_checksum;
// Saves modified LBA
iso.seek(50 * LBA_SIZE);
iso.write(buffer);
// Writes esrpatchjava.DVDV data
DVDV.write(iso);
return PATCH_OK;
} catch(Exception ex) {
ex.printStackTrace();
return ERROR_PATCHING;
} finally {
try {
iso.close();
}
catch(Exception ignore) {}
}
}
private static boolean isAlreadyPatched() {
try {
iso.seek(14 * LBA_SIZE);
iso.read(buffer);
// Checks for "+NSR" magic string
if(buffer[25] == (byte) 0x2B && buffer[26] == (byte) 0x4E && buffer[27] == (byte) 0x53 && buffer[28] == (byte) 0x52) {
return true;
}
} catch(Exception ex) {
return false;
}
return false;
}
private static boolean isUDFISO() {
try {
for(int i = 1; i < 64; i++) {
iso.seek(LBA_SIZE * i + 32768);
iso.read(buffer);
// "NSR"
if (buffer[1] == (byte) 0x4E && buffer[2] == (byte) 0x53 && buffer[3] == (byte) 0x52)
return true;
}
}
catch (Exception ex) {
return false;
}
return false;
}
public static int apply(List files, JFrame parent) {
StringBuilder results = new StringBuilder();
for (Object file : files) {
File f = new File(file.toString());
if (f.isFile() && f.exists()) {
results.append(f.getName());
switch (apply(f.getPath())) {
case ESRPatch.ALREADY_PATCHED:
results.append(" - ISO is already patched!\n");
break;
case ESRPatch.ERROR_PATCHING:
results.append(" - Error trying to patch ISO!\n");
break;
case ESRPatch.PATCH_OK:
results.append(" - ISO patched successfully! :)\n");
break;
case ESRPatch.NOT_UDF_ISO:
results.append(" - Error: ISO doesn't contain UDF descriptor!\n");
break;
}
}
}
JOptionPane.showMessageDialog(parent, results.toString(), "Results:", JOptionPane.INFORMATION_MESSAGE);
return 0;
}
public static int unPatch(String fileName) {
try {
iso = new RandomAccessFile(fileName, "rw");
// Checks if image is a UDF ISO
if(!isUDFISO()) {
iso.close();
return NOT_UDF_ISO;
}
// Checks if image is not patched
if(!isAlreadyPatched()) {
iso.close();
return NOT_PATCHED;
}
// Restore LBA 14 into 34
iso.seek(14 * LBA_SIZE);
iso.read(buffer);
iso.seek(34 * LBA_SIZE);
iso.write(buffer);
// Restore LBA 15 into 50
iso.seek(15 * LBA_SIZE);
iso.read(buffer);
iso.seek(50 * LBA_SIZE);
iso.write(buffer);
// Clear backups
Arrays.fill(buffer, (byte) 0);
iso.seek(14 * LBA_SIZE);
iso.write(buffer);
iso.seek(15 * LBA_SIZE);
iso.write(buffer);
return PATCH_OK;
} catch(Exception ex) {
ex.printStackTrace();
return ERROR_PATCHING;
}
finally {
try {
iso.close();
}
catch(Exception ignore) {}
}
}
public static int unPatch(List files, JFrame parent) {
StringBuilder results = new StringBuilder();
for (Object file : files) {
File f = new File(file.toString());
if (f.isFile() && f.exists()) {
results.append(f.getName());
switch (unPatch(f.getPath())) {
case ESRPatch.NOT_PATCHED:
results.append(" - ISO is not patched!\n");
break;
case ESRPatch.ERROR_PATCHING:
results.append(" - Error trying to unpatch ISO!\n");
break;
case ESRPatch.PATCH_OK:
results.append(" - ISO unpatched successfully! :)\n");
break;
case ESRPatch.NOT_UDF_ISO:
results.append(" - Error: ISO doesn't contain UDF descriptor!\n");
break;
}
}
}
JOptionPane.showMessageDialog(parent, results.toString(), "Results:", JOptionPane.INFORMATION_MESSAGE);
return 0;
}
}