summaryrefslogtreecommitdiff
path: root/cdutils.cpp
diff options
context:
space:
mode:
authorPixel <Pixel>2002-05-04 17:53:08 +0000
committerPixel <Pixel>2002-05-04 17:53:08 +0000
commit24fb33726eca4e8c5a88797adc9c17f4d541f543 (patch)
tree72b385bd9e880e699e43c7db3ba12817f0e8e45e /cdutils.cpp
Initial revision
Diffstat (limited to 'cdutils.cpp')
-rw-r--r--cdutils.cpp634
1 files changed, 634 insertions, 0 deletions
diff --git a/cdutils.cpp b/cdutils.cpp
new file mode 100644
index 0000000..d697b52
--- /dev/null
+++ b/cdutils.cpp
@@ -0,0 +1,634 @@
+/*
+ * PSX-Tools Bundle Pack
+ * Copyright (C) 2002 Nicolas "Pixel" Noble
+ *
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <malloc.h>
+#include "cdutils.h"
+#include "fileutils.h"
+#include "generic.h"
+
+FILE * ppf_file = 0;
+int pt1 = -1, pt2 = -1, snum = 0, ptl = 0, root = 0;
+
+long sec_sizes[5] = {0, 2048, 2336, 2048, 2324};
+long sec_offsts[5] = {0, 16, 16, 24, 24};
+char * sec_modes[5] = {"MODE 0 (no mode)", "MODE 1", "MODE 2", "MODE 2 FORM 1", "MODE 2 FORM 2"};
+
+struct DirEntry rootDir;
+
+unsigned char from_BCD(unsigned char x) {
+ return ((x & 0xff) + ((x & 0xff00) >> 4) * 10);
+}
+
+unsigned char to_BCD(unsigned char x) {
+ return ((x / 10) << 4) | (x % 10);
+}
+
+int is_valid_BCD(unsigned char x) {
+ return (((x & 15) < 10) && ((x >> 4) < 10));
+}
+
+unsigned long from_MSF(unsigned long msf, unsigned long start) {
+ unsigned char
+ f = from_BCD(msf & 0xff),
+ s = from_BCD((msf >> 8) & 0xff),
+ m = from_BCD((msf >> 16) & 0xff);
+
+ return (m * 60 + s) * 75 + f - start;
+}
+
+FILE * open_ppf(char * ppf, FILE * iso, char * comment) {
+ int i, l;
+ char buffer[1024];
+
+ if (!(ppf_file = fopen(ppf, "w")))
+ return ppf_file;
+ fwrite("PPF20\001", 1, 6, ppf_file);
+
+ l = strlen(comment);
+ if (l >= 50) {
+ fwrite(comment, 1, 50, ppf_file);
+ } else {
+ char * t = " ";
+ fwrite(comment, 1, l, ppf_file);
+ for (i = l; i < 50; i++) {
+ fwrite(t, 1, 1, ppf_file);
+ }
+ }
+
+ l = filesize(iso);
+ fwrite(&l, 1, 4, ppf_file);
+
+ fseek(iso, 0x9320, SEEK_SET);
+ fread(buffer, 1, 1024, iso);
+ fwrite(buffer, 1, 1024, ppf_file);
+ return ppf_file;
+}
+
+void write_ppf(unsigned char * old_sec, unsigned char * new_sec, int sec_num) {
+ int i, l = 0, o;
+
+ for (i = 0; i < 2352; i++) {
+ if (old_sec[i] == new_sec[i]) {
+ if (l != 0) {
+ o = 2352 * sec_num + i;
+ fwrite(&o, 1, 4, ppf_file);
+ fwrite(&l, 1, 1, ppf_file);
+ fwrite(new_sec + i - l - 1, 1, l, ppf_file);
+ l = 0;
+ }
+ } else {
+ l++;
+ if (l == 255) {
+ o = 2352 * sec_num + i;
+ fwrite(&o, 1, 4, ppf_file);
+ fwrite(&l, 1, 1, ppf_file);
+ fwrite(new_sec + i - 255, 1, 255, ppf_file);
+ l = 0;
+ }
+ }
+ }
+}
+
+char * format_date(unsigned char * input) {
+ static char output[26];
+
+ memcpy(output, input + 6, 2);
+ output[2] = '/';
+ memcpy(output + 3, input + 4, 2);
+ output[5] = '/';
+ memcpy(output + 6, input, 4);
+ output[10] = ' ';
+ memcpy(output + 11, input + 8, 2);
+ output[13] = ':';
+ memcpy(output + 14, input + 10, 2);
+ output[16] = ':';
+ memcpy(output + 17, input + 12, 2);
+ output[19] = '.';
+ memcpy(output + 20, input + 14, 2);
+ sprintf(output + 22, "%+3.1f", ((float) (*(((char *)input) + 16))) / 4);
+
+ return output;
+}
+
+unsigned short int swap_word(unsigned short int i) {
+ return (i >> 8) | (i << 8);
+}
+
+unsigned long int swap_dword(unsigned long int i) {
+ return (i >> 24) | ((i >> 8) & 0x0000ff00) | ((i << 8) & 0x00ff0000) | (i << 24);
+}
+
+void sector_seek(FILE * f_iso, long sector) {
+ long curpos;
+
+ curpos = (2352 * (long) sector);
+ fseek(f_iso, curpos, SEEK_SET);
+}
+
+int guess_type(FILE * f_iso, int number) {
+ unsigned char header[24];
+
+ if (number >= 0) {
+ sector_seek(f_iso, number);
+ }
+
+ fread(header, 1, 24, f_iso);
+ fseek(f_iso, -24, SEEK_CUR);
+ if (header[15] == 1) {
+ return MODE_1;
+ } else if (header[15] == 2) {
+ if (*((unsigned long *) &(header[16])) == *((unsigned long *) &(header[20]))) {
+ if ((header[16] == 0) && (header[17] == 0) && (header[19] == 0)) {
+ if (header[18] & 0x20) {
+ return MODE_2_FORM_2;
+ } else {
+ return MODE_2_FORM_1;
+ }
+ }
+ }
+ return MODE_2;
+ }
+
+ return MODE_0;
+}
+
+long read_sector(FILE * f_iso, unsigned char * buffer, char type, int number) {
+ if (number >= 0) {
+ sector_seek(f_iso, number);
+ }
+
+ if (type == GUESS) {
+ type = guess_type(f_iso, number);
+ }
+
+ fseek(f_iso, sec_offsts[type], SEEK_CUR);
+ fread(buffer, 1, sec_sizes[type], f_iso);
+ fseek(f_iso, 2352 - sec_offsts[type] - sec_sizes[type], SEEK_CUR);
+ return sec_sizes[type];
+}
+
+void read_datas(FILE * f_iso, unsigned char * buffer, int type, int number, long size) {
+ unsigned char sector[2352];
+ int i, n, reste;
+
+ if (type == GUESS) {
+ type = guess_type(f_iso, number);
+ }
+
+ n = size / sec_sizes[type];
+ reste = size - n * sec_sizes[type];
+
+ sector_seek(f_iso, number);
+ for (i = 0; i < n; i++) {
+ read_sector(f_iso, buffer + i * sec_sizes[type], type);
+ }
+
+ if (reste) {
+ read_sector(f_iso, sector, type);
+ bcopy((char *) sector, (char *) (buffer + n * sec_sizes[type]), reste);
+ }
+}
+
+void read_file(FILE * f_iso, FILE * file, char type, int number, long size) {
+ unsigned char sector[2352];
+ int i, n, reste;
+
+ if (type == GUESS) {
+ type = guess_type(f_iso, number);
+ }
+
+ n = size / sec_sizes[type];
+ reste = size - n * sec_sizes[type];
+
+ sector_seek(f_iso, number);
+ for (i = 0; i < n; i++) {
+ read_sector(f_iso, sector, type);
+ fwrite(sector, 1, sec_sizes[type], file);
+ }
+
+ if (reste) {
+ read_sector(f_iso, sector, type);
+ fwrite(sector, 1, reste, file);
+ }
+}
+
+void write_sector(FILE * f_iso_r, FILE * f_iso_w, unsigned char * buffer, char type, int number) {
+ unsigned char old_sector[2352], new_sector[2352];
+
+ if (type == GUESS) {
+ type = guess_type(f_iso_r, number);
+ }
+
+ if (number >= 0) {
+ sector_seek(f_iso_r, number);
+ sector_seek(f_iso_w, number);
+ }
+
+ fread(old_sector, 1, 2352, f_iso_r);
+
+ minute = old_sector[12];
+ second = old_sector[13];
+ frame = old_sector[14];
+
+ bcopy((char *) old_sector, (char *) new_sector, 2532);
+ bcopy((char *) buffer, (char *) new_sector + sec_offsts[type], sec_sizes[type]);
+
+ do_encode_L2(new_sector, type, 0);
+ if (ppf_file < 0) {
+ fwrite(new_sector, 1, 2352, f_iso_w);
+ } else {
+ write_ppf(old_sector, new_sector, number);
+ }
+}
+
+void write_datas(FILE * f_iso_r, FILE * f_iso_w, unsigned char * buffer, char type, int number, long size) {
+ long nbsectors, i;
+ unsigned char sector[2352];
+
+ if (type == GUESS) {
+ type = guess_type(f_iso_r, number);
+ }
+
+ if (number >= 0) {
+ sector_seek(f_iso_r, number);
+ sector_seek(f_iso_w, number);
+ }
+
+ nbsectors = size / sec_sizes[type];
+
+ for (i = 0; i < nbsectors; i++) {
+ write_sector(f_iso_r, f_iso_w, buffer + i * sec_sizes[type], type, number + i);
+ }
+
+ if (size % sec_sizes[type]) {
+ memset(sector, 0, 2352);
+ bcopy((char *) (buffer + i * sec_sizes[type]), (char *) sector, size % sec_sizes[type]);
+ write_sector(f_iso_r, f_iso_w, sector, type, number + i);
+ }
+}
+
+void write_file(FILE * f_iso_r, FILE * f_iso_w, FILE * file, char type, int number) {
+ long size, nbsectors, i;
+ unsigned char buffer[2352];
+
+ if (type == GUESS) {
+ type = guess_type(f_iso_r, number);
+ }
+
+ if (number >= 0) {
+ sector_seek(f_iso_r, number);
+ sector_seek(f_iso_w, number);
+ }
+
+ size = filesize(file);
+ nbsectors = size / sec_sizes[type];
+
+ if (size % sec_sizes[type]) {
+ nbsectors++;
+ }
+
+ for (i = 0; i < nbsectors; i++) {
+ memset(buffer, 0, 2352);
+ fread(buffer, 1, sec_sizes[type], file);
+ write_sector(f_iso_r, f_iso_w, buffer, type);
+ }
+}
+
+void show_head_entry(void) {
+ printm(M_BARE, "Sector - Size - Date - Time - Flags - Name\n");
+}
+
+int show_entry(struct DirEntry * dir) {
+ char pbuf[200];
+ if (!dir->R) {
+ return 1;
+ }
+
+ strncpy(pbuf, (char *) &(dir->id), dir->N);
+ pbuf[dir->N] = 0;
+
+ printm(M_BARE, "%6i - %8i - %2i/%02i/%02i - %2i:%02i:%02i%+03.1f - %c%c%c%c%c%c%c%c - %s\n",
+ dir->Sector, dir->Size, dir->Day, dir->Month, dir->Year, dir->Hour, dir->Minute, dir->Second, ((float) dir->Offset) / 4,
+ dir->Flags & 1 ? 'H' : '-', dir->Flags & 2 ? 'D' : '-', dir->Flags & 4 ? 'A' : '-', dir->Flags & 8 ? 'R' : '-',
+ dir->Flags & 16 ? 'P' : '-', dir->Flags & 32 ? '1' : '-', dir->Flags & 64 ? '1' : '-', dir->Flags & 128 ? 'C' : '-', pbuf);
+ return dir->R;
+}
+
+int show_dir(FILE * f_iso, struct DirEntry * dir) {
+ unsigned int ptr;
+ unsigned char * buffer;
+
+ if (!(dir->Flags & 2)) {
+ return 0;
+ }
+
+ buffer = (unsigned char *) malloc(dir->Size);
+ read_datas(f_iso, buffer, GUESS, dir->Sector, dir->Size);
+
+ ptr = 0;
+ while(ptr < dir->Size) {
+ ptr += show_entry((struct DirEntry *) &(buffer[ptr]));
+ }
+
+ free(buffer);
+ return 1;
+}
+
+struct DirEntry find_dir_entry(FILE * f_iso, struct DirEntry * dir, char * name) {
+ unsigned int ptr, size;
+ unsigned char * buffer;
+ struct DirEntry r = {0, 0, 0, 0, 0};
+
+ if (!(dir->Flags & 2)) {
+ return r;
+ }
+
+ buffer = (unsigned char *) malloc(size = dir->Size);
+ read_datas(f_iso, buffer, GUESS, dir->Sector, dir->Size);
+
+ ptr = 0;
+ while(ptr < size) {
+ dir = (struct DirEntry *) &(buffer[ptr]);
+ if (!dir->R) {
+ ptr++;
+ } else {
+ if (!strncmp(name, (char *) &(dir->id), dir->N)) {
+ r = *dir;
+ }
+ ptr += dir->R;
+ }
+ }
+
+ free(buffer);
+ return r;
+}
+
+struct DirEntry * find_dir_entry(FILE * f_iso, unsigned char ** bufout, struct DirEntry * dir, char * name) {
+ unsigned int ptr, size;
+ unsigned char * buffer;
+ struct DirEntry * rdir = 0;
+ *bufout = 0;
+
+ if (!(dir->Flags & 2)) {
+ return 0;
+ }
+
+ buffer = (unsigned char *) malloc(size = dir->Size);
+ read_datas(f_iso, buffer, GUESS, dir->Sector, dir->Size);
+
+ ptr = 0;
+ while(ptr < size) {
+ dir = (struct DirEntry *) &(buffer[ptr]);
+ if (!dir->R) {
+ ptr++;
+ } else {
+ if (!strncmp(name, (char *) &(dir->id), dir->N)) {
+ rdir = dir;
+ }
+ ptr += dir->R;
+ }
+ }
+
+ if (rdir->R) {
+ *bufout = buffer;
+ } else {
+ free(buffer);
+ }
+ return rdir;
+}
+
+int show_iso_infos(FILE * f_iso) {
+ unsigned char buffer[2048];
+ char pbuff[130];
+ short int s, nogood = 0;
+
+ read_sector(f_iso, buffer, GUESS, 16);
+
+ printm(M_BARE, "Sector guessed mode : %s\n", sec_modes[guess_type(f_iso, 16)]);
+ printm(M_BARE, "offset-size-info : contents\n");
+ printm(M_BARE, " 0 - 1- 1 : %i\n", buffer[0]);
+ memcpy(pbuff, buffer + 1, 5);
+ pbuff[5] = 0;
+ printm(M_BARE, " 1 - 5-`CD001' : %s\n", pbuff);
+ printm(M_BARE, " 6 - 2- 1 : %i\n", s = *((short int *) &(buffer[6])));
+ printm(M_BARE, "(*this was the signature*)\n");
+ if (buffer[0] != 1) nogood = 1;
+ if (strcmp(pbuff, "CD001")) nogood = 1;
+ if (s != 1) nogood = 1;
+
+ if (nogood) {
+ printm(M_BARE, "Not a valid iso9660 file.\n");
+ return 0;
+ }
+
+ memcpy(pbuff, buffer + 8, 32);
+ pbuff[32] = 0;
+ printm(M_BARE, " 8 - 32- SYSID : %s\n", pbuff);
+ memcpy(pbuff, buffer + 40, 32);
+ pbuff[32] = 0;
+ printm(M_BARE, " 40 - 32- VOLID : %s\n", pbuff);
+ printm(M_BARE, " 80 - 8- SNum : %li\n", *((long int *) &(buffer[80])));
+ printm(M_BARE, " 120 - 4- VOLSiz : %i\n", *((short int *) &(buffer[120])));
+ printm(M_BARE, " 124 - 4- VOLNum : %i\n", *((short int *) &(buffer[124])));
+ printm(M_BARE, " 128 - 4- SSize : %i\n", *((short int *) &(buffer[128])));
+ printm(M_BARE, " 132 - 8- PSize : %li\n", *((long int *) &(buffer[132])));
+ printm(M_BARE, " 140 - 4- 1SLPath: %i\n", *((short int *) &(buffer[140])));
+ printm(M_BARE, " 144 - 4- 2SLPath: %i\n", *((short int *) &(buffer[144])));
+ printm(M_BARE, " 148 - 4- 1SBPath: %i\n", swap_dword(*((short int *) &(buffer[148]))));
+ printm(M_BARE, " 152 - 4- 2SBPath: %i\n", swap_dword(*((short int *) &(buffer[152]))));
+ memcpy(pbuff, buffer + 190, 128);
+ pbuff[128] = 0;
+ printm(M_BARE, " 190 - 128- VStId : %s\n", pbuff);
+ memcpy(pbuff, buffer + 318, 128);
+ pbuff[128] = 0;
+ printm(M_BARE, " 318 - 128- PubId : %s\n", pbuff);
+ memcpy(pbuff, buffer + 446, 128);
+ pbuff[128] = 0;
+ printm(M_BARE, " 446 - 128- DPrId : %s\n", pbuff);
+ memcpy(pbuff, buffer + 574, 128);
+ pbuff[128] = 0;
+ printm(M_BARE, " 574 - 128- AppId : %s\n", pbuff);
+ memcpy(pbuff, buffer + 702, 37);
+ pbuff[37] = 0;
+ printm(M_BARE, " 702 - 37- CpyFile: %s\n", pbuff);
+ memcpy(pbuff, buffer + 739, 37);
+ pbuff[37] = 0;
+ printm(M_BARE, " 739 - 37- AbsFile: %s\n", pbuff);
+ memcpy(pbuff, buffer + 776, 37);
+ pbuff[37] = 0;
+ printm(M_BARE, " 776 - 37- BibFile: %s\n", pbuff);
+ printm(M_BARE, " 813 - 17- DTCreat: %s\n", format_date(&buffer[813]));
+ printm(M_BARE, " 830 - 17- DTModif: %s\n", format_date(&buffer[830]));
+ printm(M_BARE, " 847 - 17- DTExpir: %s\n", format_date(&buffer[847]));
+ printm(M_BARE, " 864 - 17- DTEffec: %s\n", format_date(&buffer[864]));
+
+ printm(M_BARE, "Root record:\n");
+ show_head_entry();
+ show_entry((DirEntry *) &(buffer[156]));
+
+ return 1;
+}
+
+int get_iso_infos(FILE * f_iso) {
+ unsigned char buffer[2048];
+ char pbuff[130];
+ short int s, nogood = 0;
+
+ read_sector(f_iso, buffer, GUESS, 16);
+
+ memcpy(pbuff, buffer + 1, 5);
+ pbuff[5] = 0;
+
+ s = *((short int *) &(buffer[6]));
+ if (buffer[0] != 1) nogood = 1;
+ if (strcmp(pbuff, "CD001")) nogood = 1;
+ if (s != 1) nogood = 1;
+
+ if (nogood) {
+ printm(M_ERROR, "Not a valid iso9660 file.\n");
+ return 0;
+ }
+
+ pt1 = *((short int *) &(buffer[140]));
+ pt2 = *((short int *) &(buffer[144]));
+ snum = *((int *) &(buffer[80]));
+ ptl = *((long int *) &(buffer[132]));
+ rootDir = *((struct DirEntry *) &(buffer[156]));
+ return 1;
+}
+
+int get_pt_infos(FILE * f_iso) {
+ unsigned char * buffer;
+
+ if ((pt1 <= 0) && (pt2 <= 0))
+ if (!get_iso_infos(f_iso))
+ return 0;
+
+ if ((!pt1) & (!pt2)) {
+ printm(M_ERROR, "No path table defined.\n");
+ return 0;
+ }
+
+ buffer = (unsigned char *) malloc(ptl);
+ read_datas(f_iso, buffer, GUESS, !pt1 ? pt2 : pt1, ptl);
+
+ if (buffer[0] == 1)
+ if (buffer[1] == 0)
+ if (buffer[6] == 1)
+ if (buffer[7] == 0)
+ if (buffer[8] == 0)
+ if (buffer[9] == 0)
+ root = *((unsigned long int *) &(buffer[2]));
+
+ free(buffer);
+ return root ? 1 : 0;
+}
+
+int show_pt_infos(FILE * f_iso) {
+ unsigned char * buffer;
+ char pbuf[100];
+ int i, ptr;
+
+ if ((pt1 <= 0) && (pt2 <= 0))
+ if (!get_iso_infos(f_iso))
+ return 0;
+
+ if ((!pt1) & (!pt2)) {
+ printm(M_ERROR, "No path table defined.\n");
+ return 0;
+ }
+
+ buffer = (unsigned char *) malloc(ptl);
+ read_datas(f_iso, buffer, GUESS, !pt1 ? pt2 : pt1, ptl);
+
+ printm(M_BARE, "node^paren@sector : name\n");
+ for (ptr = 0, i = 1; buffer[ptr]; ptr += ptr & 1, i++) {
+ strncpy(pbuf, (char *) &(buffer[8 + ptr]), buffer[ptr]);
+ pbuf[buffer[ptr]] = 0;
+ printm(M_BARE, "%3i ^ %3i @ %6i: %s\n", i, *((unsigned short *) &(buffer[6 + ptr])), *((unsigned long *) &(buffer[2 + ptr])), pbuf);
+ ptr += 8 + buffer[ptr];
+ }
+
+ free(buffer);
+ return 1;
+}
+
+struct DirEntry find_path(FILE * f_iso, char * path) {
+ char ** pts = split(path, '/');
+ struct DirEntry dir = {0, 0, 0, 0, 0};
+
+ if ((pt1 <= 0) && (pt2 <= 0))
+ if (!get_iso_infos(f_iso))
+ return dir;
+
+ if ((!pt1) & (!pt2)) {
+ printm(M_ERROR, "No path table defined.\n");
+ return dir;
+ }
+
+ if (!**pts)
+ pts++;
+
+ for (dir = rootDir; *pts; pts++) {
+ if (!strlen(*pts))
+ continue;
+ dir = find_dir_entry(f_iso, &dir, *pts);
+ if (!dir.R)
+ return dir;
+ }
+
+ return dir;
+}
+
+struct DirEntry find_parent(FILE * f_iso, char * path) {
+ char ** pts, * p;
+ struct DirEntry dir = {0, 0, 0, 0, 0};
+
+ if ((p = strchr(path, '/'))) {
+ *p = 0;
+ }
+ if (!*path) {
+ return rootDir;
+ }
+ pts = split(path, '/');
+
+ if ((pt1 <= 0) && (pt2 <= 0))
+ if (!get_iso_infos(f_iso))
+ return dir;
+
+ if ((!pt1) & (!pt2)) {
+ printm(M_ERROR, "No path table defined.\n");
+ return dir;
+ }
+
+ if (!**pts)
+ pts++;
+
+ for (dir = rootDir; *pts; pts++) {
+ if (!strlen(*pts))
+ continue;
+ dir = find_dir_entry(f_iso, &dir, *pts);
+ if (!dir.R)
+ return dir;
+ }
+
+ return dir;
+}