add 7z support, code cleanup

This commit is contained in:
dborth 2008-10-14 09:21:34 +00:00
parent 23034a6f9a
commit f5d6042073
37 changed files with 4101 additions and 168 deletions

View File

@ -20,7 +20,7 @@ include $(DEVKITPPC)/gamecube_rules
TARGET := snes9xgx-$(VERSION)-gc TARGET := snes9xgx-$(VERSION)-gc
TARGETDIR := executables TARGETDIR := executables
BUILD := build_gc BUILD := build_gc
SOURCES := source/snes9x source/ngc SOURCES := source/snes9x source/ngc source/sz
DATA := data DATA := data
INCLUDES := source/snes9x source/ngc INCLUDES := source/snes9x source/ngc
@ -34,6 +34,7 @@ CFLAGS = -g -O3 -Wall $(MACHDEP) $(INCLUDE) \
-DCPU_SHUTDOWN -DSPC700_SHUTDOWN \ -DCPU_SHUTDOWN -DSPC700_SHUTDOWN \
-DSPC700_C -DSDD1_DECOMP \ -DSPC700_C -DSDD1_DECOMP \
-DCORRECT_VRAM_READS -DNEW_COLOUR_BLENDING \ -DCORRECT_VRAM_READS -DNEW_COLOUR_BLENDING \
-D_SZ_ONE_DIRECTORY -D_LZMA_IN_CB -D_LZMA_OUT_READ \
-fomit-frame-pointer -fno-exceptions -Wno-unused-parameter \ -fomit-frame-pointer -fno-exceptions -Wno-unused-parameter \
#-D_DEBUG_VIDEO -pipe #-D_DEBUG_VIDEO -pipe
CXXFLAGS = $(CFLAGS) CXXFLAGS = $(CFLAGS)

View File

@ -20,7 +20,7 @@ include $(DEVKITPPC)/wii_rules
TARGET := snes9xgx-$(VERSION)-wii TARGET := snes9xgx-$(VERSION)-wii
TARGETDIR := executables TARGETDIR := executables
BUILD := build_wii BUILD := build_wii
SOURCES := source/snes9x source/ngc SOURCES := source/snes9x source/ngc source/sz
DATA := data DATA := data
INCLUDES := source/snes9x source/ngc INCLUDES := source/snes9x source/ngc
@ -34,6 +34,7 @@ CFLAGS = -g -O3 -Wall $(MACHDEP) $(INCLUDE) \
-DCPU_SHUTDOWN -DSPC700_SHUTDOWN \ -DCPU_SHUTDOWN -DSPC700_SHUTDOWN \
-DSPC700_C -DSDD1_DECOMP \ -DSPC700_C -DSDD1_DECOMP \
-DCORRECT_VRAM_READS -DNEW_COLOUR_BLENDING \ -DCORRECT_VRAM_READS -DNEW_COLOUR_BLENDING \
-D_SZ_ONE_DIRECTORY -D_LZMA_IN_CB -D_LZMA_OUT_READ \
-fomit-frame-pointer -fno-exceptions -Wno-unused-parameter \ -fomit-frame-pointer -fno-exceptions -Wno-unused-parameter \
#-D_DEBUG_VIDEO -pipe #-D_DEBUG_VIDEO -pipe
CXXFLAGS = -save-temps -Xassembler -aln=$@.lst $(CFLAGS) CXXFLAGS = -save-temps -Xassembler -aln=$@.lst $(CFLAGS)

View File

@ -28,9 +28,9 @@ extern "C" {
#include "snes9xGX.h" #include "snes9xGX.h"
#include "unzip.h" #include "unzip.h"
u64 dvddir = 0; u64 dvddir = 0; // offset of currently selected file or folder
u64 dvdrootdir = 0; int dvddirlength = 0; // length of currently selected file or folder
int dvddirlength = 0; u64 dvdrootdir = 0; // offset of DVD root
bool isWii = false; bool isWii = false;
#ifdef HW_DOL #ifdef HW_DOL
@ -89,6 +89,135 @@ dvd_read (void *dst, unsigned int len, u64 offset)
return 0; return 0;
} }
/****************************************************************************
* dvd_buffered_read
*
* the GC's dvd drive only supports offsets and length which are a multiple
* of 32 bytes additionally the max length of a read is 2048 bytes
* this function removes these limitations
* additionally the 7zip SDK does often read data in 1 byte parts from the
* DVD even when it could read 32 bytes. the dvdsf_buffer has been added to
* avoid having to read the same sector over and over again
***************************************************************************/
#define DVD_LENGTH_MULTIPLY 32
#define DVD_OFFSET_MULTIPLY 32
#define DVD_MAX_READ_LENGTH 2048
#define DVD_SECTOR_SIZE 2048
unsigned char dvdsf_buffer[DVD_SECTOR_SIZE];
u64 dvdsf_last_offset = 0;
u64 dvdsf_last_length = 0;
int dvd_buffered_read(void *dst, u32 len, u64 offset)
{
int ret = 0;
// only read data if the data inside dvdsf_buffer cannot be used
if(offset != dvdsf_last_offset || len > dvdsf_last_length)
{
memset(&dvdsf_buffer, '\0', DVD_SECTOR_SIZE);
ret = dvd_read(&dvdsf_buffer, len, offset);
dvdsf_last_offset = offset;
dvdsf_last_length = len;
}
memcpy(dst, &dvdsf_buffer, len);
return ret;
}
int dvd_safe_read(void *dst_v, u32 len, u64 offset)
{
unsigned char buffer[DVD_SECTOR_SIZE]; // buffer for one dvd sector
// if read size and length are a multiply of DVD_(OFFSET,LENGTH)_MULTIPLY and length < DVD_MAX_READ_LENGTH
// we don't need to fix anything
if(len % DVD_LENGTH_MULTIPLY == 0 && offset % DVD_OFFSET_MULTIPLY == 0 && len <= DVD_MAX_READ_LENGTH)
{
int ret = dvd_buffered_read(buffer, len, offset);
memcpy(dst_v, &buffer, len);
return ret;
}
else
{
// no errors yet -> ret = 0
// the return value of dvd_read will be OR'd with ret
// because dvd_read does return 1 on error and 0 on success and
// because 0 | 1 = 1 ret will also contain 1 if at least one error
// occured and 0 otherwise ;)
int ret = 0; // return value of dvd_read
// we might need to fix all 3 issues
unsigned char *dst = (unsigned char *)dst_v; // gcc will not allow to use var[num] on void* types
u64 bytesToRead; // the number of bytes we still need to read & copy to the output buffer
u64 currentOffset; // the current dvd offset
u64 bufferOffset; // the current buffer offset
u64 i, j, k; // temporary variables which might be used for different stuff
// unsigned char buffer[DVD_SECTOR_SIZE]; // buffer for one dvd sector
currentOffset = offset;
bytesToRead = len;
bufferOffset = 0;
// fix first issue (offset is not a multiply of 32)
if(offset % DVD_OFFSET_MULTIPLY)
{
// calculate offset of the prior 32 byte position
i = currentOffset - (currentOffset % DVD_OFFSET_MULTIPLY);
// calculate the offset from which the data of the dvd buffer will be copied
j = currentOffset % DVD_OFFSET_MULTIPLY;
// calculate the number of bytes needed to reach the next DVD_OFFSET_MULTIPLY byte mark
k = DVD_OFFSET_MULTIPLY - j;
// maybe we'll only need to copy a few bytes and we therefore don't even reach the next sector
if(k > len)
{
k = len;
}
// read 32 bytes from the last 32 byte position
ret |= dvd_buffered_read(buffer, DVD_OFFSET_MULTIPLY, i);
// copy the bytes to the output buffer and update currentOffset, bufferOffset and bytesToRead
memcpy(&dst[bufferOffset], &buffer[j], k);
currentOffset += k;
bufferOffset += k;
bytesToRead -= k;
}
// fix second issue (more than 2048 bytes are needed)
if(bytesToRead > DVD_MAX_READ_LENGTH)
{
// calculate the number of 2048 bytes sector needed to get all data
i = (bytesToRead - (bytesToRead % DVD_MAX_READ_LENGTH)) / DVD_MAX_READ_LENGTH;
// read data in 2048 byte sector
for(j = 0; j < i; j++)
{
ret |= dvd_buffered_read(buffer, DVD_MAX_READ_LENGTH, currentOffset); // read sector
memcpy(&dst[bufferOffset], buffer, DVD_MAX_READ_LENGTH); // copy to output buffer
// update currentOffset, bufferOffset and bytesToRead
currentOffset += DVD_MAX_READ_LENGTH;
bufferOffset += DVD_MAX_READ_LENGTH;
bytesToRead -= DVD_MAX_READ_LENGTH;
}
}
// fix third issue (length is not a multiply of 32)
if(bytesToRead)
{
ret |= dvd_buffered_read(buffer, DVD_MAX_READ_LENGTH, currentOffset); // read 32 byte from the dvd
memcpy(&dst[bufferOffset], buffer, bytesToRead); // copy bytes to output buffer
}
//free(tmp);
return ret;
}
}
/** Minimal ISO Directory Definition **/ /** Minimal ISO Directory Definition **/
#define RECLEN 0 /* Record length */ #define RECLEN 0 /* Record length */
#define EXTENT 6 /* Extent */ #define EXTENT 6 /* Extent */
@ -440,6 +569,9 @@ LoadDVDFile (unsigned char *buffer, int length)
u64 discoffset; u64 discoffset;
char readbuffer[2048]; char readbuffer[2048];
dvddir = filelist[selection].offset;
dvddirlength = filelist[selection].length;
// How many 2k blocks to read // How many 2k blocks to read
blocks = dvddirlength / 2048; blocks = dvddirlength / 2048;
offset = 0; offset = 0;
@ -474,7 +606,7 @@ LoadDVDFile (unsigned char *buffer, int length)
} }
else else
{ {
return UnZipFile (buffer, discoffset); // unzip from dvd return UnZipBuffer (buffer, METHOD_DVD); // unzip from dvd
} }
} }
return dvddirlength; return dvddirlength;

View File

@ -18,10 +18,14 @@ int ParseDVDdirectory ();
int LoadDVDFile (unsigned char *buffer, int length); int LoadDVDFile (unsigned char *buffer, int length);
bool TestDVD(); bool TestDVD();
int dvd_read (void *dst, unsigned int len, u64 offset); int dvd_read (void *dst, unsigned int len, u64 offset);
int dvd_safe_read (void *dst, unsigned int len, u64 offset);
bool SwitchDVDFolder(char dir[]); bool SwitchDVDFolder(char dir[]);
void SetDVDDriveType(); void SetDVDDriveType();
#ifdef HW_DOL #ifdef HW_DOL
void dvd_motor_off (); void dvd_motor_off ();
#endif #endif
extern u64 dvddir;
extern int dvddirlength;
#endif #endif

View File

