mirror of https://github.com/PCSX2/pcsx2.git
692 lines
20 KiB
C
692 lines
20 KiB
C
/* isofile.c
|
|
* Copyright (C) 2002-2005 PCSX2 Team
|
|
*
|
|
* 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
|
|
*
|
|
* PCSX2 members can be contacted through their website at www.pcsx2.net.
|
|
*/
|
|
|
|
#include <stddef.h> // NULL
|
|
#include <stdlib.h> // malloc()
|
|
#include <sys/types.h> // off64_t
|
|
|
|
#ifndef __LINUX__
|
|
#ifdef __linux__
|
|
#define __LINUX__
|
|
#endif /* __linux__ */
|
|
#endif /* No __LINUX__ */
|
|
#define CDVDdefs
|
|
#include "PS2Edefs.h"
|
|
|
|
#include "logfile.h"
|
|
#include "multifile.h"
|
|
#include "isocompress.h"
|
|
#include "actualfile.h"
|
|
#include "imagetype.h"
|
|
#include "toc.h"
|
|
#include "ecma119.h"
|
|
#include "isofile.h"
|
|
|
|
const char *isofileext[] =
|
|
{
|
|
".iso",
|
|
".bin",
|
|
".img",
|
|
NULL
|
|
};
|
|
const char *cdname = "CD-XA001\0";
|
|
const char *playstationid = "PLAYSTATION\0";
|
|
// const char ps1/2name?
|
|
// Internal functions
|
|
void IsoNameStripExt(struct IsoFile *isofile)
|
|
{
|
|
int tempext;
|
|
int tempnamepos;
|
|
int tempextpos;
|
|
|
|
tempext = 0;
|
|
while (isofileext[tempext] != NULL)
|
|
{
|
|
tempextpos = 0;
|
|
while (*(isofileext[tempext] + tempextpos) != 0) tempextpos++;
|
|
tempnamepos = isofile->namepos;
|
|
while ((tempnamepos > 0) && (tempextpos > 0) &&
|
|
(isofile->name[tempnamepos - 1] == *(isofileext[tempext] + tempextpos - 1)))
|
|
{
|
|
tempnamepos--;
|
|
tempextpos--;
|
|
} // ENDWHILE- Comparing one extension to the end of the file name
|
|
if (tempextpos == 0)
|
|
{
|
|
isofile->namepos = tempnamepos; // Move name pointer in front of ext.
|
|
tempext = 0; // ... and test the list all over again.
|
|
}
|
|
else
|
|
{
|
|
tempext++; // Next ext in the list to test...
|
|
} // ENDIF- Did we find a match?
|
|
} // ENDWHILE- looking through extension list
|
|
} // END IsoNameStripExt()
|
|
|
|
// External functions
|
|
struct IsoFile *IsoFileOpenForRead(const char *filename)
|
|
{
|
|
struct IsoFile *newfile;
|
|
int retval;
|
|
int i;
|
|
char tempblock[2448];
|
|
struct tocTN toctn;
|
|
struct tocTD toctd;
|
|
// union {
|
|
// struct ECMA119PrimaryVolume vol;
|
|
// char ch[sizeof(struct ECMA119PrimaryVolume)];
|
|
// } *volcheck;
|
|
union
|
|
{
|
|
struct ECMA119PrimaryVolume *vol;
|
|
char *ch;
|
|
} volcheck;
|
|
newfile = NULL;
|
|
if (filename == NULL) return(NULL);
|
|
#ifdef VERBOSE_FUNCTION_ISOFILE
|
|
PrintLog("CDVD isofile: IsoFileOpenForRead(%s)", filename);
|
|
#endif /* VERBOSE_FUNCTION_ISOFILE */
|
|
newfile = (struct IsoFile *) malloc(sizeof(struct IsoFile));
|
|
if (newfile == NULL) return(NULL);
|
|
|
|
newfile->sectorpos = 0;
|
|
newfile->openforread = 1; // Read-only ISO
|
|
newfile->filebytepos = 0;
|
|
newfile->filesectorpos = 0;
|
|
newfile->blocksize = 0; // Flags as non-detected yet (Compress vs. Image)
|
|
newfile->tabledata = NULL;
|
|
newfile->namepos = 0;
|
|
while ((newfile->namepos < 255) &&
|
|
(*(filename + newfile->namepos) != 0))
|
|
{
|
|
newfile->name[newfile->namepos] = *(filename + newfile->namepos);
|
|
newfile->namepos++;
|
|
} // ENDWHILE- copying the file name in...
|
|
newfile->name[newfile->namepos] = 0; // And 0-terminate.
|
|
IsoNameStripExt(newfile); // Ex: -I00.Z[.bin]
|
|
// File Compression name detection
|
|
newfile->compress = IsoNameStripCompress(newfile); // Ex: -I00.bin[.Z]
|
|
newfile->compresspos = newfile->namepos;
|
|
// Test File name compression
|
|
retval = -1;
|
|
if (newfile->compress > 0)
|
|
{
|
|
retval = CompressOpenForRead(newfile);
|
|
if (retval == -1) CompressClose(newfile);
|
|
} // ENDIF- Have a compression type hint? Test it out
|
|
|
|
if (retval == -1)
|
|
{
|
|
newfile->compress = 5;
|
|
while ((newfile->compress > 0) && (retval == -1))
|
|
{
|
|
retval = CompressOpenForRead(newfile);
|
|
if (retval == -1)
|
|
{
|
|
CompressClose(newfile);
|
|
newfile->compress--;
|
|
} // ENDIF- Failed to open? Close it... and try the next one.
|
|
} // ENDWHILE- Trying to find a compression scheme that will work...
|
|
|
|
if (newfile->compress == 0)
|
|
{
|
|
newfile->handle = ActualFileOpenForRead(newfile->name);
|
|
if (newfile->handle == ACTUALHANDLENULL)
|
|
{
|
|
free(newfile);
|
|
newfile = NULL;
|
|
return(NULL);
|
|
} // ENDIF- Failed to open? Abort.
|
|
newfile->filebytesize = ActualFileSize(newfile->handle);
|
|
} // ENDIF- No compression? Open it uncompressed.
|
|
} // ENDIF- Temp- failed to open? Abort...
|
|
// Compressed data file with no table? Return prematurely...
|
|
// Condition detection: compress > 0, tablehandle == ACTUALHANDLENULL
|
|
if (retval == -2)
|
|
{
|
|
#ifdef VERBOSE_FUNCTION_ISOFILE
|
|
PrintLog("CDVD isofile: Data file with no table!");
|
|
#endif /* VERBOSE_FUNCTION_ISOFILE */
|
|
return(newfile);
|
|
} // ENDIF-
|
|
|
|
newfile->imagetype = DetectImageType(newfile);
|
|
|
|
if (newfile->compress == 0)
|
|
{
|
|
newfile->filesectorsize = newfile->filebytesize / newfile->blocksize;
|
|
} // ENDIF- Now that blocksize is known, raw file sectors can be figured out
|
|
|
|
IsoNameStripExt(newfile); // Ex: -I00[.bin].Z
|
|
|
|
IsoNameStripMulti(newfile); // Ex: [-I00].bin.Z
|
|
|
|
#ifdef VERBOSE_DISC_INFO
|
|
PrintLog("CDVD isofile: Filename: %s", filename);
|
|
if (newfile->multi > 0) PrintLog("CDVD isofile: Multiple <2GB files.");
|
|
PrintLog("CDVD isofile: Compression Method: %s",
|
|
compressdesc[newfile->compress]);
|
|
PrintLog("CDVD isofile: Image Type: %s",
|
|
newfile->imagename);
|
|
PrintLog("CDVD isofile: Block Size: %lli", newfile->blocksize);
|
|
PrintLog("CDVD isofile: Total Sectors (of first file): %lli",
|
|
newfile->filesectorsize);
|
|
#endif /* VERBOSE_DISC_INFO */
|
|
|
|
// Load a TOC from a .toc file (is there is one)
|
|
retval = IsoLoadTOC(newfile);
|
|
if (retval == 0) return(newfile);
|
|
|
|
// Get the volume sector for disc type test
|
|
retval = IsoFileSeek(newfile, 16);
|
|
if (retval < 0)
|
|
{
|
|
newfile = IsoFileClose(newfile);
|
|
return(NULL);
|
|
} // ENDIF- Could not find the directory sector? Abort.
|
|
retval = IsoFileRead(newfile, tempblock);
|
|
if (retval < 0)
|
|
{
|
|
newfile = IsoFileClose(newfile);
|
|
return(NULL);
|
|
} // ENDIF- Could not read the directory sector? Abort.
|
|
|
|
volcheck.ch = tempblock;
|
|
volcheck.ch += newfile->blockoffset;
|
|
if (ValidateECMA119PrimaryVolume(volcheck.vol) != 0)
|
|
{
|
|
#ifdef VERBOSE_DISC_INFO
|
|
PrintLog("CDVD isofile: Not an ISO9660 disc! Music CD perhaps?");
|
|
#endif /* VERBOSE_DISC_INFO */
|
|
newfile->cdvdtype = CDVD_TYPE_CDDA;
|
|
|
|
}
|
|
else
|
|
{
|
|
// Is this a playstation image?
|
|
i = 0;
|
|
while ((*(playstationid + i) != 0) &&
|
|
(*(playstationid + i) == tempblock[newfile->blockoffset + 8 + i])) i++;
|
|
if (*(playstationid + i) != 0)
|
|
{
|
|
#ifdef VERBOSE_DISC_INFO
|
|
PrintLog("CDVD isofile: Not a Playstation Disc!");
|
|
#endif /* VERBOSE_DISC_INFO */
|
|
newfile->cdvdtype = CDVD_TYPE_DVDV;
|
|
}
|
|
else
|
|
{
|
|
newfile->cdvdtype = CDVD_TYPE_PS2DVD;
|
|
} // ENDIF- Is this not a Playstation 1 image?
|
|
// Sidenote: if the emulator is just playing Playstation 2 images, we could
|
|
// just invalidate the image file right here.
|
|
} // ENDIF- Not an ISO9660 disc? Assume Music CD.
|
|
if (newfile->cdvdtype == CDVD_TYPE_PS2DVD)
|
|
{
|
|
// Is this a Playstation CD image?
|
|
i = 0;
|
|
while ((*(cdname + i) != 0) &&
|
|
(*(cdname + i) == tempblock[newfile->blockoffset + 1024 + i])) i++;
|
|
if (*(cdname + i) == 0)
|
|
{
|
|
newfile->cdvdtype = CDVD_TYPE_PSCD;
|
|
#ifdef VERBOSE_DISC_INFO
|
|
PrintLog("CDVD isofile: Image is a Playstation 1 CD.");
|
|
#endif /* VERBOSE_DISC_INFO */
|
|
}
|
|
else
|
|
{
|
|
if (newfile->blocksize != 2048)
|
|
{
|
|
newfile->cdvdtype = CDVD_TYPE_PS2CD;
|
|
#ifdef VERBOSE_DISC_INFO
|
|
PrintLog("CDVD isofile: Image is a Playstation 2 CD.");
|
|
#endif /* VERBOSE_DISC_INFO */
|
|
}
|
|
else
|
|
{
|
|
#ifdef VERBOSE_DISC_INFO
|
|
PrintLog("CDVD isofile: Image is a DVD.");
|
|
#endif /* VERBOSE_DISC_INFO */
|
|
} // ENDIF- Is the blocksize not 2048? CD image then.
|
|
} // ENDIF- Is this a PS1 CD image?
|
|
} // ENDIF- Is this a Playstation image?
|
|
volcheck.ch = NULL;
|
|
|
|
if ((newfile->cdvdtype == CDVD_TYPE_DVDV) &&
|
|
(newfile->blocksize == 2352)) newfile->cdvdtype = CDVD_TYPE_CDDA;
|
|
// Slap together a TOC based on the above guesswork.
|
|
IsoInitTOC(newfile);
|
|
if ((newfile->cdvdtype != CDVD_TYPE_PS2DVD) &&
|
|
(newfile->cdvdtype != CDVD_TYPE_DVDV))
|
|
{
|
|
toctn.strack = 1;
|
|
toctn.etrack = 1;
|
|
IsoAddTNToTOC(newfile, toctn);
|
|
toctd.type = 0;
|
|
toctd.lsn = newfile->filesectorsize;
|
|
IsoAddTDToTOC(newfile, 0xAA, toctd);
|
|
toctd.type = 0; // ?
|
|
if (newfile->cdvdtype == CDVD_TYPE_CDDA)
|
|
{
|
|
toctd.type = CDVD_AUDIO_TRACK; // Music track assumed
|
|
}
|
|
else
|
|
{
|
|
toctd.type = CDVD_MODE1_TRACK; // Data track assumed
|
|
} // ENDIF- Is this track a music or data track?
|
|
toctd.lsn = 0;
|
|
IsoAddTDToTOC(newfile, 1, toctd);
|
|
} // ENDIF- Is this a CD? Single track for all sectors
|
|
return(newfile);
|
|
} // END IsoFileOpenForRead()
|
|
|
|
int IsIsoFile(const char *filename)
|
|
{
|
|
int retval;
|
|
struct IsoFile *tempfile;
|
|
#ifdef VERBOSE_FUNCTION_ISOFILE
|
|
PrintLog("CDVD isofile: IsIsoFile()");
|
|
#endif /* VERBOSE_FUNCTION_ISOFILE */
|
|
retval = IsActualFile(filename);
|
|
if (retval < 0) return(retval); // Not a regular file? Report it.
|
|
|
|
tempfile = NULL;
|
|
tempfile = IsoFileOpenForRead(filename);
|
|
if (tempfile == NULL) return(-3); // Not an image file? Report it.
|
|
|
|
retval = 0;
|
|
if ((tempfile->compress > 0) &&
|
|
(tempfile->tablehandle == ACTUALHANDLENULL) &&
|
|
(tempfile->tabledata == NULL)) retval = -4;
|
|
tempfile = IsoFileClose(tempfile);
|
|
return(retval);
|
|
} // END IsIsoFile()
|
|
|
|
int IsoFileSeek(struct IsoFile *file, off64_t sector)
|
|
{
|
|
int retval;
|
|
if (file == NULL) return(-1);
|
|
if (sector < 0) return(-1);
|
|
|
|
if (sector == file->sectorpos) return(0);
|
|
|
|
#ifdef VERBOSE_FUNCTION_ISOFILE
|
|
PrintLog("CDVD isofile: IsoFileSeek(%llu)", sector);
|
|
#endif /* VERBOSE_FUNCTION_ISOFILE */
|
|
|
|
if (file->multi > 0)
|
|
{
|
|
retval = MultiFileSeek(file, sector);
|
|
}
|
|
else if (file->compress > 0)
|
|
{
|
|
retval = CompressSeek(file, sector);
|
|
}
|
|
else
|
|
{
|
|
retval = ActualFileSeek(file->handle,
|
|
(sector * file->blocksize) + file->imageheader);
|
|
if (retval == 0)
|
|
{
|
|
file->filesectorpos = sector;
|
|
file->filebytepos = (sector * file->blocksize) + file->imageheader;
|
|
} // ENDIF- Succeeded? Adjust internal pointers
|
|
} // ENDLONGIF- Seek right file? Or compressed block? Or Raw block?
|
|
if (retval < 0)
|
|
{
|
|
#ifdef VERBOSE_FUNCTION_ISOFILE
|
|
PrintLog("CDVD isofile: Trouble finding the sector!");
|
|
#endif /* VERBOSE_FUNCTION_ISOFILE */
|
|
return(-1);
|
|
} // ENDIF- Trouble reading the block? Say so!
|
|
|
|
file->sectorpos = sector;
|
|
return(0);
|
|
} // END IsoFileSeek()
|
|
|
|
int IsoFileRead(struct IsoFile *file, char *block)
|
|
{
|
|
int retval;
|
|
|
|
if (file == NULL) return(-1);
|
|
if (block == NULL) return(-1);
|
|
if (file->openforread == 0) return(-1);
|
|
|
|
#ifdef VERBOSE_FUNCTION_ISOFILE
|
|
PrintLog("CDVD isofile: IsoFileRead(%i)", file->blocksize);
|
|
#endif /* VERBOSE_FUNCTION_ISOFILE */
|
|
|
|
if (file->multi > 0)
|
|
{
|
|
retval = MultiFileRead(file, block);
|
|
}
|
|
else if (file->compress > 0)
|
|
{
|
|
retval = CompressRead(file, block);
|
|
}
|
|
else
|
|
{
|
|
if (file->sectorpos >= file->filesectorsize) return(-1);
|
|
retval = ActualFileRead(file->handle,
|
|
file->blocksize,
|
|
block);
|
|
if (retval > 0) file->filebytepos += retval;
|
|
if (retval == file->blocksize) file->filesectorpos++;
|
|
} // ENDLONGIF- Read right file? Or compressed block? Or Raw block?
|
|
if (retval < 0)
|
|
{
|
|
#ifdef VERBOSE_FUNCTION_ISOFILE
|
|
PrintLog("CDVD isofile: Trouble reading the sector!");
|
|
#endif /* VERBOSE_FUNCTION_ISOFILE */
|
|
return(-1);
|
|
} // ENDIF- Trouble reading the block? Say so!
|
|
|
|
if (retval < file->blocksize)
|
|
{
|
|
#ifdef VERBOSE_FUNCTION_ISOFILE
|
|
PrintLog("CDVD isofile: Short block! Got %i out of %i bytes",
|
|
retval, file->blocksize);
|
|
#endif /* VERBOSE_FUNCTION_ISOFILE */
|
|
return(-1);
|
|
} // ENDIF- Didn't get enough bytes? Say so!
|
|
|
|
file->sectorpos++;
|
|
return(0);
|
|
} // END IsoFileRead()
|
|
|
|
struct IsoFile *IsoFileClose(struct IsoFile *file)
|
|
{
|
|
if (file == NULL) return(NULL);
|
|
|
|
if (file->handle != ACTUALHANDLENULL)
|
|
{
|
|
#ifdef VERBOSE_FUNCTION_ISOFILE
|
|
PrintLog("CDVD isofile: IsoFileClose()");
|
|
#endif /* VERBOSE_FUNCTION_ISOFILE */
|
|
if (file->compress > 0)
|
|
{
|
|
CompressClose(file);
|
|
}
|
|
else
|
|
{
|
|
ActualFileClose(file->handle);
|
|
file->handle = ACTUALHANDLENULL;
|
|
} // ENDIF- Compressed File? Close (and flush) compression too.
|
|
} // ENDIF- Open Handle? Close the file
|
|
free(file);
|
|
return(NULL);
|
|
} // END IsoFileClose()
|
|
|
|
struct IsoFile *IsoFileOpenForWrite(const char *filename,
|
|
int imagetype,
|
|
int multi,
|
|
int compress)
|
|
{
|
|
struct IsoFile *newfile;
|
|
|
|
newfile = NULL;
|
|
|
|
if (filename == NULL) return(NULL);
|
|
if ((imagetype < 0) || (imagetype > 11)) return(NULL);
|
|
if ((compress < 0) || (compress > 5)) return(NULL);
|
|
|
|
#ifdef VERBOSE_FUNCTION_ISOFILE
|
|
PrintLog("CDVD isofile: IsoFileOpenForWrite()");
|
|
#endif /* VERBOSE_FUNCTION_ISOFILE */
|
|
|
|
newfile = (struct IsoFile *) malloc(sizeof(struct IsoFile));
|
|
if (newfile == NULL) return(NULL);
|
|
newfile->sectorpos = 0;
|
|
newfile->openforread = 0; // Write-only file
|
|
newfile->filebytesize = 0;
|
|
newfile->filebytepos = 0;
|
|
newfile->filesectorsize = 0;
|
|
newfile->filesectorpos = 0;
|
|
|
|
// if(toc != NULL) {
|
|
// for(i = 0; i < 2048; i++) newfile->toc[i] = *(toc + i);
|
|
// } else {
|
|
// for(i = 0; i < 2048; i++) newfile->toc[i] = 0;
|
|
// } // ENDIF- Do we have a PS2 Table of Contents to save out as well?
|
|
|
|
newfile->namepos = 0;
|
|
while ((newfile->namepos < 255) &&
|
|
(*(filename + newfile->namepos) != 0))
|
|
{
|
|
newfile->name[newfile->namepos] = *(filename + newfile->namepos);
|
|
newfile->namepos++;
|
|
} // ENDWHILE- copying the file name in...
|
|
newfile->name[newfile->namepos] = 0; // And 0-terminate.
|
|
|
|
IsoNameStripExt(newfile);
|
|
IsoNameStripCompress(newfile);
|
|
IsoNameStripExt(newfile);
|
|
IsoNameStripMulti(newfile);
|
|
newfile->name[newfile->namepos] = 0; // And 0-terminate.
|
|
|
|
newfile->imagetype = imagetype;
|
|
GetImageType(newfile, imagetype);
|
|
newfile->cdvdtype = CDVD_TYPE_PS2DVD; // Does it matter here? Nope.
|
|
|
|
newfile->multi = multi;
|
|
if (newfile->multi > 0)
|
|
{
|
|
newfile->name[newfile->namepos + 0] = '-';
|
|
newfile->name[newfile->namepos + 1] = 'I';
|
|
newfile->name[newfile->namepos + 2] = '0';
|
|
newfile->name[newfile->namepos + 3] = '0';
|
|
newfile->name[newfile->namepos + 4] = 0;
|
|
newfile->multipos = newfile->namepos + 3;
|
|
newfile->namepos += 4;
|
|
newfile->multistart = 0;
|
|
newfile->multiend = 0;
|
|
newfile->multinow = 0;
|
|
newfile->multioffset = 0;
|
|
newfile->multisectorend[0] = 0;
|
|
} // ENDIF- Are we creating a multi-file?
|
|
|
|
newfile->compress = compress;
|
|
switch (newfile->compress)
|
|
{
|
|
case 1:
|
|
case 3:
|
|
newfile->name[newfile->namepos + 0] = '.';
|
|
newfile->name[newfile->namepos + 1] = 'Z';
|
|
newfile->name[newfile->namepos + 2] = 0;
|
|
newfile->namepos += 2;
|
|
break;
|
|
|
|
case 2:
|
|
newfile->name[newfile->namepos + 0] = '.';
|
|
newfile->name[newfile->namepos + 1] = 'd';
|
|
newfile->name[newfile->namepos + 2] = 'u';
|
|
newfile->name[newfile->namepos + 3] = 'm';
|
|
newfile->name[newfile->namepos + 4] = 'p';
|
|
newfile->name[newfile->namepos + 5] = 0;
|
|
newfile->namepos += 5;
|
|
break;
|
|
|
|
case 4:
|
|
newfile->name[newfile->namepos + 0] = '.';
|
|
newfile->name[newfile->namepos + 1] = 'B';
|
|
newfile->name[newfile->namepos + 2] = 'Z';
|
|
newfile->name[newfile->namepos + 3] = '2';
|
|
newfile->name[newfile->namepos + 4] = 0;
|
|
newfile->namepos += 4;
|
|
break;
|
|
case 5:
|
|
newfile->name[newfile->namepos + 0] = '.';
|
|
newfile->name[newfile->namepos + 1] = 'b';
|
|
newfile->name[newfile->namepos + 2] = 'z';
|
|
newfile->name[newfile->namepos + 3] = '2';
|
|
newfile->name[newfile->namepos + 4] = 0;
|
|
newfile->namepos += 4;
|
|
break;
|
|
|
|
case 0:
|
|
default:
|
|
break;
|
|
} // ENDSWITCH compress- which compression extension should we add on?
|
|
newfile->name[newfile->namepos + 0] = '.';
|
|
newfile->name[newfile->namepos + 4] = 0;
|
|
if (newfile->blocksize == 2048)
|
|
{
|
|
newfile->name[newfile->namepos + 1] = 'i';
|
|
newfile->name[newfile->namepos + 2] = 's';
|
|
newfile->name[newfile->namepos + 3] = 'o';
|
|
}
|
|
else
|
|
{
|
|
newfile->name[newfile->namepos + 1] = 'b';
|
|
newfile->name[newfile->namepos + 2] = 'i';
|
|
newfile->name[newfile->namepos + 3] = 'n';
|
|
} // ENDIF- Is this a true ISO (or just a raw BIN file?)
|
|
newfile->namepos += 4;
|
|
|
|
if (IsActualFile(newfile->name) == 0)
|
|
{
|
|
free(newfile);
|
|
newfile = NULL;
|
|
return(NULL);
|
|
} // ENDIF- Does the destination file already exist?
|
|
|
|
if (newfile->compress > 0)
|
|
{
|
|
CompressOpenForWrite(newfile);
|
|
if ((newfile->handle != ACTUALHANDLENULL) &&
|
|
(newfile->tablehandle == ACTUALHANDLENULL))
|
|
{
|
|
ActualFileClose(newfile->handle);
|
|
newfile->handle = ACTUALHANDLENULL;
|
|
} // ENDIF Data file created, but table file stopped? Close and remove data
|
|
}
|
|
else
|
|
{
|
|
newfile->handle = ActualFileOpenForWrite(newfile->name);
|
|
} // ENDIF- Writing out a compressed file?
|
|
if (newfile->handle == ACTUALHANDLENULL)
|
|
{
|
|
free(newfile);
|
|
newfile = NULL;
|
|
return(NULL);
|
|
} // ENDIF- Couldn't create file? Abort
|
|
return(newfile);
|
|
} // END IsoFileOpenForWrite()
|
|
|
|
int IsoFileWrite(struct IsoFile *file, char *block)
|
|
{
|
|
int byteswritten;
|
|
|
|
if (file == NULL) return(-1);
|
|
if (block == NULL) return(-1);
|
|
if (file->openforread == 1) return(-1);
|
|
|
|
#ifdef VERBOSE_FUNCTION_ISOFILE
|
|
PrintLog("CDVD isofile: IsoFileWrite()");
|
|
#endif /* VERBOSE_FUNCTION_ISOFILE */
|
|
|
|
byteswritten = 0;
|
|
if (file->multi > 0)
|
|
{
|
|
byteswritten = MultiFileWrite(file, block);
|
|
}
|
|
else if (file->compress > 0)
|
|
{
|
|
byteswritten = CompressWrite(file, block);
|
|
}
|
|
else
|
|
{
|
|
byteswritten = ActualFileWrite(file->handle,
|
|
file->blocksize,
|
|
block);
|
|
if (byteswritten > 0) file->filebytepos += byteswritten;
|
|
if (byteswritten == file->blocksize) file->filesectorpos++;
|
|
} // ENDLONGIF- Write to different file? Compressed block? or Raw?
|
|
if (byteswritten < 0)
|
|
{
|
|
#ifdef VERBOSE_FUNCTION_ISOFILE
|
|
PrintLog("CDVD isofile: Trouble writing the sector!");
|
|
#endif /* VERBOSE_FUNCTION_ISOFILE */
|
|
return(-1);
|
|
} // ENDIF- Trouble reading the block? Say so!
|
|
if (file->filebytepos > file->filebytesize)
|
|
file->filebytesize = file->filebytepos;
|
|
if (byteswritten < file->blocksize)
|
|
{
|
|
#ifdef VERBOSE_FUNCTION_ISOFILE
|
|
PrintLog("CDVD isofile: Short block! Wrote %i out of %i bytes",
|
|
byteswritten, file->blocksize);
|
|
#endif /* VERBOSE_FUNCTION_ISOFILE */
|
|
return(-1);
|
|
} // ENDIF- Didn't write enough bytes? Say so!
|
|
if (file->filesectorpos > file->filesectorsize)
|
|
file->filesectorsize = file->filesectorpos;
|
|
file->sectorpos++;
|
|
return(0);
|
|
} // END IsoFileWrite()
|
|
|
|
struct IsoFile *IsoFileCloseAndDelete(struct IsoFile *file)
|
|
{
|
|
int i;
|
|
if (file == NULL) return(NULL);
|
|
if (file->handle != ACTUALHANDLENULL)
|
|
{
|
|
#ifdef VERBOSE_FUNCTION_ISOFILE
|
|
PrintLog("CDVD isofile: IsoFileCloseAndDelete()");
|
|
#endif /* VERBOSE_FUNCTION_ISOFILE */
|
|
|
|
if (file->compress > 0)
|
|
{
|
|
CompressClose(file);
|
|
}
|
|
else
|
|
{
|
|
ActualFileClose(file->handle);
|
|
file->handle = ACTUALHANDLENULL;
|
|
} // ENDIF- Compressed File? Close (and flush) compression too.
|
|
} // ENDIF- Open Handle? Close the file
|
|
|
|
if (file->multi == 1)
|
|
{
|
|
for (i = file->multistart; i <= file->multiend; i++)
|
|
{
|
|
file->name[file->multipos] = '0' + i;
|
|
ActualFileDelete(file->name);
|
|
if (file->compress > 0)
|
|
{
|
|
file->tablename[file->multipos] = '0' + i;
|
|
ActualFileDelete(file->tablename);
|
|
} // ENDIF- Get the table file too?
|
|
} // NEXT i- iterate through each multi-file name, removing it.
|
|
}
|
|
else
|
|
{
|
|
ActualFileDelete(file->name);
|
|
if (file->compress > 0)
|
|
{
|
|
ActualFileDelete(file->tablename);
|
|
} // ENDIF- Get the table file too?
|
|
} // ENDIF- Do we have to remove multiple files?
|
|
|
|
free(file);
|
|
return(NULL);
|
|
} // END IsoFileCloseAndDelete()
|