
fbool PakFile_Create_From_List (char* outputPakName, text1024_t* listOfFiles, int numFiles)
{
	int				i;

	packheader_t	pakHeader;
	packfile_t		pakDirectory[4096];
	int				pakHeaderSize = sizeof(pakHeader);

	int				dataBytesWritten = 0, fileSize, markSpot;
	
	FILE*			pakHandle = fopen (outputPakName, "wb");
	
	if (!pakHandle)
	{
		printf ("Error opening file for write '%s'\n", outputPakName);
		return False;
	}

	memset (&pakHeader, 0, sizeof(pakHeader));
	memset (pakDirectory, 0, sizeof(pakDirectory));

	// Write the header with invalid data.  Don't worry we will be updating this later.
	fwrite (&pakHeader, pakHeaderSize, 1, pakHandle);

	// Write the files
	for (i = 0; i < numFiles ; i ++)
	{
		char* curFile	= listOfFiles[i].text;
		
		markSpot = File_GetCursor (pakHandle); 

		dataBytesWritten += (fileSize = File_Append_BinaryFile (pakHandle, curFile) ); // Get file size, increment dataBytes

		pakDirectory[i].filepos = LittleLong (markSpot); // LittleLong for Endian correctness
		pakDirectory[i].filelen = LittleLong (fileSize); // LittleLong for Endian correctness
		StringLCopy (pakDirectory[i].name, String_SkipPath(curFile));
		
	}

	{
		// Store the offset then write the directory.  Data at pakDirectory with entry size of entry 0 times filecount
			
		int direntSize			= sizeof(pakDirectory[0]);
		int directoryStart		= File_GetCursor (pakHandle);
		int directoryByteLength = direntSize * numFiles;

		fwrite (pakDirectory, directoryByteLength, 1, pakHandle);
		
		// Construct final header
		pakHeader.id[0] = 'P';
		pakHeader.id[1] = 'A';
		pakHeader.id[2] = 'C';
		pakHeader.id[3] = 'K';
		pakHeader.dirofs = LittleLong (directoryStart);
		pakHeader.dirlen = LittleLong (directoryByteLength);

		// Go back to the beginning and rewrite the header

		File_SetCursor_ToStart (pakHandle);
		fwrite (&pakHeader, pakHeaderSize, 1, pakHandle); 
	}

	// close the file

	fclose (pakHandle);
	return True;
}


mip2wad2 - Baker 5/15/2012

GPL 2.0


Dev notes (These are like notes for ME.  Not for you.):


//unsigned    attrib;
//__time64_t  time_create;    /* -1 for FAT file systems */
//__time64_t  time_access;    /* -1 for FAT file systems */
//__time64_t  time_write;
//_fsize_t    size;
//char        name[260];

// If successful, _findfirst returns a unique search handle identifying the file or group of files that
// match the filespec specification, which can be used in a subsequent call to _findnext or to _findclose.
// Otherwise, _findfirst returns -1 and sets errno to one of the following values.

//#define _A_NORMAL       0x00    /* Normal file - No read/write restrictions */
//#define _A_RDONLY       0x01    /* Read only file */
//#define _A_HIDDEN       0x02    /* Hidden file */
//#define _A_SYSTEM       0x04    /* System file */
//#define _A_SUBDIR       0x10    /* Subdirectory */
//#define _A_ARCH         0x20    /* Archive file */



Code laying around:



// For future?
// MIP
// First we need to size reinforce the proggy
// http://www.celephais.net/stuff/texturefaq.htm
// 1. Texture names must be no longer than 15 characters
// 2. All texture dimensions must be multiples of 16
// 3. GLQuake doesn't require that liquids be 64x64.
// 4. Begins with "*" Slime, lava, water, and clip textures should be 64x64. (Let's go for WinQuake compatibility)
// 5. Textures that begin with "sky"



			StringLCopy (nameCheck, strippedPath);
			String_Edit_StripExtension (nameCheck);

			nameLength = strlen (nameCheck);

			// Check for name is too long
			if (nameLength > MAX_WAD_TEXTURE_NAME_LENGTH_IS_15)
			{
				printf ("%s: Texture name '%s' is too long with %i characters\n", currentFileName, nameCheck, nameLength);
				isEverythingOK = False;
				continue;
			}

			// Check dimensions

			if (Image_Query_File_Dimensions (currentFileName, &imageWidth, &imageHeight) == False)
			{
				printf ("%s: Couldn't read TGA width and height", currentFileName);
				isEverythingOK = False;
				continue; // foobared I guess or has 0 width or 0 height
			}

			isSizeOK = IS_MULTIPLE_OF_16(imageWidth) && IS_MULTIPLE_OF_16(imageHeight);
			
			if (isSizeOK == False)
			{
				printf ("%s: Width or height (%i x %i) is not multiple of 16\n", currentFileName, imageWidth, imageHeight);
				isEverythingOK = False;
				continue; // Bad sizes print them
			}
			printf ("%i: '%s' = %i w x %i h\n", i, nameCheck, imageWidth, imageHeight);
		} // End of all files

		if (isEverythingOK == False)
		{
			printf ("One or more files failed to pass pre-check.  Aborting.\n");
			Enter_To_Exit_DebugOnly ();
			return 1; // Failure
		}

	} while (0);
				
	// Enforce the multiples of 16 rule.

	printf ("TGA files to convert to MIP = %i\n", numFiles);

	// Turn every TGA into an LMP and write it
	do
	{
		fbool	Perfect = True;
		char	outfileName[MAX_PATH_IS_1024];
		char	textureName[MAX_PATH_IS_1024];

		for (i = 0; i < numFiles; i ++)
		{
			imageRGBA_t	myTGAImage;

			char*	currentFileName = fileNames[i].text;
			fbool	wroteOK			= False;

			// Prepare outfile.mip
			StringLCopy (outfileName, currentFileName);
			String_Edit_StripExtension (outfileName);
			StringLCat (outfileName, ".mip");

			// Prepare textureName like "metal5_1"
			StringLCopy (textureName, String_SkipPath(outfileName));
			String_Edit_StripExtension (textureName);

			// Load the TGA
			if ( !Image_Import_FileX (&myTGAImage, currentFileName) )
				continue; // Skip this image

			wroteOK = Image_Export_Mip_File (&myTGAImage, outfileName, textureName);

			if (Perfect && wroteOK == False)
				Perfect = False;

			{
				char* outty = String_SkipPath (outfileName);
				printf ("%i: Wrote '%s' (%i x %i)\n", i, outty, myTGAImage.width, myTGAImage.height);
			}

			// Unload the TGA
			Image_Destroy (&myTGAImage);	
		}

		printf ("All files written successfully = %s", Perfect ? "Yes" : "**** NO ****");
	} while (0);

