/*************************************************************************** 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(addraddr) 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(addraddr) { 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(ladraddr) 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 } /////////////////////////////////////////////////////////