Fixed buffer overflow issue in DXTCImage, added nicer error messages.

This commit is contained in:
Exynox 2024-07-07 21:09:33 +03:00
parent c698136614
commit d19dc772db
8 changed files with 18 additions and 912 deletions

1
bin/.gitignore vendored
View File

@ -7,6 +7,7 @@ metin2.cfg
BGM/lastplay.inf BGM/lastplay.inf
# Log files # Log files
ErrorLog.txt
log.txt log.txt
syserr.txt syserr.txt

Binary file not shown.

View File

@ -7,32 +7,13 @@
FILE * fException; FILE * fException;
/*
static char __msg[4000], __cmsg[4000];
static int __idx;
CLZObject __l;
*/
/*
typedef BOOL
(CALLBACK *PENUMLOADED_MODULES_CALLBACK)(
__in PCSTR ModuleName,
__in ULONG ModuleBase,
__in ULONG ModuleSize,
__in_opt PVOID UserContext
);
*/
#if _MSC_VER >= 1400
BOOL CALLBACK EnumerateLoadedModulesProc(PCSTR ModuleName, ULONG ModuleBase, ULONG ModuleSize, PVOID UserContext) BOOL CALLBACK EnumerateLoadedModulesProc(PCSTR ModuleName, ULONG ModuleBase, ULONG ModuleSize, PVOID UserContext)
#else
BOOL CALLBACK EnumerateLoadedModulesProc(PSTR ModuleName, ULONG ModuleBase, ULONG ModuleSize, PVOID UserContext)
#endif
{ {
DWORD offset = *((DWORD*)UserContext); DWORD offset = *((DWORD*)UserContext);
if (offset >= ModuleBase && offset <= ModuleBase + ModuleSize) if (offset >= ModuleBase && offset <= ModuleBase + ModuleSize)
{ {
fprintf(fException, "%s", ModuleName); fprintf(fException, "%s", ModuleName);
//__idx += sprintf(__msg+__idx, "%s", ModuleName);
return FALSE; return FALSE;
} }
else else
@ -56,21 +37,11 @@ LONG __stdcall EterExceptionFilter(_EXCEPTION_POINTERS* pExceptionInfo)
module_time = (time_t)GetTimestampForLoadedLibrary(hModule); module_time = (time_t)GetTimestampForLoadedLibrary(hModule);
fprintf(fException, "Module Name: %s\n", module_name); fprintf(fException, "Module Name: %s\n", module_name);
fprintf(fException, "Time Stamp: 0x%08x - %s\n", module_time, ctime(&module_time)); fprintf(fException, "Time Stamp: %lld - %s\n", module_time, ctime(&module_time));
fprintf(fException, "\n"); fprintf(fException, "\n");
fprintf(fException, "Exception Type: 0x%08x\n", pExceptionInfo->ExceptionRecord->ExceptionCode); fprintf(fException, "Exception Type: 0x%08x\n", pExceptionInfo->ExceptionRecord->ExceptionCode);
fprintf(fException, "\n"); fprintf(fException, "\n");
/*
{
__idx+=sprintf(__msg+__idx,"Module Name: %s\n", module_name);
__idx+=sprintf(__msg+__idx, "Time Stamp: 0x%08x - %s\n", module_time, ctime(&module_time));
__idx+=sprintf(__msg+__idx, "\n");
__idx+=sprintf(__msg+__idx, "Exception Type: 0x%08x\n", pExceptionInfo->ExceptionRecord->ExceptionCode);
__idx+=sprintf(__msg+__idx, "\n");
}
*/
CONTEXT& context = *pExceptionInfo->ContextRecord; CONTEXT& context = *pExceptionInfo->ContextRecord;
fprintf(fException, "eax: 0x%08x\tebx: 0x%08x\n", context.Eax, context.Ebx); fprintf(fException, "eax: 0x%08x\tebx: 0x%08x\n", context.Eax, context.Ebx);
@ -78,15 +49,6 @@ LONG __stdcall EterExceptionFilter(_EXCEPTION_POINTERS* pExceptionInfo)
fprintf(fException, "esi: 0x%08x\tedi: 0x%08x\n", context.Esi, context.Edi); fprintf(fException, "esi: 0x%08x\tedi: 0x%08x\n", context.Esi, context.Edi);
fprintf(fException, "ebp: 0x%08x\tesp: 0x%08x\n", context.Ebp, context.Esp); fprintf(fException, "ebp: 0x%08x\tesp: 0x%08x\n", context.Ebp, context.Esp);
fprintf(fException, "\n"); fprintf(fException, "\n");
/*
{
__idx+=sprintf(__msg+__idx, "eax: 0x%08x\tebx: 0x%08x\n", context.Eax, context.Ebx);
__idx+=sprintf(__msg+__idx, "ecx: 0x%08x\tedx: 0x%08x\n", context.Ecx, context.Edx);
__idx+=sprintf(__msg+__idx, "esi: 0x%08x\tedi: 0x%08x\n", context.Esi, context.Edi);
__idx+=sprintf(__msg+__idx, "ebp: 0x%08x\tesp: 0x%08x\n", context.Ebp, context.Esp);
__idx+=sprintf(__msg+__idx, "\n");
}
*/
STACKFRAME stackFrame = {0,}; STACKFRAME stackFrame = {0,};
stackFrame.AddrPC.Offset = context.Eip; stackFrame.AddrPC.Offset = context.Eip;
@ -101,11 +63,8 @@ LONG __stdcall EterExceptionFilter(_EXCEPTION_POINTERS* pExceptionInfo)
if (StackWalk(IMAGE_FILE_MACHINE_I386, hProcess, hThread, &stackFrame, &context, NULL, NULL, NULL, NULL) != FALSE) if (StackWalk(IMAGE_FILE_MACHINE_I386, hProcess, hThread, &stackFrame, &context, NULL, NULL, NULL, NULL) != FALSE)
{ {
fprintf(fException, "0x%08x\t", stackFrame.AddrPC.Offset); fprintf(fException, "0x%08x\t", stackFrame.AddrPC.Offset);
//__idx+=sprintf(__msg+__idx, "0x%08x\t", stackFrame.AddrPC.Offset);
EnumerateLoadedModules(hProcess, (PENUMLOADED_MODULES_CALLBACK) EnumerateLoadedModulesProc, &stackFrame.AddrPC.Offset); EnumerateLoadedModules(hProcess, (PENUMLOADED_MODULES_CALLBACK) EnumerateLoadedModulesProc, &stackFrame.AddrPC.Offset);
fprintf(fException, "\n"); fprintf(fException, "\n");
//__idx+=sprintf(__msg+__idx, "\n");
} }
else else
{ {
@ -114,89 +73,13 @@ LONG __stdcall EterExceptionFilter(_EXCEPTION_POINTERS* pExceptionInfo)
} }
fprintf(fException, "\n"); fprintf(fException, "\n");
//__idx+=sprintf(__msg+__idx, "\n");
/*
BYTE* stack = (BYTE*)(context.Esp);
fprintf(fException, "stack %08x - %08x\n", context.Esp, context.Esp+1024);
//__idx+=sprintf(__msg+__idx, "stack %08x - %08x\n", context.Esp, context.Esp+1024);
for(i=0; i<16; ++i)
{
fprintf(fException, "%08X : ", context.Esp+i*16);
//__idx+=sprintf(__msg+__idx, "%08X : ", context.Esp+i*16);
for(int j=0; j<16; ++j)
{
fprintf(fException, "%02X ", stack[i*16+j]);
//__idx+=sprintf(__msg+__idx, "%02X ", stack[i*16+j]);
}
fprintf(fException, "\n");
//__idx+=sprintf(__msg+__idx, "\n");
}
fprintf(fException, "\n");
//__idx+=sprintf(__msg+__idx, "\n");
*/
fflush(fException); fflush(fException);
fclose(fException); fclose(fException);
fException = NULL; fException = NULL;
//WinExec() MessageBox(NULL, "A fatal error was encountered while running the game.\nAn error log was saved to ErrorLog.txt.\nPlease consider reporting this issue.", "Error!", MB_OK);
/*CreateProcess("cmd.exe",NULL,NULL,NULL,FALSE,
CREATE_NEW_PROCESS_GROUP|DETACHED_PROCESS,NULL,NULL,NULL,NULL);
MessageBox(NULL,"게임 실행에 치명적인 문제가 발생하였습니다.\n게임을 종료하고 에러 로그를 남깁니다.\n에러 로그를 서버에 보내시겠습니까?","에러 발생!",MB_YESNO);*/
/*
__l.BeginCompressInBuffer(__msg,__idx,__cmsg);
if (__l.Compress())
{
//fprintf(fException,"Compress printing\n");
// send this to server
SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
ioctlsocket(s,FIONBIO,0);
if (s==INVALID_SOCKET)
{
//fprintf(fException,"INVALID %X\n",WSAGetLastError());
}
sockaddr_in sa;
sa.sin_family = AF_INET;
sa.sin_port = htons(19294);
sa.sin_addr.s_addr = inet_addr("147.46.127.42");
if (connect(s,(sockaddr*)&sa,sizeof(sa)))
{
//fprintf(fException,"%X\n",WSAGetLastError());
}
int total = 0;
int ret=0;
while(1)
{
//ret = send(s,(char*)__msg+total,__idx-total,0);
ret = send(s,(char*)__l.GetBuffer()+total,__l.GetSize()-total,0);
//fprintf(fException,"send %d\n",ret);
if (ret<0)
{
//fprintf(fException,"%X\n",WSAGetLastError());
break;
}
total+=ret;
if (total>=__idx)
//if (total>=__l.GetSize())
break;
}
//__l.GetBuffer();
Sleep(500);
closesocket(s);
}*/
WinExec("errorlog.exe",SW_SHOW);
} }
return EXCEPTION_EXECUTE_HANDLER; return EXCEPTION_EXECUTE_HANDLER;

