?? savefile.cpp
字號:
/************************************************************************
* savefile.cpp *
* File I/O for saving to and reading from database files only. *
* Added in version 2.11. Compression is implemented based on rle, but *
* it is nibble based (2*nibbles=byte) rather than byte based. I decided *
* on this after closer examination of the database files. It results in *
* around a 30% reduction to the database file size. *
************************************************************************/
#include <windows.h>
#include "savefile.h"
#include "dasm.h"
#include "debug.h"
/************************************************************************
* Constructor - sets up some variables used in the compression and save *
************************************************************************/
savefile::savefile()
{ sfile=INVALID_HANDLE_VALUE;
rbufflen=0;
rbuffptr=0;
rbhigh=true;
rlecount=0;
rlemode=false;
rlestart=true;
}
/************************************************************************
* Destructor - closes the database file if it is still open *
************************************************************************/
savefile::~savefile()
{ sclose();
}
/************************************************************************
* sopen *
* - opens the database file and returns true on success *
************************************************************************/
bool savefile::sopen(LPCTSTR lpFileName,DWORD dwDesiredAccess,DWORD dwShareMode,
DWORD dwCreationDistribution,DWORD dwFlagsAndAttributes)
{ sfile=CreateFile(lpFileName,dwDesiredAccess,dwShareMode,NULL,
dwCreationDistribution,dwFlagsAndAttributes,NULL);
if(sfile==INVALID_HANDLE_VALUE)
{ MessageBox(mainwindow,"File open failed ?",lpFileName,MB_OK|MB_ICONEXCLAMATION);
return false;
}
if(GetFileType(sfile)!=FILE_TYPE_DISK)
{ MessageBox(mainwindow,"File open failed ?",lpFileName,MB_OK|MB_ICONEXCLAMATION);
sclose();
return false;
}
return true;
}
/************************************************************************
* sclose *
* - closes the database file if still open *
************************************************************************/
void savefile::sclose(void)
{ if(sfile!=INVALID_HANDLE_VALUE)
CloseHandle(sfile);
}
/************************************************************************
* getnibble *
* - This function sets n to the next nibble from the file, it uses *
* buffering and reads from the file as required *
************************************************************************/
bool savefile::getnibble(byte *n)
{ bool rval;
if(rbuffptr<rbufflen)
{ if(rbhigh)
{ (*n)=(byte)(rbuff[rbuffptr]>>4);
rbhigh=false;
return true;
}
(*n)=(byte)(rbuff[rbuffptr]&0x0f);
rbhigh=true;
rbuffptr++;
return true;
}
else
{ rval=ReadFile(sfile,rbuff,RBUFF_MAXLEN,&rbufflen,NULL);
rbhigh=true;
rbuffptr=0;
if((rval)&&(rbufflen))
return getnibble(n);
return false;
}
}
/************************************************************************
* getrlenibble *
* - this function sets n to the next nibble from the file, taking into *
* account rle encoding. So this returns the next uncompressed nibble *
* - rle encoding is: *
* rle_code count nibble *
* count is number-1 (so it can encode from 2 to 16 nibbles) *
* or rle_code 0 signifies a nibble equal to rle_code *
* - note that rle_code is a constant specified in the savefile.h which *
* indicates an rle encoding, and is currently 0x0f. Do not set this *
* constant to 0 as this would be inefficient.... *
************************************************************************/
bool savefile::getrlenibble(byte *n)
{ if(rlemode)
{ rlecount--;
if(!rlecount)
rlemode=false;
(*n)=(byte)(rlebyte);
return true;
}
if(!getnibble(&rlebyte))
return false;
if(rlebyte==rle_code)
{ if(!getnibble(&rlebyte))
return false;
if(rlebyte)
{ rlecount=rlebyte;
rlemode=true;
if(!getnibble(&rlebyte))
return false;
(*n)=rlebyte;
return true;
}
(*n)=rle_code;
return true;
}
(*n)=rlebyte;
return true;
}
/************************************************************************
* putnibble *
* - The opposite function to getnibble, it writes one nibble to the *
* file using buffering *
************************************************************************/
bool savefile::putnibble(byte n)
{ bool rval;
dword num;
if(rbuffptr<RBUFF_MAXLEN)
{ if(rbhigh)
{ rbuff[rbuffptr]=(byte)((n&0x0f)<<4);
rbhigh=false;
rbufflen++;
return true;
}
rbuff[rbuffptr]+=(byte)(n&0x0f);
rbhigh=true;
rbuffptr++;
return true;
}
else
{ rval=WriteFile(sfile,rbuff,RBUFF_MAXLEN,&num,NULL);
rbhigh=true;
rbuffptr=0;
rbufflen=0;
if(rval)
return putnibble(n);
return false;
}
}
/************************************************************************
* flushnibble *
* - A necessity of buffered writing, this flushes the remainder of the *
* buffer, writing it out to file *
************************************************************************/
bool savefile::flushnibble(void)
{ dword num;
if(rbufflen)
return WriteFile(sfile,rbuff,rbufflen,&num,NULL);
return true;
}
/************************************************************************
* putrlenibble *
* - This is the opposite function to getrlenibble. It writes nibbles to *
* file whilst performing the compression. The rle encoding happens *
* here and when nibbles are ready to be written the putnibble *
* function is called *
************************************************************************/
bool savefile::putrlenibble(byte n)
{ if(rlestart)
{ rlestart=false;
rlebyte=n;
return true;
}
if(rlemode)
{ if((rlebyte==n)&&(rlecount<0x0f))
{ rlecount++;
return true;
}
if(!putnibble(rle_code))
return false;
if(!putnibble(rlecount))
return false;
if(!putnibble(rlebyte))
return false;
rlemode=false;
rlebyte=n;
return true;
}
if(rlebyte==n)
{ rlemode=true;
rlecount=1;
return true;
}
if(!putnibble(rlebyte))
return false;
if(rlebyte==rle_code)
if(!putnibble(0))
return false;
rlebyte=n;
return true;
}
/************************************************************************
* flushrlenibble *
* - This flushes any partial rle at the end of a file and forces it to *
* the putnibble function *
************************************************************************/
bool savefile::flushrlenibble(void)
{ if(rlemode)
{ if(!putnibble(rle_code))
return false;
if(!putnibble(rlecount))
return false;
if(!putnibble(rlebyte))
return false;
}
else
{ if(!putnibble(rlebyte))
return false;
if(rlebyte==rle_code)
if(!putnibble(0))
return false;
}
return true;
}
/************************************************************************
* flushfilewrite *
* - The function to flush writing which should be called at the end of *
* the save. It flushes any partial encoding and then flushes the *
* buffered write *
************************************************************************/
bool savefile::flushfilewrite(void)
{ if(!flushrlenibble())
return false;
return flushnibble();
}
/************************************************************************
* sread *
* - This is the external call for reading from a file. Its a similar *
* format to ReadFile, and uses the rle compression routines *
************************************************************************/
bool savefile::sread(LPVOID lpBuffer,DWORD nNumberOfBytesToRead,LPDWORD lpNumberOfBytesRead)
{ byte n;
dword num;
(*lpNumberOfBytesRead)=0;
for(num=0;num<nNumberOfBytesToRead;num++)
{ if(!getrlenibble(&n))
return false;
((byte *)lpBuffer)[num]=(byte)(n<<4);
if(!getrlenibble(&n))
return false;
((byte *)lpBuffer)[num]+=n;
(*lpNumberOfBytesRead)++;
}
return true;
}
/************************************************************************
* swrite *
* - This is the external call for writing to a file. Its a similar *
* format to WriteFile, and uses the rle compression routines *
************************************************************************/
bool savefile::swrite(LPCVOID lpBuffer,DWORD nNumberOfBytesToWrite)
{ dword num;
for(num=0;num<nNumberOfBytesToWrite;num++)
{ if(!putrlenibble((byte)(((byte *)lpBuffer)[num]>>4)))
return false;
if(!putrlenibble((byte)(((byte *)lpBuffer)[num]&0x0f)))
return false;
}
return true;
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -