
No more lies...
Сообщений: 497
Спасибо сказали: 816 раз

|
Цитата(hippocamus @ 22 Dec 2013, 16:36)  Ну, пусть 2,5 гектара будет. Оправдано? Просто не нужно всех юнитов конвертить, а только призрачных, полупрозрачных, светящихся. Ну тут же про антиалиасинг всех существ говорили.... Про эффекты на поле боя (жажда крови, окаменение и т.д.) может нужно где-то позднее хук в последовательности отрисовки брать? Может за одно и глюки с пропажей альфа слоя исчезнут. И еще я вставил автоопределение разрешения экрана для HD мода, работает, но только в полноэкранном режиме... а в оконном нет, наверное надо брать размеры окна, а не экрана. И вообще может что то с потоками сделать... Вроде последний код:
#include <windows.h> #include <stdio.h> #include <setjmp.h> #include <png.h> #include <map> //#include <Era.h> using std::map; //using namespace Era;
//------------------------------------------------------------------------------------------------------- // //------------------------------------------------------------------------------------------------------- #pragma pack(1) #define stdcall __stdcall
//------------------------------------------------------------------------------------------------------- // //------------------------------------------------------------------------------------------------------- template<typename T1, typename T2> inline T1 max( T1 Value1, T2 Value2 ) { return ( Value1 > Value2 )? Value1 : Value2; }
template<typename T1, typename T2> inline T1 min( T1 Value1, T2 Value2 ) { return ( Value1 < Value2 )? Value1 : Value2; }
//------------------------------------------------------------------------------------------------------- // //------------------------------------------------------------------------------------------------------- inline char tolower( char Char ) { return ( Char >= 'A' && Char <= 'Z' )? Char - 'A' + 'a' : Char; }
//------------------------------------------------------------------------------------------------------- // //------------------------------------------------------------------------------------------------------- typedef unsigned char byte; typedef unsigned int uint; typedef long long int64; typedef unsigned long long uint64; typedef WORD color16; typedef DWORD colorRGBA;
//------------------------------------------------------------------------------------------------------- // //------------------------------------------------------------------------------------------------------- struct vector { int x, y;
vector( int x0 = 0, int y0 = 0 ) : x( x0 ), y( y0 ) {} vector& operator+=( vector Other ) { x += Other.x; y += Other.y; return *this; } vector& operator-=( vector Other ) { x -= Other.x; y -= Other.y; return *this; } vector& operator/=( int Number ) { x /= Number; y /= Number; return *this; } vector operator+( vector Other ) { vector Result = *this; Result += Other; return Result; } vector operator-( vector Other ) { vector Result = *this; Result -= Other; return Result; } vector operator/( int Number ) { vector Result = *this; Result /= Number; return Result; } };
//------------------------------------------------------------------------------------------------------- // //------------------------------------------------------------------------------------------------------- inline void rect_cross( vector *pDestPos, vector *pDestSize, vector OtherPos, vector OtherSize ) { vector DestBottomRight = *pDestPos + *pDestSize; vector OtherBottomRight = OtherPos + OtherSize;
pDestPos->x = max( pDestPos->x, OtherPos.x ); pDestPos->y = max( pDestPos->y, OtherPos.y ); DestBottomRight.x = min( DestBottomRight.x, OtherBottomRight.x ); DestBottomRight.y = min( DestBottomRight.y, OtherBottomRight.y ); *pDestSize = DestBottomRight - *pDestPos; }
//------------------------------------------------------------------------------------------------------- // //------------------------------------------------------------------------------------------------------- struct image_name { union { char chars[12]; DWORD dwords[3]; };
image_name( char *name ) { for( int i = 0; i < 12; i++ ) chars[i] = tolower( name[i] ); }
bool operator<( image_name Other ) const { if( dwords[0] < Other.dwords[0] ) return true; else if( dwords[0] > Other.dwords[0] ) return false; else { if( dwords[1] < Other.dwords[1] ) return true; else if( dwords[1] > Other.dwords[1] ) return false; else return dwords[2] < Other.dwords[2]; } } };
//------------------------------------------------------------------------------------------------------- // //------------------------------------------------------------------------------------------------------- struct new_image { vector size; colorRGBA data[0]; };
//------------------------------------------------------------------------------------------------------- // Heroes III internal structure //------------------------------------------------------------------------------------------------------- struct image { /* 0*/ void *p1; // for many or all objects this is 0x63D6BC /* 4*/ char name[12];
/*16*/ void *p2; /*20*/ int unknown1; /*24*/ int unknown2; /*28*/ int unknown3; /*32*/ int unknown4;
/*36*/ int type; // image type?
/*40*/ vector total_size; /*48*/ vector size; /*56*/ vector pos;
/*64*/ int d5; // = m_Size.x /*68*/ int *pdata; // image data(pixels), format unknown // may be more data here };
//------------------------------------------------------------------------------------------------------- // arguments for drawing functions //------------------------------------------------------------------------------------------------------- struct draw_info0 { vector pos0; vector size; color16 *pscreen; // DDSURFACEDESC::pSurface vector pos; vector screen_size; // DDSURFACEDESC::dwWidth DDSURFACEDESC::dwHeight int pitch; // DDSURFACEDESC::lPitch int *a11;
union { int a12; byte horz_invert; color16 unknown_color; };
union { int a13; byte vert_invert; // not for everything // not supported color16 color; // player color, obvodka }; };
struct draw_info : draw_info0 { int a14; };
//------------------------------------------------------------------------------------------------------- // //------------------------------------------------------------------------------------------------------- map<image_name, new_image*> g_Replace; bool g_bPrint = false;
//------------------------------------------------------------------------------------------------------- // //------------------------------------------------------------------------------------------------------- inline color16 MakeColor16( int R, int G, int B ) { return (R << 11) | (G << 5) | (B << 0); }
inline int GetRed ( color16 Color ) { return (Color>>11) ; } inline int GetGreen ( color16 Color ) { return (Color>> 5)&0x3F; } inline int GetBlue ( color16 Color ) { return (Color )&0x1F; }
inline int GetRed ( colorRGBA Color ) { return (Color )&0xFF; } inline int GetGreen ( colorRGBA Color ) { return (Color>> 8)&0xFF; } inline int GetBlue ( colorRGBA Color ) { return (Color>>16)&0xFF; } inline int GetAlpha ( colorRGBA Color ) { return (Color>>24) ; }
//------------------------------------------------------------------------------------------------------- // printf doesn't work //------------------------------------------------------------------------------------------------------- enum acolor { RED = FOREGROUND_RED | FOREGROUND_INTENSITY, GREEN = FOREGROUND_GREEN | FOREGROUND_INTENSITY, BLUE = FOREGROUND_BLUE | FOREGROUND_INTENSITY, WHITE = RED | GREEN | BLUE, };
static void aprintf( acolor Color, const char *pFormat, ... ) { va_list Args; va_start( Args, pFormat ); char Buffer[128]; vsprintf( Buffer, pFormat, Args ); va_end( Args );
DWORD Written; HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO BufferInfo; GetConsoleScreenBufferInfo( hOutput, &BufferInfo );
SetConsoleTextAttribute( hOutput, (WORD)WHITE ); WriteConsole( hOutput, "alpha.dll: ", 11, &Written, NULL ); SetConsoleTextAttribute( hOutput, (WORD)Color ); WriteConsole( hOutput, Buffer, strlen(Buffer), &Written, NULL );
SetConsoleTextAttribute( hOutput, BufferInfo.wAttributes ); }
//------------------------------------------------------------------------------------------------------- // Draw0 47BE90 - interface // Draw1 47C9C0 - adventute map objects // Draw2 47D660 - terrain // Draw3 47C300 - monsters //------------------------------------------------------------------------------------------------------- stdcall int image__sub_47BE90( image *pImage, draw_info0 DrawInfo ) asm("image__sub_47BE90"); stdcall int image__sub_47C9C0( image *pImage, draw_info0 DrawInfo ) asm("image__sub_47C9C0"); stdcall int image__sub_47D660( image *pImage, draw_info0 DrawInfo ) asm("image__sub_47D660"); stdcall int image__sub_47C300( image *pImage, draw_info DrawInfo ) asm("image__sub_47C300");
asm ( ".intel_syntax noprefix\n" // use intel syntax
"image__sub_47BE90: \n" " pop eax \n" " pop ecx \n" " push eax \n" " push ebp \n" " mov ebp, esp \n" " push ecx \n" " mov eax, [ecx+0x24] \n" " mov eax, 0x47BE97 \n" " jmp eax \n"
"image__sub_47C9C0: \n" " pop eax \n" " pop ecx \n" " push eax \n" " push ebp \n" " mov ebp, esp \n" " push ecx \n" " mov edx, ecx \n" " mov eax, 0x47C9C6 \n" " jmp eax \n"
"image__sub_47C300: \n" //" pushad \n" //" push 29502 \n" //" mov eax, 0x74CE30 \n" //" call eax \n" //" add esp, 4 \n" //" popad \n" " pop eax \n" " pop ecx \n" " push eax \n" " push ebp \n" " mov ebp, esp \n" " push ecx \n" " mov al, [ebp+0x3C] \n" " mov eax, 0x47C307 \n" " jmp eax \n"
"image__sub_47D660: \n" " pop eax \n" " pop ecx \n" " push eax \n" " push ebp \n" " mov ebp, esp \n" " push ecx \n" " mov edx, ecx \n" " mov eax, 0x47D666 \n" " jmp eax \n"
".att_syntax noprefix\n" // reset AT&T syntax or there will be errors );
//------------------------------------------------------------------------------------------------------- // //------------------------------------------------------------------------------------------------------- static int OriginalDraw( int Type, image *pImage, draw_info *pDrawInfo ) { typedef stdcall int (*pfnOriginalDraw)( image *pImage, draw_info0 DrawInfo ); static pfnOriginalDraw pOriginalDraw[3] = { &image__sub_47BE90, &image__sub_47C9C0, &image__sub_47D660 };
if( Type == 3 ) return image__sub_47C300( pImage, *pDrawInfo ); else return pOriginalDraw[Type]( pImage, (draw_info0)*pDrawInfo ); }
//------------------------------------------------------------------------------------------------------- // Draw0 47BE90 - interface // Draw1 47C9C0 - adventute map objects // Draw2 47D660 - terrain // Draw3 47C300 - monsters //-------------------------------------------------------------------------------------------------------
static int Draw( int Type, image *pImage, draw_info *pInfo ) { int screenW=GetSystemMetrics(SM_CXSCREEN);//Ïîëó÷èòü øèðèíó ýêðàíà int screenH=GetSystemMetrics(SM_CYSCREEN);//Ïîëó÷èòü âûñîòó ýêðàíà int NewRed, NewGreen, NewBlue; color16 ro1,go1,bo1,rn1,gn1,bn1,an1; if( pInfo->screen_size.x != screenW || pInfo->screen_size.y != screenH ) return OriginalDraw( Type, pImage, pInfo ); //asm //( //".intel_syntax noprefix\n" // use intel syntax //" pushad \n" //" push 29502 \n" //" mov eax, 0x74CE30 \n" //" call eax \n" //" add esp, 4 \n" //" popad \n" //".att_syntax noprefix\n" // reset AT&T syntax or there will be errors //); static char LastNames[8][13] = { {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0} }; static int CurLastName = 0;
//ExecErmCmd("VRv2007:Sd1;"); if( g_bPrint ) { for( int i = 0; i < 8; i++ ) if( strcmp( pImage->name, LastNames[i] ) == 0 ) goto draw;
strncpy( LastNames[CurLastName], pImage->name, 12 ); LastNames[CurLastName][12] = 0; aprintf( WHITE, "draw %s\n", LastNames[CurLastName] ); CurLastName++; if( CurLastName >= 8 ) CurLastName = 0; } draw:
map<image_name,new_image*>::iterator Rep = g_Replace.find( image_name(pImage->name) ); if( Rep == g_Replace.end() ) return OriginalDraw( Type, pImage, pInfo );
new_image *pNewImage = Rep->second;
// center image vector ImagePos = pInfo->pos - pInfo->pos0 + (pImage->total_size - pNewImage->size)/2;
// crop image vector Pos = pInfo->pos; vector Size = pInfo->size; rect_cross( &Pos, &Size, ImagePos, pNewImage->size ); rect_cross( &Pos, &Size, vector( 0, 0 ), vector( screenW, screenH ) );
vector Pos0 = Pos - ImagePos;
//if(Type==2){// color16 *pOld = &pInfo->pscreen[Pos.y*screenW + Pos.x]; colorRGBA *pNew; if( pInfo->horz_invert ) pNew = &pNewImage->data[(Pos0.y+1)*pNewImage->size.x - Pos0.x]; else pNew = &pNewImage->data[(Pos0.y )*pNewImage->size.x + Pos0.x];
for( int y = 0; y < Size.y; y++ ) { for( int x = 0; x < Size.x; x++ ) { ro1 = GetRed (*pOld); rn1 = GetRed (*pNew); go1 = GetGreen (*pOld); gn1 = GetGreen (*pNew); bo1 = GetBlue (*pOld); bn1 = GetBlue (*pNew); an1 = GetAlpha(*pNew); if( ( *pNew & 0xFFFFFF ) == 0xFFFF ) // color for replacement { color16 New = pInfo->color; if( New ) { NewRed = ro1 + an1*(GetRed (New) - ro1)/256; NewGreen = go1 + an1*(GetGreen (New) - go1)/256; NewBlue = bo1 + an1*(GetBlue (New) - bo1)/256; *pOld = MakeColor16( NewRed, NewGreen, NewBlue); } } else { NewRed = ro1 + an1*(rn1 - ro1)/256; NewGreen = go1 + an1*(gn1 - go1)/256; NewBlue = bo1 + an1*(bn1 - bo1)/256; *pOld = MakeColor16( NewRed, NewGreen, NewBlue); } pOld++; if( pInfo->horz_invert ) pNew--; else pNew++; }
pOld += screenW - Size.x; if( pInfo->horz_invert ) pNew += pNewImage->size.x + Size.x; else pNew += pNewImage->size.x - Size.x; } return 0; //}// }
//------------------------------------------------------------------------------------------------------- // //------------------------------------------------------------------------------------------------------- const char *g_pCurPngFile; jmp_buf g_JumpBuffer;
//------------------------------------------------------------------------------------------------------- // //------------------------------------------------------------------------------------------------------- void PngError( png_struct *png_ptr, const char *error_msg ) { aprintf( RED, "libpng error while reading %s: %s\n", g_pCurPngFile, error_msg ); longjmp( g_JumpBuffer, 1 ); }
//------------------------------------------------------------------------------------------------------- // //------------------------------------------------------------------------------------------------------- void PngWarning( png_struct *png_ptr, const char *warning_msg ) { aprintf( BLUE, "libpng warning while reading %s: %s\n", g_pCurPngFile, warning_msg ); }
//------------------------------------------------------------------------------------------------------- // //------------------------------------------------------------------------------------------------------- static void ReplaceImage( char *pName ) { char FilePath[32]; sprintf( FilePath, "replace/%s", pName );
g_pCurPngFile = FilePath;
FILE *pNewImage = fopen( FilePath, "rb" ); if( !pNewImage ) { aprintf( RED, "couldn't open file %s\n", FilePath ); return; }
png_struct *png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, &PngError, &PngWarning ); png_info *info_ptr = png_create_info_struct(png_ptr);
png_init_io( png_ptr, pNewImage );
png_uint_32 width, height; int color_type, bit_depth;
png_read_info( png_ptr, info_ptr ); png_get_IHDR( png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL );
if( color_type == PNG_COLOR_TYPE_PALETTE ) png_set_palette_to_rgb(png_ptr);
if( color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA ) png_set_gray_to_rgb(png_ptr);
if( png_get_valid( png_ptr, info_ptr, PNG_INFO_tRNS ) ) png_set_tRNS_to_alpha(png_ptr);
if( bit_depth == 16 ) png_set_strip_16(png_ptr);
png_read_update_info( png_ptr, info_ptr );
new_image *pImage = (new_image*)malloc( sizeof(new_image) + width*height*4 ); pImage->size.x = width; pImage->size.y = height;
colorRGBA **row_pointers = (colorRGBA**)malloc( height*sizeof(void*) ); for( png_uint_32 i = 0; i < height; i++ ) row_pointers[i] = pImage->data + width*i;
png_read_image( png_ptr, (byte**)row_pointers );
free( row_pointers ); png_read_end( png_ptr, NULL ); png_destroy_read_struct( &png_ptr, &info_ptr, NULL ); fclose( pNewImage );
// prepare for conversion to 16 bit byte *pCur = (byte*)pImage->data; for( uint i = 0; i < width*height; i++ ) { if( (pCur[0] == 255) && (pCur[1] == 255) && (pCur[2] == 0) ) // color for replacement { pCur += 4; continue; } pCur[0] /= 8; // red pCur[1] /= 4; // green pCur[2] /= 8; // blue pCur += 4; }
pName[strlen(pName)-4] = 0; g_Replace[image_name(pName)] = pImage; }
//------------------------------------------------------------------------------------------------------- // //------------------------------------------------------------------------------------------------------- static void LoadPNGs() { //ShellExecute(0,"open","http://www.h3lord.ru/giverus.html", NULL, NULL, 0); WIN32_FIND_DATA FindData; HANDLE hSearch = FindFirstFile( "replace/*.png", &FindData ); if( hSearch == INVALID_HANDLE_VALUE ) { aprintf( RED, "couldn't search \"replace/*.png\"\n" ); return; } do { if( FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) continue;
int len = strlen(FindData.cFileName); if( len > 12 + 4 || strcmp( &FindData.cFileName[len-4], ".png" ) != 0 ) continue;
if( setjmp( g_JumpBuffer ) == 0 ) ReplaceImage( FindData.cFileName ); } while( FindNextFile( hSearch, &FindData ) ); FindClose( hSearch ); }
//------------------------------------------------------------------------------------------------------- // //------------------------------------------------------------------------------------------------------- template<typename T> void* to_pvoid( T Value ) { return *(void**)&Value; }
//------------------------------------------------------------------------------------------------------- // write "jmp pNew" at address pOriginal //------------------------------------------------------------------------------------------------------- inline void WriteHook( void *pOriginal, void *pNew, uint Test ) { if( !IsBadReadPtr( pOriginal, 8 ) ) { if( ((uint*)pOriginal)[0] != 0x51EC8B55 || ((uint*)pOriginal)[1] != Test ) { char Msg[256]; sprintf( Msg, "Memory at 0x%X is not beginning of expected function. " "Possibly you try to run wrong version of Heroes III with alpha.dll or inject alpha.dll multiple times.\n" "Do you want to insert hook function?", (uint)pOriginal ); if( MessageBox( NULL, Msg, "alpha.dll", MB_ICONERROR | MB_YESNO ) != IDYES ) return; } } if( IsBadWritePtr( pOriginal, 5 ) ) { char Msg[100]; sprintf( Msg, "No write access to 0x%X. Disable write protection for section \".text\" and try again.", (uint)pOriginal ); MessageBox( NULL, Msg, "alpha.dll", MB_ICONERROR ); return; }
*(byte*)pOriginal = 0xE9; // jmp *(void**)( (byte*)pOriginal + 1 ) = (void*)( (byte*)pNew - (byte*)pOriginal - 5 ); aprintf( GREEN, "write 0x%X: jmp 0x%X\n", pOriginal, pNew ); }
//------------------------------------------------------------------------------------------------------- // //------------------------------------------------------------------------------------------------------- stdcall int image__hook_47BE90( draw_info0 Info ) { register void *ecx asm("ecx"); // get access to ecx where this pointer is stored return Draw( 0, (image*)ecx, (draw_info*)&Info ); }
stdcall int image__hook_47C9C0( draw_info0 Info ) { register void *ecx asm("ecx"); // get access to ecx where this pointer is stored return Draw( 1, (image*)ecx, (draw_info*)&Info ); }
stdcall int image__hook_47D660( draw_info0 Info ) { register void *ecx asm("ecx"); // get access to ecx where this pointer is stored return Draw( 2, (image*)ecx, (draw_info*)&Info ); } stdcall int image__hook_47C300( draw_info Info ) { register void *ecx asm("ecx"); // get access to ecx where this pointer is stored return Draw( 3, (image*)ecx, (draw_info*)&Info ); }
//------------------------------------------------------------------------------------------------------- // //------------------------------------------------------------------------------------------------------- extern "C" stdcall BOOL DllMain( HINSTANCE hInstanceDLL, DWORD Reason, void *pReserved ) { if( Reason != DLL_PROCESS_ATTACH ) return TRUE;
int argc; wchar_t **argv = CommandLineToArgvW( GetCommandLineW(), &argc ); while( argc-- ) { if( wcscmp( argv[argc], L"-alpha-console" ) == 0 ) AllocConsole(); if( wcscmp( argv[argc], L"-alpha-print" ) == 0 ) g_bPrint = true; } LocalFree( argv ); aprintf( GREEN, "alpha.dll loaded at address 0x%X\n", hInstanceDLL );
WriteHook( (void*)0x0047BE90, to_pvoid(&image__hook_47BE90), 0x5324418B ); WriteHook( (void*)0x0047C9C0, to_pvoid(&image__hook_47C9C0), 0x5653D18B ); WriteHook( (void*)0x0047D660, to_pvoid(&image__hook_47D660), 0x5653D18B ); WriteHook( (void*)0x0047C300, to_pvoid(&image__hook_47C300), 0x533C458A ); LoadPNGs();
return TRUE; }
|