[ create a new paste ] login | about

Link: http://codepad.org/AhyevOUQ    [ raw code | fork ]

SourceSeeker - C++, pasted on Oct 30:
// ObjectMergerFixer.cpp
// VERSION 4.1.0 [2016_10_30]
//         ^     = MAJOR REBUILDS
//           ^   = NEW STUFF
//             ^ = FIXES
// BY SourceSeeker / EdwardElric (hiveworkshop.com) / MasterOfSickness (wc3c.net)

// THANKS TO:
// - Vexorian (AUTHOR OF JASSHELPER) FOR EVERYTHING :D
// - PitzerMike (AUTHOR OF GRIMEX) FOR PUBLISHING HIS SOURCE CODE
// - WaterKnight (http://www.hiveworkshop.com/members/waterknight.178519/) FOR HELPFUL TIPS VIA CHAT (http://www.hiveworkshop.com/chat/) & BEING PATIENT WITH ME & MY QUESTIONS ;p
// - Barade (http://www.hiveworkshop.com/members/barade.125524/) FOR HELPFUL TIPS ABOUT MPQ API
// - Aniki (http://www.hiveworkshop.com/members/aniki.241724/) FOR HINT TO ADD FIX FOR UNIT OBJECT FIELD (utco)



#include "sfmpq/SFmpqapi_no-lib.h" // HEADER FOR: MpqOpenArchiveForUpdate, ...

#include <iostream>		// SYSTEM HEADER FOR: std::cout
#include <vector>		// SYSTEM HEADER FOR: std::vector
#include <algorithm>	    // SYSTEM HEADER FOR: sst::search