@ -3,7 +3,7 @@
* *
* softdev July 2006 * softdev July 2006
* crunchy2 May 2007 * crunchy2 May 2007
* Michniewski 2008 * Michniewski 2008
* Tantric August 2008 * Tantric August 2008
* *
* fileop.cpp * fileop.cpp
@ -27,7 +27,8 @@
#include "preferences.h" #include "preferences.h"
#include "snes9xGX.h" #include "snes9xGX.h"
FILE * filehandle; // FAT file pointer - the only one we should ever use!
FILE * fatfile;
/**************************************************************************** /****************************************************************************
* fat_is_mounted * fat_is_mounted
@ -172,45 +173,65 @@ LoadFATFile (char * rbuffer, int length)
{ {
char zipbuffer[2048]; char zipbuffer[2048];
char filepath[MAXPATHLEN]; char filepath[MAXPATHLEN];
FILE *handle;
u32 size; u32 size;
/* Check filename length */ /* Check filename length */
if ((strlen(currentdir)+1+strlen(filelist[selection].filename)) < MAXPATHLEN) if (!MakeROMPath(filepath, METHOD_SD))
sprintf(filepath, "%s/%s",currentdir,filelist[selection].filename);
else
{ {
WaitPrompt((char*) "Maximum filepath length reached!"); WaitPrompt((char*) "Maximum filepath length reached!");
return -1; return -1;
} }
handle = fopen (filepath, "rb"); fatfile = fopen (filepath, "rb");
if (handle > 0) if (fatfile > 0)
{ {
if(length > 0) // do a partial read (eg: to check file header) if(length > 0) // do a partial read (eg: to check file header)
{ {
fread (rbuffer, 1, length, handle); fread (rbuffer, 1, length, fatfile);
size = length; size = length;
} }
else // load whole file else // load whole file
{ {
fread (zipbuffer, 1, 2048, handle); fread (zipbuffer, 1, 2048, fatfile);
if (IsZipFile (zipbuffer)) if (IsZipFile (zipbuffer))
{ {
size = UnZipFile ((unsigned char *)rbuffer, handle); // unzip from FAT size = UnZipBuffer ((unsigned char *)rbuffer, METHOD_SD); // unzip from FAT
} }
else else
{ {
// Just load the file up // Just load the file up
fseek(handle, 0, SEEK_END); fseek(fatfile, 0, SEEK_END);
size = ftell(handle); // get filesize size = ftell(fatfile); // get filesize
fseek(handle, 2048, SEEK_SET); // seek back to point where we left off fseek(fatfile, 2048, SEEK_SET); // seek back to point where we left off
memcpy (rbuffer, zipbuffer, 2048); // copy what we already read memcpy (rbuffer, zipbuffer, 2048); // copy what we already read
fread (rbuffer + 2048, 1, size - 2048, handle); fread (rbuffer + 2048, 1, size - 2048, fatfile);
} }
} }
fclose (handle); fclose (fatfile);
return size;
}
else
{
WaitPrompt((char*) "Error opening file");
return 0;
}
}
/****************************************************************************
* LoadFATSzFile
* Loads the selected file # from the specified 7z into rbuffer
* Returns file size
***************************************************************************/
int
LoadFATSzFile(char * filepath, unsigned char * rbuffer)
{
u32 size;
fatfile = fopen (filepath, "rb");
if (fatfile > 0)
{
size = SzExtractFile(filelist[selection].offset, rbuffer);
fclose (fatfile);
return size; return size;
} }
else else
@ -226,12 +247,11 @@ LoadFATFile (char * rbuffer, int length)
int int
LoadBufferFromFAT (char *filepath, bool silent) LoadBufferFromFAT (char *filepath, bool silent)
{ {
FILE *handle;
int size = 0; int size = 0;
handle = fopen (filepath, "rb"); fatfile = fopen (filepath, "rb");
if (handle <= 0) if (fatfile <= 0)
{ {
if ( !silent ) if ( !silent )
{ {
@ -243,13 +263,11 @@ LoadBufferFromFAT (char *filepath, bool silent)
} }
// Just load the file up // Just load the file up
fseek(handle, 0, SEEK_END); // go to end of file fseek(fatfile, 0, SEEK_END); // go to end of file
size = ftell(handle); // get filesize size = ftell(fatfile); // get filesize
fseek(handle, 0, SEEK_SET); // go to start of file fseek(fatfile, 0, SEEK_SET); // go to start of file
fread (savebuffer, 1, size, handle); fread (savebuffer, 1, size, fatfile);
fclose (handle); fclose (fatfile);
fclose (handle);
return size; return size;
} }
@ -260,13 +278,11 @@ LoadBufferFromFAT (char *filepath, bool silent)
int int
SaveBufferToFAT (char *filepath, int datasize, bool silent) SaveBufferToFAT (char *filepath, int datasize, bool silent)
{ {
FILE *handle; if (datasize)
if (datasize)
{ {
handle = fopen (filepath, "wb"); fatfile = fopen (filepath, "wb");
if (handle <= 0) if (fatfile <= 0)
{ {
char msg[100]; char msg[100];
sprintf(msg, "Couldn't save %s", filepath); sprintf(msg, "Couldn't save %s", filepath);
@ -274,8 +290,8 @@ SaveBufferToFAT (char *filepath, int datasize, bool silent)
return 0; return 0;
} }
fwrite (savebuffer, 1, datasize, handle); fwrite (savebuffer, 1, datasize, fatfile);
fclose (handle); fclose (fatfile);
} }
return datasize; return datasize;
} }

View File

@ -27,9 +27,11 @@
bool ChangeFATInterface(int method, bool silent); bool ChangeFATInterface(int method, bool silent);
int ParseFATdirectory(int method); int ParseFATdirectory(int method);
int LoadFATFile (char * fbuffer, int length); int LoadFATFile (char * fbuffer, int length);
int LoadFATSzFile(char * filepath, unsigned char * rbuffer);
int SaveBufferToFAT (char *filepath, int datasize, bool silent); int SaveBufferToFAT (char *filepath, int datasize, bool silent);
int LoadBufferFromFAT (char *filepath, bool silent); int LoadBufferFromFAT (char *filepath, bool silent);
extern char currFATdir[MAXPATHLEN]; extern char currFATdir[MAXPATHLEN];
extern FILE * fatfile;
#endif #endif

View File

@ -43,6 +43,7 @@ extern "C" {
int offset; int offset;
int selection; int selection;
char currentdir[MAXPATHLEN]; char currentdir[MAXPATHLEN];
char szpath[MAXPATHLEN];
int maxfiles; int maxfiles;
extern int screenheight; extern int screenheight;
unsigned long SNESROMSize = 0; unsigned long SNESROMSize = 0;
@ -53,6 +54,7 @@ extern int dvddirlength;
// Global file entry table // Global file entry table
FILEENTRIES filelist[MAXFILES]; FILEENTRIES filelist[MAXFILES];
bool inSz = false;
unsigned char *savebuffer = NULL; unsigned char *savebuffer = NULL;
@ -192,6 +194,28 @@ int UpdateDirName(int method)
} }
} }
bool MakeROMPath(char filepath[], int method)
{
char temppath[MAXPATHLEN];
// Check filename length
if ((strlen(currentdir)+1+strlen(filelist[selection].filename)) < MAXPATHLEN)
{
sprintf(temppath, "%s/%s",currentdir,filelist[selection].filename);
if(method == METHOD_SMB)
strcpy(filepath, SMBPath(temppath));
else
strcpy(filepath, temppath);
return true;
}
else
{
filepath[0] = 0;
return false;
}
}
/**************************************************************************** /****************************************************************************
* FileSortCallback * FileSortCallback
* *
@ -244,12 +268,14 @@ bool IsValidROM(int method)
if (p != NULL) if (p != NULL)
{ {
if(stricmp(p, ".zip") == 0) if(stricmp(p, ".zip") == 0 && !inSz)
{ {
// we need to check the file extension of the first file in the archive // we need to check the file extension of the first file in the archive
char * zippedFilename = GetFirstZipFilename (method); char * zippedFilename = GetFirstZipFilename (method);
if(strlen(zippedFilename) > 4) if(zippedFilename == NULL) // we don't want to run strlen on NULL
p = NULL;
else if(strlen(zippedFilename) > 4)
p = strrchr(zippedFilename, '.'); p = strrchr(zippedFilename, '.');
else else
p = NULL; p = NULL;
@ -268,6 +294,25 @@ bool IsValidROM(int method)
return false; return false;
} }
/****************************************************************************
* IsSz
*
* Checks if the specified file is a 7z
***************************************************************************/
bool IsSz()
{
if (strlen(filelist[selection].filename) > 4)
{
char * p = strrchr(filelist[selection].filename, '.');
if (p != NULL)
if(stricmp(p, ".7z") == 0)
return true;
}
return false;
}
/**************************************************************************** /****************************************************************************
* StripExt * StripExt
* *
@ -342,7 +387,24 @@ int FileSelector (int method)
if (filelist[selection].flags) // This is directory if (filelist[selection].flags) // This is directory
{ {
/* update current directory and set new entry list if directory has changed */ /* update current directory and set new entry list if directory has changed */
int status = UpdateDirName(method); int status;
if(inSz && selection == 0) // inside a 7z, requesting to leave
{
if(method == METHOD_DVD)
{
dvddir = filelist[0].offset;
dvddirlength = filelist[0].length;
}
inSz = false;
status = 1;
SzClose();
}
else
{
status = UpdateDirName(method);
}
if (status == 1) // ok, open directory if (status == 1) // ok, open directory
{ {
switch (method) switch (method)
@ -363,8 +425,8 @@ int FileSelector (int method)
if (!maxfiles) if (!maxfiles)
{ {
WaitPrompt ((char*) "Error reading directory!"); WaitPrompt ((char*) "Error reading directory !");
return 0; // quit menu haverom = 1; // quit menu
} }
} }
else if (status == -1) // directory name too long else if (status == -1) // directory name too long
@ -374,43 +436,69 @@ int FileSelector (int method)
} }
else // this is a file else // this is a file
{ {
// check that this is a valid ROM // 7z file - let's open it up to select a file inside
if(!IsValidROM(method)) if(IsSz())
return 0;
// store the filename (w/o ext) - used for sram/freeze naming
StripExt(Memory.ROMFilename, filelist[selection].filename);
ShowAction ((char *)"Loading...");
switch (method)
{ {
case METHOD_SD: // we'll store the 7z filepath for extraction later
case METHOD_USB: if(!MakeROMPath(szpath, method))
SNESROMSize = LoadFATFile ((char *)Memory.ROM, 0); {
break; WaitPrompt((char*) "Maximum filepath length reached!");
return -1;
case METHOD_DVD: }
dvddir = filelist[selection].offset; maxfiles = SzParse(szpath, method);
dvddirlength = filelist[selection].length; if(maxfiles)
SNESROMSize = LoadDVDFile (Memory.ROM, 0); inSz = true;
break;
case METHOD_SMB:
SNESROMSize = LoadSMBFile ((char *)Memory.ROM, 0);
break;
}
if (SNESROMSize > 0)
{
Memory.LoadROM ("BLANK.SMC");
Memory.LoadSRAM ("BLANK");
haverom = 1;
return 1;
} }
else else
{ {
WaitPrompt((char*) "Error loading ROM!"); // check that this is a valid ROM
if(!IsValidROM(method))
return 0;
// store the filename (w/o ext) - used for sram/freeze naming
StripExt(Memory.ROMFilename, filelist[selection].filename);
ShowAction ((char *)"Loading...");
SNESROMSize = 0;
switch (method)
{
case METHOD_SD:
case METHOD_USB:
if(inSz)
SNESROMSize = LoadFATSzFile(szpath, (unsigned char *)Memory.ROM);
else
SNESROMSize = LoadFATFile ((char *)Memory.ROM, 0);
break;
case METHOD_DVD:
if(inSz)
SNESROMSize = SzExtractFile(filelist[selection].offset, (unsigned char *)Memory.ROM);
else
SNESROMSize = LoadDVDFile (Memory.ROM, 0);
break;
case METHOD_SMB:
if(inSz)
SNESROMSize = LoadSMBSzFile(szpath, (unsigned char *)Memory.ROM);
else
SNESROMSize = LoadSMBFile ((char *)Memory.ROM, 0);
break;
}
inSz = false;
if (SNESROMSize > 0)
{
Memory.LoadROM ("BLANK.SMC");
Memory.LoadSRAM ("BLANK");
haverom = 1;
return 1;
}
else
{
WaitPrompt((char*) "Error loading ROM!");
}
} }
} }
redraw = 1; redraw = 1;

View File

@ -40,6 +40,7 @@ extern unsigned long SNESROMSize;
void AllocSaveBuffer(); void AllocSaveBuffer();
void FreeSaveBuffer(); void FreeSaveBuffer();
bool MakeROMPath(char filepath[], int method);
int OpenROM (int method); int OpenROM (int method);
int autoLoadMethod(); int autoLoadMethod();
int autoSaveMethod(); int autoSaveMethod();

View File

@ -96,7 +96,7 @@ DefaultSettings ()
// Graphics // Graphics
Settings.Transparency = true; Settings.Transparency = true;
Settings.SupportHiRes = true; Settings.SupportHiRes = true;
Settings.SkipFrames = 10; Settings.SkipFrames = AUTO_FRAMERATE;
Settings.TurboSkipFrames = 19; Settings.TurboSkipFrames = 19;
Settings.DisplayFrameRate = false; Settings.DisplayFrameRate = false;
Settings.AutoDisplayMessages = 0; Settings.AutoDisplayMessages = 0;

View File