View File

@ -83,51 +83,7 @@ void CDXTCImage::Clear()
Initialize(); Initialize();
} }
bool CDXTCImage::LoadFromFile(const char * filename) bool CDXTCImage::LoadHeaderFromMemory(const BYTE * c_pbMap, int iSize)
{
// only understands .dds files for now
// return true if success
char * exts[] = { ".DDS" };
int next = 1;
static char fileupper[MAX_PATH+1];
strncpy(fileupper, filename, MAX_PATH);
strupr(fileupper);
int i;
bool knownformat = false;
for (i = 0; i < next; ++i)
{
char * found = strstr(fileupper, exts[0]);
if (found != NULL)
{
knownformat = true;
break;
}
}
if (knownformat == false)
{
Tracef("Unknown file format encountered! [%s]\n", filename);
return(false);
}
CMappedFile mappedFile;
LPCVOID pvMap;
if (!mappedFile.Create(filename, &pvMap, 0, 0))
{
Tracef("Can't open file for reading! [%s]\n", filename);
return false;
}
return LoadFromMemory((const BYTE*) pvMap);
}
bool CDXTCImage::LoadHeaderFromMemory(const BYTE * c_pbMap)
{ {
////////////////////////////////////// //////////////////////////////////////
// start reading the file // start reading the file
@ -135,18 +91,26 @@ bool CDXTCImage::LoadHeaderFromMemory(const BYTE * c_pbMap)
DWORD dwMagic; DWORD dwMagic;
// Read magic number // Read magic number
if (iSize < sizeof(DWORD))
return false;
dwMagic = *(DWORD *) c_pbMap; dwMagic = *(DWORD *) c_pbMap;
c_pbMap += sizeof(DWORD); c_pbMap += sizeof(DWORD);
iSize -= sizeof(DWORD);
//!@# // Check whether the magic header is correct
// if (dwMagic != MAKEFOURCC('D','D','S',' ')) if (dwMagic != MAKEFOURCC('D','D','S',' '))
// return false; return false;
DDSURFACEDESC2 ddsd; // read from dds file DDSURFACEDESC2 ddsd; // read from dds file
// Read the surface description // Read the surface description
if (iSize < sizeof(DDSURFACEDESC2))
return false;
memcpy(&ddsd, c_pbMap, sizeof(DDSURFACEDESC2)); memcpy(&ddsd, c_pbMap, sizeof(DDSURFACEDESC2));
c_pbMap += sizeof(DDSURFACEDESC2); c_pbMap += sizeof(DDSURFACEDESC2);
iSize -= sizeof(DDSURFACEDESC2);
// Does texture have mipmaps? // Does texture have mipmaps?
m_bMipTexture = (ddsd.dwMipMapCount > 0) ? TRUE : FALSE; m_bMipTexture = (ddsd.dwMipMapCount > 0) ? TRUE : FALSE;
@ -211,52 +175,6 @@ bool CDXTCImage::LoadHeaderFromMemory(const BYTE * c_pbMap)
return true; return true;
} }
//////////////////////////////////////////////////////////////////////
bool CDXTCImage::LoadFromMemory(const BYTE * c_pbMap)
{
if (!LoadHeaderFromMemory(c_pbMap))
return false;
if (m_dwFlags & DDSD_PITCH)
{
DWORD dwBytesPerRow = m_nWidth * m_xddPixelFormat.dwRGBBitCount / 8;
m_nCompSize = m_lPitch * m_nHeight;
m_nCompLineSz = dwBytesPerRow;
m_bCompVector[0].resize(m_nCompSize);
BYTE * pDest = &m_bCompVector[0][0];
c_pbMap = m_pbCompBufferByLevels[0];
for (int yp = 0; yp < m_nHeight; ++yp)
{
memcpy(pDest, c_pbMap, dwBytesPerRow);
pDest += m_lPitch;
c_pbMap += m_lPitch;
}
}
else
{
if (m_dwFlags & DDSD_MIPMAPCOUNT)
{
for (DWORD dwLinearSize = m_lPitch, i = 0; i < m_dwMipMapCount; ++i, dwLinearSize >>= 2)
{
m_bCompVector[i].resize(dwLinearSize);
Copy(i, &m_bCompVector[i][0], dwLinearSize);
}
}
else
{
m_bCompVector[0].resize(m_lPitch);
Copy(0, &m_bCompVector[0][0], m_lPitch);
}
}
// done reading file
return true;
}
bool CDXTCImage::Copy(int miplevel, BYTE * pbDest, long lDestPitch) bool CDXTCImage::Copy(int miplevel, BYTE * pbDest, long lDestPitch)
{ {
if (!(m_dwFlags & DDSD_MIPMAPCOUNT)) if (!(m_dwFlags & DDSD_MIPMAPCOUNT))
@ -959,688 +877,3 @@ VOID CDXTCImage::DecodePixelFormat(CHAR* strPixelFormat, XDDPIXELFORMAT* pxddpf)
break; break;
} }
} }
/*
// Struct to hold various timing values
struct TimingInfo
{
LARGE_INTEGER m_start_clk;
LARGE_INTEGER m_end_clk;
int m_nSamples;
LARGE_INTEGER m_interval_sum; // sum of all end-start, nSamples number added in
CString m_csName; // text desc of what timed
};
void CDXTCImage::RunTimingSession()
{
// Must have a dxt5 texture loaded
// No special reason - just lazy coding
// Functions called to time code are separate from non-timed
// code. It's alogorithm that counts.
ASSERT(m_pCompBytes != NULL);
ASSERT(m_pDecompBytes != NULL); // must already have allocated memory
switch (m_CompFormat)
{
case PF_DXT1:
case PF_DXT2:
case PF_DXT3:
case PF_DXT4:
case PF_UNKNOWN:
Tracef("You must have a DXT5 texture loaded to RunTimingSession()!!\n");
Tracef("Now I will be nasty and ASSERT(false)!\n");
ASSERT(false);
break;
case PF_DXT5:
Tracef("Running code timing session on DXT5 color decompress\n");
break;
}
LARGE_INTEGER start_clk, end_clk;
QueryPerformanceCounter(&start_clk);
#define NMETHOD 4
#define NBATCHES 4
int passes[NBATCHES];
passes[0] = 1;
passes[1] = 10;
passes[2] = 30;
passes[3] = 50;
TimingInfo method[NMETHOD][NBATCHES];
int i, n;
FILE * pf = fopen("timing.txt", "wt");
if (pf == NULL)
{
return;
}
fprintf(pf, "\n\n");
for (i = 0; i < NBATCHES; ++i)
{
Sleep(50);
fprintf(pf,"i: %d passes[i]: %d\n", i, passes[i]);
Time_Decomp5_01(passes[i], &(method[0][i]));
Time_Decomp5_02(passes[i], &(method[1][i]));
Time_Decomp5_03(passes[i], &(method[2][i]));
Time_Decomp5_04(passes[i], &(method[3][i]));
}
QueryPerformanceCounter(&end_clk);
// unsigned long total;
// total = (unsigned long) (end_clk - start_clk);
LARGE_INTEGER freq;
QueryPerformanceFrequency(& freq);
fprintf(pf, "\nCounter freq = %u %d \n", freq.LowPart, freq.HighPart);
fprintf(pf, "start: %u %u end: %u %u\n", start_clk.LowPart, start_clk.HighPart, end_clk.LowPart, end_clk.HighPart);
Tracef("\nCounter freq = %u %d \n", freq.LowPart, freq.HighPart);
Tracef("start: %u %u end: %u %u\n", start_clk.LowPart, start_clk.HighPart, end_clk.LowPart, end_clk.HighPart);
double dur = ((double)end_clk.LowPart - (double)start_clk.LowPart) / (double)freq.LowPart;
fprintf(pf, "Total timing session took: %u cycles = %f seconds\n", (end_clk.LowPart - start_clk.LowPart), dur);
fprintf(pf, "\n\n");
Tracef("Total timing session took: %u cycles = %f seconds\n", (end_clk.LowPart - start_clk.LowPart), dur);
Tracef("\n\n");
for (n = 0; n < NMETHOD; ++n)
{
for (i = 0; i < NBATCHES; ++i)
{
fprintf(pf, "method %d:\n", n);
fprintf(pf, " %s", method[n][i].m_csName);
fprintf(pf, " tot: %u %u\n", method[n][i].m_interval_sum.HighPart, method[n][i].m_interval_sum.LowPart);
Tracef("method %d:\n", n);
Tracef(" %s", method[n][i].m_csName);
Tracef(" tot: %u %u\n", method[n][i].m_interval_sum.HighPart, method[n][i].m_interval_sum.LowPart);
dur = ((double)method[n][i].m_interval_sum.LowPart) / ((double)method[n][i].m_nSamples * (double)freq.LowPart);
fprintf(pf, " avg: %u\n", method[n][i].m_interval_sum.LowPart / method[n][i].m_nSamples);
fprintf(pf, " avg time: %f sec\n", dur);
Tracef(" avg: %u\n", method[n][i].m_interval_sum.LowPart / method[n][i].m_nSamples);
Tracef(" avg time: %f sec\n", dur);
}
fprintf(pf, "\n\n");
Tracef("\n\n");
}
fclose(pf);
MessageBeep(MB_OK);
//BOOL QueryPerformanceFrequency(
// LARGE_INTEGER *lpFrequency // address of current frequency
//);
}
inline void GetColorBlockColors_m2(DXTColBlock * pBlock, Color8888 * col_0, Color8888 * col_1,
Color8888 * col_2, Color8888 * col_3,
WORD & wrd )
{
// method 2
// freak variable bit structure method
// normal math
Color565 * pCol;
pCol = (Color565*) & (pBlock->col0);
col_0->a = 0xff;
col_0->r = pCol->nRed;
col_0->r <<= 3; // shift to full precision
col_0->g = pCol->nGreen;
col_0->g <<= 2;
col_0->b = pCol->nBlue;
col_0->b <<= 3;
pCol = (Color565*) & (pBlock->col1);
col_1->a = 0xff;
col_1->r = pCol->nRed;
col_1->r <<= 3; // shift to full precision
col_1->g = pCol->nGreen;
col_1->g <<= 2;
col_1->b = pCol->nBlue;
col_1->b <<= 3;
if (pBlock->col0 > pBlock->col1)
{
// Four-color block: derive the other two colors.
// 00 = color_0, 01 = color_1, 10 = color_2, 11 = color_3
// These two bit codes correspond to the 2-bit fields
// stored in the 64-bit block.
wrd = ((WORD) col_0->r * 2 + (WORD) col_1->r) / 3;
// no +1 for rounding
// as bits have been shifted to 888
col_2->r = (BYTE)wrd;
wrd = ((WORD) col_0->g * 2 + (WORD) col_1->g) / 3;
col_2->g = (BYTE)wrd;
wrd = ((WORD) col_0->b * 2 + (WORD) col_1->b) / 3;
col_2->b = (BYTE)wrd;
col_2->a = 0xff;
wrd = ((WORD) col_0->r + (WORD) col_1->r * 2) / 3;
col_3->r = (BYTE)wrd;
wrd = ((WORD) col_0->g + (WORD) col_1->g * 2) / 3;
col_3->g = (BYTE)wrd;
wrd = ((WORD) col_0->b + (WORD) col_1->b * 2) / 3;
col_3->b = (BYTE)wrd;
col_3->a = 0xff;
}
else
{
// Three-color block: derive the other color.
// 00 = color_0, 01 = color_1, 10 = color_2,
// 11 = transparent.
// These two bit codes correspond to the 2-bit fields
// stored in the 64-bit block.
// explicit for each component, unlike some refrasts...
// Tracef("block has alpha\n");
wrd = ((WORD) col_0->r + (WORD) col_1->r) / 2;
col_2->r = (BYTE)wrd;
wrd = ((WORD) col_0->g + (WORD) col_1->g) / 2;
col_2->g = (BYTE)wrd;
wrd = ((WORD) col_0->b + (WORD) col_1->b) / 2;
col_2->b = (BYTE)wrd;
col_2->a = 0xff;
col_3->r = 0x00; // random color to indicate alpha
col_3->g = 0xff;
col_3->b = 0xff;
col_3->a = 0x00;
}
}
inline void GetColorBlockColors_m3(DXTColBlock * pBlock, Color8888 * col_0, Color8888 * col_1,
Color8888 * col_2, Color8888 * col_3,
WORD & wrd )
{
// method 3
//////////////////////////////////////////////////////
// super-freak variable bit structure with
// Cool Math Trick (tm)
// Do 2/3 1/3 math BEFORE bit shift on the whole DWORD
// as the fields will NEVER carry into the next
// or overflow!! =)
Color565 * pCol;
pCol = (Color565*) & (pBlock->col0);
col_0->a = 0x00; // must set to 0 to avoid overflow in DWORD add
col_0->r = pCol->nRed;
col_0->g = pCol->nGreen;
col_0->b = pCol->nBlue;
pCol = (Color565*) & (pBlock->col1);
col_1->a = 0x00;
col_1->r = pCol->nRed;
col_1->g = pCol->nGreen;
col_1->b = pCol->nBlue;
if (pBlock->col0 > pBlock->col1)
{
*((DWORD*)col_2) = ((*((DWORD*)col_0)) * 2 + (*((DWORD*)col_1)));
*((DWORD*)col_3) = ((*((DWORD*)col_0)) + (*((DWORD*)col_1)) * 2);
// now shift to appropriate precision & divide by 3.
col_2->r = ((WORD) col_2->r << 3) / (WORD)3;
col_2->g = ((WORD) col_2->g << 2) / (WORD)3;
col_2->b = ((WORD) col_2->b << 3) / (WORD)3;
col_3->r = ((WORD) col_3->r << 3) / (WORD)3;
col_3->g = ((WORD) col_3->g << 2) / (WORD)3;
col_3->b = ((WORD) col_3->b << 3) / (WORD)3;
col_0->a = 0xff; // now set appropriate alpha
col_1->a = 0xff;
col_2->a = 0xff;
col_3->a = 0xff;
}
else
{
*((DWORD*)col_2) = ((*((DWORD*)col_0)) + (*((DWORD*)col_1)));
// now shift to appropriate precision & divide by 2.
// << 3) / 2 == << 2
// << 2) / 2 == << 1
col_2->r = ((WORD) col_2->r << 2);
col_2->g = ((WORD) col_2->g << 1);
col_2->b = ((WORD) col_2->b << 2);
col_2->a = 0xff;
col_3->a = 0x00; //
col_3->r = 0x00; // random color to indicate alpha
col_3->g = 0xff;
col_3->b = 0xff;
}
// now shift orig color components
col_0->r <<= 3;
col_0->g <<= 2;
col_0->b <<= 3;
col_1->r <<= 3;
col_1->g <<= 2;
col_1->b <<= 3;
}
inline void GetColorBlockColors_m4(DXTColBlock * pBlock, Color8888 * col_0, Color8888 * col_1,
Color8888 * col_2, Color8888 * col_3,
WORD & wrd )
{
// m1 color extraction from 5-6-5
// m3 color math on DWORD before bit shift to full precision
wrd = pBlock->col0;
col_0->a = 0x00; // must set to 0 to avoid possible overflow & carry to next field in DWORD add
// extract r,g,b bits
col_0->b = (unsigned char) wrd & 0x1f; // 0x1f = 0001 1111 to mask out upper 3 bits
wrd >>= 5;
col_0->g = (unsigned char) wrd & 0x3f; // 0x3f = 0011 1111 to mask out upper 2 bits
wrd >>= 6;
col_0->r = (unsigned char) wrd & 0x1f;
// same for col # 2:
wrd = pBlock->col1;
col_1->a = 0x00; // must set to 0 to avoid possible overflow in DWORD add
// extract r,g,b bits
col_1->b = (unsigned char) wrd & 0x1f;
wrd >>= 5;
col_1->g = (unsigned char) wrd & 0x3f;
wrd >>= 6;
col_1->r = (unsigned char) wrd & 0x1f;
if (pBlock->col0 > pBlock->col1)
{
*((DWORD*)col_2) = ((*((DWORD*)col_0)) * 2 + (*((DWORD*)col_1)));
*((DWORD*)col_3) = ((*((DWORD*)col_0)) + (*((DWORD*)col_1)) * 2);
// shift to appropriate precision & divide by 3.
col_2->r = ((WORD) col_2->r << 3) / (WORD)3;
col_2->g = ((WORD) col_2->g << 2) / (WORD)3;
col_2->b = ((WORD) col_2->b << 3) / (WORD)3;
col_3->r = ((WORD) col_3->r << 3) / (WORD)3;
col_3->g = ((WORD) col_3->g << 2) / (WORD)3;
col_3->b = ((WORD) col_3->b << 3) / (WORD)3;
col_0->a = 0xff; // set appropriate alpha
col_1->a = 0xff;
col_2->a = 0xff;
col_3->a = 0xff;
}
else
{
*((DWORD*)col_2) = ((*((DWORD*)col_0)) + (*((DWORD*)col_1)));
// shift to appropriate precision & divide by 2.
// << 3) / 2 == << 2
// << 2) / 2 == << 1
col_2->r = ((WORD) col_2->r << 2);
col_2->g = ((WORD) col_2->g << 1);
col_2->b = ((WORD) col_2->b << 2);
col_2->a = 0xff;
col_3->a = 0x00; //
col_3->r = 0x00; // random color to indicate alpha
col_3->g = 0xff;
col_3->b = 0xff;
}
// shift orig color components to full precision
col_0->r <<= 3;
col_0->g <<= 2;
col_0->b <<= 3;
col_1->r <<= 3;
col_1->g <<= 2;
col_1->b <<= 3;
}
inline void GetColorBlockColors_m1(DXTColBlock * pBlock, Color8888 * col_0, Color8888 * col_1,
Color8888 * col_2, Color8888 * col_3,
WORD & wrd )
{
// Method 1:
// Shifty method
wrd = pBlock->col0;
col_0->a = 0xff;
// extract r,g,b bits
col_0->b = (unsigned char) wrd;
col_0->b <<= 3; // shift to full precision
wrd >>= 5;
col_0->g = (unsigned char) wrd;
col_0->g <<= 2; // shift to full precision
wrd >>= 6;
col_0->r = (unsigned char) wrd;
col_0->r <<= 3; // shift to full precision
// same for col # 2:
wrd = pBlock->col1;
col_1->a = 0xff;
// extract r,g,b bits
col_1->b = (unsigned char) wrd;
col_1->b <<= 3; // shift to full precision
wrd >>= 5;
col_1->g = (unsigned char) wrd;
col_1->g <<= 2; // shift to full precision
wrd >>= 6;
col_1->r = (unsigned char) wrd;
col_1->r <<= 3; // shift to full precision
// use this for all but the super-freak math method
if (pBlock->col0 > pBlock->col1)
{
// Four-color block: derive the other two colors.
// 00 = color_0, 01 = color_1, 10 = color_2, 11 = color_3
// These two bit codes correspond to the 2-bit fields
// stored in the 64-bit block.
wrd = ((WORD) col_0->r * 2 + (WORD) col_1->r) / 3;
// no +1 for rounding
// as bits have been shifted to 888
col_2->r = (BYTE)wrd;
wrd = ((WORD) col_0->g * 2 + (WORD) col_1->g) / 3;
col_2->g = (BYTE)wrd;
wrd = ((WORD) col_0->b * 2 + (WORD) col_1->b) / 3;
col_2->b = (BYTE)wrd;
col_2->a = 0xff;
wrd = ((WORD) col_0->r + (WORD) col_1->r * 2) / 3;
col_3->r = (BYTE)wrd;
wrd = ((WORD) col_0->g + (WORD) col_1->g * 2) / 3;
col_3->g = (BYTE)wrd;
wrd = ((WORD) col_0->b + (WORD) col_1->b * 2) / 3;
col_3->b = (BYTE)wrd;
col_3->a = 0xff;
}
else
{
// Three-color block: derive the other color.
// 00 = color_0, 01 = color_1, 10 = color_2,
// 11 = transparent.
// These two bit codes correspond to the 2-bit fields
// stored in the 64-bit block.
// explicit for each component, unlike some refrasts...
// Tracef("block has alpha\n");
wrd = ((WORD) col_0->r + (WORD) col_1->r) / 2;
col_2->r = (BYTE)wrd;
wrd = ((WORD) col_0->g + (WORD) col_1->g) / 2;
col_2->g = (BYTE)wrd;
wrd = ((WORD) col_0->b + (WORD) col_1->b) / 2;
col_2->b = (BYTE)wrd;
col_2->a = 0xff;
col_3->r = 0x00; // random color to indicate alpha
col_3->g = 0xff;
col_3->b = 0xff;
col_3->a = 0x00;
}
} // Get color block colors (...)
void CDXTCImage::Time_Decomp5_01(int ntimes, TimingInfo * info)
{
int n;
info->m_nSamples = 0;
info->m_interval_sum.QuadPart = 0;
info->m_csName.Format("Timing decomp method 1: bit shift, for %d times\n", ntimes);
for (n = 0; n < ntimes; n++)
{
QueryPerformanceCounter(& info->m_start_clk);
int xblocks, yblocks;
xblocks = m_DDSD.dwWidth / 4;
yblocks = m_DDSD.dwHeight / 4;
int i,j;
DWORD * pBase = (DWORD*) m_pDecompBytes;
DWORD * pImPos = (DWORD*) pBase; // pos in decompressed data
WORD * pPos = (WORD*) m_pCompBytes; // pos in compressed data
DXTColBlock * pBlock;
DXTAlphaBlock3BitLinear * pAlphaBlock;
Color8888 col_0, col_1, col_2, col_3;
WORD wrd;
// fill alphazero with appropriate value to zero out alpha when
// alphazero is ANDed with the image color 32 bit DWORD:
col_0.a = 0;
col_0.r = col_0.g = col_0.b = 0xff;
DWORD alphazero = *((DWORD*) &col_0);
// ** See DecompressDXT5 code for comments!!
for (j = 0; j < yblocks; ++j)
{
pBlock = (DXTColBlock*) ((DWORD)m_pCompBytes + j * xblocks * 16);
for (i = 0; i < xblocks; ++i, ++pBlock)
{
pAlphaBlock = (DXTAlphaBlock3BitLinear*) pBlock;
pBlock++;
GetColorBlockColors_m1(pBlock, &col_0, &col_1, &col_2, &col_3, wrd);
pImPos = (DWORD*)((DWORD)pBase + i*16 + (j*4) * m_nWidth * 4);
DecodeColorBlock(pImPos, pBlock, m_nWidth, (DWORD*)&col_0, (DWORD*)&col_1,
(DWORD*)&col_2, (DWORD*)&col_3);
DecodeAlpha3BitLinear(pImPos, pAlphaBlock, m_nWidth, alphazero);
}
}
QueryPerformanceCounter(& info->m_end_clk);
info->m_nSamples ++;
info->m_interval_sum.QuadPart += info->m_end_clk.QuadPart - info->m_start_clk.QuadPart;
}
}
void CDXTCImage::Time_Decomp5_02(int ntimes, TimingInfo * info)
{
int n;
info->m_nSamples = 0;
info->m_interval_sum.QuadPart = 0;
info->m_csName.Format("Timing decomp method 2: bit field struct, for %d times\n", ntimes);
for (n = 0; n < ntimes; n++)
{
QueryPerformanceCounter(& info->m_start_clk);
int xblocks, yblocks;
xblocks = m_DDSD.dwWidth / 4;
yblocks = m_DDSD.dwHeight / 4;
int i,j;
DWORD * pBase = (DWORD*) m_pDecompBytes;
DWORD * pImPos = (DWORD*) pBase; // pos in decompressed data
WORD * pPos = (WORD*) m_pCompBytes; // pos in compressed data
DXTColBlock * pBlock;
DXTAlphaBlock3BitLinear * pAlphaBlock;
Color8888 col_0, col_1, col_2, col_3;
WORD wrd;
// fill alphazero with appropriate value to zero out alpha when
// alphazero is ANDed with the image color 32 bit DWORD:
col_0.a = 0;
col_0.r = col_0.g = col_0.b = 0xff;
DWORD alphazero = *((DWORD*) &col_0);
// ** See DecompressDXT5 code for comments!!
for (j = 0; j < yblocks; ++j)
{
pBlock = (DXTColBlock*) ((DWORD)m_pCompBytes + j * xblocks * 16);
for (i = 0; i < xblocks; ++i, ++pBlock)
{
pAlphaBlock = (DXTAlphaBlock3BitLinear*) pBlock;
pBlock++;
GetColorBlockColors_m2(pBlock, &col_0, &col_1, &col_2, &col_3, wrd);
pImPos = (DWORD*)((DWORD)pBase + i*16 + (j*4) * m_nWidth * 4);
DecodeColorBlock(pImPos, pBlock, m_nWidth, (DWORD*)&col_0, (DWORD*)&col_1,
(DWORD*)&col_2, (DWORD*)&col_3);
DecodeAlpha3BitLinear(pImPos, pAlphaBlock, m_nWidth, alphazero);
}
}
QueryPerformanceCounter(& info->m_end_clk);
info->m_nSamples ++;
info->m_interval_sum.QuadPart += info->m_end_clk.QuadPart - info->m_start_clk.QuadPart;
}
}
void CDXTCImage::Time_Decomp5_03(int ntimes, TimingInfo * info)
{
int n;
info->m_nSamples = 0;
info->m_interval_sum.QuadPart = 0;
info->m_csName.Format("Timing decomp method 3: bit field struct w/ pre-shift math, for %d times\n", ntimes);
for (n = 0; n < ntimes; n++)
{
QueryPerformanceCounter(& info->m_start_clk);
int xblocks, yblocks;
xblocks = m_DDSD.dwWidth / 4;
yblocks = m_DDSD.dwHeight / 4;
int i,j;
DWORD * pBase = (DWORD*) m_pDecompBytes;
DWORD * pImPos = (DWORD*) pBase; // pos in decompressed data
WORD * pPos = (WORD*) m_pCompBytes; // pos in compressed data
DXTColBlock * pBlock;
DXTAlphaBlock3BitLinear * pAlphaBlock;
Color8888 col_0, col_1, col_2, col_3;
WORD wrd;
// fill alphazero with appropriate value to zero out alpha when
// alphazero is ANDed with the image color 32 bit DWORD:
col_0.a = 0;
col_0.r = col_0.g = col_0.b = 0xff;
DWORD alphazero = *((DWORD*) &col_0);
// ** See DecompressDXT5 code for comments!!
for (j = 0; j < yblocks; ++j)
{
pBlock = (DXTColBlock*) ((DWORD)m_pCompBytes + j * xblocks * 16);
for (i = 0; i < xblocks; ++i, ++pBlock)
{
pAlphaBlock = (DXTAlphaBlock3BitLinear*) pBlock;
pBlock++;
GetColorBlockColors_m3(pBlock, &col_0, &col_1, &col_2, &col_3, wrd);
pImPos = (DWORD*)((DWORD)pBase + i*16 + (j*4) * m_nWidth * 4);
DecodeColorBlock(pImPos, pBlock, m_nWidth, (DWORD*)&col_0, (DWORD*)&col_1,
(DWORD*)&col_2, (DWORD*)&col_3);
DecodeAlpha3BitLinear(pImPos, pAlphaBlock, m_nWidth, alphazero);
}
}
QueryPerformanceCounter(& info->m_end_clk);
info->m_nSamples ++;
info->m_interval_sum.QuadPart += info->m_end_clk.QuadPart - info->m_start_clk.QuadPart;
}
}
void CDXTCImage::Time_Decomp5_04(int ntimes, TimingInfo * info)
{
int n;
info->m_nSamples = 0;
info->m_interval_sum.QuadPart = 0;
info->m_csName.Format("Timing decomp method 4: shift extract w/ pre-shift math, for %d times\n", ntimes);
QueryPerformanceCounter(& info->m_start_clk);
for (n = 0; n < ntimes; n++)
{
int xblocks, yblocks;
xblocks = m_DDSD.dwWidth / 4;
yblocks = m_DDSD.dwHeight / 4;
int i,j;
DWORD * pBase = (DWORD*) m_pDecompBytes;
DWORD * pImPos = (DWORD*) pBase; // pos in decompressed data
WORD * pPos = (WORD*) m_pCompBytes; // pos in compressed data
DXTColBlock * pBlock;
DXTAlphaBlock3BitLinear * pAlphaBlock;
Color8888 col_0, col_1, col_2, col_3;
WORD wrd;
// fill alphazero with appropriate value to zero out alpha when
// alphazero is ANDed with the image color 32 bit DWORD:
col_0.a = 0;
col_0.r = col_0.g = col_0.b = 0xff;
DWORD alphazero = *((DWORD*) &col_0);
// ** See DecompressDXT5 code for comments!!
for (j = 0; j < yblocks; ++j)
{
pBlock = (DXTColBlock*) ((DWORD)m_pCompBytes + j * xblocks * 16);
for (i = 0; i < xblocks; ++i, ++pBlock)
{
pAlphaBlock = (DXTAlphaBlock3BitLinear*) pBlock;
pBlock++;
GetColorBlockColors_m4(pBlock, &col_0, &col_1, &col_2, &col_3, wrd);
pImPos = (DWORD*)((DWORD)pBase + i*16 + (j*4) * m_nWidth * 4);
DecodeColorBlock(pImPos, pBlock, m_nWidth, (DWORD*)&col_0, (DWORD*)&col_1,
(DWORD*)&col_2, (DWORD*)&col_3);
DecodeAlpha3BitLinear(pImPos, pAlphaBlock, m_nWidth, alphazero);
}
}
}
QueryPerformanceCounter(& info->m_end_clk);
info->m_nSamples = ntimes;
info->m_interval_sum.QuadPart += info->m_end_clk.QuadPart - info->m_start_clk.QuadPart;
}
*/

