pcsx2/plugins/CDVDisoEFP/src/toc.c

347 lines
10 KiB
C

/* toc.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 <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 "convert.h"
#include "isofile.h"
#include "actualfile.h"
#include "toc.h"
// PCSX2's .toc file format:
// 1 unsigned char - CDVD_TYPE_????
// 1 tocTN
// As many tocTDs as it takes.
extern void IsoInitTOC(struct IsoFile *isofile)
{
int i;
off64_t sectorsize;
if (isofile == NULL) return;
#ifdef VERBOSE_FUNCTION_TOC
PrintLog("CDVDiso TOC: IsoInitTOC()");
#endif /* VERBOSE_FUNCTION_TOC */
if (isofile->multi > 0)
{
sectorsize = isofile->multisectorend[isofile->multiend];
}
else
{
sectorsize = isofile->filesectorsize;
} // ENDIF- Establish largest sector from multifile? (or single file?)
for (i = 0; i < 2048; i++) isofile->toc[i] = 0;
switch (isofile->cdvdtype)
{
case CDVD_TYPE_DVDV:
case CDVD_TYPE_PS2DVD:
if ((isofile->filesectorsize > (2048*1024)) ||
(isofile->multi > 0))
{
isofile->toc[0] = 0x24; // Dual-Sided DVD (?)
isofile->toc[4] = 0x41;
isofile->toc[5] = 0x95;
}
else
{
isofile->toc[0] = 0x04; // Single-Sided DVD (?)
isofile->toc[4] = 0x86;
isofile->toc[5] = 0x72;
} // ENDIF- Too many sectors for a single-layered disc?
isofile->toc[1] = 0x02;
isofile->toc[2] = 0xF2;
isofile->toc[3] = 0x00;
isofile->toc[16] = 0x00;
isofile->toc[17] = 0x03;
isofile->toc[18] = 0x00;
isofile->toc[19] = 0x00;
return; // DVD's don't have tracks. Might track multisession later...
break;
case CDVD_TYPE_PS2CD:
case CDVD_TYPE_PSCD:
isofile->toc[0] = 0x41;
break;
case CDVD_TYPE_CDDA:
isofile->toc[0] = 0x01;
break;
default:
break;
} // ENDSWITCH isofile->cdvdtype - Which TOC for which type?
// CD Details here... (tracks and stuff)
isofile->toc[2] = 0xA0;
isofile->toc[7] = 0x01; // Starting Track No.
isofile->toc[12] = 0xA1;
isofile->toc[17] = 0x01; // Ending Track No.
isofile->toc[22] = 0xA2;
LBAtoMSF(sectorsize, &isofile->toc[27]);
isofile->toc[27] = HEXTOBCD(isofile->toc[27]);
isofile->toc[28] = HEXTOBCD(isofile->toc[28]);
isofile->toc[29] = HEXTOBCD(isofile->toc[29]);
isofile->toc[40] = 0x02; // YellowBook? Data Mode?
isofile->toc[42] = 0x01; // Track No.
LBAtoMSF(0, &isofile->toc[47]);
isofile->toc[47] = HEXTOBCD(isofile->toc[47]);
isofile->toc[48] = HEXTOBCD(isofile->toc[48]);
isofile->toc[49] = HEXTOBCD(isofile->toc[49]);
} // END IsoInitTOC()
extern void IsoAddTNToTOC(struct IsoFile *isofile, struct tocTN toctn)
{
if (isofile == NULL) return;
#ifdef VERBOSE_FUNCTION_TOC
PrintLog("CDVDiso TOC: IsoAddTNToTOC()");
#endif /* VERBOSE_FUNCTION_TOC */
isofile->toc[7] = HEXTOBCD(toctn.strack);
isofile->toc[17] = HEXTOBCD(toctn.etrack);
return;
} // END IsoAddTNToTOC()
extern void IsoAddTDToTOC(struct IsoFile *isofile,
unsigned char track,
struct tocTD toctd)
{
int temptrack;
int position;
#ifdef VERBOSE_FUNCTION_TOC
PrintLog("CDVDiso TOC: IsoAddTNToTOC(%u)", track);
#endif /* VERBOSE_FUNCTION_TOC */
if (isofile == NULL) return;
temptrack = track;
if (temptrack == 0xAA) temptrack = 0;
if (temptrack > 99) return; // Only up to 99 tracks allowed.
if (temptrack == 0)
{
LBAtoMSF(toctd.lsn, &isofile->toc[27]);
isofile->toc[27] = HEXTOBCD(isofile->toc[27]);
isofile->toc[28] = HEXTOBCD(isofile->toc[28]);
isofile->toc[29] = HEXTOBCD(isofile->toc[29]);
}
else
{
position = temptrack * 10;
position += 30;
isofile->toc[position] = toctd.type;
isofile->toc[position + 2] = HEXTOBCD(temptrack);
LBAtoMSF(toctd.lsn, &isofile->toc[position + 7]);
isofile->toc[position + 7] = HEXTOBCD(isofile->toc[position + 7]);
isofile->toc[position + 8] = HEXTOBCD(isofile->toc[position + 8]);
isofile->toc[position + 9] = HEXTOBCD(isofile->toc[position + 9]);
} // ENDIF- Is this a lead-out? (or an actual track?)
} // END IsoAddTDToTOC()
extern int IsoLoadTOC(struct IsoFile *isofile)
{
char tocext[] = ".toc\0";
char tocheader[5];
ACTUALHANDLE tochandle;
char tocname[256];
int i;
int j;
int retval;
unsigned char cdvdtype;
struct tocTN toctn;
struct tocTD toctd;
if (isofile == NULL) return(-1);
i = 0;
while ((i < 256) && (isofile->name[i] != 0))
{
tocname[i] = isofile->name[i];
i++;
} // ENDWHILE- Copying the data name to the toc name
j = 0;
while ((i < 256) && (tocext[j] != 0))
{
tocname[i] = tocext[j];
i++;
j++;
} // ENDWHILE- Append ".toc" to end of name
tocname[i] = 0; // And 0-terminate
tochandle = ActualFileOpenForRead(tocname);
if (tochandle == ACTUALHANDLENULL) return(-1);
retval = ActualFileRead(tochandle, 4, tocheader);
if (retval < 4)
{
ActualFileClose(tochandle);
tochandle = ACTUALHANDLENULL;
return(-1);
} // ENDIF- Trouble reading the 'toc' file?
if ((tocheader[0] != 'T') ||
(tocheader[1] != 'O') ||
(tocheader[2] != 'C') ||
(tocheader[3] != '1'))
{
ActualFileClose(tochandle);
tochandle = ACTUALHANDLENULL;
return(-1);
} // ENDIF- Not a 'toc' file after all?
#ifdef VERBOSE_FUNCTION_TOC
PrintLog("CDVDiso TOC: IsoLoadTOC(%s)", tocname);
#endif /* VERBOSE_FUNCTION_TOC */
retval = ActualFileRead(tochandle, 1, (char *) & cdvdtype);
if (retval < 1)
{
ActualFileClose(tochandle);
tochandle = ACTUALHANDLENULL;
return(-1);
} // ENDIF- Trouble reading the 'toc' file?
isofile->cdvdtype = cdvdtype;
IsoInitTOC(isofile);
if ((cdvdtype != CDVD_TYPE_PS2DVD) && (cdvdtype != CDVD_TYPE_DVDV))
{
retval = ActualFileRead(tochandle, sizeof(struct tocTN), (char *) & toctn);
if (retval < sizeof(struct tocTN))
{
ActualFileClose(tochandle);
tochandle = ACTUALHANDLENULL;
return(-1);
} // ENDIF- Trouble reading the 'toc' file?
if ((toctn.strack > 99) || (toctn.etrack > 99))
{
ActualFileClose(tochandle);
tochandle = ACTUALHANDLENULL;
return(-1);
} // ENDIF- Track numbers out of range?
#ifdef VERBOSE_FUNCTION_TOC
PrintLog("CDVDiso TOC: Start Track %u End Track %u",
toctn.strack, toctn.etrack);
#endif /* VERBOSE_FUNCTION_TOC */
IsoAddTNToTOC(isofile, toctn);
retval = ActualFileRead(tochandle, sizeof(struct tocTD), (char *) & toctd);
if (retval < sizeof(struct tocTD))
{
ActualFileClose(tochandle);
tochandle = ACTUALHANDLENULL;
return(-1);
} // ENDIF- Trouble reading the 'toc' file?
if (toctd.type != 0)
{
ActualFileClose(tochandle);
tochandle = ACTUALHANDLENULL;
return(-1);
} // ENDIF- Track numbers out of range?
#ifdef VERBOSE_FUNCTION_TOC
PrintLog("CDVDiso TOC: Total Sectors: %lu", toctd.lsn);
#endif /* VERBOSE_FUNCTION_TOC */
IsoAddTDToTOC(isofile, 0xAA, toctd);
for (i = toctn.strack; i <= toctn.etrack; i++)
{
retval = ActualFileRead(tochandle, sizeof(struct tocTD), (char *) & toctd);
if (retval < sizeof(struct tocTD))
{
ActualFileClose(tochandle);
tochandle = ACTUALHANDLENULL;
return(-1);
} // ENDIF- Trouble reading the 'toc' file?
#ifdef VERBOSE_FUNCTION_TOC
PrintLog("CDVDiso TOC: Track %u Type %u Sector Start: %lu",
i, toctd.type, toctd.lsn);
#endif /* VERBOSE_FUNCTION_TOC */
IsoAddTDToTOC(isofile, i, toctd);
} // NEXT i- read in each track
} // ENDIF- Not a DVD? (Then read in CD track data)
ActualFileClose(tochandle);
tochandle = ACTUALHANDLENULL;
return(0);
} // END IsoLoadTOC()
extern int IsoSaveTOC(struct IsoFile *isofile)
{
char tocext[] = ".toc\0";
char tocheader[] = "TOC1\0";
ACTUALHANDLE tochandle;
char tocname[256];
int i;
int j;
int retval;
unsigned char cdvdtype;
struct tocTN toctn;
struct tocTD toctd;
char temptime[3];
if (isofile == NULL) return(-1);
i = 0;
while ((i < 256) && (isofile->name[i] != 0))
{
tocname[i] = isofile->name[i];
i++;
} // ENDWHILE- Copying the data name to the toc name
j = 0;
while ((i < 256) && (tocext[j] != 0))
{
tocname[i] = tocext[j];
i++;
j++;
} // ENDWHILE- Append ".toc" to end of name
tocname[i] = 0; // And 0-terminate
ActualFileDelete(tocname);
tochandle = ActualFileOpenForWrite(tocname);
if (tochandle == ACTUALHANDLENULL) return(-1);
retval = ActualFileWrite(tochandle, 4, tocheader);
if (retval < 4)
{
ActualFileClose(tochandle);
tochandle = ACTUALHANDLENULL;
ActualFileDelete(tocname);
return(-1);
} // ENDIF- Trouble writing to the 'toc' file?
cdvdtype = isofile->cdvdtype;
ActualFileWrite(tochandle, 1, (char *) &cdvdtype);
if ((cdvdtype != CDVD_TYPE_PS2DVD) && (cdvdtype != CDVD_TYPE_DVDV))
{
toctn.strack = BCDTOHEX(isofile->toc[7]);
toctn.etrack = BCDTOHEX(isofile->toc[17]);
ActualFileWrite(tochandle, sizeof(struct tocTN), (char *) &toctn);
// Leadout Data
toctd.type = 0;
temptime[0] = BCDTOHEX(isofile->toc[27]);
temptime[1] = BCDTOHEX(isofile->toc[28]);
temptime[2] = BCDTOHEX(isofile->toc[29]);
toctd.lsn = MSFtoLBA(temptime);
ActualFileWrite(tochandle, sizeof(struct tocTD), (char *) &toctd);
for (i = toctn.strack; i <= toctn.etrack; i++)
{
j = i * 10 + 30;
toctd.type = isofile->toc[j];
temptime[0] = BCDTOHEX(isofile->toc[j + 7]);
temptime[1] = BCDTOHEX(isofile->toc[j + 8]);
temptime[2] = BCDTOHEX(isofile->toc[j + 9]);
toctd.lsn = MSFtoLBA(temptime);
ActualFileWrite(tochandle, sizeof(struct tocTD), (char *) &toctd);
} // NEXT i- write out each track
} // ENDIF- Not a DVD? (Then output CD track data)
ActualFileClose(tochandle);
tochandle = ACTUALHANDLENULL;
return(0);
} // END IsoSaveTOC()