@ -32,7 +32,10 @@ bool networkShareInit = false;
unsigned int SMBTimer = 0; unsigned int SMBTimer = 0;
#define SMBTIMEOUT ( 3600 ) // Some implementations timeout in 10 minutes #define SMBTIMEOUT ( 3600 ) // Some implementations timeout in 10 minutes
// SMB connection/file handles - the only ones we should ever use!
SMBCONN smbconn; SMBCONN smbconn;
SMBFILE smbfile;
#define ZIPCHUNK 16384 #define ZIPCHUNK 16384
/**************************************************************************** /****************************************************************************
@ -212,6 +215,15 @@ ParseSMBdirectory ()
return filecount; return filecount;
} }
/****************************************************************************
* Open SMB file
***************************************************************************/
SMBFILE OpenSMBFile(char * filepath)
{
return SMB_OpenFile (SMBPath(filepath), SMB_OPEN_READING, SMB_OF_OPEN, smbconn);
}
/**************************************************************************** /****************************************************************************
* Load SMB file * Load SMB file
* rom - pointer to memory where ROM will be stored * rom - pointer to memory where ROM will be stored
@ -223,14 +235,38 @@ LoadSMBFile (char * rom, int length)
char filepath[MAXPATHLEN]; char filepath[MAXPATHLEN];
/* Check filename length */ /* Check filename length */
if ((strlen(currentdir)+1+strlen(filelist[selection].filename)) < MAXPATHLEN) if (!MakeROMPath(filepath, METHOD_SMB))
sprintf(filepath, "%s/%s",currentdir,filelist[selection].filename);
else
{ {
WaitPrompt((char*) "Maximum filepath length reached!"); WaitPrompt((char*) "Maximum filepath length reached!");
return -1; return -1;
} }
return LoadBufferFromSMB(rom, SMBPath(filepath), length, NOTSILENT); return LoadBufferFromSMB(rom, filepath, length, NOTSILENT);
}
/****************************************************************************
* LoadSMBSzFile
* Loads the selected file # from the specified 7z into rbuffer
* Returns file size
***************************************************************************/
int
LoadSMBSzFile(char * filepath, unsigned char * rbuffer)
{
if(!ConnectShare (NOTSILENT))
return 0;
smbfile = OpenSMBFile(filepath);
if (smbfile)
{
u32 size = SzExtractFile(filelist[selection].offset, rbuffer);
SMB_CloseFile (smbfile);
return size;
}
else
{
WaitPrompt((char*) "Error opening file");
return 0;
}
} }
/**************************************************************************** /****************************************************************************
@ -249,7 +285,6 @@ SaveBufferToSMB (char * sbuffer, char *filepath, int datasize, bool silent)
if(!ConnectShare (NOTSILENT)) if(!ConnectShare (NOTSILENT))
return 0; return 0;
SMBFILE smbfile;
int dsize = datasize; int dsize = datasize;
int wrote = 0; int wrote = 0;
int boffset = 0; int boffset = 0;
@ -301,12 +336,10 @@ LoadBufferFromSMB (char * sbuffer, char *filepath, int length, bool silent)
if(!ConnectShare (NOTSILENT)) if(!ConnectShare (NOTSILENT))
return 0; return 0;
SMBFILE smbfile;
int ret; int ret;
int boffset = 0; int boffset = 0;
smbfile = smbfile = OpenSMBFile(filepath);
SMB_OpenFile (SMBPath(filepath), SMB_OPEN_READING, SMB_OF_OPEN, smbconn);
if (!smbfile) if (!smbfile)
{ {
@ -329,7 +362,7 @@ LoadBufferFromSMB (char * sbuffer, char *filepath, int length, bool silent)
if (IsZipFile (sbuffer)) if (IsZipFile (sbuffer))
{ {
boffset = UnZipFile ((unsigned char *)sbuffer, smbfile); // unzip from SMB boffset = UnZipBuffer ((unsigned char *)sbuffer, METHOD_SMB); // unzip from SMB
} }
else else
{ {

View File

@ -14,14 +14,21 @@
#define _NGCSMB_ #define _NGCSMB_
#include <smb.h>
bool InitializeNetwork(bool silent); bool InitializeNetwork(bool silent);
bool ConnectShare (bool silent); bool ConnectShare (bool silent);
char * SMBPath(char * path); char * SMBPath(char * path);
int UpdateSMBdirname(); int UpdateSMBdirname();
int ParseSMBdirectory (); int ParseSMBdirectory ();
SMBFILE OpenSMBFile(char * filepath);
int LoadSMBFile (char * fbuffer, int length); int LoadSMBFile (char * fbuffer, int length);
int LoadSMBSzFile(char * filepath, unsigned char * rbuffer);
int LoadBufferFromSMB (char *filepath, bool silent); int LoadBufferFromSMB (char *filepath, bool silent);
int LoadBufferFromSMB (char * sbuffer, char *filepath, int length, bool silent); int LoadBufferFromSMB (char * sbuffer, char *filepath, int length, bool silent);
int SaveBufferToSMB (char *filepath, int datasize, bool silent); int SaveBufferToSMB (char *filepath, int datasize, bool silent);
int SaveBufferToSMB (char * sbuffer, char *filepath, int datasize, bool silent); int SaveBufferToSMB (char * sbuffer, char *filepath, int datasize, bool silent);
extern SMBFILE smbfile;
#endif #endif

View File

@ -204,7 +204,6 @@ main ()
DI_Init(); // first DI_Init(); // first
#endif #endif
unsigned int save_flags;
int selectedMenu = -1; int selectedMenu = -1;
// Initialise video // Initialise video
@ -325,10 +324,6 @@ main ()
MainMenu (selectedMenu); MainMenu (selectedMenu);
} }
// Load ROM
save_flags = CPU.Flags;
CPU.Flags = save_flags;
// Emulate // Emulate
emulate (); emulate ();

View File

@ -16,6 +16,12 @@
#include <string.h> #include <string.h>
#include <zlib.h> #include <zlib.h>
extern "C" {
#include "../sz/7zCrc.h"
#include "../sz/7zIn.h"
#include "../sz/7zExtract.h"
}
#include "snes9xGX.h" #include "snes9xGX.h"
#include "dvd.h" #include "dvd.h"
#include "smbop.h" #include "smbop.h"
@ -77,17 +83,14 @@ IsZipFile (char *buffer)
return 0; return 0;
} }
/***************************************************************************** /*****************************************************************************
* unzip * UnZipBuffer
* *
* It should be noted that there is a limit of 5MB total size for any ROM * It should be noted that there is a limit of 5MB total size for any ROM
******************************************************************************/ ******************************************************************************/
FILE* fatfile; // FAT
u64 discoffset; // DVD
SMBFILE smbfile; // SMB
int int
UnZipBuffer (unsigned char *outbuffer, short where) UnZipBuffer (unsigned char *outbuffer, int method)
{ {
PKZIPHEADER pkzip; PKZIPHEADER pkzip;
int zipoffset = 0; int zipoffset = 0;
@ -100,22 +103,25 @@ UnZipBuffer (unsigned char *outbuffer, short where)
int have = 0; int have = 0;
char readbuffer[ZIPCHUNK]; char readbuffer[ZIPCHUNK];
char msg[128]; char msg[128];
u64 discoffset = 0;
/*** Read Zip Header ***/ // Read Zip Header
switch (where) switch (method)
{ {
case 0: // SD Card case METHOD_SD:
fseek(fatfile, 0, SEEK_SET); case METHOD_USB:
fread (readbuffer, 1, ZIPCHUNK, fatfile); fseek(fatfile, 0, SEEK_SET);
break; fread (readbuffer, 1, ZIPCHUNK, fatfile);
break;
case 1: // DVD case METHOD_DVD:
dvd_read (readbuffer, ZIPCHUNK, discoffset); discoffset = dvddir;
break; dvd_read (readbuffer, ZIPCHUNK, discoffset);
break;
case 2: // From SMB case METHOD_SMB:
SMB_ReadFile(readbuffer, ZIPCHUNK, 0, smbfile); SMB_ReadFile(readbuffer, ZIPCHUNK, 0, smbfile);
break; break;
} }
/*** Copy PKZip header to local, used as info ***/ /*** Copy PKZip header to local, used as info ***/
@ -175,25 +181,26 @@ UnZipBuffer (unsigned char *outbuffer, short where)
} }
while (zs.avail_out == 0); while (zs.avail_out == 0);
/*** Readup the next 2k block ***/ // Readup the next 2k block
zipoffset = 0; zipoffset = 0;
zipchunk = ZIPCHUNK; zipchunk = ZIPCHUNK;
switch (where) switch (method)
{ {
case 0: // SD Card case METHOD_SD:
fread (readbuffer, 1, ZIPCHUNK, fatfile); case METHOD_USB:
break; fread (readbuffer, 1, ZIPCHUNK, fatfile);
break;
case 1: // DVD case METHOD_DVD:
readoffset += ZIPCHUNK; readoffset += ZIPCHUNK;
dvd_read (readbuffer, ZIPCHUNK, discoffset+readoffset); dvd_read (readbuffer, ZIPCHUNK, discoffset+readoffset);
break; break;
case 2: // From SMB case METHOD_SMB:
readoffset += ZIPCHUNK; readoffset += ZIPCHUNK;
SMB_ReadFile(readbuffer, ZIPCHUNK, readoffset, smbfile); SMB_ReadFile(readbuffer, ZIPCHUNK, readoffset, smbfile);
break; break;
} }
} }
while (res != Z_STREAM_END); while (res != Z_STREAM_END);
@ -210,62 +217,345 @@ UnZipBuffer (unsigned char *outbuffer, short where)
return 0; return 0;
} }
// Reading from FAT
int
UnZipFile (unsigned char *outbuffer, FILE* infile)
{
fatfile = infile;
return UnZipBuffer(outbuffer, 0);
}
// Reading from DVD
int
UnZipFile (unsigned char *outbuffer, u64 inoffset)
{
discoffset = inoffset;
return UnZipBuffer(outbuffer, 1);
}
// Reading from SMB
int
UnZipFile (unsigned char *outbuffer, SMBFILE infile)
{
smbfile = infile;
return UnZipBuffer(outbuffer, 2);
}
/**************************************************************************** /****************************************************************************
* GetFirstZipFilename * GetFirstZipFilename
* *
* Returns the filename of the first file in the zipped archive * Returns the filename of the first file in the zipped archive
* The idea here is to do the least amount of work required * The idea here is to do the least amount of work required
***************************************************************************/ ***************************************************************************/
char * char *
GetFirstZipFilename (int method) GetFirstZipFilename (int method)
{ {
char testbuffer[ZIPCHUNK]; char * firstFilename = NULL;
char tempbuffer[ZIPCHUNK];
// read start of ZIP // read start of ZIP
switch (method) switch (method)
{ {
case METHOD_SD: // SD Card case METHOD_SD: // SD Card
case METHOD_USB: // USB case METHOD_USB: // USB
LoadFATFile (testbuffer, ZIPCHUNK); LoadFATFile (tempbuffer, ZIPCHUNK);
break; break;
case METHOD_DVD: // DVD case METHOD_DVD: // DVD
LoadDVDFile ((unsigned char *)testbuffer, ZIPCHUNK); LoadDVDFile ((unsigned char *)tempbuffer, ZIPCHUNK);
break; break;
case METHOD_SMB: // From SMB case METHOD_SMB: // From SMB
LoadSMBFile (testbuffer, ZIPCHUNK); LoadSMBFile (tempbuffer, ZIPCHUNK);
break; break;
} }
testbuffer[28] = 0; // truncate - filename length is 2 bytes long (bytes 26-27) tempbuffer[28] = 0; // truncate - filename length is 2 bytes long (bytes 26-27)
int namelength = testbuffer[26]; // filename length starts 26 bytes in int namelength = tempbuffer[26]; // filename length starts 26 bytes in
char * firstFilename = &testbuffer[30]; // first filename of a ZIP starts 31 bytes in firstFilename = &tempbuffer[30]; // first filename of a ZIP starts 31 bytes in
firstFilename[namelength] = 0; // truncate at filename length firstFilename[namelength] = 0; // truncate at filename length
return firstFilename; return firstFilename;
} }
/****************************************************************************
* 7z functions
***************************************************************************/
typedef struct _SzFileInStream
{
ISzInStream InStream;
u64 offset; // offset of the file
unsigned int len; // length of the file
u64 pos; // current position of the file pointer
} SzFileInStream;
// 7zip error list
char szerrormsg[][30] = {
"7z: Data error",
"7z: Out of memory",
"7z: CRC Error",
"7z: Not implemented",
"7z: Fail",
"7z: Archive error",
"7z: Dictionary too large",
};
SZ_RESULT SzRes;
SzFileInStream SzArchiveStream;
CArchiveDatabaseEx SzDb;
ISzAlloc SzAllocImp;
ISzAlloc SzAllocTempImp;
UInt32 SzBlockIndex = 0xFFFFFFFF;
size_t SzBufferSize;
size_t SzOffset;
size_t SzOutSizeProcessed;
CFileItem *SzF;
char sz_buffer[2048];
int szMethod = 0;
/****************************************************************************
* Is7ZipFile
*
* Returns 1 when 7z signature is found
****************************************************************************/
int
Is7ZipFile (char *buffer)
{
unsigned int *check;
check = (unsigned int *) buffer;
// 7z signature
static Byte Signature[6] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};
int i;
for(i = 0; i < 6; i++)
if(buffer[i] != Signature[i])
return 0;
return 1; // 7z archive found
}
// display an error message
void SzDisplayError(SZ_RESULT res)
{
WaitPrompt(szerrormsg[(res - 1)]);
}
// function used by the 7zip SDK to read data from SD/USB/DVD/SMB
SZ_RESULT SzFileReadImp(void *object, void **buffer, size_t maxRequiredSize, size_t *processedSize)
{
// the void* object is a SzFileInStream
SzFileInStream *s = (SzFileInStream *)object;
// calculate offset
u64 offset = (u64)(s->offset + s->pos);
if(maxRequiredSize > 2048)
maxRequiredSize = 2048;
// read data
switch(szMethod)
{
case METHOD_SD:
case METHOD_USB:
fseek(fatfile, offset, SEEK_SET);
fread (sz_buffer, 1, maxRequiredSize, fatfile);
break;
case METHOD_DVD:
dvd_safe_read(sz_buffer, maxRequiredSize, offset);
break;
case METHOD_SMB:
SMB_ReadFile(sz_buffer, maxRequiredSize, offset, smbfile);
break;
}
*buffer = sz_buffer;
*processedSize = maxRequiredSize;
s->pos += *processedSize;
return SZ_OK;
}
// function used by the 7zip SDK to change the filepointer
SZ_RESULT SzFileSeekImp(void *object, CFileSize pos)
{
// the void* object is a SzFileInStream
SzFileInStream *s = (SzFileInStream *)object;
// check if the 7z SDK wants to move the pointer to somewhere after the EOF
if(pos >= s->len)
{
WaitPrompt((char *)"7z Error: The 7z SDK wants to start reading somewhere behind the EOF...");
return SZE_FAIL;
}
// save new position and return
s->pos = pos;
return SZ_OK;
}
/****************************************************************************
* SzParse
*
* Opens a 7z file, and parses it
* Right now doesn't parse 7z, since we'll always use the first file
* But it could parse the entire 7z for full browsing capability
***************************************************************************/
int SzParse(char * filepath, int method)
{
int nbfiles = 0;
// save the offset and the length of this file inside the archive stream structure
SzArchiveStream.offset = filelist[selection].offset;
SzArchiveStream.len = filelist[selection].length;
SzArchiveStream.pos = 0;
// open file
switch (method)
{
case METHOD_SD:
case METHOD_USB:
fatfile = fopen (filepath, "rb");
if(!fatfile)
return 0;
break;
case METHOD_SMB:
smbfile = OpenSMBFile(filepath);
if(!smbfile)
return 0;
break;
}
// set szMethod to current chosen load method
szMethod = method;
// set handler functions for reading data from FAT/SMB/DVD
SzArchiveStream.InStream.Read = SzFileReadImp;
SzArchiveStream.InStream.Seek = SzFileSeekImp;
// set default 7Zip SDK handlers for allocation and freeing memory
SzAllocImp.Alloc = SzAlloc;
SzAllocImp.Free = SzFree;
SzAllocTempImp.Alloc = SzAllocTemp;
SzAllocTempImp.Free = SzFreeTemp;
// prepare CRC and 7Zip database structures
InitCrcTable();
SzArDbExInit(&SzDb);
// open the archive
SzRes = SzArchiveOpen(&SzArchiveStream.InStream, &SzDb, &SzAllocImp,
&SzAllocTempImp);
if (SzRes != SZ_OK)
{
SzDisplayError(SzRes);
// free memory used by the 7z SDK
SzClose();
}
else // archive opened successfully
{
if(SzDb.Database.NumFiles > 0)
{
// Parses the 7z into a full file listing
// store the current 7z data
unsigned int oldLength = filelist[selection].length;
u64 oldOffset = filelist[selection].offset;
// erase all previous entries
memset(&filelist, 0, sizeof(FILEENTRIES) * MAXFILES);
// add '..' folder
strncpy(filelist[0].displayname, "..", 2);
filelist[0].flags = 1;
filelist[0].length = oldLength;
filelist[0].offset = oldOffset; // in case the user wants exit 7z
// get contents and parse them into file list structure
unsigned int SzI, SzJ;
SzJ = 1;
for (SzI = 0; SzI < SzDb.Database.NumFiles; SzI++)
{
SzF = SzDb.Database.Files + SzI;
// skip directories
if (SzF->IsDirectory)
continue;
// do not exceed MAXFILES to avoid possible buffer overflows
if (SzJ == (MAXFILES - 1))
break;
// parse information about this file to the dvd file list structure
strncpy(filelist[SzJ].filename, SzF->Name, MAXJOLIET); // copy joliet name (useless...)
filelist[SzJ].filename[MAXJOLIET] = 0; // terminate string
strncpy(filelist[SzJ].displayname, SzF->Name, MAXDISPLAY+1); // crop name for display
filelist[SzJ].length = SzF->Size; // filesize
filelist[SzJ].offset = SzI; // the extraction function identifies the file with this number
filelist[SzJ].flags = 0; // only files will be displayed (-> no flags)
SzJ++;
}
// update maxfiles and select the first entry
offset = selection = 0;
nbfiles = SzJ;
}
else
{
SzArDbExFree(&SzDb, SzAllocImp.Free);
}
}
// close file
switch (method)
{
case METHOD_SD:
case METHOD_USB:
fclose(fatfile);
break;
case METHOD_SMB:
SMB_CloseFile (smbfile);
break;
}
return nbfiles;
}
/****************************************************************************
* SzClose
*
* Closes a 7z file
***************************************************************************/
void SzClose()
{
if(SzDb.Database.NumFiles > 0)
SzArDbExFree(&SzDb, SzAllocImp.Free);
}
/****************************************************************************
* SzExtractFile
*
* Extracts the given file # into the buffer specified
* Must parse the 7z BEFORE running this function
***************************************************************************/
int SzExtractFile(int i, unsigned char *buffer)
{
// prepare some variables
SzBlockIndex = 0xFFFFFFFF;
SzOffset = 0;
// Unzip the file
ShowAction((char *)"Unzipping file. Please wait...");
SzRes = SzExtract2(
&SzArchiveStream.InStream,
&SzDb,
i, // index of file
&SzBlockIndex, // index of solid block
&buffer,
&SzBufferSize,
&SzOffset, // offset of stream for required file in *outBuffer
&SzOutSizeProcessed, // size of file in *outBuffer
&SzAllocImp,
&SzAllocTempImp);
// close 7Zip archive and free memory
SzClose();
// check for errors
if(SzRes != SZ_OK)
{
// display error message
SzDisplayError(SzRes);
return 0;
}
else
{
return SzOutSizeProcessed;
}
}