std::vector<char> getFixedW3U( std::vector<char> &v_input, const char * c_wrongBytes, const char * c_rightBytes ) {
	
	std::vector<char> v_output;
	std::vector<char>::iterator it_counter;
	
	int i_distance;
	int i_distance2 = 0;
	
	
	
	// SEARCH FOR OBJECT FIELD ID [4 BYTES] & TYPE [4 BYTES] (EXAMPLE: "uaen" & STRING) IN BINARY STREAM AS HEX SEQUENCE: { 0x75, 0x61, 0x65, 0x6E, 0x03, 0x00, 0x00, 0x00 }
		// OBJECT MERGER ERROR 1:
		// THOSE LAST 4 BYTES SHOULD BE { 0x00, 0x00, 0x00, 0x00 }
	// FOR EACH MATCH RETRIEVE THE FOLLOWING BYTES UNTIL NULL BYTE
		// OBJECT MERGER ERROR 2:
		// FOR "uaen" THIS BYTE SHOULD BE 0x00, 0x01, 0x02 OR 0x03, FOLLOWED BY 3 NULL BYTES,
		// INSTEAD THE BYTE IS 0x48, 0x49, 0x50 OR 0x51, FOLLOWED BY 1 NULL BYTE!
	// PUT CORRECT BYTES INTO OUTPUT VECTOR
	it_counter = std::search( v_input.begin(), v_input.end(), c_wrongBytes, c_wrongBytes +8 );
	
	// IF W3U CONTAINS WRONG BYTES LIKE "uaen....":
	if ( it_counter != v_input.end() ) {
		while ( it_counter != v_input.end() ) {
			
			i_distance = it_counter - v_input.begin();
			
			// APPEND PART OF INPUT VECTOR v_buffer TO OUTPUT VECTOR v_output:
			v_output.insert( v_output.end(), v_input.begin() +i_distance2, v_input.begin() +i_distance +4 );
			
			i_distance2 = i_distance +4;
				// = EVERYTHING UNTIL (INLCUDING) ...uaen OR ...utco
			
			
			
			// SAVE NUMBER FOLLOWED BY WRONG BYTES UNTIL NEXT NULL BYTE:
			// SAVE UP TO TWO-PLACE (-9...99), BECAUSE:
				// FIELD (utco) RANGE: -1 - 12
				// FIELD (uaen) RANGE:  0 - 3
					// - 0 = NOTHING
					// - 1 = ONLY ATTACK 1
					// - 2 = ONLY ATTACK 2
					// - 3 = BOTH
			// EXAMPLES:
				// WRONG BYTES FOR uaen = 0:
					// BYTE:	   1    2    3    4    5    6    7    8    9   10
					// CHAR:	   u    a    e    n    .    .    .    .    0    .
					// HEX:		0x75 0x61 0x65 0x6E 0x03 0x00 0x00 0x00 0x30 0x00
				// RIGHT BYTES FOR uaen = 0:
					// BYTE:	   1    2    3    4    5    6    7    8    9   10   11   12
					// CHAR:	   u    a    e    n    .    .    .    .    .    .    .    .
					// HEX:		0x75 0x61 0x65 0x6E 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
				// WRONG BYTES FOR utco = 12:
					// BYTE:	   1    2    3    4    5    6    7    8    9   10   11
					// CHAR:	   u    t    c    o    .    .    .    .    1    2    .
					// HEX:		0x75 0x74 0x63 0x6F 0x03 0x00 0x00 0x00 0x31 0x32 0x00
				// RIGHT BYTES FOR utco = 12:
					// BYTE:	   1    2    3    4    5    6    7    8    9   10   11   12
					// CHAR:	   u    t    c    o    .    .    .    .    .    .    .    .
					// HEX:		0x75 0x74 0x63 0x6F 0x00 0x00 0x00 0x00 0x0C 0x00 0x00 0x00
				// WRONG BYTES FOR utco = -1:
					// BYTE:	   1    2    3    4    5    6    7    8    9   10   11
					// CHAR:	   u    t    c    o    .    .    .    .    -    1    .
					// HEX:		0x75 0x74 0x63 0x6F 0x03 0x00 0x00 0x00 0x2D 0x31 0x00
				// RIGHT BYTES FOR utco = -1:
					// BYTE:	   1    2    3    4    5    6    7    8     9    10    11    12
					// CHAR:	   u    t    c    o    .    .    .    .     ÿ     ÿ     ÿ     ÿ
					// HEX:		0x75 0x74 0x63 0x6F 0x00 0x00 0x00 0x00 0x255 0x255 0x255 0x255
			int i_byteValue;
			int i_byteCount = 0;
			int i_matches = 0;
			int i_sign = 1;
			int i_result = 0;
			
			// GET CHAR VALUE AT INDEX OF VECTOR:
			while ( (i_byteValue = (int)v_input[i_distance +8 +i_byteCount]) != 0 ) {
				
				// CHECK FOR MINUS:
				if ( (i_byteValue == '-') && (i_matches == 0) ) {
					i_sign = -1;
					i_matches++;
				}
				
				// CHECK FOR DIGIT:
				if ( (i_byteValue >= '0') && (i_byteValue <= '9') && (i_matches <= 2) ) {
					i_result *= 10;
					i_result += i_byteValue - '0';
					i_matches++;
				}
				
				i_byteCount++;
			}
			i_result *= i_sign;
			
			
			
			// ADD FIX:
			if (i_result < 0) {
				
				// CONVERT DECIMAL TO HEXADECIMAL:
// ONLY TESTED FOR -1!! DON'T KNOW IF ANYTHING LOWER WORKS AS IT SHOULD!! STILL HAS TO BE TESTED IF ANOTHER OBJECT FIELD WITH SUCH A RANGE < -1 SHOULD BE FIXED...
				unsigned char bytes[4];
				unsigned long n = i_result;
				
				bytes[0] = (n >> 24) & 0xFF;
				bytes[1] = (n >> 16) & 0xFF;
				bytes[2] = (n >> 8) & 0xFF;
				bytes[3] = n & 0xFF;
				
				int dataArray[8] = { 0, 0, 0, 0, bytes[0], bytes[1], bytes[2], bytes[3] };
				v_output.insert( v_output.end(), &dataArray[0], &dataArray[8] );
			} else {
				
				int dataArray[8] = { c_rightBytes[4], c_rightBytes[5], c_rightBytes[6], c_rightBytes[7], i_result, 0, 0, 0 };
				v_output.insert( v_output.end(), &dataArray[0], &dataArray[8] );
			}
			
			
			
			i_distance2 = i_distance2 +4 +i_byteCount +1;
				// i_distance2 +4 +i_byteCount +1 BECAUSE:
					//    u,    t,    c,    o, 0x03, 0x00, 0x00, 0x00,    \,    0, 0x00, 
					//                        ^ = distance2           ^ = +4      ^ = +i_byteCount
			
			// CONTINUE SEARCH:
			it_counter = std::search( v_input.begin() +i_distance +4, v_input.end(), c_wrongBytes, c_wrongBytes +8 );
		}
		
		// APPEND END OF INPUT VECTOR buffer TO OUTPUT VECTOR v_output:
		v_output.insert( v_output.end(), v_input.begin() +i_distance2, v_input.end() );
		
		return v_output;
	}
	
	return std::vector<char>();
}



