/*********************************/
/*                               */
/*           GET-BRW             */
/*                               */
/*  Extracts PSP-6.02-Browser-   */
/*       File-Name-Order         */
/*                               */
/*     Needs "pspbrwse.jpf"      */
/*    for input file, writes     */
/*  out "brwlist" with win2000+  */
/*     long file name list       */
/*                               */
/*         Version 1.1           */
/*                               */
/*    J. Nagasaki, May. 2010     */
/*                               */
/*********************************/

// History:
//
// Date        Version   Comment
// 2002-07     1.0       First version
// 2006-01-13  1.0.1     Known bug note added
// 2010-05-14  1.1       Browser file parsing improved due to known bug since version 1.0


// PSP Browser File Structure
//
// File header at position 0
// Beginning of first picture name of browser file at file position 0x400
//
// General picture entry of browser file (except first entry):
//
//   Chunk0  Chunk1  Length[0]  Length[1]  Length[2]  Length[3]  Name[0]  Name[1] ... Compressed Thumbnail data
//   0xFF    0xD9    XX         0x00       0x00       0x00       XX       XX      ... XX...

#include <stdio.h>
#include <stdlib.h>

#define		FILECHAR  257	// reserving 256+1 Characters for filenames
#define		BRWOFFSET 0x400	// Offest to first browser file name content

int		i;						// dummy counter
int		c;						// current file character during parsing
char	picturename[FILECHAR];	// current file name buffer of browser file
int		namelength;				// current extracted picture file name length
long	pointer;				// index-pointer to browser file
char	parse;					// browser file name parsing active flag; 0 == end of job

FILE	*infile, *outfile;

//-------------------------- SUB ROUTINES ----------------------------------

// common error message
void no_output(void)
{
	fprintf (stderr, "No Ouptput File generated!\n\n");
}

// file closing handler routine
void fileclose(void)
{
	fclose(infile);
	fclose(outfile);
}

//------------------------------ MAIN --------------------------------------

int main (void)
{
	fprintf (stderr, "\nExtracting file name order of 'pspbrwse.jbf' ");
	fprintf (stderr, "into 'brwlist'\n");


	// Read PSP browser file, set file positions in 'position' if hit.
	infile = fopen("pspbrwse.jbf", "rb");

	if (!infile)
	{
		fprintf (stderr, "PSP-Browser-File not found!\n");
		no_output();
		exit(1);
	}

	// Set file position to begin of first picture name (fix offset [0x400])
	fseek(infile, BRWOFFSET, SEEK_SET);

	// Open output file 'brwlist' for writing
	outfile = fopen("brwlist", "w");

	if (!outfile)
	{
		fprintf (stderr, "\nError in opening 'brwlist'\n");
		no_output();
		exit (2);
	}

	parse = 1;				// by fseek current position of file is beginning of first picture name
	pointer = BRWOFFSET;	// set file pointer to current position

	// main parsing loop - ended by EOF during parsing of browser file
	while (1)
	{
		if (1 == parse)
		{
			namelength = fgetc(infile);		// read length of picture name (<256 assumed!)
			if (EOF == namelength)
			{
				fileclose();
				return 0;
			}

			for (i = 0; i < 3; i++)
			{
				c = fgetc(infile);
				pointer++;
				if (0 != c)					// 3 next bytes must be \0
				{
					parse = 0;
					i = 2;					// "break" recent for-loop, if no \0 in next 3 bytes
				}
				else if (EOF == c)
				{
					fileclose();
					return 0;
				}
			}

			if (1 == parse)					// extract file name string
			{
				for (i = 0; i < namelength; i++)
				{
					picturename[i] = fgetc(infile);
					if (EOF == picturename[i])
					{
						fileclose();
						return 0;
					}
				}
				picturename[namelength] = '\0'; // set end of string (added for strange NTFS "postfix" entries in browser file)

				fprintf (outfile, "%s\n", picturename);	// file name finally found and added to 'brwlist'
				fprintf (stderr, "%s\n", picturename);	// file name also printed to console: May be deleted for speed reasons

				pointer += namelength;			// move on at least with size (and 4 byte length from above)
				fseek(infile, pointer, SEEK_SET);
			}
			parse = 0;							// recent parsing/extracting of file name entry finished -> seach for new one
		}

		c = fgetc(infile);			// get next byte
		pointer++;					// update index-pointer for possible next "fseek"

		if (EOF == c)
		{
			fileclose();
			return 0;
		}
		else if (0xFF == c)			// first chunk?
		{
			c = fgetc(infile);
			pointer++;
			if (EOF == c)
			{
				fileclose();
				return 0;
			}
			else if (0xD9 == c)		// second Chunk? Yes -> Next parsing in while(1)-loop
			{
				parse = 1;
			}
		}
	}

	// should never be executed
	fileclose();
	return 0;
}