View File

@ -16,9 +16,10 @@
extern int IsZipFile (char *buffer); extern int IsZipFile (char *buffer);
char * GetFirstZipFilename(int method); char * GetFirstZipFilename(int method);
int UnZipFile (unsigned char *outbuffer, FILE* infile); // Reading from FAT int UnZipBuffer (unsigned char *outbuffer, int method);
int UnZipFile (unsigned char *outbuffer, u64 inoffset); // Reading from DVD int SzParse(char * filepath, int method);
int UnZipFile (unsigned char *outbuffer, SMBFILE infile); // Reading from SMB int SzExtractFile(int i, unsigned char *buffer);
void SzClose();
/* /*
* Zip file header definition * Zip file header definition

View File

@ -197,7 +197,7 @@
#else #else
#include <gccore.h> #include <gccore.h>
extern unsigned long ROMSize; extern unsigned long SNESROMSize;
#endif #endif
#include "controls.h" #include "controls.h"
@ -1142,7 +1142,7 @@ uint32 CMemory::FileLoader (uint8 *buffer, const char *filename, int32 maxsize)
***/ ***/
HeaderCount = 0; HeaderCount = 0;
uint8 *ptr = buffer; uint8 *ptr = buffer;
uint32 size = ROMSize; uint32 size = SNESROMSize;
size = HeaderRemove(size, HeaderCount, ptr); size = HeaderRemove(size, HeaderCount, ptr);
ptr += size; ptr += size;

70
source/sz/7zAlloc.c Normal file
View File

@ -0,0 +1,70 @@
/* 7zAlloc.c */
#include <stdlib.h>
#include "7zAlloc.h"
/* #define _SZ_ALLOC_DEBUG */
/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */
#ifdef _SZ_ALLOC_DEBUG
#ifdef _WIN32
#include <windows.h>
#endif
#include <stdio.h>
int g_allocCount = 0;
int g_allocCountTemp = 0;
#endif
void *SzAlloc(size_t size)
{
if (size == 0)
return 0;
#ifdef _SZ_ALLOC_DEBUG
fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount);
g_allocCount++;
#endif
return malloc(size);
}
void SzFree(void *address)
{
#ifdef _SZ_ALLOC_DEBUG
if (address != 0)
{
g_allocCount--;
fprintf(stderr, "\nFree; count = %10d", g_allocCount);
}
#endif
free(address);
}
void *SzAllocTemp(size_t size)
{
if (size == 0)
return 0;
#ifdef _SZ_ALLOC_DEBUG
fprintf(stderr, "\nAlloc_temp %10d bytes; count = %10d", size, g_allocCountTemp);
g_allocCountTemp++;
#ifdef _WIN32
return HeapAlloc(GetProcessHeap(), 0, size);
#endif
#endif
return malloc(size);
}
void SzFreeTemp(void *address)
{
#ifdef _SZ_ALLOC_DEBUG
if (address != 0)
{
g_allocCountTemp--;
fprintf(stderr, "\nFree_temp; count = %10d", g_allocCountTemp);
}
#ifdef _WIN32
HeapFree(GetProcessHeap(), 0, address);
return;
#endif
#endif
free(address);
}

20
source/sz/7zAlloc.h Normal file
View File

@ -0,0 +1,20 @@
/* 7zAlloc.h */
#ifndef __7Z_ALLOC_H
#define __7Z_ALLOC_H
#include <stddef.h>
typedef struct _ISzAlloc
{
void *(*Alloc)(size_t size);
void (*Free)(void *address); /* address can be 0 */
} ISzAlloc;
void *SzAlloc(size_t size);
void SzFree(void *address);
void *SzAllocTemp(size_t size);
void SzFreeTemp(void *address);
#endif

29
source/sz/7zBuffer.c Normal file
View File

@ -0,0 +1,29 @@
/* 7zBuffer.c */
#include "7zBuffer.h"
#include "7zAlloc.h"
void SzByteBufferInit(CSzByteBuffer *buffer)
{
buffer->Capacity = 0;
buffer->Items = 0;
}
int SzByteBufferCreate(CSzByteBuffer *buffer, size_t newCapacity, void * (*allocFunc)(size_t size))
{
buffer->Capacity = newCapacity;
if (newCapacity == 0)
{
buffer->Items = 0;
return 1;
}
buffer->Items = (Byte *)allocFunc(newCapacity);
return (buffer->Items != 0);
}
void SzByteBufferFree(CSzByteBuffer *buffer, void (*freeFunc)(void *))
{
freeFunc(buffer->Items);
buffer->Items = 0;
buffer->Capacity = 0;
}

19
source/sz/7zBuffer.h Normal file
View File

@ -0,0 +1,19 @@
/* 7zBuffer.h */
#ifndef __7Z_BUFFER_H
#define __7Z_BUFFER_H
#include <stddef.h>
#include "7zTypes.h"
typedef struct _CSzByteBuffer
{
size_t Capacity;
Byte *Items;
}CSzByteBuffer;
void SzByteBufferInit(CSzByteBuffer *buffer);
int SzByteBufferCreate(CSzByteBuffer *buffer, size_t newCapacity, void * (*allocFunc)(size_t size));
void SzByteBufferFree(CSzByteBuffer *buffer, void (*freeFunc)(void *));
#endif

76
source/sz/7zCrc.c Normal file
View File

@ -0,0 +1,76 @@
/* 7zCrc.c */
#include "7zCrc.h"
#define kCrcPoly 0xEDB88320
UInt32 g_CrcTable[256];
void InitCrcTable()
{
UInt32 i;
for (i = 0; i < 256; i++)
{
UInt32 r = i;
int j;
for (j = 0; j < 8; j++)
if (r & 1)
r = (r >> 1) ^ kCrcPoly;
else
r >>= 1;
g_CrcTable[i] = r;
}
}
void CrcInit(UInt32 *crc) { *crc = 0xFFFFFFFF; }
UInt32 CrcGetDigest(UInt32 *crc) { return *crc ^ 0xFFFFFFFF; }
void CrcUpdateByte(UInt32 *crc, Byte b)
{
*crc = g_CrcTable[((Byte)(*crc)) ^ b] ^ (*crc >> 8);
}
void CrcUpdateUInt16(UInt32 *crc, UInt16 v)
{
CrcUpdateByte(crc, (Byte)v);
CrcUpdateByte(crc, (Byte)(v >> 8));
}
void CrcUpdateUInt32(UInt32 *crc, UInt32 v)
{
int i;
for (i = 0; i < 4; i++)
CrcUpdateByte(crc, (Byte)(v >> (8 * i)));
}
void CrcUpdateUInt64(UInt32 *crc, UInt64 v)
{
int i;
for (i = 0; i < 8; i++)
{
CrcUpdateByte(crc, (Byte)(v));
v >>= 8;
}
}
void CrcUpdate(UInt32 *crc, const void *data, size_t size)
{
UInt32 v = *crc;
const Byte *p = (const Byte *)data;
for (; size > 0 ; size--, p++)
v = g_CrcTable[((Byte)(v)) ^ *p] ^ (v >> 8);
*crc = v;
}
UInt32 CrcCalculateDigest(const void *data, size_t size)
{
UInt32 crc;
CrcInit(&crc);
CrcUpdate(&crc, data, size);
return CrcGetDigest(&crc);
}
int CrcVerifyDigest(UInt32 digest, const void *data, size_t size)
{
return (CrcCalculateDigest(data, size) == digest);
}

24
source/sz/7zCrc.h Normal file
View File

@ -0,0 +1,24 @@
/* 7zCrc.h */
#ifndef __7Z_CRC_H
#define __7Z_CRC_H
#include <stddef.h>
#include "7zTypes.h"
extern UInt32 g_CrcTable[256];
void InitCrcTable();
void CrcInit(UInt32 *crc);
UInt32 CrcGetDigest(UInt32 *crc);
void CrcUpdateByte(UInt32 *crc, Byte v);
void CrcUpdateUInt16(UInt32 *crc, UInt16 v);
void CrcUpdateUInt32(UInt32 *crc, UInt32 v);
void CrcUpdateUInt64(UInt32 *crc, UInt64 v);
void CrcUpdate(UInt32 *crc, const void *data, size_t size);
UInt32 CrcCalculateDigest(const void *data, size_t size);
int CrcVerifyDigest(UInt32 digest, const void *data, size_t size);
#endif

309
source/sz/7zDecode.c Normal file
View File

