rdpascii2rdram.c 8.59 KB
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>

#include <mbi.h>
#include <verify.h>

#define ZBUFFER_ADDR	0x00280000 /* hard coded as per rdpvector's spec file */
#define CFB0_ADDR	0x00380000 /* hard coded as per rdpvector's spec file */
#define CFB1_ADDR	0x003a5800 /* hard coded as per rdpvector's spec file */
#define RDPLIST_ADDR	0x00000a00 /* placed above verifyInfo in 1st MB of ram*/

static long long
htonll(long long x) {
    unsigned int *y = (unsigned int *)&x, z;
    if (htons(0xdead) != 0xdead) {
	z = y[0];
	y[0] = htonl(y[1]);
	y[1] = htonl(z);
    }
    return x;
}


/*
 * NOTE: Texture address is read in from the ascii dump.
 */

/*
 * rdpascii2rdram.c: convert an ascii version of a set of RDP display lists
 *		     and loaded textures to compressed 2MB binary .rdram files.
 */

main (int argc,  char *argv[])
{
    int ascii_fd, binary_fd = -1, bytesRead;
    unsigned char readbuf[80], *readPtr;
    char cmdbuf[160], fname[80], fname_prefix[80];
    int bufIndex, eof = 0;
    unsigned long long int rdp_dl_word;
    int rdp_dl_length; /* Length is in 64 bit words */
    unsigned long long int *fourMeg, *texAddr, *rdp_dl_addr;
    int dumpingTexture = 0;
    VerifyInfo *verify;

    if (argc != 2) {
	fprintf(stderr, "Usage: %s ascii_rdp_file\n", argv[0]);
	exit(1);
    }
    
    if ( (ascii_fd = open(argv[1], O_RDONLY)) == -1) {
	sprintf(cmdbuf, "Could not open ascii rdp file %s", argv[1]);
	perror(cmdbuf);
	exit(1);
    }

    fourMeg = (unsigned long long int *)malloc(0x400000);
    if (fourMeg == NULL) {
	fprintf(stderr, "Unable to malloc four megabyte .rdram buffer\n");
	exit(1);
    }
    
    verify = (VerifyInfo *)( (int)(fourMeg) + VERIFY_INFO_PHYSADDR );

    /*
     * Initialize those fields within the verifyInfo struct which must be
     * defined for purposes of RDP simulation.  The only fields which may
     * change for each display list we read in are:
     *
     *     verify->rdpListSize
     *     verify->frameBufferSize
     *     verify->width
     *     verify->height
     */
    verify->rdpListAddr = 	(unsigned int) htonl(RDPLIST_ADDR);
    verify->frameBuffer0Addr =	(unsigned int) htonl(CFB0_ADDR);
    verify->frameBuffer1Addr =	(unsigned int) htonl(CFB1_ADDR);
    verify->zBufferAddr =	(unsigned int) htonl(ZBUFFER_ADDR);
    verify->frameBufferFormat =	htonl(G_IM_FMT_RGBA);
    verify->frameBufferSize =	htonl(G_IM_SIZ_16b);
    verify->width =		htons(320);
    verify->height =		htons(240);
    verify->magicNumber =	htonl(MAGICNUMBER);
    verify->version =		htonl(VERSION);

    while (!eof) {

	bufIndex = 0;
	bytesRead = read(ascii_fd, &(readbuf[bufIndex]), 1);
	if (bytesRead == 0) {
	    close(ascii_fd);

	    /*
	     * Write out the rdp_dl_length, in bytes.
	     */
	    verify->rdpListSize = htonll(rdp_dl_length * 8);

	    /*
	     * Close the previously opened .rdram file, if one had been
	     * opened.  Also run "rdramgclr" and "compress" on the file
	     * to clear the color & z buffers, as well as to shrink the
	     * 2MB to something more reasonable.
	     */
	    if (binary_fd > 0) {
		write(binary_fd, fourMeg, 0x400000);
		if (verify->width == 1024) {
		    /*
		     * Make an 8MB file, so that rdramgclr's rdraminit()
		     * will size the rdram for a 8 MB system, which is
		     * what we need for a 2MB (1K x 1K) cfb + 2MB z buffer.
		     *
		     * The data written to the file here doesn't matter...
		     */
		    write(binary_fd, fourMeg, 0x400000);
		}
		close(binary_fd);
		sprintf(cmdbuf, "%s/usr/sbin/rdramgclr %s",
			getenv("ROOT") ? getenv("ROOT") : "", fname_prefix);
		system(cmdbuf);
		sprintf(cmdbuf, "compress -f %s", fname);
		system(cmdbuf);
	    }
	    exit(0);
	} else {

	    while (readbuf[bufIndex++] != '\n') {
		bytesRead = read(ascii_fd, &(readbuf[bufIndex]), 1);
		if (bytesRead != 1) {
		    fprintf(stderr, "short read from ascii rdp file %s\n", 
			argv[1]);
		    exit(1);
		}
	    }

	    /* 
	     * We've read in a line from the ascii file.  Check to see if the
	     * first line contains the word "TEST"; if so, the rest of the line
	     * will be read and used as the filename for the binary .rdp file
	     * we are to create from the rdp display list commands which follow.
	     *
	     * Otherwise, check to see if the line is a TEXTURE DUMP; if so, 
	     * the intervening lines up to the next "TEST" are texture data,
	     * and need to be copied into the texture segment of our four meg
	     * rdram buffer.
	     */
	    if (strncmp(readbuf, "TEST", 4) == 0) {
		/*
		 * Read the third word on this line to determine 16/32 cfb.
		 */
		readPtr = readbuf + 5; 
		if (strlen(readPtr) == 0) {
		    fprintf(stderr, 
	        "Bad filename encountered; unable to open rdp binary file.\n");
		    exit(1);
		}
		readPtr = (unsigned char *)strchr(readbuf, ' ');
		readPtr++;	/* Skip past the space */
		readPtr = (unsigned char *)strchr(readPtr, ' ');
		readPtr++;	/* Skip past the space */

		/*
		 * Terminate the remainder of the line so that we can 
		 * better extract the filename.
		 */
		*(readPtr - 1) = '\0';

		/*
		 * Write out the rdp_dl_length, in bytes.
		 */
		verify->rdpListSize = htonll(rdp_dl_length * 8);

		/*
		 * Turn off the "texture dump" mode, if we had been in that
		 * mode, and reset the rdp display list pointer.
		 */
		dumpingTexture = 0;
		rdp_dl_addr = (unsigned long long int *)
		    ( (int)(fourMeg) + RDPLIST_ADDR );

		rdp_dl_length = 0;

		/*
		 * Close the previously opened .rdram file, if one had been
		 * opened.  Also run "rdramgclr" and "compress" on the file
		 * to clear the color & z buffers, as well as to shrink the
		 * 2MB to something more reasonable.
		 */
		if (binary_fd > 0) {
		    write(binary_fd, fourMeg, 0x400000);
		    if (verify->width == htonl(1024)) {
			/*
			 * Make an 8MB file, so that rdramgclr's rdraminit()
			 * will size the rdram for a four MB system, which is
			 * what we need for a 2MB (1K x 1K) cfb + 2MB z buffer.
			 *
			 * The data written to the file here doesn't matter...
			 */
			write(binary_fd, fourMeg, 0x400000);
		    }
		    close(binary_fd);
		    sprintf(cmdbuf, "%s/usr/sbin/rdramgclr %s", 
			    getenv("ROOT") ? getenv("ROOT") : "", fname_prefix);
		    system(cmdbuf);
		    sprintf(cmdbuf, "compress -f %s", fname);
		    system(cmdbuf);
		}

		/*
		 * Determine cfb size for the DL we are about to read in.
		 */

		if (strncmp(readPtr, "16", 2) == 0) {
		    verify->frameBufferSize = htonl(G_IM_SIZ_16b);
		    verify->width = htons(320);
		    verify->height = htons(240);
		} else if (strncmp(readPtr, "32", 2) == 0) {
		    verify->frameBufferSize = htonl(G_IM_SIZ_32b);
		    verify->width = htons(320);
		    verify->height = htons(240);
		} else if (strncmp(readPtr, "1024", 4) == 0) {
		    verify->frameBufferSize = G_IM_SIZ_32b;
		    verify->width = htonl(1024);
		    verify->height = htonl(1024);
		} else {
		    fprintf(stderr, "Bogus cfb size %s\n", readPtr);
		    exit(1);
		}

		/*
		 * Skip past the "TEST ", to the start of the filename.
		 */
		readPtr = readbuf + 5; 
		if (strlen(readPtr) == 0) {
		    fprintf(stderr, 
	        "Bad filename encountered; unable to open rdp binary file.\n");
		    exit(1);
		}
		/* 
		 * Tack on a .rdram suffix.
		 */
		strcpy(fname, readPtr);
		strcpy(fname_prefix, readPtr);
		strcat(fname, ".rdram");

		if ( (binary_fd = creat(fname, 0666)) == -1 ) {
		    sprintf(cmdbuf, "Could not open binary rdp file %s", 
			fname);
		    perror(cmdbuf);
		    exit(1);
		}
	    } else if (strncmp(readbuf, "TEXTURE DUMP", 12) == 0) {
		/*
		 * Texture data will be found on all following lines, up 
		 * to the first line encountered beginning with "TEST".
		 *
		 * Skip past the "TEXTURE DUMP ", to the address of the texture
		 * segment.
		 */
		readPtr = readbuf + 13; 
		sscanf(readPtr, "%x", (char *)&texAddr);
		dumpingTexture = 1;
		texAddr = (unsigned long long int *)
		    ( (int)(fourMeg) + (int)texAddr );
	    } else {
		/*
		 * Use strchr & sscanf to convert a 64 bit word to binary, 
		 * then write this long long (64 bit) word out to the currently
		 * open binary file.
		 */
		readPtr = (unsigned char *)strchr(readbuf, ':');

		if (readPtr == NULL) {
		    fprintf(stderr, "strange line read from ascii rdp file %s\n", 
			readbuf);
		    exit(1);
		}

		/* 
		 * Skip past the ": ", and point directly at the hexnum; terminate
		 * the string with a NULL character to end the conversion.
		 */
		readPtr += 2; 
		*(readPtr + 18) = '\0';


		sscanf(readPtr, "%llx", (char *)&rdp_dl_word);
		if (dumpingTexture) {
		    *texAddr++ = htonll(rdp_dl_word);
		} else {
		    *rdp_dl_addr++ = htonll(rdp_dl_word);
		    rdp_dl_length++;
		}
	    }
	}
    }
}