SVN: Applied proper properties to all files, mainly to get native end of lines.

git-svn-id: https://svn.code.sf.net/p/vbam/code/trunk@975 a31d4220-a93d-0410-bf67-fe4944624d44
This commit is contained in:
bgk 2011-02-19 21:33:53 +00:00
parent 35f5665525
commit dee05ff978
81 changed files with 24672 additions and 24672 deletions

View File

@ -1,203 +1,203 @@
/* 7z.h -- 7z interface /* 7z.h -- 7z interface
2010-03-11 : Igor Pavlov : Public domain */ 2010-03-11 : Igor Pavlov : Public domain */
#ifndef __7Z_H #ifndef __7Z_H
#define __7Z_H #define __7Z_H
#include "7zBuf.h" #include "7zBuf.h"
EXTERN_C_BEGIN EXTERN_C_BEGIN
#define k7zStartHeaderSize 0x20 #define k7zStartHeaderSize 0x20
#define k7zSignatureSize 6 #define k7zSignatureSize 6
extern Byte k7zSignature[k7zSignatureSize]; extern Byte k7zSignature[k7zSignatureSize];
#define k7zMajorVersion 0 #define k7zMajorVersion 0
enum EIdEnum enum EIdEnum
{ {
k7zIdEnd, k7zIdEnd,
k7zIdHeader, k7zIdHeader,
k7zIdArchiveProperties, k7zIdArchiveProperties,
k7zIdAdditionalStreamsInfo, k7zIdAdditionalStreamsInfo,
k7zIdMainStreamsInfo, k7zIdMainStreamsInfo,
k7zIdFilesInfo, k7zIdFilesInfo,
k7zIdPackInfo, k7zIdPackInfo,
k7zIdUnpackInfo, k7zIdUnpackInfo,
k7zIdSubStreamsInfo, k7zIdSubStreamsInfo,
k7zIdSize, k7zIdSize,
k7zIdCRC, k7zIdCRC,
k7zIdFolder, k7zIdFolder,
k7zIdCodersUnpackSize, k7zIdCodersUnpackSize,
k7zIdNumUnpackStream, k7zIdNumUnpackStream,
k7zIdEmptyStream, k7zIdEmptyStream,
k7zIdEmptyFile, k7zIdEmptyFile,
k7zIdAnti, k7zIdAnti,
k7zIdName, k7zIdName,
k7zIdCTime, k7zIdCTime,
k7zIdATime, k7zIdATime,
k7zIdMTime, k7zIdMTime,
k7zIdWinAttributes, k7zIdWinAttributes,
k7zIdComment, k7zIdComment,
k7zIdEncodedHeader, k7zIdEncodedHeader,
k7zIdStartPos, k7zIdStartPos,
k7zIdDummy k7zIdDummy
}; };
typedef struct typedef struct
{ {
UInt32 NumInStreams; UInt32 NumInStreams;
UInt32 NumOutStreams; UInt32 NumOutStreams;
UInt64 MethodID; UInt64 MethodID;
CBuf Props; CBuf Props;
} CSzCoderInfo; } CSzCoderInfo;
void SzCoderInfo_Init(CSzCoderInfo *p); void SzCoderInfo_Init(CSzCoderInfo *p);
void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc); void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc);
typedef struct typedef struct
{ {
UInt32 InIndex; UInt32 InIndex;
UInt32 OutIndex; UInt32 OutIndex;
} CSzBindPair; } CSzBindPair;
typedef struct typedef struct
{ {
CSzCoderInfo *Coders; CSzCoderInfo *Coders;
CSzBindPair *BindPairs; CSzBindPair *BindPairs;
UInt32 *PackStreams; UInt32 *PackStreams;
UInt64 *UnpackSizes; UInt64 *UnpackSizes;
UInt32 NumCoders; UInt32 NumCoders;
UInt32 NumBindPairs; UInt32 NumBindPairs;
UInt32 NumPackStreams; UInt32 NumPackStreams;
int UnpackCRCDefined; int UnpackCRCDefined;
UInt32 UnpackCRC; UInt32 UnpackCRC;
UInt32 NumUnpackStreams; UInt32 NumUnpackStreams;
} CSzFolder; } CSzFolder;
void SzFolder_Init(CSzFolder *p); void SzFolder_Init(CSzFolder *p);
UInt64 SzFolder_GetUnpackSize(CSzFolder *p); UInt64 SzFolder_GetUnpackSize(CSzFolder *p);
int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex); int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex);
UInt32 SzFolder_GetNumOutStreams(CSzFolder *p); UInt32 SzFolder_GetNumOutStreams(CSzFolder *p);
UInt64 SzFolder_GetUnpackSize(CSzFolder *p); UInt64 SzFolder_GetUnpackSize(CSzFolder *p);
SRes SzFolder_Decode(const CSzFolder *folder, const UInt64 *packSizes, SRes SzFolder_Decode(const CSzFolder *folder, const UInt64 *packSizes,
ILookInStream *stream, UInt64 startPos, ILookInStream *stream, UInt64 startPos,
Byte *outBuffer, size_t outSize, ISzAlloc *allocMain); Byte *outBuffer, size_t outSize, ISzAlloc *allocMain);
typedef struct typedef struct
{ {
UInt32 Low; UInt32 Low;
UInt32 High; UInt32 High;
} CNtfsFileTime; } CNtfsFileTime;
typedef struct typedef struct
{ {
CNtfsFileTime MTime; CNtfsFileTime MTime;
UInt64 Size; UInt64 Size;
UInt32 Crc; UInt32 Crc;
UInt32 Attrib; UInt32 Attrib;
Byte HasStream; Byte HasStream;
Byte IsDir; Byte IsDir;
Byte IsAnti; Byte IsAnti;
Byte CrcDefined; Byte CrcDefined;
Byte MTimeDefined; Byte MTimeDefined;
Byte AttribDefined; Byte AttribDefined;
} CSzFileItem; } CSzFileItem;
void SzFile_Init(CSzFileItem *p); void SzFile_Init(CSzFileItem *p);
typedef struct typedef struct
{ {
UInt64 *PackSizes; UInt64 *PackSizes;
Byte *PackCRCsDefined; Byte *PackCRCsDefined;
UInt32 *PackCRCs; UInt32 *PackCRCs;
CSzFolder *Folders; CSzFolder *Folders;
CSzFileItem *Files; CSzFileItem *Files;
UInt32 NumPackStreams; UInt32 NumPackStreams;
UInt32 NumFolders; UInt32 NumFolders;
UInt32 NumFiles; UInt32 NumFiles;
} CSzAr; } CSzAr;
void SzAr_Init(CSzAr *p); void SzAr_Init(CSzAr *p);
void SzAr_Free(CSzAr *p, ISzAlloc *alloc); void SzAr_Free(CSzAr *p, ISzAlloc *alloc);
/* /*
SzExtract extracts file from archive SzExtract extracts file from archive
*outBuffer must be 0 before first call for each new archive. *outBuffer must be 0 before first call for each new archive.
Extracting cache: Extracting cache:
If you need to decompress more than one file, you can send If you need to decompress more than one file, you can send
these values from previous call: these values from previous call:
*blockIndex, *blockIndex,
*outBuffer, *outBuffer,
*outBufferSize *outBufferSize
You can consider "*outBuffer" as cache of solid block. If your archive is solid, You can consider "*outBuffer" as cache of solid block. If your archive is solid,
it will increase decompression speed. it will increase decompression speed.
If you use external function, you can declare these 3 cache variables If you use external function, you can declare these 3 cache variables
(blockIndex, outBuffer, outBufferSize) as static in that external function. (blockIndex, outBuffer, outBufferSize) as static in that external function.
Free *outBuffer and set *outBuffer to 0, if you want to flush cache. Free *outBuffer and set *outBuffer to 0, if you want to flush cache.
*/ */
typedef struct typedef struct
{ {
CSzAr db; CSzAr db;
UInt64 startPosAfterHeader; UInt64 startPosAfterHeader;
UInt64 dataPos; UInt64 dataPos;
UInt32 *FolderStartPackStreamIndex; UInt32 *FolderStartPackStreamIndex;
UInt64 *PackStreamStartPositions; UInt64 *PackStreamStartPositions;
UInt32 *FolderStartFileIndex; UInt32 *FolderStartFileIndex;
UInt32 *FileIndexToFolderIndexMap; UInt32 *FileIndexToFolderIndexMap;
size_t *FileNameOffsets; /* in 2-byte steps */ size_t *FileNameOffsets; /* in 2-byte steps */
CBuf FileNames; /* UTF-16-LE */ CBuf FileNames; /* UTF-16-LE */
} CSzArEx; } CSzArEx;
void SzArEx_Init(CSzArEx *p); void SzArEx_Init(CSzArEx *p);
void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc); void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc);
UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder); UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder);
int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize); int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize);
/* /*
if dest == NULL, the return value specifies the required size of the buffer, if dest == NULL, the return value specifies the required size of the buffer,
in 16-bit characters, including the null-terminating character. in 16-bit characters, including the null-terminating character.
if dest != NULL, the return value specifies the number of 16-bit characters that if dest != NULL, the return value specifies the number of 16-bit characters that
are written to the dest, including the null-terminating character. */ are written to the dest, including the null-terminating character. */
size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest); size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest);
SRes SzArEx_Extract( SRes SzArEx_Extract(
const CSzArEx *db, const CSzArEx *db,
ILookInStream *inStream, ILookInStream *inStream,
UInt32 fileIndex, /* index of file */ UInt32 fileIndex, /* index of file */
UInt32 *blockIndex, /* index of solid block */ UInt32 *blockIndex, /* index of solid block */
Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */ Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */
size_t *outBufferSize, /* buffer size for output buffer */ size_t *outBufferSize, /* buffer size for output buffer */
size_t *offset, /* offset of stream for required file in *outBuffer */ size_t *offset, /* offset of stream for required file in *outBuffer */
size_t *outSizeProcessed, /* size of file in *outBuffer */ size_t *outSizeProcessed, /* size of file in *outBuffer */
ISzAlloc *allocMain, ISzAlloc *allocMain,
ISzAlloc *allocTemp); ISzAlloc *allocTemp);
/* /*
SzArEx_Open Errors: SzArEx_Open Errors:
SZ_ERROR_NO_ARCHIVE SZ_ERROR_NO_ARCHIVE
SZ_ERROR_ARCHIVE SZ_ERROR_ARCHIVE
SZ_ERROR_UNSUPPORTED SZ_ERROR_UNSUPPORTED
SZ_ERROR_MEM SZ_ERROR_MEM
SZ_ERROR_CRC SZ_ERROR_CRC
SZ_ERROR_INPUT_EOF SZ_ERROR_INPUT_EOF
SZ_ERROR_FAIL SZ_ERROR_FAIL
*/ */
SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp); SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp);
EXTERN_C_END EXTERN_C_END
#endif #endif

View File

@ -1,15 +1,15 @@
/* 7zAlloc.h -- Allocation functions /* 7zAlloc.h -- Allocation functions
2010-10-29 : Igor Pavlov : Public domain */ 2010-10-29 : Igor Pavlov : Public domain */
#ifndef __7Z_ALLOC_H #ifndef __7Z_ALLOC_H
#define __7Z_ALLOC_H #define __7Z_ALLOC_H
#include <stdlib.h> #include <stdlib.h>
void *SzAlloc(void *p, size_t size); void *SzAlloc(void *p, size_t size);
void SzFree(void *p, void *address); void SzFree(void *p, void *address);
void *SzAllocTemp(void *p, size_t size); void *SzAllocTemp(void *p, size_t size);
void SzFreeTemp(void *p, void *address); void SzFreeTemp(void *p, void *address);
#endif #endif

View File

@ -1,36 +1,36 @@
/* 7zBuf.c -- Byte Buffer /* 7zBuf.c -- Byte Buffer
2008-03-28 2008-03-28
Igor Pavlov Igor Pavlov
Public domain */ Public domain */
#include "7zBuf.h" #include "7zBuf.h"
void Buf_Init(CBuf *p) void Buf_Init(CBuf *p)
{ {
p->data = 0; p->data = 0;
p->size = 0; p->size = 0;
} }
int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc) int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc)
{ {
p->size = 0; p->size = 0;
if (size == 0) if (size == 0)
{ {
p->data = 0; p->data = 0;
return 1; return 1;
} }
p->data = (Byte *)alloc->Alloc(alloc, size); p->data = (Byte *)alloc->Alloc(alloc, size);
if (p->data != 0) if (p->data != 0)
{ {
p->size = size; p->size = size;
return 1; return 1;
} }
return 0; return 0;
} }
void Buf_Free(CBuf *p, ISzAlloc *alloc) void Buf_Free(CBuf *p, ISzAlloc *alloc)
{ {
alloc->Free(alloc, p->data); alloc->Free(alloc, p->data);
p->data = 0; p->data = 0;
p->size = 0; p->size = 0;
} }

View File

@ -1,39 +1,39 @@
/* 7zBuf.h -- Byte Buffer /* 7zBuf.h -- Byte Buffer
2009-02-07 : Igor Pavlov : Public domain */ 2009-02-07 : Igor Pavlov : Public domain */
#ifndef __7Z_BUF_H #ifndef __7Z_BUF_H
#define __7Z_BUF_H #define __7Z_BUF_H
#include "Types.h" #include "Types.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
typedef struct typedef struct
{ {
Byte *data; Byte *data;
size_t size; size_t size;
} CBuf; } CBuf;
void Buf_Init(CBuf *p); void Buf_Init(CBuf *p);
int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc); int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc);
void Buf_Free(CBuf *p, ISzAlloc *alloc); void Buf_Free(CBuf *p, ISzAlloc *alloc);
typedef struct typedef struct
{ {
Byte *data; Byte *data;
size_t size; size_t size;
size_t pos; size_t pos;
} CDynBuf; } CDynBuf;
void DynBuf_Construct(CDynBuf *p); void DynBuf_Construct(CDynBuf *p);
void DynBuf_SeekToBeg(CDynBuf *p); void DynBuf_SeekToBeg(CDynBuf *p);
int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc); int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc);
void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc); void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif #endif

View File

@ -1,74 +1,74 @@
/* 7zCrc.c -- CRC32 calculation /* 7zCrc.c -- CRC32 calculation
2009-11-23 : Igor Pavlov : Public domain */ 2009-11-23 : Igor Pavlov : Public domain */
#include "7zCrc.h" #include "7zCrc.h"
#include "CpuArch.h" #include "CpuArch.h"
#define kCrcPoly 0xEDB88320 #define kCrcPoly 0xEDB88320
#ifdef MY_CPU_LE #ifdef MY_CPU_LE
#define CRC_NUM_TABLES 8 #define CRC_NUM_TABLES 8
#else #else
#define CRC_NUM_TABLES 1 #define CRC_NUM_TABLES 1
#endif #endif
typedef UInt32 (MY_FAST_CALL *CRC_FUNC)(UInt32 v, const void *data, size_t size, const UInt32 *table); typedef UInt32 (MY_FAST_CALL *CRC_FUNC)(UInt32 v, const void *data, size_t size, const UInt32 *table);
static CRC_FUNC g_CrcUpdate; static CRC_FUNC g_CrcUpdate;
UInt32 g_CrcTable[256 * CRC_NUM_TABLES]; UInt32 g_CrcTable[256 * CRC_NUM_TABLES];
#if CRC_NUM_TABLES == 1 #if CRC_NUM_TABLES == 1
#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) #define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
static UInt32 MY_FAST_CALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table) static UInt32 MY_FAST_CALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table)
{ {
const Byte *p = (const Byte *)data; const Byte *p = (const Byte *)data;
for (; size > 0; size--, p++) for (; size > 0; size--, p++)
v = CRC_UPDATE_BYTE_2(v, *p); v = CRC_UPDATE_BYTE_2(v, *p);
return v; return v;
} }
#else #else
UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table); UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table);
UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table); UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table);
#endif #endif
UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size) UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size)
{ {
return g_CrcUpdate(v, data, size, g_CrcTable); return g_CrcUpdate(v, data, size, g_CrcTable);
} }
UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size) UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size)
{ {
return g_CrcUpdate(CRC_INIT_VAL, data, size, g_CrcTable) ^ CRC_INIT_VAL; return g_CrcUpdate(CRC_INIT_VAL, data, size, g_CrcTable) ^ CRC_INIT_VAL;
} }
void MY_FAST_CALL CrcGenerateTable() void MY_FAST_CALL CrcGenerateTable()
{ {
UInt32 i; UInt32 i;
for (i = 0; i < 256; i++) for (i = 0; i < 256; i++)
{ {
UInt32 r = i; UInt32 r = i;
unsigned j; unsigned j;
for (j = 0; j < 8; j++) for (j = 0; j < 8; j++)
r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1)); r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));
g_CrcTable[i] = r; g_CrcTable[i] = r;
} }
#if CRC_NUM_TABLES == 1 #if CRC_NUM_TABLES == 1
g_CrcUpdate = CrcUpdateT1; g_CrcUpdate = CrcUpdateT1;
#else #else
for (; i < 256 * CRC_NUM_TABLES; i++) for (; i < 256 * CRC_NUM_TABLES; i++)
{ {
UInt32 r = g_CrcTable[i - 256]; UInt32 r = g_CrcTable[i - 256];
g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8); g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8);
} }
g_CrcUpdate = CrcUpdateT4; g_CrcUpdate = CrcUpdateT4;
#ifdef MY_CPU_X86_OR_AMD64 #ifdef MY_CPU_X86_OR_AMD64
if (!CPU_Is_InOrder()) if (!CPU_Is_InOrder())
g_CrcUpdate = CrcUpdateT8; g_CrcUpdate = CrcUpdateT8;
#endif #endif
#endif #endif
} }

View File

@ -1,25 +1,25 @@
/* 7zCrc.h -- CRC32 calculation /* 7zCrc.h -- CRC32 calculation
2009-11-21 : Igor Pavlov : Public domain */ 2009-11-21 : Igor Pavlov : Public domain */
#ifndef __7Z_CRC_H #ifndef __7Z_CRC_H
#define __7Z_CRC_H #define __7Z_CRC_H
#include "Types.h" #include "Types.h"
EXTERN_C_BEGIN EXTERN_C_BEGIN
extern UInt32 g_CrcTable[]; extern UInt32 g_CrcTable[];
/* Call CrcGenerateTable one time before other CRC functions */ /* Call CrcGenerateTable one time before other CRC functions */
void MY_FAST_CALL CrcGenerateTable(void); void MY_FAST_CALL CrcGenerateTable(void);
#define CRC_INIT_VAL 0xFFFFFFFF #define CRC_INIT_VAL 0xFFFFFFFF
#define CRC_GET_DIGEST(crc) ((crc) ^ CRC_INIT_VAL) #define CRC_GET_DIGEST(crc) ((crc) ^ CRC_INIT_VAL)
#define CRC_UPDATE_BYTE(crc, b) (g_CrcTable[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) #define CRC_UPDATE_BYTE(crc, b) (g_CrcTable[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
UInt32 MY_FAST_CALL CrcUpdate(UInt32 crc, const void *data, size_t size); UInt32 MY_FAST_CALL CrcUpdate(UInt32 crc, const void *data, size_t size);
UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size); UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size);
EXTERN_C_END EXTERN_C_END
#endif #endif

View File

@ -1,34 +1,34 @@
/* 7zCrcOpt.c -- CRC32 calculation : optimized version /* 7zCrcOpt.c -- CRC32 calculation : optimized version
2009-11-23 : Igor Pavlov : Public domain */ 2009-11-23 : Igor Pavlov : Public domain */
#include "CpuArch.h" #include "CpuArch.h"
#ifdef MY_CPU_LE #ifdef MY_CPU_LE
#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) #define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table) UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table)
{ {
const Byte *p = (const Byte *)data; const Byte *p = (const Byte *)data;
for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++) for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++)
v = CRC_UPDATE_BYTE_2(v, *p); v = CRC_UPDATE_BYTE_2(v, *p);
for (; size >= 4; size -= 4, p += 4) for (; size >= 4; size -= 4, p += 4)
{ {
v ^= *(const UInt32 *)p; v ^= *(const UInt32 *)p;
v = v =
table[0x300 + (v & 0xFF)] ^ table[0x300 + (v & 0xFF)] ^
table[0x200 + ((v >> 8) & 0xFF)] ^ table[0x200 + ((v >> 8) & 0xFF)] ^
table[0x100 + ((v >> 16) & 0xFF)] ^ table[0x100 + ((v >> 16) & 0xFF)] ^
table[0x000 + ((v >> 24))]; table[0x000 + ((v >> 24))];
} }
for (; size > 0; size--, p++) for (; size > 0; size--, p++)
v = CRC_UPDATE_BYTE_2(v, *p); v = CRC_UPDATE_BYTE_2(v, *p);
return v; return v;
} }
UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table) UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table)
{ {
return CrcUpdateT4(v, data, size, table); return CrcUpdateT4(v, data, size, table);
} }
#endif #endif

View File

@ -1,470 +1,470 @@
/* 7zDec.c -- Decoding from 7z folder /* 7zDec.c -- Decoding from 7z folder
2010-11-02 : Igor Pavlov : Public domain */ 2010-11-02 : Igor Pavlov : Public domain */
#include <string.h> #include <string.h>
/* #define _7ZIP_PPMD_SUPPPORT */ /* #define _7ZIP_PPMD_SUPPPORT */
#include "7z.h" #include "7z.h"
#include "Bcj2.h" #include "Bcj2.h"
#include "Bra.h" #include "Bra.h"
#include "CpuArch.h" #include "CpuArch.h"
#include "LzmaDec.h" #include "LzmaDec.h"
#include "Lzma2Dec.h" #include "Lzma2Dec.h"
#ifdef _7ZIP_PPMD_SUPPPORT #ifdef _7ZIP_PPMD_SUPPPORT
#include "Ppmd7.h" #include "Ppmd7.h"
#endif #endif
#define k_Copy 0 #define k_Copy 0
#define k_LZMA2 0x21 #define k_LZMA2 0x21
#define k_LZMA 0x30101 #define k_LZMA 0x30101
#define k_BCJ 0x03030103 #define k_BCJ 0x03030103
#define k_PPC 0x03030205 #define k_PPC 0x03030205
#define k_ARM 0x03030501 #define k_ARM 0x03030501
#define k_ARMT 0x03030701 #define k_ARMT 0x03030701
#define k_SPARC 0x03030805 #define k_SPARC 0x03030805
#define k_BCJ2 0x0303011B #define k_BCJ2 0x0303011B
#ifdef _7ZIP_PPMD_SUPPPORT #ifdef _7ZIP_PPMD_SUPPPORT
#define k_PPMD 0x30401 #define k_PPMD 0x30401
typedef struct typedef struct
{ {
IByteIn p; IByteIn p;
const Byte *cur; const Byte *cur;
const Byte *end; const Byte *end;
const Byte *begin; const Byte *begin;
UInt64 processed; UInt64 processed;
Bool extra; Bool extra;
SRes res; SRes res;
ILookInStream *inStream; ILookInStream *inStream;
} CByteInToLook; } CByteInToLook;
static Byte ReadByte(void *pp) static Byte ReadByte(void *pp)
{ {
CByteInToLook *p = (CByteInToLook *)pp; CByteInToLook *p = (CByteInToLook *)pp;
if (p->cur != p->end) if (p->cur != p->end)
return *p->cur++; return *p->cur++;
if (p->res == SZ_OK) if (p->res == SZ_OK)
{ {
size_t size = p->cur - p->begin; size_t size = p->cur - p->begin;
p->processed += size; p->processed += size;
p->res = p->inStream->Skip(p->inStream, size); p->res = p->inStream->Skip(p->inStream, size);
size = (1 << 25); size = (1 << 25);
p->res = p->inStream->Look(p->inStream, (const void **)&p->begin, &size); p->res = p->inStream->Look(p->inStream, (const void **)&p->begin, &size);
p->cur = p->begin; p->cur = p->begin;
p->end = p->begin + size; p->end = p->begin + size;
if (size != 0) if (size != 0)
return *p->cur++;; return *p->cur++;;
} }
p->extra = True; p->extra = True;
return 0; return 0;
} }
static SRes SzDecodePpmd(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream, static SRes SzDecodePpmd(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream,
Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)
{ {
CPpmd7 ppmd; CPpmd7 ppmd;
CByteInToLook s; CByteInToLook s;
SRes res = SZ_OK; SRes res = SZ_OK;
s.p.Read = ReadByte; s.p.Read = ReadByte;
s.inStream = inStream; s.inStream = inStream;
s.begin = s.end = s.cur = NULL; s.begin = s.end = s.cur = NULL;
s.extra = False; s.extra = False;
s.res = SZ_OK; s.res = SZ_OK;
s.processed = 0; s.processed = 0;
if (coder->Props.size != 5) if (coder->Props.size != 5)
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
{ {
unsigned order = coder->Props.data[0]; unsigned order = coder->Props.data[0];
UInt32 memSize = GetUi32(coder->Props.data + 1); UInt32 memSize = GetUi32(coder->Props.data + 1);
if (order < PPMD7_MIN_ORDER || if (order < PPMD7_MIN_ORDER ||
order > PPMD7_MAX_ORDER || order > PPMD7_MAX_ORDER ||
memSize < PPMD7_MIN_MEM_SIZE || memSize < PPMD7_MIN_MEM_SIZE ||
memSize > PPMD7_MAX_MEM_SIZE) memSize > PPMD7_MAX_MEM_SIZE)
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
Ppmd7_Construct(&ppmd); Ppmd7_Construct(&ppmd);
if (!Ppmd7_Alloc(&ppmd, memSize, allocMain)) if (!Ppmd7_Alloc(&ppmd, memSize, allocMain))
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
Ppmd7_Init(&ppmd, order); Ppmd7_Init(&ppmd, order);
} }
{ {
CPpmd7z_RangeDec rc; CPpmd7z_RangeDec rc;
Ppmd7z_RangeDec_CreateVTable(&rc); Ppmd7z_RangeDec_CreateVTable(&rc);
rc.Stream = &s.p; rc.Stream = &s.p;
if (!Ppmd7z_RangeDec_Init(&rc)) if (!Ppmd7z_RangeDec_Init(&rc))
res = SZ_ERROR_DATA; res = SZ_ERROR_DATA;
else if (s.extra) else if (s.extra)
res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA); res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA);
else else
{ {
SizeT i; SizeT i;
for (i = 0; i < outSize; i++) for (i = 0; i < outSize; i++)
{ {
int sym = Ppmd7_DecodeSymbol(&ppmd, &rc.p); int sym = Ppmd7_DecodeSymbol(&ppmd, &rc.p);
if (s.extra || sym < 0) if (s.extra || sym < 0)
break; break;
outBuffer[i] = (Byte)sym; outBuffer[i] = (Byte)sym;
} }
if (i != outSize) if (i != outSize)
res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA); res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA);
else if (s.processed + (s.cur - s.begin) != inSize || !Ppmd7z_RangeDec_IsFinishedOK(&rc)) else if (s.processed + (s.cur - s.begin) != inSize || !Ppmd7z_RangeDec_IsFinishedOK(&rc))
res = SZ_ERROR_DATA; res = SZ_ERROR_DATA;
} }
} }
Ppmd7_Free(&ppmd, allocMain); Ppmd7_Free(&ppmd, allocMain);
return res; return res;
} }
#endif #endif
static SRes SzDecodeLzma(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream, static SRes SzDecodeLzma(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream,
Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)
{ {
CLzmaDec state; CLzmaDec state;
SRes res = SZ_OK; SRes res = SZ_OK;
LzmaDec_Construct(&state); LzmaDec_Construct(&state);
RINOK(LzmaDec_AllocateProbs(&state, coder->Props.data, (unsigned)coder->Props.size, allocMain)); RINOK(LzmaDec_AllocateProbs(&state, coder->Props.data, (unsigned)coder->Props.size, allocMain));
state.dic = outBuffer; state.dic = outBuffer;
state.dicBufSize = outSize; state.dicBufSize = outSize;
LzmaDec_Init(&state); LzmaDec_Init(&state);
for (;;) for (;;)
{ {
Byte *inBuf = NULL; Byte *inBuf = NULL;
size_t lookahead = (1 << 18); size_t lookahead = (1 << 18);
if (lookahead > inSize) if (lookahead > inSize)
lookahead = (size_t)inSize; lookahead = (size_t)inSize;
res = inStream->Look((void *)inStream, (const void **)&inBuf, &lookahead); res = inStream->Look((void *)inStream, (const void **)&inBuf, &lookahead);
if (res != SZ_OK) if (res != SZ_OK)
break; break;
{ {
SizeT inProcessed = (SizeT)lookahead, dicPos = state.dicPos; SizeT inProcessed = (SizeT)lookahead, dicPos = state.dicPos;
ELzmaStatus status; ELzmaStatus status;
res = LzmaDec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status); res = LzmaDec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status);
lookahead -= inProcessed; lookahead -= inProcessed;
inSize -= inProcessed; inSize -= inProcessed;
if (res != SZ_OK) if (res != SZ_OK)
break; break;
if (state.dicPos == state.dicBufSize || (inProcessed == 0 && dicPos == state.dicPos)) if (state.dicPos == state.dicBufSize || (inProcessed == 0 && dicPos == state.dicPos))
{ {
if (state.dicBufSize != outSize || lookahead != 0 || if (state.dicBufSize != outSize || lookahead != 0 ||
(status != LZMA_STATUS_FINISHED_WITH_MARK && (status != LZMA_STATUS_FINISHED_WITH_MARK &&
status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)) status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK))
res = SZ_ERROR_DATA; res = SZ_ERROR_DATA;
break; break;
} }
res = inStream->Skip((void *)inStream, inProcessed); res = inStream->Skip((void *)inStream, inProcessed);
if (res != SZ_OK) if (res != SZ_OK)
break; break;
} }
} }
LzmaDec_FreeProbs(&state, allocMain); LzmaDec_FreeProbs(&state, allocMain);
return res; return res;
} }
static SRes SzDecodeLzma2(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream, static SRes SzDecodeLzma2(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream,
Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)
{ {
CLzma2Dec state; CLzma2Dec state;
SRes res = SZ_OK; SRes res = SZ_OK;
Lzma2Dec_Construct(&state); Lzma2Dec_Construct(&state);
if (coder->Props.size != 1) if (coder->Props.size != 1)
return SZ_ERROR_DATA; return SZ_ERROR_DATA;
RINOK(Lzma2Dec_AllocateProbs(&state, coder->Props.data[0], allocMain)); RINOK(Lzma2Dec_AllocateProbs(&state, coder->Props.data[0], allocMain));
state.decoder.dic = outBuffer; state.decoder.dic = outBuffer;
state.decoder.dicBufSize = outSize; state.decoder.dicBufSize = outSize;
Lzma2Dec_Init(&state); Lzma2Dec_Init(&state);
for (;;) for (;;)
{ {
Byte *inBuf = NULL; Byte *inBuf = NULL;
size_t lookahead = (1 << 18); size_t lookahead = (1 << 18);
if (lookahead > inSize) if (lookahead > inSize)
lookahead = (size_t)inSize; lookahead = (size_t)inSize;
res = inStream->Look((void *)inStream, (const void **)&inBuf, &lookahead); res = inStream->Look((void *)inStream, (const void **)&inBuf, &lookahead);
if (res != SZ_OK) if (res != SZ_OK)
break; break;
{ {
SizeT inProcessed = (SizeT)lookahead, dicPos = state.decoder.dicPos; SizeT inProcessed = (SizeT)lookahead, dicPos = state.decoder.dicPos;
ELzmaStatus status; ELzmaStatus status;
res = Lzma2Dec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status); res = Lzma2Dec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status);
lookahead -= inProcessed; lookahead -= inProcessed;
inSize -= inProcessed; inSize -= inProcessed;
if (res != SZ_OK) if (res != SZ_OK)
break; break;
if (state.decoder.dicPos == state.decoder.dicBufSize || (inProcessed == 0 && dicPos == state.decoder.dicPos)) if (state.decoder.dicPos == state.decoder.dicBufSize || (inProcessed == 0 && dicPos == state.decoder.dicPos))
{ {
if (state.decoder.dicBufSize != outSize || lookahead != 0 || if (state.decoder.dicBufSize != outSize || lookahead != 0 ||
(status != LZMA_STATUS_FINISHED_WITH_MARK)) (status != LZMA_STATUS_FINISHED_WITH_MARK))
res = SZ_ERROR_DATA; res = SZ_ERROR_DATA;
break; break;
} }
res = inStream->Skip((void *)inStream, inProcessed); res = inStream->Skip((void *)inStream, inProcessed);
if (res != SZ_OK) if (res != SZ_OK)
break; break;
} }
} }
Lzma2Dec_FreeProbs(&state, allocMain); Lzma2Dec_FreeProbs(&state, allocMain);
return res; return res;
} }
static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer) static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer)
{ {
while (inSize > 0) while (inSize > 0)
{ {
void *inBuf; void *inBuf;
size_t curSize = (1 << 18); size_t curSize = (1 << 18);
if (curSize > inSize) if (curSize > inSize)
curSize = (size_t)inSize; curSize = (size_t)inSize;
RINOK(inStream->Look((void *)inStream, (const void **)&inBuf, &curSize)); RINOK(inStream->Look((void *)inStream, (const void **)&inBuf, &curSize));
if (curSize == 0) if (curSize == 0)
return SZ_ERROR_INPUT_EOF; return SZ_ERROR_INPUT_EOF;
memcpy(outBuffer, inBuf, curSize); memcpy(outBuffer, inBuf, curSize);
outBuffer += curSize; outBuffer += curSize;
inSize -= curSize; inSize -= curSize;
RINOK(inStream->Skip((void *)inStream, curSize)); RINOK(inStream->Skip((void *)inStream, curSize));
} }
return SZ_OK; return SZ_OK;
} }
static Bool IS_MAIN_METHOD(UInt32 m) static Bool IS_MAIN_METHOD(UInt32 m)
{ {
switch(m) switch(m)
{ {
case k_Copy: case k_Copy:
case k_LZMA: case k_LZMA:
case k_LZMA2: case k_LZMA2:
#ifdef _7ZIP_PPMD_SUPPPORT #ifdef _7ZIP_PPMD_SUPPPORT
case k_PPMD: case k_PPMD:
#endif #endif
return True; return True;
} }
return False; return False;
} }
static Bool IS_SUPPORTED_CODER(const CSzCoderInfo *c) static Bool IS_SUPPORTED_CODER(const CSzCoderInfo *c)
{ {
return return
c->NumInStreams == 1 && c->NumInStreams == 1 &&
c->NumOutStreams == 1 && c->NumOutStreams == 1 &&
c->MethodID <= (UInt32)0xFFFFFFFF && c->MethodID <= (UInt32)0xFFFFFFFF &&
IS_MAIN_METHOD((UInt32)c->MethodID); IS_MAIN_METHOD((UInt32)c->MethodID);
} }
#define IS_BCJ2(c) ((c)->MethodID == k_BCJ2 && (c)->NumInStreams == 4 && (c)->NumOutStreams == 1) #define IS_BCJ2(c) ((c)->MethodID == k_BCJ2 && (c)->NumInStreams == 4 && (c)->NumOutStreams == 1)
static SRes CheckSupportedFolder(const CSzFolder *f) static SRes CheckSupportedFolder(const CSzFolder *f)
{ {
if (f->NumCoders < 1 || f->NumCoders > 4) if (f->NumCoders < 1 || f->NumCoders > 4)
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
if (!IS_SUPPORTED_CODER(&f->Coders[0])) if (!IS_SUPPORTED_CODER(&f->Coders[0]))
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
if (f->NumCoders == 1) if (f->NumCoders == 1)
{ {
if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 0) if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 0)
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
return SZ_OK; return SZ_OK;
} }
if (f->NumCoders == 2) if (f->NumCoders == 2)
{ {
CSzCoderInfo *c = &f->Coders[1]; CSzCoderInfo *c = &f->Coders[1];
if (c->MethodID > (UInt32)0xFFFFFFFF || if (c->MethodID > (UInt32)0xFFFFFFFF ||
c->NumInStreams != 1 || c->NumInStreams != 1 ||
c->NumOutStreams != 1 || c->NumOutStreams != 1 ||
f->NumPackStreams != 1 || f->NumPackStreams != 1 ||
f->PackStreams[0] != 0 || f->PackStreams[0] != 0 ||
f->NumBindPairs != 1 || f->NumBindPairs != 1 ||
f->BindPairs[0].InIndex != 1 || f->BindPairs[0].InIndex != 1 ||
f->BindPairs[0].OutIndex != 0) f->BindPairs[0].OutIndex != 0)
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
switch ((UInt32)c->MethodID) switch ((UInt32)c->MethodID)
{ {
case k_BCJ: case k_BCJ:
case k_ARM: case k_ARM:
break; break;
default: default:
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
} }
return SZ_OK; return SZ_OK;
} }
if (f->NumCoders == 4) if (f->NumCoders == 4)
{ {
if (!IS_SUPPORTED_CODER(&f->Coders[1]) || if (!IS_SUPPORTED_CODER(&f->Coders[1]) ||
!IS_SUPPORTED_CODER(&f->Coders[2]) || !IS_SUPPORTED_CODER(&f->Coders[2]) ||
!IS_BCJ2(&f->Coders[3])) !IS_BCJ2(&f->Coders[3]))
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
if (f->NumPackStreams != 4 || if (f->NumPackStreams != 4 ||
f->PackStreams[0] != 2 || f->PackStreams[0] != 2 ||
f->PackStreams[1] != 6 || f->PackStreams[1] != 6 ||
f->PackStreams[2] != 1 || f->PackStreams[2] != 1 ||
f->PackStreams[3] != 0 || f->PackStreams[3] != 0 ||
f->NumBindPairs != 3 || f->NumBindPairs != 3 ||
f->BindPairs[0].InIndex != 5 || f->BindPairs[0].OutIndex != 0 || f->BindPairs[0].InIndex != 5 || f->BindPairs[0].OutIndex != 0 ||
f->BindPairs[1].InIndex != 4 || f->BindPairs[1].OutIndex != 1 || f->BindPairs[1].InIndex != 4 || f->BindPairs[1].OutIndex != 1 ||
f->BindPairs[2].InIndex != 3 || f->BindPairs[2].OutIndex != 2) f->BindPairs[2].InIndex != 3 || f->BindPairs[2].OutIndex != 2)
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
return SZ_OK; return SZ_OK;
} }
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
} }
static UInt64 GetSum(const UInt64 *values, UInt32 index) static UInt64 GetSum(const UInt64 *values, UInt32 index)
{ {
UInt64 sum = 0; UInt64 sum = 0;
UInt32 i; UInt32 i;
for (i = 0; i < index; i++) for (i = 0; i < index; i++)
sum += values[i]; sum += values[i];
return sum; return sum;
} }
#define CASE_BRA_CONV(isa) case k_ ## isa: isa ## _Convert(outBuffer, outSize, 0, 0); break; #define CASE_BRA_CONV(isa) case k_ ## isa: isa ## _Convert(outBuffer, outSize, 0, 0); break;
static SRes SzFolder_Decode2(const CSzFolder *folder, const UInt64 *packSizes, static SRes SzFolder_Decode2(const CSzFolder *folder, const UInt64 *packSizes,
ILookInStream *inStream, UInt64 startPos, ILookInStream *inStream, UInt64 startPos,
Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain, Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain,
Byte *tempBuf[]) Byte *tempBuf[])
{ {
UInt32 ci; UInt32 ci;
SizeT tempSizes[3] = { 0, 0, 0}; SizeT tempSizes[3] = { 0, 0, 0};
SizeT tempSize3 = 0; SizeT tempSize3 = 0;
Byte *tempBuf3 = 0; Byte *tempBuf3 = 0;
RINOK(CheckSupportedFolder(folder)); RINOK(CheckSupportedFolder(folder));
for (ci = 0; ci < folder->NumCoders; ci++) for (ci = 0; ci < folder->NumCoders; ci++)
{ {
CSzCoderInfo *coder = &folder->Coders[ci]; CSzCoderInfo *coder = &folder->Coders[ci];
if (IS_MAIN_METHOD((UInt32)coder->MethodID)) if (IS_MAIN_METHOD((UInt32)coder->MethodID))
{ {
UInt32 si = 0; UInt32 si = 0;
UInt64 offset; UInt64 offset;
UInt64 inSize; UInt64 inSize;
Byte *outBufCur = outBuffer; Byte *outBufCur = outBuffer;
SizeT outSizeCur = outSize; SizeT outSizeCur = outSize;
if (folder->NumCoders == 4) if (folder->NumCoders == 4)
{ {
UInt32 indices[] = { 3, 2, 0 }; UInt32 indices[] = { 3, 2, 0 };
UInt64 unpackSize = folder->UnpackSizes[ci]; UInt64 unpackSize = folder->UnpackSizes[ci];
si = indices[ci]; si = indices[ci];
if (ci < 2) if (ci < 2)
{ {
Byte *temp; Byte *temp;
outSizeCur = (SizeT)unpackSize; outSizeCur = (SizeT)unpackSize;
if (outSizeCur != unpackSize) if (outSizeCur != unpackSize)
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
temp = (Byte *)IAlloc_Alloc(allocMain, outSizeCur); temp = (Byte *)IAlloc_Alloc(allocMain, outSizeCur);
if (temp == 0 && outSizeCur != 0) if (temp == 0 && outSizeCur != 0)
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
outBufCur = tempBuf[1 - ci] = temp; outBufCur = tempBuf[1 - ci] = temp;
tempSizes[1 - ci] = outSizeCur; tempSizes[1 - ci] = outSizeCur;
} }
else if (ci == 2) else if (ci == 2)
{ {
if (unpackSize > outSize) /* check it */ if (unpackSize > outSize) /* check it */
return SZ_ERROR_PARAM; return SZ_ERROR_PARAM;
tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize); tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize);
tempSize3 = outSizeCur = (SizeT)unpackSize; tempSize3 = outSizeCur = (SizeT)unpackSize;
} }
else else
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
} }
offset = GetSum(packSizes, si); offset = GetSum(packSizes, si);
inSize = packSizes[si]; inSize = packSizes[si];
RINOK(LookInStream_SeekTo(inStream, startPos + offset)); RINOK(LookInStream_SeekTo(inStream, startPos + offset));
if (coder->MethodID == k_Copy) if (coder->MethodID == k_Copy)
{ {
if (inSize != outSizeCur) /* check it */ if (inSize != outSizeCur) /* check it */
return SZ_ERROR_DATA; return SZ_ERROR_DATA;
RINOK(SzDecodeCopy(inSize, inStream, outBufCur)); RINOK(SzDecodeCopy(inSize, inStream, outBufCur));
} }
else if (coder->MethodID == k_LZMA) else if (coder->MethodID == k_LZMA)
{ {
RINOK(SzDecodeLzma(coder, inSize, inStream, outBufCur, outSizeCur, allocMain)); RINOK(SzDecodeLzma(coder, inSize, inStream, outBufCur, outSizeCur, allocMain));
} }
else if (coder->MethodID == k_LZMA2) else if (coder->MethodID == k_LZMA2)
{ {
RINOK(SzDecodeLzma2(coder, inSize, inStream, outBufCur, outSizeCur, allocMain)); RINOK(SzDecodeLzma2(coder, inSize, inStream, outBufCur, outSizeCur, allocMain));
} }
else else
{ {
#ifdef _7ZIP_PPMD_SUPPPORT #ifdef _7ZIP_PPMD_SUPPPORT
RINOK(SzDecodePpmd(coder, inSize, inStream, outBufCur, outSizeCur, allocMain)); RINOK(SzDecodePpmd(coder, inSize, inStream, outBufCur, outSizeCur, allocMain));
#else #else
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
#endif #endif
} }
} }
else if (coder->MethodID == k_BCJ2) else if (coder->MethodID == k_BCJ2)
{ {
UInt64 offset = GetSum(packSizes, 1); UInt64 offset = GetSum(packSizes, 1);
UInt64 s3Size = packSizes[1]; UInt64 s3Size = packSizes[1];
SRes res; SRes res;
if (ci != 3) if (ci != 3)
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
RINOK(LookInStream_SeekTo(inStream, startPos + offset)); RINOK(LookInStream_SeekTo(inStream, startPos + offset));
tempSizes[2] = (SizeT)s3Size; tempSizes[2] = (SizeT)s3Size;
if (tempSizes[2] != s3Size) if (tempSizes[2] != s3Size)
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
tempBuf[2] = (Byte *)IAlloc_Alloc(allocMain, tempSizes[2]); tempBuf[2] = (Byte *)IAlloc_Alloc(allocMain, tempSizes[2]);
if (tempBuf[2] == 0 && tempSizes[2] != 0) if (tempBuf[2] == 0 && tempSizes[2] != 0)
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
res = SzDecodeCopy(s3Size, inStream, tempBuf[2]); res = SzDecodeCopy(s3Size, inStream, tempBuf[2]);
RINOK(res) RINOK(res)
res = Bcj2_Decode( res = Bcj2_Decode(
tempBuf3, tempSize3, tempBuf3, tempSize3,
tempBuf[0], tempSizes[0], tempBuf[0], tempSizes[0],
tempBuf[1], tempSizes[1], tempBuf[1], tempSizes[1],
tempBuf[2], tempSizes[2], tempBuf[2], tempSizes[2],
outBuffer, outSize); outBuffer, outSize);
RINOK(res) RINOK(res)
} }
else else
{ {
if (ci != 1) if (ci != 1)
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
switch(coder->MethodID) switch(coder->MethodID)
{ {
case k_BCJ: case k_BCJ:
{ {
UInt32 state; UInt32 state;
x86_Convert_Init(state); x86_Convert_Init(state);
x86_Convert(outBuffer, outSize, 0, &state, 0); x86_Convert(outBuffer, outSize, 0, &state, 0);
break; break;
} }
CASE_BRA_CONV(ARM) CASE_BRA_CONV(ARM)
default: default:
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
} }
} }
} }
return SZ_OK; return SZ_OK;
} }
SRes SzFolder_Decode(const CSzFolder *folder, const UInt64 *packSizes, SRes SzFolder_Decode(const CSzFolder *folder, const UInt64 *packSizes,
ILookInStream *inStream, UInt64 startPos, ILookInStream *inStream, UInt64 startPos,
Byte *outBuffer, size_t outSize, ISzAlloc *allocMain) Byte *outBuffer, size_t outSize, ISzAlloc *allocMain)
{ {
Byte *tempBuf[3] = { 0, 0, 0}; Byte *tempBuf[3] = { 0, 0, 0};
int i; int i;
SRes res = SzFolder_Decode2(folder, packSizes, inStream, startPos, SRes res = SzFolder_Decode2(folder, packSizes, inStream, startPos,
outBuffer, (SizeT)outSize, allocMain, tempBuf); outBuffer, (SizeT)outSize, allocMain, tempBuf);
for (i = 0; i < 3; i++) for (i = 0; i < 3; i++)
IAlloc_Free(allocMain, tempBuf[i]); IAlloc_Free(allocMain, tempBuf[i]);
return res; return res;
} }

View File

@ -1,13 +1,13 @@
/* 7zDecode.h -- Decoding from 7z folder /* 7zDecode.h -- Decoding from 7z folder
2008-11-23 : Igor Pavlov : Public domain */ 2008-11-23 : Igor Pavlov : Public domain */
#ifndef __7Z_DECODE_H #ifndef __7Z_DECODE_H
#define __7Z_DECODE_H #define __7Z_DECODE_H
#include "7zItem.h" #include "7zItem.h"
SRes SzDecode(const UInt64 *packSizes, const CSzFolder *folder, SRes SzDecode(const UInt64 *packSizes, const CSzFolder *folder,
ILookInStream *stream, UInt64 startPos, ILookInStream *stream, UInt64 startPos,
Byte *outBuffer, size_t outSize, ISzAlloc *allocMain); Byte *outBuffer, size_t outSize, ISzAlloc *allocMain);
#endif #endif

View File

@ -1,93 +1,93 @@
/* 7zExtract.c -- Extracting from 7z archive /* 7zExtract.c -- Extracting from 7z archive
2008-11-23 : Igor Pavlov : Public domain */ 2008-11-23 : Igor Pavlov : Public domain */
#include "7zCrc.h" #include "7zCrc.h"
#include "7zDecode.h" #include "7zDecode.h"
#include "7zExtract.h" #include "7zExtract.h"
SRes SzAr_Extract( SRes SzAr_Extract(
const CSzArEx *p, const CSzArEx *p,
ILookInStream *inStream, ILookInStream *inStream,
UInt32 fileIndex, UInt32 fileIndex,
UInt32 *blockIndex, UInt32 *blockIndex,
Byte **outBuffer, Byte **outBuffer,
size_t *outBufferSize, size_t *outBufferSize,
size_t *offset, size_t *offset,
size_t *outSizeProcessed, size_t *outSizeProcessed,
ISzAlloc *allocMain, ISzAlloc *allocMain,
ISzAlloc *allocTemp) ISzAlloc *allocTemp)
{ {
UInt32 folderIndex = p->FileIndexToFolderIndexMap[fileIndex]; UInt32 folderIndex = p->FileIndexToFolderIndexMap[fileIndex];
SRes res = SZ_OK; SRes res = SZ_OK;
*offset = 0; *offset = 0;
*outSizeProcessed = 0; *outSizeProcessed = 0;
if (folderIndex == (UInt32)-1) if (folderIndex == (UInt32)-1)
{ {
IAlloc_Free(allocMain, *outBuffer); IAlloc_Free(allocMain, *outBuffer);
*blockIndex = folderIndex; *blockIndex = folderIndex;
*outBuffer = 0; *outBuffer = 0;
*outBufferSize = 0; *outBufferSize = 0;
return SZ_OK; return SZ_OK;
} }
if (*outBuffer == 0 || *blockIndex != folderIndex) if (*outBuffer == 0 || *blockIndex != folderIndex)
{ {
CSzFolder *folder = p->db.Folders + folderIndex; CSzFolder *folder = p->db.Folders + folderIndex;
UInt64 unpackSizeSpec = SzFolder_GetUnpackSize(folder); UInt64 unpackSizeSpec = SzFolder_GetUnpackSize(folder);
size_t unpackSize = (size_t)unpackSizeSpec; size_t unpackSize = (size_t)unpackSizeSpec;
UInt64 startOffset = SzArEx_GetFolderStreamPos(p, folderIndex, 0); UInt64 startOffset = SzArEx_GetFolderStreamPos(p, folderIndex, 0);
if (unpackSize != unpackSizeSpec) if (unpackSize != unpackSizeSpec)
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
*blockIndex = folderIndex; *blockIndex = folderIndex;
IAlloc_Free(allocMain, *outBuffer); IAlloc_Free(allocMain, *outBuffer);
*outBuffer = 0; *outBuffer = 0;
RINOK(LookInStream_SeekTo(inStream, startOffset)); RINOK(LookInStream_SeekTo(inStream, startOffset));
if (res == SZ_OK) if (res == SZ_OK)
{ {
*outBufferSize = unpackSize; *outBufferSize = unpackSize;
if (unpackSize != 0) if (unpackSize != 0)
{ {
*outBuffer = (Byte *)IAlloc_Alloc(allocMain, unpackSize); *outBuffer = (Byte *)IAlloc_Alloc(allocMain, unpackSize);
if (*outBuffer == 0) if (*outBuffer == 0)
res = SZ_ERROR_MEM; res = SZ_ERROR_MEM;
} }
if (res == SZ_OK) if (res == SZ_OK)
{ {
res = SzDecode(p->db.PackSizes + res = SzDecode(p->db.PackSizes +
p->FolderStartPackStreamIndex[folderIndex], folder, p->FolderStartPackStreamIndex[folderIndex], folder,
inStream, startOffset, inStream, startOffset,
*outBuffer, unpackSize, allocTemp); *outBuffer, unpackSize, allocTemp);
if (res == SZ_OK) if (res == SZ_OK)
{ {
if (folder->UnpackCRCDefined) if (folder->UnpackCRCDefined)
{ {
if (CrcCalc(*outBuffer, unpackSize) != folder->UnpackCRC) if (CrcCalc(*outBuffer, unpackSize) != folder->UnpackCRC)
res = SZ_ERROR_CRC; res = SZ_ERROR_CRC;
} }
} }
} }
} }
} }
if (res == SZ_OK) if (res == SZ_OK)
{ {
UInt32 i; UInt32 i;
CSzFileItem *fileItem = p->db.Files + fileIndex; CSzFileItem *fileItem = p->db.Files + fileIndex;
*offset = 0; *offset = 0;
for (i = p->FolderStartFileIndex[folderIndex]; i < fileIndex; i++) for (i = p->FolderStartFileIndex[folderIndex]; i < fileIndex; i++)
*offset += (UInt32)p->db.Files[i].Size; *offset += (UInt32)p->db.Files[i].Size;
*outSizeProcessed = (size_t)fileItem->Size; *outSizeProcessed = (size_t)fileItem->Size;
if (*offset + *outSizeProcessed > *outBufferSize) if (*offset + *outSizeProcessed > *outBufferSize)
return SZ_ERROR_FAIL; return SZ_ERROR_FAIL;
{ {
if (fileItem->FileCRCDefined) if (fileItem->FileCRCDefined)
{ {
if (CrcCalc(*outBuffer + *offset, *outSizeProcessed) != fileItem->FileCRC) if (CrcCalc(*outBuffer + *offset, *outSizeProcessed) != fileItem->FileCRC)
res = SZ_ERROR_CRC; res = SZ_ERROR_CRC;
} }
} }
} }
return res; return res;
} }

View File

@ -1,49 +1,49 @@
/* 7zExtract.h -- Extracting from 7z archive /* 7zExtract.h -- Extracting from 7z archive
2008-11-23 : Igor Pavlov : Public domain */ 2008-11-23 : Igor Pavlov : Public domain */
#ifndef __7Z_EXTRACT_H #ifndef __7Z_EXTRACT_H
#define __7Z_EXTRACT_H #define __7Z_EXTRACT_H
#include "7zIn.h" #include "7zIn.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/* /*
SzExtract extracts file from archive SzExtract extracts file from archive
*outBuffer must be 0 before first call for each new archive. *outBuffer must be 0 before first call for each new archive.
Extracting cache: Extracting cache:
If you need to decompress more than one file, you can send If you need to decompress more than one file, you can send
these values from previous call: these values from previous call:
*blockIndex, *blockIndex,
*outBuffer, *outBuffer,
*outBufferSize *outBufferSize
You can consider "*outBuffer" as cache of solid block. If your archive is solid, You can consider "*outBuffer" as cache of solid block. If your archive is solid,
it will increase decompression speed. it will increase decompression speed.
If you use external function, you can declare these 3 cache variables If you use external function, you can declare these 3 cache variables
(blockIndex, outBuffer, outBufferSize) as static in that external function. (blockIndex, outBuffer, outBufferSize) as static in that external function.
Free *outBuffer and set *outBuffer to 0, if you want to flush cache. Free *outBuffer and set *outBuffer to 0, if you want to flush cache.
*/ */
SRes SzAr_Extract( SRes SzAr_Extract(
const CSzArEx *db, const CSzArEx *db,
ILookInStream *inStream, ILookInStream *inStream,
UInt32 fileIndex, /* index of file */ UInt32 fileIndex, /* index of file */
UInt32 *blockIndex, /* index of solid block */ UInt32 *blockIndex, /* index of solid block */
Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */ Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */
size_t *outBufferSize, /* buffer size for output buffer */ size_t *outBufferSize, /* buffer size for output buffer */
size_t *offset, /* offset of stream for required file in *outBuffer */ size_t *offset, /* offset of stream for required file in *outBuffer */
size_t *outSizeProcessed, /* size of file in *outBuffer */ size_t *outSizeProcessed, /* size of file in *outBuffer */
ISzAlloc *allocMain, ISzAlloc *allocMain,
ISzAlloc *allocTemp); ISzAlloc *allocTemp);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif #endif

View File

@ -1,6 +1,6 @@
/* 7zHeader.c -- 7z Headers /* 7zHeader.c -- 7z Headers
2008-10-04 : Igor Pavlov : Public domain */ 2008-10-04 : Igor Pavlov : Public domain */
#include "7zHeader.h" #include "7zHeader.h"
Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};

View File

@ -1,57 +1,57 @@
/* 7zHeader.h -- 7z Headers /* 7zHeader.h -- 7z Headers
2008-10-04 : Igor Pavlov : Public domain */ 2008-10-04 : Igor Pavlov : Public domain */
#ifndef __7Z_HEADER_H #ifndef __7Z_HEADER_H
#define __7Z_HEADER_H #define __7Z_HEADER_H
#include "Types.h" #include "Types.h"
#define k7zSignatureSize 6 #define k7zSignatureSize 6
extern Byte k7zSignature[k7zSignatureSize]; extern Byte k7zSignature[k7zSignatureSize];
#define k7zMajorVersion 0 #define k7zMajorVersion 0
#define k7zStartHeaderSize 0x20 #define k7zStartHeaderSize 0x20
enum EIdEnum enum EIdEnum
{ {
k7zIdEnd, k7zIdEnd,
k7zIdHeader, k7zIdHeader,
k7zIdArchiveProperties, k7zIdArchiveProperties,
k7zIdAdditionalStreamsInfo, k7zIdAdditionalStreamsInfo,
k7zIdMainStreamsInfo, k7zIdMainStreamsInfo,
k7zIdFilesInfo, k7zIdFilesInfo,
k7zIdPackInfo, k7zIdPackInfo,
k7zIdUnpackInfo, k7zIdUnpackInfo,
k7zIdSubStreamsInfo, k7zIdSubStreamsInfo,
k7zIdSize, k7zIdSize,
k7zIdCRC, k7zIdCRC,
k7zIdFolder, k7zIdFolder,
k7zIdCodersUnpackSize, k7zIdCodersUnpackSize,
k7zIdNumUnpackStream, k7zIdNumUnpackStream,
k7zIdEmptyStream, k7zIdEmptyStream,
k7zIdEmptyFile, k7zIdEmptyFile,
k7zIdAnti, k7zIdAnti,
k7zIdName, k7zIdName,
k7zIdCTime, k7zIdCTime,
k7zIdATime, k7zIdATime,
k7zIdMTime, k7zIdMTime,
k7zIdWinAttributes, k7zIdWinAttributes,
k7zIdComment, k7zIdComment,
k7zIdEncodedHeader, k7zIdEncodedHeader,
k7zIdStartPos, k7zIdStartPos,
k7zIdDummy k7zIdDummy
}; };
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -1,49 +1,49 @@
/* 7zIn.h -- 7z Input functions /* 7zIn.h -- 7z Input functions
2008-11-23 : Igor Pavlov : Public domain */ 2008-11-23 : Igor Pavlov : Public domain */
#ifndef __7Z_IN_H #ifndef __7Z_IN_H
#define __7Z_IN_H #define __7Z_IN_H
#include "7zHeader.h" #include "7zHeader.h"
#include "7zItem.h" #include "7zItem.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
typedef struct typedef struct
{ {
CSzAr db; CSzAr db;
UInt64 startPosAfterHeader; UInt64 startPosAfterHeader;
UInt64 dataPos; UInt64 dataPos;
UInt32 *FolderStartPackStreamIndex; UInt32 *FolderStartPackStreamIndex;
UInt64 *PackStreamStartPositions; UInt64 *PackStreamStartPositions;
UInt32 *FolderStartFileIndex; UInt32 *FolderStartFileIndex;
UInt32 *FileIndexToFolderIndexMap; UInt32 *FileIndexToFolderIndexMap;
} CSzArEx; } CSzArEx;
void SzArEx_Init(CSzArEx *p); void SzArEx_Init(CSzArEx *p);
void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc); void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc);
UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder); UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder);
int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize); int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize);
/* /*
Errors: Errors:
SZ_ERROR_NO_ARCHIVE SZ_ERROR_NO_ARCHIVE
SZ_ERROR_ARCHIVE SZ_ERROR_ARCHIVE
SZ_ERROR_UNSUPPORTED SZ_ERROR_UNSUPPORTED
SZ_ERROR_MEM SZ_ERROR_MEM
SZ_ERROR_CRC SZ_ERROR_CRC
SZ_ERROR_INPUT_EOF SZ_ERROR_INPUT_EOF
SZ_ERROR_FAIL SZ_ERROR_FAIL
*/ */
SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp); SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif #endif

View File

@ -1,129 +1,129 @@
/* 7zItem.c -- 7z Items /* 7zItem.c -- 7z Items
2008-10-04 : Igor Pavlov : Public domain */ 2008-10-04 : Igor Pavlov : Public domain */
#include "7zItem.h" #include "7zItem.h"
void SzCoderInfo_Init(CSzCoderInfo *p) void SzCoderInfo_Init(CSzCoderInfo *p)
{ {
Buf_Init(&p->Props); Buf_Init(&p->Props);
} }
void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc) void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc)
{ {
Buf_Free(&p->Props, alloc); Buf_Free(&p->Props, alloc);
SzCoderInfo_Init(p); SzCoderInfo_Init(p);
} }
void SzFolder_Init(CSzFolder *p) void SzFolder_Init(CSzFolder *p)
{ {
p->Coders = 0; p->Coders = 0;
p->BindPairs = 0; p->BindPairs = 0;
p->PackStreams = 0; p->PackStreams = 0;
p->UnpackSizes = 0; p->UnpackSizes = 0;
p->NumCoders = 0; p->NumCoders = 0;
p->NumBindPairs = 0; p->NumBindPairs = 0;
p->NumPackStreams = 0; p->NumPackStreams = 0;
p->UnpackCRCDefined = 0; p->UnpackCRCDefined = 0;
p->UnpackCRC = 0; p->UnpackCRC = 0;
p->NumUnpackStreams = 0; p->NumUnpackStreams = 0;
} }
static static
void SzFolder_Free(CSzFolder *p, ISzAlloc *alloc) void SzFolder_Free(CSzFolder *p, ISzAlloc *alloc)
{ {
UInt32 i; UInt32 i;
if (p->Coders) if (p->Coders)
for (i = 0; i < p->NumCoders; i++) for (i = 0; i < p->NumCoders; i++)
SzCoderInfo_Free(&p->Coders[i], alloc); SzCoderInfo_Free(&p->Coders[i], alloc);
IAlloc_Free(alloc, p->Coders); IAlloc_Free(alloc, p->Coders);
IAlloc_Free(alloc, p->BindPairs); IAlloc_Free(alloc, p->BindPairs);
IAlloc_Free(alloc, p->PackStreams); IAlloc_Free(alloc, p->PackStreams);
IAlloc_Free(alloc, p->UnpackSizes); IAlloc_Free(alloc, p->UnpackSizes);
SzFolder_Init(p); SzFolder_Init(p);
} }
UInt32 SzFolder_GetNumOutStreams(CSzFolder *p) UInt32 SzFolder_GetNumOutStreams(CSzFolder *p)
{ {
UInt32 result = 0; UInt32 result = 0;
UInt32 i; UInt32 i;
for (i = 0; i < p->NumCoders; i++) for (i = 0; i < p->NumCoders; i++)
result += p->Coders[i].NumOutStreams; result += p->Coders[i].NumOutStreams;
return result; return result;
} }
int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex) int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex)
{ {
UInt32 i; UInt32 i;
for (i = 0; i < p->NumBindPairs; i++) for (i = 0; i < p->NumBindPairs; i++)
if (p->BindPairs[i].InIndex == inStreamIndex) if (p->BindPairs[i].InIndex == inStreamIndex)
return i; return i;
return -1; return -1;
} }
static static
int SzFolder_FindBindPairForOutStream(CSzFolder *p, UInt32 outStreamIndex) int SzFolder_FindBindPairForOutStream(CSzFolder *p, UInt32 outStreamIndex)
{ {
UInt32 i; UInt32 i;
for (i = 0; i < p->NumBindPairs; i++) for (i = 0; i < p->NumBindPairs; i++)
if (p->BindPairs[i].OutIndex == outStreamIndex) if (p->BindPairs[i].OutIndex == outStreamIndex)
return i; return i;
return -1; return -1;
} }
UInt64 SzFolder_GetUnpackSize(CSzFolder *p) UInt64 SzFolder_GetUnpackSize(CSzFolder *p)
{ {
int i = (int)SzFolder_GetNumOutStreams(p); int i = (int)SzFolder_GetNumOutStreams(p);
if (i == 0) if (i == 0)
return 0; return 0;
for (i--; i >= 0; i--) for (i--; i >= 0; i--)
if (SzFolder_FindBindPairForOutStream(p, i) < 0) if (SzFolder_FindBindPairForOutStream(p, i) < 0)
return p->UnpackSizes[i]; return p->UnpackSizes[i];
/* throw 1; */ /* throw 1; */
return 0; return 0;
} }
void SzFile_Init(CSzFileItem *p) void SzFile_Init(CSzFileItem *p)
{ {
p->HasStream = 1; p->HasStream = 1;
p->IsDir = 0; p->IsDir = 0;
p->IsAnti = 0; p->IsAnti = 0;
p->FileCRCDefined = 0; p->FileCRCDefined = 0;
p->MTimeDefined = 0; p->MTimeDefined = 0;
p->Name = 0; p->Name = 0;
} }
static void SzFile_Free(CSzFileItem *p, ISzAlloc *alloc) static void SzFile_Free(CSzFileItem *p, ISzAlloc *alloc)
{ {
IAlloc_Free(alloc, p->Name); IAlloc_Free(alloc, p->Name);
SzFile_Init(p); SzFile_Init(p);
} }
void SzAr_Init(CSzAr *p) void SzAr_Init(CSzAr *p)
{ {
p->PackSizes = 0; p->PackSizes = 0;
p->PackCRCsDefined = 0; p->PackCRCsDefined = 0;
p->PackCRCs = 0; p->PackCRCs = 0;
p->Folders = 0; p->Folders = 0;
p->Files = 0; p->Files = 0;
p->NumPackStreams = 0; p->NumPackStreams = 0;
p->NumFolders = 0; p->NumFolders = 0;
p->NumFiles = 0; p->NumFiles = 0;
} }
void SzAr_Free(CSzAr *p, ISzAlloc *alloc) void SzAr_Free(CSzAr *p, ISzAlloc *alloc)
{ {
UInt32 i; UInt32 i;
if (p->Folders) if (p->Folders)
for (i = 0; i < p->NumFolders; i++) for (i = 0; i < p->NumFolders; i++)
SzFolder_Free(&p->Folders[i], alloc); SzFolder_Free(&p->Folders[i], alloc);
if (p->Files) if (p->Files)
for (i = 0; i < p->NumFiles; i++) for (i = 0; i < p->NumFiles; i++)
SzFile_Free(&p->Files[i], alloc); SzFile_Free(&p->Files[i], alloc);
IAlloc_Free(alloc, p->PackSizes); IAlloc_Free(alloc, p->PackSizes);
IAlloc_Free(alloc, p->PackCRCsDefined); IAlloc_Free(alloc, p->PackCRCsDefined);
IAlloc_Free(alloc, p->PackCRCs); IAlloc_Free(alloc, p->PackCRCs);
IAlloc_Free(alloc, p->Folders); IAlloc_Free(alloc, p->Folders);
IAlloc_Free(alloc, p->Files); IAlloc_Free(alloc, p->Files);
SzAr_Init(p); SzAr_Init(p);
} }

View File

@ -1,83 +1,83 @@
/* 7zItem.h -- 7z Items /* 7zItem.h -- 7z Items
2008-10-04 : Igor Pavlov : Public domain */ 2008-10-04 : Igor Pavlov : Public domain */
#ifndef __7Z_ITEM_H #ifndef __7Z_ITEM_H
#define __7Z_ITEM_H #define __7Z_ITEM_H
#include "7zBuf.h" #include "7zBuf.h"
typedef struct typedef struct
{ {
UInt32 NumInStreams; UInt32 NumInStreams;
UInt32 NumOutStreams; UInt32 NumOutStreams;
UInt64 MethodID; UInt64 MethodID;
CBuf Props; CBuf Props;
} CSzCoderInfo; } CSzCoderInfo;
void SzCoderInfo_Init(CSzCoderInfo *p); void SzCoderInfo_Init(CSzCoderInfo *p);
void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc); void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc);
typedef struct typedef struct
{ {
UInt32 InIndex; UInt32 InIndex;
UInt32 OutIndex; UInt32 OutIndex;
} CBindPair; } CBindPair;
typedef struct typedef struct
{ {
CSzCoderInfo *Coders; CSzCoderInfo *Coders;
CBindPair *BindPairs; CBindPair *BindPairs;
UInt32 *PackStreams; UInt32 *PackStreams;
UInt64 *UnpackSizes; UInt64 *UnpackSizes;
UInt32 NumCoders; UInt32 NumCoders;
UInt32 NumBindPairs; UInt32 NumBindPairs;
UInt32 NumPackStreams; UInt32 NumPackStreams;
int UnpackCRCDefined; int UnpackCRCDefined;
UInt32 UnpackCRC; UInt32 UnpackCRC;
UInt32 NumUnpackStreams; UInt32 NumUnpackStreams;
} CSzFolder; } CSzFolder;
void SzFolder_Init(CSzFolder *p); void SzFolder_Init(CSzFolder *p);
UInt64 SzFolder_GetUnpackSize(CSzFolder *p); UInt64 SzFolder_GetUnpackSize(CSzFolder *p);
int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex); int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex);
UInt32 SzFolder_GetNumOutStreams(CSzFolder *p); UInt32 SzFolder_GetNumOutStreams(CSzFolder *p);
typedef struct typedef struct
{ {
UInt32 Low; UInt32 Low;
UInt32 High; UInt32 High;
} CNtfsFileTime; } CNtfsFileTime;
typedef struct typedef struct
{ {
CNtfsFileTime MTime; CNtfsFileTime MTime;
UInt64 Size; UInt64 Size;
char *Name; char *Name;
UInt32 FileCRC; UInt32 FileCRC;
Byte HasStream; Byte HasStream;
Byte IsDir; Byte IsDir;
Byte IsAnti; Byte IsAnti;
Byte FileCRCDefined; Byte FileCRCDefined;
Byte MTimeDefined; Byte MTimeDefined;
} CSzFileItem; } CSzFileItem;
void SzFile_Init(CSzFileItem *p); void SzFile_Init(CSzFileItem *p);
typedef struct typedef struct
{ {
UInt64 *PackSizes; UInt64 *PackSizes;
Byte *PackCRCsDefined; Byte *PackCRCsDefined;
UInt32 *PackCRCs; UInt32 *PackCRCs;
CSzFolder *Folders; CSzFolder *Folders;
CSzFileItem *Files; CSzFileItem *Files;
UInt32 NumPackStreams; UInt32 NumPackStreams;
UInt32 NumFolders; UInt32 NumFolders;
UInt32 NumFiles; UInt32 NumFiles;
} CSzAr; } CSzAr;
void SzAr_Init(CSzAr *p); void SzAr_Init(CSzAr *p);
void SzAr_Free(CSzAr *p, ISzAlloc *alloc); void SzAr_Free(CSzAr *p, ISzAlloc *alloc);
#endif #endif

View File

@ -1,169 +1,169 @@
/* 7zStream.c -- 7z Stream functions /* 7zStream.c -- 7z Stream functions
2010-03-11 : Igor Pavlov : Public domain */ 2010-03-11 : Igor Pavlov : Public domain */
#include <string.h> #include <string.h>
#include "Types.h" #include "Types.h"
SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType) SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType)
{ {
while (size != 0) while (size != 0)
{ {
size_t processed = size; size_t processed = size;
RINOK(stream->Read(stream, buf, &processed)); RINOK(stream->Read(stream, buf, &processed));
if (processed == 0) if (processed == 0)
return errorType; return errorType;
buf = (void *)((Byte *)buf + processed); buf = (void *)((Byte *)buf + processed);
size -= processed; size -= processed;
} }
return SZ_OK; return SZ_OK;
} }
SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size) SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size)
{ {
return SeqInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF); return SeqInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF);
} }
SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf) SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf)
{ {
size_t processed = 1; size_t processed = 1;
RINOK(stream->Read(stream, buf, &processed)); RINOK(stream->Read(stream, buf, &processed));
return (processed == 1) ? SZ_OK : SZ_ERROR_INPUT_EOF; return (processed == 1) ? SZ_OK : SZ_ERROR_INPUT_EOF;
} }
SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset) SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset)
{ {
Int64 t = offset; Int64 t = offset;
return stream->Seek(stream, &t, SZ_SEEK_SET); return stream->Seek(stream, &t, SZ_SEEK_SET);
} }
SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size) SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size)
{ {
const void *lookBuf; const void *lookBuf;
if (*size == 0) if (*size == 0)
return SZ_OK; return SZ_OK;
RINOK(stream->Look(stream, &lookBuf, size)); RINOK(stream->Look(stream, &lookBuf, size));
memcpy(buf, lookBuf, *size); memcpy(buf, lookBuf, *size);
return stream->Skip(stream, *size); return stream->Skip(stream, *size);
} }
SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType) SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType)
{ {
while (size != 0) while (size != 0)
{ {
size_t processed = size; size_t processed = size;
RINOK(stream->Read(stream, buf, &processed)); RINOK(stream->Read(stream, buf, &processed));
if (processed == 0) if (processed == 0)
return errorType; return errorType;
buf = (void *)((Byte *)buf + processed); buf = (void *)((Byte *)buf + processed);
size -= processed; size -= processed;
} }
return SZ_OK; return SZ_OK;
} }
SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size) SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size)
{ {
return LookInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF); return LookInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF);
} }
static SRes LookToRead_Look_Lookahead(void *pp, const void **buf, size_t *size) static SRes LookToRead_Look_Lookahead(void *pp, const void **buf, size_t *size)
{ {
SRes res = SZ_OK; SRes res = SZ_OK;
CLookToRead *p = (CLookToRead *)pp; CLookToRead *p = (CLookToRead *)pp;
size_t size2 = p->size - p->pos; size_t size2 = p->size - p->pos;
if (size2 == 0 && *size > 0) if (size2 == 0 && *size > 0)
{ {
p->pos = 0; p->pos = 0;
size2 = LookToRead_BUF_SIZE; size2 = LookToRead_BUF_SIZE;
res = p->realStream->Read(p->realStream, p->buf, &size2); res = p->realStream->Read(p->realStream, p->buf, &size2);
p->size = size2; p->size = size2;
} }
if (size2 < *size) if (size2 < *size)
*size = size2; *size = size2;
*buf = p->buf + p->pos; *buf = p->buf + p->pos;
return res; return res;
} }
static SRes LookToRead_Look_Exact(void *pp, const void **buf, size_t *size) static SRes LookToRead_Look_Exact(void *pp, const void **buf, size_t *size)
{ {
SRes res = SZ_OK; SRes res = SZ_OK;
CLookToRead *p = (CLookToRead *)pp; CLookToRead *p = (CLookToRead *)pp;
size_t size2 = p->size - p->pos; size_t size2 = p->size - p->pos;
if (size2 == 0 && *size > 0) if (size2 == 0 && *size > 0)
{ {
p->pos = 0; p->pos = 0;
if (*size > LookToRead_BUF_SIZE) if (*size > LookToRead_BUF_SIZE)
*size = LookToRead_BUF_SIZE; *size = LookToRead_BUF_SIZE;
res = p->realStream->Read(p->realStream, p->buf, size); res = p->realStream->Read(p->realStream, p->buf, size);
size2 = p->size = *size; size2 = p->size = *size;
} }
if (size2 < *size) if (size2 < *size)
*size = size2; *size = size2;
*buf = p->buf + p->pos; *buf = p->buf + p->pos;
return res; return res;
} }
static SRes LookToRead_Skip(void *pp, size_t offset) static SRes LookToRead_Skip(void *pp, size_t offset)
{ {
CLookToRead *p = (CLookToRead *)pp; CLookToRead *p = (CLookToRead *)pp;
p->pos += offset; p->pos += offset;
return SZ_OK; return SZ_OK;
} }
static SRes LookToRead_Read(void *pp, void *buf, size_t *size) static SRes LookToRead_Read(void *pp, void *buf, size_t *size)
{ {
CLookToRead *p = (CLookToRead *)pp; CLookToRead *p = (CLookToRead *)pp;
size_t rem = p->size - p->pos; size_t rem = p->size - p->pos;
if (rem == 0) if (rem == 0)
return p->realStream->Read(p->realStream, buf, size); return p->realStream->Read(p->realStream, buf, size);
if (rem > *size) if (rem > *size)
rem = *size; rem = *size;
memcpy(buf, p->buf + p->pos, rem); memcpy(buf, p->buf + p->pos, rem);
p->pos += rem; p->pos += rem;
*size = rem; *size = rem;
return SZ_OK; return SZ_OK;
} }
static SRes LookToRead_Seek(void *pp, Int64 *pos, ESzSeek origin) static SRes LookToRead_Seek(void *pp, Int64 *pos, ESzSeek origin)
{ {
CLookToRead *p = (CLookToRead *)pp; CLookToRead *p = (CLookToRead *)pp;
p->pos = p->size = 0; p->pos = p->size = 0;
return p->realStream->Seek(p->realStream, pos, origin); return p->realStream->Seek(p->realStream, pos, origin);
} }
void LookToRead_CreateVTable(CLookToRead *p, int lookahead) void LookToRead_CreateVTable(CLookToRead *p, int lookahead)
{ {
p->s.Look = lookahead ? p->s.Look = lookahead ?
LookToRead_Look_Lookahead : LookToRead_Look_Lookahead :
LookToRead_Look_Exact; LookToRead_Look_Exact;
p->s.Skip = LookToRead_Skip; p->s.Skip = LookToRead_Skip;
p->s.Read = LookToRead_Read; p->s.Read = LookToRead_Read;
p->s.Seek = LookToRead_Seek; p->s.Seek = LookToRead_Seek;
} }
void LookToRead_Init(CLookToRead *p) void LookToRead_Init(CLookToRead *p)
{ {
p->pos = p->size = 0; p->pos = p->size = 0;
} }
static SRes SecToLook_Read(void *pp, void *buf, size_t *size) static SRes SecToLook_Read(void *pp, void *buf, size_t *size)
{ {
CSecToLook *p = (CSecToLook *)pp; CSecToLook *p = (CSecToLook *)pp;
return LookInStream_LookRead(p->realStream, buf, size); return LookInStream_LookRead(p->realStream, buf, size);
} }
void SecToLook_CreateVTable(CSecToLook *p) void SecToLook_CreateVTable(CSecToLook *p)
{ {
p->s.Read = SecToLook_Read; p->s.Read = SecToLook_Read;
} }
static SRes SecToRead_Read(void *pp, void *buf, size_t *size) static SRes SecToRead_Read(void *pp, void *buf, size_t *size)
{ {
CSecToRead *p = (CSecToRead *)pp; CSecToRead *p = (CSecToRead *)pp;
return p->realStream->Read(p->realStream, buf, size); return p->realStream->Read(p->realStream, buf, size);
} }
void SecToRead_CreateVTable(CSecToRead *p) void SecToRead_CreateVTable(CSecToRead *p)
{ {
p->s.Read = SecToRead_Read; p->s.Read = SecToRead_Read;
} }

View File

@ -1,132 +1,132 @@
/* Bcj2.c -- Converter for x86 code (BCJ2) /* Bcj2.c -- Converter for x86 code (BCJ2)
2008-10-04 : Igor Pavlov : Public domain */ 2008-10-04 : Igor Pavlov : Public domain */
#include "Bcj2.h" #include "Bcj2.h"
#ifdef _LZMA_PROB32 #ifdef _LZMA_PROB32
#define CProb UInt32 #define CProb UInt32
#else #else
#define CProb UInt16 #define CProb UInt16
#endif #endif
#define IsJcc(b0, b1) ((b0) == 0x0F && ((b1) & 0xF0) == 0x80) #define IsJcc(b0, b1) ((b0) == 0x0F && ((b1) & 0xF0) == 0x80)
#define IsJ(b0, b1) ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1)) #define IsJ(b0, b1) ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1))
#define kNumTopBits 24 #define kNumTopBits 24
#define kTopValue ((UInt32)1 << kNumTopBits) #define kTopValue ((UInt32)1 << kNumTopBits)
#define kNumBitModelTotalBits 11 #define kNumBitModelTotalBits 11
#define kBitModelTotal (1 << kNumBitModelTotalBits) #define kBitModelTotal (1 << kNumBitModelTotalBits)
#define kNumMoveBits 5 #define kNumMoveBits 5
#define RC_READ_BYTE (*buffer++) #define RC_READ_BYTE (*buffer++)
#define RC_TEST { if (buffer == bufferLim) return SZ_ERROR_DATA; } #define RC_TEST { if (buffer == bufferLim) return SZ_ERROR_DATA; }
#define RC_INIT2 code = 0; range = 0xFFFFFFFF; \ #define RC_INIT2 code = 0; range = 0xFFFFFFFF; \
{ int i; for (i = 0; i < 5; i++) { RC_TEST; code = (code << 8) | RC_READ_BYTE; }} { int i; for (i = 0; i < 5; i++) { RC_TEST; code = (code << 8) | RC_READ_BYTE; }}
#define NORMALIZE if (range < kTopValue) { RC_TEST; range <<= 8; code = (code << 8) | RC_READ_BYTE; } #define NORMALIZE if (range < kTopValue) { RC_TEST; range <<= 8; code = (code << 8) | RC_READ_BYTE; }
#define IF_BIT_0(p) ttt = *(p); bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) #define IF_BIT_0(p) ttt = *(p); bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
#define UPDATE_0(p) range = bound; *(p) = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); NORMALIZE; #define UPDATE_0(p) range = bound; *(p) = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); NORMALIZE;
#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CProb)(ttt - (ttt >> kNumMoveBits)); NORMALIZE; #define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CProb)(ttt - (ttt >> kNumMoveBits)); NORMALIZE;
int Bcj2_Decode( int Bcj2_Decode(
const Byte *buf0, SizeT size0, const Byte *buf0, SizeT size0,
const Byte *buf1, SizeT size1, const Byte *buf1, SizeT size1,
const Byte *buf2, SizeT size2, const Byte *buf2, SizeT size2,
const Byte *buf3, SizeT size3, const Byte *buf3, SizeT size3,
Byte *outBuf, SizeT outSize) Byte *outBuf, SizeT outSize)
{ {
CProb p[256 + 2]; CProb p[256 + 2];
SizeT inPos = 0, outPos = 0; SizeT inPos = 0, outPos = 0;
const Byte *buffer, *bufferLim; const Byte *buffer, *bufferLim;
UInt32 range, code; UInt32 range, code;
Byte prevByte = 0; Byte prevByte = 0;
unsigned int i; unsigned int i;
for (i = 0; i < sizeof(p) / sizeof(p[0]); i++) for (i = 0; i < sizeof(p) / sizeof(p[0]); i++)
p[i] = kBitModelTotal >> 1; p[i] = kBitModelTotal >> 1;
buffer = buf3; buffer = buf3;
bufferLim = buffer + size3; bufferLim = buffer + size3;
RC_INIT2 RC_INIT2
if (outSize == 0) if (outSize == 0)
return SZ_OK; return SZ_OK;
for (;;) for (;;)
{ {
Byte b; Byte b;
CProb *prob; CProb *prob;
UInt32 bound; UInt32 bound;
UInt32 ttt; UInt32 ttt;
SizeT limit = size0 - inPos; SizeT limit = size0 - inPos;
if (outSize - outPos < limit) if (outSize - outPos < limit)
limit = outSize - outPos; limit = outSize - outPos;
while (limit != 0) while (limit != 0)
{ {
Byte b = buf0[inPos]; Byte b = buf0[inPos];
outBuf[outPos++] = b; outBuf[outPos++] = b;
if (IsJ(prevByte, b)) if (IsJ(prevByte, b))
break; break;
inPos++; inPos++;
prevByte = b; prevByte = b;
limit--; limit--;
} }
if (limit == 0 || outPos == outSize) if (limit == 0 || outPos == outSize)
break; break;
b = buf0[inPos++]; b = buf0[inPos++];
if (b == 0xE8) if (b == 0xE8)
prob = p + prevByte; prob = p + prevByte;
else if (b == 0xE9) else if (b == 0xE9)
prob = p + 256; prob = p + 256;
else else
prob = p + 257; prob = p + 257;
IF_BIT_0(prob) IF_BIT_0(prob)
{ {
UPDATE_0(prob) UPDATE_0(prob)
prevByte = b; prevByte = b;
} }
else else
{ {
UInt32 dest; UInt32 dest;
const Byte *v; const Byte *v;
UPDATE_1(prob) UPDATE_1(prob)
if (b == 0xE8) if (b == 0xE8)
{ {
v = buf1; v = buf1;
if (size1 < 4) if (size1 < 4)
return SZ_ERROR_DATA; return SZ_ERROR_DATA;
buf1 += 4; buf1 += 4;
size1 -= 4; size1 -= 4;
} }
else else
{ {
v = buf2; v = buf2;
if (size2 < 4) if (size2 < 4)
return SZ_ERROR_DATA; return SZ_ERROR_DATA;
buf2 += 4; buf2 += 4;
size2 -= 4; size2 -= 4;
} }
dest = (((UInt32)v[0] << 24) | ((UInt32)v[1] << 16) | dest = (((UInt32)v[0] << 24) | ((UInt32)v[1] << 16) |
((UInt32)v[2] << 8) | ((UInt32)v[3])) - ((UInt32)outPos + 4); ((UInt32)v[2] << 8) | ((UInt32)v[3])) - ((UInt32)outPos + 4);
outBuf[outPos++] = (Byte)dest; outBuf[outPos++] = (Byte)dest;
if (outPos == outSize) if (outPos == outSize)
break; break;
outBuf[outPos++] = (Byte)(dest >> 8); outBuf[outPos++] = (Byte)(dest >> 8);
if (outPos == outSize) if (outPos == outSize)
break; break;
outBuf[outPos++] = (Byte)(dest >> 16); outBuf[outPos++] = (Byte)(dest >> 16);
if (outPos == outSize) if (outPos == outSize)
break; break;
outBuf[outPos++] = prevByte = (Byte)(dest >> 24); outBuf[outPos++] = prevByte = (Byte)(dest >> 24);
} }
} }
return (outPos == outSize) ? SZ_OK : SZ_ERROR_DATA; return (outPos == outSize) ? SZ_OK : SZ_ERROR_DATA;
} }

View File

@ -1,38 +1,38 @@
/* Bcj2.h -- Converter for x86 code (BCJ2) /* Bcj2.h -- Converter for x86 code (BCJ2)
2009-02-07 : Igor Pavlov : Public domain */ 2009-02-07 : Igor Pavlov : Public domain */
#ifndef __BCJ2_H #ifndef __BCJ2_H
#define __BCJ2_H #define __BCJ2_H
#include "Types.h" #include "Types.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/* /*
Conditions: Conditions:
outSize <= FullOutputSize, outSize <= FullOutputSize,
where FullOutputSize is full size of output stream of x86_2 filter. where FullOutputSize is full size of output stream of x86_2 filter.
If buf0 overlaps outBuf, there are two required conditions: If buf0 overlaps outBuf, there are two required conditions:
1) (buf0 >= outBuf) 1) (buf0 >= outBuf)
2) (buf0 + size0 >= outBuf + FullOutputSize). 2) (buf0 + size0 >= outBuf + FullOutputSize).
Returns: Returns:
SZ_OK SZ_OK
SZ_ERROR_DATA - Data error SZ_ERROR_DATA - Data error
*/ */
int Bcj2_Decode( int Bcj2_Decode(
const Byte *buf0, SizeT size0, const Byte *buf0, SizeT size0,
const Byte *buf1, SizeT size1, const Byte *buf1, SizeT size1,
const Byte *buf2, SizeT size2, const Byte *buf2, SizeT size2,
const Byte *buf3, SizeT size3, const Byte *buf3, SizeT size3,
Byte *outBuf, SizeT outSize); Byte *outBuf, SizeT outSize);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif #endif

View File

@ -1,133 +1,133 @@
/* Bra.c -- Converters for RISC code /* Bra.c -- Converters for RISC code
2010-04-16 : Igor Pavlov : Public domain */ 2010-04-16 : Igor Pavlov : Public domain */
#include "Bra.h" #include "Bra.h"
SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
{ {
SizeT i; SizeT i;
if (size < 4) if (size < 4)
return 0; return 0;
size -= 4; size -= 4;
ip += 8; ip += 8;
for (i = 0; i <= size; i += 4) for (i = 0; i <= size; i += 4)
{ {
if (data[i + 3] == 0xEB) if (data[i + 3] == 0xEB)
{ {
UInt32 dest; UInt32 dest;
UInt32 src = ((UInt32)data[i + 2] << 16) | ((UInt32)data[i + 1] << 8) | (data[i + 0]); UInt32 src = ((UInt32)data[i + 2] << 16) | ((UInt32)data[i + 1] << 8) | (data[i + 0]);
src <<= 2; src <<= 2;
if (encoding) if (encoding)
dest = ip + (UInt32)i + src; dest = ip + (UInt32)i + src;
else else
dest = src - (ip + (UInt32)i); dest = src - (ip + (UInt32)i);
dest >>= 2; dest >>= 2;
data[i + 2] = (Byte)(dest >> 16); data[i + 2] = (Byte)(dest >> 16);
data[i + 1] = (Byte)(dest >> 8); data[i + 1] = (Byte)(dest >> 8);
data[i + 0] = (Byte)dest; data[i + 0] = (Byte)dest;
} }
} }
return i; return i;
} }
SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
{ {
SizeT i; SizeT i;
if (size < 4) if (size < 4)
return 0; return 0;
size -= 4; size -= 4;
ip += 4; ip += 4;
for (i = 0; i <= size; i += 2) for (i = 0; i <= size; i += 2)
{ {
if ((data[i + 1] & 0xF8) == 0xF0 && if ((data[i + 1] & 0xF8) == 0xF0 &&
(data[i + 3] & 0xF8) == 0xF8) (data[i + 3] & 0xF8) == 0xF8)
{ {
UInt32 dest; UInt32 dest;
UInt32 src = UInt32 src =
(((UInt32)data[i + 1] & 0x7) << 19) | (((UInt32)data[i + 1] & 0x7) << 19) |
((UInt32)data[i + 0] << 11) | ((UInt32)data[i + 0] << 11) |
(((UInt32)data[i + 3] & 0x7) << 8) | (((UInt32)data[i + 3] & 0x7) << 8) |
(data[i + 2]); (data[i + 2]);
src <<= 1; src <<= 1;
if (encoding) if (encoding)
dest = ip + (UInt32)i + src; dest = ip + (UInt32)i + src;
else else
dest = src - (ip + (UInt32)i); dest = src - (ip + (UInt32)i);
dest >>= 1; dest >>= 1;
data[i + 1] = (Byte)(0xF0 | ((dest >> 19) & 0x7)); data[i + 1] = (Byte)(0xF0 | ((dest >> 19) & 0x7));
data[i + 0] = (Byte)(dest >> 11); data[i + 0] = (Byte)(dest >> 11);
data[i + 3] = (Byte)(0xF8 | ((dest >> 8) & 0x7)); data[i + 3] = (Byte)(0xF8 | ((dest >> 8) & 0x7));
data[i + 2] = (Byte)dest; data[i + 2] = (Byte)dest;
i += 2; i += 2;
} }
} }
return i; return i;
} }
SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
{ {
SizeT i; SizeT i;
if (size < 4) if (size < 4)
return 0; return 0;
size -= 4; size -= 4;
for (i = 0; i <= size; i += 4) for (i = 0; i <= size; i += 4)
{ {
if ((data[i] >> 2) == 0x12 && (data[i + 3] & 3) == 1) if ((data[i] >> 2) == 0x12 && (data[i + 3] & 3) == 1)
{ {
UInt32 src = ((UInt32)(data[i + 0] & 3) << 24) | UInt32 src = ((UInt32)(data[i + 0] & 3) << 24) |
((UInt32)data[i + 1] << 16) | ((UInt32)data[i + 1] << 16) |
((UInt32)data[i + 2] << 8) | ((UInt32)data[i + 2] << 8) |
((UInt32)data[i + 3] & (~3)); ((UInt32)data[i + 3] & (~3));
UInt32 dest; UInt32 dest;
if (encoding) if (encoding)
dest = ip + (UInt32)i + src; dest = ip + (UInt32)i + src;
else else
dest = src - (ip + (UInt32)i); dest = src - (ip + (UInt32)i);
data[i + 0] = (Byte)(0x48 | ((dest >> 24) & 0x3)); data[i + 0] = (Byte)(0x48 | ((dest >> 24) & 0x3));
data[i + 1] = (Byte)(dest >> 16); data[i + 1] = (Byte)(dest >> 16);
data[i + 2] = (Byte)(dest >> 8); data[i + 2] = (Byte)(dest >> 8);
data[i + 3] &= 0x3; data[i + 3] &= 0x3;
data[i + 3] |= dest; data[i + 3] |= dest;
} }
} }
return i; return i;
} }
SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
{ {
UInt32 i; UInt32 i;
if (size < 4) if (size < 4)
return 0; return 0;
size -= 4; size -= 4;
for (i = 0; i <= size; i += 4) for (i = 0; i <= size; i += 4)
{ {
if ((data[i] == 0x40 && (data[i + 1] & 0xC0) == 0x00) || if ((data[i] == 0x40 && (data[i + 1] & 0xC0) == 0x00) ||
(data[i] == 0x7F && (data[i + 1] & 0xC0) == 0xC0)) (data[i] == 0x7F && (data[i + 1] & 0xC0) == 0xC0))
{ {
UInt32 src = UInt32 src =
((UInt32)data[i + 0] << 24) | ((UInt32)data[i + 0] << 24) |
((UInt32)data[i + 1] << 16) | ((UInt32)data[i + 1] << 16) |
((UInt32)data[i + 2] << 8) | ((UInt32)data[i + 2] << 8) |
((UInt32)data[i + 3]); ((UInt32)data[i + 3]);
UInt32 dest; UInt32 dest;
src <<= 2; src <<= 2;
if (encoding) if (encoding)
dest = ip + i + src; dest = ip + i + src;
else else
dest = src - (ip + i); dest = src - (ip + i);
dest >>= 2; dest >>= 2;
dest = (((0 - ((dest >> 22) & 1)) << 22) & 0x3FFFFFFF) | (dest & 0x3FFFFF) | 0x40000000; dest = (((0 - ((dest >> 22) & 1)) << 22) & 0x3FFFFFFF) | (dest & 0x3FFFFF) | 0x40000000;
data[i + 0] = (Byte)(dest >> 24); data[i + 0] = (Byte)(dest >> 24);
data[i + 1] = (Byte)(dest >> 16); data[i + 1] = (Byte)(dest >> 16);
data[i + 2] = (Byte)(dest >> 8); data[i + 2] = (Byte)(dest >> 8);
data[i + 3] = (Byte)dest; data[i + 3] = (Byte)dest;
} }
} }
return i; return i;
} }

View File

@ -1,68 +1,68 @@
/* Bra.h -- Branch converters for executables /* Bra.h -- Branch converters for executables
2009-02-07 : Igor Pavlov : Public domain */ 2009-02-07 : Igor Pavlov : Public domain */
#ifndef __BRA_H #ifndef __BRA_H
#define __BRA_H #define __BRA_H
#include "Types.h" #include "Types.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/* /*
These functions convert relative addresses to absolute addresses These functions convert relative addresses to absolute addresses
in CALL instructions to increase the compression ratio. in CALL instructions to increase the compression ratio.
In: In:
data - data buffer data - data buffer
size - size of data size - size of data
ip - current virtual Instruction Pinter (IP) value ip - current virtual Instruction Pinter (IP) value
state - state variable for x86 converter state - state variable for x86 converter
encoding - 0 (for decoding), 1 (for encoding) encoding - 0 (for decoding), 1 (for encoding)
Out: Out:
state - state variable for x86 converter state - state variable for x86 converter
Returns: Returns:
The number of processed bytes. If you call these functions with multiple calls, The number of processed bytes. If you call these functions with multiple calls,
you must start next call with first byte after block of processed bytes. you must start next call with first byte after block of processed bytes.
Type Endian Alignment LookAhead Type Endian Alignment LookAhead
x86 little 1 4 x86 little 1 4
ARMT little 2 2 ARMT little 2 2
ARM little 4 0 ARM little 4 0
PPC big 4 0 PPC big 4 0
SPARC big 4 0 SPARC big 4 0
IA64 little 16 0 IA64 little 16 0
size must be >= Alignment + LookAhead, if it's not last block. size must be >= Alignment + LookAhead, if it's not last block.
If (size < Alignment + LookAhead), converter returns 0. If (size < Alignment + LookAhead), converter returns 0.
Example: Example:
UInt32 ip = 0; UInt32 ip = 0;
for () for ()
{ {
; size must be >= Alignment + LookAhead, if it's not last block ; size must be >= Alignment + LookAhead, if it's not last block
SizeT processed = Convert(data, size, ip, 1); SizeT processed = Convert(data, size, ip, 1);
data += processed; data += processed;
size -= processed; size -= processed;
ip += processed; ip += processed;
} }
*/ */
#define x86_Convert_Init(state) { state = 0; } #define x86_Convert_Init(state) { state = 0; }
SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding); SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding);
SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif #endif

View File

@ -1,85 +1,85 @@
/* Bra86.c -- Converter for x86 code (BCJ) /* Bra86.c -- Converter for x86 code (BCJ)
2008-10-04 : Igor Pavlov : Public domain */ 2008-10-04 : Igor Pavlov : Public domain */
#include "Bra.h" #include "Bra.h"
#define Test86MSByte(b) ((b) == 0 || (b) == 0xFF) #define Test86MSByte(b) ((b) == 0 || (b) == 0xFF)
const Byte kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0}; const Byte kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0};
const Byte kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3}; const Byte kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3};
SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding) SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding)
{ {
SizeT bufferPos = 0, prevPosT; SizeT bufferPos = 0, prevPosT;
UInt32 prevMask = *state & 0x7; UInt32 prevMask = *state & 0x7;
if (size < 5) if (size < 5)
return 0; return 0;
ip += 5; ip += 5;
prevPosT = (SizeT)0 - 1; prevPosT = (SizeT)0 - 1;
for (;;) for (;;)
{ {
Byte *p = data + bufferPos; Byte *p = data + bufferPos;
Byte *limit = data + size - 4; Byte *limit = data + size - 4;
for (; p < limit; p++) for (; p < limit; p++)
if ((*p & 0xFE) == 0xE8) if ((*p & 0xFE) == 0xE8)
break; break;
bufferPos = (SizeT)(p - data); bufferPos = (SizeT)(p - data);
if (p >= limit) if (p >= limit)
break; break;
prevPosT = bufferPos - prevPosT; prevPosT = bufferPos - prevPosT;
if (prevPosT > 3) if (prevPosT > 3)
prevMask = 0; prevMask = 0;
else else
{ {
prevMask = (prevMask << ((int)prevPosT - 1)) & 0x7; prevMask = (prevMask << ((int)prevPosT - 1)) & 0x7;
if (prevMask != 0) if (prevMask != 0)
{ {
Byte b = p[4 - kMaskToBitNumber[prevMask]]; Byte b = p[4 - kMaskToBitNumber[prevMask]];
if (!kMaskToAllowedStatus[prevMask] || Test86MSByte(b)) if (!kMaskToAllowedStatus[prevMask] || Test86MSByte(b))
{ {
prevPosT = bufferPos; prevPosT = bufferPos;
prevMask = ((prevMask << 1) & 0x7) | 1; prevMask = ((prevMask << 1) & 0x7) | 1;
bufferPos++; bufferPos++;
continue; continue;
} }
} }
} }
prevPosT = bufferPos; prevPosT = bufferPos;
if (Test86MSByte(p[4])) if (Test86MSByte(p[4]))
{ {
UInt32 src = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]); UInt32 src = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]);
UInt32 dest; UInt32 dest;
for (;;) for (;;)
{ {
Byte b; Byte b;
int index; int index;
if (encoding) if (encoding)
dest = (ip + (UInt32)bufferPos) + src; dest = (ip + (UInt32)bufferPos) + src;
else else
dest = src - (ip + (UInt32)bufferPos); dest = src - (ip + (UInt32)bufferPos);
if (prevMask == 0) if (prevMask == 0)
break; break;
index = kMaskToBitNumber[prevMask] * 8; index = kMaskToBitNumber[prevMask] * 8;
b = (Byte)(dest >> (24 - index)); b = (Byte)(dest >> (24 - index));
if (!Test86MSByte(b)) if (!Test86MSByte(b))
break; break;
src = dest ^ ((1 << (32 - index)) - 1); src = dest ^ ((1 << (32 - index)) - 1);
} }
p[4] = (Byte)(~(((dest >> 24) & 1) - 1)); p[4] = (Byte)(~(((dest >> 24) & 1) - 1));
p[3] = (Byte)(dest >> 16); p[3] = (Byte)(dest >> 16);
p[2] = (Byte)(dest >> 8); p[2] = (Byte)(dest >> 8);
p[1] = (Byte)dest; p[1] = (Byte)dest;
bufferPos += 5; bufferPos += 5;
} }
else else
{ {
prevMask = ((prevMask << 1) & 0x7) | 1; prevMask = ((prevMask << 1) & 0x7) | 1;
bufferPos++; bufferPos++;
} }
} }
prevPosT = bufferPos - prevPosT; prevPosT = bufferPos - prevPosT;
*state = ((prevPosT > 3) ? 0 : ((prevMask << ((int)prevPosT - 1)) & 0x7)); *state = ((prevPosT > 3) ? 0 : ((prevMask << ((int)prevPosT - 1)) & 0x7));
return bufferPos; return bufferPos;
} }

View File

@ -1,168 +1,168 @@
/* CpuArch.c -- CPU specific code /* CpuArch.c -- CPU specific code
2010-10-26: Igor Pavlov : Public domain */ 2010-10-26: Igor Pavlov : Public domain */
#include "CpuArch.h" #include "CpuArch.h"
#ifdef MY_CPU_X86_OR_AMD64 #ifdef MY_CPU_X86_OR_AMD64
#if (defined(_MSC_VER) && !defined(MY_CPU_AMD64)) || defined(__GNUC__) #if (defined(_MSC_VER) && !defined(MY_CPU_AMD64)) || defined(__GNUC__)
#define USE_ASM #define USE_ASM
#endif #endif
#if defined(USE_ASM) && !defined(MY_CPU_AMD64) #if defined(USE_ASM) && !defined(MY_CPU_AMD64)
static UInt32 CheckFlag(UInt32 flag) static UInt32 CheckFlag(UInt32 flag)
{ {
#ifdef _MSC_VER #ifdef _MSC_VER
__asm pushfd; __asm pushfd;
__asm pop EAX; __asm pop EAX;
__asm mov EDX, EAX; __asm mov EDX, EAX;
__asm xor EAX, flag; __asm xor EAX, flag;
__asm push EAX; __asm push EAX;
__asm popfd; __asm popfd;
__asm pushfd; __asm pushfd;
__asm pop EAX; __asm pop EAX;
__asm xor EAX, EDX; __asm xor EAX, EDX;
__asm push EDX; __asm push EDX;
__asm popfd; __asm popfd;
__asm and flag, EAX; __asm and flag, EAX;
#else #else
__asm__ __volatile__ ( __asm__ __volatile__ (
"pushf\n\t" "pushf\n\t"
"pop %%EAX\n\t" "pop %%EAX\n\t"
"movl %%EAX,%%EDX\n\t" "movl %%EAX,%%EDX\n\t"
"xorl %0,%%EAX\n\t" "xorl %0,%%EAX\n\t"
"push %%EAX\n\t" "push %%EAX\n\t"
"popf\n\t" "popf\n\t"
"pushf\n\t" "pushf\n\t"
"pop %%EAX\n\t" "pop %%EAX\n\t"
"xorl %%EDX,%%EAX\n\t" "xorl %%EDX,%%EAX\n\t"
"push %%EDX\n\t" "push %%EDX\n\t"
"popf\n\t" "popf\n\t"
"andl %%EAX, %0\n\t": "andl %%EAX, %0\n\t":
"=c" (flag) : "c" (flag)); "=c" (flag) : "c" (flag));
#endif #endif
return flag; return flag;
} }
#define CHECK_CPUID_IS_SUPPORTED if (CheckFlag(1 << 18) == 0 || CheckFlag(1 << 21) == 0) return False; #define CHECK_CPUID_IS_SUPPORTED if (CheckFlag(1 << 18) == 0 || CheckFlag(1 << 21) == 0) return False;
#else #else
#define CHECK_CPUID_IS_SUPPORTED #define CHECK_CPUID_IS_SUPPORTED
#endif #endif
static void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d) static void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d)
{ {
#ifdef USE_ASM #ifdef USE_ASM
#ifdef _MSC_VER #ifdef _MSC_VER
UInt32 a2, b2, c2, d2; UInt32 a2, b2, c2, d2;
__asm xor EBX, EBX; __asm xor EBX, EBX;
__asm xor ECX, ECX; __asm xor ECX, ECX;
__asm xor EDX, EDX; __asm xor EDX, EDX;
__asm mov EAX, function; __asm mov EAX, function;
__asm cpuid; __asm cpuid;
__asm mov a2, EAX; __asm mov a2, EAX;
__asm mov b2, EBX; __asm mov b2, EBX;
__asm mov c2, ECX; __asm mov c2, ECX;
__asm mov d2, EDX; __asm mov d2, EDX;
*a = a2; *a = a2;
*b = b2; *b = b2;
*c = c2; *c = c2;
*d = d2; *d = d2;
#else #else
__asm__ __volatile__ ( __asm__ __volatile__ (
"cpuid" "cpuid"
: "=a" (*a) , : "=a" (*a) ,
"=b" (*b) , "=b" (*b) ,
"=c" (*c) , "=c" (*c) ,
"=d" (*d) "=d" (*d)
: "0" (function)) ; : "0" (function)) ;
#endif #endif
#else #else
int CPUInfo[4]; int CPUInfo[4];
__cpuid(CPUInfo, function); __cpuid(CPUInfo, function);
*a = CPUInfo[0]; *a = CPUInfo[0];
*b = CPUInfo[1]; *b = CPUInfo[1];
*c = CPUInfo[2]; *c = CPUInfo[2];
*d = CPUInfo[3]; *d = CPUInfo[3];
#endif #endif
} }
Bool x86cpuid_CheckAndRead(Cx86cpuid *p) Bool x86cpuid_CheckAndRead(Cx86cpuid *p)
{ {
CHECK_CPUID_IS_SUPPORTED CHECK_CPUID_IS_SUPPORTED
MyCPUID(0, &p->maxFunc, &p->vendor[0], &p->vendor[2], &p->vendor[1]); MyCPUID(0, &p->maxFunc, &p->vendor[0], &p->vendor[2], &p->vendor[1]);
MyCPUID(1, &p->ver, &p->b, &p->c, &p->d); MyCPUID(1, &p->ver, &p->b, &p->c, &p->d);
return True; return True;
} }
static UInt32 kVendors[][3] = static UInt32 kVendors[][3] =
{ {
{ 0x756E6547, 0x49656E69, 0x6C65746E}, { 0x756E6547, 0x49656E69, 0x6C65746E},
{ 0x68747541, 0x69746E65, 0x444D4163}, { 0x68747541, 0x69746E65, 0x444D4163},
{ 0x746E6543, 0x48727561, 0x736C7561} { 0x746E6543, 0x48727561, 0x736C7561}
}; };
int x86cpuid_GetFirm(const Cx86cpuid *p) int x86cpuid_GetFirm(const Cx86cpuid *p)
{ {
unsigned i; unsigned i;
for (i = 0; i < sizeof(kVendors) / sizeof(kVendors[i]); i++) for (i = 0; i < sizeof(kVendors) / sizeof(kVendors[i]); i++)
{ {
const UInt32 *v = kVendors[i]; const UInt32 *v = kVendors[i];
if (v[0] == p->vendor[0] && if (v[0] == p->vendor[0] &&
v[1] == p->vendor[1] && v[1] == p->vendor[1] &&
v[2] == p->vendor[2]) v[2] == p->vendor[2])
return (int)i; return (int)i;
} }
return -1; return -1;
} }
Bool CPU_Is_InOrder() Bool CPU_Is_InOrder()
{ {
Cx86cpuid p; Cx86cpuid p;
int firm; int firm;
UInt32 family, model; UInt32 family, model;
if (!x86cpuid_CheckAndRead(&p)) if (!x86cpuid_CheckAndRead(&p))
return True; return True;
family = x86cpuid_GetFamily(&p); family = x86cpuid_GetFamily(&p);
model = x86cpuid_GetModel(&p); model = x86cpuid_GetModel(&p);
firm = x86cpuid_GetFirm(&p); firm = x86cpuid_GetFirm(&p);
switch (firm) switch (firm)
{ {
case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && model == 0x100C)); case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && model == 0x100C));
case CPU_FIRM_AMD: return (family < 5 || (family == 5 && (model < 6 || model == 0xA))); case CPU_FIRM_AMD: return (family < 5 || (family == 5 && (model < 6 || model == 0xA)));
case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF)); case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF));
} }
return True; return True;
} }
#if !defined(MY_CPU_AMD64) && defined(_WIN32) #if !defined(MY_CPU_AMD64) && defined(_WIN32)
static Bool CPU_Sys_Is_SSE_Supported() static Bool CPU_Sys_Is_SSE_Supported()
{ {
OSVERSIONINFO vi; OSVERSIONINFO vi;
vi.dwOSVersionInfoSize = sizeof(vi); vi.dwOSVersionInfoSize = sizeof(vi);
if (!GetVersionEx(&vi)) if (!GetVersionEx(&vi))
return False; return False;
return (vi.dwMajorVersion >= 5); return (vi.dwMajorVersion >= 5);
} }
#define CHECK_SYS_SSE_SUPPORT if (!CPU_Sys_Is_SSE_Supported()) return False; #define CHECK_SYS_SSE_SUPPORT if (!CPU_Sys_Is_SSE_Supported()) return False;
#else #else
#define CHECK_SYS_SSE_SUPPORT #define CHECK_SYS_SSE_SUPPORT
#endif #endif
Bool CPU_Is_Aes_Supported() Bool CPU_Is_Aes_Supported()
{ {
Cx86cpuid p; Cx86cpuid p;
CHECK_SYS_SSE_SUPPORT CHECK_SYS_SSE_SUPPORT
if (!x86cpuid_CheckAndRead(&p)) if (!x86cpuid_CheckAndRead(&p))
return False; return False;
return (p.c >> 25) & 1; return (p.c >> 25) & 1;
} }
#endif #endif

View File

@ -1,155 +1,155 @@
/* CpuArch.h -- CPU specific code /* CpuArch.h -- CPU specific code
2010-10-26: Igor Pavlov : Public domain */ 2010-10-26: Igor Pavlov : Public domain */
#ifndef __CPU_ARCH_H #ifndef __CPU_ARCH_H
#define __CPU_ARCH_H #define __CPU_ARCH_H
#include "Types.h" #include "Types.h"
EXTERN_C_BEGIN EXTERN_C_BEGIN
/* /*
MY_CPU_LE means that CPU is LITTLE ENDIAN. MY_CPU_LE means that CPU is LITTLE ENDIAN.
If MY_CPU_LE is not defined, we don't know about that property of platform (it can be LITTLE ENDIAN). If MY_CPU_LE is not defined, we don't know about that property of platform (it can be LITTLE ENDIAN).
MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned memory accesses. MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned memory accesses.
If MY_CPU_LE_UNALIGN is not defined, we don't know about these properties of platform. If MY_CPU_LE_UNALIGN is not defined, we don't know about these properties of platform.
*/ */
#if defined(_M_X64) || defined(_M_AMD64) || defined(__x86_64__) #if defined(_M_X64) || defined(_M_AMD64) || defined(__x86_64__)
#define MY_CPU_AMD64 #define MY_CPU_AMD64
#endif #endif
#if defined(MY_CPU_AMD64) || defined(_M_IA64) #if defined(MY_CPU_AMD64) || defined(_M_IA64)
#define MY_CPU_64BIT #define MY_CPU_64BIT
#endif #endif
#if defined(_M_IX86) || defined(__i386__) #if defined(_M_IX86) || defined(__i386__)
#define MY_CPU_X86 #define MY_CPU_X86
#endif #endif
#if defined(MY_CPU_X86) || defined(MY_CPU_AMD64) #if defined(MY_CPU_X86) || defined(MY_CPU_AMD64)
#define MY_CPU_X86_OR_AMD64 #define MY_CPU_X86_OR_AMD64
#endif #endif
#if defined(MY_CPU_X86) || defined(_M_ARM) #if defined(MY_CPU_X86) || defined(_M_ARM)
#define MY_CPU_32BIT #define MY_CPU_32BIT
#endif #endif
#if defined(_WIN32) && defined(_M_ARM) #if defined(_WIN32) && defined(_M_ARM)
#define MY_CPU_ARM_LE #define MY_CPU_ARM_LE
#endif #endif
#if defined(_WIN32) && defined(_M_IA64) #if defined(_WIN32) && defined(_M_IA64)
#define MY_CPU_IA64_LE #define MY_CPU_IA64_LE
#endif #endif
#if defined(MY_CPU_X86_OR_AMD64) #if defined(MY_CPU_X86_OR_AMD64)
#define MY_CPU_LE_UNALIGN #define MY_CPU_LE_UNALIGN
#endif #endif
#if defined(MY_CPU_X86_OR_AMD64) || defined(MY_CPU_ARM_LE) || defined(MY_CPU_IA64_LE) || defined(__ARMEL__) || defined(__MIPSEL__) || defined(__LITTLE_ENDIAN__) #if defined(MY_CPU_X86_OR_AMD64) || defined(MY_CPU_ARM_LE) || defined(MY_CPU_IA64_LE) || defined(__ARMEL__) || defined(__MIPSEL__) || defined(__LITTLE_ENDIAN__)
#define MY_CPU_LE #define MY_CPU_LE
#endif #endif
#if defined(__BIG_ENDIAN__) #if defined(__BIG_ENDIAN__)
#define MY_CPU_BE #define MY_CPU_BE
#endif #endif
#if defined(MY_CPU_LE) && defined(MY_CPU_BE) #if defined(MY_CPU_LE) && defined(MY_CPU_BE)
Stop_Compiling_Bad_Endian Stop_Compiling_Bad_Endian
#endif #endif
#ifdef MY_CPU_LE_UNALIGN #ifdef MY_CPU_LE_UNALIGN
#define GetUi16(p) (*(const UInt16 *)(p)) #define GetUi16(p) (*(const UInt16 *)(p))
#define GetUi32(p) (*(const UInt32 *)(p)) #define GetUi32(p) (*(const UInt32 *)(p))
#define GetUi64(p) (*(const UInt64 *)(p)) #define GetUi64(p) (*(const UInt64 *)(p))
#define SetUi16(p, d) *(UInt16 *)(p) = (d); #define SetUi16(p, d) *(UInt16 *)(p) = (d);
#define SetUi32(p, d) *(UInt32 *)(p) = (d); #define SetUi32(p, d) *(UInt32 *)(p) = (d);
#define SetUi64(p, d) *(UInt64 *)(p) = (d); #define SetUi64(p, d) *(UInt64 *)(p) = (d);
#else #else
#define GetUi16(p) (((const Byte *)(p))[0] | ((UInt16)((const Byte *)(p))[1] << 8)) #define GetUi16(p) (((const Byte *)(p))[0] | ((UInt16)((const Byte *)(p))[1] << 8))
#define GetUi32(p) ( \ #define GetUi32(p) ( \
((const Byte *)(p))[0] | \ ((const Byte *)(p))[0] | \
((UInt32)((const Byte *)(p))[1] << 8) | \ ((UInt32)((const Byte *)(p))[1] << 8) | \
((UInt32)((const Byte *)(p))[2] << 16) | \ ((UInt32)((const Byte *)(p))[2] << 16) | \
((UInt32)((const Byte *)(p))[3] << 24)) ((UInt32)((const Byte *)(p))[3] << 24))
#define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32)) #define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32))
#define SetUi16(p, d) { UInt32 _x_ = (d); \ #define SetUi16(p, d) { UInt32 _x_ = (d); \
((Byte *)(p))[0] = (Byte)_x_; \ ((Byte *)(p))[0] = (Byte)_x_; \
((Byte *)(p))[1] = (Byte)(_x_ >> 8); } ((Byte *)(p))[1] = (Byte)(_x_ >> 8); }
#define SetUi32(p, d) { UInt32 _x_ = (d); \ #define SetUi32(p, d) { UInt32 _x_ = (d); \
((Byte *)(p))[0] = (Byte)_x_; \ ((Byte *)(p))[0] = (Byte)_x_; \
((Byte *)(p))[1] = (Byte)(_x_ >> 8); \ ((Byte *)(p))[1] = (Byte)(_x_ >> 8); \
((Byte *)(p))[2] = (Byte)(_x_ >> 16); \ ((Byte *)(p))[2] = (Byte)(_x_ >> 16); \
((Byte *)(p))[3] = (Byte)(_x_ >> 24); } ((Byte *)(p))[3] = (Byte)(_x_ >> 24); }
#define SetUi64(p, d) { UInt64 _x64_ = (d); \ #define SetUi64(p, d) { UInt64 _x64_ = (d); \
SetUi32(p, (UInt32)_x64_); \ SetUi32(p, (UInt32)_x64_); \
SetUi32(((Byte *)(p)) + 4, (UInt32)(_x64_ >> 32)); } SetUi32(((Byte *)(p)) + 4, (UInt32)(_x64_ >> 32)); }
#endif #endif
#if defined(MY_CPU_LE_UNALIGN) && defined(_WIN64) && (_MSC_VER >= 1300) #if defined(MY_CPU_LE_UNALIGN) && defined(_WIN64) && (_MSC_VER >= 1300)
#pragma intrinsic(_byteswap_ulong) #pragma intrinsic(_byteswap_ulong)
#pragma intrinsic(_byteswap_uint64) #pragma intrinsic(_byteswap_uint64)
#define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p)) #define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p))
#define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const Byte *)(p)) #define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const Byte *)(p))
#else #else
#define GetBe32(p) ( \ #define GetBe32(p) ( \
((UInt32)((const Byte *)(p))[0] << 24) | \ ((UInt32)((const Byte *)(p))[0] << 24) | \
((UInt32)((const Byte *)(p))[1] << 16) | \ ((UInt32)((const Byte *)(p))[1] << 16) | \
((UInt32)((const Byte *)(p))[2] << 8) | \ ((UInt32)((const Byte *)(p))[2] << 8) | \
((const Byte *)(p))[3] ) ((const Byte *)(p))[3] )
#define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4)) #define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4))
#endif #endif
#define GetBe16(p) (((UInt16)((const Byte *)(p))[0] << 8) | ((const Byte *)(p))[1]) #define GetBe16(p) (((UInt16)((const Byte *)(p))[0] << 8) | ((const Byte *)(p))[1])
#ifdef MY_CPU_X86_OR_AMD64 #ifdef MY_CPU_X86_OR_AMD64
typedef struct typedef struct
{ {
UInt32 maxFunc; UInt32 maxFunc;
UInt32 vendor[3]; UInt32 vendor[3];
UInt32 ver; UInt32 ver;
UInt32 b; UInt32 b;
UInt32 c; UInt32 c;
UInt32 d; UInt32 d;
} Cx86cpuid; } Cx86cpuid;
enum enum
{ {
CPU_FIRM_INTEL, CPU_FIRM_INTEL,
CPU_FIRM_AMD, CPU_FIRM_AMD,
CPU_FIRM_VIA CPU_FIRM_VIA
}; };
Bool x86cpuid_CheckAndRead(Cx86cpuid *p); Bool x86cpuid_CheckAndRead(Cx86cpuid *p);
int x86cpuid_GetFirm(const Cx86cpuid *p); int x86cpuid_GetFirm(const Cx86cpuid *p);
#define x86cpuid_GetFamily(p) (((p)->ver >> 8) & 0xFF00F) #define x86cpuid_GetFamily(p) (((p)->ver >> 8) & 0xFF00F)
#define x86cpuid_GetModel(p) (((p)->ver >> 4) & 0xF00F) #define x86cpuid_GetModel(p) (((p)->ver >> 4) & 0xF00F)
#define x86cpuid_GetStepping(p) ((p)->ver & 0xF) #define x86cpuid_GetStepping(p) ((p)->ver & 0xF)
Bool CPU_Is_InOrder(); Bool CPU_Is_InOrder();
Bool CPU_Is_Aes_Supported(); Bool CPU_Is_Aes_Supported();
#endif #endif
EXTERN_C_END EXTERN_C_END
#endif #endif

View File

@ -1,371 +1,371 @@
/* Lzma2Dec.c -- LZMA2 Decoder /* Lzma2Dec.c -- LZMA2 Decoder
2009-05-03 : Igor Pavlov : Public domain */ 2009-05-03 : Igor Pavlov : Public domain */
/* #define SHOW_DEBUG_INFO */ /* #define SHOW_DEBUG_INFO */
#ifdef SHOW_DEBUG_INFO #ifdef SHOW_DEBUG_INFO
#include <stdio.h> #include <stdio.h>
#endif #endif
#include <string.h> #include <string.h>
#include "Lzma2Dec.h" #include "Lzma2Dec.h"
/* /*
00000000 - EOS 00000000 - EOS
00000001 U U - Uncompressed Reset Dic 00000001 U U - Uncompressed Reset Dic
00000010 U U - Uncompressed No Reset 00000010 U U - Uncompressed No Reset
100uuuuu U U P P - LZMA no reset 100uuuuu U U P P - LZMA no reset
101uuuuu U U P P - LZMA reset state 101uuuuu U U P P - LZMA reset state
110uuuuu U U P P S - LZMA reset state + new prop 110uuuuu U U P P S - LZMA reset state + new prop
111uuuuu U U P P S - LZMA reset state + new prop + reset dic 111uuuuu U U P P S - LZMA reset state + new prop + reset dic
u, U - Unpack Size u, U - Unpack Size
P - Pack Size P - Pack Size
S - Props S - Props
*/ */
#define LZMA2_CONTROL_LZMA (1 << 7) #define LZMA2_CONTROL_LZMA (1 << 7)
#define LZMA2_CONTROL_COPY_NO_RESET 2 #define LZMA2_CONTROL_COPY_NO_RESET 2
#define LZMA2_CONTROL_COPY_RESET_DIC 1 #define LZMA2_CONTROL_COPY_RESET_DIC 1
#define LZMA2_CONTROL_EOF 0 #define LZMA2_CONTROL_EOF 0
#define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & LZMA2_CONTROL_LZMA) == 0) #define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & LZMA2_CONTROL_LZMA) == 0)
#define LZMA2_GET_LZMA_MODE(p) (((p)->control >> 5) & 3) #define LZMA2_GET_LZMA_MODE(p) (((p)->control >> 5) & 3)
#define LZMA2_IS_THERE_PROP(mode) ((mode) >= 2) #define LZMA2_IS_THERE_PROP(mode) ((mode) >= 2)
#define LZMA2_LCLP_MAX 4 #define LZMA2_LCLP_MAX 4
#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11)) #define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))
#ifdef SHOW_DEBUG_INFO #ifdef SHOW_DEBUG_INFO
#define PRF(x) x #define PRF(x) x
#else #else
#define PRF(x) #define PRF(x)
#endif #endif
typedef enum typedef enum
{ {
LZMA2_STATE_CONTROL, LZMA2_STATE_CONTROL,
LZMA2_STATE_UNPACK0, LZMA2_STATE_UNPACK0,
LZMA2_STATE_UNPACK1, LZMA2_STATE_UNPACK1,
LZMA2_STATE_PACK0, LZMA2_STATE_PACK0,
LZMA2_STATE_PACK1, LZMA2_STATE_PACK1,
LZMA2_STATE_PROP, LZMA2_STATE_PROP,
LZMA2_STATE_DATA, LZMA2_STATE_DATA,
LZMA2_STATE_DATA_CONT, LZMA2_STATE_DATA_CONT,
LZMA2_STATE_FINISHED, LZMA2_STATE_FINISHED,
LZMA2_STATE_ERROR LZMA2_STATE_ERROR
} ELzma2State; } ELzma2State;
static SRes Lzma2Dec_GetOldProps(Byte prop, Byte *props) static SRes Lzma2Dec_GetOldProps(Byte prop, Byte *props)
{ {
UInt32 dicSize; UInt32 dicSize;
if (prop > 40) if (prop > 40)
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
dicSize = (prop == 40) ? 0xFFFFFFFF : LZMA2_DIC_SIZE_FROM_PROP(prop); dicSize = (prop == 40) ? 0xFFFFFFFF : LZMA2_DIC_SIZE_FROM_PROP(prop);
props[0] = (Byte)LZMA2_LCLP_MAX; props[0] = (Byte)LZMA2_LCLP_MAX;
props[1] = (Byte)(dicSize); props[1] = (Byte)(dicSize);
props[2] = (Byte)(dicSize >> 8); props[2] = (Byte)(dicSize >> 8);
props[3] = (Byte)(dicSize >> 16); props[3] = (Byte)(dicSize >> 16);
props[4] = (Byte)(dicSize >> 24); props[4] = (Byte)(dicSize >> 24);
return SZ_OK; return SZ_OK;
} }
SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAlloc *alloc) SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAlloc *alloc)
{ {
Byte props[LZMA_PROPS_SIZE]; Byte props[LZMA_PROPS_SIZE];
RINOK(Lzma2Dec_GetOldProps(prop, props)); RINOK(Lzma2Dec_GetOldProps(prop, props));
return LzmaDec_AllocateProbs(&p->decoder, props, LZMA_PROPS_SIZE, alloc); return LzmaDec_AllocateProbs(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
} }
SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc) SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc)
{ {
Byte props[LZMA_PROPS_SIZE]; Byte props[LZMA_PROPS_SIZE];
RINOK(Lzma2Dec_GetOldProps(prop, props)); RINOK(Lzma2Dec_GetOldProps(prop, props));
return LzmaDec_Allocate(&p->decoder, props, LZMA_PROPS_SIZE, alloc); return LzmaDec_Allocate(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
} }
void Lzma2Dec_Init(CLzma2Dec *p) void Lzma2Dec_Init(CLzma2Dec *p)
{ {
p->state = LZMA2_STATE_CONTROL; p->state = LZMA2_STATE_CONTROL;
p->needInitDic = True; p->needInitDic = True;
p->needInitState = True; p->needInitState = True;
p->needInitProp = True; p->needInitProp = True;
LzmaDec_Init(&p->decoder); LzmaDec_Init(&p->decoder);
} }
static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b) static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
{ {
switch(p->state) switch(p->state)
{ {
case LZMA2_STATE_CONTROL: case LZMA2_STATE_CONTROL:
p->control = b; p->control = b;
PRF(printf("\n %4X ", p->decoder.dicPos)); PRF(printf("\n %4X ", p->decoder.dicPos));
PRF(printf(" %2X", b)); PRF(printf(" %2X", b));
if (p->control == 0) if (p->control == 0)
return LZMA2_STATE_FINISHED; return LZMA2_STATE_FINISHED;
if (LZMA2_IS_UNCOMPRESSED_STATE(p)) if (LZMA2_IS_UNCOMPRESSED_STATE(p))
{ {
if ((p->control & 0x7F) > 2) if ((p->control & 0x7F) > 2)
return LZMA2_STATE_ERROR; return LZMA2_STATE_ERROR;
p->unpackSize = 0; p->unpackSize = 0;
} }
else else
p->unpackSize = (UInt32)(p->control & 0x1F) << 16; p->unpackSize = (UInt32)(p->control & 0x1F) << 16;
return LZMA2_STATE_UNPACK0; return LZMA2_STATE_UNPACK0;
case LZMA2_STATE_UNPACK0: case LZMA2_STATE_UNPACK0:
p->unpackSize |= (UInt32)b << 8; p->unpackSize |= (UInt32)b << 8;
return LZMA2_STATE_UNPACK1; return LZMA2_STATE_UNPACK1;
case LZMA2_STATE_UNPACK1: case LZMA2_STATE_UNPACK1:
p->unpackSize |= (UInt32)b; p->unpackSize |= (UInt32)b;
p->unpackSize++; p->unpackSize++;
PRF(printf(" %8d", p->unpackSize)); PRF(printf(" %8d", p->unpackSize));
return (LZMA2_IS_UNCOMPRESSED_STATE(p)) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0; return (LZMA2_IS_UNCOMPRESSED_STATE(p)) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0;
case LZMA2_STATE_PACK0: case LZMA2_STATE_PACK0:
p->packSize = (UInt32)b << 8; p->packSize = (UInt32)b << 8;
return LZMA2_STATE_PACK1; return LZMA2_STATE_PACK1;
case LZMA2_STATE_PACK1: case LZMA2_STATE_PACK1:
p->packSize |= (UInt32)b; p->packSize |= (UInt32)b;
p->packSize++; p->packSize++;
PRF(printf(" %8d", p->packSize)); PRF(printf(" %8d", p->packSize));
return LZMA2_IS_THERE_PROP(LZMA2_GET_LZMA_MODE(p)) ? LZMA2_STATE_PROP: return LZMA2_IS_THERE_PROP(LZMA2_GET_LZMA_MODE(p)) ? LZMA2_STATE_PROP:
(p->needInitProp ? LZMA2_STATE_ERROR : LZMA2_STATE_DATA); (p->needInitProp ? LZMA2_STATE_ERROR : LZMA2_STATE_DATA);
case LZMA2_STATE_PROP: case LZMA2_STATE_PROP:
{ {
int lc, lp; int lc, lp;
if (b >= (9 * 5 * 5)) if (b >= (9 * 5 * 5))
return LZMA2_STATE_ERROR; return LZMA2_STATE_ERROR;
lc = b % 9; lc = b % 9;
b /= 9; b /= 9;
p->decoder.prop.pb = b / 5; p->decoder.prop.pb = b / 5;
lp = b % 5; lp = b % 5;
if (lc + lp > LZMA2_LCLP_MAX) if (lc + lp > LZMA2_LCLP_MAX)
return LZMA2_STATE_ERROR; return LZMA2_STATE_ERROR;
p->decoder.prop.lc = lc; p->decoder.prop.lc = lc;
p->decoder.prop.lp = lp; p->decoder.prop.lp = lp;
p->needInitProp = False; p->needInitProp = False;
return LZMA2_STATE_DATA; return LZMA2_STATE_DATA;
} }
} }
return LZMA2_STATE_ERROR; return LZMA2_STATE_ERROR;
} }
static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size) static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size)
{ {
memcpy(p->dic + p->dicPos, src, size); memcpy(p->dic + p->dicPos, src, size);
p->dicPos += size; p->dicPos += size;
if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= size) if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= size)
p->checkDicSize = p->prop.dicSize; p->checkDicSize = p->prop.dicSize;
p->processedPos += (UInt32)size; p->processedPos += (UInt32)size;
} }
static static
void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState) void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState)
{ {
p->needFlush = 1; p->needFlush = 1;
p->remainLen = 0; p->remainLen = 0;
p->tempBufSize = 0; p->tempBufSize = 0;
if (initDic) if (initDic)
{ {
p->processedPos = 0; p->processedPos = 0;
p->checkDicSize = 0; p->checkDicSize = 0;
p->needInitState = 1; p->needInitState = 1;
} }
if (initState) if (initState)
p->needInitState = 1; p->needInitState = 1;
} }
SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit, SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
{ {
SizeT inSize = *srcLen; SizeT inSize = *srcLen;
*srcLen = 0; *srcLen = 0;
*status = LZMA_STATUS_NOT_SPECIFIED; *status = LZMA_STATUS_NOT_SPECIFIED;
while (p->state != LZMA2_STATE_FINISHED) while (p->state != LZMA2_STATE_FINISHED)
{ {
SizeT dicPos = p->decoder.dicPos; SizeT dicPos = p->decoder.dicPos;
if (p->state == LZMA2_STATE_ERROR) if (p->state == LZMA2_STATE_ERROR)
return SZ_ERROR_DATA; return SZ_ERROR_DATA;
if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY) if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY)
{ {
*status = LZMA_STATUS_NOT_FINISHED; *status = LZMA_STATUS_NOT_FINISHED;
return SZ_OK; return SZ_OK;
} }
if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT) if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
{ {
if (*srcLen == inSize) if (*srcLen == inSize)
{ {
*status = LZMA_STATUS_NEEDS_MORE_INPUT; *status = LZMA_STATUS_NEEDS_MORE_INPUT;
return SZ_OK; return SZ_OK;
} }
(*srcLen)++; (*srcLen)++;
p->state = Lzma2Dec_UpdateState(p, *src++); p->state = Lzma2Dec_UpdateState(p, *src++);
continue; continue;
} }
{ {
SizeT destSizeCur = dicLimit - dicPos; SizeT destSizeCur = dicLimit - dicPos;
SizeT srcSizeCur = inSize - *srcLen; SizeT srcSizeCur = inSize - *srcLen;
ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY; ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY;
if (p->unpackSize <= destSizeCur) if (p->unpackSize <= destSizeCur)
{ {
destSizeCur = (SizeT)p->unpackSize; destSizeCur = (SizeT)p->unpackSize;
curFinishMode = LZMA_FINISH_END; curFinishMode = LZMA_FINISH_END;
} }
if (LZMA2_IS_UNCOMPRESSED_STATE(p)) if (LZMA2_IS_UNCOMPRESSED_STATE(p))
{ {
if (*srcLen == inSize) if (*srcLen == inSize)
{ {
*status = LZMA_STATUS_NEEDS_MORE_INPUT; *status = LZMA_STATUS_NEEDS_MORE_INPUT;
return SZ_OK; return SZ_OK;
} }
if (p->state == LZMA2_STATE_DATA) if (p->state == LZMA2_STATE_DATA)
{ {
Bool initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC); Bool initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC);
if (initDic) if (initDic)
p->needInitProp = p->needInitState = True; p->needInitProp = p->needInitState = True;
else if (p->needInitDic) else if (p->needInitDic)
return SZ_ERROR_DATA; return SZ_ERROR_DATA;
p->needInitDic = False; p->needInitDic = False;
LzmaDec_InitDicAndState(&p->decoder, initDic, False); LzmaDec_InitDicAndState(&p->decoder, initDic, False);
} }
if (srcSizeCur > destSizeCur) if (srcSizeCur > destSizeCur)
srcSizeCur = destSizeCur; srcSizeCur = destSizeCur;
if (srcSizeCur == 0) if (srcSizeCur == 0)
return SZ_ERROR_DATA; return SZ_ERROR_DATA;
LzmaDec_UpdateWithUncompressed(&p->decoder, src, srcSizeCur); LzmaDec_UpdateWithUncompressed(&p->decoder, src, srcSizeCur);
src += srcSizeCur; src += srcSizeCur;
*srcLen += srcSizeCur; *srcLen += srcSizeCur;
p->unpackSize -= (UInt32)srcSizeCur; p->unpackSize -= (UInt32)srcSizeCur;
p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT; p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
} }
else else
{ {
SizeT outSizeProcessed; SizeT outSizeProcessed;
SRes res; SRes res;
if (p->state == LZMA2_STATE_DATA) if (p->state == LZMA2_STATE_DATA)
{ {
int mode = LZMA2_GET_LZMA_MODE(p); int mode = LZMA2_GET_LZMA_MODE(p);
Bool initDic = (mode == 3); Bool initDic = (mode == 3);
Bool initState = (mode > 0); Bool initState = (mode > 0);
if ((!initDic && p->needInitDic) || (!initState && p->needInitState)) if ((!initDic && p->needInitDic) || (!initState && p->needInitState))
return SZ_ERROR_DATA; return SZ_ERROR_DATA;
LzmaDec_InitDicAndState(&p->decoder, initDic, initState); LzmaDec_InitDicAndState(&p->decoder, initDic, initState);
p->needInitDic = False; p->needInitDic = False;
p->needInitState = False; p->needInitState = False;
p->state = LZMA2_STATE_DATA_CONT; p->state = LZMA2_STATE_DATA_CONT;
} }
if (srcSizeCur > p->packSize) if (srcSizeCur > p->packSize)
srcSizeCur = (SizeT)p->packSize; srcSizeCur = (SizeT)p->packSize;
res = LzmaDec_DecodeToDic(&p->decoder, dicPos + destSizeCur, src, &srcSizeCur, curFinishMode, status); res = LzmaDec_DecodeToDic(&p->decoder, dicPos + destSizeCur, src, &srcSizeCur, curFinishMode, status);
src += srcSizeCur; src += srcSizeCur;
*srcLen += srcSizeCur; *srcLen += srcSizeCur;
p->packSize -= (UInt32)srcSizeCur; p->packSize -= (UInt32)srcSizeCur;
outSizeProcessed = p->decoder.dicPos - dicPos; outSizeProcessed = p->decoder.dicPos - dicPos;
p->unpackSize -= (UInt32)outSizeProcessed; p->unpackSize -= (UInt32)outSizeProcessed;
RINOK(res); RINOK(res);
if (*status == LZMA_STATUS_NEEDS_MORE_INPUT) if (*status == LZMA_STATUS_NEEDS_MORE_INPUT)
return res; return res;
if (srcSizeCur == 0 && outSizeProcessed == 0) if (srcSizeCur == 0 && outSizeProcessed == 0)
{ {
if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK || if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK ||
p->unpackSize != 0 || p->packSize != 0) p->unpackSize != 0 || p->packSize != 0)
return SZ_ERROR_DATA; return SZ_ERROR_DATA;
p->state = LZMA2_STATE_CONTROL; p->state = LZMA2_STATE_CONTROL;
} }
if (*status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK) if (*status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
*status = LZMA_STATUS_NOT_FINISHED; *status = LZMA_STATUS_NOT_FINISHED;
} }
} }
} }
*status = LZMA_STATUS_FINISHED_WITH_MARK; *status = LZMA_STATUS_FINISHED_WITH_MARK;
return SZ_OK; return SZ_OK;
} }
SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
{ {
SizeT outSize = *destLen, inSize = *srcLen; SizeT outSize = *destLen, inSize = *srcLen;
*srcLen = *destLen = 0; *srcLen = *destLen = 0;
for (;;) for (;;)
{ {
SizeT srcSizeCur = inSize, outSizeCur, dicPos; SizeT srcSizeCur = inSize, outSizeCur, dicPos;
ELzmaFinishMode curFinishMode; ELzmaFinishMode curFinishMode;
SRes res; SRes res;
if (p->decoder.dicPos == p->decoder.dicBufSize) if (p->decoder.dicPos == p->decoder.dicBufSize)
p->decoder.dicPos = 0; p->decoder.dicPos = 0;
dicPos = p->decoder.dicPos; dicPos = p->decoder.dicPos;
if (outSize > p->decoder.dicBufSize - dicPos) if (outSize > p->decoder.dicBufSize - dicPos)
{ {
outSizeCur = p->decoder.dicBufSize; outSizeCur = p->decoder.dicBufSize;
curFinishMode = LZMA_FINISH_ANY; curFinishMode = LZMA_FINISH_ANY;
} }
else else
{ {
outSizeCur = dicPos + outSize; outSizeCur = dicPos + outSize;
curFinishMode = finishMode; curFinishMode = finishMode;
} }
res = Lzma2Dec_DecodeToDic(p, outSizeCur, src, &srcSizeCur, curFinishMode, status); res = Lzma2Dec_DecodeToDic(p, outSizeCur, src, &srcSizeCur, curFinishMode, status);
src += srcSizeCur; src += srcSizeCur;
inSize -= srcSizeCur; inSize -= srcSizeCur;
*srcLen += srcSizeCur; *srcLen += srcSizeCur;
outSizeCur = p->decoder.dicPos - dicPos; outSizeCur = p->decoder.dicPos - dicPos;
memcpy(dest, p->decoder.dic + dicPos, outSizeCur); memcpy(dest, p->decoder.dic + dicPos, outSizeCur);
dest += outSizeCur; dest += outSizeCur;
outSize -= outSizeCur; outSize -= outSizeCur;
*destLen += outSizeCur; *destLen += outSizeCur;
if (res != 0) if (res != 0)
return res; return res;
if (outSizeCur == 0 || outSize == 0) if (outSizeCur == 0 || outSize == 0)
return SZ_OK; return SZ_OK;
} }
} }
SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc) Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc)
{ {
CLzma2Dec decoder; CLzma2Dec decoder;
SRes res; SRes res;
SizeT outSize = *destLen, inSize = *srcLen; SizeT outSize = *destLen, inSize = *srcLen;
Byte props[LZMA_PROPS_SIZE]; Byte props[LZMA_PROPS_SIZE];
Lzma2Dec_Construct(&decoder); Lzma2Dec_Construct(&decoder);
*destLen = *srcLen = 0; *destLen = *srcLen = 0;
*status = LZMA_STATUS_NOT_SPECIFIED; *status = LZMA_STATUS_NOT_SPECIFIED;
decoder.decoder.dic = dest; decoder.decoder.dic = dest;
decoder.decoder.dicBufSize = outSize; decoder.decoder.dicBufSize = outSize;
RINOK(Lzma2Dec_GetOldProps(prop, props)); RINOK(Lzma2Dec_GetOldProps(prop, props));
RINOK(LzmaDec_AllocateProbs(&decoder.decoder, props, LZMA_PROPS_SIZE, alloc)); RINOK(LzmaDec_AllocateProbs(&decoder.decoder, props, LZMA_PROPS_SIZE, alloc));
*srcLen = inSize; *srcLen = inSize;
res = Lzma2Dec_DecodeToDic(&decoder, outSize, src, srcLen, finishMode, status); res = Lzma2Dec_DecodeToDic(&decoder, outSize, src, srcLen, finishMode, status);
*destLen = decoder.decoder.dicPos; *destLen = decoder.decoder.dicPos;
if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT) if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
res = SZ_ERROR_INPUT_EOF; res = SZ_ERROR_INPUT_EOF;
LzmaDec_FreeProbs(&decoder.decoder, alloc); LzmaDec_FreeProbs(&decoder.decoder, alloc);
return res; return res;
} }

View File

@ -1,84 +1,84 @@
/* Lzma2Dec.h -- LZMA2 Decoder /* Lzma2Dec.h -- LZMA2 Decoder
2009-05-03 : Igor Pavlov : Public domain */ 2009-05-03 : Igor Pavlov : Public domain */
#ifndef __LZMA2_DEC_H #ifndef __LZMA2_DEC_H
#define __LZMA2_DEC_H #define __LZMA2_DEC_H
#include "LzmaDec.h" #include "LzmaDec.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/* ---------- State Interface ---------- */ /* ---------- State Interface ---------- */
typedef struct typedef struct
{ {
CLzmaDec decoder; CLzmaDec decoder;
UInt32 packSize; UInt32 packSize;
UInt32 unpackSize; UInt32 unpackSize;
int state; int state;
Byte control; Byte control;
Bool needInitDic; Bool needInitDic;
Bool needInitState; Bool needInitState;
Bool needInitProp; Bool needInitProp;
} CLzma2Dec; } CLzma2Dec;
#define Lzma2Dec_Construct(p) LzmaDec_Construct(&(p)->decoder) #define Lzma2Dec_Construct(p) LzmaDec_Construct(&(p)->decoder)
#define Lzma2Dec_FreeProbs(p, alloc) LzmaDec_FreeProbs(&(p)->decoder, alloc); #define Lzma2Dec_FreeProbs(p, alloc) LzmaDec_FreeProbs(&(p)->decoder, alloc);
#define Lzma2Dec_Free(p, alloc) LzmaDec_Free(&(p)->decoder, alloc); #define Lzma2Dec_Free(p, alloc) LzmaDec_Free(&(p)->decoder, alloc);
SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAlloc *alloc); SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAlloc *alloc);
SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc); SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc);
void Lzma2Dec_Init(CLzma2Dec *p); void Lzma2Dec_Init(CLzma2Dec *p);
/* /*
finishMode: finishMode:
It has meaning only if the decoding reaches output limit (*destLen or dicLimit). It has meaning only if the decoding reaches output limit (*destLen or dicLimit).
LZMA_FINISH_ANY - use smallest number of input bytes LZMA_FINISH_ANY - use smallest number of input bytes
LZMA_FINISH_END - read EndOfStream marker after decoding LZMA_FINISH_END - read EndOfStream marker after decoding
Returns: Returns:
SZ_OK SZ_OK
status: status:
LZMA_STATUS_FINISHED_WITH_MARK LZMA_STATUS_FINISHED_WITH_MARK
LZMA_STATUS_NOT_FINISHED LZMA_STATUS_NOT_FINISHED
LZMA_STATUS_NEEDS_MORE_INPUT LZMA_STATUS_NEEDS_MORE_INPUT
SZ_ERROR_DATA - Data error SZ_ERROR_DATA - Data error
*/ */
SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit, SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen,
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
/* ---------- One Call Interface ---------- */ /* ---------- One Call Interface ---------- */
/* /*
finishMode: finishMode:
It has meaning only if the decoding reaches output limit (*destLen). It has meaning only if the decoding reaches output limit (*destLen).
LZMA_FINISH_ANY - use smallest number of input bytes LZMA_FINISH_ANY - use smallest number of input bytes
LZMA_FINISH_END - read EndOfStream marker after decoding LZMA_FINISH_END - read EndOfStream marker after decoding
Returns: Returns:
SZ_OK SZ_OK
status: status:
LZMA_STATUS_FINISHED_WITH_MARK LZMA_STATUS_FINISHED_WITH_MARK
LZMA_STATUS_NOT_FINISHED LZMA_STATUS_NOT_FINISHED
SZ_ERROR_DATA - Data error SZ_ERROR_DATA - Data error
SZ_ERROR_MEM - Memory allocation error SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_UNSUPPORTED - Unsupported properties SZ_ERROR_UNSUPPORTED - Unsupported properties
SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
*/ */
SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc); Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -1,231 +1,231 @@
/* LzmaDec.h -- LZMA Decoder /* LzmaDec.h -- LZMA Decoder
2009-02-07 : Igor Pavlov : Public domain */ 2009-02-07 : Igor Pavlov : Public domain */
#ifndef __LZMA_DEC_H #ifndef __LZMA_DEC_H
#define __LZMA_DEC_H #define __LZMA_DEC_H
#include "Types.h" #include "Types.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/* #define _LZMA_PROB32 */ /* #define _LZMA_PROB32 */
/* _LZMA_PROB32 can increase the speed on some CPUs, /* _LZMA_PROB32 can increase the speed on some CPUs,
but memory usage for CLzmaDec::probs will be doubled in that case */ but memory usage for CLzmaDec::probs will be doubled in that case */
#ifdef _LZMA_PROB32 #ifdef _LZMA_PROB32
#define CLzmaProb UInt32 #define CLzmaProb UInt32
#else #else
#define CLzmaProb UInt16 #define CLzmaProb UInt16
#endif #endif
/* ---------- LZMA Properties ---------- */ /* ---------- LZMA Properties ---------- */
#define LZMA_PROPS_SIZE 5 #define LZMA_PROPS_SIZE 5
typedef struct _CLzmaProps typedef struct _CLzmaProps
{ {
unsigned lc, lp, pb; unsigned lc, lp, pb;
UInt32 dicSize; UInt32 dicSize;
} CLzmaProps; } CLzmaProps;
/* LzmaProps_Decode - decodes properties /* LzmaProps_Decode - decodes properties
Returns: Returns:
SZ_OK SZ_OK
SZ_ERROR_UNSUPPORTED - Unsupported properties SZ_ERROR_UNSUPPORTED - Unsupported properties
*/ */
SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size); SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size);
/* ---------- LZMA Decoder state ---------- */ /* ---------- LZMA Decoder state ---------- */
/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case. /* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case.
Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */ Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */
#define LZMA_REQUIRED_INPUT_MAX 20 #define LZMA_REQUIRED_INPUT_MAX 20
typedef struct typedef struct
{ {
CLzmaProps prop; CLzmaProps prop;
CLzmaProb *probs; CLzmaProb *probs;
Byte *dic; Byte *dic;
const Byte *buf; const Byte *buf;
UInt32 range, code; UInt32 range, code;
SizeT dicPos; SizeT dicPos;
SizeT dicBufSize; SizeT dicBufSize;
UInt32 processedPos; UInt32 processedPos;
UInt32 checkDicSize; UInt32 checkDicSize;
unsigned state; unsigned state;
UInt32 reps[4]; UInt32 reps[4];
unsigned remainLen; unsigned remainLen;
int needFlush; int needFlush;
int needInitState; int needInitState;
UInt32 numProbs; UInt32 numProbs;
unsigned tempBufSize; unsigned tempBufSize;
Byte tempBuf[LZMA_REQUIRED_INPUT_MAX]; Byte tempBuf[LZMA_REQUIRED_INPUT_MAX];
} CLzmaDec; } CLzmaDec;
#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; } #define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; }
void LzmaDec_Init(CLzmaDec *p); void LzmaDec_Init(CLzmaDec *p);
/* There are two types of LZMA streams: /* There are two types of LZMA streams:
0) Stream with end mark. That end mark adds about 6 bytes to compressed size. 0) Stream with end mark. That end mark adds about 6 bytes to compressed size.
1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */ 1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */
typedef enum typedef enum
{ {
LZMA_FINISH_ANY, /* finish at any point */ LZMA_FINISH_ANY, /* finish at any point */
LZMA_FINISH_END /* block must be finished at the end */ LZMA_FINISH_END /* block must be finished at the end */
} ELzmaFinishMode; } ELzmaFinishMode;
/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!! /* ELzmaFinishMode has meaning only if the decoding reaches output limit !!!
You must use LZMA_FINISH_END, when you know that current output buffer You must use LZMA_FINISH_END, when you know that current output buffer
covers last bytes of block. In other cases you must use LZMA_FINISH_ANY. covers last bytes of block. In other cases you must use LZMA_FINISH_ANY.
If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK, If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK,
and output value of destLen will be less than output buffer size limit. and output value of destLen will be less than output buffer size limit.
You can check status result also. You can check status result also.
You can use multiple checks to test data integrity after full decompression: You can use multiple checks to test data integrity after full decompression:
1) Check Result and "status" variable. 1) Check Result and "status" variable.
2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize. 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize.
3) Check that output(srcLen) = compressedSize, if you know real compressedSize. 3) Check that output(srcLen) = compressedSize, if you know real compressedSize.
You must use correct finish mode in that case. */ You must use correct finish mode in that case. */
typedef enum typedef enum
{ {
LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */ LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */
LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */ LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */
LZMA_STATUS_NOT_FINISHED, /* stream was not finished */ LZMA_STATUS_NOT_FINISHED, /* stream was not finished */
LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */ LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */ LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */
} ELzmaStatus; } ELzmaStatus;
/* ELzmaStatus is used only as output value for function call */ /* ELzmaStatus is used only as output value for function call */
/* ---------- Interfaces ---------- */ /* ---------- Interfaces ---------- */
/* There are 3 levels of interfaces: /* There are 3 levels of interfaces:
1) Dictionary Interface 1) Dictionary Interface
2) Buffer Interface 2) Buffer Interface
3) One Call Interface 3) One Call Interface
You can select any of these interfaces, but don't mix functions from different You can select any of these interfaces, but don't mix functions from different
groups for same object. */ groups for same object. */
/* There are two variants to allocate state for Dictionary Interface: /* There are two variants to allocate state for Dictionary Interface:
1) LzmaDec_Allocate / LzmaDec_Free 1) LzmaDec_Allocate / LzmaDec_Free
2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs 2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs
You can use variant 2, if you set dictionary buffer manually. You can use variant 2, if you set dictionary buffer manually.
For Buffer Interface you must always use variant 1. For Buffer Interface you must always use variant 1.
LzmaDec_Allocate* can return: LzmaDec_Allocate* can return:
SZ_OK SZ_OK
SZ_ERROR_MEM - Memory allocation error SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_UNSUPPORTED - Unsupported properties SZ_ERROR_UNSUPPORTED - Unsupported properties
*/ */
SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc); SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc);
void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc); void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc);
SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc); SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc);
void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc); void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc);
/* ---------- Dictionary Interface ---------- */ /* ---------- Dictionary Interface ---------- */
/* You can use it, if you want to eliminate the overhead for data copying from /* You can use it, if you want to eliminate the overhead for data copying from
dictionary to some other external buffer. dictionary to some other external buffer.
You must work with CLzmaDec variables directly in this interface. You must work with CLzmaDec variables directly in this interface.
STEPS: STEPS:
LzmaDec_Constr() LzmaDec_Constr()
LzmaDec_Allocate() LzmaDec_Allocate()
for (each new stream) for (each new stream)
{ {
LzmaDec_Init() LzmaDec_Init()
while (it needs more decompression) while (it needs more decompression)
{ {
LzmaDec_DecodeToDic() LzmaDec_DecodeToDic()
use data from CLzmaDec::dic and update CLzmaDec::dicPos use data from CLzmaDec::dic and update CLzmaDec::dicPos
} }
} }
LzmaDec_Free() LzmaDec_Free()
*/ */
/* LzmaDec_DecodeToDic /* LzmaDec_DecodeToDic
The decoding to internal dictionary buffer (CLzmaDec::dic). The decoding to internal dictionary buffer (CLzmaDec::dic).
You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!! You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!!
finishMode: finishMode:
It has meaning only if the decoding reaches output limit (dicLimit). It has meaning only if the decoding reaches output limit (dicLimit).
LZMA_FINISH_ANY - Decode just dicLimit bytes. LZMA_FINISH_ANY - Decode just dicLimit bytes.
LZMA_FINISH_END - Stream must be finished after dicLimit. LZMA_FINISH_END - Stream must be finished after dicLimit.
Returns: Returns:
SZ_OK SZ_OK
status: status:
LZMA_STATUS_FINISHED_WITH_MARK LZMA_STATUS_FINISHED_WITH_MARK
LZMA_STATUS_NOT_FINISHED LZMA_STATUS_NOT_FINISHED
LZMA_STATUS_NEEDS_MORE_INPUT LZMA_STATUS_NEEDS_MORE_INPUT
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
SZ_ERROR_DATA - Data error SZ_ERROR_DATA - Data error
*/ */
SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit,
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
/* ---------- Buffer Interface ---------- */ /* ---------- Buffer Interface ---------- */
/* It's zlib-like interface. /* It's zlib-like interface.
See LzmaDec_DecodeToDic description for information about STEPS and return results, See LzmaDec_DecodeToDic description for information about STEPS and return results,
but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need
to work with CLzmaDec variables manually. to work with CLzmaDec variables manually.
finishMode: finishMode:
It has meaning only if the decoding reaches output limit (*destLen). It has meaning only if the decoding reaches output limit (*destLen).
LZMA_FINISH_ANY - Decode just destLen bytes. LZMA_FINISH_ANY - Decode just destLen bytes.
LZMA_FINISH_END - Stream must be finished after (*destLen). LZMA_FINISH_END - Stream must be finished after (*destLen).
*/ */
SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen,
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
/* ---------- One Call Interface ---------- */ /* ---------- One Call Interface ---------- */
/* LzmaDecode /* LzmaDecode
finishMode: finishMode:
It has meaning only if the decoding reaches output limit (*destLen). It has meaning only if the decoding reaches output limit (*destLen).
LZMA_FINISH_ANY - Decode just destLen bytes. LZMA_FINISH_ANY - Decode just destLen bytes.
LZMA_FINISH_END - Stream must be finished after (*destLen). LZMA_FINISH_END - Stream must be finished after (*destLen).
Returns: Returns:
SZ_OK SZ_OK
status: status:
LZMA_STATUS_FINISHED_WITH_MARK LZMA_STATUS_FINISHED_WITH_MARK
LZMA_STATUS_NOT_FINISHED LZMA_STATUS_NOT_FINISHED
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
SZ_ERROR_DATA - Data error SZ_ERROR_DATA - Data error
SZ_ERROR_MEM - Memory allocation error SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_UNSUPPORTED - Unsupported properties SZ_ERROR_UNSUPPORTED - Unsupported properties
SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
*/ */
SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
ELzmaStatus *status, ISzAlloc *alloc); ELzmaStatus *status, ISzAlloc *alloc);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif #endif

View File

@ -1,254 +1,254 @@
/* Types.h -- Basic types /* Types.h -- Basic types
2010-10-09 : Igor Pavlov : Public domain */ 2010-10-09 : Igor Pavlov : Public domain */
#ifndef __7Z_TYPES_H #ifndef __7Z_TYPES_H
#define __7Z_TYPES_H #define __7Z_TYPES_H
#include <stddef.h> #include <stddef.h>
#ifdef _WIN32 #ifdef _WIN32
#include <windows.h> #include <windows.h>
#endif #endif
#ifndef EXTERN_C_BEGIN #ifndef EXTERN_C_BEGIN
#ifdef __cplusplus #ifdef __cplusplus
#define EXTERN_C_BEGIN extern "C" { #define EXTERN_C_BEGIN extern "C" {
#define EXTERN_C_END } #define EXTERN_C_END }
#else #else
#define EXTERN_C_BEGIN #define EXTERN_C_BEGIN
#define EXTERN_C_END #define EXTERN_C_END
#endif #endif
#endif #endif
EXTERN_C_BEGIN EXTERN_C_BEGIN
#define SZ_OK 0 #define SZ_OK 0
#define SZ_ERROR_DATA 1 #define SZ_ERROR_DATA 1
#define SZ_ERROR_MEM 2 #define SZ_ERROR_MEM 2
#define SZ_ERROR_CRC 3 #define SZ_ERROR_CRC 3
#define SZ_ERROR_UNSUPPORTED 4 #define SZ_ERROR_UNSUPPORTED 4
#define SZ_ERROR_PARAM 5 #define SZ_ERROR_PARAM 5
#define SZ_ERROR_INPUT_EOF 6 #define SZ_ERROR_INPUT_EOF 6
#define SZ_ERROR_OUTPUT_EOF 7 #define SZ_ERROR_OUTPUT_EOF 7
#define SZ_ERROR_READ 8 #define SZ_ERROR_READ 8
#define SZ_ERROR_WRITE 9 #define SZ_ERROR_WRITE 9
#define SZ_ERROR_PROGRESS 10 #define SZ_ERROR_PROGRESS 10
#define SZ_ERROR_FAIL 11 #define SZ_ERROR_FAIL 11
#define SZ_ERROR_THREAD 12 #define SZ_ERROR_THREAD 12
#define SZ_ERROR_ARCHIVE 16 #define SZ_ERROR_ARCHIVE 16
#define SZ_ERROR_NO_ARCHIVE 17 #define SZ_ERROR_NO_ARCHIVE 17
typedef int SRes; typedef int SRes;
#ifdef _WIN32 #ifdef _WIN32
typedef DWORD WRes; typedef DWORD WRes;
#else #else
typedef int WRes; typedef int WRes;
#endif #endif
#ifndef RINOK #ifndef RINOK
#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; } #define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; }
#endif #endif
typedef unsigned char Byte; typedef unsigned char Byte;
typedef short Int16; typedef short Int16;
typedef unsigned short UInt16; typedef unsigned short UInt16;
#ifdef _LZMA_UINT32_IS_ULONG #ifdef _LZMA_UINT32_IS_ULONG
typedef long Int32; typedef long Int32;
typedef unsigned long UInt32; typedef unsigned long UInt32;
#else #else
typedef int Int32; typedef int Int32;
typedef unsigned int UInt32; typedef unsigned int UInt32;
#endif #endif
#ifdef _SZ_NO_INT_64 #ifdef _SZ_NO_INT_64
/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers. /* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers.
NOTES: Some code will work incorrectly in that case! */ NOTES: Some code will work incorrectly in that case! */
typedef long Int64; typedef long Int64;
typedef unsigned long UInt64; typedef unsigned long UInt64;
#else #else
#if defined(_MSC_VER) || defined(__BORLANDC__) #if defined(_MSC_VER) || defined(__BORLANDC__)
typedef __int64 Int64; typedef __int64 Int64;
typedef unsigned __int64 UInt64; typedef unsigned __int64 UInt64;
#define UINT64_CONST(n) n #define UINT64_CONST(n) n
#else #else
typedef long long int Int64; typedef long long int Int64;
typedef unsigned long long int UInt64; typedef unsigned long long int UInt64;
#define UINT64_CONST(n) n ## ULL #define UINT64_CONST(n) n ## ULL
#endif #endif
#endif #endif
#ifdef _LZMA_NO_SYSTEM_SIZE_T #ifdef _LZMA_NO_SYSTEM_SIZE_T
typedef UInt32 SizeT; typedef UInt32 SizeT;
#else #else
typedef size_t SizeT; typedef size_t SizeT;
#endif #endif
typedef int Bool; typedef int Bool;
#define True 1 #define True 1
#define False 0 #define False 0
#ifdef _WIN32 #ifdef _WIN32
#define MY_STD_CALL __stdcall #define MY_STD_CALL __stdcall
#else #else
#define MY_STD_CALL #define MY_STD_CALL
#endif #endif
#ifdef _MSC_VER #ifdef _MSC_VER
#if _MSC_VER >= 1300 #if _MSC_VER >= 1300
#define MY_NO_INLINE __declspec(noinline) #define MY_NO_INLINE __declspec(noinline)
#else #else
#define MY_NO_INLINE #define MY_NO_INLINE
#endif #endif
#define MY_CDECL __cdecl #define MY_CDECL __cdecl
#define MY_FAST_CALL __fastcall #define MY_FAST_CALL __fastcall
#else #else
#define MY_CDECL #define MY_CDECL
#define MY_FAST_CALL #define MY_FAST_CALL
#endif #endif
/* The following interfaces use first parameter as pointer to structure */ /* The following interfaces use first parameter as pointer to structure */
typedef struct typedef struct
{ {
Byte (*Read)(void *p); /* reads one byte, returns 0 in case of EOF or error */ Byte (*Read)(void *p); /* reads one byte, returns 0 in case of EOF or error */
} IByteIn; } IByteIn;
typedef struct typedef struct
{ {
void (*Write)(void *p, Byte b); void (*Write)(void *p, Byte b);
} IByteOut; } IByteOut;
typedef struct typedef struct
{ {
SRes (*Read)(void *p, void *buf, size_t *size); SRes (*Read)(void *p, void *buf, size_t *size);
/* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
(output(*size) < input(*size)) is allowed */ (output(*size) < input(*size)) is allowed */
} ISeqInStream; } ISeqInStream;
/* it can return SZ_ERROR_INPUT_EOF */ /* it can return SZ_ERROR_INPUT_EOF */
SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size); SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size);
SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType); SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType);
SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf); SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf);
typedef struct typedef struct
{ {
size_t (*Write)(void *p, const void *buf, size_t size); size_t (*Write)(void *p, const void *buf, size_t size);
/* Returns: result - the number of actually written bytes. /* Returns: result - the number of actually written bytes.
(result < size) means error */ (result < size) means error */
} ISeqOutStream; } ISeqOutStream;
typedef enum typedef enum
{ {
SZ_SEEK_SET = 0, SZ_SEEK_SET = 0,
SZ_SEEK_CUR = 1, SZ_SEEK_CUR = 1,
SZ_SEEK_END = 2 SZ_SEEK_END = 2
} ESzSeek; } ESzSeek;
typedef struct typedef struct
{ {
SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */ SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */
SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);
} ISeekInStream; } ISeekInStream;
typedef struct typedef struct
{ {
SRes (*Look)(void *p, const void **buf, size_t *size); SRes (*Look)(void *p, const void **buf, size_t *size);
/* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
(output(*size) > input(*size)) is not allowed (output(*size) > input(*size)) is not allowed
(output(*size) < input(*size)) is allowed */ (output(*size) < input(*size)) is allowed */
SRes (*Skip)(void *p, size_t offset); SRes (*Skip)(void *p, size_t offset);
/* offset must be <= output(*size) of Look */ /* offset must be <= output(*size) of Look */
SRes (*Read)(void *p, void *buf, size_t *size); SRes (*Read)(void *p, void *buf, size_t *size);
/* reads directly (without buffer). It's same as ISeqInStream::Read */ /* reads directly (without buffer). It's same as ISeqInStream::Read */
SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);
} ILookInStream; } ILookInStream;
SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size); SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size);
SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset); SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset);
/* reads via ILookInStream::Read */ /* reads via ILookInStream::Read */
SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType); SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType);
SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size); SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size);
#define LookToRead_BUF_SIZE (1 << 14) #define LookToRead_BUF_SIZE (1 << 14)
typedef struct typedef struct
{ {
ILookInStream s; ILookInStream s;
ISeekInStream *realStream; ISeekInStream *realStream;
size_t pos; size_t pos;
size_t size; size_t size;
Byte buf[LookToRead_BUF_SIZE]; Byte buf[LookToRead_BUF_SIZE];
} CLookToRead; } CLookToRead;
void LookToRead_CreateVTable(CLookToRead *p, int lookahead); void LookToRead_CreateVTable(CLookToRead *p, int lookahead);
void LookToRead_Init(CLookToRead *p); void LookToRead_Init(CLookToRead *p);
typedef struct typedef struct
{ {
ISeqInStream s; ISeqInStream s;
ILookInStream *realStream; ILookInStream *realStream;
} CSecToLook; } CSecToLook;
void SecToLook_CreateVTable(CSecToLook *p); void SecToLook_CreateVTable(CSecToLook *p);
typedef struct typedef struct
{ {
ISeqInStream s; ISeqInStream s;
ILookInStream *realStream; ILookInStream *realStream;
} CSecToRead; } CSecToRead;
void SecToRead_CreateVTable(CSecToRead *p); void SecToRead_CreateVTable(CSecToRead *p);
typedef struct typedef struct
{ {
SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize); SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize);
/* Returns: result. (result != SZ_OK) means break. /* Returns: result. (result != SZ_OK) means break.
Value (UInt64)(Int64)-1 for size means unknown value. */ Value (UInt64)(Int64)-1 for size means unknown value. */
} ICompressProgress; } ICompressProgress;
typedef struct typedef struct
{ {
void *(*Alloc)(void *p, size_t size); void *(*Alloc)(void *p, size_t size);
void (*Free)(void *p, void *address); /* address can be 0 */ void (*Free)(void *p, void *address); /* address can be 0 */
} ISzAlloc; } ISzAlloc;
#define IAlloc_Alloc(p, size) (p)->Alloc((p), size) #define IAlloc_Alloc(p, size) (p)->Alloc((p), size)
#define IAlloc_Free(p, a) (p)->Free((p), a) #define IAlloc_Free(p, a) (p)->Free((p), a)
#ifdef _WIN32 #ifdef _WIN32
#define CHAR_PATH_SEPARATOR '\\' #define CHAR_PATH_SEPARATOR '\\'
#define WCHAR_PATH_SEPARATOR L'\\' #define WCHAR_PATH_SEPARATOR L'\\'
#define STRING_PATH_SEPARATOR "\\" #define STRING_PATH_SEPARATOR "\\"
#define WSTRING_PATH_SEPARATOR L"\\" #define WSTRING_PATH_SEPARATOR L"\\"
#else #else
#define CHAR_PATH_SEPARATOR '/' #define CHAR_PATH_SEPARATOR '/'
#define WCHAR_PATH_SEPARATOR L'/' #define WCHAR_PATH_SEPARATOR L'/'
#define STRING_PATH_SEPARATOR "/" #define STRING_PATH_SEPARATOR "/"
#define WSTRING_PATH_SEPARATOR L"/" #define WSTRING_PATH_SEPARATOR L"/"
#endif #endif
EXTERN_C_END EXTERN_C_END
#endif #endif

View File

@ -1,26 +1,26 @@
// Presents a single file as an "archive" of just that file. // Presents a single file as an "archive" of just that file.
// File_Extractor 1.0.0 // File_Extractor 1.0.0
#ifndef BINARY_EXTRACTOR_H #ifndef BINARY_EXTRACTOR_H
#define BINARY_EXTRACTOR_H #define BINARY_EXTRACTOR_H
#include "File_Extractor.h" #include "File_Extractor.h"
class Binary_Extractor : public File_Extractor { class Binary_Extractor : public File_Extractor {
public: public:
Binary_Extractor(); Binary_Extractor();
virtual ~Binary_Extractor(); virtual ~Binary_Extractor();
protected: protected:
virtual blargg_err_t open_path_v(); virtual blargg_err_t open_path_v();
virtual blargg_err_t open_v(); virtual blargg_err_t open_v();
virtual void close_v(); virtual void close_v();
virtual blargg_err_t next_v(); virtual blargg_err_t next_v();
virtual blargg_err_t rewind_v(); virtual blargg_err_t rewind_v();
virtual blargg_err_t stat_v(); virtual blargg_err_t stat_v();
virtual blargg_err_t extract_v( void*, int ); virtual blargg_err_t extract_v( void*, int );
}; };
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -1,264 +1,264 @@
// Lightweight interface for reading data from byte stream // Lightweight interface for reading data from byte stream
// File_Extractor 1.0.0 // File_Extractor 1.0.0
#ifndef DATA_READER_H #ifndef DATA_READER_H
#define DATA_READER_H #define DATA_READER_H
#include "blargg_common.h" #include "blargg_common.h"
/* Some functions accept a long instead of int for convenience where caller has /* Some functions accept a long instead of int for convenience where caller has
a long due to some other interface, and would otherwise have to get a warning, a long due to some other interface, and would otherwise have to get a warning,
or cast it (and verify that it wasn't outside the range of an int). or cast it (and verify that it wasn't outside the range of an int).
To really support huge (>2GB) files, long isn't a solution, since there's no To really support huge (>2GB) files, long isn't a solution, since there's no
guarantee it's more than 32 bits. We'd need to use long long (if available), or guarantee it's more than 32 bits. We'd need to use long long (if available), or
something compiler-specific, and change all places file sizes or offsets are something compiler-specific, and change all places file sizes or offsets are
used. */ used. */
// Supports reading and finding out how many bytes are remaining // Supports reading and finding out how many bytes are remaining
class Data_Reader { class Data_Reader {
public: public:
// Reads min(*n,remain()) bytes and sets *n to this number, thus trying to read more // Reads min(*n,remain()) bytes and sets *n to this number, thus trying to read more
// tham remain() bytes doesn't result in error, just *n being set to remain(). // tham remain() bytes doesn't result in error, just *n being set to remain().
blargg_err_t read_avail( void* p, int* n ); blargg_err_t read_avail( void* p, int* n );
blargg_err_t read_avail( void* p, long* n ); blargg_err_t read_avail( void* p, long* n );
// Reads exactly n bytes, or returns error if they couldn't ALL be read. // Reads exactly n bytes, or returns error if they couldn't ALL be read.
// Reading past end of file results in blargg_err_file_eof. // Reading past end of file results in blargg_err_file_eof.
blargg_err_t read( void* p, int n ); blargg_err_t read( void* p, int n );
// Number of bytes remaining until end of file // Number of bytes remaining until end of file
int remain() const { return remain_; } int remain() const { return remain_; }
// Reads and discards n bytes. Skipping past end of file results in blargg_err_file_eof. // Reads and discards n bytes. Skipping past end of file results in blargg_err_file_eof.
blargg_err_t skip( int n ); blargg_err_t skip( int n );
virtual ~Data_Reader() { } virtual ~Data_Reader() { }
private: private:
// noncopyable // noncopyable
Data_Reader( const Data_Reader& ); Data_Reader( const Data_Reader& );
Data_Reader& operator = ( const Data_Reader& ); Data_Reader& operator = ( const Data_Reader& );
// Derived interface // Derived interface
protected: protected:
Data_Reader() : remain_( 0 ) { } Data_Reader() : remain_( 0 ) { }
// Sets remain // Sets remain
void set_remain( int n ) { assert( n >= 0 ); remain_ = n; } void set_remain( int n ) { assert( n >= 0 ); remain_ = n; }
// Do same as read(). Guaranteed that 0 < n <= remain(). Value of remain() is updated // Do same as read(). Guaranteed that 0 < n <= remain(). Value of remain() is updated
// AFTER this call succeeds, not before. set_remain() should NOT be called from this. // AFTER this call succeeds, not before. set_remain() should NOT be called from this.
virtual blargg_err_t read_v( void*, int n ) BLARGG_PURE( { (void)n; return blargg_ok; } ) virtual blargg_err_t read_v( void*, int n ) BLARGG_PURE( { (void)n; return blargg_ok; } )
// Do same as skip(). Guaranteed that 0 < n <= remain(). Default just reads data // Do same as skip(). Guaranteed that 0 < n <= remain(). Default just reads data
// and discards it. Value of remain() is updated AFTER this call succeeds, not // and discards it. Value of remain() is updated AFTER this call succeeds, not
// before. set_remain() should NOT be called from this. // before. set_remain() should NOT be called from this.
virtual blargg_err_t skip_v( int n ); virtual blargg_err_t skip_v( int n );
// Implementation // Implementation
public: public:
BLARGG_DISABLE_NOTHROW BLARGG_DISABLE_NOTHROW
private: private:
int remain_; int remain_;
}; };
// Supports seeking in addition to Data_Reader operations // Supports seeking in addition to Data_Reader operations
class File_Reader : public Data_Reader { class File_Reader : public Data_Reader {
public: public:
// Size of file // Size of file
int size() const { return size_; } int size() const { return size_; }
// Current position in file // Current position in file
int tell() const { return size_ - remain(); } int tell() const { return size_ - remain(); }
// Goes to new position // Goes to new position
blargg_err_t seek( int ); blargg_err_t seek( int );
// Derived interface // Derived interface
protected: protected:
// Sets size and resets position // Sets size and resets position
void set_size( int n ) { size_ = n; Data_Reader::set_remain( n ); } void set_size( int n ) { size_ = n; Data_Reader::set_remain( n ); }
void set_size( long n ) { set_size( STATIC_CAST(int, n) ); } void set_size( long n ) { set_size( STATIC_CAST(int, n) ); }
// Sets reported position // Sets reported position
void set_tell( int i ) { assert( 0 <= i && i <= size_ ); Data_Reader::set_remain( size_ - i ); } void set_tell( int i ) { assert( 0 <= i && i <= size_ ); Data_Reader::set_remain( size_ - i ); }
// Do same as seek(). Guaranteed that 0 <= n <= size(). Value of tell() is updated // Do same as seek(). Guaranteed that 0 <= n <= size(). Value of tell() is updated
// AFTER this call succeeds, not before. set_* functions should NOT be called from this. // AFTER this call succeeds, not before. set_* functions should NOT be called from this.
virtual blargg_err_t seek_v( int n ) BLARGG_PURE( { (void)n; return blargg_ok; } ) virtual blargg_err_t seek_v( int n ) BLARGG_PURE( { (void)n; return blargg_ok; } )
// Implementation // Implementation
protected: protected:
File_Reader() : size_( 0 ) { } File_Reader() : size_( 0 ) { }
virtual blargg_err_t skip_v( int ); virtual blargg_err_t skip_v( int );
private: private:
int size_; int size_;
void set_remain(); // avoid accidental use of set_remain void set_remain(); // avoid accidental use of set_remain
}; };
// Reads from file on disk // Reads from file on disk
class Std_File_Reader : public File_Reader { class Std_File_Reader : public File_Reader {
public: public:
// Opens file // Opens file
blargg_err_t open( const char path [] ); blargg_err_t open( const char path [] );
// Closes file if one was open // Closes file if one was open
void close(); void close();
// Switches to unbuffered mode. Useful if buffering is already being // Switches to unbuffered mode. Useful if buffering is already being
// done at a higher level. // done at a higher level.
void make_unbuffered(); void make_unbuffered();
// Implementation // Implementation
public: public:
Std_File_Reader(); Std_File_Reader();
virtual ~Std_File_Reader(); virtual ~Std_File_Reader();
protected: protected:
virtual blargg_err_t read_v( void*, int ); virtual blargg_err_t read_v( void*, int );
virtual blargg_err_t seek_v( int ); virtual blargg_err_t seek_v( int );
private: private:
void* file_; void* file_;
}; };
// Treats range of memory as a file // Treats range of memory as a file
class Mem_File_Reader : public File_Reader { class Mem_File_Reader : public File_Reader {
public: public:
Mem_File_Reader( const void* begin, long size ); Mem_File_Reader( const void* begin, long size );
// Implementation // Implementation
protected: protected:
virtual blargg_err_t read_v( void*, int ); virtual blargg_err_t read_v( void*, int );
virtual blargg_err_t seek_v( int ); virtual blargg_err_t seek_v( int );
private: private:
const char* const begin; const char* const begin;
}; };
// Allows only count bytes to be read from reader passed // Allows only count bytes to be read from reader passed
class Subset_Reader : public Data_Reader { class Subset_Reader : public Data_Reader {
public: public:
Subset_Reader( Data_Reader*, int count ); Subset_Reader( Data_Reader*, int count );
// Implementation // Implementation
protected: protected:
virtual blargg_err_t read_v( void*, int ); virtual blargg_err_t read_v( void*, int );
private: private:
Data_Reader* const in; Data_Reader* const in;
}; };
// Joins already-read header and remaining data into original file. // Joins already-read header and remaining data into original file.
// Meant for cases where you've already read header and don't want // Meant for cases where you've already read header and don't want
// to seek and re-read data (for efficiency). // to seek and re-read data (for efficiency).
class Remaining_Reader : public Data_Reader { class Remaining_Reader : public Data_Reader {
public: public:
Remaining_Reader( void const* header, int header_size, Data_Reader* ); Remaining_Reader( void const* header, int header_size, Data_Reader* );
// Implementation // Implementation
protected: protected:
virtual blargg_err_t read_v( void*, int ); virtual blargg_err_t read_v( void*, int );
private: private:
Data_Reader* const in; Data_Reader* const in;
void const* header; void const* header;
int header_remain; int header_remain;
}; };
// Invokes callback function to read data // Invokes callback function to read data
extern "C" { // necessary to be usable from C extern "C" { // necessary to be usable from C
typedef const char* (*callback_reader_func_t)( typedef const char* (*callback_reader_func_t)(
void* user_data, // Same value passed to constructor void* user_data, // Same value passed to constructor
void* out, // Buffer to place data into void* out, // Buffer to place data into
int count // Number of bytes to read int count // Number of bytes to read
); );
} }
class Callback_Reader : public Data_Reader { class Callback_Reader : public Data_Reader {
public: public:
typedef callback_reader_func_t callback_t; typedef callback_reader_func_t callback_t;
Callback_Reader( callback_t, long size, void* user_data ); Callback_Reader( callback_t, long size, void* user_data );
// Implementation // Implementation
protected: protected:
virtual blargg_err_t read_v( void*, int ); virtual blargg_err_t read_v( void*, int );
private: private:
callback_t const callback; callback_t const callback;
void* const user_data; void* const user_data;
}; };
// Invokes callback function to read data // Invokes callback function to read data
extern "C" { // necessary to be usable from C extern "C" { // necessary to be usable from C
typedef const char* (*callback_file_reader_func_t)( typedef const char* (*callback_file_reader_func_t)(
void* user_data, // Same value passed to constructor void* user_data, // Same value passed to constructor
void* out, // Buffer to place data into void* out, // Buffer to place data into
int count, // Number of bytes to read int count, // Number of bytes to read
int pos // Position in file to read from int pos // Position in file to read from
); );
} }
class Callback_File_Reader : public File_Reader { class Callback_File_Reader : public File_Reader {
public: public:
typedef callback_file_reader_func_t callback_t; typedef callback_file_reader_func_t callback_t;
Callback_File_Reader( callback_t, long size, void* user_data ); Callback_File_Reader( callback_t, long size, void* user_data );
// Implementation // Implementation
protected: protected:
virtual blargg_err_t read_v( void*, int ); virtual blargg_err_t read_v( void*, int );
virtual blargg_err_t seek_v( int ); virtual blargg_err_t seek_v( int );
private: private:
callback_t const callback; callback_t const callback;
void* const user_data; void* const user_data;
}; };
#ifdef HAVE_ZLIB_H #ifdef HAVE_ZLIB_H
// Reads file compressed with gzip (or uncompressed) // Reads file compressed with gzip (or uncompressed)
class Gzip_File_Reader : public File_Reader { class Gzip_File_Reader : public File_Reader {
public: public:
// Opens possibly gzipped file // Opens possibly gzipped file
blargg_err_t open( const char path [] ); blargg_err_t open( const char path [] );
// Closes file if one was open // Closes file if one was open
void close(); void close();
// Implementation // Implementation
public: public:
Gzip_File_Reader(); Gzip_File_Reader();
~Gzip_File_Reader(); ~Gzip_File_Reader();
protected: protected:
virtual blargg_err_t read_v( void*, int ); virtual blargg_err_t read_v( void*, int );
virtual blargg_err_t seek_v( int ); virtual blargg_err_t seek_v( int );
private: private:
// void* so "zlib.h" doesn't have to be included here // void* so "zlib.h" doesn't have to be included here
void* file_; void* file_;
}; };
#endif #endif
char* blargg_to_utf8( const wchar_t* ); char* blargg_to_utf8( const wchar_t* );
wchar_t* blargg_to_wide( const char* ); wchar_t* blargg_to_wide( const char* );
#endif #endif

View File

@ -1,341 +1,341 @@
// File_Extractor 1.0.0. http://www.slack.net/~ant/ // File_Extractor 1.0.0. http://www.slack.net/~ant/
#include "File_Extractor.h" #include "File_Extractor.h"
/* Copyright (C) 2005-2009 Shay Green. This module is free software; you /* Copyright (C) 2005-2009 Shay Green. This module is free software; you
can redistribute it and/or modify it under the terms of the GNU Lesser can redistribute it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software Foundation; either General Public License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version. This version 2.1 of the License, or (at your option) any later version. This
module is distributed in the hope that it will be useful, but WITHOUT ANY module is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details. You should have received a copy of the GNU Lesser General Public details. You should have received a copy of the GNU Lesser General Public
License along with this module; if not, write to the Free Software Foundation, License along with this module; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
#include "blargg_source.h" #include "blargg_source.h"
File_Extractor::fex_t( fex_type_t t ) : File_Extractor::fex_t( fex_type_t t ) :
type_( t ) type_( t )
{ {
own_file_ = NULL; own_file_ = NULL;
close_(); close_();
} }
// Open // Open
blargg_err_t File_Extractor::set_path( const char* path ) blargg_err_t File_Extractor::set_path( const char* path )
{ {
if ( !path ) if ( !path )
path = ""; path = "";
RETURN_ERR( path_.resize( strlen( path ) + 1 ) ); RETURN_ERR( path_.resize( strlen( path ) + 1 ) );
memcpy( path_.begin(), path, path_.size() ); memcpy( path_.begin(), path, path_.size() );
return blargg_ok; return blargg_ok;
} }
blargg_err_t File_Extractor::open( const char path [] ) blargg_err_t File_Extractor::open( const char path [] )
{ {
close(); close();
RETURN_ERR( set_path( path ) ); RETURN_ERR( set_path( path ) );
blargg_err_t err = open_path_v(); blargg_err_t err = open_path_v();
if ( err ) if ( err )
close(); close();
else else
opened_ = true; opened_ = true;
return err; return err;
} }
blargg_err_t File_Extractor::open_path_v() blargg_err_t File_Extractor::open_path_v()
{ {
RETURN_ERR( open_arc_file() ); RETURN_ERR( open_arc_file() );
return open_v(); return open_v();
} }
inline inline
static void make_unbuffered( Std_File_Reader* r ) static void make_unbuffered( Std_File_Reader* r )
{ {
r->make_unbuffered(); r->make_unbuffered();
} }
inline inline
static void make_unbuffered( void* ) static void make_unbuffered( void* )
{ } { }
blargg_err_t File_Extractor::open_arc_file( bool unbuffered ) blargg_err_t File_Extractor::open_arc_file( bool unbuffered )
{ {
if ( reader_ ) if ( reader_ )
return blargg_ok; return blargg_ok;
FEX_FILE_READER* in = BLARGG_NEW FEX_FILE_READER; FEX_FILE_READER* in = BLARGG_NEW FEX_FILE_READER;
CHECK_ALLOC( in ); CHECK_ALLOC( in );
blargg_err_t err = in->open( arc_path() ); blargg_err_t err = in->open( arc_path() );
if ( err ) if ( err )
{ {
delete in; delete in;
} }
else else
{ {
reader_ = in; reader_ = in;
own_file(); own_file();
if ( unbuffered ) if ( unbuffered )
make_unbuffered( in ); make_unbuffered( in );
} }
return err; return err;
} }
blargg_err_t File_Extractor::open( File_Reader* input, const char* path ) blargg_err_t File_Extractor::open( File_Reader* input, const char* path )
{ {
close(); close();
RETURN_ERR( set_path( path ) ); RETURN_ERR( set_path( path ) );
RETURN_ERR( input->seek( 0 ) ); RETURN_ERR( input->seek( 0 ) );
reader_ = input; reader_ = input;
blargg_err_t err = open_v(); blargg_err_t err = open_v();
if ( err ) if ( err )
close(); close();
else else
opened_ = true; opened_ = true;
return err; return err;
} }
// Close // Close
void File_Extractor::close() void File_Extractor::close()
{ {
close_v(); close_v();
close_(); close_();
} }
void File_Extractor::close_() void File_Extractor::close_()
{ {
delete own_file_; delete own_file_;
own_file_ = NULL; own_file_ = NULL;
tell_ = 0; tell_ = 0;
reader_ = NULL; reader_ = NULL;
opened_ = false; opened_ = false;
path_.clear(); path_.clear();
clear_file(); clear_file();
} }
File_Extractor::~fex_t() File_Extractor::~fex_t()
{ {
check( !opened() ); // fails if derived destructor didn't call close() check( !opened() ); // fails if derived destructor didn't call close()
delete own_file_; delete own_file_;
} }
// Scanning // Scanning
void File_Extractor::clear_file() void File_Extractor::clear_file()
{ {
name_ = NULL; name_ = NULL;
wname_ = NULL; wname_ = NULL;
done_ = true; done_ = true;
stat_called = false; stat_called = false;
data_ptr_ = NULL; data_ptr_ = NULL;
set_info( 0 ); set_info( 0 );
own_data_.clear(); own_data_.clear();
clear_file_v(); clear_file_v();
} }
void File_Extractor::set_name( const char new_name [], const wchar_t* new_wname ) void File_Extractor::set_name( const char new_name [], const wchar_t* new_wname )
{ {
name_ = new_name; name_ = new_name;
wname_ = new_wname; wname_ = new_wname;
done_ = false; done_ = false;
} }
void File_Extractor::set_info( int new_size, unsigned date, unsigned crc ) void File_Extractor::set_info( int new_size, unsigned date, unsigned crc )
{ {
size_ = new_size; size_ = new_size;
date_ = (date != 0xFFFFFFFF ? date : 0); date_ = (date != 0xFFFFFFFF ? date : 0);
crc32_ = crc; crc32_ = crc;
set_remain( new_size ); set_remain( new_size );
} }
blargg_err_t File_Extractor::next_() blargg_err_t File_Extractor::next_()
{ {
tell_++; tell_++;
clear_file(); clear_file();
blargg_err_t err = next_v(); blargg_err_t err = next_v();
if ( err ) if ( err )
clear_file(); clear_file();
return err; return err;
} }
blargg_err_t File_Extractor::next() blargg_err_t File_Extractor::next()
{ {
assert( !done() ); assert( !done() );
return next_(); return next_();
} }
blargg_err_t File_Extractor::rewind() blargg_err_t File_Extractor::rewind()
{ {
assert( opened() ); assert( opened() );
tell_ = 0; tell_ = 0;
clear_file(); clear_file();
blargg_err_t err = rewind_v(); blargg_err_t err = rewind_v();
if ( err ) if ( err )
clear_file(); clear_file();
return err; return err;
} }
blargg_err_t File_Extractor::stat() blargg_err_t File_Extractor::stat()
{ {
assert( !done() ); assert( !done() );
if ( !stat_called ) if ( !stat_called )
{ {
RETURN_ERR( stat_v() ); RETURN_ERR( stat_v() );
stat_called = true; stat_called = true;
} }
return blargg_ok; return blargg_ok;
} }
// Tell/seek // Tell/seek
int const pos_offset = 1; int const pos_offset = 1;
fex_pos_t File_Extractor::tell_arc() const fex_pos_t File_Extractor::tell_arc() const
{ {
assert( opened() ); assert( opened() );
fex_pos_t pos = tell_arc_v(); fex_pos_t pos = tell_arc_v();
assert( pos >= 0 ); assert( pos >= 0 );
return pos + pos_offset; return pos + pos_offset;
} }
blargg_err_t File_Extractor::seek_arc( fex_pos_t pos ) blargg_err_t File_Extractor::seek_arc( fex_pos_t pos )
{ {
assert( opened() ); assert( opened() );
assert( pos != 0 ); assert( pos != 0 );
clear_file(); clear_file();
blargg_err_t err = seek_arc_v( pos - pos_offset ); blargg_err_t err = seek_arc_v( pos - pos_offset );
if ( err ) if ( err )
clear_file(); clear_file();
return err; return err;
} }
fex_pos_t File_Extractor::tell_arc_v() const fex_pos_t File_Extractor::tell_arc_v() const
{ {
return tell_; return tell_;
} }
blargg_err_t File_Extractor::seek_arc_v( fex_pos_t pos ) blargg_err_t File_Extractor::seek_arc_v( fex_pos_t pos )
{ {
// >= because seeking to current file should always reset read pointer etc. // >= because seeking to current file should always reset read pointer etc.
if ( tell_ >= pos ) if ( tell_ >= pos )
RETURN_ERR( rewind() ); RETURN_ERR( rewind() );
while ( tell_ < pos ) while ( tell_ < pos )
{ {
RETURN_ERR( next_() ); RETURN_ERR( next_() );
if ( done() ) if ( done() )
{ {
assert( false ); assert( false );
return blargg_err_caller; return blargg_err_caller;
} }
} }
assert( tell_ == pos ); assert( tell_ == pos );
return blargg_ok; return blargg_ok;
} }
// Extraction // Extraction
blargg_err_t File_Extractor::rewind_file() blargg_err_t File_Extractor::rewind_file()
{ {
RETURN_ERR( stat() ); RETURN_ERR( stat() );
if ( tell() > 0 ) if ( tell() > 0 )
{ {
if ( data_ptr_ ) if ( data_ptr_ )
{ {
set_remain( size() ); set_remain( size() );
} }
else else
{ {
RETURN_ERR( seek_arc( tell_arc() ) ); RETURN_ERR( seek_arc( tell_arc() ) );
RETURN_ERR( stat() ); RETURN_ERR( stat() );
} }
} }
return blargg_ok; return blargg_ok;
} }
blargg_err_t File_Extractor::data( const void** data_out ) blargg_err_t File_Extractor::data( const void** data_out )
{ {
assert( !done() ); assert( !done() );
*data_out = NULL; *data_out = NULL;
if ( !data_ptr_ ) if ( !data_ptr_ )
{ {
int old_tell = tell(); int old_tell = tell();
RETURN_ERR( rewind_file() ); RETURN_ERR( rewind_file() );
void const* ptr; void const* ptr;
RETURN_ERR( data_v( &ptr ) ); RETURN_ERR( data_v( &ptr ) );
data_ptr_ = ptr; data_ptr_ = ptr;
// Now that data is in memory, we can seek by simply setting remain // Now that data is in memory, we can seek by simply setting remain
set_remain( size() - old_tell ); set_remain( size() - old_tell );
} }
*data_out = data_ptr_; *data_out = data_ptr_;
return blargg_ok; return blargg_ok;
} }
blargg_err_t File_Extractor::data_v( void const** out ) blargg_err_t File_Extractor::data_v( void const** out )
{ {
RETURN_ERR( own_data_.resize( size() ) ); RETURN_ERR( own_data_.resize( size() ) );
*out = own_data_.begin(); *out = own_data_.begin();
blargg_err_t err = extract_v( own_data_.begin(), own_data_.size() ); blargg_err_t err = extract_v( own_data_.begin(), own_data_.size() );
if ( err ) if ( err )
own_data_.clear(); own_data_.clear();
return err; return err;
} }
blargg_err_t File_Extractor::extract_v( void* out, int count ) blargg_err_t File_Extractor::extract_v( void* out, int count )
{ {
void const* p; void const* p;
RETURN_ERR( data( &p ) ); RETURN_ERR( data( &p ) );
memcpy( out, STATIC_CAST(char const*,p) + (size() - remain()), count ); memcpy( out, STATIC_CAST(char const*,p) + (size() - remain()), count );
return blargg_ok; return blargg_ok;
} }
blargg_err_t File_Extractor::read_v( void* out, int count ) blargg_err_t File_Extractor::read_v( void* out, int count )
{ {
if ( data_ptr_ ) if ( data_ptr_ )
return File_Extractor::extract_v( out, count ); return File_Extractor::extract_v( out, count );
return extract_v( out, count ); return extract_v( out, count );
} }

View File

@ -1,191 +1,191 @@
// Compressed file archive interface // Compressed file archive interface
// File_Extractor 1.0.0 // File_Extractor 1.0.0
#ifndef FILE_EXTRACTOR_H #ifndef FILE_EXTRACTOR_H
#define FILE_EXTRACTOR_H #define FILE_EXTRACTOR_H
#include "blargg_common.h" #include "blargg_common.h"
#include "Data_Reader.h" #include "Data_Reader.h"
#include "fex.h" #include "fex.h"
struct fex_t : private Data_Reader { struct fex_t : private Data_Reader {
public: public:
virtual ~fex_t(); virtual ~fex_t();
// Open/close // Open/close
// Opens archive from custom data source. Keeps pointer until close(). // Opens archive from custom data source. Keeps pointer until close().
blargg_err_t open( File_Reader* input, const char* path = NULL ); blargg_err_t open( File_Reader* input, const char* path = NULL );
// Takes ownership of File_Reader* passed to open(), so that close() // Takes ownership of File_Reader* passed to open(), so that close()
// will delete it. // will delete it.
void own_file() { own_file_ = reader_; } void own_file() { own_file_ = reader_; }
// See fex.h // See fex.h
blargg_err_t open( const char path [] ); blargg_err_t open( const char path [] );
fex_type_t type() const { return type_; } fex_type_t type() const { return type_; }
void close(); void close();
// Scanning // Scanning
// See fex.h // See fex.h
bool done() const { return done_; } bool done() const { return done_; }
blargg_err_t next(); blargg_err_t next();
blargg_err_t rewind(); blargg_err_t rewind();
fex_pos_t tell_arc() const; fex_pos_t tell_arc() const;
blargg_err_t seek_arc( fex_pos_t ); blargg_err_t seek_arc( fex_pos_t );
// Info // Info
// See fex.h // See fex.h
const char* name() const { return name_; } const char* name() const { return name_; }
const wchar_t* wname() const { return wname_; } const wchar_t* wname() const { return wname_; }
blargg_err_t stat(); blargg_err_t stat();
int size() const { assert( stat_called ); return size_; } int size() const { assert( stat_called ); return size_; }
unsigned int dos_date() const { return date_; } unsigned int dos_date() const { return date_; }
unsigned int crc32() const { return crc32_; } unsigned int crc32() const { return crc32_; }
// Extraction // Extraction
// Data_Reader to current file's data, so standard Data_Reader interface can // Data_Reader to current file's data, so standard Data_Reader interface can
// be used, rather than having to treat archives specially. stat() must have // be used, rather than having to treat archives specially. stat() must have
// been called. // been called.
Data_Reader& reader() { assert( stat_called ); return *this; } Data_Reader& reader() { assert( stat_called ); return *this; }
// See fex.h // See fex.h
blargg_err_t data( const void** data_out ); blargg_err_t data( const void** data_out );
int tell() const { return size_ - remain(); } int tell() const { return size_ - remain(); }
// Derived interface // Derived interface
protected: protected:
// Sets type of object // Sets type of object
fex_t( fex_type_t ); fex_t( fex_type_t );
// Path to archive file, or "" if none supplied // Path to archive file, or "" if none supplied
const char* arc_path() const { return path_.begin(); } const char* arc_path() const { return path_.begin(); }
// Opens archive file if it's not already. If unbuffered is true, opens file // Opens archive file if it's not already. If unbuffered is true, opens file
// without any buffering. // without any buffering.
blargg_err_t open_arc_file( bool unbuffered = false ); blargg_err_t open_arc_file( bool unbuffered = false );
// Archive file // Archive file
File_Reader& arc() const { return *reader_; } File_Reader& arc() const { return *reader_; }
// Sets current file name // Sets current file name
void set_name( const char name [], const wchar_t* wname = NULL ); void set_name( const char name [], const wchar_t* wname = NULL );
// Sets current file information // Sets current file information
void set_info( int size, unsigned date = 0, unsigned crc = 0 ); void set_info( int size, unsigned date = 0, unsigned crc = 0 );
// User overrides // User overrides
// Overrides must do indicated task. Non-pure functions have reasonable default // Overrides must do indicated task. Non-pure functions have reasonable default
// implementation. Overrides should avoid calling public functions like // implementation. Overrides should avoid calling public functions like
// next() and rewind(). // next() and rewind().
// Open archive using file_path(). OK to delay actual file opening until later. // Open archive using file_path(). OK to delay actual file opening until later.
// Default just calls open_arc_file(), then open_v(). // Default just calls open_arc_file(), then open_v().
virtual blargg_err_t open_path_v(); virtual blargg_err_t open_path_v();
// Open archive using file() for source data. If unsupported, return error. // Open archive using file() for source data. If unsupported, return error.
virtual blargg_err_t open_v() BLARGG_PURE( ; ) virtual blargg_err_t open_v() BLARGG_PURE( ; )
// Go to next file in archive and call set_name() and optionally set_info() // Go to next file in archive and call set_name() and optionally set_info()
virtual blargg_err_t next_v() BLARGG_PURE( ; ) virtual blargg_err_t next_v() BLARGG_PURE( ; )
// Go back to first file in archive // Go back to first file in archive
virtual blargg_err_t rewind_v() BLARGG_PURE( ; ) virtual blargg_err_t rewind_v() BLARGG_PURE( ; )
// Close archive. Called even if open_path_v() or open_v() return unsuccessfully. // Close archive. Called even if open_path_v() or open_v() return unsuccessfully.
virtual void close_v() BLARGG_PURE( ; ) virtual void close_v() BLARGG_PURE( ; )
// Clear any fields related to current file // Clear any fields related to current file
virtual void clear_file_v() { } virtual void clear_file_v() { }
// Call set_info() if not already called by next_v() // Call set_info() if not already called by next_v()
virtual blargg_err_t stat_v() { return blargg_ok; } virtual blargg_err_t stat_v() { return blargg_ok; }
// Return value that allows later return to this file. Result must be >= 0. // Return value that allows later return to this file. Result must be >= 0.
virtual fex_pos_t tell_arc_v() const; virtual fex_pos_t tell_arc_v() const;
// Return to previously saved position // Return to previously saved position
virtual blargg_err_t seek_arc_v( fex_pos_t ); virtual blargg_err_t seek_arc_v( fex_pos_t );
// One or both of the following must be overridden // One or both of the following must be overridden
// Provide pointer to data for current file in archive // Provide pointer to data for current file in archive
virtual blargg_err_t data_v( const void** out ); virtual blargg_err_t data_v( const void** out );
// Extract next n bytes // Extract next n bytes
virtual blargg_err_t extract_v( void* out, int n ); virtual blargg_err_t extract_v( void* out, int n );
// Implementation // Implementation
public: public:
BLARGG_DISABLE_NOTHROW BLARGG_DISABLE_NOTHROW
private: private:
fex_type_t const type_; fex_type_t const type_;
// Archive file // Archive file
blargg_vector<char> path_; blargg_vector<char> path_;
File_Reader* reader_; File_Reader* reader_;
File_Reader* own_file_; File_Reader* own_file_;
bool opened_; bool opened_;
// Position in archive // Position in archive
fex_pos_t tell_; // only used by default implementation of tell/seek fex_pos_t tell_; // only used by default implementation of tell/seek
bool done_; bool done_;
// Info for current file in archive // Info for current file in archive
const char* name_; const char* name_;
const wchar_t* wname_; const wchar_t* wname_;
unsigned date_; unsigned date_;
unsigned crc32_; unsigned crc32_;
int size_; int size_;
bool stat_called; bool stat_called;
// Current file contents // Current file contents
void const* data_ptr_; // NULL if not read into memory void const* data_ptr_; // NULL if not read into memory
blargg_vector<char> own_data_; blargg_vector<char> own_data_;
bool opened() const { return opened_; } bool opened() const { return opened_; }
void clear_file(); void clear_file();
void close_(); void close_();
blargg_err_t set_path( const char* path ); blargg_err_t set_path( const char* path );
blargg_err_t rewind_file(); blargg_err_t rewind_file();
blargg_err_t next_(); blargg_err_t next_();
// Data_Reader overrides // Data_Reader overrides
// TODO: override skip_v? // TODO: override skip_v?
virtual blargg_err_t read_v( void* out, int n ); virtual blargg_err_t read_v( void* out, int n );
}; };
struct fex_type_t_ struct fex_type_t_
{ {
const char* extension; const char* extension;
File_Extractor* (*new_fex)(); File_Extractor* (*new_fex)();
const char* name; const char* name;
blargg_err_t (*init)(); // Called by fex_init(). Can be NULL. blargg_err_t (*init)(); // Called by fex_init(). Can be NULL.
}; };
extern const fex_type_t_ extern const fex_type_t_
fex_7z_type [1], fex_7z_type [1],
fex_gz_type [1], fex_gz_type [1],
fex_rar_type [1], fex_rar_type [1],
fex_zip_type [1], fex_zip_type [1],
fex_bin_type [1]; fex_bin_type [1];
inline blargg_err_t File_Extractor::open_v() { return blargg_ok; } inline blargg_err_t File_Extractor::open_v() { return blargg_ok; }
inline blargg_err_t File_Extractor::next_v() { return blargg_ok; } inline blargg_err_t File_Extractor::next_v() { return blargg_ok; }
inline blargg_err_t File_Extractor::rewind_v() { return blargg_ok; } inline blargg_err_t File_Extractor::rewind_v() { return blargg_ok; }
inline void File_Extractor::close_v() { } inline void File_Extractor::close_v() { }
// Default to Std_File_Reader for archive access // Default to Std_File_Reader for archive access
#ifndef FEX_FILE_READER #ifndef FEX_FILE_READER
#define FEX_FILE_READER Std_File_Reader #define FEX_FILE_READER Std_File_Reader
#elif defined (FEX_FILE_READER_INCLUDE) #elif defined (FEX_FILE_READER_INCLUDE)
#include FEX_FILE_READER_INCLUDE #include FEX_FILE_READER_INCLUDE
#endif #endif
#endif #endif

View File

@ -1,98 +1,98 @@
// File_Extractor 1.0.0. http://www.slack.net/~ant/ // File_Extractor 1.0.0. http://www.slack.net/~ant/
#include "Gzip_Extractor.h" #include "Gzip_Extractor.h"
/* Copyright (C) 2005-2009 Shay Green. This module is free software; you /* Copyright (C) 2005-2009 Shay Green. This module is free software; you
can redistribute it and/or modify it under the terms of the GNU Lesser can redistribute it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software Foundation; either General Public License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version. This version 2.1 of the License, or (at your option) any later version. This
module is distributed in the hope that it will be useful, but WITHOUT ANY module is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details. You should have received a copy of the GNU Lesser General Public details. You should have received a copy of the GNU Lesser General Public
License along with this module; if not, write to the Free Software Foundation, License along with this module; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
#include "blargg_source.h" #include "blargg_source.h"
// TODO: could close file once data has been read into memory // TODO: could close file once data has been read into memory
static blargg_err_t init_gzip_file() static blargg_err_t init_gzip_file()
{ {
get_crc_table(); // initialize zlib's CRC-32 tables get_crc_table(); // initialize zlib's CRC-32 tables
return blargg_ok; return blargg_ok;
} }
static File_Extractor* new_gzip() static File_Extractor* new_gzip()
{ {
return BLARGG_NEW Gzip_Extractor; return BLARGG_NEW Gzip_Extractor;
} }
fex_type_t_ const fex_gz_type [1] = {{ fex_type_t_ const fex_gz_type [1] = {{
".gz", ".gz",
&new_gzip, &new_gzip,
"gzipped file", "gzipped file",
&init_gzip_file &init_gzip_file
}}; }};
Gzip_Extractor::Gzip_Extractor() : Gzip_Extractor::Gzip_Extractor() :
File_Extractor( fex_gz_type ) File_Extractor( fex_gz_type )
{ } { }
Gzip_Extractor::~Gzip_Extractor() Gzip_Extractor::~Gzip_Extractor()
{ {
close(); close();
} }
blargg_err_t Gzip_Extractor::open_path_v() blargg_err_t Gzip_Extractor::open_path_v()
{ {
// skip opening file // skip opening file
return open_v(); return open_v();
} }
blargg_err_t Gzip_Extractor::stat_v() blargg_err_t Gzip_Extractor::stat_v()
{ {
RETURN_ERR( open_arc_file( true ) ); RETURN_ERR( open_arc_file( true ) );
if ( !gr.opened() || gr.tell() != 0 ) if ( !gr.opened() || gr.tell() != 0 )
RETURN_ERR( gr.open( &arc() ) ); RETURN_ERR( gr.open( &arc() ) );
set_info( gr.remain(), 0, gr.crc32() ); set_info( gr.remain(), 0, gr.crc32() );
return blargg_ok; return blargg_ok;
} }
blargg_err_t Gzip_Extractor::open_v() blargg_err_t Gzip_Extractor::open_v()
{ {
// Remove .gz suffix // Remove .gz suffix
size_t len = strlen( arc_path() ); size_t len = strlen( arc_path() );
if ( fex_has_extension( arc_path(), ".gz" ) ) if ( fex_has_extension( arc_path(), ".gz" ) )
len -= 3; len -= 3;
RETURN_ERR( name.resize( len + 1 ) ); RETURN_ERR( name.resize( len + 1 ) );
memcpy( name.begin(), arc_path(), name.size() ); memcpy( name.begin(), arc_path(), name.size() );
name [name.size() - 1] = '\0'; name [name.size() - 1] = '\0';
set_name( name.begin() ); set_name( name.begin() );
return blargg_ok; return blargg_ok;
} }
void Gzip_Extractor::close_v() void Gzip_Extractor::close_v()
{ {
name.clear(); name.clear();
gr.close(); gr.close();
} }
blargg_err_t Gzip_Extractor::next_v() blargg_err_t Gzip_Extractor::next_v()
{ {
return blargg_ok; return blargg_ok;
} }
blargg_err_t Gzip_Extractor::rewind_v() blargg_err_t Gzip_Extractor::rewind_v()
{ {
set_name( name.begin() ); set_name( name.begin() );
return blargg_ok; return blargg_ok;
} }
blargg_err_t Gzip_Extractor::extract_v( void* p, int n ) blargg_err_t Gzip_Extractor::extract_v( void* p, int n )
{ {
return gr.read( p, n ); return gr.read( p, n );
} }

View File

@ -1,34 +1,34 @@
// Presents a gzipped file as an "archive" of just that file. // Presents a gzipped file as an "archive" of just that file.
// Also handles non-gzipped files. // Also handles non-gzipped files.
// File_Extractor 1.0.0 // File_Extractor 1.0.0
#ifndef GZIP_EXTRACTOR_H #ifndef GZIP_EXTRACTOR_H
#define GZIP_EXTRACTOR_H #define GZIP_EXTRACTOR_H
#include "File_Extractor.h" #include "File_Extractor.h"
#include "Gzip_Reader.h" #include "Gzip_Reader.h"
class Gzip_Extractor : public File_Extractor { class Gzip_Extractor : public File_Extractor {
public: public:
Gzip_Extractor(); Gzip_Extractor();
virtual ~Gzip_Extractor(); virtual ~Gzip_Extractor();
protected: protected:
virtual blargg_err_t open_path_v(); virtual blargg_err_t open_path_v();
virtual blargg_err_t open_v(); virtual blargg_err_t open_v();
virtual void close_v(); virtual void close_v();
virtual blargg_err_t next_v(); virtual blargg_err_t next_v();
virtual blargg_err_t rewind_v(); virtual blargg_err_t rewind_v();
virtual blargg_err_t stat_v(); virtual blargg_err_t stat_v();
virtual blargg_err_t extract_v( void*, int ); virtual blargg_err_t extract_v( void*, int );
private: private:
Gzip_Reader gr; Gzip_Reader gr;
blargg_vector<char> name; blargg_vector<char> name;
void set_info_(); void set_info_();
}; };
#endif #endif

View File

@ -1,85 +1,85 @@
// File_Extractor 1.0.0. http://www.slack.net/~ant/ // File_Extractor 1.0.0. http://www.slack.net/~ant/
#include "Gzip_Reader.h" #include "Gzip_Reader.h"
#include "blargg_endian.h" #include "blargg_endian.h"
/* Copyright (C) 2006-2009 Shay Green. This module is free software; you /* Copyright (C) 2006-2009 Shay Green. This module is free software; you
can redistribute it and/or modify it under the terms of the GNU Lesser can redistribute it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software Foundation; either General Public License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version. This version 2.1 of the License, or (at your option) any later version. This
module is distributed in the hope that it will be useful, but WITHOUT ANY module is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details. You should have received a copy of the GNU Lesser General Public details. You should have received a copy of the GNU Lesser General Public
License along with this module; if not, write to the Free Software Foundation, License along with this module; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
#include "blargg_source.h" #include "blargg_source.h"
Gzip_Reader::Gzip_Reader() Gzip_Reader::Gzip_Reader()
{ {
close(); close();
} }
Gzip_Reader::~Gzip_Reader() Gzip_Reader::~Gzip_Reader()
{ } { }
static blargg_err_t gzip_reader_read( void* file, void* out, int* count ) static blargg_err_t gzip_reader_read( void* file, void* out, int* count )
{ {
return STATIC_CAST(File_Reader*,file)->read_avail( out, count ); return STATIC_CAST(File_Reader*,file)->read_avail( out, count );
} }
blargg_err_t Gzip_Reader::calc_size() blargg_err_t Gzip_Reader::calc_size()
{ {
size_ = in->size(); size_ = in->size();
crc32_ = 0; crc32_ = 0;
if ( inflater.deflated() ) if ( inflater.deflated() )
{ {
byte trailer [8]; byte trailer [8];
int old_pos = in->tell(); int old_pos = in->tell();
RETURN_ERR( in->seek( size_ - sizeof trailer ) ); RETURN_ERR( in->seek( size_ - sizeof trailer ) );
RETURN_ERR( in->read( trailer, sizeof trailer ) ); RETURN_ERR( in->read( trailer, sizeof trailer ) );
RETURN_ERR( in->seek( old_pos ) ); RETURN_ERR( in->seek( old_pos ) );
crc32_ = get_le32( trailer + 0 ); crc32_ = get_le32( trailer + 0 );
unsigned n = get_le32( trailer + 4 ); unsigned n = get_le32( trailer + 4 );
if ( n > INT_MAX ) if ( n > INT_MAX )
return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "gzip larger than 2GB" ); return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "gzip larger than 2GB" );
size_ = n; size_ = n;
} }
return blargg_ok; return blargg_ok;
} }
blargg_err_t Gzip_Reader::open( File_Reader* new_in ) blargg_err_t Gzip_Reader::open( File_Reader* new_in )
{ {
close(); close();
in = new_in; in = new_in;
RETURN_ERR( in->seek( 0 ) ); RETURN_ERR( in->seek( 0 ) );
RETURN_ERR( inflater.begin( gzip_reader_read, new_in ) ); RETURN_ERR( inflater.begin( gzip_reader_read, new_in ) );
RETURN_ERR( inflater.set_mode( inflater.mode_auto ) ); RETURN_ERR( inflater.set_mode( inflater.mode_auto ) );
RETURN_ERR( calc_size() ); RETURN_ERR( calc_size() );
set_remain( size_ ); set_remain( size_ );
return blargg_ok; return blargg_ok;
} }
void Gzip_Reader::close() void Gzip_Reader::close()
{ {
in = NULL; in = NULL;
inflater.end(); inflater.end();
} }
blargg_err_t Gzip_Reader::read_v( void* out, int count ) blargg_err_t Gzip_Reader::read_v( void* out, int count )
{ {
assert( in ); assert( in );
int actual = count; int actual = count;
RETURN_ERR( inflater.read( out, &actual ) ); RETURN_ERR( inflater.read( out, &actual ) );
if ( actual != count ) if ( actual != count )
return blargg_err_file_corrupt; return blargg_err_file_corrupt;
return blargg_ok; return blargg_ok;
} }

View File

@ -1,46 +1,46 @@
// Transparently decompresses gzip files, as well as uncompressed // Transparently decompresses gzip files, as well as uncompressed
// File_Extractor 1.0.0 // File_Extractor 1.0.0
#ifndef GZIP_READER_H #ifndef GZIP_READER_H
#define GZIP_READER_H #define GZIP_READER_H
#include "Data_Reader.h" #include "Data_Reader.h"
#include "Zlib_Inflater.h" #include "Zlib_Inflater.h"
class Gzip_Reader : public Data_Reader { class Gzip_Reader : public Data_Reader {
public: public:
// Keeps pointer to reader until close(). If // Keeps pointer to reader until close(). If
blargg_err_t open( File_Reader* ); blargg_err_t open( File_Reader* );
// True if file is open // True if file is open
bool opened() const { return in != NULL; } bool opened() const { return in != NULL; }
// Frees memory // Frees memory
void close(); void close();
// True if file is compressed // True if file is compressed
bool deflated() const { return inflater.deflated(); } bool deflated() const { return inflater.deflated(); }
// CRC-32 of data, of 0 if unavailable // CRC-32 of data, of 0 if unavailable
unsigned int crc32() const { return crc32_; } unsigned int crc32() const { return crc32_; }
// Number of bytes read since opening // Number of bytes read since opening
int tell() const { return size_ - remain(); } int tell() const { return size_ - remain(); }
public: public:
Gzip_Reader(); Gzip_Reader();
virtual ~Gzip_Reader(); virtual ~Gzip_Reader();
protected: protected:
virtual blargg_err_t read_v( void*, int ); virtual blargg_err_t read_v( void*, int );
private: private:
File_Reader* in; File_Reader* in;
unsigned crc32_; unsigned crc32_;
int size_; int size_;
Zlib_Inflater inflater; Zlib_Inflater inflater;
blargg_err_t calc_size(); blargg_err_t calc_size();
}; };
#endif #endif

View File

@ -1,197 +1,197 @@
// File_Extractor 1.0.0. http://www.slack.net/~ant/ // File_Extractor 1.0.0. http://www.slack.net/~ant/
#include "blargg_common.h" #include "blargg_common.h"
#if FEX_ENABLE_RAR #if FEX_ENABLE_RAR
#include "Rar_Extractor.h" #include "Rar_Extractor.h"
/* Copyright (C) 2009 Shay Green. This module is free software; you /* Copyright (C) 2009 Shay Green. This module is free software; you
can redistribute it and/or modify it under the terms of the GNU Lesser can redistribute it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software Foundation; either General Public License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version. This version 2.1 of the License, or (at your option) any later version. This
module is distributed in the hope that it will be useful, but WITHOUT ANY module is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details. You should have received a copy of the GNU Lesser General Public details. You should have received a copy of the GNU Lesser General Public
License along with this module; if not, write to the Free Software Foundation, License along with this module; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
#include "blargg_source.h" #include "blargg_source.h"
static blargg_err_t init_rar() static blargg_err_t init_rar()
{ {
unrar_init(); unrar_init();
return blargg_ok; return blargg_ok;
} }
static File_Extractor* new_rar() static File_Extractor* new_rar()
{ {
return BLARGG_NEW Rar_Extractor; return BLARGG_NEW Rar_Extractor;
} }
fex_type_t_ const fex_rar_type [1] = {{ fex_type_t_ const fex_rar_type [1] = {{
".rar", ".rar",
&new_rar, &new_rar,
"RAR archive", "RAR archive",
&init_rar &init_rar
}}; }};
blargg_err_t Rar_Extractor::convert_err( unrar_err_t err ) blargg_err_t Rar_Extractor::convert_err( unrar_err_t err )
{ {
blargg_err_t reader_err = reader.err; blargg_err_t reader_err = reader.err;
reader.err = blargg_ok; reader.err = blargg_ok;
if ( reader_err ) if ( reader_err )
check( err == unrar_next_err ); check( err == unrar_next_err );
switch ( err ) switch ( err )
{ {
case unrar_ok: return blargg_ok; case unrar_ok: return blargg_ok;
case unrar_err_memory: return blargg_err_memory; case unrar_err_memory: return blargg_err_memory;
case unrar_err_open: return blargg_err_file_read; case unrar_err_open: return blargg_err_file_read;
case unrar_err_not_arc: return blargg_err_file_type; case unrar_err_not_arc: return blargg_err_file_type;
case unrar_err_corrupt: return blargg_err_file_corrupt; case unrar_err_corrupt: return blargg_err_file_corrupt;
case unrar_err_io: return blargg_err_file_io; case unrar_err_io: return blargg_err_file_io;
case unrar_err_arc_eof: return blargg_err_internal; case unrar_err_arc_eof: return blargg_err_internal;
case unrar_err_encrypted: return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "RAR encryption not supported" ); case unrar_err_encrypted: return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "RAR encryption not supported" );
case unrar_err_segmented: return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "RAR segmentation not supported" ); case unrar_err_segmented: return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "RAR segmentation not supported" );
case unrar_err_huge: return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "Huge RAR files not supported" ); case unrar_err_huge: return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "Huge RAR files not supported" );
case unrar_err_old_algo: return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "Old RAR compression not supported" ); case unrar_err_old_algo: return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "Old RAR compression not supported" );
case unrar_err_new_algo: return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "RAR uses unknown newer compression" ); case unrar_err_new_algo: return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "RAR uses unknown newer compression" );
case unrar_next_err: break; case unrar_next_err: break;
default: default:
check( false ); // unhandled RAR error check( false ); // unhandled RAR error
} }
if ( reader_err ) if ( reader_err )
return reader_err; return reader_err;
check( false ); check( false );
return BLARGG_ERR( BLARGG_ERR_INTERNAL, "RAR archive" ); return BLARGG_ERR( BLARGG_ERR_INTERNAL, "RAR archive" );
} }
static inline unrar_err_t handle_err( Rar_Extractor::read_callback_t* h, blargg_err_t err ) static inline unrar_err_t handle_err( Rar_Extractor::read_callback_t* h, blargg_err_t err )
{ {
if ( !err ) if ( !err )
return unrar_ok; return unrar_ok;
h->err = err; h->err = err;
return unrar_next_err; return unrar_next_err;
} }
extern "C" extern "C"
{ {
static unrar_err_t my_unrar_read( void* data, void* out, int* count, unrar_pos_t pos ) static unrar_err_t my_unrar_read( void* data, void* out, int* count, unrar_pos_t pos )
{ {
// TODO: 64-bit file support // TODO: 64-bit file support
Rar_Extractor::read_callback_t* h = STATIC_CAST(Rar_Extractor::read_callback_t*,data); Rar_Extractor::read_callback_t* h = STATIC_CAST(Rar_Extractor::read_callback_t*,data);
if ( h->pos != pos ) if ( h->pos != pos )
{ {
blargg_err_t err = h->in->seek( pos ); blargg_err_t err = h->in->seek( pos );
if ( err ) if ( err )
return handle_err( h, err ); return handle_err( h, err );
h->pos = pos; h->pos = pos;
} }
blargg_err_t err = h->in->read_avail( out, count ); blargg_err_t err = h->in->read_avail( out, count );
if ( err ) if ( err )
return handle_err( h, err ); return handle_err( h, err );
h->pos += *count; h->pos += *count;
return unrar_ok; return unrar_ok;
} }
} }
Rar_Extractor::Rar_Extractor() : Rar_Extractor::Rar_Extractor() :
File_Extractor( fex_rar_type ) File_Extractor( fex_rar_type )
{ {
unrar = NULL; unrar = NULL;
} }
Rar_Extractor::~Rar_Extractor() Rar_Extractor::~Rar_Extractor()
{ {
close(); close();
} }
blargg_err_t Rar_Extractor::open_v() blargg_err_t Rar_Extractor::open_v()
{ {
reader.pos = 0; reader.pos = 0;
reader.in = &arc(); reader.in = &arc();
reader.err = blargg_ok; reader.err = blargg_ok;
RETURN_ERR( arc().seek( 0 ) ); RETURN_ERR( arc().seek( 0 ) );
RETURN_ERR( convert_err( unrar_open_custom( &unrar, &my_unrar_read, &reader ) ) ); RETURN_ERR( convert_err( unrar_open_custom( &unrar, &my_unrar_read, &reader ) ) );
return skip_unextractables(); return skip_unextractables();
} }
void Rar_Extractor::close_v() void Rar_Extractor::close_v()
{ {
unrar_close( unrar ); unrar_close( unrar );
unrar = NULL; unrar = NULL;
reader.in = NULL; reader.in = NULL;
} }
blargg_err_t Rar_Extractor::skip_unextractables() blargg_err_t Rar_Extractor::skip_unextractables()
{ {
while ( !unrar_done( unrar ) && unrar_try_extract( unrar ) ) while ( !unrar_done( unrar ) && unrar_try_extract( unrar ) )
RETURN_ERR( next_raw() ); RETURN_ERR( next_raw() );
if ( !unrar_done( unrar ) ) if ( !unrar_done( unrar ) )
{ {
unrar_info_t const* info = unrar_info( unrar ); unrar_info_t const* info = unrar_info( unrar );
set_name( info->name, (info->name_w && *info->name_w) ? info->name_w : NULL ); set_name( info->name, (info->name_w && *info->name_w) ? info->name_w : NULL );
set_info( info->size, info->dos_date, (info->is_crc32 ? info->crc : 0) ); set_info( info->size, info->dos_date, (info->is_crc32 ? info->crc : 0) );
} }
return blargg_ok; return blargg_ok;
} }
blargg_err_t Rar_Extractor::next_raw() blargg_err_t Rar_Extractor::next_raw()
{ {
return convert_err( unrar_next( unrar ) ); return convert_err( unrar_next( unrar ) );
} }
blargg_err_t Rar_Extractor::next_v() blargg_err_t Rar_Extractor::next_v()
{ {
RETURN_ERR( next_raw() ); RETURN_ERR( next_raw() );
return skip_unextractables(); return skip_unextractables();
} }
blargg_err_t Rar_Extractor::rewind_v() blargg_err_t Rar_Extractor::rewind_v()
{ {
RETURN_ERR( convert_err( unrar_rewind( unrar ) ) ); RETURN_ERR( convert_err( unrar_rewind( unrar ) ) );
return skip_unextractables(); return skip_unextractables();
} }
fex_pos_t Rar_Extractor::tell_arc_v() const fex_pos_t Rar_Extractor::tell_arc_v() const
{ {
return unrar_tell( unrar ); return unrar_tell( unrar );
} }
blargg_err_t Rar_Extractor::seek_arc_v( fex_pos_t pos ) blargg_err_t Rar_Extractor::seek_arc_v( fex_pos_t pos )
{ {
RETURN_ERR( convert_err( unrar_seek( unrar, pos ) ) ); RETURN_ERR( convert_err( unrar_seek( unrar, pos ) ) );
return skip_unextractables(); return skip_unextractables();
} }
blargg_err_t Rar_Extractor::data_v( void const** out ) blargg_err_t Rar_Extractor::data_v( void const** out )
{ {
return convert_err( unrar_extract_mem( unrar, out ) ); return convert_err( unrar_extract_mem( unrar, out ) );
} }
blargg_err_t Rar_Extractor::extract_v( void* out, int count ) blargg_err_t Rar_Extractor::extract_v( void* out, int count )
{ {
// We can read entire file directly into user buffer // We can read entire file directly into user buffer
if ( count == size() ) if ( count == size() )
return convert_err( unrar_extract( unrar, out, count ) ); return convert_err( unrar_extract( unrar, out, count ) );
// This will call data_v() and copy from that buffer for us // This will call data_v() and copy from that buffer for us
return File_Extractor::extract_v( out, count ); return File_Extractor::extract_v( out, count );
} }
#endif #endif

View File

@ -1,43 +1,43 @@
// RAR archive extractor // RAR archive extractor
// File_Extractor 1.0.0 // File_Extractor 1.0.0
#ifndef RAR_EXTRACTOR_H #ifndef RAR_EXTRACTOR_H
#define RAR_EXTRACTOR_H #define RAR_EXTRACTOR_H
#include "File_Extractor.h" #include "File_Extractor.h"
#include "unrar/unrar.h" #include "unrar/unrar.h"
class Rar_Extractor : public File_Extractor { class Rar_Extractor : public File_Extractor {
public: public:
Rar_Extractor(); Rar_Extractor();
virtual ~Rar_Extractor(); virtual ~Rar_Extractor();
struct read_callback_t struct read_callback_t
{ {
const char* err; const char* err;
int pos; int pos;
File_Reader* in; File_Reader* in;
}; };
protected: protected:
virtual blargg_err_t open_v(); virtual blargg_err_t open_v();
virtual void close_v(); virtual void close_v();
virtual blargg_err_t next_v(); virtual blargg_err_t next_v();
virtual blargg_err_t rewind_v(); virtual blargg_err_t rewind_v();
virtual fex_pos_t tell_arc_v() const; virtual fex_pos_t tell_arc_v() const;
virtual blargg_err_t seek_arc_v( fex_pos_t ); virtual blargg_err_t seek_arc_v( fex_pos_t );
virtual blargg_err_t data_v( void const** ); virtual blargg_err_t data_v( void const** );
virtual blargg_err_t extract_v( void*, int ); virtual blargg_err_t extract_v( void*, int );
private: private:
unrar_t* unrar; unrar_t* unrar;
read_callback_t reader; read_callback_t reader;
blargg_err_t convert_err( unrar_err_t ); blargg_err_t convert_err( unrar_err_t );
blargg_err_t skip_unextractables(); blargg_err_t skip_unextractables();
blargg_err_t next_raw(); blargg_err_t next_raw();
}; };
#endif #endif

View File

@ -1,285 +1,285 @@
// File_Extractor 1.0.0. http://www.slack.net/~ant/ // File_Extractor 1.0.0. http://www.slack.net/~ant/
#include "Zip7_Extractor.h" #include "Zip7_Extractor.h"
extern "C" { extern "C" {
#include "7z_C/7z.h" #include "7z_C/7z.h"
#include "7z_C/7zAlloc.h" #include "7z_C/7zAlloc.h"
#include "7z_C/7zCrc.h" #include "7z_C/7zCrc.h"
} }
#include <time.h> #include <time.h>
/* Copyright (C) 2005-2009 Shay Green. This module is free software; you /* Copyright (C) 2005-2009 Shay Green. This module is free software; you
can redistribute it and/or modify it under the terms of the GNU Lesser can redistribute it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software Foundation; either General Public License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version. This version 2.1 of the License, or (at your option) any later version. This
module is distributed in the hope that it will be useful, but WITHOUT ANY module is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details. You should have received a copy of the GNU Lesser General Public details. You should have received a copy of the GNU Lesser General Public
License along with this module; if not, write to the Free Software Foundation, License along with this module; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
#include "blargg_source.h" #include "blargg_source.h"
static ISzAlloc zip7_alloc = { SzAlloc, SzFree }; static ISzAlloc zip7_alloc = { SzAlloc, SzFree };
static ISzAlloc zip7_alloc_temp = { SzAllocTemp, SzFreeTemp }; static ISzAlloc zip7_alloc_temp = { SzAllocTemp, SzFreeTemp };
struct Zip7_Extractor_Impl : struct Zip7_Extractor_Impl :
ISeekInStream ISeekInStream
{ {
CLookToRead look; CLookToRead look;
CSzArEx db; CSzArEx db;
// SzExtract state // SzExtract state
UInt32 block_index; UInt32 block_index;
Byte* buf; Byte* buf;
size_t buf_size; size_t buf_size;
File_Reader* in; File_Reader* in;
const char* in_err; const char* in_err;
}; };
extern "C" extern "C"
{ {
// 7-zip callbacks pass an ISeekInStream* for data, so we must cast it // 7-zip callbacks pass an ISeekInStream* for data, so we must cast it
// back to ISeekInStream* FIRST, then cast to our Impl structure // back to ISeekInStream* FIRST, then cast to our Impl structure
static SRes zip7_read_( void* vstream, void* out, size_t* size ) static SRes zip7_read_( void* vstream, void* out, size_t* size )
{ {
assert( out && size ); assert( out && size );
ISeekInStream* stream = STATIC_CAST(ISeekInStream*,vstream); ISeekInStream* stream = STATIC_CAST(ISeekInStream*,vstream);
Zip7_Extractor_Impl* impl = STATIC_CAST(Zip7_Extractor_Impl*,stream); Zip7_Extractor_Impl* impl = STATIC_CAST(Zip7_Extractor_Impl*,stream);
long lsize = *size; long lsize = *size;
blargg_err_t err = impl->in->read_avail( out, &lsize ); blargg_err_t err = impl->in->read_avail( out, &lsize );
if ( err ) if ( err )
{ {
*size = 0; *size = 0;
impl->in_err = err; impl->in_err = err;
return SZ_ERROR_READ; return SZ_ERROR_READ;
} }
*size = lsize; *size = lsize;
return SZ_OK; return SZ_OK;
} }
static SRes zip7_seek_( void* vstream, Int64* pos, ESzSeek mode ) static SRes zip7_seek_( void* vstream, Int64* pos, ESzSeek mode )
{ {
ISeekInStream* stream = STATIC_CAST(ISeekInStream*,vstream); ISeekInStream* stream = STATIC_CAST(ISeekInStream*,vstream);
Zip7_Extractor_Impl* impl = STATIC_CAST(Zip7_Extractor_Impl*,stream); Zip7_Extractor_Impl* impl = STATIC_CAST(Zip7_Extractor_Impl*,stream);
// assert( mode != SZ_SEEK_CUR ); // never used // assert( mode != SZ_SEEK_CUR ); // never used
if ( mode == SZ_SEEK_END ) if ( mode == SZ_SEEK_END )
{ {
assert( *pos == 0 ); // only used to find file length assert( *pos == 0 ); // only used to find file length
*pos = impl->in->size(); *pos = impl->in->size();
return SZ_OK; return SZ_OK;
} }
// assert( mode == SZ_SEEK_SET ); // assert( mode == SZ_SEEK_SET );
blargg_err_t err = impl->in->seek( *pos ); blargg_err_t err = impl->in->seek( *pos );
if ( err ) if ( err )
{ {
// don't set in_err in this case, since it might be benign // don't set in_err in this case, since it might be benign
if ( err == blargg_err_file_eof ) if ( err == blargg_err_file_eof )
return SZ_ERROR_INPUT_EOF; return SZ_ERROR_INPUT_EOF;
impl->in_err = err; impl->in_err = err;
return SZ_ERROR_READ; return SZ_ERROR_READ;
} }
return SZ_OK; return SZ_OK;
} }
} }
blargg_err_t Zip7_Extractor::zip7_err( int err ) blargg_err_t Zip7_Extractor::zip7_err( int err )
{ {
// TODO: ignore in_err in some cases? unsure about which error to use // TODO: ignore in_err in some cases? unsure about which error to use
blargg_err_t in_err = impl->in_err; blargg_err_t in_err = impl->in_err;
impl->in_err = NULL; impl->in_err = NULL;
if ( in_err ) if ( in_err )
{ {
check( err != SZ_OK ); check( err != SZ_OK );
return in_err; return in_err;
} }
switch ( err ) switch ( err )
{ {
case SZ_OK: return blargg_ok; case SZ_OK: return blargg_ok;
case SZ_ERROR_MEM: return blargg_err_memory; case SZ_ERROR_MEM: return blargg_err_memory;
case SZ_ERROR_READ: return blargg_err_file_io; case SZ_ERROR_READ: return blargg_err_file_io;
case SZ_ERROR_CRC: case SZ_ERROR_CRC:
case SZ_ERROR_DATA: case SZ_ERROR_DATA:
case SZ_ERROR_INPUT_EOF: case SZ_ERROR_INPUT_EOF:
case SZ_ERROR_ARCHIVE: return blargg_err_file_corrupt; case SZ_ERROR_ARCHIVE: return blargg_err_file_corrupt;
case SZ_ERROR_UNSUPPORTED: return blargg_err_file_feature; case SZ_ERROR_UNSUPPORTED: return blargg_err_file_feature;
case SZ_ERROR_NO_ARCHIVE: return blargg_err_file_type; case SZ_ERROR_NO_ARCHIVE: return blargg_err_file_type;
} }
return blargg_err_generic; return blargg_err_generic;
} }
static blargg_err_t init_7z() static blargg_err_t init_7z()
{ {
static bool inited; static bool inited;
if ( !inited ) if ( !inited )
{ {
inited = true; inited = true;
CrcGenerateTable(); CrcGenerateTable();
} }
return blargg_ok; return blargg_ok;
} }
static File_Extractor* new_7z() static File_Extractor* new_7z()
{ {
return BLARGG_NEW Zip7_Extractor; return BLARGG_NEW Zip7_Extractor;
} }
fex_type_t_ const fex_7z_type [1] = {{ fex_type_t_ const fex_7z_type [1] = {{
".7z", ".7z",
&new_7z, &new_7z,
"7-zip archive", "7-zip archive",
&init_7z &init_7z
}}; }};
Zip7_Extractor::Zip7_Extractor() : Zip7_Extractor::Zip7_Extractor() :
File_Extractor( fex_7z_type ) File_Extractor( fex_7z_type )
{ {
impl = NULL; impl = NULL;
} }
Zip7_Extractor::~Zip7_Extractor() Zip7_Extractor::~Zip7_Extractor()
{ {
close(); close();
} }
blargg_err_t Zip7_Extractor::open_v() blargg_err_t Zip7_Extractor::open_v()
{ {
RETURN_ERR( init_7z() ); RETURN_ERR( init_7z() );
if ( !impl ) if ( !impl )
{ {
impl = (Zip7_Extractor_Impl*) malloc( sizeof *impl ); impl = (Zip7_Extractor_Impl*) malloc( sizeof *impl );
CHECK_ALLOC( impl ); CHECK_ALLOC( impl );
} }
impl->in = &arc(); impl->in = &arc();
impl->block_index = (UInt32) -1; impl->block_index = (UInt32) -1;
impl->buf = NULL; impl->buf = NULL;
impl->buf_size = 0; impl->buf_size = 0;
LookToRead_CreateVTable( &impl->look, false ); LookToRead_CreateVTable( &impl->look, false );
impl->ISeekInStream::Read = zip7_read_; impl->ISeekInStream::Read = zip7_read_;
impl->ISeekInStream::Seek = zip7_seek_; impl->ISeekInStream::Seek = zip7_seek_;
impl->look.realStream = impl; impl->look.realStream = impl;
LookToRead_Init( &impl->look ); LookToRead_Init( &impl->look );
SzArEx_Init( &impl->db ); SzArEx_Init( &impl->db );
impl->in_err = NULL; impl->in_err = NULL;
RETURN_ERR( zip7_err( SzArEx_Open( &impl->db, &impl->look.s, RETURN_ERR( zip7_err( SzArEx_Open( &impl->db, &impl->look.s,
&zip7_alloc, &zip7_alloc_temp ) ) ); &zip7_alloc, &zip7_alloc_temp ) ) );
return seek_arc_v( 0 ); return seek_arc_v( 0 );
} }
void Zip7_Extractor::close_v() void Zip7_Extractor::close_v()
{ {
if ( impl ) if ( impl )
{ {
if ( impl->in ) if ( impl->in )
{ {
impl->in = NULL; impl->in = NULL;
SzArEx_Free( &impl->db, &zip7_alloc ); SzArEx_Free( &impl->db, &zip7_alloc );
} }
IAlloc_Free( &zip7_alloc, impl->buf ); IAlloc_Free( &zip7_alloc, impl->buf );
free( impl ); free( impl );
impl = NULL; impl = NULL;
} }
} }
blargg_err_t Zip7_Extractor::next_v() blargg_err_t Zip7_Extractor::next_v()
{ {
while ( ++index < (int) impl->db.db.NumFiles ) while ( ++index < (int) impl->db.db.NumFiles )
{ {
CSzFileItem const& item = impl->db.db.Files [index]; CSzFileItem const& item = impl->db.db.Files [index];
if ( !item.IsDir ) if ( !item.IsDir )
{ {
unsigned long date = 0; unsigned long date = 0;
if ( item.MTimeDefined ) if ( item.MTimeDefined )
{ {
const UInt64 epoch = ((UInt64)0x019db1de << 32) + 0xd53e8000; const UInt64 epoch = ((UInt64)0x019db1de << 32) + 0xd53e8000;
/* 0x019db1ded53e8000ULL: 1970-01-01 00:00:00 (UTC) */ /* 0x019db1ded53e8000ULL: 1970-01-01 00:00:00 (UTC) */
struct tm tm; struct tm tm;
UInt64 time = ((UInt64)item.MTime.High << 32) + item.MTime.Low - epoch; UInt64 time = ((UInt64)item.MTime.High << 32) + item.MTime.Low - epoch;
time /= 1000000; time /= 1000000;
time_t _time = time; time_t _time = time;
#ifdef _WIN32 #ifdef _WIN32
localtime_s( &tm, &_time ); localtime_s( &tm, &_time );
#else #else
localtime_r( &_time, &tm ); localtime_r( &_time, &tm );
#endif #endif
date = ( tm.tm_sec >> 1 ) & 0x1F | date = ( tm.tm_sec >> 1 ) & 0x1F |
(( tm.tm_min & 0x3F ) << 5 ) | (( tm.tm_min & 0x3F ) << 5 ) |
(( tm.tm_hour & 0x1F ) << 11 ) | (( tm.tm_hour & 0x1F ) << 11 ) |
(( tm.tm_mday & 0x1F ) << 16 ) | (( tm.tm_mday & 0x1F ) << 16 ) |
(( ( tm.tm_mon + 1 ) & 0x0F ) << 21 ) | (( ( tm.tm_mon + 1 ) & 0x0F ) << 21 ) |
(( ( tm.tm_year - 80 ) & 0x7F ) << 25 ); (( ( tm.tm_year - 80 ) & 0x7F ) << 25 );
} }
size_t name_length = SzArEx_GetFileNameUtf16( &impl->db, index, 0 ); size_t name_length = SzArEx_GetFileNameUtf16( &impl->db, index, 0 );
name16.resize( name_length ); name16.resize( name_length );
SzArEx_GetFileNameUtf16( &impl->db, index, ( UInt16 * ) name16.begin() ); SzArEx_GetFileNameUtf16( &impl->db, index, ( UInt16 * ) name16.begin() );
char * temp = blargg_to_utf8( name16.begin() ); char * temp = blargg_to_utf8( name16.begin() );
if ( !temp ) temp = ""; if ( !temp ) temp = "";
size_t utf8_length = strlen( temp ); size_t utf8_length = strlen( temp );
name8.resize( utf8_length + 1 ); name8.resize( utf8_length + 1 );
memcpy( name8.begin(), temp, utf8_length + 1 ); memcpy( name8.begin(), temp, utf8_length + 1 );
free( temp ); free( temp );
set_name( name8.begin(), name16.begin() ); set_name( name8.begin(), name16.begin() );
set_info( item.Size, 0, (item.CrcDefined ? item.Crc : 0) ); set_info( item.Size, 0, (item.CrcDefined ? item.Crc : 0) );
break; break;
} }
} }
return blargg_ok; return blargg_ok;
} }
blargg_err_t Zip7_Extractor::rewind_v() blargg_err_t Zip7_Extractor::rewind_v()
{ {
return seek_arc_v( 0 ); return seek_arc_v( 0 );
} }
fex_pos_t Zip7_Extractor::tell_arc_v() const fex_pos_t Zip7_Extractor::tell_arc_v() const
{ {
return index; return index;
} }
blargg_err_t Zip7_Extractor::seek_arc_v( fex_pos_t pos ) blargg_err_t Zip7_Extractor::seek_arc_v( fex_pos_t pos )
{ {
assert( 0 <= pos && pos <= (int) impl->db.db.NumFiles ); assert( 0 <= pos && pos <= (int) impl->db.db.NumFiles );
index = pos - 1; index = pos - 1;
return next_v(); return next_v();
} }
blargg_err_t Zip7_Extractor::data_v( void const** out ) blargg_err_t Zip7_Extractor::data_v( void const** out )
{ {
impl->in_err = NULL; impl->in_err = NULL;
size_t offset = 0; size_t offset = 0;
size_t count = 0; size_t count = 0;
RETURN_ERR( zip7_err( SzArEx_Extract( &impl->db, &impl->look.s, index, RETURN_ERR( zip7_err( SzArEx_Extract( &impl->db, &impl->look.s, index,
&impl->block_index, &impl->buf, &impl->buf_size, &impl->block_index, &impl->buf, &impl->buf_size,
&offset, &count, &zip7_alloc, &zip7_alloc_temp ) ) ); &offset, &count, &zip7_alloc, &zip7_alloc_temp ) ) );
assert( count == (size_t) size() ); assert( count == (size_t) size() );
*out = impl->buf + offset; *out = impl->buf + offset;
return blargg_ok; return blargg_ok;
} }

View File

@ -1,36 +1,36 @@
// 7-zip archive extractor // 7-zip archive extractor
// File_Extractor 1.0.0 // File_Extractor 1.0.0
#ifndef ZIP7_EXTRACTOR_H #ifndef ZIP7_EXTRACTOR_H
#define ZIP7_EXTRACTOR_H #define ZIP7_EXTRACTOR_H
#include "File_Extractor.h" #include "File_Extractor.h"
struct Zip7_Extractor_Impl; struct Zip7_Extractor_Impl;
class Zip7_Extractor : public File_Extractor { class Zip7_Extractor : public File_Extractor {
public: public:
Zip7_Extractor(); Zip7_Extractor();
virtual ~Zip7_Extractor(); virtual ~Zip7_Extractor();
protected: protected:
virtual blargg_err_t open_v(); virtual blargg_err_t open_v();
virtual void close_v(); virtual void close_v();
virtual blargg_err_t next_v(); virtual blargg_err_t next_v();
virtual blargg_err_t rewind_v(); virtual blargg_err_t rewind_v();
virtual fex_pos_t tell_arc_v() const; virtual fex_pos_t tell_arc_v() const;
virtual blargg_err_t seek_arc_v( fex_pos_t ); virtual blargg_err_t seek_arc_v( fex_pos_t );
virtual blargg_err_t data_v( void const** out ); virtual blargg_err_t data_v( void const** out );
private: private:
Zip7_Extractor_Impl* impl; Zip7_Extractor_Impl* impl;
int index; int index;
blargg_vector<char> name8; blargg_vector<char> name8;
blargg_vector<wchar_t> name16; blargg_vector<wchar_t> name16;
blargg_err_t zip7_err( int err ); blargg_err_t zip7_err( int err );
}; };
#endif #endif

View File

@ -1,390 +1,390 @@
// File_Extractor 1.0.0. http://www.slack.net/~ant/ // File_Extractor 1.0.0. http://www.slack.net/~ant/
#include "Zip_Extractor.h" #include "Zip_Extractor.h"
#include "blargg_endian.h" #include "blargg_endian.h"
/* Copyright (C) 2005-2009 Shay Green. This module is free software; you /* Copyright (C) 2005-2009 Shay Green. This module is free software; you
can redistribute it and/or modify it under the terms of the GNU Lesser can redistribute it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software Foundation; either General Public License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version. This version 2.1 of the License, or (at your option) any later version. This
module is distributed in the hope that it will be useful, but WITHOUT ANY module is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details. You should have received a copy of the GNU Lesser General Public details. You should have received a copy of the GNU Lesser General Public
License along with this module; if not, write to the Free Software Foundation, License along with this module; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
/* To avoid copying filename string from catalog, I terminate it by modifying /* To avoid copying filename string from catalog, I terminate it by modifying
catalog data. This potentially requires moving the first byte of the type catalog data. This potentially requires moving the first byte of the type
of the next entry elsewhere; I move it to the first byte of made_by. Kind of the next entry elsewhere; I move it to the first byte of made_by. Kind
of hacky, but I'd rather not have to allocate memory for a copy of it. */ of hacky, but I'd rather not have to allocate memory for a copy of it. */
#include "blargg_source.h" #include "blargg_source.h"
/* Reads this much from end of file when first opening. Only this much is /* Reads this much from end of file when first opening. Only this much is
searched for the end catalog entry. If whole catalog is within this data, searched for the end catalog entry. If whole catalog is within this data,
nothing more needs to be read on open. */ nothing more needs to be read on open. */
int const end_read_size = 8 * 1024; int const end_read_size = 8 * 1024;
/* Reads are are made using file offset that's a multiple of this, /* Reads are are made using file offset that's a multiple of this,
increasing performance. */ increasing performance. */
int const disk_block_size = 4 * 1024; int const disk_block_size = 4 * 1024;
// Read buffer used for extracting file data // Read buffer used for extracting file data
int const read_buf_size = 16 * 1024; int const read_buf_size = 16 * 1024;
struct header_t struct header_t
{ {
char type [4]; char type [4];
byte vers [2]; byte vers [2];
byte flags [2]; byte flags [2];
byte method [2]; byte method [2];
byte date [4]; byte date [4];
byte crc [4]; byte crc [4];
byte raw_size [4]; byte raw_size [4];
byte size [4]; byte size [4];
byte filename_len [2]; byte filename_len [2];
byte extra_len [2]; byte extra_len [2];
char filename [2]; // [filename_len] char filename [2]; // [filename_len]
//char extra [extra_len]; //char extra [extra_len];
}; };
int const header_size = 30; int const header_size = 30;
struct entry_t struct entry_t
{ {
char type [4]; char type [4];
byte made_by [2]; byte made_by [2];
byte vers [2]; byte vers [2];
byte flags [2]; byte flags [2];
byte method [2]; byte method [2];
byte date [4]; byte date [4];
byte crc [4]; byte crc [4];
byte raw_size [4]; byte raw_size [4];
byte size [4]; byte size [4];
byte filename_len [2]; byte filename_len [2];
byte extra_len [2]; byte extra_len [2];
byte comment_len [2]; byte comment_len [2];
byte disk [2]; byte disk [2];
byte int_attrib [2]; byte int_attrib [2];
byte ext_attrib [4]; byte ext_attrib [4];
byte file_offset [4]; byte file_offset [4];
char filename [2]; // [filename_len] char filename [2]; // [filename_len]
//char extra [extra_len]; //char extra [extra_len];
//char comment [comment_len]; //char comment [comment_len];
}; };
int const entry_size = 46; int const entry_size = 46;
struct end_entry_t struct end_entry_t
{ {
char type [4]; char type [4];
byte disk [2]; byte disk [2];
byte first_disk [2]; byte first_disk [2];
byte disk_entry_count [2]; byte disk_entry_count [2];
byte entry_count [2]; byte entry_count [2];
byte dir_size [4]; byte dir_size [4];
byte dir_offset [4]; byte dir_offset [4];
byte comment_len [2]; byte comment_len [2];
char comment [2]; // [comment_len] char comment [2]; // [comment_len]
}; };
int const end_entry_size = 22; int const end_entry_size = 22;
static blargg_err_t init_zip() static blargg_err_t init_zip()
{ {
get_crc_table(); // initialize zlib's CRC-32 tables get_crc_table(); // initialize zlib's CRC-32 tables
return blargg_ok; return blargg_ok;
} }
static File_Extractor* new_zip() static File_Extractor* new_zip()
{ {
return BLARGG_NEW Zip_Extractor; return BLARGG_NEW Zip_Extractor;
} }
fex_type_t_ const fex_zip_type [1] = {{ fex_type_t_ const fex_zip_type [1] = {{
".zip", ".zip",
&new_zip, &new_zip,
"ZIP archive", "ZIP archive",
&init_zip &init_zip
}}; }};
Zip_Extractor::Zip_Extractor() : Zip_Extractor::Zip_Extractor() :
File_Extractor( fex_zip_type ) File_Extractor( fex_zip_type )
{ {
Zip_Extractor::clear_file_v(); Zip_Extractor::clear_file_v();
// If these fail, structures had extra padding inserted by compiler // If these fail, structures had extra padding inserted by compiler
assert( offsetof (header_t,filename) == header_size ); assert( offsetof (header_t,filename) == header_size );
assert( offsetof (entry_t,filename) == entry_size ); assert( offsetof (entry_t,filename) == entry_size );
assert( offsetof (end_entry_t,comment) == end_entry_size ); assert( offsetof (end_entry_t,comment) == end_entry_size );
} }
Zip_Extractor::~Zip_Extractor() Zip_Extractor::~Zip_Extractor()
{ {
close(); close();
} }
blargg_err_t Zip_Extractor::open_path_v() blargg_err_t Zip_Extractor::open_path_v()
{ {
RETURN_ERR( open_arc_file( true ) ); RETURN_ERR( open_arc_file( true ) );
return File_Extractor::open_path_v(); return File_Extractor::open_path_v();
} }
inline inline
void Zip_Extractor::reorder_entry_header( int offset ) void Zip_Extractor::reorder_entry_header( int offset )
{ {
catalog [offset + 0] = 0; catalog [offset + 0] = 0;
catalog [offset + 4] = 'P'; catalog [offset + 4] = 'P';
} }
blargg_err_t Zip_Extractor::open_v() blargg_err_t Zip_Extractor::open_v()
{ {
if ( arc().size() < end_entry_size ) if ( arc().size() < end_entry_size )
return blargg_err_file_type; return blargg_err_file_type;
// Read final end_read_size bytes of file // Read final end_read_size bytes of file
int file_pos = max( 0, arc().size() - end_read_size ); int file_pos = max( 0, arc().size() - end_read_size );
file_pos -= file_pos % disk_block_size; file_pos -= file_pos % disk_block_size;
RETURN_ERR( catalog.resize( arc().size() - file_pos ) ); RETURN_ERR( catalog.resize( arc().size() - file_pos ) );
RETURN_ERR( arc().seek( file_pos ) ); RETURN_ERR( arc().seek( file_pos ) );
RETURN_ERR( arc().read( catalog.begin(), catalog.size() ) ); RETURN_ERR( arc().read( catalog.begin(), catalog.size() ) );
// Find end-of-catalog entry // Find end-of-catalog entry
int end_pos = catalog.size() - end_entry_size; int end_pos = catalog.size() - end_entry_size;
while ( end_pos >= 0 && memcmp( &catalog [end_pos], "PK\5\6", 4 ) ) while ( end_pos >= 0 && memcmp( &catalog [end_pos], "PK\5\6", 4 ) )
end_pos--; end_pos--;
if ( end_pos < 0 ) if ( end_pos < 0 )
return blargg_err_file_type; return blargg_err_file_type;
end_entry_t const& end_entry = (end_entry_t&) catalog [end_pos]; end_entry_t const& end_entry = (end_entry_t&) catalog [end_pos];
end_pos += file_pos; end_pos += file_pos;
// some idiotic zip compressors add data to end of zip without setting comment len // some idiotic zip compressors add data to end of zip without setting comment len
// check( arc().size() == end_pos + end_entry_size + get_le16( end_entry.comment_len ) ); // check( arc().size() == end_pos + end_entry_size + get_le16( end_entry.comment_len ) );
// Find file offset of beginning of catalog // Find file offset of beginning of catalog
catalog_begin = get_le32( end_entry.dir_offset ); catalog_begin = get_le32( end_entry.dir_offset );
int catalog_size = end_pos - catalog_begin; int catalog_size = end_pos - catalog_begin;
if ( catalog_size < 0 ) if ( catalog_size < 0 )
return blargg_err_file_corrupt; return blargg_err_file_corrupt;
catalog_size += end_entry_size; catalog_size += end_entry_size;
// See if catalog is entirely contained in bytes already read // See if catalog is entirely contained in bytes already read
int begin_offset = catalog_begin - file_pos; int begin_offset = catalog_begin - file_pos;
if ( begin_offset >= 0 ) if ( begin_offset >= 0 )
memmove( catalog.begin(), &catalog [begin_offset], catalog_size ); memmove( catalog.begin(), &catalog [begin_offset], catalog_size );
RETURN_ERR( catalog.resize( catalog_size ) ); RETURN_ERR( catalog.resize( catalog_size ) );
if ( begin_offset < 0 ) if ( begin_offset < 0 )
{ {
// Catalog begins before bytes read, so it needs to be read // Catalog begins before bytes read, so it needs to be read
RETURN_ERR( arc().seek( catalog_begin ) ); RETURN_ERR( arc().seek( catalog_begin ) );
RETURN_ERR( arc().read( catalog.begin(), catalog.size() ) ); RETURN_ERR( arc().read( catalog.begin(), catalog.size() ) );
} }
// First entry in catalog should be a file or end of archive // First entry in catalog should be a file or end of archive
if ( memcmp( catalog.begin(), "PK\1\2", 4 ) && memcmp( catalog.begin(), "PK\5\6", 4 ) ) if ( memcmp( catalog.begin(), "PK\1\2", 4 ) && memcmp( catalog.begin(), "PK\5\6", 4 ) )
return blargg_err_file_type; return blargg_err_file_type;
reorder_entry_header( 0 ); reorder_entry_header( 0 );
return rewind_v(); return rewind_v();
} }
void Zip_Extractor::close_v() void Zip_Extractor::close_v()
{ {
catalog.clear(); catalog.clear();
} }
// Scanning // Scanning
inline inline
static bool is_normal_file( entry_t const& e, unsigned len ) static bool is_normal_file( entry_t const& e, unsigned len )
{ {
int last_char = (len ? e.filename [len - 1] : '/'); int last_char = (len ? e.filename [len - 1] : '/');
bool is_dir = (last_char == '/' || last_char == '\\'); bool is_dir = (last_char == '/' || last_char == '\\');
if ( is_dir && get_le32( e.size ) == 0 ) if ( is_dir && get_le32( e.size ) == 0 )
return false; return false;
check( !is_dir ); check( !is_dir );
// Mac OS X puts meta-information in separate files with normal extensions, // Mac OS X puts meta-information in separate files with normal extensions,
// so they must be filtered out or caller will mistake them for normal files. // so they must be filtered out or caller will mistake them for normal files.
if ( e.made_by[1] == 3 ) if ( e.made_by[1] == 3 )
{ {
const char* dir = strrchr( e.filename, '/' ); const char* dir = strrchr( e.filename, '/' );
if ( dir ) if ( dir )
dir++; dir++;
else else
dir = e.filename; dir = e.filename;
if ( *dir == '.' ) if ( *dir == '.' )
return false; return false;
if ( !strcmp( dir, "Icon\x0D" ) ) if ( !strcmp( dir, "Icon\x0D" ) )
return false; return false;
} }
return true; return true;
} }
blargg_err_t Zip_Extractor::update_info( bool advance_first ) blargg_err_t Zip_Extractor::update_info( bool advance_first )
{ {
while ( 1 ) while ( 1 )
{ {
entry_t& e = (entry_t&) catalog [catalog_pos]; entry_t& e = (entry_t&) catalog [catalog_pos];
if ( memcmp( e.type, "\0K\1\2P", 5 ) && memcmp( e.type, "PK\1\2", 4 ) ) if ( memcmp( e.type, "\0K\1\2P", 5 ) && memcmp( e.type, "PK\1\2", 4 ) )
{ {
check( !memcmp( e.type, "\0K\5\6P", 5 ) ); check( !memcmp( e.type, "\0K\5\6P", 5 ) );
break; break;
} }
unsigned len = get_le16( e.filename_len ); unsigned len = get_le16( e.filename_len );
int next_offset = catalog_pos + entry_size + len + get_le16( e.extra_len ) + int next_offset = catalog_pos + entry_size + len + get_le16( e.extra_len ) +
get_le16( e.comment_len ); get_le16( e.comment_len );
if ( (unsigned) next_offset > catalog.size() - end_entry_size ) if ( (unsigned) next_offset > catalog.size() - end_entry_size )
return blargg_err_file_corrupt; return blargg_err_file_corrupt;
if ( catalog [next_offset] == 'P' ) if ( catalog [next_offset] == 'P' )
reorder_entry_header( next_offset ); reorder_entry_header( next_offset );
if ( !advance_first ) if ( !advance_first )
{ {
e.filename [len] = 0; // terminate name e.filename [len] = 0; // terminate name
if ( is_normal_file( e, len ) ) if ( is_normal_file( e, len ) )
{ {
set_name( e.filename ); set_name( e.filename );
set_info( get_le32( e.size ), get_le32( e.date ), get_le32( e.crc ) ); set_info( get_le32( e.size ), get_le32( e.date ), get_le32( e.crc ) );
break; break;
} }
} }
catalog_pos = next_offset; catalog_pos = next_offset;
advance_first = false; advance_first = false;
} }
return blargg_ok; return blargg_ok;
} }
blargg_err_t Zip_Extractor::next_v() blargg_err_t Zip_Extractor::next_v()
{ {
return update_info( true ); return update_info( true );
} }
blargg_err_t Zip_Extractor::rewind_v() blargg_err_t Zip_Extractor::rewind_v()
{ {
return seek_arc_v( 0 ); return seek_arc_v( 0 );
} }
fex_pos_t Zip_Extractor::tell_arc_v() const fex_pos_t Zip_Extractor::tell_arc_v() const
{ {
return catalog_pos; return catalog_pos;
} }
blargg_err_t Zip_Extractor::seek_arc_v( fex_pos_t pos ) blargg_err_t Zip_Extractor::seek_arc_v( fex_pos_t pos )
{ {
assert( 0 <= pos && (size_t) pos <= catalog.size() - end_entry_size ); assert( 0 <= pos && (size_t) pos <= catalog.size() - end_entry_size );
catalog_pos = pos; catalog_pos = pos;
return update_info( false ); return update_info( false );
} }
// Reading // Reading
void Zip_Extractor::clear_file_v() void Zip_Extractor::clear_file_v()
{ {
buf.end(); buf.end();
} }
blargg_err_t Zip_Extractor::inflater_read( void* data, void* out, int* count ) blargg_err_t Zip_Extractor::inflater_read( void* data, void* out, int* count )
{ {
Zip_Extractor& self = *STATIC_CAST(Zip_Extractor*,data); Zip_Extractor& self = *STATIC_CAST(Zip_Extractor*,data);
if ( *count > self.raw_remain ) if ( *count > self.raw_remain )
*count = self.raw_remain; *count = self.raw_remain;
self.raw_remain -= *count; self.raw_remain -= *count;
return self.arc().read( out, *count ); return self.arc().read( out, *count );
} }
blargg_err_t Zip_Extractor::fill_buf( int offset, int buf_size, int initial_read ) blargg_err_t Zip_Extractor::fill_buf( int offset, int buf_size, int initial_read )
{ {
raw_remain = arc().size() - offset; raw_remain = arc().size() - offset;
RETURN_ERR( arc().seek( offset ) ); RETURN_ERR( arc().seek( offset ) );
return buf.begin( inflater_read, this, buf_size, initial_read ); return buf.begin( inflater_read, this, buf_size, initial_read );
} }
blargg_err_t Zip_Extractor::first_read( int count ) blargg_err_t Zip_Extractor::first_read( int count )
{ {
entry_t const& e = (entry_t&) catalog [catalog_pos]; entry_t const& e = (entry_t&) catalog [catalog_pos];
// Determine compression // Determine compression
{ {
int method = get_le16( e.method ); int method = get_le16( e.method );
if ( (method && method != Z_DEFLATED) || get_le16( e.vers ) > 20 ) if ( (method && method != Z_DEFLATED) || get_le16( e.vers ) > 20 )
return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "compression method" ); return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "compression method" );
file_deflated = (method != 0); file_deflated = (method != 0);
} }
int raw_size = get_le32( e.raw_size ); int raw_size = get_le32( e.raw_size );
int file_offset = get_le32( e.file_offset ); int file_offset = get_le32( e.file_offset );
int align = file_offset % disk_block_size; int align = file_offset % disk_block_size;
{ {
// read header // read header
int buf_size = 3 * disk_block_size - 1 + raw_size; // space for all raw data int buf_size = 3 * disk_block_size - 1 + raw_size; // space for all raw data
buf_size -= buf_size % disk_block_size; buf_size -= buf_size % disk_block_size;
int initial_read = buf_size; int initial_read = buf_size;
if ( !file_deflated || count < size() ) if ( !file_deflated || count < size() )
{ {
buf_size = read_buf_size; buf_size = read_buf_size;
initial_read = disk_block_size * 2; initial_read = disk_block_size * 2;
} }
// TODO: avoid re-reading if buffer already has data we want? // TODO: avoid re-reading if buffer already has data we want?
RETURN_ERR( fill_buf( file_offset - align, buf_size, initial_read ) ); RETURN_ERR( fill_buf( file_offset - align, buf_size, initial_read ) );
} }
header_t const& h = (header_t&) buf.data() [align]; header_t const& h = (header_t&) buf.data() [align];
if ( buf.filled() < align + header_size || memcmp( h.type, "PK\3\4", 4 ) ) if ( buf.filled() < align + header_size || memcmp( h.type, "PK\3\4", 4 ) )
return blargg_err_file_corrupt; return blargg_err_file_corrupt;
// CRCs of header and file data // CRCs of header and file data
correct_crc = get_le32( h.crc ); correct_crc = get_le32( h.crc );
if ( !correct_crc ) if ( !correct_crc )
correct_crc = get_le32( e.crc ); correct_crc = get_le32( e.crc );
check( correct_crc == get_le32( e.crc ) ); // catalog CRC should match check( correct_crc == get_le32( e.crc ) ); // catalog CRC should match
crc = ::crc32( 0, NULL, 0 ); crc = ::crc32( 0, NULL, 0 );
// Data offset // Data offset
int data_offset = file_offset + header_size + int data_offset = file_offset + header_size +
get_le16( h.filename_len ) + get_le16( h.extra_len ); get_le16( h.filename_len ) + get_le16( h.extra_len );
if ( data_offset + raw_size > catalog_begin ) if ( data_offset + raw_size > catalog_begin )
return blargg_err_file_corrupt; return blargg_err_file_corrupt;
// Refill buffer if there's lots of extra data after header // Refill buffer if there's lots of extra data after header
int buf_offset = data_offset - file_offset + align; int buf_offset = data_offset - file_offset + align;
if ( buf_offset > buf.filled() ) if ( buf_offset > buf.filled() )
{ {
// TODO: this will almost never occur, making it a good place for bugs // TODO: this will almost never occur, making it a good place for bugs
buf_offset = data_offset % disk_block_size; buf_offset = data_offset % disk_block_size;
RETURN_ERR( fill_buf( data_offset - buf_offset, read_buf_size, disk_block_size ) ); RETURN_ERR( fill_buf( data_offset - buf_offset, read_buf_size, disk_block_size ) );
} }
raw_remain = raw_size - (buf.filled() - buf_offset); raw_remain = raw_size - (buf.filled() - buf_offset);
return buf.set_mode( (file_deflated ? buf.mode_raw_deflate : buf.mode_copy), buf_offset ); return buf.set_mode( (file_deflated ? buf.mode_raw_deflate : buf.mode_copy), buf_offset );
} }
blargg_err_t Zip_Extractor::extract_v( void* out, int count ) blargg_err_t Zip_Extractor::extract_v( void* out, int count )
{ {
if ( tell() == 0 ) if ( tell() == 0 )
RETURN_ERR( first_read( count ) ); RETURN_ERR( first_read( count ) );
int actual = count; int actual = count;
RETURN_ERR( buf.read( out, &actual ) ); RETURN_ERR( buf.read( out, &actual ) );
if ( actual < count ) if ( actual < count )
return blargg_err_file_corrupt; return blargg_err_file_corrupt;
crc = ::crc32( crc, (byte const*) out, count ); crc = ::crc32( crc, (byte const*) out, count );
if ( count == reader().remain() && crc != correct_crc ) if ( count == reader().remain() && crc != correct_crc )
return blargg_err_file_corrupt; return blargg_err_file_corrupt;
return blargg_ok; return blargg_ok;
} }

View File

@ -1,45 +1,45 @@
// ZIP archive extractor. Only supports deflation and store (no compression). // ZIP archive extractor. Only supports deflation and store (no compression).
// File_Extractor 1.0.0 // File_Extractor 1.0.0
#ifndef ZIP_EXTRACTOR_H #ifndef ZIP_EXTRACTOR_H
#define ZIP_EXTRACTOR_H #define ZIP_EXTRACTOR_H
#include "File_Extractor.h" #include "File_Extractor.h"
#include "Zlib_Inflater.h" #include "Zlib_Inflater.h"
class Zip_Extractor : public File_Extractor { class Zip_Extractor : public File_Extractor {
public: public:
Zip_Extractor(); Zip_Extractor();
virtual ~Zip_Extractor(); virtual ~Zip_Extractor();
protected: protected:
virtual blargg_err_t open_path_v(); virtual blargg_err_t open_path_v();
virtual blargg_err_t open_v(); virtual blargg_err_t open_v();
virtual void close_v(); virtual void close_v();
virtual void clear_file_v(); virtual void clear_file_v();
virtual blargg_err_t next_v(); virtual blargg_err_t next_v();
virtual blargg_err_t rewind_v(); virtual blargg_err_t rewind_v();
virtual fex_pos_t tell_arc_v() const; virtual fex_pos_t tell_arc_v() const;
virtual blargg_err_t seek_arc_v( fex_pos_t ); virtual blargg_err_t seek_arc_v( fex_pos_t );
virtual blargg_err_t extract_v( void*, int ); virtual blargg_err_t extract_v( void*, int );
private: private:
blargg_vector<char> catalog; blargg_vector<char> catalog;
int catalog_begin; // offset of first catalog entry in file (to detect corruption) int catalog_begin; // offset of first catalog entry in file (to detect corruption)
int catalog_pos; // position of current entry in catalog int catalog_pos; // position of current entry in catalog
int raw_remain; // bytes remaining to be read from zip file for current file int raw_remain; // bytes remaining to be read from zip file for current file
unsigned crc; // ongoing CRC of extracted bytes unsigned crc; // ongoing CRC of extracted bytes
unsigned correct_crc; unsigned correct_crc;
bool file_deflated; bool file_deflated;
Zlib_Inflater buf; Zlib_Inflater buf;
blargg_err_t fill_buf( int offset, int buf_size, int initial_read ); blargg_err_t fill_buf( int offset, int buf_size, int initial_read );
blargg_err_t update_info( bool advance_first ); blargg_err_t update_info( bool advance_first );
blargg_err_t first_read( int count ); blargg_err_t first_read( int count );
void reorder_entry_header( int offset ); void reorder_entry_header( int offset );
static blargg_err_t inflater_read( void* data, void* out, int* count ); static blargg_err_t inflater_read( void* data, void* out, int* count );
}; };
#endif #endif

View File

@ -1,257 +1,257 @@
// File_Extractor 1.0.0. http://www.slack.net/~ant/ // File_Extractor 1.0.0. http://www.slack.net/~ant/
#include "Zlib_Inflater.h" #include "Zlib_Inflater.h"
/* Copyright (C) 2006-2009 Shay Green. This module is free software; you /* Copyright (C) 2006-2009 Shay Green. This module is free software; you
can redistribute it and/or modify it under the terms of the GNU Lesser can redistribute it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software Foundation; either General Public License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version. This version 2.1 of the License, or (at your option) any later version. This
module is distributed in the hope that it will be useful, but WITHOUT ANY module is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details. You should have received a copy of the GNU Lesser General Public details. You should have received a copy of the GNU Lesser General Public
License along with this module; if not, write to the Free Software Foundation, License along with this module; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
#include "blargg_source.h" #include "blargg_source.h"
int const block_size = 4096; int const block_size = 4096;
static const char* get_zlib_err( int code ) static const char* get_zlib_err( int code )
{ {
assert( code != Z_OK ); assert( code != Z_OK );
switch ( code ) switch ( code )
{ {
case Z_MEM_ERROR: return blargg_err_memory; case Z_MEM_ERROR: return blargg_err_memory;
case Z_DATA_ERROR: return blargg_err_file_corrupt; case Z_DATA_ERROR: return blargg_err_file_corrupt;
// TODO: handle more error codes // TODO: handle more error codes
} }
const char* str = zError( code ); const char* str = zError( code );
if ( !str ) if ( !str )
str = BLARGG_ERR( BLARGG_ERR_GENERIC, "problem unzipping data" ); str = BLARGG_ERR( BLARGG_ERR_GENERIC, "problem unzipping data" );
return str; return str;
} }
void Zlib_Inflater::end() void Zlib_Inflater::end()
{ {
if ( deflated_ ) if ( deflated_ )
{ {
deflated_ = false; deflated_ = false;
if ( inflateEnd( &zbuf ) ) if ( inflateEnd( &zbuf ) )
check( false ); check( false );
} }
buf.clear(); buf.clear();
static z_stream const empty = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static z_stream const empty = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
memcpy( &zbuf, &empty, sizeof zbuf ); memcpy( &zbuf, &empty, sizeof zbuf );
} }
Zlib_Inflater::Zlib_Inflater() Zlib_Inflater::Zlib_Inflater()
{ {
deflated_ = false; deflated_ = false;
end(); // initialize things end(); // initialize things
} }
Zlib_Inflater::~Zlib_Inflater() Zlib_Inflater::~Zlib_Inflater()
{ {
end(); end();
} }
blargg_err_t Zlib_Inflater::fill_buf( int count ) blargg_err_t Zlib_Inflater::fill_buf( int count )
{ {
byte* out = buf.end() - count; byte* out = buf.end() - count;
RETURN_ERR( callback( user_data, out, &count ) ); RETURN_ERR( callback( user_data, out, &count ) );
zbuf.avail_in = count; zbuf.avail_in = count;
zbuf.next_in = out; zbuf.next_in = out;
return blargg_ok; return blargg_ok;
} }
blargg_err_t Zlib_Inflater::begin( callback_t new_callback, void* new_user_data, blargg_err_t Zlib_Inflater::begin( callback_t new_callback, void* new_user_data,
int new_buf_size, int initial_read ) int new_buf_size, int initial_read )
{ {
callback = new_callback; callback = new_callback;
user_data = new_user_data; user_data = new_user_data;
end(); end();
// TODO: decide whether using different size on alloc failure is a good idea // TODO: decide whether using different size on alloc failure is a good idea
//RETURN_ERR( buf.resize( new_buf_size ? new_buf_size : 4 * block_size ) ); //RETURN_ERR( buf.resize( new_buf_size ? new_buf_size : 4 * block_size ) );
if ( new_buf_size && buf.resize( new_buf_size ) ) if ( new_buf_size && buf.resize( new_buf_size ) )
{ {
ACK_FAILURE(); ACK_FAILURE();
new_buf_size = 0; new_buf_size = 0;
} }
if ( !new_buf_size ) if ( !new_buf_size )
{ {
RETURN_ERR( buf.resize( 4 * block_size ) ); RETURN_ERR( buf.resize( 4 * block_size ) );
initial_read = 0; initial_read = 0;
} }
// Fill buffer with some data, less than normal buffer size since caller might // Fill buffer with some data, less than normal buffer size since caller might
// just be examining beginning of file. // just be examining beginning of file.
return fill_buf( initial_read ? initial_read : block_size ); return fill_buf( initial_read ? initial_read : block_size );
} }
blargg_err_t Zlib_Inflater::set_mode( mode_t mode, int data_offset ) blargg_err_t Zlib_Inflater::set_mode( mode_t mode, int data_offset )
{ {
zbuf.next_in += data_offset; zbuf.next_in += data_offset;
zbuf.avail_in -= data_offset; zbuf.avail_in -= data_offset;
if ( mode == mode_auto ) if ( mode == mode_auto )
{ {
// examine buffer for gzip header // examine buffer for gzip header
mode = mode_copy; mode = mode_copy;
unsigned const min_gzip_size = 2 + 8 + 8; unsigned const min_gzip_size = 2 + 8 + 8;
if ( zbuf.avail_in >= min_gzip_size && if ( zbuf.avail_in >= min_gzip_size &&
zbuf.next_in [0] == 0x1F && zbuf.next_in [1] == 0x8B ) zbuf.next_in [0] == 0x1F && zbuf.next_in [1] == 0x8B )
mode = mode_ungz; mode = mode_ungz;
} }
if ( mode != mode_copy ) if ( mode != mode_copy )
{ {
int wb = MAX_WBITS + 16; // have zlib handle gzip header int wb = MAX_WBITS + 16; // have zlib handle gzip header
if ( mode == mode_raw_deflate ) if ( mode == mode_raw_deflate )
wb = -MAX_WBITS; wb = -MAX_WBITS;
int zerr = inflateInit2( &zbuf, wb ); int zerr = inflateInit2( &zbuf, wb );
if ( zerr ) if ( zerr )
{ {
zbuf.next_in = NULL; zbuf.next_in = NULL;
return get_zlib_err( zerr ); return get_zlib_err( zerr );
} }
deflated_ = true; deflated_ = true;
} }
return blargg_ok; return blargg_ok;
} }
/* /*
// Reads/inflates entire stream. All input must be in buffer, and count must be total // Reads/inflates entire stream. All input must be in buffer, and count must be total
// of all output. // of all output.
blargg_err_t read_all( void* out, int count ); blargg_err_t read_all( void* out, int count );
// zlib automatically applies this optimization (uses inflateFast) // zlib automatically applies this optimization (uses inflateFast)
// TODO: remove // TODO: remove
blargg_err_t Zlib_Inflater::read_all( void* out, int count ) blargg_err_t Zlib_Inflater::read_all( void* out, int count )
{ {
if ( deflated_ ) if ( deflated_ )
{ {
zbuf.next_out = (Bytef*) out; zbuf.next_out = (Bytef*) out;
zbuf.avail_out = count; zbuf.avail_out = count;
int err = inflate( &zbuf, Z_FINISH ); int err = inflate( &zbuf, Z_FINISH );
if ( zbuf.avail_out || err != Z_STREAM_END ) if ( zbuf.avail_out || err != Z_STREAM_END )
return blargg_err_file_corrupt; return blargg_err_file_corrupt;
} }
else else
{ {
if ( zbuf.avail_in < count ) if ( zbuf.avail_in < count )
return blargg_err_file_corrupt; return blargg_err_file_corrupt;
memcpy( out, zbuf.next_in, count ); memcpy( out, zbuf.next_in, count );
zbuf.next_in += count; zbuf.next_in += count;
zbuf.avail_in -= count; zbuf.avail_in -= count;
} }
return blargg_ok; return blargg_ok;
} }
*/ */
blargg_err_t Zlib_Inflater::read( void* out, int* count_io ) blargg_err_t Zlib_Inflater::read( void* out, int* count_io )
{ {
int remain = *count_io; int remain = *count_io;
if ( remain && zbuf.next_in ) if ( remain && zbuf.next_in )
{ {
if ( deflated_ ) if ( deflated_ )
{ {
zbuf.next_out = (Bytef*) out; zbuf.next_out = (Bytef*) out;
zbuf.avail_out = remain; zbuf.avail_out = remain;
while ( 1 ) while ( 1 )
{ {
uInt old_avail_in = zbuf.avail_in; uInt old_avail_in = zbuf.avail_in;
int err = inflate( &zbuf, Z_NO_FLUSH ); int err = inflate( &zbuf, Z_NO_FLUSH );
if ( err == Z_STREAM_END ) if ( err == Z_STREAM_END )
{ {
remain = zbuf.avail_out; remain = zbuf.avail_out;
end(); end();
break; // no more data to inflate break; // no more data to inflate
} }
if ( err && (err != Z_BUF_ERROR || old_avail_in) ) if ( err && (err != Z_BUF_ERROR || old_avail_in) )
return get_zlib_err( err ); return get_zlib_err( err );
if ( !zbuf.avail_out ) if ( !zbuf.avail_out )
{ {
remain = 0; remain = 0;
break; // requested number of bytes inflated break; // requested number of bytes inflated
} }
if ( zbuf.avail_in ) if ( zbuf.avail_in )
{ {
// inflate() should never leave input if there's still space for output // inflate() should never leave input if there's still space for output
check( false ); check( false );
return blargg_err_file_corrupt; return blargg_err_file_corrupt;
} }
RETURN_ERR( fill_buf( buf.size() ) ); RETURN_ERR( fill_buf( buf.size() ) );
if ( !zbuf.avail_in ) if ( !zbuf.avail_in )
return blargg_err_file_corrupt; // stream didn't end but there's no more data return blargg_err_file_corrupt; // stream didn't end but there's no more data
} }
} }
else else
{ {
while ( 1 ) while ( 1 )
{ {
// copy buffered data // copy buffered data
if ( zbuf.avail_in ) if ( zbuf.avail_in )
{ {
long count = zbuf.avail_in; long count = zbuf.avail_in;
if ( count > remain ) if ( count > remain )
count = remain; count = remain;
memcpy( out, zbuf.next_in, count ); memcpy( out, zbuf.next_in, count );
zbuf.total_out += count; zbuf.total_out += count;
out = (char*) out + count; out = (char*) out + count;
remain -= count; remain -= count;
zbuf.next_in += count; zbuf.next_in += count;
zbuf.avail_in -= count; zbuf.avail_in -= count;
} }
if ( !zbuf.avail_in && zbuf.next_in < buf.end() ) if ( !zbuf.avail_in && zbuf.next_in < buf.end() )
{ {
end(); end();
break; break;
} }
// read large request directly // read large request directly
if ( remain + zbuf.total_out % block_size >= buf.size() ) if ( remain + zbuf.total_out % block_size >= buf.size() )
{ {
int count = remain; int count = remain;
RETURN_ERR( callback( user_data, out, &count ) ); RETURN_ERR( callback( user_data, out, &count ) );
zbuf.total_out += count; zbuf.total_out += count;
out = (char*) out + count; out = (char*) out + count;
remain -= count; remain -= count;
if ( remain ) if ( remain )
{ {
end(); end();
break; break;
} }
} }
if ( !remain ) if ( !remain )
break; break;
RETURN_ERR( fill_buf( buf.size() - zbuf.total_out % block_size ) ); RETURN_ERR( fill_buf( buf.size() - zbuf.total_out % block_size ) );
} }
} }
} }
*count_io -= remain; *count_io -= remain;
return blargg_ok; return blargg_ok;
} }

View File

@ -1,70 +1,70 @@
// Simplifies use of zlib for inflating data // Simplifies use of zlib for inflating data
// File_Extractor 1.0.0 // File_Extractor 1.0.0
#ifndef ZLIB_INFLATER_H #ifndef ZLIB_INFLATER_H
#define ZLIB_INFLATER_H #define ZLIB_INFLATER_H
#include "blargg_common.h" #include "blargg_common.h"
#include "Data_Reader.h" #include "Data_Reader.h"
#include "zlib.h" #include "zlib.h"
class Zlib_Inflater { class Zlib_Inflater {
public: public:
// Reads at most min(*count,bytes_until_eof()) bytes into *out and set *count // Reads at most min(*count,bytes_until_eof()) bytes into *out and set *count
// to that number, or returns error if that many can't be read. // to that number, or returns error if that many can't be read.
typedef blargg_err_t (*callback_t)( void* user_data, void* out, int* count ); typedef blargg_err_t (*callback_t)( void* user_data, void* out, int* count );
// Begins by setting callback and filling buffer. Default buffer is 16K and // Begins by setting callback and filling buffer. Default buffer is 16K and
// filled to 4K, or specify buf_size and initial_read for custom buffer size // filled to 4K, or specify buf_size and initial_read for custom buffer size
// and how much to read initially. // and how much to read initially.
blargg_err_t begin( callback_t, void* user_data, blargg_err_t begin( callback_t, void* user_data,
int buf_size = 0, int initial_read = 0 ); int buf_size = 0, int initial_read = 0 );
// Data read into buffer by begin() // Data read into buffer by begin()
const unsigned char* data() const { return zbuf.next_in; } const unsigned char* data() const { return zbuf.next_in; }
int filled() const { return zbuf.avail_in; } int filled() const { return zbuf.avail_in; }
// Begins inflation using specified mode. Using mode_auto selects between // Begins inflation using specified mode. Using mode_auto selects between
// mode_copy and mode_ungz by examining first two bytes of buffer. Use // mode_copy and mode_ungz by examining first two bytes of buffer. Use
// buf_offset to specify where data begins in buffer, in case there is // buf_offset to specify where data begins in buffer, in case there is
// header data that should be skipped. // header data that should be skipped.
enum mode_t { mode_copy, mode_ungz, mode_raw_deflate, mode_auto }; enum mode_t { mode_copy, mode_ungz, mode_raw_deflate, mode_auto };
blargg_err_t set_mode( mode_t, int buf_offset = 0 ); blargg_err_t set_mode( mode_t, int buf_offset = 0 );
// True if set_mode() has been called with mode_ungz or mode_raw_deflate // True if set_mode() has been called with mode_ungz or mode_raw_deflate
bool deflated() const { return deflated_; } bool deflated() const { return deflated_; }
// Reads/inflates at most *count_io bytes into *out and sets *count_io to actual // Reads/inflates at most *count_io bytes into *out and sets *count_io to actual
// number of bytes read (less than requested if end of data was reached). // number of bytes read (less than requested if end of data was reached).
// Buffers source data internally, even in copy mode, so input file can be // Buffers source data internally, even in copy mode, so input file can be
// unbuffered without sacrificing performance. // unbuffered without sacrificing performance.
blargg_err_t read( void* out, int* count_io ); blargg_err_t read( void* out, int* count_io );
// Total number of bytes read since begin() // Total number of bytes read since begin()
int tell() const { return zbuf.total_out; } int tell() const { return zbuf.total_out; }
// Ends inflation and frees memory // Ends inflation and frees memory
void end(); void end();
private: private:
// noncopyable // noncopyable
Zlib_Inflater( const Zlib_Inflater& ); Zlib_Inflater( const Zlib_Inflater& );
Zlib_Inflater& operator = ( const Zlib_Inflater& ); Zlib_Inflater& operator = ( const Zlib_Inflater& );
// Implementation // Implementation
public: public:
Zlib_Inflater(); Zlib_Inflater();
~Zlib_Inflater(); ~Zlib_Inflater();
private: private:
z_stream_s zbuf; z_stream_s zbuf;
blargg_vector<unsigned char> buf; blargg_vector<unsigned char> buf;
bool deflated_; bool deflated_;
callback_t callback; callback_t callback;
void* user_data; void* user_data;
blargg_err_t fill_buf( int count ); blargg_err_t fill_buf( int count );
}; };
#endif #endif

View File

@ -1,51 +1,51 @@
// File_Extractor 1.0.0. http://www.slack.net/~ant/ // File_Extractor 1.0.0. http://www.slack.net/~ant/
#include "blargg_common.h" #include "blargg_common.h"
/* Copyright (C) 2008-2009 Shay Green. This module is free software; you /* Copyright (C) 2008-2009 Shay Green. This module is free software; you
can redistribute it and/or modify it under the terms of the GNU Lesser can redistribute it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software Foundation; either General Public License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version. This version 2.1 of the License, or (at your option) any later version. This
module is distributed in the hope that it will be useful, but WITHOUT ANY module is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details. You should have received a copy of the GNU Lesser General Public details. You should have received a copy of the GNU Lesser General Public
License along with this module; if not, write to the Free Software Foundation, License along with this module; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
#include "blargg_source.h" #include "blargg_source.h"
void blargg_vector_::init() void blargg_vector_::init()
{ {
begin_ = NULL; begin_ = NULL;
size_ = 0; size_ = 0;
} }
void blargg_vector_::clear() void blargg_vector_::clear()
{ {
void* p = begin_; void* p = begin_;
begin_ = NULL; begin_ = NULL;
size_ = 0; size_ = 0;
free( p ); free( p );
} }
blargg_err_t blargg_vector_::resize_( size_t n, size_t elem_size ) blargg_err_t blargg_vector_::resize_( size_t n, size_t elem_size )
{ {
if ( n != size_ ) if ( n != size_ )
{ {
if ( n == 0 ) if ( n == 0 )
{ {
// Simpler to handle explicitly. Realloc will handle a size of 0, // Simpler to handle explicitly. Realloc will handle a size of 0,
// but then we have to avoid raising an error for a NULL return. // but then we have to avoid raising an error for a NULL return.
clear(); clear();
} }
else else
{ {
void* p = realloc( begin_, n * elem_size ); void* p = realloc( begin_, n * elem_size );
CHECK_ALLOC( p ); CHECK_ALLOC( p );
begin_ = p; begin_ = p;
size_ = n; size_ = n;
} }
} }
return blargg_ok; return blargg_ok;
} }

View File

@ -1,201 +1,201 @@
// Sets up common environment for Shay Green's libraries. // Sets up common environment for Shay Green's libraries.
// To change configuration options, modify blargg_config.h, not this file. // To change configuration options, modify blargg_config.h, not this file.
// File_Extractor 1.0.0 // File_Extractor 1.0.0
#ifndef BLARGG_COMMON_H #ifndef BLARGG_COMMON_H
#define BLARGG_COMMON_H #define BLARGG_COMMON_H
#include <stdlib.h> #include <stdlib.h>
#include <assert.h> #include <assert.h>
#include <limits.h> #include <limits.h>
typedef const char* blargg_err_t; // 0 on success, otherwise error string typedef const char* blargg_err_t; // 0 on success, otherwise error string
// Success; no error // Success; no error
int const blargg_ok = 0; int const blargg_ok = 0;
// BLARGG_RESTRICT: equivalent to C99's restrict, where supported // BLARGG_RESTRICT: equivalent to C99's restrict, where supported
#if __GNUC__ >= 3 || _MSC_VER >= 1100 #if __GNUC__ >= 3 || _MSC_VER >= 1100
#define BLARGG_RESTRICT __restrict #define BLARGG_RESTRICT __restrict
#else #else
#define BLARGG_RESTRICT #define BLARGG_RESTRICT
#endif #endif
#if __cplusplus >= 199711 #if __cplusplus >= 199711
#define BLARGG_MUTABLE mutable #define BLARGG_MUTABLE mutable
#else #else
#define BLARGG_MUTABLE #define BLARGG_MUTABLE
#endif #endif
/* BLARGG_4CHAR('a','b','c','d') = 'abcd' (four character integer constant). /* BLARGG_4CHAR('a','b','c','d') = 'abcd' (four character integer constant).
I don't just use 'abcd' because that's implementation-dependent. */ I don't just use 'abcd' because that's implementation-dependent. */
#define BLARGG_4CHAR( a, b, c, d ) \ #define BLARGG_4CHAR( a, b, c, d ) \
((a&0xFF)*0x1000000 + (b&0xFF)*0x10000 + (c&0xFF)*0x100 + (d&0xFF)) ((a&0xFF)*0x1000000 + (b&0xFF)*0x10000 + (c&0xFF)*0x100 + (d&0xFF))
/* BLARGG_STATIC_ASSERT( expr ): Generates compile error if expr is 0. /* BLARGG_STATIC_ASSERT( expr ): Generates compile error if expr is 0.
Can be used at file, function, or class scope. */ Can be used at file, function, or class scope. */
#ifdef _MSC_VER #ifdef _MSC_VER
// MSVC6 (_MSC_VER < 1300) __LINE__ fails when /Zl is specified // MSVC6 (_MSC_VER < 1300) __LINE__ fails when /Zl is specified
#define BLARGG_STATIC_ASSERT( expr ) \ #define BLARGG_STATIC_ASSERT( expr ) \
void blargg_failed_( int (*arg) [2 / (int) !!(expr) - 1] ) void blargg_failed_( int (*arg) [2 / (int) !!(expr) - 1] )
#else #else
// Others fail when declaring same function multiple times in class, // Others fail when declaring same function multiple times in class,
// so differentiate them by line // so differentiate them by line
#define BLARGG_STATIC_ASSERT( expr ) \ #define BLARGG_STATIC_ASSERT( expr ) \
void blargg_failed_( int (*arg) [2 / !!(expr) - 1] [__LINE__] ) void blargg_failed_( int (*arg) [2 / !!(expr) - 1] [__LINE__] )
#endif #endif
/* Pure virtual functions cause a vtable entry to a "called pure virtual" /* Pure virtual functions cause a vtable entry to a "called pure virtual"
error handler, requiring linkage to the C++ runtime library. This macro is error handler, requiring linkage to the C++ runtime library. This macro is
used in place of the "= 0", and simply expands to its argument. During used in place of the "= 0", and simply expands to its argument. During
development, it expands to "= 0", allowing detection of missing overrides. */ development, it expands to "= 0", allowing detection of missing overrides. */
#define BLARGG_PURE( def ) def #define BLARGG_PURE( def ) def
/* My code depends on ASCII anywhere a character or string constant is /* My code depends on ASCII anywhere a character or string constant is
compared with data read from a file, and anywhere file data is read and compared with data read from a file, and anywhere file data is read and
treated as a string. */ treated as a string. */
#if '\n'!=0x0A || ' '!=0x20 || '0'!=0x30 || 'A'!=0x41 || 'a'!=0x61 #if '\n'!=0x0A || ' '!=0x20 || '0'!=0x30 || 'A'!=0x41 || 'a'!=0x61
#error "ASCII character set required" #error "ASCII character set required"
#endif #endif
/* My code depends on int being at least 32 bits. Almost everything these days /* My code depends on int being at least 32 bits. Almost everything these days
uses at least 32-bit ints, so it's hard to even find a system with 16-bit ints uses at least 32-bit ints, so it's hard to even find a system with 16-bit ints
to test with. The issue can't be gotten around by using a suitable blargg_int to test with. The issue can't be gotten around by using a suitable blargg_int
everywhere either, because int is often converted to implicitly when doing everywhere either, because int is often converted to implicitly when doing
arithmetic on smaller types. */ arithmetic on smaller types. */
#if UINT_MAX < 0xFFFFFFFF #if UINT_MAX < 0xFFFFFFFF
#error "int must be at least 32 bits" #error "int must be at least 32 bits"
#endif #endif
// In case compiler doesn't support these properly. Used rarely. // In case compiler doesn't support these properly. Used rarely.
#define STATIC_CAST(T,expr) static_cast<T> (expr) #define STATIC_CAST(T,expr) static_cast<T> (expr)
#define CONST_CAST( T,expr) const_cast<T> (expr) #define CONST_CAST( T,expr) const_cast<T> (expr)
// User configuration can override the above macros if necessary // User configuration can override the above macros if necessary
#include "blargg_config.h" #include "blargg_config.h"
/* BLARGG_DEPRECATED [_TEXT] for any declarations/text to be removed in a /* BLARGG_DEPRECATED [_TEXT] for any declarations/text to be removed in a
future version. In GCC, we can let the compiler warn. In other compilers, future version. In GCC, we can let the compiler warn. In other compilers,
we strip it out unless BLARGG_LEGACY is true. */ we strip it out unless BLARGG_LEGACY is true. */
#if BLARGG_LEGACY #if BLARGG_LEGACY
// Allow old client code to work without warnings // Allow old client code to work without warnings
#define BLARGG_DEPRECATED_TEXT( text ) text #define BLARGG_DEPRECATED_TEXT( text ) text
#define BLARGG_DEPRECATED( text ) text #define BLARGG_DEPRECATED( text ) text
#elif __GNUC__ >= 4 #elif __GNUC__ >= 4
// In GCC, we can mark declarations and let the compiler warn // In GCC, we can mark declarations and let the compiler warn
#define BLARGG_DEPRECATED_TEXT( text ) text #define BLARGG_DEPRECATED_TEXT( text ) text
#define BLARGG_DEPRECATED( text ) __attribute__ ((deprecated)) text #define BLARGG_DEPRECATED( text ) __attribute__ ((deprecated)) text
#else #else
// By default, deprecated items are removed, to avoid use in new code // By default, deprecated items are removed, to avoid use in new code
#define BLARGG_DEPRECATED_TEXT( text ) #define BLARGG_DEPRECATED_TEXT( text )
#define BLARGG_DEPRECATED( text ) #define BLARGG_DEPRECATED( text )
#endif #endif
/* BOOST::int8_t, BOOST::int32_t, etc. /* BOOST::int8_t, BOOST::int32_t, etc.
I used BOOST since I originally was going to allow use of the boost library I used BOOST since I originally was going to allow use of the boost library
for prividing the definitions. If I'm defining them, they must be scoped or for prividing the definitions. If I'm defining them, they must be scoped or
else they could conflict with the standard ones at global scope. Even if else they could conflict with the standard ones at global scope. Even if
HAVE_STDINT_H isn't defined, I can't assume the typedefs won't exist at HAVE_STDINT_H isn't defined, I can't assume the typedefs won't exist at
global scope already. */ global scope already. */
#if defined (HAVE_STDINT_H) || \ #if defined (HAVE_STDINT_H) || \
UCHAR_MAX != 0xFF || USHRT_MAX != 0xFFFF || UINT_MAX != 0xFFFFFFFF UCHAR_MAX != 0xFF || USHRT_MAX != 0xFFFF || UINT_MAX != 0xFFFFFFFF
#include <stdint.h> #include <stdint.h>
#define BOOST #define BOOST
#else #else
struct BOOST struct BOOST
{ {
typedef signed char int8_t; typedef signed char int8_t;
typedef unsigned char uint8_t; typedef unsigned char uint8_t;
typedef short int16_t; typedef short int16_t;
typedef unsigned short uint16_t; typedef unsigned short uint16_t;
typedef int int32_t; typedef int int32_t;
typedef unsigned int uint32_t; typedef unsigned int uint32_t;
}; };
#endif #endif
/* My code is not written with exceptions in mind, so either uses new (nothrow) /* My code is not written with exceptions in mind, so either uses new (nothrow)
OR overrides operator new in my classes. The former is best since clients OR overrides operator new in my classes. The former is best since clients
creating objects will get standard exceptions on failure, but that causes it creating objects will get standard exceptions on failure, but that causes it
to require the standard C++ library. So, when the client is using the C to require the standard C++ library. So, when the client is using the C
interface, I override operator new to use malloc. */ interface, I override operator new to use malloc. */
// BLARGG_DISABLE_NOTHROW is put inside classes // BLARGG_DISABLE_NOTHROW is put inside classes
#ifndef BLARGG_DISABLE_NOTHROW #ifndef BLARGG_DISABLE_NOTHROW
// throw spec mandatory in ISO C++ if NULL can be returned // throw spec mandatory in ISO C++ if NULL can be returned
#if __cplusplus >= 199711 || __GNUC__ >= 3 || _MSC_VER >= 1300 #if __cplusplus >= 199711 || __GNUC__ >= 3 || _MSC_VER >= 1300
#define BLARGG_THROWS_NOTHING throw () #define BLARGG_THROWS_NOTHING throw ()
#else #else
#define BLARGG_THROWS_NOTHING #define BLARGG_THROWS_NOTHING
#endif #endif
#define BLARGG_DISABLE_NOTHROW \ #define BLARGG_DISABLE_NOTHROW \
void* operator new ( size_t s ) BLARGG_THROWS_NOTHING { return malloc( s ); }\ void* operator new ( size_t s ) BLARGG_THROWS_NOTHING { return malloc( s ); }\
void operator delete( void* p ) BLARGG_THROWS_NOTHING { free( p ); } void operator delete( void* p ) BLARGG_THROWS_NOTHING { free( p ); }
#define BLARGG_NEW new #define BLARGG_NEW new
#else #else
// BLARGG_NEW is used in place of new in library code // BLARGG_NEW is used in place of new in library code
#include <new> #include <new>
#define BLARGG_NEW new (std::nothrow) #define BLARGG_NEW new (std::nothrow)
#endif #endif
class blargg_vector_ { class blargg_vector_ {
protected: protected:
void* begin_; void* begin_;
size_t size_; size_t size_;
void init(); void init();
blargg_err_t resize_( size_t n, size_t elem_size ); blargg_err_t resize_( size_t n, size_t elem_size );
public: public:
size_t size() const { return size_; } size_t size() const { return size_; }
void clear(); void clear();
}; };
// Very lightweight vector for POD types (no constructor/destructor) // Very lightweight vector for POD types (no constructor/destructor)
template<class T> template<class T>
class blargg_vector : public blargg_vector_ { class blargg_vector : public blargg_vector_ {
union T_must_be_pod { T t; }; // fails if T is not POD union T_must_be_pod { T t; }; // fails if T is not POD
public: public:
blargg_vector() { init(); } blargg_vector() { init(); }
~blargg_vector() { clear(); } ~blargg_vector() { clear(); }
blargg_err_t resize( size_t n ) { return resize_( n, sizeof (T) ); } blargg_err_t resize( size_t n ) { return resize_( n, sizeof (T) ); }
T* begin() { return static_cast<T*> (begin_); } T* begin() { return static_cast<T*> (begin_); }
const T* begin() const { return static_cast<T*> (begin_); } const T* begin() const { return static_cast<T*> (begin_); }
T* end() { return static_cast<T*> (begin_) + size_; } T* end() { return static_cast<T*> (begin_) + size_; }
const T* end() const { return static_cast<T*> (begin_) + size_; } const T* end() const { return static_cast<T*> (begin_) + size_; }
T& operator [] ( size_t n ) T& operator [] ( size_t n )
{ {
assert( n < size_ ); assert( n < size_ );
return static_cast<T*> (begin_) [n]; return static_cast<T*> (begin_) [n];
} }
const T& operator [] ( size_t n ) const const T& operator [] ( size_t n ) const
{ {
assert( n < size_ ); assert( n < size_ );
return static_cast<T*> (begin_) [n]; return static_cast<T*> (begin_) [n];
} }
}; };
// Callback function with user data. // Callback function with user data.
// blargg_callback<T> set_callback; // for user, this acts like... // blargg_callback<T> set_callback; // for user, this acts like...
// void set_callback( T func, void* user_data = NULL ); // ...this // void set_callback( T func, void* user_data = NULL ); // ...this
// To call function, do set_callback.f( .. set_callback.data ... ); // To call function, do set_callback.f( .. set_callback.data ... );
template<class T> template<class T>
struct blargg_callback struct blargg_callback
{ {
T f; T f;
void* data; void* data;
blargg_callback() { f = NULL; } blargg_callback() { f = NULL; }
void operator () ( T callback, void* user_data = NULL ) { f = callback; data = user_data; } void operator () ( T callback, void* user_data = NULL ) { f = callback; data = user_data; }
}; };
BLARGG_DEPRECATED( typedef signed int blargg_long; ) BLARGG_DEPRECATED( typedef signed int blargg_long; )
BLARGG_DEPRECATED( typedef unsigned int blargg_ulong; ) BLARGG_DEPRECATED( typedef unsigned int blargg_ulong; )
#if BLARGG_LEGACY #if BLARGG_LEGACY
#define BOOST_STATIC_ASSERT BLARGG_STATIC_ASSERT #define BOOST_STATIC_ASSERT BLARGG_STATIC_ASSERT
#endif #endif
#endif #endif

View File

@ -1,31 +1,31 @@
// Library configuration. Modify this file as necessary. // Library configuration. Modify this file as necessary.
// File_Extractor 1.0.0 // File_Extractor 1.0.0
#ifndef BLARGG_CONFIG_H #ifndef BLARGG_CONFIG_H
#define BLARGG_CONFIG_H #define BLARGG_CONFIG_H
// Uncomment a #define line below to have effect described. // Uncomment a #define line below to have effect described.
// Enable RAR archive support. Doing so adds extra licensing restrictions // Enable RAR archive support. Doing so adds extra licensing restrictions
// to this library (see unrar/readme.txt for more information). // to this library (see unrar/readme.txt for more information).
//#define FEX_ENABLE_RAR 1 //#define FEX_ENABLE_RAR 1
// Accept file paths encoded as UTF-8. Currently only affects Windows, // Accept file paths encoded as UTF-8. Currently only affects Windows,
// as Unix/Linux/Mac OS X already use UTF-8 paths. // as Unix/Linux/Mac OS X already use UTF-8 paths.
//#define BLARGG_UTF8_PATHS 1 //#define BLARGG_UTF8_PATHS 1
// Enable support for as building DLL on Windows. // Enable support for as building DLL on Windows.
//#define BLARGG_BUILD_DLL 1 //#define BLARGG_BUILD_DLL 1
// Support only the listed archive types. Remove any you don't need. // Support only the listed archive types. Remove any you don't need.
#define FEX_TYPE_LIST \ #define FEX_TYPE_LIST \
fex_7z_type,\ fex_7z_type,\
fex_gz_type,\ fex_gz_type,\
fex_zip_type, fex_zip_type,
// Use standard config.h if present // Use standard config.h if present
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "config.h" #include "config.h"
#endif #endif
#endif #endif

View File

@ -1,185 +1,185 @@
// CPU Byte Order Utilities // CPU Byte Order Utilities
// File_Extractor 1.0.0 // File_Extractor 1.0.0
#ifndef BLARGG_ENDIAN_H #ifndef BLARGG_ENDIAN_H
#define BLARGG_ENDIAN_H #define BLARGG_ENDIAN_H
#include "blargg_common.h" #include "blargg_common.h"
// BLARGG_CPU_CISC: Defined if CPU has very few general-purpose registers (< 16) // BLARGG_CPU_CISC: Defined if CPU has very few general-purpose registers (< 16)
#if defined (__i386__) || defined (__x86_64__) || defined (_M_IX86) || defined (_M_X64) #if defined (__i386__) || defined (__x86_64__) || defined (_M_IX86) || defined (_M_X64)
#define BLARGG_CPU_X86 1 #define BLARGG_CPU_X86 1
#define BLARGG_CPU_CISC 1 #define BLARGG_CPU_CISC 1
#endif #endif
#if defined (__powerpc__) || defined (__ppc__) || defined (__ppc64__) || \ #if defined (__powerpc__) || defined (__ppc__) || defined (__ppc64__) || \
defined (__POWERPC__) || defined (__powerc) defined (__POWERPC__) || defined (__powerc)
#define BLARGG_CPU_POWERPC 1 #define BLARGG_CPU_POWERPC 1
#define BLARGG_CPU_RISC 1 #define BLARGG_CPU_RISC 1
#endif #endif
// BLARGG_BIG_ENDIAN, BLARGG_LITTLE_ENDIAN: Determined automatically, otherwise only // BLARGG_BIG_ENDIAN, BLARGG_LITTLE_ENDIAN: Determined automatically, otherwise only
// one may be #defined to 1. Only needed if something actually depends on byte order. // one may be #defined to 1. Only needed if something actually depends on byte order.
#if !defined (BLARGG_BIG_ENDIAN) && !defined (BLARGG_LITTLE_ENDIAN) #if !defined (BLARGG_BIG_ENDIAN) && !defined (BLARGG_LITTLE_ENDIAN)
#ifdef __GLIBC__ #ifdef __GLIBC__
// GCC handles this for us // GCC handles this for us
#include <endian.h> #include <endian.h>
#if __BYTE_ORDER == __LITTLE_ENDIAN #if __BYTE_ORDER == __LITTLE_ENDIAN
#define BLARGG_LITTLE_ENDIAN 1 #define BLARGG_LITTLE_ENDIAN 1
#elif __BYTE_ORDER == __BIG_ENDIAN #elif __BYTE_ORDER == __BIG_ENDIAN
#define BLARGG_BIG_ENDIAN 1 #define BLARGG_BIG_ENDIAN 1
#endif #endif
#else #else
#if defined (LSB_FIRST) || defined (__LITTLE_ENDIAN__) || BLARGG_CPU_X86 || \ #if defined (LSB_FIRST) || defined (__LITTLE_ENDIAN__) || BLARGG_CPU_X86 || \
(defined (LITTLE_ENDIAN) && LITTLE_ENDIAN+0 != 1234) (defined (LITTLE_ENDIAN) && LITTLE_ENDIAN+0 != 1234)
#define BLARGG_LITTLE_ENDIAN 1 #define BLARGG_LITTLE_ENDIAN 1
#endif #endif
#if defined (MSB_FIRST) || defined (__BIG_ENDIAN__) || defined (WORDS_BIGENDIAN) || \ #if defined (MSB_FIRST) || defined (__BIG_ENDIAN__) || defined (WORDS_BIGENDIAN) || \
defined (__sparc__) || BLARGG_CPU_POWERPC || \ defined (__sparc__) || BLARGG_CPU_POWERPC || \
(defined (BIG_ENDIAN) && BIG_ENDIAN+0 != 4321) (defined (BIG_ENDIAN) && BIG_ENDIAN+0 != 4321)
#define BLARGG_BIG_ENDIAN 1 #define BLARGG_BIG_ENDIAN 1
#elif !defined (__mips__) #elif !defined (__mips__)
// No endian specified; assume little-endian, since it's most common // No endian specified; assume little-endian, since it's most common
#define BLARGG_LITTLE_ENDIAN 1 #define BLARGG_LITTLE_ENDIAN 1
#endif #endif
#endif #endif
#endif #endif
#if BLARGG_LITTLE_ENDIAN && BLARGG_BIG_ENDIAN #if BLARGG_LITTLE_ENDIAN && BLARGG_BIG_ENDIAN
#undef BLARGG_LITTLE_ENDIAN #undef BLARGG_LITTLE_ENDIAN
#undef BLARGG_BIG_ENDIAN #undef BLARGG_BIG_ENDIAN
#endif #endif
inline void blargg_verify_byte_order() inline void blargg_verify_byte_order()
{ {
#ifndef NDEBUG #ifndef NDEBUG
#if BLARGG_BIG_ENDIAN #if BLARGG_BIG_ENDIAN
volatile int i = 1; volatile int i = 1;
assert( *(volatile char*) &i == 0 ); assert( *(volatile char*) &i == 0 );
#elif BLARGG_LITTLE_ENDIAN #elif BLARGG_LITTLE_ENDIAN
volatile int i = 1; volatile int i = 1;
assert( *(volatile char*) &i != 0 ); assert( *(volatile char*) &i != 0 );
#endif #endif
#endif #endif
} }
inline unsigned get_le16( void const* p ) inline unsigned get_le16( void const* p )
{ {
return (unsigned) ((unsigned char const*) p) [1] << 8 | return (unsigned) ((unsigned char const*) p) [1] << 8 |
(unsigned) ((unsigned char const*) p) [0]; (unsigned) ((unsigned char const*) p) [0];
} }
inline unsigned get_be16( void const* p ) inline unsigned get_be16( void const* p )
{ {
return (unsigned) ((unsigned char const*) p) [0] << 8 | return (unsigned) ((unsigned char const*) p) [0] << 8 |
(unsigned) ((unsigned char const*) p) [1]; (unsigned) ((unsigned char const*) p) [1];
} }
inline unsigned get_le32( void const* p ) inline unsigned get_le32( void const* p )
{ {
return (unsigned) ((unsigned char const*) p) [3] << 24 | return (unsigned) ((unsigned char const*) p) [3] << 24 |
(unsigned) ((unsigned char const*) p) [2] << 16 | (unsigned) ((unsigned char const*) p) [2] << 16 |
(unsigned) ((unsigned char const*) p) [1] << 8 | (unsigned) ((unsigned char const*) p) [1] << 8 |
(unsigned) ((unsigned char const*) p) [0]; (unsigned) ((unsigned char const*) p) [0];
} }
inline unsigned get_be32( void const* p ) inline unsigned get_be32( void const* p )
{ {
return (unsigned) ((unsigned char const*) p) [0] << 24 | return (unsigned) ((unsigned char const*) p) [0] << 24 |
(unsigned) ((unsigned char const*) p) [1] << 16 | (unsigned) ((unsigned char const*) p) [1] << 16 |
(unsigned) ((unsigned char const*) p) [2] << 8 | (unsigned) ((unsigned char const*) p) [2] << 8 |
(unsigned) ((unsigned char const*) p) [3]; (unsigned) ((unsigned char const*) p) [3];
} }
inline void set_le16( void* p, unsigned n ) inline void set_le16( void* p, unsigned n )
{ {
((unsigned char*) p) [1] = (unsigned char) (n >> 8); ((unsigned char*) p) [1] = (unsigned char) (n >> 8);
((unsigned char*) p) [0] = (unsigned char) n; ((unsigned char*) p) [0] = (unsigned char) n;
} }
inline void set_be16( void* p, unsigned n ) inline void set_be16( void* p, unsigned n )
{ {
((unsigned char*) p) [0] = (unsigned char) (n >> 8); ((unsigned char*) p) [0] = (unsigned char) (n >> 8);
((unsigned char*) p) [1] = (unsigned char) n; ((unsigned char*) p) [1] = (unsigned char) n;
} }
inline void set_le32( void* p, unsigned n ) inline void set_le32( void* p, unsigned n )
{ {
((unsigned char*) p) [0] = (unsigned char) n; ((unsigned char*) p) [0] = (unsigned char) n;
((unsigned char*) p) [1] = (unsigned char) (n >> 8); ((unsigned char*) p) [1] = (unsigned char) (n >> 8);
((unsigned char*) p) [2] = (unsigned char) (n >> 16); ((unsigned char*) p) [2] = (unsigned char) (n >> 16);
((unsigned char*) p) [3] = (unsigned char) (n >> 24); ((unsigned char*) p) [3] = (unsigned char) (n >> 24);
} }
inline void set_be32( void* p, unsigned n ) inline void set_be32( void* p, unsigned n )
{ {
((unsigned char*) p) [3] = (unsigned char) n; ((unsigned char*) p) [3] = (unsigned char) n;
((unsigned char*) p) [2] = (unsigned char) (n >> 8); ((unsigned char*) p) [2] = (unsigned char) (n >> 8);
((unsigned char*) p) [1] = (unsigned char) (n >> 16); ((unsigned char*) p) [1] = (unsigned char) (n >> 16);
((unsigned char*) p) [0] = (unsigned char) (n >> 24); ((unsigned char*) p) [0] = (unsigned char) (n >> 24);
} }
#if BLARGG_NONPORTABLE #if BLARGG_NONPORTABLE
// Optimized implementation if byte order is known // Optimized implementation if byte order is known
#if BLARGG_LITTLE_ENDIAN #if BLARGG_LITTLE_ENDIAN
#define GET_LE16( addr ) (*(BOOST::uint16_t const*) (addr)) #define GET_LE16( addr ) (*(BOOST::uint16_t const*) (addr))
#define GET_LE32( addr ) (*(BOOST::uint32_t const*) (addr)) #define GET_LE32( addr ) (*(BOOST::uint32_t const*) (addr))
#define SET_LE16( addr, data ) (void) (*(BOOST::uint16_t*) (addr) = (data)) #define SET_LE16( addr, data ) (void) (*(BOOST::uint16_t*) (addr) = (data))
#define SET_LE32( addr, data ) (void) (*(BOOST::uint32_t*) (addr) = (data)) #define SET_LE32( addr, data ) (void) (*(BOOST::uint32_t*) (addr) = (data))
#elif BLARGG_BIG_ENDIAN #elif BLARGG_BIG_ENDIAN
#define GET_BE16( addr ) (*(BOOST::uint16_t const*) (addr)) #define GET_BE16( addr ) (*(BOOST::uint16_t const*) (addr))
#define GET_BE32( addr ) (*(BOOST::uint32_t const*) (addr)) #define GET_BE32( addr ) (*(BOOST::uint32_t const*) (addr))
#define SET_BE16( addr, data ) (void) (*(BOOST::uint16_t*) (addr) = (data)) #define SET_BE16( addr, data ) (void) (*(BOOST::uint16_t*) (addr) = (data))
#define SET_BE32( addr, data ) (void) (*(BOOST::uint32_t*) (addr) = (data)) #define SET_BE32( addr, data ) (void) (*(BOOST::uint32_t*) (addr) = (data))
#if BLARGG_CPU_POWERPC #if BLARGG_CPU_POWERPC
// PowerPC has special byte-reversed instructions // PowerPC has special byte-reversed instructions
#if defined (__MWERKS__) #if defined (__MWERKS__)
#define GET_LE16( addr ) (__lhbrx( addr, 0 )) #define GET_LE16( addr ) (__lhbrx( addr, 0 ))
#define GET_LE32( addr ) (__lwbrx( addr, 0 )) #define GET_LE32( addr ) (__lwbrx( addr, 0 ))
#define SET_LE16( addr, in ) (__sthbrx( in, addr, 0 )) #define SET_LE16( addr, in ) (__sthbrx( in, addr, 0 ))
#define SET_LE32( addr, in ) (__stwbrx( in, addr, 0 )) #define SET_LE32( addr, in ) (__stwbrx( in, addr, 0 ))
#elif defined (__GNUC__) #elif defined (__GNUC__)
#define GET_LE16( addr ) ({unsigned short ppc_lhbrx_; __asm__ volatile( "lhbrx %0,0,%1" : "=r" (ppc_lhbrx_) : "r" (addr) : "memory" ); ppc_lhbrx_;}) #define GET_LE16( addr ) ({unsigned short ppc_lhbrx_; __asm__ volatile( "lhbrx %0,0,%1" : "=r" (ppc_lhbrx_) : "r" (addr) : "memory" ); ppc_lhbrx_;})
#define GET_LE32( addr ) ({unsigned short ppc_lwbrx_; __asm__ volatile( "lwbrx %0,0,%1" : "=r" (ppc_lwbrx_) : "r" (addr) : "memory" ); ppc_lwbrx_;}) #define GET_LE32( addr ) ({unsigned short ppc_lwbrx_; __asm__ volatile( "lwbrx %0,0,%1" : "=r" (ppc_lwbrx_) : "r" (addr) : "memory" ); ppc_lwbrx_;})
#define SET_LE16( addr, in ) ({__asm__ volatile( "sthbrx %0,0,%1" : : "r" (in), "r" (addr) : "memory" );}) #define SET_LE16( addr, in ) ({__asm__ volatile( "sthbrx %0,0,%1" : : "r" (in), "r" (addr) : "memory" );})
#define SET_LE32( addr, in ) ({__asm__ volatile( "stwbrx %0,0,%1" : : "r" (in), "r" (addr) : "memory" );}) #define SET_LE32( addr, in ) ({__asm__ volatile( "stwbrx %0,0,%1" : : "r" (in), "r" (addr) : "memory" );})
#endif #endif
#endif #endif
#endif #endif
#endif #endif
#ifndef GET_LE16 #ifndef GET_LE16
#define GET_LE16( addr ) get_le16( addr ) #define GET_LE16( addr ) get_le16( addr )
#define SET_LE16( addr, data ) set_le16( addr, data ) #define SET_LE16( addr, data ) set_le16( addr, data )
#endif #endif
#ifndef GET_LE32 #ifndef GET_LE32
#define GET_LE32( addr ) get_le32( addr ) #define GET_LE32( addr ) get_le32( addr )
#define SET_LE32( addr, data ) set_le32( addr, data ) #define SET_LE32( addr, data ) set_le32( addr, data )
#endif #endif
#ifndef GET_BE16 #ifndef GET_BE16
#define GET_BE16( addr ) get_be16( addr ) #define GET_BE16( addr ) get_be16( addr )
#define SET_BE16( addr, data ) set_be16( addr, data ) #define SET_BE16( addr, data ) set_be16( addr, data )
#endif #endif
#ifndef GET_BE32 #ifndef GET_BE32
#define GET_BE32( addr ) get_be32( addr ) #define GET_BE32( addr ) get_be32( addr )
#define SET_BE32( addr, data ) set_be32( addr, data ) #define SET_BE32( addr, data ) set_be32( addr, data )
#endif #endif
// auto-selecting versions // auto-selecting versions
inline void set_le( BOOST::uint16_t* p, unsigned n ) { SET_LE16( p, n ); } inline void set_le( BOOST::uint16_t* p, unsigned n ) { SET_LE16( p, n ); }
inline void set_le( BOOST::uint32_t* p, unsigned n ) { SET_LE32( p, n ); } inline void set_le( BOOST::uint32_t* p, unsigned n ) { SET_LE32( p, n ); }
inline void set_be( BOOST::uint16_t* p, unsigned n ) { SET_BE16( p, n ); } inline void set_be( BOOST::uint16_t* p, unsigned n ) { SET_BE16( p, n ); }
inline void set_be( BOOST::uint32_t* p, unsigned n ) { SET_BE32( p, n ); } inline void set_be( BOOST::uint32_t* p, unsigned n ) { SET_BE32( p, n ); }
inline unsigned get_le( BOOST::uint16_t const* p ) { return GET_LE16( p ); } inline unsigned get_le( BOOST::uint16_t const* p ) { return GET_LE16( p ); }
inline unsigned get_le( BOOST::uint32_t const* p ) { return GET_LE32( p ); } inline unsigned get_le( BOOST::uint32_t const* p ) { return GET_LE32( p ); }
inline unsigned get_be( BOOST::uint16_t const* p ) { return GET_BE16( p ); } inline unsigned get_be( BOOST::uint16_t const* p ) { return GET_BE16( p ); }
inline unsigned get_be( BOOST::uint32_t const* p ) { return GET_BE32( p ); } inline unsigned get_be( BOOST::uint32_t const* p ) { return GET_BE32( p ); }
#endif #endif

View File

@ -1,113 +1,113 @@
// File_Extractor 1.0.0. http://www.slack.net/~ant/ // File_Extractor 1.0.0. http://www.slack.net/~ant/
#include "blargg_errors.h" #include "blargg_errors.h"
/* Copyright (C) 2009 Shay Green. This module is free software; you /* Copyright (C) 2009 Shay Green. This module is free software; you
can redistribute it and/or modify it under the terms of the GNU Lesser can redistribute it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software Foundation; either General Public License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version. This version 2.1 of the License, or (at your option) any later version. This
module is distributed in the hope that it will be useful, but WITHOUT ANY module is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details. You should have received a copy of the GNU Lesser General Public details. You should have received a copy of the GNU Lesser General Public
License along with this module; if not, write to the Free Software Foundation, License along with this module; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
#include "blargg_source.h" #include "blargg_source.h"
blargg_err_def_t blargg_err_generic = BLARGG_ERR_GENERIC; blargg_err_def_t blargg_err_generic = BLARGG_ERR_GENERIC;
blargg_err_def_t blargg_err_memory = BLARGG_ERR_MEMORY; blargg_err_def_t blargg_err_memory = BLARGG_ERR_MEMORY;
blargg_err_def_t blargg_err_caller = BLARGG_ERR_CALLER; blargg_err_def_t blargg_err_caller = BLARGG_ERR_CALLER;
blargg_err_def_t blargg_err_internal = BLARGG_ERR_INTERNAL; blargg_err_def_t blargg_err_internal = BLARGG_ERR_INTERNAL;
blargg_err_def_t blargg_err_limitation = BLARGG_ERR_LIMITATION; blargg_err_def_t blargg_err_limitation = BLARGG_ERR_LIMITATION;
blargg_err_def_t blargg_err_file_missing = BLARGG_ERR_FILE_MISSING; blargg_err_def_t blargg_err_file_missing = BLARGG_ERR_FILE_MISSING;
blargg_err_def_t blargg_err_file_read = BLARGG_ERR_FILE_READ; blargg_err_def_t blargg_err_file_read = BLARGG_ERR_FILE_READ;
blargg_err_def_t blargg_err_file_write = BLARGG_ERR_FILE_WRITE; blargg_err_def_t blargg_err_file_write = BLARGG_ERR_FILE_WRITE;
blargg_err_def_t blargg_err_file_io = BLARGG_ERR_FILE_IO; blargg_err_def_t blargg_err_file_io = BLARGG_ERR_FILE_IO;
blargg_err_def_t blargg_err_file_full = BLARGG_ERR_FILE_FULL; blargg_err_def_t blargg_err_file_full = BLARGG_ERR_FILE_FULL;
blargg_err_def_t blargg_err_file_eof = BLARGG_ERR_FILE_EOF; blargg_err_def_t blargg_err_file_eof = BLARGG_ERR_FILE_EOF;
blargg_err_def_t blargg_err_file_type = BLARGG_ERR_FILE_TYPE; blargg_err_def_t blargg_err_file_type = BLARGG_ERR_FILE_TYPE;
blargg_err_def_t blargg_err_file_feature = BLARGG_ERR_FILE_FEATURE; blargg_err_def_t blargg_err_file_feature = BLARGG_ERR_FILE_FEATURE;
blargg_err_def_t blargg_err_file_corrupt = BLARGG_ERR_FILE_CORRUPT; blargg_err_def_t blargg_err_file_corrupt = BLARGG_ERR_FILE_CORRUPT;
const char* blargg_err_str( blargg_err_t err ) const char* blargg_err_str( blargg_err_t err )
{ {
if ( !err ) if ( !err )
return ""; return "";
if ( *err == BLARGG_ERR_TYPE("")[0] ) if ( *err == BLARGG_ERR_TYPE("")[0] )
return err + 1; return err + 1;
return err; return err;
} }
bool blargg_is_err_type( blargg_err_t err, const char type [] ) bool blargg_is_err_type( blargg_err_t err, const char type [] )
{ {
if ( err ) if ( err )
{ {
// True if first strlen(type) characters of err match type // True if first strlen(type) characters of err match type
char const* p = err; char const* p = err;
while ( *type && *type == *p ) while ( *type && *type == *p )
{ {
type++; type++;
p++; p++;
} }
if ( !*type ) if ( !*type )
return true; return true;
} }
return false; return false;
} }
const char* blargg_err_details( blargg_err_t err ) const char* blargg_err_details( blargg_err_t err )
{ {
const char* p = err; const char* p = err;
if ( !p ) if ( !p )
{ {
p = ""; p = "";
} }
else if ( *p == BLARGG_ERR_TYPE("")[0] ) else if ( *p == BLARGG_ERR_TYPE("")[0] )
{ {
while ( *p && *p != ';' ) while ( *p && *p != ';' )
p++; p++;
// Skip ; and space after it // Skip ; and space after it
if ( *p ) if ( *p )
{ {
p++; p++;
check( *p == ' ' ); check( *p == ' ' );
if ( *p ) if ( *p )
p++; p++;
} }
} }
return p; return p;
} }
int blargg_err_to_code( blargg_err_t err, blargg_err_to_code_t const codes [] ) int blargg_err_to_code( blargg_err_t err, blargg_err_to_code_t const codes [] )
{ {
if ( !err ) if ( !err )
return 0; return 0;
while ( codes->str && !blargg_is_err_type( err, codes->str ) ) while ( codes->str && !blargg_is_err_type( err, codes->str ) )
codes++; codes++;
return codes->code; return codes->code;
} }
blargg_err_t blargg_code_to_err( int code, blargg_err_to_code_t const codes [] ) blargg_err_t blargg_code_to_err( int code, blargg_err_to_code_t const codes [] )
{ {
if ( !code ) if ( !code )
return blargg_ok; return blargg_ok;
while ( codes->str && codes->code != code ) while ( codes->str && codes->code != code )
codes++; codes++;
if ( !codes->str ) if ( !codes->str )
return blargg_err_generic; return blargg_err_generic;
return codes->str; return codes->str;
} }

View File

@ -1,80 +1,80 @@
// Error strings and conversion functions // Error strings and conversion functions
// File_Extractor 1.0.0 // File_Extractor 1.0.0
#ifndef BLARGG_ERRORS_H #ifndef BLARGG_ERRORS_H
#define BLARGG_ERRORS_H #define BLARGG_ERRORS_H
#ifndef BLARGG_COMMON_H #ifndef BLARGG_COMMON_H
#include "blargg_common.h" #include "blargg_common.h"
#endif #endif
typedef const char blargg_err_def_t []; typedef const char blargg_err_def_t [];
// Basic errors // Basic errors
extern blargg_err_def_t blargg_err_generic; extern blargg_err_def_t blargg_err_generic;
extern blargg_err_def_t blargg_err_memory; extern blargg_err_def_t blargg_err_memory;
extern blargg_err_def_t blargg_err_caller; extern blargg_err_def_t blargg_err_caller;
extern blargg_err_def_t blargg_err_internal; extern blargg_err_def_t blargg_err_internal;
extern blargg_err_def_t blargg_err_limitation; extern blargg_err_def_t blargg_err_limitation;
// File low-level // File low-level
extern blargg_err_def_t blargg_err_file_missing; // not found extern blargg_err_def_t blargg_err_file_missing; // not found
extern blargg_err_def_t blargg_err_file_read; extern blargg_err_def_t blargg_err_file_read;
extern blargg_err_def_t blargg_err_file_write; extern blargg_err_def_t blargg_err_file_write;
extern blargg_err_def_t blargg_err_file_io; extern blargg_err_def_t blargg_err_file_io;
extern blargg_err_def_t blargg_err_file_full; extern blargg_err_def_t blargg_err_file_full;
extern blargg_err_def_t blargg_err_file_eof; extern blargg_err_def_t blargg_err_file_eof;
// File high-level // File high-level
extern blargg_err_def_t blargg_err_file_type; // wrong file type extern blargg_err_def_t blargg_err_file_type; // wrong file type
extern blargg_err_def_t blargg_err_file_feature; extern blargg_err_def_t blargg_err_file_feature;
extern blargg_err_def_t blargg_err_file_corrupt; extern blargg_err_def_t blargg_err_file_corrupt;
// C string describing error, or "" if err == NULL // C string describing error, or "" if err == NULL
const char* blargg_err_str( blargg_err_t err ); const char* blargg_err_str( blargg_err_t err );
// True iff error is of given type, or false if err == NULL // True iff error is of given type, or false if err == NULL
bool blargg_is_err_type( blargg_err_t, const char type [] ); bool blargg_is_err_type( blargg_err_t, const char type [] );
// Details of error without describing main cause, or "" if err == NULL // Details of error without describing main cause, or "" if err == NULL
const char* blargg_err_details( blargg_err_t err ); const char* blargg_err_details( blargg_err_t err );
// Converts error string to integer code using mapping table. Calls blargg_is_err_type() // Converts error string to integer code using mapping table. Calls blargg_is_err_type()
// for each str and returns code on first match. Returns 0 if err == NULL. // for each str and returns code on first match. Returns 0 if err == NULL.
struct blargg_err_to_code_t { struct blargg_err_to_code_t {
const char* str; const char* str;
int code; int code;
}; };
int blargg_err_to_code( blargg_err_t err, blargg_err_to_code_t const [] ); int blargg_err_to_code( blargg_err_t err, blargg_err_to_code_t const [] );
// Converts error code back to string. If code == 0, returns NULL. If not in table, // Converts error code back to string. If code == 0, returns NULL. If not in table,
// returns blargg_err_generic. // returns blargg_err_generic.
blargg_err_t blargg_code_to_err( int code, blargg_err_to_code_t const [] ); blargg_err_t blargg_code_to_err( int code, blargg_err_to_code_t const [] );
// Generates error string literal with details of cause // Generates error string literal with details of cause
#define BLARGG_ERR( type, str ) (type "; " str) #define BLARGG_ERR( type, str ) (type "; " str)
// Extra space to make it clear when blargg_err_str() isn't called to get // Extra space to make it clear when blargg_err_str() isn't called to get
// printable version of error. At some point, I might prefix error strings // printable version of error. At some point, I might prefix error strings
// with a code, to speed conversion to a code. // with a code, to speed conversion to a code.
#define BLARGG_ERR_TYPE( str ) " " str #define BLARGG_ERR_TYPE( str ) " " str
// Error types to pass to BLARGG_ERR macro // Error types to pass to BLARGG_ERR macro
#define BLARGG_ERR_GENERIC BLARGG_ERR_TYPE( "operation failed" ) #define BLARGG_ERR_GENERIC BLARGG_ERR_TYPE( "operation failed" )
#define BLARGG_ERR_MEMORY BLARGG_ERR_TYPE( "out of memory" ) #define BLARGG_ERR_MEMORY BLARGG_ERR_TYPE( "out of memory" )
#define BLARGG_ERR_CALLER BLARGG_ERR_TYPE( "internal usage bug" ) #define BLARGG_ERR_CALLER BLARGG_ERR_TYPE( "internal usage bug" )
#define BLARGG_ERR_INTERNAL BLARGG_ERR_TYPE( "internal bug" ) #define BLARGG_ERR_INTERNAL BLARGG_ERR_TYPE( "internal bug" )
#define BLARGG_ERR_LIMITATION BLARGG_ERR_TYPE( "exceeded limitation" ) #define BLARGG_ERR_LIMITATION BLARGG_ERR_TYPE( "exceeded limitation" )
#define BLARGG_ERR_FILE_MISSING BLARGG_ERR_TYPE( "file not found" ) #define BLARGG_ERR_FILE_MISSING BLARGG_ERR_TYPE( "file not found" )
#define BLARGG_ERR_FILE_READ BLARGG_ERR_TYPE( "couldn't open file" ) #define BLARGG_ERR_FILE_READ BLARGG_ERR_TYPE( "couldn't open file" )
#define BLARGG_ERR_FILE_WRITE BLARGG_ERR_TYPE( "couldn't modify file" ) #define BLARGG_ERR_FILE_WRITE BLARGG_ERR_TYPE( "couldn't modify file" )
#define BLARGG_ERR_FILE_IO BLARGG_ERR_TYPE( "read/write error" ) #define BLARGG_ERR_FILE_IO BLARGG_ERR_TYPE( "read/write error" )
#define BLARGG_ERR_FILE_FULL BLARGG_ERR_TYPE( "disk full" ) #define BLARGG_ERR_FILE_FULL BLARGG_ERR_TYPE( "disk full" )
#define BLARGG_ERR_FILE_EOF BLARGG_ERR_TYPE( "truncated file" ) #define BLARGG_ERR_FILE_EOF BLARGG_ERR_TYPE( "truncated file" )
#define BLARGG_ERR_FILE_TYPE BLARGG_ERR_TYPE( "wrong file type" ) #define BLARGG_ERR_FILE_TYPE BLARGG_ERR_TYPE( "wrong file type" )
#define BLARGG_ERR_FILE_FEATURE BLARGG_ERR_TYPE( "unsupported file feature" ) #define BLARGG_ERR_FILE_FEATURE BLARGG_ERR_TYPE( "unsupported file feature" )
#define BLARGG_ERR_FILE_CORRUPT BLARGG_ERR_TYPE( "corrupt file" ) #define BLARGG_ERR_FILE_CORRUPT BLARGG_ERR_TYPE( "corrupt file" )
#endif #endif

View File

@ -1,321 +1,321 @@
// File_Extractor 1.0.0. http://www.slack.net/~ant/ // File_Extractor 1.0.0. http://www.slack.net/~ant/
#include "fex.h" #include "fex.h"
#include "File_Extractor.h" #include "File_Extractor.h"
#include "blargg_endian.h" #include "blargg_endian.h"
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
/* Copyright (C) 2005-2009 Shay Green. This module is free software; you /* Copyright (C) 2005-2009 Shay Green. This module is free software; you
can redistribute it and/or modify it under the terms of the GNU Lesser can redistribute it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software Foundation; either General Public License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version. This version 2.1 of the License, or (at your option) any later version. This
module is distributed in the hope that it will be useful, but WITHOUT ANY module is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details. You should have received a copy of the GNU Lesser General Public details. You should have received a copy of the GNU Lesser General Public
License along with this module; if not, write to the Free Software Foundation, License along with this module; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
#include "blargg_source.h" #include "blargg_source.h"
//// Types //// Types
BLARGG_EXPORT const fex_type_t* fex_type_list( void ) BLARGG_EXPORT const fex_type_t* fex_type_list( void )
{ {
static fex_type_t const fex_type_list_ [] = static fex_type_t const fex_type_list_ [] =
{ {
#ifdef FEX_TYPE_LIST #ifdef FEX_TYPE_LIST
FEX_TYPE_LIST FEX_TYPE_LIST
#else #else
// Modify blargg_config.h to change type list, NOT this file // Modify blargg_config.h to change type list, NOT this file
fex_7z_type, fex_7z_type,
fex_gz_type, fex_gz_type,
#if FEX_ENABLE_RAR #if FEX_ENABLE_RAR
fex_rar_type, fex_rar_type,
#endif #endif
fex_zip_type, fex_zip_type,
#endif #endif
fex_bin_type, fex_bin_type,
NULL NULL
}; };
return fex_type_list_; return fex_type_list_;
} }
BLARGG_EXPORT fex_err_t fex_init( void ) BLARGG_EXPORT fex_err_t fex_init( void )
{ {
static bool inited; static bool inited;
if ( !inited ) if ( !inited )
{ {
for ( fex_type_t const* t = fex_type_list(); *t != NULL; ++t ) for ( fex_type_t const* t = fex_type_list(); *t != NULL; ++t )
{ {
if ( (*t)->init ) if ( (*t)->init )
RETURN_ERR( (*t)->init() ); RETURN_ERR( (*t)->init() );
} }
inited = true; inited = true;
} }
return blargg_ok; return blargg_ok;
} }
BLARGG_EXPORT const char* fex_identify_header( void const* header ) BLARGG_EXPORT const char* fex_identify_header( void const* header )
{ {
unsigned four = get_be32( header ); unsigned four = get_be32( header );
switch ( four ) switch ( four )
{ {
case 0x52457E5E: case 0x52457E5E:
case 0x52617221: return ".rar"; case 0x52617221: return ".rar";
case 0x377ABCAF: return ".7z"; case 0x377ABCAF: return ".7z";
case 0x504B0304: case 0x504B0304:
case 0x504B0506: return ".zip"; case 0x504B0506: return ".zip";
case 0x53495421: return ".sit"; case 0x53495421: return ".sit";
case 0x41724301: return ".arc"; case 0x41724301: return ".arc";
case 0x4D534346: return ".cab"; case 0x4D534346: return ".cab";
case 0x5A4F4F20: return ".zoo"; case 0x5A4F4F20: return ".zoo";
} }
unsigned three = four >> 8; unsigned three = four >> 8;
switch ( three ) switch ( three )
{ {
case 0x425A68: return ".bz2"; case 0x425A68: return ".bz2";
} }
unsigned two = four >> 16; unsigned two = four >> 16;
switch ( two ) switch ( two )
{ {
case 0x1F8B: return ".gz"; case 0x1F8B: return ".gz";
case 0x60EA: return ".arj"; case 0x60EA: return ".arj";
} }
unsigned skip_first_two = four & 0xFFFF; unsigned skip_first_two = four & 0xFFFF;
if ( skip_first_two == 0x2D6C ) if ( skip_first_two == 0x2D6C )
return ".lha"; return ".lha";
return ""; return "";
} }
static int fex_has_extension_( const char str [], const char suffix [], size_t str_len ) static int fex_has_extension_( const char str [], const char suffix [], size_t str_len )
{ {
size_t suffix_len = strlen( suffix ); size_t suffix_len = strlen( suffix );
if ( str_len >= suffix_len ) if ( str_len >= suffix_len )
{ {
str += str_len - suffix_len; str += str_len - suffix_len;
while ( *str && tolower( (unsigned char) *str ) == *suffix ) while ( *str && tolower( (unsigned char) *str ) == *suffix )
{ {
str++; str++;
suffix++; suffix++;
} }
} }
return *suffix == 0; return *suffix == 0;
} }
BLARGG_EXPORT int fex_has_extension( const char str [], const char suffix [] ) BLARGG_EXPORT int fex_has_extension( const char str [], const char suffix [] )
{ {
return fex_has_extension_( str, suffix, strlen( str ) ); return fex_has_extension_( str, suffix, strlen( str ) );
} }
static int is_archive_extension( const char str [] ) static int is_archive_extension( const char str [] )
{ {
static const char exts [] [6] = { static const char exts [] [6] = {
".7z", ".7z",
".arc", ".arc",
".arj", ".arj",
".bz2", ".bz2",
".cab", ".cab",
".dmg", ".dmg",
".gz", ".gz",
".lha", ".lha",
".lz", ".lz",
".lzh", ".lzh",
".lzma", ".lzma",
".lzo", ".lzo",
".lzx", ".lzx",
".pea", ".pea",
".rar", ".rar",
".sit", ".sit",
".sitx", ".sitx",
".tgz", ".tgz",
".tlz", ".tlz",
".z", ".z",
".zip", ".zip",
".zoo", ".zoo",
"" ""
}; };
size_t str_len = strlen( str ); size_t str_len = strlen( str );
const char (*ext) [6] = exts; const char (*ext) [6] = exts;
for ( ; **ext; ext++ ) for ( ; **ext; ext++ )
{ {
if ( fex_has_extension_( str, *ext, str_len ) ) if ( fex_has_extension_( str, *ext, str_len ) )
return 1; return 1;
} }
return 0; return 0;
} }
BLARGG_EXPORT fex_type_t fex_identify_extension( const char str [] ) BLARGG_EXPORT fex_type_t fex_identify_extension( const char str [] )
{ {
size_t str_len = strlen( str ); size_t str_len = strlen( str );
for ( fex_type_t const* types = fex_type_list(); *types; types++ ) for ( fex_type_t const* types = fex_type_list(); *types; types++ )
{ {
if ( fex_has_extension_( str, (*types)->extension, str_len ) ) if ( fex_has_extension_( str, (*types)->extension, str_len ) )
{ {
// Avoid treating known archive type as binary // Avoid treating known archive type as binary
if ( *(*types)->extension || !is_archive_extension( str ) ) if ( *(*types)->extension || !is_archive_extension( str ) )
return *types; return *types;
} }
} }
return NULL; return NULL;
} }
BLARGG_EXPORT fex_err_t fex_identify_file( fex_type_t* type_out, const char path [] ) BLARGG_EXPORT fex_err_t fex_identify_file( fex_type_t* type_out, const char path [] )
{ {
*type_out = NULL; *type_out = NULL;
fex_type_t type = fex_identify_extension( path ); fex_type_t type = fex_identify_extension( path );
// Unsupported extension? // Unsupported extension?
if ( !type ) if ( !type )
return blargg_ok; // reject return blargg_ok; // reject
// Unknown/no extension? // Unknown/no extension?
if ( !*(type->extension) ) if ( !*(type->extension) )
{ {
// Examine header // Examine header
FEX_FILE_READER in; FEX_FILE_READER in;
RETURN_ERR( in.open( path ) ); RETURN_ERR( in.open( path ) );
if ( in.remain() >= fex_identify_header_size ) if ( in.remain() >= fex_identify_header_size )
{ {
char h [fex_identify_header_size]; char h [fex_identify_header_size];
RETURN_ERR( in.read( h, sizeof h ) ); RETURN_ERR( in.read( h, sizeof h ) );
type = fex_identify_extension( fex_identify_header( h ) ); type = fex_identify_extension( fex_identify_header( h ) );
} }
} }
*type_out = type; *type_out = type;
return blargg_ok; return blargg_ok;
} }
BLARGG_EXPORT fex_err_t fex_open_type( fex_t** fe_out, const char path [], fex_type_t type ) BLARGG_EXPORT fex_err_t fex_open_type( fex_t** fe_out, const char path [], fex_type_t type )
{ {
*fe_out = NULL; *fe_out = NULL;
if ( !type ) if ( !type )
return blargg_err_file_type; return blargg_err_file_type;
fex_t* fe = type->new_fex(); fex_t* fe = type->new_fex();
CHECK_ALLOC( fe ); CHECK_ALLOC( fe );
fex_err_t err = fe->open( path ); fex_err_t err = fe->open( path );
if ( err ) if ( err )
{ {
delete fe; delete fe;
return err; return err;
} }
*fe_out = fe; *fe_out = fe;
return blargg_ok; return blargg_ok;
} }
BLARGG_EXPORT fex_err_t fex_open( fex_t** fe_out, const char path [] ) BLARGG_EXPORT fex_err_t fex_open( fex_t** fe_out, const char path [] )
{ {
*fe_out = NULL; *fe_out = NULL;
fex_type_t type; fex_type_t type;
RETURN_ERR( fex_identify_file( &type, path ) ); RETURN_ERR( fex_identify_file( &type, path ) );
return fex_open_type( fe_out, path, type ); return fex_open_type( fe_out, path, type );
} }
//// Wide paths //// Wide paths
char* fex_wide_to_path( const wchar_t* wide ) char* fex_wide_to_path( const wchar_t* wide )
{ {
return blargg_to_utf8( wide ); return blargg_to_utf8( wide );
} }
void fex_free_path( char* path ) void fex_free_path( char* path )
{ {
free( path ); free( path );
} }
//// Errors //// Errors
#define ENTRY( name ) { blargg_err_##name, fex_err_##name } #define ENTRY( name ) { blargg_err_##name, fex_err_##name }
static blargg_err_to_code_t const fex_codes [] = static blargg_err_to_code_t const fex_codes [] =
{ {
ENTRY( generic ), ENTRY( generic ),
ENTRY( memory ), ENTRY( memory ),
ENTRY( caller ), ENTRY( caller ),
ENTRY( internal ), ENTRY( internal ),
ENTRY( limitation ), ENTRY( limitation ),
ENTRY( file_missing ), ENTRY( file_missing ),
ENTRY( file_read ), ENTRY( file_read ),
ENTRY( file_io ), ENTRY( file_io ),
ENTRY( file_eof ), ENTRY( file_eof ),
ENTRY( file_type ), ENTRY( file_type ),
ENTRY( file_feature ), ENTRY( file_feature ),
ENTRY( file_corrupt ), ENTRY( file_corrupt ),
{ 0, -1 } { 0, -1 }
}; };
#undef ENTRY #undef ENTRY
static int err_code( fex_err_t err ) static int err_code( fex_err_t err )
{ {
return blargg_err_to_code( err, fex_codes ); return blargg_err_to_code( err, fex_codes );
} }
BLARGG_EXPORT int fex_err_code( fex_err_t err ) BLARGG_EXPORT int fex_err_code( fex_err_t err )
{ {
int code = err_code( err ); int code = err_code( err );
return (code >= 0 ? code : fex_err_generic); return (code >= 0 ? code : fex_err_generic);
} }
BLARGG_EXPORT fex_err_t fex_code_to_err( int code ) BLARGG_EXPORT fex_err_t fex_code_to_err( int code )
{ {
return blargg_code_to_err( code, fex_codes ); return blargg_code_to_err( code, fex_codes );
} }
BLARGG_EXPORT const char* fex_err_details( fex_err_t err ) BLARGG_EXPORT const char* fex_err_details( fex_err_t err )
{ {
// If we don't have error code assigned, return entire string // If we don't have error code assigned, return entire string
return (err_code( err ) >= 0 ? blargg_err_details( err ) : blargg_err_str( err )); return (err_code( err ) >= 0 ? blargg_err_details( err ) : blargg_err_str( err ));
} }
//// Wrappers //// Wrappers
BLARGG_EXPORT fex_err_t fex_read( fex_t* fe, void* out, int count ) BLARGG_EXPORT fex_err_t fex_read( fex_t* fe, void* out, int count )
{ {
RETURN_ERR( fe->stat() ); RETURN_ERR( fe->stat() );
return fe->reader().read( out, count ); return fe->reader().read( out, count );
} }
BLARGG_EXPORT void fex_close ( fex_t* fe ) { delete fe; } BLARGG_EXPORT void fex_close ( fex_t* fe ) { delete fe; }
BLARGG_EXPORT fex_type_t fex_type ( const fex_t* fe ) { return fe->type(); } BLARGG_EXPORT fex_type_t fex_type ( const fex_t* fe ) { return fe->type(); }
BLARGG_EXPORT int fex_done ( const fex_t* fe ) { return fe->done(); } BLARGG_EXPORT int fex_done ( const fex_t* fe ) { return fe->done(); }
BLARGG_EXPORT const char* fex_name ( const fex_t* fe ) { return fe->name(); } BLARGG_EXPORT const char* fex_name ( const fex_t* fe ) { return fe->name(); }
BLARGG_EXPORT const wchar_t* fex_wname ( const fex_t* fe ) { return fe->wname(); } BLARGG_EXPORT const wchar_t* fex_wname ( const fex_t* fe ) { return fe->wname(); }
BLARGG_EXPORT int fex_size ( const fex_t* fe ) { return fe->size(); } BLARGG_EXPORT int fex_size ( const fex_t* fe ) { return fe->size(); }
BLARGG_EXPORT unsigned fex_dos_date ( const fex_t* fe ) { return fe->dos_date(); } BLARGG_EXPORT unsigned fex_dos_date ( const fex_t* fe ) { return fe->dos_date(); }
BLARGG_EXPORT unsigned fex_crc32 ( const fex_t* fe ) { return fe->crc32(); } BLARGG_EXPORT unsigned fex_crc32 ( const fex_t* fe ) { return fe->crc32(); }
BLARGG_EXPORT fex_err_t fex_stat ( fex_t* fe ) { return fe->stat(); } BLARGG_EXPORT fex_err_t fex_stat ( fex_t* fe ) { return fe->stat(); }
BLARGG_EXPORT fex_err_t fex_next ( fex_t* fe ) { return fe->next(); } BLARGG_EXPORT fex_err_t fex_next ( fex_t* fe ) { return fe->next(); }
BLARGG_EXPORT fex_err_t fex_rewind ( fex_t* fe ) { return fe->rewind(); } BLARGG_EXPORT fex_err_t fex_rewind ( fex_t* fe ) { return fe->rewind(); }
BLARGG_EXPORT int fex_tell ( const fex_t* fe ) { return fe->tell(); } BLARGG_EXPORT int fex_tell ( const fex_t* fe ) { return fe->tell(); }
BLARGG_EXPORT fex_pos_t fex_tell_arc ( const fex_t* fe ) { return fe->tell_arc(); } BLARGG_EXPORT fex_pos_t fex_tell_arc ( const fex_t* fe ) { return fe->tell_arc(); }
BLARGG_EXPORT fex_err_t fex_seek_arc ( fex_t* fe, fex_pos_t pos ) { return fe->seek_arc( pos ); } BLARGG_EXPORT fex_err_t fex_seek_arc ( fex_t* fe, fex_pos_t pos ) { return fe->seek_arc( pos ); }
BLARGG_EXPORT const char* fex_type_extension ( fex_type_t t ) { return t->extension; } BLARGG_EXPORT const char* fex_type_extension ( fex_type_t t ) { return t->extension; }
BLARGG_EXPORT const char* fex_type_name ( fex_type_t t ) { return t->name; } BLARGG_EXPORT const char* fex_type_name ( fex_type_t t ) { return t->name; }
BLARGG_EXPORT fex_err_t fex_data ( fex_t* fe, const void** data_out ) { return fe->data( data_out ); } BLARGG_EXPORT fex_err_t fex_data ( fex_t* fe, const void** data_out ) { return fe->data( data_out ); }
BLARGG_EXPORT const char* fex_err_str ( fex_err_t err ) { return blargg_err_str( err ); } BLARGG_EXPORT const char* fex_err_str ( fex_err_t err ) { return blargg_err_str( err ); }

View File

@ -1,204 +1,204 @@
/** Uniform access to zip, gzip, 7-zip, and RAR compressed archives \file */ /** Uniform access to zip, gzip, 7-zip, and RAR compressed archives \file */
/* File_Extractor 1.0.0 */ /* File_Extractor 1.0.0 */
#ifndef FEX_H #ifndef FEX_H
#define FEX_H #define FEX_H
#include <stddef.h> #include <stddef.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/** First parameter of most functions is fex_t*, or const fex_t* if nothing is /** First parameter of most functions is fex_t*, or const fex_t* if nothing is
changed. Once one of these functions returns an error, the archive should not changed. Once one of these functions returns an error, the archive should not
be used any further, other than to close it. One exception is be used any further, other than to close it. One exception is
fex_error_file_eof; the archive may still be used after this. */ fex_error_file_eof; the archive may still be used after this. */
typedef struct fex_t fex_t; typedef struct fex_t fex_t;
/** Pointer to error, or NULL if function was successful. See error functions /** Pointer to error, or NULL if function was successful. See error functions
below. */ below. */
#ifndef fex_err_t /* (#ifndef allows better testing of library) */ #ifndef fex_err_t /* (#ifndef allows better testing of library) */
typedef const char* fex_err_t; typedef const char* fex_err_t;
#endif #endif
/**** File types ****/ /**** File types ****/
/** Archive file type identifier. Can also hold NULL. */ /** Archive file type identifier. Can also hold NULL. */
typedef const struct fex_type_t_* fex_type_t; typedef const struct fex_type_t_* fex_type_t;
/** Array of supported types, with NULL at end */ /** Array of supported types, with NULL at end */
const fex_type_t* fex_type_list( void ); const fex_type_t* fex_type_list( void );
/** Name of this archive type, e.g. "ZIP archive", "file" */ /** Name of this archive type, e.g. "ZIP archive", "file" */
const char* fex_type_name( fex_type_t ); const char* fex_type_name( fex_type_t );
/** Usual file extension for type, e.g. ".zip", ".7z". For binary file type, /** Usual file extension for type, e.g. ".zip", ".7z". For binary file type,
returns "", since it can open any file. */ returns "", since it can open any file. */
const char* fex_type_extension( fex_type_t ); const char* fex_type_extension( fex_type_t );
/**** Wide-character file paths ****/ /**** Wide-character file paths ****/
/** Converts wide-character path to form suitable for use with fex functions. */ /** Converts wide-character path to form suitable for use with fex functions. */
char* fex_wide_to_path( const wchar_t* wide ); char* fex_wide_to_path( const wchar_t* wide );
/** Frees converted path. OK to pass NULL. */ /** Frees converted path. OK to pass NULL. */
void fex_free_path( char* ); void fex_free_path( char* );
/**** Identification ****/ /**** Identification ****/
/** True if str ends in extension. If extension is "", always returns true. /** True if str ends in extension. If extension is "", always returns true.
Converts str to lowercase before comparison, so extension should ALREADY be Converts str to lowercase before comparison, so extension should ALREADY be
lowercase (i.e. pass ".zip", NOT ".ZIP"). */ lowercase (i.e. pass ".zip", NOT ".ZIP"). */
int fex_has_extension( const char str [], const char extension [] ); int fex_has_extension( const char str [], const char extension [] );
/** Determines type based on first fex_identify_header_size bytes of file. /** Determines type based on first fex_identify_header_size bytes of file.
Returns usual file extension this should have (e.g. ".zip", ".gz", etc.). Returns usual file extension this should have (e.g. ".zip", ".gz", etc.).
Returns "" if file header is not recognized. */ Returns "" if file header is not recognized. */
const char* fex_identify_header( const void* header ); const char* fex_identify_header( const void* header );
enum { fex_identify_header_size = 16 }; enum { fex_identify_header_size = 16 };
/** Determines type based on extension of a file path, or just a lone extension /** Determines type based on extension of a file path, or just a lone extension
(must include '.', e.g. ".zip", NOT just "zip"). Returns NULL if extension is (must include '.', e.g. ".zip", NOT just "zip"). Returns NULL if extension is
for an unsupported type (e.g. ".lzh"). */ for an unsupported type (e.g. ".lzh"). */
fex_type_t fex_identify_extension( const char path_or_extension [] ); fex_type_t fex_identify_extension( const char path_or_extension [] );
/** Determines type based on filename extension and/or file header. Sets *out /** Determines type based on filename extension and/or file header. Sets *out
to determined type, or NULL if type is not supported. */ to determined type, or NULL if type is not supported. */
fex_err_t fex_identify_file( fex_type_t* out, const char path [] ); fex_err_t fex_identify_file( fex_type_t* out, const char path [] );
/** Type of an already-opened archive */ /** Type of an already-opened archive */
fex_type_t fex_type( const fex_t* ); fex_type_t fex_type( const fex_t* );
/**** Open/close ****/ /**** Open/close ****/
/** Initializes static tables used by library. Automatically called by /** Initializes static tables used by library. Automatically called by
fex_open(). OK to call more than once. */ fex_open(). OK to call more than once. */
fex_err_t fex_init( void ); fex_err_t fex_init( void );
/** Opens archive and points *out at it. If error, sets *out to NULL. */ /** Opens archive and points *out at it. If error, sets *out to NULL. */
fex_err_t fex_open( fex_t** out, const char path [] ); fex_err_t fex_open( fex_t** out, const char path [] );
/** Opens archive of specified type and sets *out. Returns error if file is not /** Opens archive of specified type and sets *out. Returns error if file is not
of that archive type. If error, sets *out to NULL. */ of that archive type. If error, sets *out to NULL. */
fex_err_t fex_open_type( fex_t** out, const char path [], fex_type_t ); fex_err_t fex_open_type( fex_t** out, const char path [], fex_type_t );
/** Closes archive and frees memory. OK to pass NULL. */ /** Closes archive and frees memory. OK to pass NULL. */
void fex_close( fex_t* ); void fex_close( fex_t* );
/**** Scanning ****/ /**** Scanning ****/
/** True if at end of archive. Must be called after fex_open() or fex_rewind(), /** True if at end of archive. Must be called after fex_open() or fex_rewind(),
as an archive might contain no files. */ as an archive might contain no files. */
int fex_done( const fex_t* ); int fex_done( const fex_t* );
/** Goes to next file in archive. If there are no more files, fex_done() will /** Goes to next file in archive. If there are no more files, fex_done() will
now return true. */ now return true. */
fex_err_t fex_next( fex_t* ); fex_err_t fex_next( fex_t* );
/** Goes back to first file in archive, as if it were just opened with /** Goes back to first file in archive, as if it were just opened with
fex_open() */ fex_open() */
fex_err_t fex_rewind( fex_t* ); fex_err_t fex_rewind( fex_t* );
/** Saved position in archive. Can also store zero. */ /** Saved position in archive. Can also store zero. */
typedef int fex_pos_t; typedef int fex_pos_t;
/** Position of current file in archive. Never returns zero. */ /** Position of current file in archive. Never returns zero. */
fex_pos_t fex_tell_arc( const fex_t* ); fex_pos_t fex_tell_arc( const fex_t* );
/** Returns to file at previously-saved position */ /** Returns to file at previously-saved position */
fex_err_t fex_seek_arc( fex_t*, fex_pos_t ); fex_err_t fex_seek_arc( fex_t*, fex_pos_t );
/**** Info ****/ /**** Info ****/
/** Name of current file */ /** Name of current file */
const char* fex_name( const fex_t* ); const char* fex_name( const fex_t* );
/** Wide-character name of current file, or NULL if unavailable */ /** Wide-character name of current file, or NULL if unavailable */
const wchar_t* fex_wname( const fex_t* ); const wchar_t* fex_wname( const fex_t* );
/** Makes further information available for file */ /** Makes further information available for file */
fex_err_t fex_stat( fex_t* ); fex_err_t fex_stat( fex_t* );
/** Size of current file. fex_stat() or fex_data() must have been called. */ /** Size of current file. fex_stat() or fex_data() must have been called. */
int fex_size( const fex_t* ); int fex_size( const fex_t* );
/** Modification date of current file (MS-DOS format), or 0 if unavailable. /** Modification date of current file (MS-DOS format), or 0 if unavailable.
fex_stat() must have been called. */ fex_stat() must have been called. */
unsigned int fex_dos_date( const fex_t* ); unsigned int fex_dos_date( const fex_t* );
/** CRC-32 checksum of current file's contents, or 0 if unavailable. Doesn't /** CRC-32 checksum of current file's contents, or 0 if unavailable. Doesn't
require calculation; simply gets it from file's header. fex_stat() must have require calculation; simply gets it from file's header. fex_stat() must have
been called. */ been called. */
unsigned int fex_crc32( const fex_t* ); unsigned int fex_crc32( const fex_t* );
/**** Extraction ****/ /**** Extraction ****/
/** Reads n bytes from current file. Reading past end of file results in /** Reads n bytes from current file. Reading past end of file results in
fex_err_file_eof. */ fex_err_file_eof. */
fex_err_t fex_read( fex_t*, void* out, int n ); fex_err_t fex_read( fex_t*, void* out, int n );
/** Number of bytes read from current file */ /** Number of bytes read from current file */
int fex_tell( const fex_t* ); int fex_tell( const fex_t* );
/** Points *out at current file's data in memory. Pointer is valid until /** Points *out at current file's data in memory. Pointer is valid until
fex_next(), fex_rewind(), fex_seek_arc(), or fex_close() is called. Pointer fex_next(), fex_rewind(), fex_seek_arc(), or fex_close() is called. Pointer
must NOT be freed(); library frees it automatically. If error, sets *out to must NOT be freed(); library frees it automatically. If error, sets *out to
NULL. */ NULL. */
fex_err_t fex_data( fex_t*, const void** out ); fex_err_t fex_data( fex_t*, const void** out );
/**** Errors ****/ /**** Errors ****/
/** Error string associated with err. Returns "" if err is NULL. Returns err /** Error string associated with err. Returns "" if err is NULL. Returns err
unchanged if it isn't a fex_err_t returned by library. */ unchanged if it isn't a fex_err_t returned by library. */
const char* fex_err_str( fex_err_t err ); const char* fex_err_str( fex_err_t err );
/** Details of error beyond main cause, or "" if none or err is NULL. Returns /** Details of error beyond main cause, or "" if none or err is NULL. Returns
err unchanged if it isn't a fex_err_t returned by library. */ err unchanged if it isn't a fex_err_t returned by library. */
const char* fex_err_details( fex_err_t err ); const char* fex_err_details( fex_err_t err );
/** Numeric code corresponding to err. Returns fex_ok if err is NULL. Returns /** Numeric code corresponding to err. Returns fex_ok if err is NULL. Returns
fex_err_generic if err isn't a fex_err_t returned by library. */ fex_err_generic if err isn't a fex_err_t returned by library. */
int fex_err_code( fex_err_t err ); int fex_err_code( fex_err_t err );
enum { enum {
fex_ok = 0,/**< Successful call. Guaranteed to be zero. */ fex_ok = 0,/**< Successful call. Guaranteed to be zero. */
fex_err_generic = 0x01,/**< Error of unspecified type */ fex_err_generic = 0x01,/**< Error of unspecified type */
fex_err_memory = 0x02,/**< Out of memory */ fex_err_memory = 0x02,/**< Out of memory */
fex_err_caller = 0x03,/**< Caller called function with bad args */ fex_err_caller = 0x03,/**< Caller called function with bad args */
fex_err_internal = 0x04,/**< Internal problem, bug, etc. */ fex_err_internal = 0x04,/**< Internal problem, bug, etc. */
fex_err_limitation = 0x05,/**< Exceeded program limit */ fex_err_limitation = 0x05,/**< Exceeded program limit */
fex_err_file_missing = 0x20,/**< File not found at specified path */ fex_err_file_missing = 0x20,/**< File not found at specified path */
fex_err_file_read = 0x21,/**< Couldn't open file for reading */ fex_err_file_read = 0x21,/**< Couldn't open file for reading */
fex_err_file_io = 0x23,/**< Read/write error */ fex_err_file_io = 0x23,/**< Read/write error */
fex_err_file_eof = 0x25,/**< Tried to read past end of file */ fex_err_file_eof = 0x25,/**< Tried to read past end of file */
fex_err_file_type = 0x30,/**< File is of wrong type */ fex_err_file_type = 0x30,/**< File is of wrong type */
fex_err_file_feature = 0x32,/**< File requires unsupported feature */ fex_err_file_feature = 0x32,/**< File requires unsupported feature */
fex_err_file_corrupt = 0x33 /**< File is corrupt */ fex_err_file_corrupt = 0x33 /**< File is corrupt */
}; };
/** fex_err_t corresponding to numeric code. Note that this might not recover /** fex_err_t corresponding to numeric code. Note that this might not recover
the original fex_err_t before it was converted to a numeric code; in the original fex_err_t before it was converted to a numeric code; in
particular, fex_err_details(fex_code_to_err(code)) will be "" in most cases. */ particular, fex_err_details(fex_code_to_err(code)) will be "" in most cases. */
fex_err_t fex_code_to_err( int code ); fex_err_t fex_code_to_err( int code );
/* Deprecated */ /* Deprecated */
typedef fex_t File_Extractor; typedef fex_t File_Extractor;
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif #endif

View File

@ -1,2 +1,2 @@
#define SVN_REV $WCREV$ #define SVN_REV $WCREV$
#define SVN_REV_STR "$WCREV$" #define SVN_REV_STR "$WCREV$"

View File

@ -1,2 +1,2 @@
#define SVN_REV $WCREV$ #define SVN_REV $WCREV$
#define SVN_REV_STR "$WCREV$" #define SVN_REV_STR "$WCREV$"

View File

@ -1,92 +1,92 @@
#ifndef SYSTEM_H #ifndef SYSTEM_H
#define SYSTEM_H #define SYSTEM_H
#include "common/Types.h" #include "common/Types.h"
#include <zlib.h> #include <zlib.h>
class SoundDriver; class SoundDriver;
struct EmulatedSystem { struct EmulatedSystem {
// main emulation function // main emulation function
void (*emuMain)(int); void (*emuMain)(int);
// reset emulator // reset emulator
void (*emuReset)(); void (*emuReset)();
// clean up memory // clean up memory
void (*emuCleanUp)(); void (*emuCleanUp)();
// load battery file // load battery file
bool (*emuReadBattery)(const char *); bool (*emuReadBattery)(const char *);
// write battery file // write battery file
bool (*emuWriteBattery)(const char *); bool (*emuWriteBattery)(const char *);
// load state // load state
bool (*emuReadState)(const char *); bool (*emuReadState)(const char *);
// save state // save state
bool (*emuWriteState)(const char *); bool (*emuWriteState)(const char *);
// load memory state (rewind) // load memory state (rewind)
bool (*emuReadMemState)(char *, int); bool (*emuReadMemState)(char *, int);
// write memory state (rewind) // write memory state (rewind)
bool (*emuWriteMemState)(char *, int); bool (*emuWriteMemState)(char *, int);
// write PNG file // write PNG file
bool (*emuWritePNG)(const char *); bool (*emuWritePNG)(const char *);
// write BMP file // write BMP file
bool (*emuWriteBMP)(const char *); bool (*emuWriteBMP)(const char *);
// emulator update CPSR (ARM only) // emulator update CPSR (ARM only)
void (*emuUpdateCPSR)(); void (*emuUpdateCPSR)();
// emulator has debugger // emulator has debugger
bool emuHasDebugger; bool emuHasDebugger;
// clock ticks to emulate // clock ticks to emulate
int emuCount; int emuCount;
}; };
extern void log(const char *,...); extern void log(const char *,...);
extern bool systemPauseOnFrame(); extern bool systemPauseOnFrame();
extern void systemGbPrint(u8 *,int,int,int,int); extern void systemGbPrint(u8 *,int,int,int,int);
extern void systemScreenCapture(int); extern void systemScreenCapture(int);
extern void systemDrawScreen(); extern void systemDrawScreen();
// updates the joystick data // updates the joystick data
extern bool systemReadJoypads(); extern bool systemReadJoypads();
// return information about the given joystick, -1 for default joystick // return information about the given joystick, -1 for default joystick
extern u32 systemReadJoypad(int); extern u32 systemReadJoypad(int);
extern u32 systemGetClock(); extern u32 systemGetClock();
extern void systemMessage(int, const char *, ...); extern void systemMessage(int, const char *, ...);
extern void systemSetTitle(const char *); extern void systemSetTitle(const char *);
extern SoundDriver * systemSoundInit(); extern SoundDriver * systemSoundInit();
extern void systemOnWriteDataToSoundBuffer(const u16 * finalWave, int length); extern void systemOnWriteDataToSoundBuffer(const u16 * finalWave, int length);
extern void systemOnSoundShutdown(); extern void systemOnSoundShutdown();
extern void systemScreenMessage(const char *); extern void systemScreenMessage(const char *);
extern void systemUpdateMotionSensor(); extern void systemUpdateMotionSensor();
extern int systemGetSensorX(); extern int systemGetSensorX();
extern int systemGetSensorY(); extern int systemGetSensorY();
extern bool systemCanChangeSoundQuality(); extern bool systemCanChangeSoundQuality();
extern void systemShowSpeed(int); extern void systemShowSpeed(int);
extern void system10Frames(int); extern void system10Frames(int);
extern void systemFrame(); extern void systemFrame();
extern void systemGbBorderOn(); extern void systemGbBorderOn();
extern void Sm60FPS_Init(); extern void Sm60FPS_Init();
extern bool Sm60FPS_CanSkipFrame(); extern bool Sm60FPS_CanSkipFrame();
extern void Sm60FPS_Sleep(); extern void Sm60FPS_Sleep();
extern void DbgMsg(const char *msg, ...); extern void DbgMsg(const char *msg, ...);
extern void winlog(const char *,...); extern void winlog(const char *,...);
extern void (*dbgOutput)(const char *s, u32 addr); extern void (*dbgOutput)(const char *s, u32 addr);
extern void (*dbgSignal)(int sig,int number); extern void (*dbgSignal)(int sig,int number);
extern u16 systemColorMap16[0x10000]; extern u16 systemColorMap16[0x10000];
extern u32 systemColorMap32[0x10000]; extern u32 systemColorMap32[0x10000];
extern u16 systemGbPalette[24]; extern u16 systemGbPalette[24];
extern int systemRedShift; extern int systemRedShift;
extern int systemGreenShift; extern int systemGreenShift;
extern int systemBlueShift; extern int systemBlueShift;
extern int systemColorDepth; extern int systemColorDepth;
extern int systemDebug; extern int systemDebug;
extern int systemVerbose; extern int systemVerbose;
extern int systemFrameSkip; extern int systemFrameSkip;
extern int systemSaveUpdateCounter; extern int systemSaveUpdateCounter;
extern int systemSpeed; extern int systemSpeed;
#define SYSTEM_SAVE_UPDATED 30 #define SYSTEM_SAVE_UPDATED 30
#define SYSTEM_SAVE_NOT_UPDATED 0 #define SYSTEM_SAVE_NOT_UPDATED 0
#endif // SYSTEM_H #endif // SYSTEM_H

View File

@ -1,459 +1,459 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <zlib.h> #include <zlib.h>
#include "Patch.h" #include "Patch.h"
#ifdef __GNUC__ #ifdef __GNUC__
#if defined(__APPLE__) || defined (BSD) #if defined(__APPLE__) || defined (BSD)
typedef off_t __off64_t; /* off_t is 64 bits on BSD. */ typedef off_t __off64_t; /* off_t is 64 bits on BSD. */
#define fseeko64 fseeko #define fseeko64 fseeko
#define ftello64 ftello #define ftello64 ftello
#else #else
typedef off64_t __off64_t; typedef off64_t __off64_t;
#endif /* __APPLE__ || BSD */ #endif /* __APPLE__ || BSD */
#endif /* __GNUC__ */ #endif /* __GNUC__ */
#ifndef _MSC_VER #ifndef _MSC_VER
#define _stricmp strcasecmp #define _stricmp strcasecmp
#endif // ! _MSC_VER #endif // ! _MSC_VER
#ifdef _MSC_VER #ifdef _MSC_VER
#define fseeko64 _fseeki64 #define fseeko64 _fseeki64
#define ftello64 _ftelli64 #define ftello64 _ftelli64
typedef __int64 __off64_t; typedef __int64 __off64_t;
#endif #endif
static int readInt2(FILE *f) static int readInt2(FILE *f)
{ {
int res = 0; int res = 0;
int c = fgetc(f); int c = fgetc(f);
if(c == EOF) if(c == EOF)
return -1; return -1;
res = c; res = c;
c = fgetc(f); c = fgetc(f);
if(c == EOF) if(c == EOF)
return -1; return -1;
return c + (res<<8); return c + (res<<8);
} }
static int readInt3(FILE *f) static int readInt3(FILE *f)
{ {
int res = 0; int res = 0;
int c = fgetc(f); int c = fgetc(f);
if(c == EOF) if(c == EOF)
return -1; return -1;
res = c; res = c;
c = fgetc(f); c = fgetc(f);
if(c == EOF) if(c == EOF)
return -1; return -1;
res = c + (res<<8); res = c + (res<<8);
c = fgetc(f); c = fgetc(f);
if(c == EOF) if(c == EOF)
return -1; return -1;
return c + (res<<8); return c + (res<<8);
} }
static s64 readInt4(FILE *f) static s64 readInt4(FILE *f)
{ {
s64 tmp, res = 0; s64 tmp, res = 0;
int c; int c;
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
c = fgetc(f); c = fgetc(f);
if (c == EOF) if (c == EOF)
return -1; return -1;
tmp = c; tmp = c;
res = res + (tmp << (i*8)); res = res + (tmp << (i*8));
} }
return res; return res;
} }
static s64 readInt8(FILE *f) static s64 readInt8(FILE *f)
{ {
s64 tmp, res = 0; s64 tmp, res = 0;
int c; int c;
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
c = fgetc(f); c = fgetc(f);
if (c == EOF) if (c == EOF)
return -1; return -1;
tmp = c; tmp = c;
res = res + (tmp << (i*8)); res = res + (tmp << (i*8));
} }
return res; return res;
} }
static s64 readVarPtr(FILE *f) static s64 readVarPtr(FILE *f)
{ {
s64 offset = 0, shift = 1; s64 offset = 0, shift = 1;
for (;;) { for (;;) {
int c = fgetc(f); int c = fgetc(f);
if (c == EOF) return 0; if (c == EOF) return 0;
offset += (c & 0x7F) * shift; offset += (c & 0x7F) * shift;
if (c & 0x80) break; if (c & 0x80) break;
shift <<= 7; shift <<= 7;
offset += shift; offset += shift;
} }
return offset; return offset;
} }
#ifndef MIN #ifndef MIN
#define MIN(a,b) (((a)<(b))?(a):(b)) #define MIN(a,b) (((a)<(b))?(a):(b))
#endif #endif
static uLong computePatchCRC(FILE *f, unsigned int size) static uLong computePatchCRC(FILE *f, unsigned int size)
{ {
Bytef buf[4096]; Bytef buf[4096];
long readed; long readed;
uLong crc = crc32(0L, Z_NULL, 0); uLong crc = crc32(0L, Z_NULL, 0);
do { do {
readed = fread(buf, 1, MIN(size, sizeof(buf)), f); readed = fread(buf, 1, MIN(size, sizeof(buf)), f);
crc = crc32(crc, buf, readed); crc = crc32(crc, buf, readed);
size -= readed; size -= readed;
} while (readed > 0); } while (readed > 0);
return crc; return crc;
} }
static bool patchApplyIPS(const char *patchname, u8 **r, int *s) static bool patchApplyIPS(const char *patchname, u8 **r, int *s)
{ {
// from the IPS spec at http://zerosoft.zophar.net/ips.htm // from the IPS spec at http://zerosoft.zophar.net/ips.htm
FILE *f = fopen(patchname, "rb"); FILE *f = fopen(patchname, "rb");
if(!f) if(!f)
return false; return false;
bool result = false; bool result = false;
u8 *rom = *r; u8 *rom = *r;
int size = *s; int size = *s;
if(fgetc(f) == 'P' && if(fgetc(f) == 'P' &&
fgetc(f) == 'A' && fgetc(f) == 'A' &&
fgetc(f) == 'T' && fgetc(f) == 'T' &&
fgetc(f) == 'C' && fgetc(f) == 'C' &&
fgetc(f) == 'H') { fgetc(f) == 'H') {
int b; int b;
int offset; int offset;
int len; int len;
result = true; result = true;
for(;;) { for(;;) {
// read offset // read offset
offset = readInt3(f); offset = readInt3(f);
// if offset == EOF, end of patch // if offset == EOF, end of patch
if(offset == 0x454f46 || offset == -1) if(offset == 0x454f46 || offset == -1)
break; break;
// read length // read length
len = readInt2(f); len = readInt2(f);
if(!len) { if(!len) {
// len == 0, RLE block // len == 0, RLE block
len = readInt2(f); len = readInt2(f);
// byte to fill // byte to fill
int c = fgetc(f); int c = fgetc(f);
if(c == -1) if(c == -1)
break; break;
b = (u8)c; b = (u8)c;
} else } else
b= -1; b= -1;
// check if we need to reallocate our ROM // check if we need to reallocate our ROM
if((offset + len) >= size) { if((offset + len) >= size) {
size *= 2; size *= 2;
rom = (u8 *)realloc(rom, size); rom = (u8 *)realloc(rom, size);
*r = rom; *r = rom;
*s = size; *s = size;
} }
if(b == -1) { if(b == -1) {
// normal block, just read the data // normal block, just read the data
if(fread(&rom[offset], 1, len, f) != (size_t)len) if(fread(&rom[offset], 1, len, f) != (size_t)len)
break; break;
} else { } else {
// fill the region with the given byte // fill the region with the given byte
while(len--) { while(len--) {
rom[offset++] = b; rom[offset++] = b;
} }
} }
} }
} }
// close the file // close the file
fclose(f); fclose(f);
return result; return result;
} }
static bool patchApplyUPS(const char *patchname, u8 **rom, int *size) static bool patchApplyUPS(const char *patchname, u8 **rom, int *size)
{ {
s64 srcCRC, dstCRC, patchCRC; s64 srcCRC, dstCRC, patchCRC;
FILE *f = fopen(patchname, "rb"); FILE *f = fopen(patchname, "rb");
if (!f) if (!f)
return false; return false;
fseeko64(f, 0, SEEK_END); fseeko64(f, 0, SEEK_END);
__off64_t patchSize = ftello64(f); __off64_t patchSize = ftello64(f);
if (patchSize < 20) { if (patchSize < 20) {
fclose(f); fclose(f);
return false; return false;
} }
fseeko64(f, 0, SEEK_SET); fseeko64(f, 0, SEEK_SET);
if(fgetc(f) != 'U' || fgetc(f) != 'P' || fgetc(f) != 'S' || fgetc(f) != '1') { if(fgetc(f) != 'U' || fgetc(f) != 'P' || fgetc(f) != 'S' || fgetc(f) != '1') {
fclose(f); fclose(f);
return false; return false;
} }
fseeko64(f, -12, SEEK_END); fseeko64(f, -12, SEEK_END);
srcCRC = readInt4(f); srcCRC = readInt4(f);
dstCRC = readInt4(f); dstCRC = readInt4(f);
patchCRC = readInt4(f); patchCRC = readInt4(f);
if (srcCRC == -1 || dstCRC == -1 || patchCRC == -1) { if (srcCRC == -1 || dstCRC == -1 || patchCRC == -1) {
fclose(f); fclose(f);
return false; return false;
} }
fseeko64(f, 0, SEEK_SET); fseeko64(f, 0, SEEK_SET);
u32 crc = computePatchCRC(f, patchSize-4); u32 crc = computePatchCRC(f, patchSize-4);
if (crc != patchCRC) { if (crc != patchCRC) {
fclose(f); fclose(f);
return false; return false;
} }
crc = crc32(0L, Z_NULL, 0); crc = crc32(0L, Z_NULL, 0);
crc = crc32(crc, *rom, *size); crc = crc32(crc, *rom, *size);
fseeko64(f, 4, SEEK_SET); fseeko64(f, 4, SEEK_SET);
s64 dataSize; s64 dataSize;
s64 srcSize = readVarPtr(f); s64 srcSize = readVarPtr(f);
s64 dstSize = readVarPtr(f); s64 dstSize = readVarPtr(f);
if (crc == srcCRC) { if (crc == srcCRC) {
if (srcSize != *size) { if (srcSize != *size) {
fclose(f); fclose(f);
return false; return false;
} }
dataSize = dstSize; dataSize = dstSize;
} else if (crc == dstCRC) { } else if (crc == dstCRC) {
if (dstSize != *size) { if (dstSize != *size) {
fclose(f); fclose(f);
return false; return false;
} }
dataSize = srcSize; dataSize = srcSize;
} else { } else {
fclose(f); fclose(f);
return false; return false;
} }
if (dataSize > *size) { if (dataSize > *size) {
*rom = (u8*)realloc(*rom, dataSize); *rom = (u8*)realloc(*rom, dataSize);
memset(*rom + *size, 0, dataSize - *size); memset(*rom + *size, 0, dataSize - *size);
*size = dataSize; *size = dataSize;
} }
s64 relative = 0; s64 relative = 0;
u8 *mem; u8 *mem;
while(ftello64(f) < patchSize - 12) { while(ftello64(f) < patchSize - 12) {
relative += readVarPtr(f); relative += readVarPtr(f);
if (relative > dataSize) continue; if (relative > dataSize) continue;
mem = *rom + relative; mem = *rom + relative;
for(s64 i = relative; i < dataSize; i++) { for(s64 i = relative; i < dataSize; i++) {
int x = fgetc(f); int x = fgetc(f);
relative++; relative++;
if (!x) break; if (!x) break;
if (i < dataSize) { if (i < dataSize) {
*mem++ ^= x; *mem++ ^= x;
} }
} }
} }
fclose(f); fclose(f);
return true; return true;
} }
static int ppfVersion(FILE *f) static int ppfVersion(FILE *f)
{ {
fseeko64(f, 0, SEEK_SET); fseeko64(f, 0, SEEK_SET);
if (fgetc(f) != 'P' || fgetc(f) != 'P' || fgetc(f) != 'F') if (fgetc(f) != 'P' || fgetc(f) != 'P' || fgetc(f) != 'F')
return 0; return 0;
switch(fgetc(f)){ switch(fgetc(f)){
case '1': return 1; case '1': return 1;
case '2': return 2; case '2': return 2;
case '3': return 3; case '3': return 3;
default: return 0; default: return 0;
} }
} }
static int ppfFileIdLen(FILE *f, int version) static int ppfFileIdLen(FILE *f, int version)
{ {
if (version == 2) { if (version == 2) {
fseeko64(f, -8, SEEK_END); fseeko64(f, -8, SEEK_END);
} else { } else {
fseeko64(f, -6, SEEK_END); fseeko64(f, -6, SEEK_END);
} }
if (fgetc(f) != '.' || fgetc(f) != 'D' || fgetc(f) != 'I' || fgetc(f) != 'Z') if (fgetc(f) != '.' || fgetc(f) != 'D' || fgetc(f) != 'I' || fgetc(f) != 'Z')
return 0; return 0;
return (version == 2) ? readInt4(f) : readInt2(f); return (version == 2) ? readInt4(f) : readInt2(f);
} }
static bool patchApplyPPF1(FILE *f, u8 **rom, int *size) static bool patchApplyPPF1(FILE *f, u8 **rom, int *size)
{ {
fseek(f, 0, SEEK_END); fseek(f, 0, SEEK_END);
int count = ftell(f); int count = ftell(f);
if (count < 56) if (count < 56)
return false; return false;
count -= 56; count -= 56;
fseek(f, 56, SEEK_SET); fseek(f, 56, SEEK_SET);
u8 *mem = *rom; u8 *mem = *rom;
while (count > 0) { while (count > 0) {
int offset = readInt4(f); int offset = readInt4(f);
if (offset == -1) if (offset == -1)
break; break;
int len = fgetc(f); int len = fgetc(f);
if (len == EOF) if (len == EOF)
break; break;
if (offset+len > *size) if (offset+len > *size)
break; break;
if (fread(&mem[offset], 1, len, f) != (size_t)len) if (fread(&mem[offset], 1, len, f) != (size_t)len)
break; break;
count -= 4 + 1 + len; count -= 4 + 1 + len;
} }
return (count == 0); return (count == 0);
} }
static bool patchApplyPPF2(FILE *f, u8 **rom, int *size) static bool patchApplyPPF2(FILE *f, u8 **rom, int *size)
{ {
fseek(f, 0, SEEK_END); fseek(f, 0, SEEK_END);
int count = ftell(f); int count = ftell(f);
if (count < 56+4+1024) if (count < 56+4+1024)
return false; return false;
count -= 56+4+1024; count -= 56+4+1024;
fseek(f, 56, SEEK_SET); fseek(f, 56, SEEK_SET);
int datalen = readInt4(f); int datalen = readInt4(f);
if (datalen != *size) if (datalen != *size)
return false; return false;
u8 *mem = *rom; u8 *mem = *rom;
u8 block[1024]; u8 block[1024];
fread(&block, 1, 1024, f); fread(&block, 1, 1024, f);
if (memcmp(&mem[0x9320], &block, 1024) != 0) if (memcmp(&mem[0x9320], &block, 1024) != 0)
return false; return false;
int idlen = ppfFileIdLen(f, 2); int idlen = ppfFileIdLen(f, 2);
if (idlen > 0) if (idlen > 0)
count -= 16 + 16 + idlen; count -= 16 + 16 + idlen;
fseek(f, 56+4+1024, SEEK_SET); fseek(f, 56+4+1024, SEEK_SET);
while (count > 0) { while (count > 0) {
int offset = readInt4(f); int offset = readInt4(f);
if (offset == -1) if (offset == -1)
break; break;
int len = fgetc(f); int len = fgetc(f);
if (len == EOF) if (len == EOF)
break; break;
if (offset+len > *size) if (offset+len > *size)
break; break;
if (fread(&mem[offset], 1, len, f) != (size_t)len) if (fread(&mem[offset], 1, len, f) != (size_t)len)
break; break;
count -= 4 + 1 + len; count -= 4 + 1 + len;
} }
return (count == 0); return (count == 0);
} }
static bool patchApplyPPF3(FILE *f, u8 **rom, int *size) static bool patchApplyPPF3(FILE *f, u8 **rom, int *size)
{ {
fseek(f, 0, SEEK_END); fseek(f, 0, SEEK_END);
int count = ftell(f); int count = ftell(f);
if (count < 56+4+1024) if (count < 56+4+1024)
return false; return false;
count -= 56+4; count -= 56+4;
fseek(f, 56, SEEK_SET); fseek(f, 56, SEEK_SET);
int imagetype = fgetc(f); int imagetype = fgetc(f);
int blockcheck = fgetc(f); int blockcheck = fgetc(f);
int undo = fgetc(f); int undo = fgetc(f);
fgetc(f); fgetc(f);
u8 *mem = *rom; u8 *mem = *rom;
if (blockcheck) { if (blockcheck) {
u8 block[1024]; u8 block[1024];
fread(&block, 1, 1024, f); fread(&block, 1, 1024, f);
if (memcmp(&mem[(imagetype == 0) ? 0x9320 : 0x80A0], &block, 1024) != 0) if (memcmp(&mem[(imagetype == 0) ? 0x9320 : 0x80A0], &block, 1024) != 0)
return false; return false;
count -= 1024; count -= 1024;
} }
int idlen = ppfFileIdLen(f, 2); int idlen = ppfFileIdLen(f, 2);
if (idlen > 0) if (idlen > 0)
count -= 16 + 16 + idlen; count -= 16 + 16 + idlen;
fseek(f, 56+4+(blockcheck ? 1024 : 0), SEEK_SET); fseek(f, 56+4+(blockcheck ? 1024 : 0), SEEK_SET);
while (count > 0) { while (count > 0) {
__off64_t offset = readInt8(f); __off64_t offset = readInt8(f);
if (offset == -1) if (offset == -1)
break; break;
int len = fgetc(f); int len = fgetc(f);
if (len == EOF) if (len == EOF)
break; break;
if (offset+len > *size) if (offset+len > *size)
break; break;
if (fread(&mem[offset], 1, len, f) != (size_t)len) if (fread(&mem[offset], 1, len, f) != (size_t)len)
break; break;
if (undo) fseeko64(f, len, SEEK_CUR); if (undo) fseeko64(f, len, SEEK_CUR);
count -= 8 + 1 + len; count -= 8 + 1 + len;
if (undo) count -= len; if (undo) count -= len;
} }
return (count == 0); return (count == 0);
} }
static bool patchApplyPPF(const char *patchname, u8 **rom, int *size) static bool patchApplyPPF(const char *patchname, u8 **rom, int *size)
{ {
FILE *f = fopen(patchname, "rb"); FILE *f = fopen(patchname, "rb");
if (!f) if (!f)
return false; return false;
bool res = false; bool res = false;
int version = ppfVersion(f); int version = ppfVersion(f);
switch (version) { switch (version) {
case 1: res = patchApplyPPF1(f, rom, size); break; case 1: res = patchApplyPPF1(f, rom, size); break;
case 2: res = patchApplyPPF2(f, rom, size); break; case 2: res = patchApplyPPF2(f, rom, size); break;
case 3: res = patchApplyPPF3(f, rom, size); break; case 3: res = patchApplyPPF3(f, rom, size); break;
} }
fclose(f); fclose(f);
return res; return res;
} }
bool applyPatch(const char *patchname, u8 **rom, int *size) bool applyPatch(const char *patchname, u8 **rom, int *size)
{ {
if (strlen(patchname) < 5) if (strlen(patchname) < 5)
return false; return false;
const char * p = strrchr(patchname, '.'); const char * p = strrchr(patchname, '.');
if (p == NULL) if (p == NULL)
return false; return false;
if (_stricmp(p, ".ips") == 0) if (_stricmp(p, ".ips") == 0)
return patchApplyIPS(patchname, rom, size); return patchApplyIPS(patchname, rom, size);
if (_stricmp(p, ".ups") == 0) if (_stricmp(p, ".ups") == 0)
return patchApplyUPS(patchname, rom, size); return patchApplyUPS(patchname, rom, size);
if (_stricmp(p, ".ppf") == 0) if (_stricmp(p, ".ppf") == 0)
return patchApplyPPF(patchname, rom, size); return patchApplyPPF(patchname, rom, size);
return false; return false;
} }

View File

@ -1,8 +1,8 @@
#ifndef PATCH_H #ifndef PATCH_H
#define PATCH_H #define PATCH_H
#include "Types.h" #include "Types.h"
bool applyPatch(const char *patchname, u8 **rom, int *size); bool applyPatch(const char *patchname, u8 **rom, int *size);
#endif // PATCH_H #endif // PATCH_H

View File

@ -9,7 +9,7 @@
* Adapted from original gzio.c from zlib library by Forgotten * Adapted from original gzio.c from zlib library by Forgotten
*/ */
/* @(#) $Id: memgzio.c,v 1.5 2006/06/06 21:04:20 spacy51 Exp $ */ /* @(#) $Id$ */
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <stdarg.h>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,38 +1,38 @@
#include "GBASockClient.h" #include "GBASockClient.h"
// Currently only for Joybus communications // Currently only for Joybus communications
GBASockClient::GBASockClient(sf::IPAddress _server_addr) GBASockClient::GBASockClient(sf::IPAddress _server_addr)
{ {
if (!_server_addr.IsValid()) if (!_server_addr.IsValid())
server_addr = sf::IPAddress::LocalHost; server_addr = sf::IPAddress::LocalHost;
else else
server_addr = _server_addr; server_addr = _server_addr;
client.Connect(0xd6ba, server_addr); client.Connect(0xd6ba, server_addr);
//client.SetBlocking(false); //client.SetBlocking(false);
} }
GBASockClient::~GBASockClient() GBASockClient::~GBASockClient()
{ {
client.Close(); client.Close();
} }
void GBASockClient::Send(std::vector<char> data) void GBASockClient::Send(std::vector<char> data)
{ {
char* plain_data = new char[data.size()]; char* plain_data = new char[data.size()];
std::copy(data.begin(), data.end(), plain_data); std::copy(data.begin(), data.end(), plain_data);
client.Send(plain_data, data.size()); client.Send(plain_data, data.size());
delete[] plain_data; delete[] plain_data;
} }
// Returns cmd for convenience // Returns cmd for convenience
char GBASockClient::ReceiveCmd(char* data_in) char GBASockClient::ReceiveCmd(char* data_in)
{ {
std::size_t num_received; std::size_t num_received;
client.Receive(data_in, 5, num_received); client.Receive(data_in, 5, num_received);
return data_in[0]; return data_in[0];
} }

View File

@ -1,18 +1,18 @@
#pragma once #pragma once
#include <SFML/Network.hpp> #include <SFML/Network.hpp>
#include "../common/Types.h" #include "../common/Types.h"
class GBASockClient : public sf::SocketTCP class GBASockClient : public sf::SocketTCP
{ {
public: public:
GBASockClient(sf::IPAddress server_addr); GBASockClient(sf::IPAddress server_addr);
~GBASockClient(); ~GBASockClient();
void Send(std::vector<char> data); void Send(std::vector<char> data);
char ReceiveCmd(char* data_in); char ReceiveCmd(char* data_in);
private: private:
sf::IPAddress server_addr; sf::IPAddress server_addr;
sf::SocketTCP client; sf::SocketTCP client;
}; };

File diff suppressed because it is too large Load Diff

View File

@ -1,208 +1,208 @@
#include "../System.h" #include "../System.h"
#include "GBA.h" #include "GBA.h"
#include "Globals.h" #include "Globals.h"
#include "../common/Port.h" #include "../common/Port.h"
#include "../Util.h" #include "../Util.h"
#include "../NLS.h" #include "../NLS.h"
#include <time.h> #include <time.h>
#include <memory.h> #include <memory.h>
enum RTCSTATE { IDLE, COMMAND, DATA, READDATA }; enum RTCSTATE { IDLE, COMMAND, DATA, READDATA };
typedef struct { typedef struct {
u8 byte0; u8 byte0;
u8 byte1; u8 byte1;
u8 byte2; u8 byte2;
u8 command; u8 command;
int dataLen; int dataLen;
int bits; int bits;
RTCSTATE state; RTCSTATE state;
u8 data[12]; u8 data[12];
// reserved variables for future // reserved variables for future
u8 reserved[12]; u8 reserved[12];
bool reserved2; bool reserved2;
u32 reserved3; u32 reserved3;
} RTCCLOCKDATA; } RTCCLOCKDATA;
static RTCCLOCKDATA rtcClockData; static RTCCLOCKDATA rtcClockData;
static bool rtcEnabled = false; static bool rtcEnabled = false;
void rtcEnable(bool e) void rtcEnable(bool e)
{ {
rtcEnabled = e; rtcEnabled = e;
} }
bool rtcIsEnabled() bool rtcIsEnabled()
{ {
return rtcEnabled; return rtcEnabled;
} }
u16 rtcRead(u32 address) u16 rtcRead(u32 address)
{ {
if(rtcEnabled) { if(rtcEnabled) {
switch(address){ switch(address){
case 0x80000c8: case 0x80000c8:
return rtcClockData.byte2; return rtcClockData.byte2;
break; break;
case 0x80000c6: case 0x80000c6:
return rtcClockData.byte1; return rtcClockData.byte1;
break; break;
case 0x80000c4: case 0x80000c4:
return rtcClockData.byte0; return rtcClockData.byte0;
break; break;
} }
} }
return READ16LE((&rom[address & 0x1FFFFFE])); return READ16LE((&rom[address & 0x1FFFFFE]));
} }
static u8 toBCD(u8 value) static u8 toBCD(u8 value)
{ {
value = value % 100; value = value % 100;
int l = value % 10; int l = value % 10;
int h = value / 10; int h = value / 10;
return h * 16 + l; return h * 16 + l;
} }
bool rtcWrite(u32 address, u16 value) bool rtcWrite(u32 address, u16 value)
{ {
if(!rtcEnabled) if(!rtcEnabled)
return false; return false;
if(address == 0x80000c8) { if(address == 0x80000c8) {
rtcClockData.byte2 = (u8)value; // enable ? rtcClockData.byte2 = (u8)value; // enable ?
} else if(address == 0x80000c6) { } else if(address == 0x80000c6) {
rtcClockData.byte1 = (u8)value; // read/write rtcClockData.byte1 = (u8)value; // read/write
} else if(address == 0x80000c4) { } else if(address == 0x80000c4) {
if(rtcClockData.byte2 & 1) { if(rtcClockData.byte2 & 1) {
if(rtcClockData.state == IDLE && rtcClockData.byte0 == 1 && value == 5) { if(rtcClockData.state == IDLE && rtcClockData.byte0 == 1 && value == 5) {
rtcClockData.state = COMMAND; rtcClockData.state = COMMAND;
rtcClockData.bits = 0; rtcClockData.bits = 0;
rtcClockData.command = 0; rtcClockData.command = 0;
} else if(!(rtcClockData.byte0 & 1) && (value & 1)) { // bit transfer } else if(!(rtcClockData.byte0 & 1) && (value & 1)) { // bit transfer
rtcClockData.byte0 = (u8)value; rtcClockData.byte0 = (u8)value;
switch(rtcClockData.state) { switch(rtcClockData.state) {
case COMMAND: case COMMAND:
rtcClockData.command |= ((value & 2) >> 1) << (7-rtcClockData.bits); rtcClockData.command |= ((value & 2) >> 1) << (7-rtcClockData.bits);
rtcClockData.bits++; rtcClockData.bits++;
if(rtcClockData.bits == 8) { if(rtcClockData.bits == 8) {
rtcClockData.bits = 0; rtcClockData.bits = 0;
switch(rtcClockData.command) { switch(rtcClockData.command) {
case 0x60: case 0x60:
// not sure what this command does but it doesn't take parameters // not sure what this command does but it doesn't take parameters
// maybe it is a reset or stop // maybe it is a reset or stop
rtcClockData.state = IDLE; rtcClockData.state = IDLE;
rtcClockData.bits = 0; rtcClockData.bits = 0;
break; break;
case 0x62: case 0x62:
// this sets the control state but not sure what those values are // this sets the control state but not sure what those values are
rtcClockData.state = READDATA; rtcClockData.state = READDATA;
rtcClockData.dataLen = 1; rtcClockData.dataLen = 1;
break; break;
case 0x63: case 0x63:
rtcClockData.dataLen = 1; rtcClockData.dataLen = 1;
rtcClockData.data[0] = 0x40; rtcClockData.data[0] = 0x40;
rtcClockData.state = DATA; rtcClockData.state = DATA;
break; break;
case 0x64: case 0x64:
break; break;
case 0x65: case 0x65:
{ {
struct tm *newtime; struct tm *newtime;
time_t long_time; time_t long_time;
time( &long_time ); /* Get time as long integer. */ time( &long_time ); /* Get time as long integer. */
newtime = localtime( &long_time ); /* Convert to local time. */ newtime = localtime( &long_time ); /* Convert to local time. */
rtcClockData.dataLen = 7; rtcClockData.dataLen = 7;
rtcClockData.data[0] = toBCD(newtime->tm_year); rtcClockData.data[0] = toBCD(newtime->tm_year);
rtcClockData.data[1] = toBCD(newtime->tm_mon+1); rtcClockData.data[1] = toBCD(newtime->tm_mon+1);
rtcClockData.data[2] = toBCD(newtime->tm_mday); rtcClockData.data[2] = toBCD(newtime->tm_mday);
rtcClockData.data[3] = toBCD(newtime->tm_wday); rtcClockData.data[3] = toBCD(newtime->tm_wday);
rtcClockData.data[4] = toBCD(newtime->tm_hour); rtcClockData.data[4] = toBCD(newtime->tm_hour);
rtcClockData.data[5] = toBCD(newtime->tm_min); rtcClockData.data[5] = toBCD(newtime->tm_min);
rtcClockData.data[6] = toBCD(newtime->tm_sec); rtcClockData.data[6] = toBCD(newtime->tm_sec);
rtcClockData.state = DATA; rtcClockData.state = DATA;
} }
break; break;
case 0x67: case 0x67:
{ {
struct tm *newtime; struct tm *newtime;
time_t long_time; time_t long_time;
time( &long_time ); /* Get time as long integer. */ time( &long_time ); /* Get time as long integer. */
newtime = localtime( &long_time ); /* Convert to local time. */ newtime = localtime( &long_time ); /* Convert to local time. */
rtcClockData.dataLen = 3; rtcClockData.dataLen = 3;
rtcClockData.data[0] = toBCD(newtime->tm_hour); rtcClockData.data[0] = toBCD(newtime->tm_hour);
rtcClockData.data[1] = toBCD(newtime->tm_min); rtcClockData.data[1] = toBCD(newtime->tm_min);
rtcClockData.data[2] = toBCD(newtime->tm_sec); rtcClockData.data[2] = toBCD(newtime->tm_sec);
rtcClockData.state = DATA; rtcClockData.state = DATA;
} }
break; break;
default: default:
systemMessage(0, N_("Unknown RTC command %02x"), rtcClockData.command); systemMessage(0, N_("Unknown RTC command %02x"), rtcClockData.command);
rtcClockData.state = IDLE; rtcClockData.state = IDLE;
break; break;
} }
} }
break; break;
case DATA: case DATA:
if(rtcClockData.byte1 & 2) { if(rtcClockData.byte1 & 2) {
} else { } else {
rtcClockData.byte0 = (rtcClockData.byte0 & ~2) | rtcClockData.byte0 = (rtcClockData.byte0 & ~2) |
((rtcClockData.data[rtcClockData.bits >> 3] >> ((rtcClockData.data[rtcClockData.bits >> 3] >>
(rtcClockData.bits & 7)) & 1)*2; (rtcClockData.bits & 7)) & 1)*2;
rtcClockData.bits++; rtcClockData.bits++;
if(rtcClockData.bits == 8*rtcClockData.dataLen) { if(rtcClockData.bits == 8*rtcClockData.dataLen) {
rtcClockData.bits = 0; rtcClockData.bits = 0;
rtcClockData.state = IDLE; rtcClockData.state = IDLE;
} }
} }
break; break;
case READDATA: case READDATA:
if(!(rtcClockData.byte1 & 2)) { if(!(rtcClockData.byte1 & 2)) {
} else { } else {
rtcClockData.data[rtcClockData.bits >> 3] = rtcClockData.data[rtcClockData.bits >> 3] =
(rtcClockData.data[rtcClockData.bits >> 3] >> 1) | (rtcClockData.data[rtcClockData.bits >> 3] >> 1) |
((value << 6) & 128); ((value << 6) & 128);
rtcClockData.bits++; rtcClockData.bits++;
if(rtcClockData.bits == 8*rtcClockData.dataLen) { if(rtcClockData.bits == 8*rtcClockData.dataLen) {
rtcClockData.bits = 0; rtcClockData.bits = 0;
rtcClockData.state = IDLE; rtcClockData.state = IDLE;
} }
} }
break; break;
default: default:
break; break;
} }
} else } else
rtcClockData.byte0 = (u8)value; rtcClockData.byte0 = (u8)value;
} }
} }
return true; return true;
} }
void rtcReset() void rtcReset()
{ {
memset(&rtcClockData, 0, sizeof(rtcClockData)); memset(&rtcClockData, 0, sizeof(rtcClockData));
rtcClockData.byte0 = 0; rtcClockData.byte0 = 0;
rtcClockData.byte1 = 0; rtcClockData.byte1 = 0;
rtcClockData.byte2 = 0; rtcClockData.byte2 = 0;
rtcClockData.command = 0; rtcClockData.command = 0;
rtcClockData.dataLen = 0; rtcClockData.dataLen = 0;
rtcClockData.bits = 0; rtcClockData.bits = 0;
rtcClockData.state = IDLE; rtcClockData.state = IDLE;
} }
void rtcSaveGame(gzFile gzFile) void rtcSaveGame(gzFile gzFile)
{ {
utilGzWrite(gzFile, &rtcClockData, sizeof(rtcClockData)); utilGzWrite(gzFile, &rtcClockData, sizeof(rtcClockData));
} }
void rtcReadGame(gzFile gzFile) void rtcReadGame(gzFile gzFile)
{ {
utilGzRead(gzFile, &rtcClockData, sizeof(rtcClockData)); utilGzRead(gzFile, &rtcClockData, sizeof(rtcClockData));
} }

View File

@ -1,13 +1,13 @@
#ifndef RTC_H #ifndef RTC_H
#define RTC_H #define RTC_H
u16 rtcRead(u32 address); u16 rtcRead(u32 address);
bool rtcWrite(u32 address, u16 value); bool rtcWrite(u32 address, u16 value);
void rtcEnable(bool); void rtcEnable(bool);
bool rtcIsEnabled(); bool rtcIsEnabled();
void rtcReset(); void rtcReset();
void rtcReadGame(gzFile gzFile); void rtcReadGame(gzFile gzFile);
void rtcSaveGame(gzFile gzFile); void rtcSaveGame(gzFile gzFile);
#endif // RTC_H #endif // RTC_H

View File

@ -1,227 +1,227 @@
#include "gbafilter.h" #include "gbafilter.h"
#include <math.h> #include <math.h>
extern int systemColorDepth; extern int systemColorDepth;
extern int systemRedShift; extern int systemRedShift;
extern int systemGreenShift; extern int systemGreenShift;
extern int systemBlueShift; extern int systemBlueShift;
extern u16 systemColorMap16[0x10000]; extern u16 systemColorMap16[0x10000];
extern u32 systemColorMap32[0x10000]; extern u32 systemColorMap32[0x10000];
static const unsigned char curve[32] = { 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0e, 0x10, 0x12, static const unsigned char curve[32] = { 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0e, 0x10, 0x12,
0x14, 0x16, 0x18, 0x1c, 0x20, 0x28, 0x30, 0x38, 0x14, 0x16, 0x18, 0x1c, 0x20, 0x28, 0x30, 0x38,
0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x80, 0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x80,
0x88, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0}; 0x88, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0};
// output R G B // output R G B
static const unsigned char influence[3 * 3] = { 16, 4, 4, // red static const unsigned char influence[3 * 3] = { 16, 4, 4, // red
8, 16, 8, // green 8, 16, 8, // green
0, 8, 16};// blue 0, 8, 16};// blue
inline void swap(short & a, short & b) inline void swap(short & a, short & b)
{ {
short temp = a; short temp = a;
a = b; a = b;
b = temp; b = temp;
} }
void gbafilter_pal(u16 * buf, int count) void gbafilter_pal(u16 * buf, int count)
{ {
short temp[3 * 3], s; short temp[3 * 3], s;
unsigned pix; unsigned pix;
u8 red, green, blue; u8 red, green, blue;
while (count--) while (count--)
{ {
pix = *buf; pix = *buf;
s = curve[(pix >> systemGreenShift) & 0x1f]; s = curve[(pix >> systemGreenShift) & 0x1f];
temp[3] = s * influence[3]; temp[3] = s * influence[3];
temp[4] = s * influence[4]; temp[4] = s * influence[4];
temp[5] = s * influence[5]; temp[5] = s * influence[5];
s = curve[(pix >> systemRedShift) & 0x1f]; s = curve[(pix >> systemRedShift) & 0x1f];
temp[0] = s * influence[0]; temp[0] = s * influence[0];
temp[1] = s * influence[1]; temp[1] = s * influence[1];
temp[2] = s * influence[2]; temp[2] = s * influence[2];
s = curve[(pix >> systemBlueShift) & 0x1f]; s = curve[(pix >> systemBlueShift) & 0x1f];
temp[6] = s * influence[6]; temp[6] = s * influence[6];
temp[7] = s * influence[7]; temp[7] = s * influence[7];
temp[8] = s * influence[8]; temp[8] = s * influence[8];
if (temp[0] < temp[3]) swap(temp[0], temp[3]); if (temp[0] < temp[3]) swap(temp[0], temp[3]);
if (temp[0] < temp[6]) swap(temp[0], temp[6]); if (temp[0] < temp[6]) swap(temp[0], temp[6]);
if (temp[3] < temp[6]) swap(temp[3], temp[6]); if (temp[3] < temp[6]) swap(temp[3], temp[6]);
temp[3] <<= 1; temp[3] <<= 1;
temp[0] <<= 2; temp[0] <<= 2;
temp[0] += temp[3] + temp[6]; temp[0] += temp[3] + temp[6];
red = ((int(temp[0]) * 160) >> 17) + 4; red = ((int(temp[0]) * 160) >> 17) + 4;
if (red > 31) red = 31; if (red > 31) red = 31;
if (temp[2] < temp[5]) swap(temp[2], temp[5]); if (temp[2] < temp[5]) swap(temp[2], temp[5]);
if (temp[2] < temp[8]) swap(temp[2], temp[8]); if (temp[2] < temp[8]) swap(temp[2], temp[8]);
if (temp[5] < temp[8]) swap(temp[5], temp[8]); if (temp[5] < temp[8]) swap(temp[5], temp[8]);
temp[5] <<= 1; temp[5] <<= 1;
temp[2] <<= 2; temp[2] <<= 2;
temp[2] += temp[5] + temp[8]; temp[2] += temp[5] + temp[8];
blue = ((int(temp[2]) * 160) >> 17) + 4; blue = ((int(temp[2]) * 160) >> 17) + 4;
if (blue > 31) blue = 31; if (blue > 31) blue = 31;
if (temp[1] < temp[4]) swap(temp[1], temp[4]); if (temp[1] < temp[4]) swap(temp[1], temp[4]);
if (temp[1] < temp[7]) swap(temp[1], temp[7]); if (temp[1] < temp[7]) swap(temp[1], temp[7]);
if (temp[4] < temp[7]) swap(temp[4], temp[7]); if (temp[4] < temp[7]) swap(temp[4], temp[7]);
temp[4] <<= 1; temp[4] <<= 1;
temp[1] <<= 2; temp[1] <<= 2;
temp[1] += temp[4] + temp[7]; temp[1] += temp[4] + temp[7];
green = ((int(temp[1]) * 160) >> 17) + 4; green = ((int(temp[1]) * 160) >> 17) + 4;
if (green > 31) green = 31; if (green > 31) green = 31;
pix = red << systemRedShift; pix = red << systemRedShift;
pix += green << systemGreenShift; pix += green << systemGreenShift;
pix += blue << systemBlueShift; pix += blue << systemBlueShift;
*buf++ = pix; *buf++ = pix;
} }
} }
void gbafilter_pal32(u32 * buf, int count) void gbafilter_pal32(u32 * buf, int count)
{ {
short temp[3 * 3], s; short temp[3 * 3], s;
unsigned pix; unsigned pix;
u8 red, green, blue; u8 red, green, blue;
while (count--) while (count--)
{ {
pix = *buf; pix = *buf;
s = curve[(pix >> systemGreenShift) & 0x1f]; s = curve[(pix >> systemGreenShift) & 0x1f];
temp[3] = s * influence[3]; temp[3] = s * influence[3];
temp[4] = s * influence[4]; temp[4] = s * influence[4];
temp[5] = s * influence[5]; temp[5] = s * influence[5];
s = curve[(pix >> systemRedShift) & 0x1f]; s = curve[(pix >> systemRedShift) & 0x1f];
temp[0] = s * influence[0]; temp[0] = s * influence[0];
temp[1] = s * influence[1]; temp[1] = s * influence[1];
temp[2] = s * influence[2]; temp[2] = s * influence[2];
s = curve[(pix >> systemBlueShift) & 0x1f]; s = curve[(pix >> systemBlueShift) & 0x1f];
temp[6] = s * influence[6]; temp[6] = s * influence[6];
temp[7] = s * influence[7]; temp[7] = s * influence[7];
temp[8] = s * influence[8]; temp[8] = s * influence[8];
if (temp[0] < temp[3]) swap(temp[0], temp[3]); if (temp[0] < temp[3]) swap(temp[0], temp[3]);
if (temp[0] < temp[6]) swap(temp[0], temp[6]); if (temp[0] < temp[6]) swap(temp[0], temp[6]);
if (temp[3] < temp[6]) swap(temp[3], temp[6]); if (temp[3] < temp[6]) swap(temp[3], temp[6]);
temp[3] <<= 1; temp[3] <<= 1;
temp[0] <<= 2; temp[0] <<= 2;
temp[0] += temp[3] + temp[6]; temp[0] += temp[3] + temp[6];
//red = ((int(temp[0]) * 160) >> 17) + 4; //red = ((int(temp[0]) * 160) >> 17) + 4;
red = ((int(temp[0]) * 160) >> 14) + 32; red = ((int(temp[0]) * 160) >> 14) + 32;
if (temp[2] < temp[5]) swap(temp[2], temp[5]); if (temp[2] < temp[5]) swap(temp[2], temp[5]);
if (temp[2] < temp[8]) swap(temp[2], temp[8]); if (temp[2] < temp[8]) swap(temp[2], temp[8]);
if (temp[5] < temp[8]) swap(temp[5], temp[8]); if (temp[5] < temp[8]) swap(temp[5], temp[8]);
temp[5] <<= 1; temp[5] <<= 1;
temp[2] <<= 2; temp[2] <<= 2;
temp[2] += temp[5] + temp[8]; temp[2] += temp[5] + temp[8];
//blue = ((int(temp[2]) * 160) >> 17) + 4; //blue = ((int(temp[2]) * 160) >> 17) + 4;
blue = ((int(temp[2]) * 160) >> 14) + 32; blue = ((int(temp[2]) * 160) >> 14) + 32;
if (temp[1] < temp[4]) swap(temp[1], temp[4]); if (temp[1] < temp[4]) swap(temp[1], temp[4]);
if (temp[1] < temp[7]) swap(temp[1], temp[7]); if (temp[1] < temp[7]) swap(temp[1], temp[7]);
if (temp[4] < temp[7]) swap(temp[4], temp[7]); if (temp[4] < temp[7]) swap(temp[4], temp[7]);
temp[4] <<= 1; temp[4] <<= 1;
temp[1] <<= 2; temp[1] <<= 2;
temp[1] += temp[4] + temp[7]; temp[1] += temp[4] + temp[7];
//green = ((int(temp[1]) * 160) >> 17) + 4; //green = ((int(temp[1]) * 160) >> 17) + 4;
green = ((int(temp[1]) * 160) >> 14) + 32; green = ((int(temp[1]) * 160) >> 14) + 32;
//pix = red << redshift; //pix = red << redshift;
//pix += green << greenshift; //pix += green << greenshift;
//pix += blue << blueshift; //pix += blue << blueshift;
pix = red << (systemRedShift - 3); pix = red << (systemRedShift - 3);
pix += green << (systemGreenShift - 3); pix += green << (systemGreenShift - 3);
pix += blue << (systemBlueShift - 3); pix += blue << (systemBlueShift - 3);
*buf++ = pix; *buf++ = pix;
} }
} }
// for palette mode to work with the three spoony filters in 32bpp depth // for palette mode to work with the three spoony filters in 32bpp depth
void gbafilter_pad(u8 * buf, int count) void gbafilter_pad(u8 * buf, int count)
{ {
union union
{ {
struct struct
{ {
u8 r; u8 r;
u8 g; u8 g;
u8 b; u8 b;
u8 a; u8 a;
} part; } part;
unsigned whole; unsigned whole;
} }
mask; mask;
mask.whole = 0x1f << systemRedShift; mask.whole = 0x1f << systemRedShift;
mask.whole += 0x1f << systemGreenShift; mask.whole += 0x1f << systemGreenShift;
mask.whole += 0x1f << systemBlueShift; mask.whole += 0x1f << systemBlueShift;
switch (systemColorDepth) switch (systemColorDepth)
{ {
case 24: case 24:
while (count--) while (count--)
{ {
*buf++ &= mask.part.r; *buf++ &= mask.part.r;
*buf++ &= mask.part.g; *buf++ &= mask.part.g;
*buf++ &= mask.part.b; *buf++ &= mask.part.b;
} }
break; break;
case 32: case 32:
while (count--) while (count--)
{ {
*((u32*)buf) &= mask.whole; *((u32*)buf) &= mask.whole;
buf += 4; buf += 4;
} }
} }
} }
/* /*
void UpdateSystemColorMaps(int lcd) void UpdateSystemColorMaps(int lcd)
{ {
switch(systemColorDepth) { switch(systemColorDepth) {
case 16: case 16:
{ {
for(int i = 0; i < 0x10000; i++) { for(int i = 0; i < 0x10000; i++) {
systemColorMap16[i] = ((i & 0x1f) << systemRedShift) | systemColorMap16[i] = ((i & 0x1f) << systemRedShift) |
(((i & 0x3e0) >> 5) << systemGreenShift) | (((i & 0x3e0) >> 5) << systemGreenShift) |
(((i & 0x7c00) >> 10) << systemBlueShift); (((i & 0x7c00) >> 10) << systemBlueShift);
} }
if (lcd == 1) gbafilter_pal(systemColorMap16, 0x10000); if (lcd == 1) gbafilter_pal(systemColorMap16, 0x10000);
} }
break; break;
case 24: case 24:
case 32: case 32:
{ {
for(int i = 0; i < 0x10000; i++) { for(int i = 0; i < 0x10000; i++) {
systemColorMap32[i] = ((i & 0x1f) << systemRedShift) | systemColorMap32[i] = ((i & 0x1f) << systemRedShift) |
(((i & 0x3e0) >> 5) << systemGreenShift) | (((i & 0x3e0) >> 5) << systemGreenShift) |
(((i & 0x7c00) >> 10) << systemBlueShift); (((i & 0x7c00) >> 10) << systemBlueShift);
} }
if (lcd == 1) gbafilter_pal32(systemColorMap32, 0x10000); if (lcd == 1) gbafilter_pal32(systemColorMap32, 0x10000);
} }
break; break;
} }
} }
*/ */

View File

@ -1,5 +1,5 @@
#include "../System.h" #include "../System.h"
void gbafilter_pal(u16 * buf, int count); void gbafilter_pal(u16 * buf, int count);
void gbafilter_pal32(u32 * buf, int count); void gbafilter_pal32(u32 * buf, int count);
void gbafilter_pad(u8 * buf, int count); void gbafilter_pad(u8 * buf, int count);

File diff suppressed because it is too large Load Diff

View File

@ -1,57 +1,57 @@
// -*- C++ -*- // -*- C++ -*-
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten // Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team // Copyright (C) 2004 Forgotten and the VBA development team
// This program is free software; you can redistribute it and/or modify // This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2, or(at your option) // the Free Software Foundation; either version 2, or(at your option)
// any later version. // any later version.
// //
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software Foundation, // along with this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define VBA_NAME "VisualBoyAdvance-M" #define VBA_NAME "VisualBoyAdvance-M"
#ifdef WIN32 #ifdef WIN32
#include "svnrev.h" #include "svnrev.h"
#else #else
#ifdef SVN_REV #ifdef SVN_REV
#define SVN_REV_STR SVN_REV #define SVN_REV_STR SVN_REV
#else #else
#define SVN_REV_STR "" #define SVN_REV_STR ""
#endif #endif
#endif #endif
#define VBA_FEATURE_STRING "" #define VBA_FEATURE_STRING ""
#ifdef DEBUG #ifdef DEBUG
#define VBA_SUBVERSION_STRING " debug" #define VBA_SUBVERSION_STRING " debug"
#elif defined(PUBLIC_RELEASE) #elif defined(PUBLIC_RELEASE)
#define VBA_SUBVERSION_STRING "" #define VBA_SUBVERSION_STRING ""
#else #else
#define VBA_SUBVERSION_STRING " (SVN" SVN_REV_STR ")" #define VBA_SUBVERSION_STRING " (SVN" SVN_REV_STR ")"
#endif #endif
#if defined(_MSC_VER) #if defined(_MSC_VER)
#define VBA_COMPILER "" #define VBA_COMPILER ""
#define VBA_COMPILER_DETAIL " msvc " _Py_STRINGIZE(_MSC_VER) #define VBA_COMPILER_DETAIL " msvc " _Py_STRINGIZE(_MSC_VER)
#define _Py_STRINGIZE(X) _Py_STRINGIZE1((X)) #define _Py_STRINGIZE(X) _Py_STRINGIZE1((X))
#define _Py_STRINGIZE1(X) _Py_STRINGIZE2 ## X #define _Py_STRINGIZE1(X) _Py_STRINGIZE2 ## X
#define _Py_STRINGIZE2(X) #X #define _Py_STRINGIZE2(X) #X
//re: http://72.14.203.104/search?q=cache:HG-okth5NGkJ:mail.python.org/pipermail/python-checkins/2002-November/030704.html+_msc_ver+compiler+version+string&hl=en&gl=us&ct=clnk&cd=5 //re: http://72.14.203.104/search?q=cache:HG-okth5NGkJ:mail.python.org/pipermail/python-checkins/2002-November/030704.html+_msc_ver+compiler+version+string&hl=en&gl=us&ct=clnk&cd=5
#else #else
// TODO: make for others compilers // TODO: make for others compilers
#define VBA_COMPILER "" #define VBA_COMPILER ""
#define VBA_COMPILER_DETAIL "" #define VBA_COMPILER_DETAIL ""
#endif #endif
#define VBA_VERSION_STRING " " "1.8.0" VBA_SUBVERSION_STRING VBA_FEATURE_STRING VBA_COMPILER #define VBA_VERSION_STRING " " "1.8.0" VBA_SUBVERSION_STRING VBA_FEATURE_STRING VBA_COMPILER
#define VBA_NAME_AND_VERSION " " VBA_NAME VBA_VERSION_STRING #define VBA_NAME_AND_VERSION " " VBA_NAME VBA_VERSION_STRING
#define VBA_NAME_AND_SUBVERSION " " VBA_NAME VBA_SUBVERSION_STRING #define VBA_NAME_AND_SUBVERSION " " VBA_NAME VBA_SUBVERSION_STRING

View File

@ -1,191 +1,191 @@
#include "stdafx.h" #include "stdafx.h"
#include "VBA.h" #include "VBA.h"
#include "AudioCoreSettingsDlg.h" #include "AudioCoreSettingsDlg.h"
#define MIN_VOLUME 0.0f #define MIN_VOLUME 0.0f
#define MAX_VOLUME 4.0f #define MAX_VOLUME 4.0f
// AudioCoreSettingsDlg dialog // AudioCoreSettingsDlg dialog
IMPLEMENT_DYNAMIC(AudioCoreSettingsDlg, CDialog) IMPLEMENT_DYNAMIC(AudioCoreSettingsDlg, CDialog)
AudioCoreSettingsDlg::AudioCoreSettingsDlg(CWnd* pParent /*=NULL*/) AudioCoreSettingsDlg::AudioCoreSettingsDlg(CWnd* pParent /*=NULL*/)
: CDialog(AudioCoreSettingsDlg::IDD, pParent) : CDialog(AudioCoreSettingsDlg::IDD, pParent)
, m_enabled( false ) , m_enabled( false )
, m_surround( false ) , m_surround( false )
, m_declicking( false ) , m_declicking( false )
, m_sound_interpolation( false ) , m_sound_interpolation( false )
, m_echo( 0.0f ) , m_echo( 0.0f )
, m_stereo( 0.0f ) , m_stereo( 0.0f )
, m_volume( 0.0f ) , m_volume( 0.0f )
, m_sound_filtering( 0.0f ) , m_sound_filtering( 0.0f )
, m_sample_rate( 0 ) , m_sample_rate( 0 )
, toolTip( NULL ) , toolTip( NULL )
{ {
} }
AudioCoreSettingsDlg::~AudioCoreSettingsDlg() AudioCoreSettingsDlg::~AudioCoreSettingsDlg()
{ {
delete toolTip; delete toolTip;
} }
void AudioCoreSettingsDlg::DoDataExchange(CDataExchange* pDX) void AudioCoreSettingsDlg::DoDataExchange(CDataExchange* pDX)
{ {
CDialog::DoDataExchange(pDX); CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_ENHANCE_SOUND, enhance_sound); DDX_Control(pDX, IDC_ENHANCE_SOUND, enhance_sound);
DDX_Control(pDX, IDC_SURROUND, surround); DDX_Control(pDX, IDC_SURROUND, surround);
DDX_Control(pDX, IDC_ECHO, echo); DDX_Control(pDX, IDC_ECHO, echo);
DDX_Control(pDX, IDC_STEREO, stereo); DDX_Control(pDX, IDC_STEREO, stereo);
DDX_Control(pDX, IDC_VOLUME, volume); DDX_Control(pDX, IDC_VOLUME, volume);
DDX_Control(pDX, IDC_DECLICKING, declicking); DDX_Control(pDX, IDC_DECLICKING, declicking);
DDX_Control(pDX, IDC_SOUND_INTERPOLATION, sound_interpolation); DDX_Control(pDX, IDC_SOUND_INTERPOLATION, sound_interpolation);
DDX_Control(pDX, IDC_SOUND_FILTERING, sound_filtering); DDX_Control(pDX, IDC_SOUND_FILTERING, sound_filtering);
DDX_Control(pDX, IDC_SAMPLE_RATE, sample_rate); DDX_Control(pDX, IDC_SAMPLE_RATE, sample_rate);
if( pDX->m_bSaveAndValidate == TRUE ) { if( pDX->m_bSaveAndValidate == TRUE ) {
m_enabled = BST_CHECKED == enhance_sound.GetCheck(); m_enabled = BST_CHECKED == enhance_sound.GetCheck();
m_surround = BST_CHECKED == surround.GetCheck(); m_surround = BST_CHECKED == surround.GetCheck();
m_declicking = BST_CHECKED == declicking.GetCheck(); m_declicking = BST_CHECKED == declicking.GetCheck();
m_sound_interpolation = BST_CHECKED == sound_interpolation.GetCheck(); m_sound_interpolation = BST_CHECKED == sound_interpolation.GetCheck();
m_echo = (float)echo.GetPos() / 100.0f; m_echo = (float)echo.GetPos() / 100.0f;
m_stereo = (float)stereo.GetPos() / 100.0f; m_stereo = (float)stereo.GetPos() / 100.0f;
m_volume = (float)volume.GetPos() / 100.0f; m_volume = (float)volume.GetPos() / 100.0f;
m_sound_filtering = (float)sound_filtering.GetPos() / 100.0f; m_sound_filtering = (float)sound_filtering.GetPos() / 100.0f;
m_sample_rate = (unsigned int)sample_rate.GetItemData( sample_rate.GetCurSel() ); m_sample_rate = (unsigned int)sample_rate.GetItemData( sample_rate.GetCurSel() );
} }
} }
BOOL AudioCoreSettingsDlg::OnTtnNeedText(UINT id, NMHDR *pNMHDR, LRESULT *pResult) BOOL AudioCoreSettingsDlg::OnTtnNeedText(UINT id, NMHDR *pNMHDR, LRESULT *pResult)
{ {
TOOLTIPTEXT *t3 = (TOOLTIPTEXT *)pNMHDR; // dirty Windows API TOOLTIPTEXT *t3 = (TOOLTIPTEXT *)pNMHDR; // dirty Windows API
BOOL i_provided_tooltip_with_text = TRUE; BOOL i_provided_tooltip_with_text = TRUE;
if( !( t3->uFlags & TTF_IDISHWND ) ) { if( !( t3->uFlags & TTF_IDISHWND ) ) {
return FALSE; return FALSE;
} }
// even dirtier Windows API: // even dirtier Windows API:
// t3->hdr.idFrom is actually a HWND, holy cow, why? // t3->hdr.idFrom is actually a HWND, holy cow, why?
// The other case does not even occur. // The other case does not even occur.
int controlID = ::GetDlgCtrlID( (HWND)t3->hdr.idFrom ); int controlID = ::GetDlgCtrlID( (HWND)t3->hdr.idFrom );
CString res; CString res;
TCHAR buf[0x400]; // Use own string buffer because szText has an 80 char limit. TCHAR buf[0x400]; // Use own string buffer because szText has an 80 char limit.
// We can't use a dynamic buffer size because Windows does some shady things with // We can't use a dynamic buffer size because Windows does some shady things with
// t3->lpszText at the end of this function, so we have no chance to free the buffer // t3->lpszText at the end of this function, so we have no chance to free the buffer
// before the end of this function. // before the end of this function.
switch( controlID ) { switch( controlID ) {
case IDC_VOLUME: case IDC_VOLUME:
_stprintf_s( t3->szText, _countof( t3->szText ), _T( "%i%%" ), volume.GetPos() ); _stprintf_s( t3->szText, _countof( t3->szText ), _T( "%i%%" ), volume.GetPos() );
break; break;
case IDC_ECHO: case IDC_ECHO:
_stprintf_s( t3->szText, _countof( t3->szText ), _T( "%i%%" ), echo.GetPos() ); _stprintf_s( t3->szText, _countof( t3->szText ), _T( "%i%%" ), echo.GetPos() );
break; break;
case IDC_STEREO: case IDC_STEREO:
_stprintf_s( t3->szText, _countof( t3->szText ), _T( "%i%%" ), stereo.GetPos() ); _stprintf_s( t3->szText, _countof( t3->szText ), _T( "%i%%" ), stereo.GetPos() );
break; break;
case IDC_SOUND_FILTERING: case IDC_SOUND_FILTERING:
_stprintf_s( t3->szText, _countof( t3->szText ), _T( "%i%%" ), sound_filtering.GetPos() ); _stprintf_s( t3->szText, _countof( t3->szText ), _T( "%i%%" ), sound_filtering.GetPos() );
break; break;
case IDC_DEFAULT_VOLUME: case IDC_DEFAULT_VOLUME:
res.LoadString( IDS_TOOLTIP_DEFAULT_VOLUME ); res.LoadString( IDS_TOOLTIP_DEFAULT_VOLUME );
_tcscpy_s( buf, _countof( buf ), res.GetString() ); _tcscpy_s( buf, _countof( buf ), res.GetString() );
t3->lpszText = buf; t3->lpszText = buf;
break; break;
case IDC_ENHANCE_SOUND: case IDC_ENHANCE_SOUND:
res.LoadString( IDS_TOOLTIP_ENHANCE_SOUND ); res.LoadString( IDS_TOOLTIP_ENHANCE_SOUND );
_tcscpy_s( buf, _countof( buf ), res.GetString() ); _tcscpy_s( buf, _countof( buf ), res.GetString() );
t3->lpszText = buf; t3->lpszText = buf;
break; break;
case IDC_SURROUND: case IDC_SURROUND:
res.LoadString( IDS_TOOLTIP_SURROUND ); res.LoadString( IDS_TOOLTIP_SURROUND );
_tcscpy_s( buf, _countof( buf ), res.GetString() ); _tcscpy_s( buf, _countof( buf ), res.GetString() );
t3->lpszText = buf; t3->lpszText = buf;
break; break;
case IDC_DECLICKING: case IDC_DECLICKING:
res.LoadString( IDS_TOOLTIP_DECLICKING ); res.LoadString( IDS_TOOLTIP_DECLICKING );
_tcscpy_s( buf, _countof( buf ), res.GetString() ); _tcscpy_s( buf, _countof( buf ), res.GetString() );
t3->lpszText = buf; t3->lpszText = buf;
break; break;
default: default:
i_provided_tooltip_with_text = FALSE; i_provided_tooltip_with_text = FALSE;
break; break;
} }
return i_provided_tooltip_with_text; return i_provided_tooltip_with_text;
} }
BEGIN_MESSAGE_MAP(AudioCoreSettingsDlg, CDialog) BEGIN_MESSAGE_MAP(AudioCoreSettingsDlg, CDialog)
ON_NOTIFY_EX(TTN_NEEDTEXT, 0, &AudioCoreSettingsDlg::OnTtnNeedText) ON_NOTIFY_EX(TTN_NEEDTEXT, 0, &AudioCoreSettingsDlg::OnTtnNeedText)
ON_BN_CLICKED(IDC_DEFAULT_VOLUME, &AudioCoreSettingsDlg::OnBnClickedDefaultVolume) ON_BN_CLICKED(IDC_DEFAULT_VOLUME, &AudioCoreSettingsDlg::OnBnClickedDefaultVolume)
END_MESSAGE_MAP() END_MESSAGE_MAP()
// AudioCoreSettingsDlg message handlers // AudioCoreSettingsDlg message handlers
BOOL AudioCoreSettingsDlg::OnInitDialog() BOOL AudioCoreSettingsDlg::OnInitDialog()
{ {
CDialog::OnInitDialog(); CDialog::OnInitDialog();
// Set up tooltip control // Set up tooltip control
toolTip = new CToolTipCtrl; toolTip = new CToolTipCtrl;
toolTip->Create( this ); toolTip->Create( this );
toolTip->AddTool( GetDlgItem( IDC_DEFAULT_VOLUME ) ); toolTip->AddTool( GetDlgItem( IDC_DEFAULT_VOLUME ) );
toolTip->AddTool( GetDlgItem( IDC_ENHANCE_SOUND ) ); toolTip->AddTool( GetDlgItem( IDC_ENHANCE_SOUND ) );
toolTip->AddTool( GetDlgItem( IDC_SURROUND ) ); toolTip->AddTool( GetDlgItem( IDC_SURROUND ) );
toolTip->AddTool( GetDlgItem( IDC_DECLICKING ) ); toolTip->AddTool( GetDlgItem( IDC_DECLICKING ) );
toolTip->Activate( TRUE ); toolTip->Activate( TRUE );
enhance_sound.SetCheck( m_enabled ? BST_CHECKED : BST_UNCHECKED ); enhance_sound.SetCheck( m_enabled ? BST_CHECKED : BST_UNCHECKED );
surround.SetCheck( m_surround ? BST_CHECKED : BST_UNCHECKED ); surround.SetCheck( m_surround ? BST_CHECKED : BST_UNCHECKED );
declicking.SetCheck( m_declicking ? BST_CHECKED : BST_UNCHECKED ); declicking.SetCheck( m_declicking ? BST_CHECKED : BST_UNCHECKED );
sound_interpolation.SetCheck( m_sound_interpolation ? BST_CHECKED : BST_UNCHECKED ); sound_interpolation.SetCheck( m_sound_interpolation ? BST_CHECKED : BST_UNCHECKED );
echo.SetRange( 0, 100 ); echo.SetRange( 0, 100 );
echo.SetPos( (int)( m_echo * 100.0f ) ); echo.SetPos( (int)( m_echo * 100.0f ) );
stereo.SetRange( 0, 100 ); stereo.SetRange( 0, 100 );
stereo.SetPos( (int)( m_stereo * 100.0f ) ); stereo.SetPos( (int)( m_stereo * 100.0f ) );
sound_filtering.SetRange( 0, 100 ); sound_filtering.SetRange( 0, 100 );
sound_filtering.SetPos( (int)( m_sound_filtering * 100.0f ) ); sound_filtering.SetPos( (int)( m_sound_filtering * 100.0f ) );
volume.SetRange( (int)( MIN_VOLUME * 100.0f ), (int)( MAX_VOLUME * 100.0f ) ); volume.SetRange( (int)( MIN_VOLUME * 100.0f ), (int)( MAX_VOLUME * 100.0f ) );
volume.SetPos( (int)( m_volume * 100.0f ) ); volume.SetPos( (int)( m_volume * 100.0f ) );
unsigned int rate = 44100; unsigned int rate = 44100;
CString temp; CString temp;
for( int i = 0 ; i <= 2 ; i++ ) { for( int i = 0 ; i <= 2 ; i++ ) {
temp.Format( _T("%u Hz"), rate ); temp.Format( _T("%u Hz"), rate );
int id = sample_rate.AddString( temp.GetString() ); int id = sample_rate.AddString( temp.GetString() );
sample_rate.SetItemData( id, rate ); sample_rate.SetItemData( id, rate );
if( rate == m_sample_rate ) { if( rate == m_sample_rate ) {
sample_rate.SetCurSel( id ); sample_rate.SetCurSel( id );
} }
rate /= 2; rate /= 2;
} }
return TRUE; // return TRUE unless you set the focus to a control return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE // EXCEPTION: OCX Property Pages should return FALSE
} }
BOOL AudioCoreSettingsDlg::PreTranslateMessage(MSG* pMsg) BOOL AudioCoreSettingsDlg::PreTranslateMessage(MSG* pMsg)
{ {
// Required for enabling ToolTips in a modal dialog box. // Required for enabling ToolTips in a modal dialog box.
if( NULL != toolTip ) { if( NULL != toolTip ) {
toolTip->RelayEvent( pMsg ); toolTip->RelayEvent( pMsg );
} }
return CDialog::PreTranslateMessage(pMsg); return CDialog::PreTranslateMessage(pMsg);
} }
void AudioCoreSettingsDlg::OnBnClickedDefaultVolume() void AudioCoreSettingsDlg::OnBnClickedDefaultVolume()
{ {
volume.SetPos( 100 ); volume.SetPos( 100 );
} }

View File

@ -1,47 +1,47 @@
#pragma once #pragma once
// AudioCoreSettingsDlg dialog // AudioCoreSettingsDlg dialog
class AudioCoreSettingsDlg : public CDialog class AudioCoreSettingsDlg : public CDialog
{ {
DECLARE_DYNAMIC(AudioCoreSettingsDlg) DECLARE_DYNAMIC(AudioCoreSettingsDlg)
public: public:
bool m_enabled; bool m_enabled;
bool m_surround; bool m_surround;
bool m_declicking; bool m_declicking;
bool m_sound_interpolation; bool m_sound_interpolation;
float m_echo; float m_echo;
float m_stereo; float m_stereo;
float m_volume; float m_volume;
float m_sound_filtering; float m_sound_filtering;
unsigned int m_sample_rate; unsigned int m_sample_rate;
AudioCoreSettingsDlg(CWnd* pParent = NULL); // standard constructor AudioCoreSettingsDlg(CWnd* pParent = NULL); // standard constructor
virtual ~AudioCoreSettingsDlg(); virtual ~AudioCoreSettingsDlg();
virtual BOOL OnInitDialog(); virtual BOOL OnInitDialog();
virtual BOOL PreTranslateMessage(MSG* pMsg); virtual BOOL PreTranslateMessage(MSG* pMsg);
afx_msg void OnBnClickedDefaultVolume(); afx_msg void OnBnClickedDefaultVolume();
// Dialog Data // Dialog Data
enum { IDD = IDD_AUDIO_CORE_SETTINGS }; enum { IDD = IDD_AUDIO_CORE_SETTINGS };
protected: protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
afx_msg BOOL OnTtnNeedText(UINT id, NMHDR *pNMHDR, LRESULT *pResult); // Retrieve text for ToolTip afx_msg BOOL OnTtnNeedText(UINT id, NMHDR *pNMHDR, LRESULT *pResult); // Retrieve text for ToolTip
DECLARE_MESSAGE_MAP() DECLARE_MESSAGE_MAP()
private: private:
CButton enhance_sound; CButton enhance_sound;
CButton surround; CButton surround;
CButton declicking; CButton declicking;
CButton sound_interpolation; CButton sound_interpolation;
CSliderCtrl echo; CSliderCtrl echo;
CSliderCtrl stereo; CSliderCtrl stereo;
CSliderCtrl volume; CSliderCtrl volume;
CSliderCtrl sound_filtering; CSliderCtrl sound_filtering;
CToolTipCtrl *toolTip; CToolTipCtrl *toolTip;
CComboBox sample_rate; CComboBox sample_rate;
}; };

View File

@ -1,76 +1,76 @@
#include "stdafx.h" #include "stdafx.h"
#include "vba.h" #include "vba.h"
#include "JoybusOptions.h" #include "JoybusOptions.h"
#include "../gba/GBALink.h" #include "../gba/GBALink.h"
// JoybusOptions dialog // JoybusOptions dialog
IMPLEMENT_DYNAMIC(JoybusOptions, CDialog) IMPLEMENT_DYNAMIC(JoybusOptions, CDialog)
JoybusOptions::JoybusOptions(CWnd* pParent /*=NULL*/) JoybusOptions::JoybusOptions(CWnd* pParent /*=NULL*/)
: CDialog(JoybusOptions::IDD, pParent) : CDialog(JoybusOptions::IDD, pParent)
{ {
} }
JoybusOptions::~JoybusOptions() JoybusOptions::~JoybusOptions()
{ {
} }
void JoybusOptions::DoDataExchange(CDataExchange* pDX) void JoybusOptions::DoDataExchange(CDataExchange* pDX)
{ {
CDialog::DoDataExchange(pDX); CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_JOYBUS_ENABLE, enable_check); DDX_Control(pDX, IDC_JOYBUS_ENABLE, enable_check);
DDX_Control(pDX, IDC_JOYBUS_HOSTNAME, hostname); DDX_Control(pDX, IDC_JOYBUS_HOSTNAME, hostname);
} }
BEGIN_MESSAGE_MAP(JoybusOptions, CDialog) BEGIN_MESSAGE_MAP(JoybusOptions, CDialog)
ON_BN_CLICKED(IDC_JOYBUS_ENABLE, &JoybusOptions::OnBnClickedJoybusEnable) ON_BN_CLICKED(IDC_JOYBUS_ENABLE, &JoybusOptions::OnBnClickedJoybusEnable)
ON_BN_CLICKED(IDOK, &JoybusOptions::OnBnClickedOk) ON_BN_CLICKED(IDOK, &JoybusOptions::OnBnClickedOk)
END_MESSAGE_MAP() END_MESSAGE_MAP()
BOOL JoybusOptions::OnInitDialog() BOOL JoybusOptions::OnInitDialog()
{ {
CDialog::OnInitDialog(); CDialog::OnInitDialog();
enable_check.SetCheck(gba_joybus_enabled ? BST_CHECKED : BST_UNCHECKED); enable_check.SetCheck(gba_joybus_enabled ? BST_CHECKED : BST_UNCHECKED);
hostname.EnableWindow(enable_check.GetCheck() == BST_CHECKED); hostname.EnableWindow(enable_check.GetCheck() == BST_CHECKED);
hostname.SetWindowText(joybusHostAddr.ToString().c_str()); hostname.SetWindowText(joybusHostAddr.ToString().c_str());
return TRUE; return TRUE;
} }
void JoybusOptions::OnBnClickedJoybusEnable() void JoybusOptions::OnBnClickedJoybusEnable()
{ {
hostname.EnableWindow(enable_check.GetCheck() == BST_CHECKED); hostname.EnableWindow(enable_check.GetCheck() == BST_CHECKED);
} }
void JoybusOptions::OnBnClickedOk() void JoybusOptions::OnBnClickedOk()
{ {
if ( (hostname.GetWindowTextLength() == 0) if ( (hostname.GetWindowTextLength() == 0)
&& (enable_check.GetCheck() == BST_CHECKED) ) && (enable_check.GetCheck() == BST_CHECKED) )
{ {
hostname.SetWindowText("Enter IP or Hostname"); hostname.SetWindowText("Enter IP or Hostname");
return; return;
} }
gba_joybus_enabled = enable_check.GetCheck() == BST_CHECKED; gba_joybus_enabled = enable_check.GetCheck() == BST_CHECKED;
CString address; CString address;
hostname.GetWindowText(address); hostname.GetWindowText(address);
sf::IPAddress new_server; sf::IPAddress new_server;
new_server = std::string(address); new_server = std::string(address);
if (!new_server.IsValid()) if (!new_server.IsValid())
{ {
hostname.SetWindowText("Enter IP or Hostname"); hostname.SetWindowText("Enter IP or Hostname");
return; return;
} }
joybusHostAddr = new_server; joybusHostAddr = new_server;
JoyBusConnect(); JoyBusConnect();
OnOK(); OnOK();
} }

View File

@ -1,27 +1,27 @@
#pragma once #pragma once
#include "afxwin.h" #include "afxwin.h"
// JoybusOptions dialog // JoybusOptions dialog
class JoybusOptions : public CDialog class JoybusOptions : public CDialog
{ {
DECLARE_DYNAMIC(JoybusOptions) DECLARE_DYNAMIC(JoybusOptions)
public: public:
JoybusOptions(CWnd* pParent = NULL); // standard constructor JoybusOptions(CWnd* pParent = NULL); // standard constructor
virtual ~JoybusOptions(); virtual ~JoybusOptions();
// Dialog Data // Dialog Data
enum { IDD = IDD_JOYBUS_DIALOG }; enum { IDD = IDD_JOYBUS_DIALOG };
protected: protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
DECLARE_MESSAGE_MAP() DECLARE_MESSAGE_MAP()
public: public:
virtual BOOL OnInitDialog(); virtual BOOL OnInitDialog();
afx_msg void OnBnClickedJoybusEnable(); afx_msg void OnBnClickedJoybusEnable();
CButton enable_check; CButton enable_check;
CEdit hostname; CEdit hostname;
afx_msg void OnBnClickedOk(); afx_msg void OnBnClickedOk();
}; };

View File

@ -1,384 +1,384 @@
#ifndef NO_XAUDIO2 #ifndef NO_XAUDIO2
// MFC // MFC
#include "stdafx.h" #include "stdafx.h"
// Application // Application
#include "VBA.h" #include "VBA.h"
// Interface // Interface
#include "../common/SoundDriver.h" #include "../common/SoundDriver.h"
// XAudio2 // XAudio2
#include <xaudio2.h> #include <xaudio2.h>
// Internals // Internals
#include "../System.h" // for systemMessage() #include "../System.h" // for systemMessage()
#include "../gba/Globals.h" #include "../gba/Globals.h"
// Synchronization Event // Synchronization Event
class XAudio2_BufferNotify : public IXAudio2VoiceCallback class XAudio2_BufferNotify : public IXAudio2VoiceCallback
{ {
public: public:
HANDLE hBufferEndEvent; HANDLE hBufferEndEvent;
XAudio2_BufferNotify() { XAudio2_BufferNotify() {
hBufferEndEvent = NULL; hBufferEndEvent = NULL;
hBufferEndEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); hBufferEndEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
ASSERT( hBufferEndEvent != NULL ); ASSERT( hBufferEndEvent != NULL );
} }
~XAudio2_BufferNotify() { ~XAudio2_BufferNotify() {
CloseHandle( hBufferEndEvent ); CloseHandle( hBufferEndEvent );
hBufferEndEvent = NULL; hBufferEndEvent = NULL;
} }
STDMETHOD_( void, OnBufferEnd ) ( void *pBufferContext ) { STDMETHOD_( void, OnBufferEnd ) ( void *pBufferContext ) {
ASSERT( hBufferEndEvent != NULL ); ASSERT( hBufferEndEvent != NULL );
SetEvent( hBufferEndEvent ); SetEvent( hBufferEndEvent );
} }
// dummies: // dummies:
STDMETHOD_( void, OnVoiceProcessingPassStart ) ( UINT32 BytesRequired ) {} STDMETHOD_( void, OnVoiceProcessingPassStart ) ( UINT32 BytesRequired ) {}
STDMETHOD_( void, OnVoiceProcessingPassEnd ) () {} STDMETHOD_( void, OnVoiceProcessingPassEnd ) () {}
STDMETHOD_( void, OnStreamEnd ) () {} STDMETHOD_( void, OnStreamEnd ) () {}
STDMETHOD_( void, OnBufferStart ) ( void *pBufferContext ) {} STDMETHOD_( void, OnBufferStart ) ( void *pBufferContext ) {}
STDMETHOD_( void, OnLoopEnd ) ( void *pBufferContext ) {} STDMETHOD_( void, OnLoopEnd ) ( void *pBufferContext ) {}
STDMETHOD_( void, OnVoiceError ) ( void *pBufferContext, HRESULT Error ) {}; STDMETHOD_( void, OnVoiceError ) ( void *pBufferContext, HRESULT Error ) {};
}; };
// Class Declaration // Class Declaration
class XAudio2_Output class XAudio2_Output
: public SoundDriver : public SoundDriver
{ {
public: public:
XAudio2_Output(); XAudio2_Output();
~XAudio2_Output(); ~XAudio2_Output();
// Initialization // Initialization
bool init(long sampleRate); bool init(long sampleRate);
// Sound Data Feed // Sound Data Feed
void write(u16 * finalWave, int length); void write(u16 * finalWave, int length);
// Play Control // Play Control
void pause(); void pause();
void resume(); void resume();
void reset(); void reset();
// Configuration Changes // Configuration Changes
void setThrottle( unsigned short throttle ); void setThrottle( unsigned short throttle );
private: private:
bool failed; bool failed;
bool initialized; bool initialized;
bool playing; bool playing;
UINT32 freq; UINT32 freq;
UINT32 bufferCount; UINT32 bufferCount;
BYTE *buffers; BYTE *buffers;
int currentBuffer; int currentBuffer;
int soundBufferLen; int soundBufferLen;
IXAudio2 *xaud; IXAudio2 *xaud;
IXAudio2MasteringVoice *mVoice; // listener IXAudio2MasteringVoice *mVoice; // listener
IXAudio2SourceVoice *sVoice; // sound source IXAudio2SourceVoice *sVoice; // sound source
XAUDIO2_BUFFER buf; XAUDIO2_BUFFER buf;
XAUDIO2_VOICE_STATE vState; XAUDIO2_VOICE_STATE vState;
XAudio2_BufferNotify notify; // buffer end notification XAudio2_BufferNotify notify; // buffer end notification
}; };
// Class Implementation // Class Implementation
XAudio2_Output::XAudio2_Output() XAudio2_Output::XAudio2_Output()
{ {
failed = false; failed = false;
initialized = false; initialized = false;
playing = false; playing = false;
freq = 0; freq = 0;
bufferCount = theApp.xa2BufferCount; bufferCount = theApp.xa2BufferCount;
buffers = NULL; buffers = NULL;
currentBuffer = 0; currentBuffer = 0;
xaud = NULL; xaud = NULL;
mVoice = NULL; mVoice = NULL;
sVoice = NULL; sVoice = NULL;
ZeroMemory( &buf, sizeof( buf ) ); ZeroMemory( &buf, sizeof( buf ) );
ZeroMemory( &vState, sizeof( vState ) ); ZeroMemory( &vState, sizeof( vState ) );
} }
XAudio2_Output::~XAudio2_Output() XAudio2_Output::~XAudio2_Output()
{ {
initialized = false; initialized = false;
if( sVoice ) { if( sVoice ) {
if( playing ) { if( playing ) {
HRESULT hr = sVoice->Stop( 0 ); HRESULT hr = sVoice->Stop( 0 );
ASSERT( hr == S_OK ); ASSERT( hr == S_OK );
} }
sVoice->DestroyVoice(); sVoice->DestroyVoice();
} }
if( buffers ) { if( buffers ) {
free( buffers ); free( buffers );
buffers = NULL; buffers = NULL;
} }
if( mVoice ) { if( mVoice ) {
mVoice->DestroyVoice(); mVoice->DestroyVoice();
} }
if( xaud ) { if( xaud ) {
xaud->Release(); xaud->Release();
xaud = NULL; xaud = NULL;
} }
} }
bool XAudio2_Output::init(long sampleRate) bool XAudio2_Output::init(long sampleRate)
{ {
if( failed || initialized ) return false; if( failed || initialized ) return false;
HRESULT hr; HRESULT hr;
// Initialize XAudio2 // Initialize XAudio2
UINT32 flags = 0; UINT32 flags = 0;
#ifdef _DEBUG #ifdef _DEBUG
flags = XAUDIO2_DEBUG_ENGINE; flags = XAUDIO2_DEBUG_ENGINE;
#endif #endif
hr = XAudio2Create( &xaud, flags ); hr = XAudio2Create( &xaud, flags );
if( hr != S_OK ) { if( hr != S_OK ) {
systemMessage( IDS_XAUDIO2_FAILURE, NULL ); systemMessage( IDS_XAUDIO2_FAILURE, NULL );
failed = true; failed = true;
return false; return false;
} }
freq = sampleRate; freq = sampleRate;
// calculate the number of samples per frame first // calculate the number of samples per frame first
// then multiply it with the size of a sample frame (16 bit * stereo) // then multiply it with the size of a sample frame (16 bit * stereo)
soundBufferLen = ( freq / 60 ) * 4; soundBufferLen = ( freq / 60 ) * 4;
// create own buffers to store sound data because it must not be // create own buffers to store sound data because it must not be
// manipulated while the voice plays from it // manipulated while the voice plays from it
buffers = (BYTE *)malloc( ( bufferCount + 1 ) * soundBufferLen ); buffers = (BYTE *)malloc( ( bufferCount + 1 ) * soundBufferLen );
// + 1 because we need one temporary buffer when all others are in use // + 1 because we need one temporary buffer when all others are in use
WAVEFORMATEX wfx; WAVEFORMATEX wfx;
ZeroMemory( &wfx, sizeof( wfx ) ); ZeroMemory( &wfx, sizeof( wfx ) );
wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.wFormatTag = WAVE_FORMAT_PCM;
wfx.nChannels = 2; wfx.nChannels = 2;
wfx.nSamplesPerSec = freq; wfx.nSamplesPerSec = freq;
wfx.wBitsPerSample = 16; wfx.wBitsPerSample = 16;
wfx.nBlockAlign = wfx.nChannels * ( wfx.wBitsPerSample / 8 ); wfx.nBlockAlign = wfx.nChannels * ( wfx.wBitsPerSample / 8 );
wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
// create sound receiver // create sound receiver
hr = xaud->CreateMasteringVoice( hr = xaud->CreateMasteringVoice(
&mVoice, &mVoice,
XAUDIO2_DEFAULT_CHANNELS, XAUDIO2_DEFAULT_CHANNELS,
XAUDIO2_DEFAULT_SAMPLERATE, XAUDIO2_DEFAULT_SAMPLERATE,
0, 0,
theApp.xa2Device, theApp.xa2Device,
NULL ); NULL );
if( hr != S_OK ) { if( hr != S_OK ) {
systemMessage( IDS_XAUDIO2_CANNOT_CREATE_MASTERINGVOICE, NULL ); systemMessage( IDS_XAUDIO2_CANNOT_CREATE_MASTERINGVOICE, NULL );
failed = true; failed = true;
return false; return false;
} }
// create sound emitter // create sound emitter
hr = xaud->CreateSourceVoice( &sVoice, &wfx, 0, 4.0f, &notify ); hr = xaud->CreateSourceVoice( &sVoice, &wfx, 0, 4.0f, &notify );
if( hr != S_OK ) { if( hr != S_OK ) {
systemMessage( IDS_XAUDIO2_CANNOT_CREATE_SOURCEVOICE, NULL ); systemMessage( IDS_XAUDIO2_CANNOT_CREATE_SOURCEVOICE, NULL );
failed = true; failed = true;
return false; return false;
} }
if( theApp.xa2Upmixing ) { if( theApp.xa2Upmixing ) {
// set up stereo upmixing // set up stereo upmixing
XAUDIO2_DEVICE_DETAILS dd; XAUDIO2_DEVICE_DETAILS dd;
ZeroMemory( &dd, sizeof( dd ) ); ZeroMemory( &dd, sizeof( dd ) );
hr = xaud->GetDeviceDetails( 0, &dd ); hr = xaud->GetDeviceDetails( 0, &dd );
ASSERT( hr == S_OK ); ASSERT( hr == S_OK );
float *matrix = NULL; float *matrix = NULL;
matrix = (float*)malloc( sizeof( float ) * 2 * dd.OutputFormat.Format.nChannels ); matrix = (float*)malloc( sizeof( float ) * 2 * dd.OutputFormat.Format.nChannels );
if( matrix == NULL ) return false; if( matrix == NULL ) return false;
bool matrixAvailable = true; bool matrixAvailable = true;
switch( dd.OutputFormat.Format.nChannels ) { switch( dd.OutputFormat.Format.nChannels ) {
case 4: // 4.0 case 4: // 4.0
//Speaker \ Left Source Right Source //Speaker \ Left Source Right Source
/*Front L*/ matrix[0] = 1.0000f; matrix[1] = 0.0000f; /*Front L*/ matrix[0] = 1.0000f; matrix[1] = 0.0000f;
/*Front R*/ matrix[2] = 0.0000f; matrix[3] = 1.0000f; /*Front R*/ matrix[2] = 0.0000f; matrix[3] = 1.0000f;
/*Back L*/ matrix[4] = 1.0000f; matrix[5] = 0.0000f; /*Back L*/ matrix[4] = 1.0000f; matrix[5] = 0.0000f;
/*Back R*/ matrix[6] = 0.0000f; matrix[7] = 1.0000f; /*Back R*/ matrix[6] = 0.0000f; matrix[7] = 1.0000f;
break; break;
case 5: // 5.0 case 5: // 5.0
//Speaker \ Left Source Right Source //Speaker \ Left Source Right Source
/*Front L*/ matrix[0] = 1.0000f; matrix[1] = 0.0000f; /*Front L*/ matrix[0] = 1.0000f; matrix[1] = 0.0000f;
/*Front R*/ matrix[2] = 0.0000f; matrix[3] = 1.0000f; /*Front R*/ matrix[2] = 0.0000f; matrix[3] = 1.0000f;
/*Front C*/ matrix[4] = 0.7071f; matrix[5] = 0.7071f; /*Front C*/ matrix[4] = 0.7071f; matrix[5] = 0.7071f;
/*Side L*/ matrix[6] = 1.0000f; matrix[7] = 0.0000f; /*Side L*/ matrix[6] = 1.0000f; matrix[7] = 0.0000f;
/*Side R*/ matrix[8] = 0.0000f; matrix[9] = 1.0000f; /*Side R*/ matrix[8] = 0.0000f; matrix[9] = 1.0000f;
break; break;
case 6: // 5.1 case 6: // 5.1
//Speaker \ Left Source Right Source //Speaker \ Left Source Right Source
/*Front L*/ matrix[0] = 1.0000f; matrix[1] = 0.0000f; /*Front L*/ matrix[0] = 1.0000f; matrix[1] = 0.0000f;
/*Front R*/ matrix[2] = 0.0000f; matrix[3] = 1.0000f; /*Front R*/ matrix[2] = 0.0000f; matrix[3] = 1.0000f;
/*Front C*/ matrix[4] = 0.7071f; matrix[5] = 0.7071f; /*Front C*/ matrix[4] = 0.7071f; matrix[5] = 0.7071f;
/*LFE */ matrix[6] = 0.0000f; matrix[7] = 0.0000f; /*LFE */ matrix[6] = 0.0000f; matrix[7] = 0.0000f;
/*Side L*/ matrix[8] = 1.0000f; matrix[9] = 0.0000f; /*Side L*/ matrix[8] = 1.0000f; matrix[9] = 0.0000f;
/*Side R*/ matrix[10] = 0.0000f; matrix[11] = 1.0000f; /*Side R*/ matrix[10] = 0.0000f; matrix[11] = 1.0000f;
break; break;
case 7: // 6.1 case 7: // 6.1
//Speaker \ Left Source Right Source //Speaker \ Left Source Right Source
/*Front L*/ matrix[0] = 1.0000f; matrix[1] = 0.0000f; /*Front L*/ matrix[0] = 1.0000f; matrix[1] = 0.0000f;
/*Front R*/ matrix[2] = 0.0000f; matrix[3] = 1.0000f; /*Front R*/ matrix[2] = 0.0000f; matrix[3] = 1.0000f;
/*Front C*/ matrix[4] = 0.7071f; matrix[5] = 0.7071f; /*Front C*/ matrix[4] = 0.7071f; matrix[5] = 0.7071f;
/*LFE */ matrix[6] = 0.0000f; matrix[7] = 0.0000f; /*LFE */ matrix[6] = 0.0000f; matrix[7] = 0.0000f;
/*Side L*/ matrix[8] = 1.0000f; matrix[9] = 0.0000f; /*Side L*/ matrix[8] = 1.0000f; matrix[9] = 0.0000f;
/*Side R*/ matrix[10] = 0.0000f; matrix[11] = 1.0000f; /*Side R*/ matrix[10] = 0.0000f; matrix[11] = 1.0000f;
/*Back C*/ matrix[12] = 0.7071f; matrix[13] = 0.7071f; /*Back C*/ matrix[12] = 0.7071f; matrix[13] = 0.7071f;
break; break;
case 8: // 7.1 case 8: // 7.1
//Speaker \ Left Source Right Source //Speaker \ Left Source Right Source
/*Front L*/ matrix[0] = 1.0000f; matrix[1] = 0.0000f; /*Front L*/ matrix[0] = 1.0000f; matrix[1] = 0.0000f;
/*Front R*/ matrix[2] = 0.0000f; matrix[3] = 1.0000f; /*Front R*/ matrix[2] = 0.0000f; matrix[3] = 1.0000f;
/*Front C*/ matrix[4] = 0.7071f; matrix[5] = 0.7071f; /*Front C*/ matrix[4] = 0.7071f; matrix[5] = 0.7071f;
/*LFE */ matrix[6] = 0.0000f; matrix[7] = 0.0000f; /*LFE */ matrix[6] = 0.0000f; matrix[7] = 0.0000f;
/*Back L*/ matrix[8] = 1.0000f; matrix[9] = 0.0000f; /*Back L*/ matrix[8] = 1.0000f; matrix[9] = 0.0000f;
/*Back R*/ matrix[10] = 0.0000f; matrix[11] = 1.0000f; /*Back R*/ matrix[10] = 0.0000f; matrix[11] = 1.0000f;
/*Side L*/ matrix[12] = 1.0000f; matrix[13] = 0.0000f; /*Side L*/ matrix[12] = 1.0000f; matrix[13] = 0.0000f;
/*Side R*/ matrix[14] = 0.0000f; matrix[15] = 1.0000f; /*Side R*/ matrix[14] = 0.0000f; matrix[15] = 1.0000f;
break; break;
default: default:
matrixAvailable = false; matrixAvailable = false;
break; break;
} }
if( matrixAvailable ) { if( matrixAvailable ) {
hr = sVoice->SetOutputMatrix( NULL, 2, dd.OutputFormat.Format.nChannels, matrix ); hr = sVoice->SetOutputMatrix( NULL, 2, dd.OutputFormat.Format.nChannels, matrix );
ASSERT( hr == S_OK ); ASSERT( hr == S_OK );
} }
free( matrix ); free( matrix );
matrix = NULL; matrix = NULL;
} }
hr = sVoice->Start( 0 ); hr = sVoice->Start( 0 );
ASSERT( hr == S_OK ); ASSERT( hr == S_OK );
playing = true; playing = true;
initialized = true; initialized = true;
return true; return true;
} }
void XAudio2_Output::write(u16 * finalWave, int length) void XAudio2_Output::write(u16 * finalWave, int length)
{ {
if( !initialized || failed ) return; if( !initialized || failed ) return;
while( true ) { while( true ) {
sVoice->GetState( &vState ); sVoice->GetState( &vState );
ASSERT( vState.BuffersQueued <= bufferCount ); ASSERT( vState.BuffersQueued <= bufferCount );
if( vState.BuffersQueued < bufferCount ) { if( vState.BuffersQueued < bufferCount ) {
if( vState.BuffersQueued == 0 ) { if( vState.BuffersQueued == 0 ) {
// buffers ran dry // buffers ran dry
if( systemVerbose & VERBOSE_SOUNDOUTPUT ) { if( systemVerbose & VERBOSE_SOUNDOUTPUT ) {
static unsigned int i = 0; static unsigned int i = 0;
log( "XAudio2: Buffers were not refilled fast enough (i=%i)\n", i++ ); log( "XAudio2: Buffers were not refilled fast enough (i=%i)\n", i++ );
} }
} }
// there is at least one free buffer // there is at least one free buffer
break; break;
} else { } else {
// the maximum number of buffers is currently queued // the maximum number of buffers is currently queued
if( synchronize && !speedup && !theApp.throttle ) { if( synchronize && !speedup && !theApp.throttle ) {
// wait for one buffer to finish playing // wait for one buffer to finish playing
WaitForSingleObject( notify.hBufferEndEvent, INFINITE ); WaitForSingleObject( notify.hBufferEndEvent, INFINITE );
} else { } else {
// drop current audio frame // drop current audio frame
return; return;
} }
} }
} }
// copy & protect the audio data in own memory area while playing it // copy & protect the audio data in own memory area while playing it
CopyMemory( &buffers[ currentBuffer * soundBufferLen ], finalWave, soundBufferLen ); CopyMemory( &buffers[ currentBuffer * soundBufferLen ], finalWave, soundBufferLen );
buf.AudioBytes = soundBufferLen; buf.AudioBytes = soundBufferLen;
buf.pAudioData = &buffers[ currentBuffer * soundBufferLen ]; buf.pAudioData = &buffers[ currentBuffer * soundBufferLen ];
currentBuffer++; currentBuffer++;
currentBuffer %= ( bufferCount + 1 ); // + 1 because we need one temporary buffer currentBuffer %= ( bufferCount + 1 ); // + 1 because we need one temporary buffer
HRESULT hr = sVoice->SubmitSourceBuffer( &buf ); // send buffer to queue HRESULT hr = sVoice->SubmitSourceBuffer( &buf ); // send buffer to queue
ASSERT( hr == S_OK ); ASSERT( hr == S_OK );
} }
void XAudio2_Output::pause() void XAudio2_Output::pause()
{ {
if( !initialized || failed ) return; if( !initialized || failed ) return;
if( playing ) { if( playing ) {
HRESULT hr = sVoice->Stop( 0 ); HRESULT hr = sVoice->Stop( 0 );
ASSERT( hr == S_OK ); ASSERT( hr == S_OK );
playing = false; playing = false;
} }
} }
void XAudio2_Output::resume() void XAudio2_Output::resume()
{ {
if( !initialized || failed ) return; if( !initialized || failed ) return;
if( !playing ) { if( !playing ) {
HRESULT hr = sVoice->Start( 0 ); HRESULT hr = sVoice->Start( 0 );
ASSERT( hr == S_OK ); ASSERT( hr == S_OK );
playing = true; playing = true;
} }
} }
void XAudio2_Output::reset() void XAudio2_Output::reset()
{ {
if( !initialized || failed ) return; if( !initialized || failed ) return;
if( playing ) { if( playing ) {
HRESULT hr = sVoice->Stop( 0 ); HRESULT hr = sVoice->Stop( 0 );
ASSERT( hr == S_OK ); ASSERT( hr == S_OK );
} }
sVoice->FlushSourceBuffers(); sVoice->FlushSourceBuffers();
sVoice->Start( 0 ); sVoice->Start( 0 );
playing = true; playing = true;
} }
void XAudio2_Output::setThrottle( unsigned short throttle ) void XAudio2_Output::setThrottle( unsigned short throttle )
{ {
if( !initialized || failed ) return; if( !initialized || failed ) return;
if( throttle == 0 ) throttle = 100; if( throttle == 0 ) throttle = 100;
HRESULT hr = sVoice->SetFrequencyRatio( (float)throttle / 100.0f ); HRESULT hr = sVoice->SetFrequencyRatio( (float)throttle / 100.0f );
ASSERT( hr == S_OK ); ASSERT( hr == S_OK );
} }
SoundDriver *newXAudio2_Output() SoundDriver *newXAudio2_Output()
{ {
return new XAudio2_Output(); return new XAudio2_Output();
} }
#endif // #ifndef NO_XAUDIO2 #endif // #ifndef NO_XAUDIO2

View File

@ -1,151 +1,151 @@
#include "stdafx.h" #include "stdafx.h"
#ifndef NO_XAUDIO2 #ifndef NO_XAUDIO2
#include "VBA.h" #include "VBA.h"
#include "XAudio2_Config.h" #include "XAudio2_Config.h"
#include <xaudio2.h> #include <xaudio2.h>
// XAudio2_Config dialog // XAudio2_Config dialog
IMPLEMENT_DYNAMIC(XAudio2_Config, CDialog) IMPLEMENT_DYNAMIC(XAudio2_Config, CDialog)
XAudio2_Config::XAudio2_Config(CWnd* pParent /*=NULL*/) XAudio2_Config::XAudio2_Config(CWnd* pParent /*=NULL*/)
: CDialog(XAudio2_Config::IDD, pParent) : CDialog(XAudio2_Config::IDD, pParent)
, m_selected_device_index(0) , m_selected_device_index(0)
, m_enable_upmixing(false) , m_enable_upmixing(false)
, m_buffer_count(0) , m_buffer_count(0)
{ {
} }
XAudio2_Config::~XAudio2_Config() XAudio2_Config::~XAudio2_Config()
{ {
} }
void XAudio2_Config::DoDataExchange(CDataExchange* pDX) void XAudio2_Config::DoDataExchange(CDataExchange* pDX)
{ {
CDialog::DoDataExchange(pDX); CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_COMBO_DEV, m_combo_dev); DDX_Control(pDX, IDC_COMBO_DEV, m_combo_dev);
DDX_Control(pDX, IDC_SLIDER_BUFFER, m_slider_buffer); DDX_Control(pDX, IDC_SLIDER_BUFFER, m_slider_buffer);
DDX_Control(pDX, IDC_INFO_BUFFER, m_info_buffer); DDX_Control(pDX, IDC_INFO_BUFFER, m_info_buffer);
DDX_Control(pDX, IDC_CHECK_UPMIX, m_check_upmix); DDX_Control(pDX, IDC_CHECK_UPMIX, m_check_upmix);
if( pDX->m_bSaveAndValidate == TRUE ) { if( pDX->m_bSaveAndValidate == TRUE ) {
if( CB_ERR != m_combo_dev.GetCurSel() ) { if( CB_ERR != m_combo_dev.GetCurSel() ) {
if( CB_ERR != m_combo_dev.GetItemData( m_combo_dev.GetCurSel() ) ) { if( CB_ERR != m_combo_dev.GetItemData( m_combo_dev.GetCurSel() ) ) {
m_selected_device_index = m_combo_dev.GetItemData( m_combo_dev.GetCurSel() ); m_selected_device_index = m_combo_dev.GetItemData( m_combo_dev.GetCurSel() );
} }
} }
m_enable_upmixing = ( m_check_upmix.GetCheck() == BST_CHECKED ); m_enable_upmixing = ( m_check_upmix.GetCheck() == BST_CHECKED );
m_buffer_count = (UINT32)m_slider_buffer.GetPos(); m_buffer_count = (UINT32)m_slider_buffer.GetPos();
} else { } else {
m_check_upmix.SetCheck( m_enable_upmixing ? BST_CHECKED : BST_UNCHECKED ); m_check_upmix.SetCheck( m_enable_upmixing ? BST_CHECKED : BST_UNCHECKED );
} }
} }
BEGIN_MESSAGE_MAP(XAudio2_Config, CDialog) BEGIN_MESSAGE_MAP(XAudio2_Config, CDialog)
ON_WM_HSCROLL() ON_WM_HSCROLL()
END_MESSAGE_MAP() END_MESSAGE_MAP()
// XAudio2_Config message handlers // XAudio2_Config message handlers
BOOL XAudio2_Config::OnInitDialog() BOOL XAudio2_Config::OnInitDialog()
{ {
CDialog::OnInitDialog(); CDialog::OnInitDialog();
m_combo_dev.ResetContent(); m_combo_dev.ResetContent();
m_slider_buffer.SetRange( 2, 10, FALSE ); m_slider_buffer.SetRange( 2, 10, FALSE );
m_slider_buffer.SetTicFreq( 1 ); m_slider_buffer.SetTicFreq( 1 );
m_slider_buffer.SetPos( (int)m_buffer_count ); m_slider_buffer.SetPos( (int)m_buffer_count );
CString info; CString info;
int pos = m_slider_buffer.GetPos(); int pos = m_slider_buffer.GetPos();
info.Format( _T("%i frames = %.2f ms"), pos, (float)pos / 60.0f * 1000.0f ); info.Format( _T("%i frames = %.2f ms"), pos, (float)pos / 60.0f * 1000.0f );
m_info_buffer.SetWindowText( info ); m_info_buffer.SetWindowText( info );
HRESULT hr; HRESULT hr;
IXAudio2 *xa = NULL; IXAudio2 *xa = NULL;
UINT32 flags = 0; UINT32 flags = 0;
#ifdef _DEBUG #ifdef _DEBUG
flags = XAUDIO2_DEBUG_ENGINE; flags = XAUDIO2_DEBUG_ENGINE;
#endif #endif
hr = XAudio2Create( &xa, flags ); hr = XAudio2Create( &xa, flags );
if( hr != S_OK ) { if( hr != S_OK ) {
systemMessage( IDS_XAUDIO2_FAILURE, NULL ); systemMessage( IDS_XAUDIO2_FAILURE, NULL );
} else { } else {
UINT32 dev_count = 0; UINT32 dev_count = 0;
hr = xa->GetDeviceCount( &dev_count ); hr = xa->GetDeviceCount( &dev_count );
if( hr != S_OK ) { if( hr != S_OK ) {
systemMessage( IDS_XAUDIO2_CANNOT_ENUMERATE_DEVICES, NULL ); systemMessage( IDS_XAUDIO2_CANNOT_ENUMERATE_DEVICES, NULL );
} else { } else {
XAUDIO2_DEVICE_DETAILS dd; XAUDIO2_DEVICE_DETAILS dd;
for( UINT32 i = 0; i < dev_count; i++ ) { for( UINT32 i = 0; i < dev_count; i++ ) {
hr = xa->GetDeviceDetails( i, &dd ); hr = xa->GetDeviceDetails( i, &dd );
if( hr != S_OK ) { if( hr != S_OK ) {
continue; continue;
} else { } else {
#ifdef _UNICODE #ifdef _UNICODE
int id = m_combo_dev.AddString( dd.DisplayName ); int id = m_combo_dev.AddString( dd.DisplayName );
#else #else
CHAR temp[256]; CHAR temp[256];
ZeroMemory( temp, sizeof( temp ) ); ZeroMemory( temp, sizeof( temp ) );
WideCharToMultiByte( WideCharToMultiByte(
CP_ACP, CP_ACP,
WC_NO_BEST_FIT_CHARS, WC_NO_BEST_FIT_CHARS,
dd.DisplayName, dd.DisplayName,
-1, -1,
temp, temp,
sizeof( temp ) - 1, sizeof( temp ) - 1,
NULL, NULL,
NULL ); NULL );
int id = m_combo_dev.AddString( temp ); int id = m_combo_dev.AddString( temp );
#endif #endif
if( id < 0 ) { if( id < 0 ) {
systemMessage( IDS_XAUDIO2_CANNOT_ENUMERATE_DEVICES, NULL ); systemMessage( IDS_XAUDIO2_CANNOT_ENUMERATE_DEVICES, NULL );
break; break;
} else { } else {
m_combo_dev.SetItemData( id, i ); m_combo_dev.SetItemData( id, i );
} }
} }
} }
// select the currently configured device { // select the currently configured device {
int count = m_combo_dev.GetCount(); int count = m_combo_dev.GetCount();
if( count > 0 ) { if( count > 0 ) {
for( int i = 0; i < count; i++ ) { for( int i = 0; i < count; i++ ) {
if( m_combo_dev.GetItemData( i ) == m_selected_device_index ) { if( m_combo_dev.GetItemData( i ) == m_selected_device_index ) {
m_combo_dev.SetCurSel( i ); m_combo_dev.SetCurSel( i );
break; break;
} }
} }
} }
// } // }
} }
xa->Release(); xa->Release();
xa = NULL; xa = NULL;
} }
return TRUE; // return TRUE unless you set the focus to a control return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE // EXCEPTION: OCX Property Pages should return FALSE
} }
void XAudio2_Config::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) void XAudio2_Config::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{ {
CString info; CString info;
int pos = m_slider_buffer.GetPos(); int pos = m_slider_buffer.GetPos();
info.Format( _T("%i frames = %.2f ms"), pos, (float)pos / 60.0f * 1000.0f ); info.Format( _T("%i frames = %.2f ms"), pos, (float)pos / 60.0f * 1000.0f );
m_info_buffer.SetWindowText( info ); m_info_buffer.SetWindowText( info );
CDialog::OnHScroll(nSBCode, nPos, pScrollBar); CDialog::OnHScroll(nSBCode, nPos, pScrollBar);
} }
#endif #endif

View File

@ -1,37 +1,37 @@
#ifndef NO_XAUDIO2 #ifndef NO_XAUDIO2
#pragma once #pragma once
class XAudio2_Config : public CDialog class XAudio2_Config : public CDialog
{ {
DECLARE_DYNAMIC(XAudio2_Config) DECLARE_DYNAMIC(XAudio2_Config)
DECLARE_MESSAGE_MAP() DECLARE_MESSAGE_MAP()
public: public:
UINT32 m_selected_device_index; UINT32 m_selected_device_index;
UINT32 m_buffer_count; UINT32 m_buffer_count;
bool m_enable_upmixing; bool m_enable_upmixing;
private: private:
CComboBox m_combo_dev; CComboBox m_combo_dev;
CSliderCtrl m_slider_buffer; CSliderCtrl m_slider_buffer;
CStatic m_info_buffer; CStatic m_info_buffer;
CButton m_check_upmix; CButton m_check_upmix;
public: public:
XAudio2_Config(CWnd* pParent = NULL); // standard constructor XAudio2_Config(CWnd* pParent = NULL); // standard constructor
virtual ~XAudio2_Config(); virtual ~XAudio2_Config();
// Dialog Data // Dialog Data
enum { IDD = IDD_XAUDIO2_CONFIG }; enum { IDD = IDD_XAUDIO2_CONFIG };
virtual BOOL OnInitDialog(); virtual BOOL OnInitDialog();
afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
protected: protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
}; };
#endif #endif

View File

@ -1,24 +1,24 @@
#pragma once #pragma once
// The following macros define the minimum required platform. The minimum required platform // The following macros define the minimum required platform. The minimum required platform
// is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run // is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run
// your application. The macros work by enabling all features available on platform versions up to and // your application. The macros work by enabling all features available on platform versions up to and
// including the version specified. // including the version specified.
// Modify the following defines if you have to target a platform prior to the ones specified below. // Modify the following defines if you have to target a platform prior to the ones specified below.
// Refer to MSDN for the latest info on corresponding values for different platforms. // Refer to MSDN for the latest info on corresponding values for different platforms.
#ifndef WINVER // Specifies that the minimum required platform is Windows 2000. #ifndef WINVER // Specifies that the minimum required platform is Windows 2000.
#define WINVER 0x0500 // Change this to the appropriate value to target other versions of Windows. #define WINVER 0x0500 // Change this to the appropriate value to target other versions of Windows.
#endif #endif
#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows 2000. #ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows 2000.
#define _WIN32_WINNT 0x0500 // Change this to the appropriate value to target other versions of Windows. #define _WIN32_WINNT 0x0500 // Change this to the appropriate value to target other versions of Windows.
#endif #endif
#ifndef _WIN32_WINDOWS // Specifies that the minimum required platform is Windows 98. #ifndef _WIN32_WINDOWS // Specifies that the minimum required platform is Windows 98.
#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later. #define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later.
#endif #endif
#ifndef _WIN32_IE // Specifies that the minimum required platform is Internet Explorer 5.0. #ifndef _WIN32_IE // Specifies that the minimum required platform is Internet Explorer 5.0.
#define _WIN32_IE 0x0500 // Change this to the appropriate value to target other versions of IE. #define _WIN32_IE 0x0500 // Change this to the appropriate value to target other versions of IE.
#endif // Actually, we don't care #endif // Actually, we don't care