@ -0,0 +1,309 @@
/* 7zDecode.c */
#include "7zDecode.h"
#ifdef _SZ_ONE_DIRECTORY
#include "LzmaDecode.h"
#else
#include "../../Compress/LZMA_C/LzmaDecode.h"
#endif
#ifdef _LZMA_OUT_READ
#include <string.h> // for memcpy
#endif
CMethodID k_Copy = { { 0x0 }, 1 };
CMethodID k_LZMA = { { 0x3, 0x1, 0x1 }, 3 };
#ifdef _LZMA_IN_CB
typedef struct _CLzmaInCallbackImp
{
ILzmaInCallback InCallback;
ISzInStream *InStream;
size_t Size;
} CLzmaInCallbackImp;
int LzmaReadImp(void *object, const unsigned char **buffer, SizeT *size)
{
CLzmaInCallbackImp *cb = (CLzmaInCallbackImp *)object;
size_t processedSize;
SZ_RESULT res;
*size = 0;
res = cb->InStream->Read((void *)cb->InStream, (void **)buffer, cb->Size, &processedSize);
*size = (SizeT)processedSize;
if (processedSize > cb->Size)
return (int)SZE_FAIL;
cb->Size -= processedSize;
if (res == SZ_OK)
return 0;
return (int)res;
}
#endif
SZ_RESULT SzDecode(const CFileSize *packSizes, const CFolder *folder,
#ifdef _LZMA_IN_CB
ISzInStream *inStream,
#else
const Byte *inBuffer,
#endif
Byte *outBuffer, size_t outSize,
size_t *outSizeProcessed, ISzAlloc *allocMain)
{
UInt32 si;
size_t inSize = 0;
CCoderInfo *coder;
if (folder->NumPackStreams != 1)
return SZE_NOTIMPL;
if (folder->NumCoders != 1)
return SZE_NOTIMPL;
coder = folder->Coders;
*outSizeProcessed = 0;
for (si = 0; si < folder->NumPackStreams; si++)
inSize += (size_t)packSizes[si];
if (AreMethodsEqual(&coder->MethodID, &k_Copy))
{
size_t i;
if (inSize != outSize)
return SZE_DATA_ERROR;
#ifdef _LZMA_IN_CB
for (i = 0; i < inSize;)
{
size_t j;
Byte *inBuffer;
size_t bufferSize;
RINOK(inStream->Read((void *)inStream, (void **)&inBuffer, inSize - i, &bufferSize));
if (bufferSize == 0)
return SZE_DATA_ERROR;
if (bufferSize > inSize - i)
return SZE_FAIL;
*outSizeProcessed += bufferSize;
for (j = 0; j < bufferSize && i < inSize; j++, i++)
outBuffer[i] = inBuffer[j];
}
#else
for (i = 0; i < inSize; i++)
outBuffer[i] = inBuffer[i];
*outSizeProcessed = inSize;
#endif
return SZ_OK;
}
if (AreMethodsEqual(&coder->MethodID, &k_LZMA))
{
#ifdef _LZMA_IN_CB
CLzmaInCallbackImp lzmaCallback;
#else
SizeT inProcessed;
#endif
CLzmaDecoderState state; /* it's about 24-80 bytes structure, if int is 32-bit */
int result;
SizeT outSizeProcessedLoc;
#ifdef _LZMA_IN_CB
lzmaCallback.Size = inSize;
lzmaCallback.InStream = inStream;
lzmaCallback.InCallback.Read = LzmaReadImp;
#endif
if (LzmaDecodeProperties(&state.Properties, coder->Properties.Items,
coder->Properties.Capacity) != LZMA_RESULT_OK)
return SZE_FAIL;
state.Probs = (CProb *)allocMain->Alloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb));
if (state.Probs == 0)
return SZE_OUTOFMEMORY;
#ifdef _LZMA_OUT_READ
if (state.Properties.DictionarySize == 0)
state.Dictionary = 0;
else
{
state.Dictionary = (unsigned char *)allocMain->Alloc(state.Properties.DictionarySize);
if (state.Dictionary == 0)
{
allocMain->Free(state.Probs);
return SZE_OUTOFMEMORYDIC;
}
}
LzmaDecoderInit(&state);
#endif
result = LzmaDecode(&state,
#ifdef _LZMA_IN_CB
&lzmaCallback.InCallback,
#else
inBuffer, (SizeT)inSize, &inProcessed,
#endif
outBuffer, (SizeT)outSize, &outSizeProcessedLoc);
*outSizeProcessed = (size_t)outSizeProcessedLoc;
allocMain->Free(state.Probs);
#ifdef _LZMA_OUT_READ
allocMain->Free(state.Dictionary);
#endif
if (result == LZMA_RESULT_DATA_ERROR)
return SZE_DATA_ERROR;
if (result != LZMA_RESULT_OK)
return SZE_FAIL;
return SZ_OK;
}
return SZE_NOTIMPL;
}
#ifdef _LZMA_OUT_READ
// like SzDecode but uses less memory
SZ_RESULT SzDecode2(const CFileSize *packSizes, const CFolder *folder,
ISzInStream *inStream,
Byte *outBuffer, size_t outSize,
size_t *outSizeProcessed, ISzAlloc *allocMain,
size_t *fileOffset, size_t *fileSize)
{
UInt32 si;
size_t inSize = 0;
CCoderInfo *coder;
if (folder->NumPackStreams != 1)
return SZE_NOTIMPL;
if (folder->NumCoders != 1)
return SZE_NOTIMPL;
coder = folder->Coders;
*outSizeProcessed = 0;
for (si = 0; si < folder->NumPackStreams; si++)
inSize += (size_t)packSizes[si];
if (AreMethodsEqual(&coder->MethodID, &k_Copy))
{
size_t i;
if (inSize != outSize)
return SZE_DATA_ERROR;
#ifdef _LZMA_IN_CB
for (i = 0; i < inSize;)
{
size_t j;
Byte *inBuffer;
size_t bufferSize;
RINOK(inStream->Read((void *)inStream, (void **)&inBuffer, inSize - i, &bufferSize));
if (bufferSize == 0)
return SZE_DATA_ERROR;
if (bufferSize > inSize - i)
return SZE_FAIL;
*outSizeProcessed += bufferSize;
for (j = 0; j < bufferSize && i < inSize; j++, i++)
outBuffer[i] = inBuffer[j];
}
#else
for (i = 0; i < inSize; i++)
outBuffer[i] = inBuffer[i];
*outSizeProcessed = inSize;
#endif
return SZ_OK;
}
if (AreMethodsEqual(&coder->MethodID, &k_LZMA))
{
#ifdef _LZMA_IN_CB
CLzmaInCallbackImp lzmaCallback;
#else
SizeT inProcessed;
#endif
CLzmaDecoderState state; /* it's about 24-80 bytes structure, if int is 32-bit */
int result;
SizeT outSizeProcessedLoc;
#ifdef _LZMA_IN_CB
lzmaCallback.Size = inSize;
lzmaCallback.InStream = inStream;
lzmaCallback.InCallback.Read = LzmaReadImp;
#endif
if (LzmaDecodeProperties(&state.Properties, coder->Properties.Items,
coder->Properties.Capacity) != LZMA_RESULT_OK)
return SZE_FAIL;
state.Probs = (CProb *)allocMain->Alloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb));
if (state.Probs == 0)
return SZE_OUTOFMEMORY;
if (state.Properties.DictionarySize == 0)
state.Dictionary = 0;
else
{
state.Dictionary = (unsigned char *)allocMain->Alloc(state.Properties.DictionarySize);
if (state.Dictionary == 0)
{
allocMain->Free(state.Probs);
return SZE_OUTOFMEMORY;
}
}
LzmaDecoderInit(&state);
// allocate memory for the temporary buffer
Byte *tmpBuffer = (Byte *)allocMain->Alloc(_LZMA_TEMP_BUFFER_SIZE);
// decompress data in _LZMA_TEMP_BUFFER_SIZE byte steps and copy the wanted file to outBuffer
size_t bytesLeft = *fileSize; // total bytes remaining to be read
size_t bytesToRead = 0; // bytes to read on this pass
size_t bytesRead = 0; // total bytes read
size_t offset = 0; // buffer offset
do
{
if(bytesLeft > _LZMA_TEMP_BUFFER_SIZE)
bytesToRead = _LZMA_TEMP_BUFFER_SIZE;
else
bytesToRead = bytesLeft;
bytesLeft -= bytesToRead;
// decompress next bytes
result = LzmaDecode(&state,
#ifdef _LZMA_IN_CB
&lzmaCallback.InCallback,
#else
//inBuffer, (SizeT)inSize, &inProcessed, //TODO!
#endif
tmpBuffer, bytesToRead, &outSizeProcessedLoc
);
// check result
if(result == LZMA_RESULT_DATA_ERROR)
return SZE_DATA_ERROR;
else if(result != LZMA_RESULT_OK)
return SZE_FAIL;
// normally this should never happen
if(outSizeProcessedLoc > _LZMA_TEMP_BUFFER_SIZE)
{
return SZE_FAIL;
}
memcpy(outBuffer + offset, tmpBuffer, outSizeProcessedLoc);
bytesRead += bytesToRead;
offset += outSizeProcessedLoc;
}
while(bytesLeft > 0);
/* result = LzmaDecode(&state,
#ifdef _LZMA_IN_CB
&lzmaCallback.InCallback,
#else
inBuffer, (SizeT)inSize, &inProcessed,
#endif
outBuffer, (SizeT)outSize, &outSizeProcessedLoc);*/
//*outSizeProcessed = (size_t)outSizeProcessedLoc;
*outSizeProcessed = offset;
allocMain->Free(tmpBuffer); // free the temporary buffer again
allocMain->Free(state.Probs);
allocMain->Free(state.Dictionary);
/* if (result == LZMA_RESULT_DATA_ERROR)
return SZE_DATA_ERROR;
if (result != LZMA_RESULT_OK)
return SZE_FAIL;*/
return SZ_OK;
}
return SZE_NOTIMPL;
}
#endif

37
source/sz/7zDecode.h Normal file
View File

@ -0,0 +1,37 @@
/* 7zDecode.h */
#if defined(_LZMA_OUT_READ) && !defined(_LZMA_IN_CB)
#error "Fixme: _LZMA_OUT_READ && _LZMA_IN_CB isn't currently possible!"
#endif
#ifndef __7Z_DECODE_H
#define __7Z_DECODE_H
#include "7zItem.h"
#include "7zAlloc.h"
#ifdef _LZMA_IN_CB
#include "7zIn.h"
#endif
SZ_RESULT SzDecode(const CFileSize *packSizes, const CFolder *folder,
#ifdef _LZMA_IN_CB
ISzInStream *stream,
#else
const Byte *inBuffer,
#endif
Byte *outBuffer, size_t outSize,
size_t *outSizeProcessed, ISzAlloc *allocMain);
#ifdef _LZMA_OUT_READ
#ifndef _LZMA_TEMP_BUFFER_SIZE
#define _LZMA_TEMP_BUFFER_SIZE (2048) // size of the temporary buffer in bytes
#endif
SZ_RESULT SzDecode2(const CFileSize *packSizes, const CFolder *folder,
ISzInStream *stream,
Byte *outBuffer, size_t outSize,
size_t *outSizeProcessed, ISzAlloc *allocMain,
size_t *fileOffset, size_t *fileSize);
#endif // #ifdef _LZMA_OUT_READ
#endif

254
source/sz/7zExtract.c Normal file
View File

