Пример #1
0
FArchive& FArray::Serialize(FArchive &Ar, void (*Serializer)(FArchive&, void*), int elementSize)
{
	int i = 0;

	guard(TArray::Serialize);

//-- if (Ar.IsLoading) Empty();	-- cleanup is done in TArray serializer (do not need
//								-- to pass array eraser/destructor to this function)
	// Here:
	// 1) when loading: 'this' array is empty (cleared from TArray's operator<<)
	// 2) when saving : data is not modified by this function

	// serialize data count
	int Count = DataCount;
	if (GameUsesFCompactIndex(Ar))
		Ar << AR_INDEX(Count);
	else
		Ar << Count;

	if (Ar.IsLoading)
	{
		// loading array items - should prepare array
		Empty(Count, elementSize);
		DataCount = Count;
	}
	// perform serialization itself
	void *ptr;
	for (i = 0, ptr = DataPtr; i < Count; i++, ptr = OffsetPointer(ptr, elementSize))
		Serializer(Ar, ptr);
	return Ar;

	unguardf("%d/%d", i, DataCount);
}
Пример #2
0
void Sys_ProcessMessages()
{
#if !DEDICATED_ONLY
	guard(Sys_ProcessMessages);
	MSG		msg;
	while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
	{
		if (msg.message == WM_QUIT)
			GIsRequestingExit = true;

		// TranslateMessage() used for convert VK_XXX messages to WM_CHAR-like
		// We don't need this, but keep TranslateMessage() just in case of compatibility
		// with future Windows versions (at least in Win2K MS implemented "some feature",
		// which requires to call this function -- what feature - they don't tell)
		TranslateMessage(&msg);

		guard(DispatchMessage);
		DispatchMessage(&msg);
		unguardf(("msg=%X", msg.message));
	}

	// grab frame time; this should be in MainLoop ?
	sys_frame_time = appMilliseconds();
	unguard;
#endif
}
Пример #3
0
bool LoadWholePackage(UnPackage* Package, IProgressCallback* progress)
{
	guard(LoadWholePackage);

	if (GFullyLoadedPackages.FindItem(Package) >= 0) return true;	// already loaded

#if PROFILE
	appResetProfiler();
#endif

	UObject::BeginLoad();
	for (int idx = 0; idx < Package->Summary.ExportCount; idx++)
	{
		if (!IsKnownClass(Package->GetObjectName(Package->GetExport(idx).ClassIndex)))
			continue;
		if (progress && !progress->Tick()) return false;
		Package->CreateExport(idx);
	}
	UObject::EndLoad();
	GFullyLoadedPackages.Add(Package);

#if PROFILE
	appPrintProfiler();
#endif

	return true;

	unguardf("%s", Package->Name);
}
Пример #4
0
void* FArray::GetItem(int index, int elementSize) const
{
	guard(operator[]);
	assert(index >= 0 && index < DataCount);
	return OffsetPointer(DataPtr, index * elementSize);
	unguardf("%d/%d", index, DataCount);
}
Пример #5
0
// This method will grow array's MaxCount. No items will be allocated.
// The allocated memory is not initialized because items could be inserted
// and removed at any time - so initialization should be performed in
// upper level functions like Insert()
void FArray::GrowArray(int count, int elementSize)
{
	guard(FArray::GrowArray);
	assert(count > 0);

	int prevCount = MaxCount;

	// check for available space
	if (DataCount + count > MaxCount)
	{
		// not enough space, resize ...
		MaxCount = ((DataCount + count + 15) / 16) * 16 + 16;
		if (!IsStatic())
		{
			DataPtr = appRealloc(DataPtr, MaxCount * elementSize);
		}
		else
		{
			// "static" array becomes non-static
			void* oldData = DataPtr; // this is a static pointer
			DataPtr = appMalloc(MaxCount * elementSize);
			memcpy(DataPtr, oldData, prevCount * elementSize);
		}
	}

	unguardf("%d x %d", count, elementSize);
}
Пример #6
0
void USetupDefinition::InstallTree( const TCHAR* Action, FInstallPoll* Poll, void (USetupDefinition::*Process)( FString Key, FString Value, UBOOL Selected, FInstallPoll* Poll ), USetupGroup* SetupGroup, UBOOL Selected )
{
	guard(USetupDefinition::InstallTree);
	if( !SetupGroup )
		SetupGroup = RootGroup;

	// Update selection status.
	Selected = Selected && SetupGroup->Selected;

	// Process this item.
	(this->*Process)( TEXT("GroupSpecial"), SetupGroup->GetName(), Selected, Poll );
	TMultiMap<FString,FString>* Map = GConfig->GetSectionPrivate( SetupGroup->GetName(), 0, 1, *ConfigFile );
	check(Map);
	for( TMultiMap<FString,FString>::TIterator It(*Map); It; ++It )
	{
		FString V = Format(It.Value());
		(this->*Process)( It.Key(), V, Selected, Poll );
	}

	// Handle all subgroups here.
	for( TArray<USetupGroup*>::TIterator ItG(SetupGroup->Subgroups); ItG; ++ItG )
		InstallTree( Action, Poll, Process, *ItG, Selected );

	unguardf(( TEXT("(%s %s)"), Action, SetupGroup->GetFullName() ));
}
Пример #7
0
UProperty* FindStrictScriptVariable( UStruct* InStruct, const TCHAR* PropName)
{
	guard(FindStrictScriptVariable);
	FName NAME_PropName = FName( PropName, FNAME_Find);
	check( NAME_PropName != NAME_None );
	for( TStrictFieldIterator<UProperty> Prop( InStruct ); Prop; ++Prop )
		if( Prop->GetFName() == NAME_PropName )
			return *Prop;
	appThrowf( (TEXT("Property not found in %s!!"), InStruct->GetName() ) );
	return NULL;
	unguardf( (PropName) );
}
Пример #8
0
void appSetRootDirectory(const char *dir, bool recurse)
{
	guard(appSetRootDirectory);
	if (dir[0] == 0) dir = ".";	// using dir="" will cause scanning of "/dir1", "/dir2" etc (i.e. drive root)
	appStrncpyz(RootDirectory, dir, ARRAY_COUNT(RootDirectory));
	ScanGameDirectory(RootDirectory, recurse);
	appPrintf("Found %d game files (%d skipped)\n", GNumGameFiles, GNumForeignFiles);
#if PRINT_HASH_DISTRIBUTION
	PrintHashDistribution();
#endif
	unguardf("dir=%s", dir);
}
Пример #9
0
static bool BioReadBulkCatalogFile(const CGameFileInfo *file)
{
	guard(BioReadBulkCatalogFile);
	FArchive *Ar = appCreateFileReader(file);
	// setup for reading Bioshock data
	Ar->ArVer         = 141;
	Ar->ArLicenseeVer = 0x38;
	Ar->Game          = GAME_Bioshock;
	// serialize
	appPrintf("Reading %s\n", file->RelativeName);
	BioBulkCatalog *cat = new (bioCatalog) BioBulkCatalog;
	*Ar << *cat;
	// finalize
	delete Ar;
	return true;
	unguardf("%s", file->RelativeName);
}
Пример #10
0
// This method will grow array's MaxCount. No items will be allocated.
// The allocated memory is not initialized because items could be inserted
// and removed at any time - so initialization should be performed in
// upper level functions like Insert()
void FArray::GrowArray(int count, int elementSize)
{
	guard(FArray::GrowArray);
	assert(count > 0);

	int prevCount = MaxCount;

	// check for available space
	int newCount = DataCount + count;
	if (newCount > MaxCount)
	{
		// Not enough space, resize ...
		// Allow small initial size of array
		const int minCount = 4;
		if (newCount > minCount)
		{
			MaxCount = Align(DataCount + count, 16) + 16;
		}
		else
		{
			MaxCount = minCount;
		}
		// Align memory block to reduce fragmentation
		int dataSize = Align(MaxCount * elementSize, 16);
		// Recompute MaxCount in a case if alignment increases its capacity
		MaxCount = dataSize / elementSize;
		// Reallocate memory
		if (!IsStatic())
		{
			DataPtr = appRealloc(DataPtr, dataSize);
		}
		else
		{
			// "static" array becomes non-static
			void* oldData = DataPtr; // this is a static pointer
			DataPtr = appMalloc(dataSize);
			memcpy(DataPtr, oldData, prevCount * elementSize);
		}
	}

	unguardf("%d x %d", count, elementSize);
}
Пример #11
0
//?? TODO: may be pass "Ext" here
void appFindGameFiles(const char *Filename, TArray<const CGameFileInfo*>& Files)
{
	guard(appFindGameFiles);

	if (!appContainsWildcard(Filename))
	{
		const CGameFileInfo* File = appFindGameFile(Filename);
		if (File)
			Files.Add(File);
		return;
	}

	// here we're working with wildcard and should iterate over all files

	char buf[MAX_PACKAGE_PATH];
	appStrncpyz(buf, Filename, ARRAY_COUNT(buf));
	// replace backslashes
	bool containsPath = false;
	for (char* s = buf; *s; s++)
	{
		char c = *s;
		if (c == '\\')
		{
			*s = '/';
			containsPath = true;
		}
		else if (c == '/')
		{
			containsPath = true;
		}
	}

	FindPackageWildcardData findData;
	findData.WildcardContainsPath = containsPath;
	findData.Wildcard = buf;
	appEnumGameFiles(FindPackageWildcardCallback, findData);

	CopyArray(Files, findData.FoundFiles);

	unguardf("wildcard=%s", Filename);
}
Пример #12
0
void FArray::Empty(int count, int elementSize)
{
	guard(FArray::Empty);

	DataCount = 0;

	if (IsStatic())
	{
		if (count <= MaxCount)
			return;
		// "static" array becomes non-static, invalidate data pointer
		DataPtr = NULL;
	}

	//!! TODO: perhaps round up 'Max' to 16 bytes, allow comparison below to be 'softer'
	//!! (i.e. when array is 16 items, and calling Empty(15) - don't reallicate it, unless
	//!! item size is large
	if (DataPtr)
	{
		// check if we need to release old array
		if (count == MaxCount)
		{
			// the size was not changed
			return;
		}
		// delete old memory block
		appFree(DataPtr);
		DataPtr = NULL;
	}

	MaxCount = count;

	if (count)
	{
		DataPtr = appMalloc(count * elementSize);
	}

	unguardf("%d x %d", count, elementSize);
}
Пример #13
0
model_t	*FindModel(const char *name)
{
	guard(R_FindModel);

	TString<64> Name2;
	Name2.filename(name);

#if 0
	// try to load md3 instead of md2
	//!! disable later
	char *ext = strrchr(Name2, '.');
	if (ext && !strcmp(ext, ".md2"))
	{
		ext[3] = '3';		// ".md2" -> ".md3"
		if (GFileSystem->FileExists(Name2))
			return FindModel(Name2);
		// md3 model with the same name is not found -- load md2
		ext[3] = '2';		// ".md3" -> ".md2"
	}
#endif

	model_t *m;
	// search already loaded models
	for (int i = 0; i < modelCount; i++)
	{
		m = modelsArray[i];
		if (!m) continue;				//?? should not happens
		if (Name2 == m->Name)
		{
			// found
			if (m->type == MODEL_UNKNOWN)
				return NULL;			// model name was cached to avoid file system lookup again
			return m;
		}
	}
	if (Name2[0] == '*')
		Com_DropError("R_FindModel: inline model \"%s\" was not found", *Name2);

	if (modelCount == MAX_GLMODELS)
	{
		appWPrintf("R_FindModel: MAX_GLMODELS\n");
		return NULL;
	}

	/*----- not found -- load model ------*/
	unsigned len;
	unsigned *file;
	if (!(file = (unsigned*) GFileSystem->LoadFile(Name2, &len)))
	{
		m = new model_t;
		m->Name = Name2;
		modelsArray[modelCount++] = m;
		Com_DPrintf("R_FindModel: not found: %s\n", *Name2);
		return NULL;	// file not found
	}

	switch (LittleLong(*file))
	{
	case MD2_IDENT:
		m = LoadMd2(Name2, (byte*)file, len);
		break;
	case MD3_IDENT:
		m = LoadMd3(Name2, (byte*)file, len);
		break;
	case SP2_IDENT:
		m = LoadSp2(Name2, (byte*)file, len);
		break;
	case BYTES4('/','/','S','P'):
		m = LoadSpr(Name2, (byte*)file, len);
		break;
	default:
		// no error here: simply ignore unknown model formats
		appWPrintf("R_FindModel: unknown ID 0x%X in %s", (unsigned)LittleLong(*file), name);
		m = NULL;
	}
	if (m) modelsArray[modelCount++] = m;

	delete file;
	return m;

	unguardf(("mdl=%s", name));
}
Пример #14
0
int appDecompress(byte *CompressedBuffer, int CompressedSize, byte *UncompressedBuffer, int UncompressedSize, int Flags)
{
	guard(appDecompress);

#if BLADENSOUL
	if (GForceGame == GAME_BladeNSoul && Flags == COMPRESS_LZO_ENC)	// note: GForceGame is required (to not pass 'Game' here)
	{
		if (CompressedSize >= 32)
		{
			static const char *key = "qiffjdlerdoqymvketdcl0er2subioxq";
			for (int i = 0; i < CompressedSize; i++)
				CompressedBuffer[i] ^= key[i % 32];
		}
		// overide compression
		Flags = COMPRESS_LZO;
	}
#endif // BLADENSOUL

#if TAO_YUAN
	if (GForceGame == GAME_TaoYuan)	// note: GForceGame is required (to not pass 'Game' here);
	{
		static const byte key[] =
		{
			137, 35, 95, 142, 69, 136, 243, 119, 25, 35, 111, 94, 101, 136, 243, 204,
			243, 67, 95, 158, 69, 106, 107, 187, 237, 35, 103, 142, 72, 142, 243
		};
		for (int i = 0; i < CompressedSize; i++)
			CompressedBuffer[i] ^= key[i % 31];		// note: "N % 31" is not the same as "N & 0x1F"
	}
#endif // TAO_YUAN

#if ALICE
	// this code exists in Alice: Madness Returns only
	if (GForceGame == GAME_Alice && CompressedSize == UncompressedSize)
	{
		// CompressedSize == UncompressedSize -> no compression
		memcpy(UncompressedBuffer, CompressedBuffer, UncompressedSize);
		return UncompressedSize;
	}
#endif // ALICE

	if (Flags == COMPRESS_FIND && CompressedSize >= 2)
	{
		byte b1 = CompressedBuffer[0];
		byte b2 = CompressedBuffer[1];
		// detect compression
		// zlib:
		//   http://tools.ietf.org/html/rfc1950
		//   http://stackoverflow.com/questions/9050260/what-does-a-zlib-header-look-like
		if ( b1 == 0x78 &&					// b1=CMF: 7=32k buffer (CINFO), 8=deflate (CM)
			(b2 == 0x9C || b2 == 0xDA) )	// b2=FLG
		{
			Flags = COMPRESS_ZLIB;
		}
		else
			Flags = COMPRESS_LZO;
	}

	if (Flags == COMPRESS_LZO)
	{
		int r;
		r = lzo_init();
		if (r != LZO_E_OK) appError("lzo_init() returned %d", r);
		lzo_uint newLen = UncompressedSize;
		r = lzo1x_decompress_safe(CompressedBuffer, CompressedSize, UncompressedBuffer, &newLen, NULL);
		if (r != LZO_E_OK) appError("lzo_decompress(%d,%d) returned %d", CompressedSize, UncompressedSize, r);
		if (newLen != UncompressedSize) appError("len mismatch: %d != %d", newLen, UncompressedSize);
		return newLen;
	}

	if (Flags == COMPRESS_ZLIB)
	{
#if 0
		appError("appDecompress: Zlib compression is not supported");
#else
		unsigned long newLen = UncompressedSize;
		int r = uncompress(UncompressedBuffer, &newLen, CompressedBuffer, CompressedSize);
		if (r != Z_OK) appError("zlib uncompress(%d,%d) returned %d", CompressedSize, UncompressedSize, r);
//		if (newLen != UncompressedSize) appError("len mismatch: %d != %d", newLen, UncompressedSize); -- needed by Bioshock
		return newLen;
#endif
	}

	if (Flags == COMPRESS_LZX)
	{
#if SUPPORT_XBOX360
#	if !USE_XDK
		appDecompressLZX(CompressedBuffer, CompressedSize, UncompressedBuffer, UncompressedSize);
		return UncompressedSize;
#	else
		void *context;
		int r;
		r = XMemCreateDecompressionContext(0, NULL, 0, &context);
		if (r < 0) appError("XMemCreateDecompressionContext failed");
		unsigned int newLen = UncompressedSize;
		r = XMemDecompress(context, UncompressedBuffer, &newLen, CompressedBuffer, CompressedSize);
		if (r < 0) appError("XMemDecompress failed");
		if (newLen != UncompressedSize) appError("len mismatch: %d != %d", newLen, UncompressedSize);
		XMemDestroyDecompressionContext(context);
		return newLen;
#	endif // USE_XDK
#else  // SUPPORT_XBOX360
		appError("appDecompress: LZX compression is not supported");
#endif // SUPPORT_XBOX360
	}

	appError("appDecompress: unknown compression flags: %d", Flags);
	return 0;

	unguardf("CompSize=%d UncompSize=%d Flags=0x%X", CompressedSize, UncompressedSize, Flags);
}
Пример #15
0
const CGameFileInfo *appFindGameFile(const char *Filename, const char *Ext)
{
	guard(appFindGameFile);

#if UNREAL3
	bool findStartupPackage = (strcmp(Filename, GStartupPackage) == 0);
	if (findStartupPackage)
		return GStartupPackageInfo;
#endif

	char buf[MAX_PACKAGE_PATH];
	appStrncpyz(buf, Filename, ARRAY_COUNT(buf));

	// replace backslashes
	const char* ShortFilename = buf;
	for (char* s = buf; *s; s++)
	{
		char c = *s;
		if (c == '\\') *s = '/';
		if (*s == '/') ShortFilename = s + 1;
	}

	if (Ext)
	{
		// extension is provided
		assert(!strchr(buf, '.'));
	}
	else
	{
		// check for extension in filename
		char *s = strrchr(buf, '.');
		if (s)
		{
			Ext = s + 1;	// remember extension
			*s = 0;			// cut extension
		}
	}

	int nameLen = strlen(ShortFilename);
	int hash = GetHashForFileName(buf);
#ifdef DEBUG_HASH_NAME
	printf("--> Loading %s (%s, len=%d)\n", buf, ShortFilename, nameLen);
#endif

	CGameFileInfo* bestMatch = NULL;
	int bestMatchWeight = -1;
	for (CGameFileInfo* info = GGameFileHash[hash]; info; info = info->HashNext)
	{
#ifdef DEBUG_HASH_NAME
		printf("----> verify %s\n", info->RelativeName);
#endif
		if (info->Extension - 1 - info->ShortFilename != nameLen)	// info->Extension points to char after '.'
		{
//			printf("-----> wrong length %d\n", info->Extension - info->ShortFilename);
			continue;		// different filename length
		}

		// verify extension
		if (Ext)
		{
			if (stricmp(info->Extension, Ext) != 0) continue;
		}
		else
		{
			// Ext = NULL => should be any package extension
			if (!info->IsPackage) continue;
		}

		// verify a filename
		if (strnicmp(info->ShortFilename, ShortFilename, nameLen) != 0)
			continue;
//		if (info->ShortFilename[nameLen] != '.') -- verified before extension comparison
//			continue;

		// Short filename matched, now compare path before the filename.
		// Assume 'ShortFilename' is part of 'buf' and 'info->ShortFilename' is part of 'info->RelativeName'.
		int matchWeight = 0;
		const char *s = ShortFilename;
		const char *d = info->ShortFilename;
		while (--s >= buf && --d >= info->RelativeName)
		{
			if (*s != *d) break;
			matchWeight++;
		}
//		printf("--> matched: %s (weight=%d)\n", info->RelativeName, matchWeight);
		if (matchWeight > bestMatchWeight)
		{
//			printf("---> better match\n");
			bestMatch = info;
			bestMatchWeight = matchWeight;
		}
	}
	return bestMatch;

	unguardf("name=%s ext=%s", Filename, Ext);
}
Пример #16
0
static bool RegisterGameFile(const char *FullName, FVirtualFileSystem* parentVfs = NULL)
{
	guard(RegisterGameFile);

//	printf("..file %s\n", FullName);
	// return false when MAX_GAME_FILES
	if (GNumGameFiles >= ARRAY_COUNT(GameFiles))
		return false;

	if (!parentVfs)		// no nested VFSs
	{
		const char* ext = strrchr(FullName, '.');
		if (ext)
		{
			guard(MountVFS);

			ext++;
			FVirtualFileSystem* vfs = NULL;
			FArchive* reader = NULL;

#if SUPPORT_ANDROID
			if (!stricmp(ext, "obb"))
			{
				GForcePlatform = PLATFORM_ANDROID;
				reader = new FFileReader(FullName);
				if (!reader) return true;
				reader->Game = GAME_UE3;
				vfs = new FObbVFS();
			}
#endif // SUPPORT_ANDROID
#if UNREAL4
			if (!stricmp(ext, "pak"))
			{
				reader = new FFileReader(FullName);
				if (!reader) return true;
				reader->Game = GAME_UE4;
				vfs = new FPakVFS();
				//!! detect game by file name
			}
#endif // UNREAL4
			//!! process other VFS types here
			if (vfs)
			{
				assert(reader);
				// read VF directory
				if (!vfs->AttachReader(reader))
				{
					// something goes wrong
					delete vfs;
					delete reader;
					return true;
				}
				// add game files
				int NumVFSFiles = vfs->NumFiles();
				for (int i = 0; i < NumVFSFiles; i++)
				{
					if (!RegisterGameFile(vfs->FileName(i), vfs))
						return false;
				}
				return true;
			}

			unguard;
		}
	}

	bool IsPackage;
	if (FindExtension(FullName, ARRAY_ARG(PackageExtensions)))
	{
		IsPackage = true;
	}
	else
	{
#if HAS_SUPORT_FILES
		if (!FindExtension(FullName, ARRAY_ARG(KnownExtensions)))
#endif
		{
			// perhaps this file was exported by our tool - skip it
			if (FindExtension(FullName, ARRAY_ARG(SkipExtensions)))
				return true;
			// unknown file type
			if (++GNumForeignFiles >= MAX_FOREIGN_FILES)
				appError("Too much unknown files - bad root directory (%s)?", RootDirectory);
			return true;
		}
		IsPackage = false;
	}

	// create entry
	CGameFileInfo *info = new CGameFileInfo;
	GameFiles[GNumGameFiles++] = info;
	info->IsPackage = IsPackage;
	info->FileSystem = parentVfs;
	if (IsPackage) GNumPackageFiles++;

	if (!parentVfs)
	{
		// regular file
		FILE* f = fopen(FullName, "rb");
		if (f)
		{
			fseek(f, 0, SEEK_END);
			info->SizeInKb = (ftell(f) + 512) / 1024;
			fclose(f);
		}
		else
		{
			info->SizeInKb = 0;
		}
		// cut RootDirectory from filename
		const char *s = FullName + strlen(RootDirectory) + 1;
		assert(s[-1] == '/');
		appStrncpyz(info->RelativeName, s, ARRAY_COUNT(info->RelativeName));
	}
	else
	{
		// file in virtual file system
		info->SizeInKb = parentVfs->GetFileSize(FullName);
		appStrncpyz(info->RelativeName, FullName, ARRAY_COUNT(info->RelativeName));
	}

	// find filename
	const char* s = strrchr(info->RelativeName, '/');
	if (s) s++; else s = info->RelativeName;
	info->ShortFilename = s;
	// find extension
	s = strrchr(info->ShortFilename, '.');
	if (s) s++;
	info->Extension = s;
//	printf("..  -> %s (pkg=%d)\n", info->ShortFilename, info->IsPackage);

#if UNREAL3
	if (info->IsPackage && (strnicmp(info->ShortFilename, "startup", 7) == 0))
	{
		// Register a startup package
		// possible name variants:
		// - startup
		// - startup_int
		// - startup_*
		int startupWeight = 0;
		if (info->ShortFilename[7] == '.')
			startupWeight = 30;							// "startup.upk"
		else if (strnicmp(info->ShortFilename+7, "_int.", 5) == 0)
			startupWeight = 20;							// "startup_int.upk"
		else if (strnicmp(info->ShortFilename+7, "_loc_int.", 9) == 0)
			startupWeight = 20;							// "startup_int.upk"
		else if (info->ShortFilename[7] == '_')
			startupWeight = 1;							// non-int locale, lower priority - use if when other is not detected
		if (startupWeight > GStartupPackageInfoWeight)
		{
			GStartupPackageInfoWeight = startupWeight;
			GStartupPackageInfo = info;
		}
	}
#endif // UNREAL3

	// insert CGameFileInfo into hash table
	int hash = GetHashForFileName(info->ShortFilename);
	info->HashNext = GGameFileHash[hash];
	GGameFileHash[hash] = info;

	return true;

	unguardf("%s", FullName);
}
Пример #17
0
bool UTexture::GetTextureData(CTextureData &TexData) const
{
	guard(UTexture::GetTextureData);

	TexData.Platform           = PLATFORM_PC;
	TexData.OriginalFormatEnum = Format;
	TexData.OriginalFormatName = EnumToName("ETextureFormat", Format);
	TexData.Obj                = this;
	TexData.Palette            = Palette;

	const FArchive* PackageAr = GetPackageArchive();

	// process external sources for some games
#if BIOSHOCK
	if (PackageAr && PackageAr->Game == GAME_Bioshock && CachedBulkDataSize) //?? check bStripped or Baked ?
	{
		byte* CompressedData = FindBioTexture(this);	// may be NULL
		if (CompressedData)
		{
			CMipMap* DstMip = new (TexData.Mips) CMipMap;
			DstMip->CompressedData = CompressedData;
			DstMip->ShouldFreeData = true;
			DstMip->USize = USize;
			DstMip->VSize = VSize;
			DstMip->DataSize = (int)CachedBulkDataSize;
		}
		TexData.Platform = PackageAr->Platform;
	}
#endif // BIOSHOCK
#if UC2
	if (PackageAr && PackageAr->Engine() == GAME_UE2X)
	{
		// try to find texture inside XBox xpr files
		int DataSize;
		byte* CompressedData = FindXprData(Name, &DataSize);	// may be NULL
		if (CompressedData)
		{
			CMipMap* DstMip = new (TexData.Mips) CMipMap;
			DstMip->CompressedData = CompressedData;
			DstMip->ShouldFreeData = true;
			DstMip->USize = USize;
			DstMip->VSize = VSize;
			DstMip->DataSize = DataSize;
		}
	}
#endif // UC2

	if (TexData.Mips.Num() == 0)
	{
		// texture was not taken from external source
		for (int n = 0; n < Mips.Num(); n++)
		{
			// find 1st mipmap with non-null data array
			// reference: DemoPlayerSkins.utx/DemoSkeleton have null-sized 1st 2 mips
			const FMipmap &Mip = Mips[n];
			if (!Mip.DataArray.Num())
				continue;
			CMipMap* DstMip = new (TexData.Mips) CMipMap;
			DstMip->CompressedData = &Mip.DataArray[0];
			DstMip->ShouldFreeData = false;
			DstMip->USize = Mip.USize;
			DstMip->VSize = Mip.VSize;
			DstMip->DataSize = Mip.DataArray.Num();
			break;
		}
	}

	ETexturePixelFormat intFormat;

	//?? return old code back - UE1 and UE2 differs in codes 6 and 7 only
	if (Package && (PackageAr->Engine() == GAME_UE1))
	{
		// UE1 has different ETextureFormat layout
		switch (Format)
		{
		case 0:
			intFormat = TPF_P8;
			break;
//		case 1:
//			intFormat = TPF_RGB32; // in script source code: TEXF_RGB32, but TEXF_RGBA7 in .h
//			break;
//		case 2:
//			intFormat = TPF_RGB64; // in script source code: TEXF_RGB64, but TEXF_RGB16 in .h
//			break;
		case 3:
			intFormat = TPF_DXT1;
			break;
		case 4:
			intFormat = TPF_RGB8;
			break;
		case 5:
			intFormat = TPF_BGRA8;
			break;
		// newer UE1 versions has DXT3 and DXT5
		case 6:
			intFormat = TPF_DXT3;
			break;
		case 7:
			intFormat = TPF_DXT5;
			break;
		default:
			appNotify("Unknown UE1 texture format: %d", Format);
			return false;
		}
	}
	else
	{
		// UE2
		switch (Format)
		{
		case TEXF_P8:
			intFormat = TPF_P8;
			break;
		case TEXF_DXT1:
			intFormat = TPF_DXT1;
			break;
		case TEXF_RGB8:
			intFormat = TPF_RGB8;
			break;
		case TEXF_RGBA8:
			intFormat = TPF_BGRA8;
			break;
		case TEXF_DXT3:
			intFormat = TPF_DXT3;
			break;
		case TEXF_DXT5:
			intFormat = TPF_DXT5;
			break;
		case TEXF_L8:
			intFormat = TPF_G8;
			break;
		case TEXF_CxV8U8:
			intFormat = TPF_V8U8_2;
			break;
		case TEXF_DXT5N:
			intFormat = TPF_DXT5N;
			break;
		case TEXF_3DC:
			intFormat = TPF_BC5;
			break;
		default:
			appNotify("Unknown UE2 texture format: %s (%d)", TexData.OriginalFormatName, Format);
			return false;
		}
	}

	TexData.Format = intFormat;

#if BIOSHOCK && SUPPORT_XBOX360
	if (TexData.Mips.Num() && TexData.Platform == PLATFORM_XBOX360)
	{
		for (int MipLevel = 0; MipLevel < TexData.Mips.Num(); MipLevel++)
			TexData.DecodeXBox360(MipLevel);
	}
#endif
#if BIOSHOCK
	if (Package && PackageAr->Game == GAME_Bioshock)
	{
		// This game has DataSize stored for all mipmaps, we should compute side of 1st mipmap
		// in order to accept this value when uploading texture to video card (some vendors rejects
		// large values)
		//?? Place code to CTextureData method?
		const CPixelFormatInfo &Info = PixelFormatInfo[intFormat];
		int numBlocks = TexData.Mips[0].USize * TexData.Mips[0].VSize / (Info.BlockSizeX * Info.BlockSizeY);	// used for validation only
		int requiredDataSize = numBlocks * Info.BytesPerBlock;
		if (requiredDataSize > TexData.Mips[0].DataSize)
		{
			appNotify("Bioshock texture %s: data too small; %dx%d, requires %X bytes, got %X\n",
				Name, TexData.Mips[0].USize, TexData.Mips[0].VSize, requiredDataSize, TexData.Mips[0].DataSize);
		}
		else if (requiredDataSize < TexData.Mips[0].DataSize)
		{
//			appPrintf("Bioshock texture %s: stripping data size from %X to %X\n", Name, TexData.Mips[0].DataSize, requiredDataSize);
			TexData.Mips[0].DataSize = requiredDataSize;
		}
	}
#endif // BIOSHOCK

	return (TexData.Mips.Num() > 0);

	unguardf("%s", Name);
}
Пример #18
0
static bool ReadXprFile(const CGameFileInfo *file)
{
	guard(ReadXprFile);

	FArchive *Ar = appCreateFileReader(file);

	int Tag, FileLen, DataStart, DataCount;
	*Ar << Tag << FileLen << DataStart << DataCount;
	//?? "XPR0" - xpr variant with a single object (texture) inside
	if (Tag != BYTES4('X','P','R','1'))
	{
#if XPR_DEBUG
		appPrintf("Unknown XPR tag in %s\n", file->RelativeName);
#endif
		delete Ar;
		return true;
	}
#if XPR_DEBUG
	appPrintf("Scanning %s ...\n", file->RelativeName);
#endif

	XprInfo *Info = new(xprFiles) XprInfo;
	Info->File      = file;
	Info->DataStart = DataStart;
	// read filelist
	int i;
	for (i = 0; i < DataCount; i++)
	{
		int NameOffset, DataOffset;
		*Ar << NameOffset << DataOffset;
		int savePos = Ar->Tell();
		Ar->Seek(NameOffset + 12);
		// read name
		char c, buf[256];
		int n = 0;
		while (true)
		{
			*Ar << c;
			if (n < ARRAY_COUNT(buf))
				buf[n++] = c;
			if (!c) break;
		}
		buf[ARRAY_COUNT(buf)-1] = 0;			// just in case
		// create item
		XprEntry *Entry = new(Info->Items) XprEntry;
		appStrncpyz(Entry->Name, buf, ARRAY_COUNT(Entry->Name));
		Entry->DataOffset = DataOffset + 12;
		assert(Entry->DataOffset < DataStart);
		// seek back
		Ar->Seek(savePos);
		// setup size of previous item
		if (i >= 1)
		{
			XprEntry *PrevEntry = &Info->Items[i - 1];
			PrevEntry->DataSize = Entry->DataOffset - PrevEntry->DataOffset;
		}
		// setup size of the last item
		if (i == DataCount - 1)
			Entry->DataSize = DataStart - Entry->DataOffset;
	}
	// scan data
	// data block is either embedded in this block or followed after DataStart position
	for (i = 0; i < DataCount; i++)
	{
		XprEntry *Entry = &Info->Items[i];
#if XPR_DEBUG
//		appPrintf("  %08X [%08X]  %s\n", Entry->DataOffset, Entry->DataSize, Entry->Name);
#endif
		Ar->Seek(Entry->DataOffset);
		int id;
		*Ar << id;
		switch (id)
		{
		case 0x80020001:
			// header is 4 dwords + immediately followed data
			Entry->DataOffset += 4 * 4;
			Entry->DataSize   -= 4 * 4;
			break;

		case 0x00040001:
			// header is 5 dwords + external data
			{
				int pos;
				*Ar << pos;
				Entry->DataOffset = DataStart + pos;
			}
			break;

		case 0x00020001:
			// header is 4 dwords + external data
			{
				int d1, d2, pos;
				*Ar << d1 << d2 << pos;
				Entry->DataOffset = DataStart + pos;
			}
			break;

		default:
			// header is 2 dwords - offset and size + external data
			{
				int pos;
				*Ar << pos;
				Entry->DataOffset = DataStart + pos;
			}
			break;
		}
	}
	// setup sizes of blocks placed after DataStart (not embedded into file list)
	for (i = 0; i < DataCount; i++)
	{
		XprEntry *Entry = &Info->Items[i];
		if (Entry->DataOffset < DataStart) continue; // embedded data
		// Entry points to a data block placed after DataStart position
		// we should find a next block
		int NextPos = FileLen;
		for (int j = i + 1; j < DataCount; j++)
		{
			XprEntry *NextEntry = &Info->Items[j];
			if (NextEntry->DataOffset < DataStart) continue; // embedded data
			NextPos = NextEntry->DataOffset;
			break;
		}
		Entry->DataSize = NextPos - Entry->DataOffset;
	}
#if XPR_DEBUG
	for (i = 0; i < DataCount; i++)
	{
		XprEntry *Entry = &Info->Items[i];
		appPrintf("  %3d %08X [%08X] .. %08X  %s\n", i, Entry->DataOffset, Entry->DataSize, Entry->DataOffset + Entry->DataSize, Entry->Name);
	}
#endif

	delete Ar;
	return true;

	unguardf("%s", file->RelativeName);
}
Пример #19
0
void CSkelMeshViewer::FindUE4Animations()
{
#if UNREAL4
	guard(CSkelMeshViewer::FindUE4Animations);

	if (!bIsUE4Mesh)
		return;

	if (!Skeleton)
	{
		appPrintf("No Skeleton object attached to the mesh, doing nothing\n");
		return;
	}

	// Find all packages
	TArray<const CGameFileInfo*> PackageInfos;
	appEnumGameFiles<TArray<const CGameFileInfo*> >( // won't compile with lambda without explicitly providing template argument
		[](const CGameFileInfo* file, TArray<const CGameFileInfo*>& param) -> bool
		{
			param.Add(file);
			return true;
		}, PackageInfos);

	UIProgressDialog progress;
	progress.Show("Finding animations");
	progress.SetDescription("Scanning package");

	// Perform full scan to be able to locate AnimSequence objects
	if (!ScanContent(PackageInfos, &progress))
	{
		appPrintf("Interrupted by user\n");
		return;
	}

	// Find potential uasset files with animations
	TArray<UnPackage*> packagesToLoad;
	packagesToLoad.Empty(256);

	const char* lookupSkeletonName = Skeleton->Name;
	for (int i = 0; i < PackageInfos.Num(); i++)
	{
		UnPackage* package = PackageInfos[i]->Package;
		bool found = false;
		for (int importIndex = 0; importIndex < package->Summary.ImportCount; importIndex++)
		{
			FObjectImport& imp = package->GetImport(importIndex);
			const char* ObjectClass = *imp.ClassName;
			const char* ObjectName = *imp.ObjectName;
			if (!stricmp(ObjectClass, "Skeleton") && !stricmp(ObjectName, lookupSkeletonName))
			{
				// This uasset refers to the Skeleton object with the same name, check if this
				// is an exactly the same Skeleton object as we're using
				const char* referencedFilename = package->GetObjectPackageName(imp.PackageIndex);
				const CGameFileInfo* referencedFile = appFindGameFile(referencedFilename);
				if (!stricmp(Skeleton->Package->Filename, *referencedFile->GetRelativeName()))
				{
					found = true;
					break;
				}
			}
		}

		if (!found) continue; // this package doesn't use our Skeleton

		// Now, if this package has animation sequence - enqueue it for loading
		if (PackageInfos[i]->NumAnimations)
		{
			packagesToLoad.Add(package);
		}
	}

	// Sort packages by name for easier navigation after loading
	packagesToLoad.Sort([](UnPackage* const& a, UnPackage* const& b) -> int
		{
			return stricmp(a->Name, b->Name);
		});

	// Load queued packages
	progress.SetDescription("Loading animations");
	for (int i = 0; i < packagesToLoad.Num(); i++)
	{
		guard(Load);
		UnPackage* package = packagesToLoad[i];
		if (!progress.Progress(package->Filename, i, packagesToLoad.Num()))
			break;
		LoadWholePackage(package);
		unguardf("%d/%d", i, packagesToLoad.Num());
	}

	unguard;
#endif // UNREAL4
}
Пример #20
0
static bool ScanPackage(const CGameFileInfo *file, ScanPackageData &data)
{
	guard(ScanPackage);

	if (data.Progress)
	{
		if (!data.Progress->Progress(file->RelativeName, data.Index++, GNumPackageFiles))
		{
			data.Cancelled = true;
			return false;
		}
	}

	// read a few first bytes as integers
	FArchive *Ar = appCreateFileReader(file);
	unsigned int FileData[16];
	Ar->Serialize(FileData, sizeof(FileData));
	delete Ar;

	unsigned Tag = FileData[0];
	if (Tag == PACKAGE_FILE_TAG_REV)
	{
		// big-endian package
		appReverseBytes(&FileData, ARRAY_COUNT(FileData), sizeof(FileData[0]));
	}
	else if (Tag != PACKAGE_FILE_TAG)	//?? possibly Lineage2 file etc
	{
		//!! use CreatePackageLoader() here to allow scanning of packages with custom header (Lineage etc);
		//!! do that only when something "strange" within data noticed
		return true;
	}
	unsigned int Version = FileData[1];

	FileInfo Info;

#if UNREAL4
	if ((Version & 0xFFFFF000) == 0xFFFFF000)
	{
		// next fields are: int VersionUE3, Version, LicenseeVersion
		Info.Ver    = FileData[3];
		Info.LicVer = FileData[4];
	}
	else
#endif // UNREAL4
	{
		Info.Ver    = Version & 0xFFFF;
		Info.LicVer = Version >> 16;
	}

	Info.Count  = 0;
	strcpy(Info.FileName, file->RelativeName);
//	printf("%s - %d/%d\n", file->RelativeName, Info.Ver, Info.LicVer);
	int Index = INDEX_NONE;
	for (int i = 0; i < data.PkgInfo->Num(); i++)
	{
		FileInfo &Info2 = (*data.PkgInfo)[i];
		if (Info2.Ver == Info.Ver && Info2.LicVer == Info.LicVer)
		{
			Index = i;
			break;
		}
	}
	if (Index == INDEX_NONE)
		Index = data.PkgInfo->Add(Info);
	// update info
	FileInfo& fileInfo = (*data.PkgInfo)[Index];
	fileInfo.Count++;
	// combine filename
	char *s = fileInfo.FileName;
	char *d = Info.FileName;
	while (*s == *d && *s != 0)
	{
		s++;
		d++;
	}
	*s = 0;

	return true;

	unguardf("%s", file->RelativeName);
}