pcsx2/plugins/CDVDpeops/ppf.c

354 lines
7.8 KiB
C
Raw Normal View History

/***************************************************************************
ppf.c - description
-------------------
begin : Wed Sep 18 2002
copyright : (C) 2002 by Pete Bernert
email : BlackDove@addcom.de
***************************************************************************/
/***************************************************************************
* *
* 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. See also the license.txt file for *
* additional informations. *
* *
***************************************************************************/
//*************************************************************************//
// History of changes:
//
// 2003/02/14 - Pete
// - fixed a bug reading PPF3 patches reported by Zydio
//
// 2002/09/19 - Pete
// - generic cleanup for the Peops release
//
//*************************************************************************//
/////////////////////////////////////////////////////////
#include "stdafx.h"
#define _IN_PPF
#include "externals.h"
/////////////////////////////////////////////////////////
int iUsePPF=0;
char szPPF[260];
PPF_CACHE * ppfCache=NULL;
PPF_DATA * ppfHead=NULL;
int iPPFNum=0;
/////////////////////////////////////////////////////////
// works like sub cache... using a linked data list, and address array
void FillPPFCache(void)
{
PPF_DATA * p;PPF_CACHE * pc;
long lastaddr;
p=ppfHead;
lastaddr=-1;
iPPFNum=0;
while(p)
{
if(p->addr!=lastaddr) iPPFNum++;
lastaddr=p->addr;
p=(PPF_DATA *)p->pNext;
}
if(!iPPFNum) return;
pc=ppfCache=(PPF_CACHE *)malloc(iPPFNum*sizeof(PPF_CACHE));
iPPFNum--;
p=ppfHead;
lastaddr=-1;
while(p)
{
if(p->addr!=lastaddr)
{
pc->addr=p->addr;
pc->pNext=(void *)p;
pc++;
}
lastaddr=p->addr;
p=(PPF_DATA *)p->pNext;
}
}
/////////////////////////////////////////////////////////
void FreePPFCache(void)
{
PPF_DATA * p=ppfHead;
void * pn;
while(p)
{
pn=p->pNext;
free(p);
p=(PPF_DATA *)pn;
}
ppfHead=NULL;
if(ppfCache) free(ppfCache);
ppfCache=NULL;
}
/////////////////////////////////////////////////////////
void CheckPPFCache(long addr,unsigned char * pB)
{
PPF_CACHE * pcstart, * pcend, * pcpos;
pcstart=ppfCache;
if(addr<pcstart->addr) return;
pcend=ppfCache+iPPFNum;
if(addr>pcend->addr) return;
while(1)
{
if(addr==pcend->addr) {pcpos=pcend;break;}
pcpos=pcstart+(pcend-pcstart)/2;
if(pcpos==pcstart) break;
if(addr<pcpos->addr)
{
pcend=pcpos;
continue;
}
if(addr>pcpos->addr)
{
pcstart=pcpos;
continue;
}
break;
}
if(addr==pcpos->addr)
{
PPF_DATA * p=(PPF_DATA *)pcpos->pNext;
while(p && p->addr==addr)
{
memcpy(pB+p->pos,p+1,p->anz);
p=(PPF_DATA *)p->pNext;
}
}
}
/////////////////////////////////////////////////////////
void AddToPPF(long ladr,long pos,long anz,char * ppfmem)
{
if(!ppfHead)
{
ppfHead=(PPF_DATA *)malloc(sizeof(PPF_DATA)+anz);
ppfHead->addr=ladr;
ppfHead->pNext=NULL;
ppfHead->pos=pos;
ppfHead->anz=anz;
memcpy(ppfHead+1,ppfmem,anz);
iPPFNum=1;
}
else
{
PPF_DATA * p=ppfHead;
PPF_DATA * plast=NULL;
PPF_DATA * padd;
while(p)
{
if(ladr<p->addr) break;
if(ladr==p->addr)
{
while(p && ladr==p->addr && pos>p->pos)
{
plast=p;
p=(PPF_DATA *)p->pNext;
}
break;
}
plast=p;
p=(PPF_DATA *)p->pNext;
}
padd=(PPF_DATA *)malloc(sizeof(PPF_DATA)+anz);
padd->addr=ladr;
padd->pNext=(void *)p;
padd->pos=pos;
padd->anz=anz;
memcpy(padd+1,ppfmem,anz);
iPPFNum++;
if(plast==NULL)
ppfHead=padd;
else plast->pNext=(void *)padd;
}
}
/////////////////////////////////////////////////////////
// build ppf cache, if wanted
void BuildPPFCache(void)
{
FILE * ppffile;
char buffer[5];
char method,undo=0,blockcheck=0;
int dizlen, dizyn, dizlensave=0;
char ppfmem[512];
int count,seekpos, pos;
//unsigned char anz;
unsigned int anz; // new! avoids stupid overflows
long ladr,off,anx;
ppfHead=NULL;
if(iUsePPF==0) return; // no ppf cache wanted?
if(szPPF[0]==0) return; // no ppf file given?
ppffile=fopen(szPPF, "rb");
if(ppffile==0)
{
MessageBox(NULL,"No PPF file found!",libraryName,MB_OK);
return;
}
memset(buffer,0,5);
fread(buffer, 3, 1, ppffile);
if(strcmp(buffer,"PPF"))
{
MessageBox(NULL,"No PPF file format!",libraryName,MB_OK);
fclose(ppffile);
return;
}
fseek(ppffile, 5, SEEK_SET);
fread(&method, 1, 1,ppffile);
switch(method)
{
case 0: // ppf1
fseek(ppffile, 0, SEEK_END);
count=ftell(ppffile);
count-=56;
seekpos=56;
break;
case 1: // ppf2
fseek(ppffile, -8,SEEK_END);
memset(buffer,0,5);
fread(buffer, 4, 1,ppffile);
if(strcmp(".DIZ", buffer))
{
dizyn=0;
}
else
{
fread(&dizlen, 4, 1, ppffile);
dizyn=1;
dizlensave=dizlen;
}
fseek(ppffile, 56, SEEK_SET);
fread(&dizlen, 4, 1,ppffile);
fseek(ppffile, 0, SEEK_END);
count=ftell(ppffile);
if(dizyn==0)
{
count-=1084;
seekpos=1084;
}
else
{
count-=1084;
count-=38;
count-=dizlensave;
seekpos=1084;
}
break;
case 2: // ppf3
fseek(ppffile, 57, SEEK_SET);
fread(&blockcheck, 1, 1,ppffile);
fseek(ppffile, 58, SEEK_SET);
fread(&undo, 1, 1,ppffile);
fseek(ppffile, -6,SEEK_END);
memset(buffer,0,5);
fread(buffer, 4, 1,ppffile);
dizlen=0;
if(!strcmp(".DIZ", buffer))
{
fseek(ppffile, -2,SEEK_END);
fread(&dizlen, 2, 1, ppffile);
dizlen+=36;
}
fseek(ppffile, 0, SEEK_END);
count=ftell(ppffile);
count-=dizlen;
if(blockcheck)
{
seekpos=1084;
count-=1084;
}
else
{
seekpos=60;
count-=60;
}
break;
default:
fclose(ppffile);
MessageBox(NULL,"Unknown PPF format!",libraryName,MB_OK);
return;
}
do // now do the data reading
{
fseek(ppffile, seekpos, SEEK_SET);
fread(&pos, 4, 1, ppffile);
if(method==2) fread(buffer, 4, 1, ppffile); // skip 4 bytes on ppf3 (no int64 support here)
anz=0; // new! init anz (since it's no unsigned char anymore)
fread(&anz, 1, 1, ppffile);
fread(ppfmem, anz, 1, ppffile);
ladr=pos/2352;
off=pos%2352;
if(off+anz>2352)
{
anx=off+anz-2352;
anz-=(unsigned char)anx;
AddToPPF(ladr+1,0,anx,ppfmem+anz);
}
AddToPPF(ladr,off,anz,ppfmem); // add to link list
if(method==2) // adjust ppf3 size
{
if(undo) anz+=anz;
anz+=4;
}
seekpos=seekpos+5+anz;
count=count-5-anz;
}
while(count!=0); // loop til end
fclose(ppffile);
FillPPFCache(); // build address array
}
/////////////////////////////////////////////////////////