@ -0,0 +1,254 @@
/* 7zExtract.c */
#include "7zExtract.h"
#include "7zDecode.h"
#include "7zCrc.h"
SZ_RESULT SzExtract(
ISzInStream *inStream,
CArchiveDatabaseEx *db,
UInt32 fileIndex,
UInt32 *blockIndex,
Byte **outBuffer,
size_t *outBufferSize,
size_t *offset,
size_t *outSizeProcessed,
ISzAlloc *allocMain,
ISzAlloc *allocTemp)
{
UInt32 folderIndex = db->FileIndexToFolderIndexMap[fileIndex];
SZ_RESULT res = SZ_OK;
*offset = 0;
*outSizeProcessed = 0;
if (folderIndex == (UInt32)-1)
{
allocMain->Free(*outBuffer);
*blockIndex = folderIndex;
*outBuffer = 0;
*outBufferSize = 0;
return SZ_OK;
}
if (*outBuffer == 0 || *blockIndex != folderIndex)
{
CFolder *folder = db->Database.Folders + folderIndex;
CFileSize unPackSize = SzFolderGetUnPackSize(folder);
#ifndef _LZMA_IN_CB
CFileSize packSize = SzArDbGetFolderFullPackSize(db, folderIndex);
Byte *inBuffer = 0;
size_t processedSize;
#endif
*blockIndex = folderIndex;
allocMain->Free(*outBuffer);
*outBuffer = 0;
RINOK(inStream->Seek(inStream, SzArDbGetFolderStreamPos(db, folderIndex, 0)));
#ifndef _LZMA_IN_CB
if (packSize != 0)
{
inBuffer = (Byte *)allocTemp->Alloc((size_t)packSize);
if (inBuffer == 0)
return SZE_OUTOFMEMORY;
}
res = inStream->Read(inStream, inBuffer, (size_t)packSize, &processedSize);
if (res == SZ_OK && processedSize != (size_t)packSize)
res = SZE_FAIL;
#endif
if (res == SZ_OK)
{
*outBufferSize = (size_t)unPackSize;
if (unPackSize != 0)
{
*outBuffer = (Byte *)allocMain->Alloc((size_t)unPackSize);
if (*outBuffer == 0)
res = SZE_OUTOFMEMORY;
}
if (res == SZ_OK)
{
size_t outRealSize;
res = SzDecode(db->Database.PackSizes +
db->FolderStartPackStreamIndex[folderIndex], folder,
#ifdef _LZMA_IN_CB
inStream,
#else
inBuffer,
#endif
*outBuffer, (size_t)unPackSize, &outRealSize, allocTemp);
if (res == SZ_OK)
{
if (outRealSize == (size_t)unPackSize)
{
if (folder->UnPackCRCDefined)
{
if (!CrcVerifyDigest(folder->UnPackCRC, *outBuffer, (size_t)unPackSize))
res = SZE_FAIL;
}
}
else
res = SZE_FAIL;
}
}
}
#ifndef _LZMA_IN_CB
allocTemp->Free(inBuffer);
#endif
}
if (res == SZ_OK)
{
UInt32 i;
CFileItem *fileItem = db->Database.Files + fileIndex;
*offset = 0;
for(i = db->FolderStartFileIndex[folderIndex]; i < fileIndex; i++)
*offset += (UInt32)db->Database.Files[i].Size;
*outSizeProcessed = (size_t)fileItem->Size;
if (*offset + *outSizeProcessed > *outBufferSize)
return SZE_FAIL;
{
if (fileItem->IsFileCRCDefined)
{
if (!CrcVerifyDigest(fileItem->FileCRC, *outBuffer + *offset, *outSizeProcessed))
res = SZE_FAIL;
}
}
}
return res;
}
#ifdef _LZMA_OUT_READ
// similar to SzExtract but needs less memory
SZ_RESULT SzExtract2(
ISzInStream *inStream,
CArchiveDatabaseEx *db,
UInt32 fileIndex,
UInt32 *blockIndex,
Byte **outBuffer,
size_t *outBufferSize,
size_t *offset,
size_t *outSizeProcessed,
ISzAlloc *allocMain,
ISzAlloc *allocTemp)
{
UInt32 folderIndex = db->FileIndexToFolderIndexMap[fileIndex];
SZ_RESULT res = SZ_OK;
*offset = 0;
*outSizeProcessed = 0;
if (folderIndex == (UInt32)-1)
{
*blockIndex = folderIndex;
#ifndef NGC
allocMain->Free(*outBuffer);
*outBuffer = 0;
#endif
*outBufferSize = 0;
return SZ_OK;
}
// if (*outBuffer == 0 || *blockIndex != folderIndex)
// {
CFolder *folder = db->Database.Folders + folderIndex;
CFileSize unPackSize = SzFolderGetUnPackSize(folder);
#ifndef _LZMA_IN_CB
CFileSize packSize = SzArDbGetFolderFullPackSize(db, folderIndex);
Byte *inBuffer = 0;
size_t processedSize;
#endif
*blockIndex = folderIndex;
#ifndef NGC
allocMain->Free(*outBuffer);
*outBuffer = 0;
#endif
RINOK(inStream->Seek(inStream, SzArDbGetFolderStreamPos(db, folderIndex, 0)));
#ifndef _LZMA_IN_CB
if (packSize != 0)
{
inBuffer = (Byte *)allocTemp->Alloc((size_t)packSize);
if (inBuffer == 0)
return SZE_OUTOFMEMORY;
}
res = inStream->Read(inStream, inBuffer, (size_t)packSize, &processedSize);
if (res == SZ_OK && processedSize != (size_t)packSize)
res = SZE_FAIL;
#endif
if (res == SZ_OK)
{
// calculate file offset and filesize
CFileItem *fileItem = db->Database.Files + fileIndex;
UInt32 i;
*offset = 0;
for(i = db->FolderStartFileIndex[folderIndex]; i < fileIndex; i++)
*offset += (UInt32)db->Database.Files[i].Size;
*outSizeProcessed = (size_t)fileItem->Size;
*outBufferSize = (size_t)fileItem->Size;
if (unPackSize != 0)
{
#ifndef NGC
*outBuffer = (Byte *)allocMain->Alloc((size_t)fileItem->Size);
if (*outBuffer == 0)
res = SZE_OUTOFMEMORY;
#endif
}
if (res == SZ_OK)
{
size_t outRealSize;
res = SzDecode2(db->Database.PackSizes +
db->FolderStartPackStreamIndex[folderIndex], folder,
#ifdef _LZMA_IN_CB
inStream,
#else
inBuffer,
#endif
*outBuffer, (size_t)unPackSize, &outRealSize, allocTemp,
offset, outSizeProcessed
);
*outSizeProcessed = outRealSize;
/* if (res == SZ_OK) // we can't validate the CRC of the whole data stream because we only extracted the wanted file
{
if (outRealSize == (size_t)unPackSize)
{
if (folder->UnPackCRCDefined)
{
if (!CrcVerifyDigest(folder->UnPackCRC, *outBuffer, (size_t)unPackSize))
res = SZE_FAIL;
}
}
else
res = SZE_FAIL;
}*/
}
// }
#ifndef _LZMA_IN_CB
allocTemp->Free(inBuffer);
#endif
}
if (res == SZ_OK)
{
/* UInt32 i;
CFileItem *fileItem = db->Database.Files + fileIndex;
*offset = 0;
for(i = db->FolderStartFileIndex[folderIndex]; i < fileIndex; i++)
*offset += (UInt32)db->Database.Files[i].Size;
*outSizeProcessed = (size_t)fileItem->Size;*/
//CFileItem *fileItem = db->Database.Files + fileIndex;
if (/**offset +*/ *outSizeProcessed > *outBufferSize)
return SZE_FAIL;
{
//if (fileItem->IsFileCRCDefined)
//{
// if (!CrcVerifyDigest(fileItem->FileCRC, *outBuffer/* + *offset*/, *outSizeProcessed))
// res = SZE_CRC_ERROR; // why does SzExtract return SZE_FAIL when we can return SZE_CRC_ERROR?
//}
}
}
// change *offset to 0 because SzExtract normally decompresses the whole solid block
// and sets *offset to the offset of the wanted file.
// SzDecode2 does only copy the needed file to the output buffer and has to set *offset
// to 0 to ensure compatibility with SzExtract
*offset = 0;
return res;
}
#endif

60
source/sz/7zExtract.h Normal file
View File

@ -0,0 +1,60 @@
/* 7zExtract.h */
#if defined(_LZMA_OUT_READ) && !defined(_LZMA_IN_CB)
#error "Fixme: _LZMA_OUT_READ && _LZMA_IN_CB isn't currently possible!"
#endif
#ifndef __7Z_EXTRACT_H
#define __7Z_EXTRACT_H
#include "7zIn.h"
/*
SzExtract extracts file from archive
SzExtract2 does the same but needs less memory
*outBuffer must be 0 before first call for each new archive.
Extracting cache:
If you need to decompress more than one file, you can send
these values from previous call:
*blockIndex,
*outBuffer,
*outBufferSize
You can consider "*outBuffer" as cache of solid block. If your archive is solid,
it will increase decompression speed.
If you use external function, you can declare these 3 cache variables
(blockIndex, outBuffer, outBufferSize) as static in that external function.
Free *outBuffer and set *outBuffer to 0, if you want to flush cache.
*/
SZ_RESULT SzExtract(
ISzInStream *inStream,
CArchiveDatabaseEx *db,
UInt32 fileIndex, /* index of file */
UInt32 *blockIndex, /* index of solid block */
Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */
size_t *outBufferSize, /* buffer size for output buffer */
size_t *offset, /* offset of stream for required file in *outBuffer */
size_t *outSizeProcessed, /* size of file in *outBuffer */
ISzAlloc *allocMain,
ISzAlloc *allocTemp);
#ifdef _LZMA_OUT_READ
SZ_RESULT SzExtract2(
ISzInStream *inStream,
CArchiveDatabaseEx *db,
UInt32 fileIndex, /* index of file */
UInt32 *blockIndex, /* index of solid block */
Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */
size_t *outBufferSize, /* buffer size for output buffer */
size_t *offset, /* offset of stream for required file in *outBuffer */
size_t *outSizeProcessed, /* size of file in *outBuffer */
ISzAlloc *allocMain,
ISzAlloc *allocTemp);
#endif
#endif

5
source/sz/7zHeader.c Normal file
View File

@ -0,0 +1,5 @@
/* 7zHeader.c */
#include "7zHeader.h"
Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};

55
source/sz/7zHeader.h Normal file
View File

@ -0,0 +1,55 @@
/* 7zHeader.h */
#ifndef __7Z_HEADER_H
#define __7Z_HEADER_H
#include "7zTypes.h"
#define k7zSignatureSize 6
extern Byte k7zSignature[k7zSignatureSize];
#define k7zMajorVersion 0
#define k7zStartHeaderSize 0x20
enum EIdEnum
{
k7zIdEnd,
k7zIdHeader,
k7zIdArchiveProperties,
k7zIdAdditionalStreamsInfo,
k7zIdMainStreamsInfo,
k7zIdFilesInfo,
k7zIdPackInfo,
k7zIdUnPackInfo,
k7zIdSubStreamsInfo,
k7zIdSize,
k7zIdCRC,
k7zIdFolder,
k7zIdCodersUnPackSize,
k7zIdNumUnPackStream,
k7zIdEmptyStream,
k7zIdEmptyFile,
k7zIdAnti,
k7zIdName,
k7zIdCreationTime,
k7zIdLastAccessTime,
k7zIdLastWriteTime,
k7zIdWinAttributes,
k7zIdComment,
k7zIdEncodedHeader,
k7zIdStartPos
};
#endif

1281
source/sz/7zIn.c Normal file

File diff suppressed because it is too large Load Diff

55
source/sz/7zIn.h Normal file
View File

@ -0,0 +1,55 @@
/* 7zIn.h */
#ifndef __7Z_IN_H
#define __7Z_IN_H
#include "7zHeader.h"
#include "7zItem.h"
#include "7zAlloc.h"
typedef struct _CInArchiveInfo
{
CFileSize StartPositionAfterHeader;
CFileSize DataStartPosition;
}CInArchiveInfo;
typedef struct _CArchiveDatabaseEx
{
CArchiveDatabase Database;
CInArchiveInfo ArchiveInfo;
UInt32 *FolderStartPackStreamIndex;
CFileSize *PackStreamStartPositions;
UInt32 *FolderStartFileIndex;
UInt32 *FileIndexToFolderIndexMap;
}CArchiveDatabaseEx;
void SzArDbExInit(CArchiveDatabaseEx *db);
void SzArDbExFree(CArchiveDatabaseEx *db, void (*freeFunc)(void *));
CFileSize SzArDbGetFolderStreamPos(CArchiveDatabaseEx *db, UInt32 folderIndex, UInt32 indexInFolder);
CFileSize SzArDbGetFolderFullPackSize(CArchiveDatabaseEx *db, UInt32 folderIndex);
typedef struct _ISzInStream
{
#ifdef _LZMA_IN_CB
SZ_RESULT (*Read)(
void *object, /* pointer to ISzInStream itself */
void **buffer, /* out: pointer to buffer with data */
size_t maxRequiredSize, /* max required size to read */
size_t *processedSize); /* real processed size.
processedSize can be less than maxRequiredSize.
If processedSize == 0, then there are no more
bytes in stream. */
#else
SZ_RESULT (*Read)(void *object, void *buffer, size_t size, size_t *processedSize);
#endif
SZ_RESULT (*Seek)(void *object, CFileSize pos);
} ISzInStream;
int SzArchiveOpen(
ISzInStream *inStream,
CArchiveDatabaseEx *db,
ISzAlloc *allocMain,
ISzAlloc *allocTemp);
#endif

133
source/sz/7zItem.c Normal file
View File

