esrpatch/main.c

153 lines
3.7 KiB
C

/*
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/>.
*/
#include <stdio.h>
#include <string.h>
#include "crc-itu-t.h"
#include "dvdv.h"
#define LBA_SIZE 2048
int main(int argc, char ** argv) {
FILE *iso;
unsigned char buffer[LBA_SIZE], tag_checksum;
unsigned short i, is_udf = 0;
unsigned short *desc_crc;
unsigned short *desc_crc_len;
printf("ESRPATCH v0.2 - PS2 ISO patcher for ffgriever's ESR project.\n");
printf("By: bootsector - http://www.brunofreitas.com/\n\n");
if(argc != 2) {
printf("Usage: esrpatch <path_to_iso>\n");
return 1;
}
if((iso = fopen(argv[1], "rb+")) == NULL) {
printf("Error opening ISO.\n");
return 1;
}
memset(buffer, 0, sizeof(buffer));
// Checks if ISO has an UDF descriptor
for(i = 1; i < 64; i++) {
fseek(iso, LBA_SIZE * i + 32768, SEEK_SET);
fread(buffer, LBA_SIZE, 1, iso);
// "NSR"
if(!strncmp(buffer + 1, "NSR", 3)) {
is_udf = 1;
break;
}
}
if(!is_udf) {
printf("Error: ISO doesn't contain an UDF descriptor.\n");
fclose(iso);
return 1;
}
// Checks if image is already patched
fseek(iso, 14 * LBA_SIZE, SEEK_SET);
fread(buffer, LBA_SIZE, 1, iso);
if(!strncmp(buffer + 25, "+NSR", 4)) {
printf("ISO is already patched.\n");
fclose(iso);
return 1;
}
// Backups LBA 34 into 14
fseek(iso, 34 * LBA_SIZE, SEEK_SET);
fread(buffer, LBA_SIZE, 1, iso);
fseek(iso, 14 * LBA_SIZE, SEEK_SET);
fwrite(buffer, LBA_SIZE, 1, iso);
// Backups LBA 50 into 15
fseek(iso, 50 * LBA_SIZE, SEEK_SET);
fread(buffer, LBA_SIZE, 1, iso);
fseek(iso, 15 * LBA_SIZE, SEEK_SET);
fwrite(buffer, LBA_SIZE, 1, iso);
// Updates LBA 34
fseek(iso, 34 * LBA_SIZE, SEEK_SET);
fread(buffer, LBA_SIZE, 1, iso);
// Updates new referenced LBA: Now it points to a DVD_VIDEO structure
buffer[0xBC] = 0x80;
buffer[0xBD] = 0x00;
// Calculates new checksums
desc_crc_len = (unsigned short *)(buffer + 10);
desc_crc = (unsigned short *)(buffer + 8);
*desc_crc = crc_itu_t(0, (buffer + 16), *desc_crc_len);
tag_checksum = 0;
for(i = 0; i < 4; i++)
tag_checksum += buffer[i];
for(i = 5; i < 16; i++)
tag_checksum += buffer[i];
buffer[4] = tag_checksum;
// Save modified LBA
fseek(iso, 34 * LBA_SIZE, SEEK_SET);
fwrite(buffer, LBA_SIZE, 1, iso);
// Updates LBA 50
fseek(iso, 50 * LBA_SIZE, SEEK_SET);
fread(buffer, LBA_SIZE, 1, iso);
// Updates new referenced LBA: Now it points to a DVD_VIDEO structure
buffer[0xBC] = 0x80;
buffer[0xBD] = 0x00;
desc_crc_len = (unsigned short *)(buffer + 10);
desc_crc = (unsigned short *)(buffer + 8);
*desc_crc = crc_itu_t(0, (buffer + 16), *desc_crc_len);
// Calculates new checksums
tag_checksum = 0;
for(i = 0; i < 4; i++)
tag_checksum += buffer[i];
for(i = 5; i < 16; i++)
tag_checksum += buffer[i];
buffer[4] = tag_checksum;
// Save modified LBA
fseek(iso, 50 * LBA_SIZE, SEEK_SET);
fwrite(buffer, LBA_SIZE, 1, iso);
// Writes DVD Video data @ LBA 128
fseek(iso, 128 * LBA_SIZE, SEEK_SET);
fwrite(dvdvdata, DVDVDATA_SIZE, 1, iso);
fclose(iso);
printf("Done!\n");
return 0;
}