View File

@ -114,9 +114,7 @@ class CDXTCImage
XDDPIXELFORMAT m_xddPixelFormat; XDDPIXELFORMAT m_xddPixelFormat;
bool LoadFromFile(const char * filename); // true if success bool LoadHeaderFromMemory(const BYTE * c_pbMap, int iSize);
bool LoadFromMemory(const BYTE * c_pbMap);
bool LoadHeaderFromMemory(const BYTE * c_pbMap);
bool Copy(int miplevel, BYTE * pbDest, long lDestPitch); bool Copy(int miplevel, BYTE * pbDest, long lDestPitch);
void Decompress(int miplevel, DWORD * pdwDest); void Decompress(int miplevel, DWORD * pdwDest);
@ -128,16 +126,6 @@ class CDXTCImage
VOID DecodePixelFormat(CHAR* strPixelFormat, XDDPIXELFORMAT* pddpf); VOID DecodePixelFormat(CHAR* strPixelFormat, XDDPIXELFORMAT* pddpf);
void Unextract(BYTE * pbDest, int iWidth, int iHeight, int iPitch); void Unextract(BYTE * pbDest, int iWidth, int iHeight, int iPitch);
/*
struct TimingInfo; // defined in Image_DXTC.cpp
void RunTimingSession(); // run a few methods & time the code
// must use dxt5 texture
void Time_Decomp5_01(int ntimes, TimingInfo * info);
void Time_Decomp5_02(int ntimes, TimingInfo * info);
void Time_Decomp5_03(int ntimes, TimingInfo * info);
void Time_Decomp5_04(int ntimes, TimingInfo * info);
*/
}; };
#endif // #ifndef AFX_IMAGE_DXTC_H__4B89D8D0_7857_11D4_9630_00A0C996DE3D__INCLUDED_ #endif // #ifndef AFX_IMAGE_DXTC_H__4B89D8D0_7857_11D4_9630_00A0C996DE3D__INCLUDED_

View File

@ -209,7 +209,8 @@ bool CGraphicImageTexture::CreateFromMemoryFile(UINT bufSize, const void * c_pvB
static CDXTCImage image; static CDXTCImage image;
if (image.LoadHeaderFromMemory((const BYTE *) c_pvBuf)) // DDS인가 확인 // Check whether the file is a DDS
if (image.LoadHeaderFromMemory((const BYTE *) c_pvBuf, bufSize))
{ {
return (CreateDDSTexture(image, (const BYTE *) c_pvBuf)); return (CreateDDSTexture(image, (const BYTE *) c_pvBuf));
} }