@ -0,0 +1,133 @@
/* 7zItem.c */
#include "7zItem.h"
#include "7zAlloc.h"
void SzCoderInfoInit(CCoderInfo *coder)
{
SzByteBufferInit(&coder->Properties);
}
void SzCoderInfoFree(CCoderInfo *coder, void (*freeFunc)(void *p))
{
SzByteBufferFree(&coder->Properties, freeFunc);
SzCoderInfoInit(coder);
}
void SzFolderInit(CFolder *folder)
{
folder->NumCoders = 0;
folder->Coders = 0;
folder->NumBindPairs = 0;
folder->BindPairs = 0;
folder->NumPackStreams = 0;
folder->PackStreams = 0;
folder->UnPackSizes = 0;
folder->UnPackCRCDefined = 0;
folder->UnPackCRC = 0;
folder->NumUnPackStreams = 0;
}
void SzFolderFree(CFolder *folder, void (*freeFunc)(void *p))
{
UInt32 i;
for (i = 0; i < folder->NumCoders; i++)
SzCoderInfoFree(&folder->Coders[i], freeFunc);
freeFunc(folder->Coders);
freeFunc(folder->BindPairs);
freeFunc(folder->PackStreams);
freeFunc(folder->UnPackSizes);
SzFolderInit(folder);
}
UInt32 SzFolderGetNumOutStreams(CFolder *folder)
{
UInt32 result = 0;
UInt32 i;
for (i = 0; i < folder->NumCoders; i++)
result += folder->Coders[i].NumOutStreams;
return result;
}
int SzFolderFindBindPairForInStream(CFolder *folder, UInt32 inStreamIndex)
{
UInt32 i;
for(i = 0; i < folder->NumBindPairs; i++)
if (folder->BindPairs[i].InIndex == inStreamIndex)
return i;
return -1;
}
int SzFolderFindBindPairForOutStream(CFolder *folder, UInt32 outStreamIndex)
{
UInt32 i;
for(i = 0; i < folder->NumBindPairs; i++)
if (folder->BindPairs[i].OutIndex == outStreamIndex)
return i;
return -1;
}
CFileSize SzFolderGetUnPackSize(CFolder *folder)
{
int i = (int)SzFolderGetNumOutStreams(folder);
if (i == 0)
return 0;
for (i--; i >= 0; i--)
if (SzFolderFindBindPairForOutStream(folder, i) < 0)
return folder->UnPackSizes[i];
/* throw 1; */
return 0;
}
/*
int FindPackStreamArrayIndex(int inStreamIndex) const
{
for(int i = 0; i < PackStreams.Size(); i++)
if (PackStreams[i] == inStreamIndex)
return i;
return -1;
}
*/
void SzFileInit(CFileItem *fileItem)
{
fileItem->IsFileCRCDefined = 0;
fileItem->HasStream = 1;
fileItem->IsDirectory = 0;
fileItem->IsAnti = 0;
fileItem->Name = 0;
}
void SzFileFree(CFileItem *fileItem, void (*freeFunc)(void *p))
{
freeFunc(fileItem->Name);
SzFileInit(fileItem);
}
void SzArchiveDatabaseInit(CArchiveDatabase *db)
{
db->NumPackStreams = 0;
db->PackSizes = 0;
db->PackCRCsDefined = 0;
db->PackCRCs = 0;
db->NumFolders = 0;
db->Folders = 0;
db->NumFiles = 0;
db->Files = 0;
}
void SzArchiveDatabaseFree(CArchiveDatabase *db, void (*freeFunc)(void *))
{
UInt32 i;
for (i = 0; i < db->NumFolders; i++)
SzFolderFree(&db->Folders[i], freeFunc);
for (i = 0; i < db->NumFiles; i++)
SzFileFree(&db->Files[i], freeFunc);
freeFunc(db->PackSizes);
freeFunc(db->PackCRCsDefined);
freeFunc(db->PackCRCs);
freeFunc(db->Folders);
freeFunc(db->Files);
SzArchiveDatabaseInit(db);
}

90
source/sz/7zItem.h Normal file
View File

@ -0,0 +1,90 @@
/* 7zItem.h */
#ifndef __7Z_ITEM_H
#define __7Z_ITEM_H
#include "7zMethodID.h"
#include "7zHeader.h"
#include "7zBuffer.h"
typedef struct _CCoderInfo
{
UInt32 NumInStreams;
UInt32 NumOutStreams;
CMethodID MethodID;
CSzByteBuffer Properties;
}CCoderInfo;
void SzCoderInfoInit(CCoderInfo *coder);
void SzCoderInfoFree(CCoderInfo *coder, void (*freeFunc)(void *p));
typedef struct _CBindPair
{
UInt32 InIndex;
UInt32 OutIndex;
}CBindPair;
typedef struct _CFolder
{
UInt32 NumCoders;
CCoderInfo *Coders;
UInt32 NumBindPairs;
CBindPair *BindPairs;
UInt32 NumPackStreams;
UInt32 *PackStreams;
CFileSize *UnPackSizes;
int UnPackCRCDefined;
UInt32 UnPackCRC;
UInt32 NumUnPackStreams;
}CFolder;
void SzFolderInit(CFolder *folder);
CFileSize SzFolderGetUnPackSize(CFolder *folder);
int SzFolderFindBindPairForInStream(CFolder *folder, UInt32 inStreamIndex);
UInt32 SzFolderGetNumOutStreams(CFolder *folder);
CFileSize SzFolderGetUnPackSize(CFolder *folder);
/* #define CArchiveFileTime UInt64 */
typedef struct _CFileItem
{
/*
CArchiveFileTime LastWriteTime;
CFileSize StartPos;
UInt32 Attributes;
*/
CFileSize Size;
UInt32 FileCRC;
char *Name;
Byte IsFileCRCDefined;
Byte HasStream;
Byte IsDirectory;
Byte IsAnti;
/*
int AreAttributesDefined;
int IsLastWriteTimeDefined;
int IsStartPosDefined;
*/
}CFileItem;
void SzFileInit(CFileItem *fileItem);
typedef struct _CArchiveDatabase
{
UInt32 NumPackStreams;
CFileSize *PackSizes;
Byte *PackCRCsDefined;
UInt32 *PackCRCs;
UInt32 NumFolders;
CFolder *Folders;
UInt32 NumFiles;
CFileItem *Files;
}CArchiveDatabase;
void SzArchiveDatabaseInit(CArchiveDatabase *db);
void SzArchiveDatabaseFree(CArchiveDatabase *db, void (*freeFunc)(void *));
#endif

14
source/sz/7zMethodID.c Normal file
View File

@ -0,0 +1,14 @@
/* 7zMethodID.c */
#include "7zMethodID.h"
int AreMethodsEqual(CMethodID *a1, CMethodID *a2)
{
int i;
if (a1->IDSize != a2->IDSize)
return 0;
for (i = 0; i < a1->IDSize; i++)
if (a1->ID[i] != a2->ID[i])
return 0;
return 1;
}

18
source/sz/7zMethodID.h Normal file
View File

@ -0,0 +1,18 @@
/* 7zMethodID.h */
#ifndef __7Z_METHOD_ID_H
#define __7Z_METHOD_ID_H
#include "7zTypes.h"
#define kMethodIDSize 15
typedef struct _CMethodID
{
Byte ID[kMethodIDSize];
Byte IDSize;
} CMethodID;
int AreMethodsEqual(CMethodID *a1, CMethodID *a2);
#endif

71
source/sz/7zTypes.h Normal file
View File

@ -0,0 +1,71 @@
/* 7zTypes.h */
#ifndef __COMMON_TYPES_H
#define __COMMON_TYPES_H
#ifndef _7ZIP_BYTE_DEFINED
#define _7ZIP_BYTE_DEFINED
#ifndef ZCONF_H
typedef unsigned char Byte;
#endif
#endif
#ifndef _7ZIP_UINT16_DEFINED
#define _7ZIP_UINT16_DEFINED
typedef unsigned short UInt16;
#endif
#ifndef _7ZIP_UINT32_DEFINED
#define _7ZIP_UINT32_DEFINED
#ifdef _LZMA_UINT32_IS_ULONG
typedef unsigned long UInt32;
#else
typedef unsigned int UInt32;
#endif
#endif
/* #define _SZ_NO_INT_64 */
/* define it your compiler doesn't support long long int */
#ifndef _7ZIP_UINT64_DEFINED
#define _7ZIP_UINT64_DEFINED
#ifdef _SZ_NO_INT_64
typedef unsigned long UInt64;
#else
#ifdef _MSC_VER
typedef unsigned __int64 UInt64;
#else
typedef unsigned long long int UInt64;
#endif
#endif
#endif
/* #define _SZ_FILE_SIZE_64 */
/* Use _SZ_FILE_SIZE_64 if you need support for files larger than 4 GB*/
#ifndef CFileSize
#ifdef _SZ_FILE_SIZE_64
typedef UInt64 CFileSize;
#else
typedef UInt32 CFileSize;
#endif
#endif
#define SZ_RESULT int
#define SZ_OK (0)
#define SZE_DATA_ERROR (1)
#define SZE_OUTOFMEMORY (2)
#define SZE_CRC_ERROR (3)
#define SZE_NOTIMPL (4)
#define SZE_FAIL (5)
#define SZE_ARCHIVE_ERROR (6)
#define SZE_OUTOFMEMORYDIC (7)
#define RINOK(x) { int __result_ = (x); if(__result_ != 0) return __result_; }
#endif

584
source/sz/LzmaDecode.c Normal file
View File

@ -0,0 +1,584 @@
/*
LzmaDecode.c
LZMA Decoder (optimized for Speed version)
LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
http://www.7-zip.org/
LZMA SDK is licensed under two licenses:
1) GNU Lesser General Public License (GNU LGPL)
2) Common Public License (CPL)
It means that you can select one of these two licenses and
follow rules of that license.
SPECIAL EXCEPTION:
Igor Pavlov, as the author of this Code, expressly permits you to
statically or dynamically link your Code (or bind by name) to the
interfaces of this file without subjecting your linked Code to the
terms of the CPL or GNU LGPL. Any modifications or additions
to this file, however, are subject to the LGPL or CPL terms.
*/
#include "LzmaDecode.h"
#define kNumTopBits 24
#define kTopValue ((UInt32)1 << kNumTopBits)
#define kNumBitModelTotalBits 11
#define kBitModelTotal (1 << kNumBitModelTotalBits)
#define kNumMoveBits 5
#define RC_READ_BYTE (*Buffer++)
#define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \
{ int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }}
#ifdef _LZMA_IN_CB
#define RC_TEST { if (Buffer == BufferLim) \
{ SizeT size; int result = InCallback->Read(InCallback, &Buffer, &size); if (result != LZMA_RESULT_OK) return result; \
BufferLim = Buffer + size; if (size == 0) return LZMA_RESULT_DATA_ERROR; }}
#define RC_INIT Buffer = BufferLim = 0; RC_INIT2
#else
#define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; }
#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2
#endif
#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)
#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;
#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;
#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \
{ UpdateBit0(p); mi <<= 1; A0; } else \
{ UpdateBit1(p); mi = (mi + mi) + 1; A1; }
#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;)
#define RangeDecoderBitTreeDecode(probs, numLevels, res) \
{ int i = numLevels; res = 1; \
do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \
res -= (1 << numLevels); }
#define kNumPosBitsMax 4
#define kNumPosStatesMax (1 << kNumPosBitsMax)
#define kLenNumLowBits 3
#define kLenNumLowSymbols (1 << kLenNumLowBits)
#define kLenNumMidBits 3
#define kLenNumMidSymbols (1 << kLenNumMidBits)
#define kLenNumHighBits 8
#define kLenNumHighSymbols (1 << kLenNumHighBits)
#define LenChoice 0
#define LenChoice2 (LenChoice + 1)
#define LenLow (LenChoice2 + 1)
#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
#define kNumStates 12
#define kNumLitStates 7
#define kStartPosModelIndex 4
#define kEndPosModelIndex 14
#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
#define kNumPosSlotBits 6
#define kNumLenToPosStates 4
#define kNumAlignBits 4
#define kAlignTableSize (1 << kNumAlignBits)
#define kMatchMinLen 2
#define IsMatch 0
#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
#define IsRepG0 (IsRep + kNumStates)
#define IsRepG1 (IsRepG0 + kNumStates)
#define IsRepG2 (IsRepG1 + kNumStates)
#define IsRep0Long (IsRepG2 + kNumStates)
#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
#define LenCoder (Align + kAlignTableSize)
#define RepLenCoder (LenCoder + kNumLenProbs)
#define Literal (RepLenCoder + kNumLenProbs)
#if Literal != LZMA_BASE_SIZE
StopCompilingDueBUG
#endif
int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size)
{
unsigned char prop0;
if (size < LZMA_PROPERTIES_SIZE)
return LZMA_RESULT_DATA_ERROR;
prop0 = propsData[0];
if (prop0 >= (9 * 5 * 5))
return LZMA_RESULT_DATA_ERROR;
{
for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5));
for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9);
propsRes->lc = prop0;
/*
unsigned char remainder = (unsigned char)(prop0 / 9);
propsRes->lc = prop0 % 9;
propsRes->pb = remainder / 5;
propsRes->lp = remainder % 5;
*/
}
#ifdef _LZMA_OUT_READ
{
int i;
propsRes->DictionarySize = 0;
for (i = 0; i < 4; i++)
propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8);
if (propsRes->DictionarySize == 0)
propsRes->DictionarySize = 1;
}
#endif
return LZMA_RESULT_OK;
}
#define kLzmaStreamWasFinishedId (-1)
int LzmaDecode(CLzmaDecoderState *vs,
#ifdef _LZMA_IN_CB
ILzmaInCallback *InCallback,
#else
const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
#endif
unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed)
{
CProb *p = vs->Probs;
SizeT nowPos = 0;
Byte previousByte = 0;
UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1;
UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1;
int lc = vs->Properties.lc;
#ifdef _LZMA_OUT_READ
UInt32 Range = vs->Range;
UInt32 Code = vs->Code;
#ifdef _LZMA_IN_CB
const Byte *Buffer = vs->Buffer;
const Byte *BufferLim = vs->BufferLim;
#else
const Byte *Buffer = inStream;
const Byte *BufferLim = inStream + inSize;
#endif
int state = vs->State;
UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
int len = vs->RemainLen;
UInt32 globalPos = vs->GlobalPos;
UInt32 distanceLimit = vs->DistanceLimit;
Byte *dictionary = vs->Dictionary;
UInt32 dictionarySize = vs->Properties.DictionarySize;
UInt32 dictionaryPos = vs->DictionaryPos;
Byte tempDictionary[4];
#ifndef _LZMA_IN_CB
*inSizeProcessed = 0;
#endif
*outSizeProcessed = 0;
if (len == kLzmaStreamWasFinishedId)
return LZMA_RESULT_OK;
if (dictionarySize == 0)
{
dictionary = tempDictionary;
dictionarySize = 1;
tempDictionary[0] = vs->TempDictionary[0];
}
if (len == kLzmaNeedInitId)
{
{
UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
UInt32 i;
for (i = 0; i < numProbs; i++)
p[i] = kBitModelTotal >> 1;
rep0 = rep1 = rep2 = rep3 = 1;
state = 0;
globalPos = 0;
distanceLimit = 0;
dictionaryPos = 0;
dictionary[dictionarySize - 1] = 0;
#ifdef _LZMA_IN_CB
RC_INIT;
#else
RC_INIT(inStream, inSize);
#endif
}
len = 0;
}
while(len != 0 && nowPos < outSize)
{
UInt32 pos = dictionaryPos - rep0;
if (pos >= dictionarySize)
pos += dictionarySize;
outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
if (++dictionaryPos == dictionarySize)
dictionaryPos = 0;
len--;
}
if (dictionaryPos == 0)
previousByte = dictionary[dictionarySize - 1];
else
previousByte = dictionary[dictionaryPos - 1];
#else /* if !_LZMA_OUT_READ */
int state = 0;
UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
int len = 0;
const Byte *Buffer;
const Byte *BufferLim;
UInt32 Range;
UInt32 Code;
#ifndef _LZMA_IN_CB
*inSizeProcessed = 0;
#endif
*outSizeProcessed = 0;
{
UInt32 i;
UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
for (i = 0; i < numProbs; i++)
p[i] = kBitModelTotal >> 1;
}
#ifdef _LZMA_IN_CB
RC_INIT;
#else
RC_INIT(inStream, inSize);
#endif
#endif /* _LZMA_OUT_READ */
while(nowPos < outSize)
{
CProb *prob;
UInt32 bound;
int posState = (int)(
(nowPos
#ifdef _LZMA_OUT_READ
+ globalPos
#endif
)
& posStateMask);
prob = p + IsMatch + (state << kNumPosBitsMax) + posState;
IfBit0(prob)
{
int symbol = 1;
UpdateBit0(prob)
prob = p + Literal + (LZMA_LIT_SIZE *
(((
(nowPos
#ifdef _LZMA_OUT_READ
+ globalPos
#endif
)
& literalPosMask) << lc) + (previousByte >> (8 - lc))));
if (state >= kNumLitStates)
{
int matchByte;
#ifdef _LZMA_OUT_READ
UInt32 pos = dictionaryPos - rep0;
if (pos >= dictionarySize)
pos += dictionarySize;
matchByte = dictionary[pos];
#else
matchByte = outStream[nowPos - rep0];
#endif
do
{
int bit;
CProb *probLit;
matchByte <<= 1;
bit = (matchByte & 0x100);
probLit = prob + 0x100 + bit + symbol;
RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break)
}
while (symbol < 0x100);
}
while (symbol < 0x100)
{
CProb *probLit = prob + symbol;
RC_GET_BIT(probLit, symbol)
}
previousByte = (Byte)symbol;
outStream[nowPos++] = previousByte;
#ifdef _LZMA_OUT_READ
if (distanceLimit < dictionarySize)
distanceLimit++;
dictionary[dictionaryPos] = previousByte;
if (++dictionaryPos == dictionarySize)
dictionaryPos = 0;
#endif
if (state < 4) state = 0;
else if (state < 10) state -= 3;
else state -= 6;
}
else
{
UpdateBit1(prob);
prob = p + IsRep + state;
IfBit0(prob)
{
UpdateBit0(prob);
rep3 = rep2;
rep2 = rep1;
rep1 = rep0;
state = state < kNumLitStates ? 0 : 3;
prob = p + LenCoder;
}
else
{
UpdateBit1(prob);
prob = p + IsRepG0 + state;
IfBit0(prob)
{
UpdateBit0(prob);
prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState;
IfBit0(prob)
{
#ifdef _LZMA_OUT_READ
UInt32 pos;
#endif
UpdateBit0(prob);
#ifdef _LZMA_OUT_READ
if (distanceLimit == 0)
#else
if (nowPos == 0)
#endif
return LZMA_RESULT_DATA_ERROR;
state = state < kNumLitStates ? 9 : 11;
#ifdef _LZMA_OUT_READ
pos = dictionaryPos - rep0;
if (pos >= dictionarySize)
pos += dictionarySize;
previousByte = dictionary[pos];
dictionary[dictionaryPos] = previousByte;
if (++dictionaryPos == dictionarySize)
dictionaryPos = 0;
#else
previousByte = outStream[nowPos - rep0];
#endif
outStream[nowPos++] = previousByte;
#ifdef _LZMA_OUT_READ
if (distanceLimit < dictionarySize)
distanceLimit++;
#endif
continue;
}
else
{
UpdateBit1(prob);
}
}
else
{
UInt32 distance;
UpdateBit1(prob);
prob = p + IsRepG1 + state;
IfBit0(prob)
{
UpdateBit0(prob);
distance = rep1;
}
else
{
UpdateBit1(prob);
prob = p + IsRepG2 + state;
IfBit0(prob)
{
UpdateBit0(prob);
distance = rep2;
}
else
{
UpdateBit1(prob);
distance = rep3;
rep3 = rep2;
}
rep2 = rep1;
}
rep1 = rep0;
rep0 = distance;
}
state = state < kNumLitStates ? 8 : 11;
prob = p + RepLenCoder;
}
{
int numBits, offset;
CProb *probLen = prob + LenChoice;
IfBit0(probLen)
{
UpdateBit0(probLen);
probLen = prob + LenLow + (posState << kLenNumLowBits);
offset = 0;
numBits = kLenNumLowBits;
}
else
{
UpdateBit1(probLen);
probLen = prob + LenChoice2;
IfBit0(probLen)
{
UpdateBit0(probLen);
probLen = prob + LenMid + (posState << kLenNumMidBits);
offset = kLenNumLowSymbols;
numBits = kLenNumMidBits;
}
else
{
UpdateBit1(probLen);
probLen = prob + LenHigh;
offset = kLenNumLowSymbols + kLenNumMidSymbols;
numBits = kLenNumHighBits;
}
}
RangeDecoderBitTreeDecode(probLen, numBits, len);
len += offset;
}
if (state < 4)
{
int posSlot;
state += kNumLitStates;
prob = p + PosSlot +
((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
kNumPosSlotBits);
RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot);
if (posSlot >= kStartPosModelIndex)
{
int numDirectBits = ((posSlot >> 1) - 1);
rep0 = (2 | ((UInt32)posSlot & 1));
if (posSlot < kEndPosModelIndex)
{
rep0 <<= numDirectBits;
prob = p + SpecPos + rep0 - posSlot - 1;
}
else
{
numDirectBits -= kNumAlignBits;
do
{
RC_NORMALIZE
Range >>= 1;
rep0 <<= 1;
if (Code >= Range)
{
Code -= Range;
rep0 |= 1;
}
}
while (--numDirectBits != 0);
prob = p + Align;
rep0 <<= kNumAlignBits;
numDirectBits = kNumAlignBits;
}
{
int i = 1;
int mi = 1;
do
{
CProb *prob3 = prob + mi;
RC_GET_BIT2(prob3, mi, ; , rep0 |= i);
i <<= 1;
}
while(--numDirectBits != 0);
}
}
else
rep0 = posSlot;
if (++rep0 == (UInt32)(0))
{
/* it's for stream version */
len = kLzmaStreamWasFinishedId;
break;
}
}
len += kMatchMinLen;
#ifdef _LZMA_OUT_READ
if (rep0 > distanceLimit)
#else
if (rep0 > nowPos)
#endif
return LZMA_RESULT_DATA_ERROR;
#ifdef _LZMA_OUT_READ
if (dictionarySize - distanceLimit > (UInt32)len)
distanceLimit += len;
else
distanceLimit = dictionarySize;
#endif
do
{
#ifdef _LZMA_OUT_READ
UInt32 pos = dictionaryPos - rep0;
if (pos >= dictionarySize)
pos += dictionarySize;
previousByte = dictionary[pos];
dictionary[dictionaryPos] = previousByte;
if (++dictionaryPos == dictionarySize)
dictionaryPos = 0;
#else
previousByte = outStream[nowPos - rep0];
#endif
len--;
outStream[nowPos++] = previousByte;
}
while(len != 0 && nowPos < outSize);
}
}
RC_NORMALIZE;
#ifdef _LZMA_OUT_READ
vs->Range = Range;
vs->Code = Code;
vs->DictionaryPos = dictionaryPos;
vs->GlobalPos = globalPos + (UInt32)nowPos;
vs->DistanceLimit = distanceLimit;
vs->Reps[0] = rep0;
vs->Reps[1] = rep1;
vs->Reps[2] = rep2;
vs->Reps[3] = rep3;
vs->State = state;
vs->RemainLen = len;
vs->TempDictionary[0] = tempDictionary[0];
#endif
#ifdef _LZMA_IN_CB
vs->Buffer = Buffer;
vs->BufferLim = BufferLim;
#else
*inSizeProcessed = (SizeT)(Buffer - inStream);
#endif
*outSizeProcessed = nowPos;
return LZMA_RESULT_OK;
}

113
source/sz/LzmaDecode.h Normal file
View File

@ -0,0 +1,113 @@
/*
LzmaDecode.h
LZMA Decoder interface
LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
http://www.7-zip.org/
LZMA SDK is licensed under two licenses:
1) GNU Lesser General Public License (GNU LGPL)
2) Common Public License (CPL)
It means that you can select one of these two licenses and
follow rules of that license.
SPECIAL EXCEPTION:
Igor Pavlov, as the author of this code, expressly permits you to
statically or dynamically link your code (or bind by name) to the
interfaces of this file without subjecting your linked code to the
terms of the CPL or GNU LGPL. Any modifications or additions
to this file, however, are subject to the LGPL or CPL terms.
*/
#ifndef __LZMADECODE_H
#define __LZMADECODE_H
#include "LzmaTypes.h"
/* #define _LZMA_IN_CB */
/* Use callback for input data */
/* #define _LZMA_OUT_READ */
/* Use read function for output data */
/* #define _LZMA_PROB32 */
/* It can increase speed on some 32-bit CPUs,
but memory usage will be doubled in that case */
/* #define _LZMA_LOC_OPT */
/* Enable local speed optimizations inside code */
#ifdef _LZMA_PROB32
#define CProb UInt32
#else
#define CProb UInt16
#endif
#define LZMA_RESULT_OK 0
#define LZMA_RESULT_DATA_ERROR 1
#ifdef _LZMA_IN_CB
typedef struct _ILzmaInCallback
{
int (*Read)(void *object, const unsigned char **buffer, SizeT *bufferSize);
} ILzmaInCallback;
#endif
#define LZMA_BASE_SIZE 1846
#define LZMA_LIT_SIZE 768
#define LZMA_PROPERTIES_SIZE 5
typedef struct _CLzmaProperties
{
int lc;
int lp;
int pb;
#ifdef _LZMA_OUT_READ
UInt32 DictionarySize;
#endif
}CLzmaProperties;
int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size);
#define LzmaGetNumProbs(Properties) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((Properties)->lc + (Properties)->lp)))
#define kLzmaNeedInitId (-2)
typedef struct _CLzmaDecoderState
{
CLzmaProperties Properties;
CProb *Probs;
#ifdef _LZMA_IN_CB
const unsigned char *Buffer;
const unsigned char *BufferLim;
#endif
#ifdef _LZMA_OUT_READ
unsigned char *Dictionary;
UInt32 Range;
UInt32 Code;
UInt32 DictionaryPos;
UInt32 GlobalPos;
UInt32 DistanceLimit;
UInt32 Reps[4];
int State;
int RemainLen;
unsigned char TempDictionary[4];
#endif
} CLzmaDecoderState;
#ifdef _LZMA_OUT_READ
#define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; }
#endif
int LzmaDecode(CLzmaDecoderState *vs,
#ifdef _LZMA_IN_CB
ILzmaInCallback *inCallback,
#else
const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
#endif
unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed);
#endif

45
source/sz/LzmaTypes.h Normal file
View File

@ -0,0 +1,45 @@
/*
LzmaTypes.h
Types for LZMA Decoder
This file written and distributed to public domain by Igor Pavlov.
This file is part of LZMA SDK 4.40 (2006-05-01)
*/
#ifndef __LZMATYPES_H
#define __LZMATYPES_H
#ifndef _7ZIP_BYTE_DEFINED
#define _7ZIP_BYTE_DEFINED
typedef unsigned char Byte;
#endif
#ifndef _7ZIP_UINT16_DEFINED
#define _7ZIP_UINT16_DEFINED
typedef unsigned short UInt16;
#endif
#ifndef _7ZIP_UINT32_DEFINED
#define _7ZIP_UINT32_DEFINED
#ifdef _LZMA_UINT32_IS_ULONG
typedef unsigned long UInt32;
#else
typedef unsigned int UInt32;
#endif
#endif
/* #define _LZMA_SYSTEM_SIZE_T */
/* Use system's size_t. You can use it to enable 64-bit sizes supporting */
#ifndef _7ZIP_SIZET_DEFINED
#define _7ZIP_SIZET_DEFINED
#ifdef _LZMA_SYSTEM_SIZE_T
#include <stddef.h>
typedef size_t SizeT;
#else
typedef UInt32 SizeT;
#endif
#endif
#endif