int main(int argc, char **argv) {
	
	funcMpqOpenArchiveForUpdate MpqOpenArchiveForUpdate = 0;
	funcMpqCloseUpdatedArchive MpqCloseUpdatedArchive = 0;
	funcMpqAddFileFromBufferEx MpqAddFileFromBufferEx = 0;
	funcMpqAddFileFromBuffer MpqAddFileFromBuffer = 0;
	
	funcSFileOpenFileEx SFileOpenFileEx = 0;
	funcSFileGetFileSize SFileGetFileSize = 0;
	funcSFileReadFile SFileReadFile = 0;
	funcSFileCloseFile SFileCloseFile = 0;
	
	
	
	HINSTANCE hSFMpq = 0;
	hSFMpq = LoadLibrary("SFMpq.dll");
		// "SFMpq.dll" FROM PitzerMike WAS BUILD AS 32-BIT DLL!
		// IF YOU WANT TO USE THIS DLL, YOUR PROJECT HAS TO BE COMPILED AS 32-BIT TOO, OTHERWISE THE DLL ISN'T LOADED!
	
	// IF DLL 'SFMpq.dll' WAS LOADED, CONTINUE:
	if (hSFMpq!=0) {
		
		MpqOpenArchiveForUpdate = (funcMpqOpenArchiveForUpdate)GetProcAddress(hSFMpq,"MpqOpenArchiveForUpdate");
		MpqCloseUpdatedArchive = (funcMpqCloseUpdatedArchive)GetProcAddress(hSFMpq,"MpqCloseUpdatedArchive");
		MpqAddFileFromBufferEx = (funcMpqAddFileFromBufferEx)GetProcAddress(hSFMpq,"MpqAddFileFromBufferEx");
		MpqAddFileFromBuffer = (funcMpqAddFileFromBuffer)GetProcAddress(hSFMpq,"MpqAddFileFromBuffer");
		
		SFileOpenFileEx = (funcSFileOpenFileEx)GetProcAddress(hSFMpq,"SFileOpenFileEx");
		SFileGetFileSize = (funcSFileGetFileSize)GetProcAddress(hSFMpq,"SFileGetFileSize");
		SFileReadFile = (funcSFileReadFile)GetProcAddress(hSFMpq,"SFileReadFile");
		SFileCloseFile = (funcSFileCloseFile)GetProcAddress(hSFMpq,"SFileCloseFile");
		
		
		
		HANDLE mpq = MpqOpenArchiveForUpdate(argv[1], MOAU_OPEN_EXISTING | MOAU_MAINTAIN_LISTFILE, 1024);
		
		HANDLE file;
		
		if(!SFileOpenFileEx(mpq, "war3map.w3u", 0, &file)) {
			// DEBUG:
			MessageBox(0, "fail: could not open 'war3map.w3u'", "ObjectMergerFixer: error", MB_OK);
			std::cout << "fail: could not open 'war3map.w3u'\n" << "HIT ENTER TO CONTINUE!\n";
			getchar();
			return 0;
		}
		
		DWORD size = SFileGetFileSize(file, 0);
			// Retrieves a size of the file within archive
			// http://www.zezula.net/en/mpq/stormlib.html
		
		char * c_buf = new char[size];
		
		SFileReadFile(file, c_buf, size, &size, NULL);
			// Reads data from the file
			// http://www.zezula.net/en/mpq/stormlib.html
			// CONTENT FROM FILE file IS SAVED TO buf.buf
		
		SFileCloseFile(file);
		
		
		
		// W3U FIXES:
		
		// COPY INPUT W3U DATA INTO BUFFER:
		std::vector<char> v_input( c_buf, c_buf +size );
		
		// uaen:
		const char c_uaen_wrong[9] = { 0x75, 0x61, 0x65, 0x6E, 0x03, 0x00, 0x00, 0x00 }; // { 0x75, 0x61, 0x65, 0x6E, ... } = { u, a, e, n, ... }
		const char c_uaen_right[9] = { 0x75, 0x61, 0x65, 0x6E, 0x00, 0x00, 0x00, 0x00 }; // { 0x75, 0x61, 0x65, 0x6E, ... } = { u, a, e, n, ... }
		std::vector<char> v_output = getFixedW3U( v_input, c_uaen_wrong, c_uaen_right );
		
		// utco:
		const char c_utco_wrong[9] = { 0x75, 0x74, 0x63, 0x6F, 0x03, 0x00, 0x00, 0x00 }; // { 0x75, 0x74, 0x63, 0x6F, ... } = { u, t, c, o, ... }
		const char c_utco_right[9] = { 0x75, 0x74, 0x63, 0x6F, 0x00, 0x00, 0x00, 0x00 }; // { 0x75, 0x74, 0x63, 0x6F, ... } = { u, t, c, o, ... }
		if ( v_output.empty() ) {
			v_output = getFixedW3U( v_input, c_utco_wrong, c_utco_right );
		} else {
			v_output = getFixedW3U( v_output, c_utco_wrong, c_utco_right );
		}
		
		
		
		// EXIT IF NO FIXES NEED TO BE APPLIED:
		if ( v_output.empty() ) {
			MpqCloseUpdatedArchive(mpq, 0);
			return 0;
		}
		
		// ADD FIXED W3U BACK TO W3M/W3X:
		if ( !MpqAddFileFromBufferEx(mpq, (LPVOID)v_output.data(), v_output.size(), "war3map.w3u", MAFA_REPLACE_EXISTING | MAFA_COMPRESS, MAFA_COMPRESS_DEFLATE, Z_BEST_COMPRESSION) ) {
			// DEBUG:
			MessageBox(0, "fail: could not write 'war3map.w3u'", "ObjectMergerFixer: error", MB_OK);
			std::cout << "fail: could not write 'war3map.w3u'\n" << "HIT ENTER TO CONTINUE!\n";
			getchar();
		}
		
		
		
		if ( !MpqCloseUpdatedArchive(mpq, 0) ) {
			// DEBUG:
			MessageBox(0, "fail: could not update MPQ", "ObjectMergerFixer: error", MB_OK);
			std::cout << "fail: could not update MPQ\n" << "HIT ENTER TO CONTINUE!\n";
			getchar();
		}
	
	// IF DLL 'SFMpq.dll' WAS NOT LOADED, EXIT:
	} else {
		// DEBUG:
		MessageBox(0, "fail: could not load 'SFMpq.dll'", "ObjectMergerFixer: error", MB_OK);
		std::cout << "fail: could not load 'SFMpq.dll'\n" << "HIT ENTER TO CONTINUE!\n";
		getchar();
	}
	
	
	
	return 0;
}


Create a new paste based on this one


Comments: