commit 2781ab32ce207523441cbe4ecce967f408c86217
parent 03a8240a9cce607b8632178bb243a1d79f80e15e
Author: lostd <lostd@2f30.org>
Date: Mon, 10 Aug 2015 18:07:46 +0300
Include ISO LBA fixer tool by DeXT
Diffstat:
3 files changed, 351 insertions(+), 1 deletion(-)
diff --git a/selfboot/Makefile b/selfboot/Makefile
@@ -1,6 +1,6 @@
# dreamcast selfboot tools
-BINS = makeip scramble 1strdchk
+BINS = makeip scramble 1strdchk isofix
all: $(BINS)
diff --git a/selfboot/isofix.c b/selfboot/isofix.c
@@ -0,0 +1,325 @@
+/******************************************************/
+/* */
+/* ISO start LBA fixing utility */
+/* */
+/* This tool will take an ISO image with PVD pointing */
+/* to bad DR offset and add padding data so actual DR */
+/* gets located in right absolute address. */
+/* */
+/* Original boot area, PVD, SVD and VDT are copied to */
+/* the start of new, fixed ISO image. */
+/* */
+/* Supported input image formats are: 2048, 2336, */
+/* 2352 and 2056 bytes per sector. All of them are */
+/* converted to 2048 bytes per sector when writing */
+/* excluding 2056 format which is needed by Mac users.*/
+/* */
+/******************************************************/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "isofix.h"
+
+
+int main( int argc, char **argv )
+{
+ int sector_size = 2048, mode = 1;
+ long image_length, remaining_length, progress, last_pos, start_lba, i;
+ char lba_parameter = 0;
+
+ char destfname[256];
+ char string[256];
+ char buffer[4096];
+
+ struct opts_s opts = { false, false, false, false, false };
+
+ FILE *fsource, *fdest, *fboot, *fheader;
+
+
+printf("ISO LBA fixer 1.3 - (C) 2001 by DeXT\n\n");
+
+// process command line
+
+strcpy(destfname,"fixed.iso");
+
+if (argc < 2)
+ opts.askforimage = true;
+else
+ {
+ for (i = 1; i < argc; i++)
+ {
+ if (atol(argv[i]) <= 0) // not a number, or negative one
+ {
+ if (!stricmp(argv[i], "/boot"))
+ {
+ opts.extractbootonly = true;
+ if (i == 1) opts.askforimage = true;
+ }
+ else if (!stricmp(argv[i], "/header"))
+ {
+ opts.extractheaderonly = true;
+ if (i == 1) opts.askforimage = true;
+ }
+ else if (!stricmp(argv[i], "/mac"))
+ {
+ opts.macformat = true;
+ if (i == 1) opts.askforimage = true;
+ }
+ else if (!stricmp(argv[i], "/iso"))
+ {
+ opts.isoformat = true;
+ if (i == 1) opts.askforimage = true;
+ }
+ else
+ {
+ if (i == 1) strcpy(string, argv[i]);
+ else strcpy(destfname, argv[i]);
+ }
+ }
+ else lba_parameter = i;
+ }
+ }
+
+if (opts.askforimage == true)
+ {
+ printf("\nPlease enter name of image to fix (Return to exit): ");
+ gets(string);
+ if (strlen(string) == 0) exit(1);
+ }
+
+printf("Processing file: '%s'\n",string);
+
+fsource = fopen(string,"rb");
+
+if (fsource == NULL) { printf("Image not found!"); exit(1); }
+
+fseek(fsource, 0L, SEEK_END);
+image_length = ftell(fsource);
+fseek(fsource, 0L, SEEK_SET);
+
+// detect format
+
+printf("Scanning image...\n");
+
+fread(buffer, 1, 16, fsource);
+if (!memcmp(SYNC_DATA, buffer, 12)) // raw (2352)
+ {
+ sector_size = 2352;
+ switch(buffer[15])
+ {
+ case 2: mode = 2; break;
+ case 1: mode = 1; break;
+ default: { printf("Unsupported track mode (%d)", buffer[15]); exit (1); }
+ }
+ if (seek_pvd(buffer, 2352, mode, fsource) == 0) { printf("Could not find PVD!\n"); exit(1); }
+ }
+else if (seek_pvd(buffer, 2048, 1, fsource))
+ {
+ sector_size = 2048;
+ mode = 1;
+ }
+else if (seek_pvd(buffer, 2336, 2, fsource))
+ {
+ sector_size = 2336;
+ mode = 2;
+ }
+else if (seek_pvd(buffer, 2056, 2, fsource))
+ {
+ sector_size = 2056;
+ mode = 2;
+ opts.macformat = true;
+ }
+else { printf("Could not find PVD!\n"); exit(1); }
+
+if (opts.isoformat == true) opts.macformat = false;
+
+printf("sector size = %d, mode = %d\n", sector_size, mode);
+
+if (opts.extractbootonly == false && opts.extractheaderonly == false)
+ {
+ if (lba_parameter != 0)
+ start_lba = atol(argv[lba_parameter]);
+ else
+ {
+ printf("\nPlease enter starting LBA value: ");
+ gets(string);
+ start_lba = atol(string);
+ if (start_lba <= 0) { printf("Bad LBA value"); exit(1); }
+ }
+
+ printf("Creating destination file '%s'...\n",destfname);
+ fdest = fopen(destfname, "wb");
+ if (fdest == NULL) { printf("Can't open destination file!"); exit(1); }
+ }
+
+if (opts.extractheaderonly == false || (opts.extractheaderonly == true && opts.extractbootonly == true))
+ {
+ printf("Saving boot area to file 'bootfile.bin'...\n");
+ fboot = fopen("bootfile.bin", "wb");
+ }
+if (opts.extractbootonly == false || (opts.extractheaderonly == true && opts.extractbootonly == true))
+ {
+ printf("Saving ISO header to file 'header.iso'...\n");
+ fheader = fopen("header.iso", "wb");
+ }
+
+// save boot area
+
+fseek(fsource, 0L, SEEK_SET);
+for (i = 0; i < 16 ; i++)
+ {
+ sector_read(buffer, sector_size, mode, fsource);
+ if (opts.extractbootonly == false && opts.extractheaderonly == false)
+ {
+ if (opts.macformat == true) fwrite (SUB_HEADER, 8, 1, fdest);
+ fwrite(buffer, 2048, 1, fdest);
+ }
+ if (opts.extractheaderonly == false || (opts.extractheaderonly == true && opts.extractbootonly == true))
+ {
+ if (opts.macformat == true) fwrite (SUB_HEADER, 8, 1, fboot);
+ fwrite(buffer, 2048, 1, fboot);
+ }
+ if (opts.extractbootonly == false || (opts.extractheaderonly == true && opts.extractbootonly == true))
+ {
+ if (opts.macformat == true) fwrite (SUB_HEADER, 8, 1, fheader);
+ fwrite(buffer, 2048, 1, fheader);
+ }
+ }
+
+if (opts.extractheaderonly == false || (opts.extractheaderonly == true && opts.extractbootonly == true))
+ fclose(fboot);
+if (opts.extractbootonly == true && opts.extractheaderonly == false) exit(0); // boot saved, exit
+
+// seek & copy pvd etc.
+
+last_pos = ftell(fsource); // start of pvd
+
+do {
+ sector_read(buffer, sector_size, mode, fsource);
+
+ if (!memcmp(PVD_STRING, buffer, 8)) { printf("Found PVD at sector %ld\n", last_pos/sector_size); }
+ else if (!memcmp(SVD_STRING, buffer, 8)) { printf("Found SVD at sector %ld\n", last_pos/sector_size); }
+ else if (!memcmp(VDT_STRING, buffer, 8)) { printf("Found VDT at sector %ld\n", last_pos/sector_size); opts.last_vd = true; }
+ else { printf("Error: Found unknown Volume Descriptor"); exit(1); }
+
+ if (opts.extractbootonly == false && opts.extractheaderonly == false)
+ {
+ if (opts.macformat == true) fwrite (SUB_HEADER, 8, 1, fdest);
+ fwrite(buffer, 2048, 1, fdest);
+ }
+ if (opts.macformat == true) fwrite (SUB_HEADER, 8, 1, fheader);
+ fwrite(buffer, 2048, 1, fheader);
+ last_pos = ftell(fsource);
+ }
+ while (opts.last_vd == false);
+
+// add padding data to header file
+
+for(i = 0; i < (long)sizeof(buffer); i++) // clear buffer
+ buffer[i] = 0;
+
+remaining_length = 300 - (last_pos/sector_size);
+for(i = 0; i < remaining_length; i++)
+ {
+ if (opts.macformat == true) fwrite (SUB_HEADER, 8, 1, fheader);
+ fwrite(buffer, 2048, 1, fheader);
+ }
+
+fclose(fheader);
+if (opts.extractheaderonly == true) exit(0); // header saved, exit
+
+// add padding data to iso image
+
+if (last_pos > start_lba*sector_size)
+ { printf("Sorry, LBA value is too small...\nIt should be at least %d for current ISO image (probably greater)", last_pos/sector_size); exit(1); }
+if (start_lba < 11700)
+ printf("Warning! LBA value should be greater or equal to 11700 for multisession images\n");
+
+printf("Adding padding data up to start LBA value...");
+
+remaining_length = start_lba - (last_pos/sector_size);
+
+printf(" ");
+for(i = 0; i < remaining_length; i++)
+ {
+ if (!(i%512))
+ {
+ progress = i*100/remaining_length;
+ printf("\b\b\b%02d%%", progress);
+ }
+ if (opts.macformat == true) fwrite (SUB_HEADER, 8, 1, fdest);
+ if (!fwrite(buffer, 2048, 1, fdest)) { printf("\nCan't write file! (disk full?)"); exit(1); }
+ }
+printf("\b\b\b \b\b\b");
+
+printf("Done!\n");
+
+// append original iso image
+
+printf("Appending ISO image...");
+
+fseek(fsource, 0L, SEEK_SET);
+
+remaining_length = image_length/sector_size;
+
+printf(" ");
+for(i = 0; i < remaining_length; i++)
+ {
+ if (!(i%512))
+ {
+ progress = i*100/remaining_length;
+ printf("\b\b\b%02d%%", progress);
+ }
+ if (!sector_read(buffer, sector_size, mode, fsource)) { printf("\nCan't read image!"); exit(1); }
+ if (opts.macformat == true) fwrite (SUB_HEADER, 8, 1, fdest);
+ if (!fwrite(buffer, 2048, 1, fdest)) { printf("\nCan't write file! (disk full?)"); exit(1); }
+ }
+printf("\b\b\b \b\b\b");
+
+printf("Done!\n");
+
+printf("\nImage is now fixed!\n");
+
+fclose(fsource);
+fclose(fdest);
+
+return 0;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+
+// seek_pvd() will search for valid PVD in sector 16 of source image
+
+int seek_pvd(char *buffer, int sector_size, int mode, FILE *fsource)
+{
+ fseek(fsource, 0L, SEEK_SET);
+ fseek(fsource, 16*sector_size, SEEK_CUR); // boot area
+ if (sector_size == 2352) fseek(fsource, 16, SEEK_CUR); // header
+ if (mode == 2) fseek(fsource, 8, SEEK_CUR); // subheader
+ fread(buffer, 1, 8, fsource);
+ if (!memcmp(PVD_STRING, buffer, 8)) return 1;
+
+return 0;
+}
+
+// sector_read() will put user data into buffer no matter the source format
+
+int sector_read(char *buffer, int sector_size, int mode, FILE *fsource)
+{
+int status;
+
+ if (sector_size == 2352) fseek(fsource, 16, SEEK_CUR); // header
+ if (mode == 2) fseek(fsource, 8, SEEK_CUR); // subheader
+ status = fread(buffer, 2048, 1, fsource);
+ if (sector_size >= 2336)
+ {
+ fseek(fsource, 280, SEEK_CUR);
+ if (mode == 1) fseek(fsource, 8, SEEK_CUR);
+ }
+
+return status;
+}
+
diff --git a/selfboot/isofix.h b/selfboot/isofix.h
@@ -0,0 +1,25 @@
+#ifdef __linux__
+ #define stricmp strcasecmp
+#endif
+
+
+typedef enum bool_t { false, true } bool;
+
+struct opts_s {
+ bool last_vd;
+ bool askforimage;
+ bool extractbootonly;
+ bool extractheaderonly;
+ bool macformat;
+ bool isoformat;
+ };
+
+static const char PVD_STRING[8] = { 0x01, 0x43, 0x44, 0x30, 0x30, 0x31, 0x01, 0 }; //"\x01" "CD001" "\x01" "\0";
+static const char SVD_STRING[8] = { 0x02, 0x43, 0x44, 0x30, 0x30, 0x31, 0x01, 0 }; //"\x02" "CD001" "\x01" "\0";
+static const char VDT_STRING[8] = { 0xff, 0x43, 0x44, 0x30, 0x30, 0x31, 0x01, 0 }; //"\xFF" "CD001" "\x01" "\0";
+static const char SYNC_DATA[12] = { 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0 };
+static const char SUB_HEADER[8] = { 0, 0, 0x08, 0, 0, 0, 0x08, 0 };
+
+int seek_pvd(char *buffer, int sector_size, int mode, FILE *fsource);
+int sector_read(char *buffer, int sector_size, int mode, FILE *fsource);
+