Difference between revisions of "User:Steven/flip frame decode.c"

From DSiBrew
Jump to navigation Jump to search
(New page: Please note that there is very little comments and this application just outputs to the text console at the moment, but the code used here can be expanded to produce any other image file f...)
 
(GCC gave me errors which were caused by "wise" M$ thinking that typecast isn't neccessary :()
 
(2 intermediate revisions by one other user not shown)
Line 99: Line 99:
 
{
 
{
 
     printf( "Magic Number    : %c%c%c%c\n", ptr->magic[0], ptr->magic[1], ptr->magic[2], ptr->magic[3] );
 
     printf( "Magic Number    : %c%c%c%c\n", ptr->magic[0], ptr->magic[1], ptr->magic[2], ptr->magic[3] );
     printf( "File Size      : %d (%08X)\n", ptr->fileSize, ptr->fileSize );
+
     printf( "File Size      : %d (%08X)\n", (int)ptr->fileSize, (unsigned int)ptr->fileSize );
     printf( "Audio offset    : %d (%08X)\n", ptr->audioOffset, ptr->audioOffset );
+
     printf( "Audio offset    : %d (%08X)\n", (int)ptr->audioOffset, (unsigned int)ptr->audioOffset );
 
     printf( "# Frames        : %d\n", ptr->numberOfFrames );
 
     printf( "# Frames        : %d\n", ptr->numberOfFrames );
 
     printf( "Unknown        : 0x%04X\n", ptr->unk0 );
 
     printf( "Unknown        : 0x%04X\n", ptr->unk0 );
Line 237: Line 237:
 
if( buf == NULL )
 
if( buf == NULL )
 
{
 
{
printf( "Error unable to allocate buffer for frame %d\n", frmBuf );
+
printf( "Error unable to allocate buffer for frame %d\n", (int)frmBuf );
 
return;
 
return;
 
}
 
}
Line 243: Line 243:
 
frmOffset = getFrameOffset( frmBuf, 1 );
 
frmOffset = getFrameOffset( frmBuf, 1 );
  
printf( "Frame #%d offset %08X\n", frmNum, frmOffset );
+
printf( "Frame #%d offset %08X\n", frmNum, (unsigned int)frmOffset );
  
 
colPaper  = frmBuf[ frmOffset ] & 0x01;
 
colPaper  = frmBuf[ frmOffset ] & 0x01;
Line 294: Line 294:
 
case 0: // Skip this line
 
case 0: // Skip this line
 
byteUse = 0;
 
byteUse = 0;
printf( "Line %3d(%04X), Layer 1, Skip Frame [%08X]\toffset %08X\n", lnePos, lnePos, byteUse, frmOffset + 0x6a0 );
+
printf( "Line %3d(%04X), Layer 1, Skip Frame [%08X]\toffset %08X\n", lnePos, lnePos, (unsigned int)byteUse, (unsigned int)frmOffset + 0x6a0 );
 
break;
 
break;
 
case 1: // Coded
 
case 1: // Coded
 
byteUse = getu32inv( &frmBuf[ frmOffset ] );
 
byteUse = getu32inv( &frmBuf[ frmOffset ] );
printf( "Line %3d(%04X), Layer 1, Coded      [%08X]\toffset %08X\n", lnePos, lnePos, byteUse, frmOffset + 0x6a0 );
+
printf( "Line %3d(%04X), Layer 1, Coded      [%08X]\toffset %08X\n", lnePos, lnePos, (unsigned int)byteUse, (unsigned int)frmOffset + 0x6a0 );
 
frmOffset += 4;
 
frmOffset += 4;
 
frmOffset += decodeLine( &buf[ lnePos << 8 ], &frmBuf[ frmOffset ], byteUse, outFrameG[ 0 ], outFrameG[ colLayer1 ], 0 );
 
frmOffset += decodeLine( &buf[ lnePos << 8 ], &frmBuf[ frmOffset ], byteUse, outFrameG[ 0 ], outFrameG[ colLayer1 ], 0 );
Line 304: Line 304:
 
case 2: // Inv Coded
 
case 2: // Inv Coded
 
byteUse = getu32inv( &frmBuf[ frmOffset ] );
 
byteUse = getu32inv( &frmBuf[ frmOffset ] );
printf( "Line %3d(%04X), Layer 1, Inv Coded  [%08X]\toffset %08X\n", lnePos, lnePos, byteUse, frmOffset + 0x6a0 );
+
printf( "Line %3d(%04X), Layer 1, Inv Coded  [%08X]\toffset %08X\n", lnePos, lnePos, (unsigned int)byteUse, (unsigned int)frmOffset + 0x6a0 );
 
frmOffset += 4;
 
frmOffset += 4;
 
frmOffset += decodeLine( &buf[ lnePos << 8 ], &frmBuf[ frmOffset ], byteUse, outFrameG[ colLayer1 ], outFrameG[ 0 ], 1 );
 
frmOffset += decodeLine( &buf[ lnePos << 8 ], &frmBuf[ frmOffset ], byteUse, outFrameG[ colLayer1 ], outFrameG[ 0 ], 1 );
Line 310: Line 310:
 
case 3: // Full Line
 
case 3: // Full Line
 
byteUse = 0xFFFFFFFF;
 
byteUse = 0xFFFFFFFF;
printf( "Line %3d(%04X), Layer 1, Full Frame [%08X]\toffset %08X\n", lnePos, lnePos, byteUse, frmOffset + 0x6a0 );
+
printf( "Line %3d(%04X), Layer 1, Full Frame [%08X]\toffset %08X\n", lnePos, lnePos, (unsigned int)byteUse, (unsigned int)frmOffset + 0x6a0 );
 
frmOffset += decodeLine( &buf[ lnePos << 8 ], &frmBuf[ frmOffset ], byteUse, outFrameG[ 0 ], outFrameG[ colLayer1 ], 0 );
 
frmOffset += decodeLine( &buf[ lnePos << 8 ], &frmBuf[ frmOffset ], byteUse, outFrameG[ 0 ], outFrameG[ colLayer1 ], 0 );
 
break;
 
break;

Latest revision as of 21:18, 15 February 2010

Please note that there is very little comments and this application just outputs to the text console at the moment, but the code used here can be expanded to produce any other image file formats you wanted. I'm still working on the sound format and as such there is no functions for the sound yet.

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

// Disable MS VC's "unsecure / depricated" code warning
#pragma warning( disable : 4996 )

// setup some file types for set sizes
typedef signed char		s8;
typedef signed short	s16;
typedef signed long		s32;
typedef unsigned char	u8;
typedef unsigned short	u16;
typedef unsigned long	u32;

typedef struct PPM_HEADER
{
    u8  magic[4];
    u32 fileSize;
    u32 audioOffset;
    u16 numberOfFrames;
    u16 unk0;
    u16 flags;
    u16 previewFrameNumber;
    u16 originalAuthorName[11];
    u16 authorName[11];
    u16 userName[11];
    u8  originalAuthorID[8];
    u8  editAuthorID[8];
    u8  originalFileName[18];
    u8  fileName[18];
    u8  authorID[8];
    u8  unk1[8];
    u8  unk2[6];
    u8  previewBitmap[1536];
} ppmHeader;

int flength(FILE *f)
{
  int pos,end;
  pos = ftell (f);
  fseek (f, 0, SEEK_END);
  end = ftell (f);
  fseek (f, pos, SEEK_SET);
  return end;
}

char *idFromStr( u8 is[8] )
{
    static char retVal[32];
    int i;
    
    memset( retVal, 0, 32 );
    
    for( i = 7; i >= 0; i -- )
         sprintf( retVal, "%s%02X", retVal, ( is[ i ] & 0xFF ) );
    
    return retVal;
}

char *filenameFromStr( u8 fn[18] )
{
    static char retVal[64];
    int i;
    
    memset( retVal, 0, 32 );
    
    for( i = 0; i < 3; i ++ )
         sprintf( retVal, "%s%02X", retVal, ( fn[ i ] & 0xFF ) );
         
    strcat( retVal, "_" );
    
    for( i = 3; i < 16; i ++ )
         sprintf( retVal, "%s%c", retVal, ( fn[ i ] & 0xFF ) );
    
    sprintf( retVal, "%s_%03d", retVal, ( fn[ 16 ] & 0xFF ) + ( ( fn[ 17 ] & 0xFF ) << 8 ) );
    
    return retVal;
}

char *hexFromStr( u8 is[8], int len )
{
    static char retVal[256];
    int i;
    
    memset( retVal, 0, 256 );
    
    for( i = 0; i < len; i ++ )
         sprintf( retVal, "%s%02X ", retVal, ( is[ i ] & 0xFF ) );
    
    return retVal;
}

void printHeaderInfo( ppmHeader *ptr )
{
    printf( "Magic Number    : %c%c%c%c\n", ptr->magic[0], ptr->magic[1], ptr->magic[2], ptr->magic[3] );
    printf( "File Size       : %d (%08X)\n", (int)ptr->fileSize, (unsigned int)ptr->fileSize );
    printf( "Audio offset    : %d (%08X)\n", (int)ptr->audioOffset, (unsigned int)ptr->audioOffset );
    printf( "# Frames        : %d\n", ptr->numberOfFrames );
    printf( "Unknown         : 0x%04X\n", ptr->unk0 );
    printf( "Flags?          : 0x%04X - 0 = open, 1 = locked\n", ptr->flags );
    printf( "Preview Frame # : %d\n", ptr->previewFrameNumber );
    printf( "Orig Author     : UCS-2 string \n" );
    printf( "Author          : UCS-2 string \n" );
    printf( "Edit Author     : UCS-2 string \n" );
    printf( "Orig Author ID  : %s\n", idFromStr( ptr->originalAuthorID ) );
    printf( "Edit Author ID  : %s\n", idFromStr( ptr->editAuthorID ) );
    printf( "Orig Filename   : %s\n", filenameFromStr( ptr->originalFileName ) );
    printf( "Curr Filename   : %s\n", filenameFromStr( ptr->fileName ) );
    printf( "Author ID       : %s\n", idFromStr( ptr->authorID ) );
    printf( "Unknown 8 bytes : %s\n", hexFromStr( ptr->unk1, 8 ) ) ;
    printf( "Unknown 6 bytes : %s\n", hexFromStr( ptr->unk2, 6 ) ) ;
}

static char outPreviewG[] = { ' ', 176, 219, 178, 'r', 'R', 'p', 'X', 'B', 'P', 'b', 'x', 'M', '.', '.', '.' };

static char outFrameG0[] = {  32, 219, 176, 178 };
static char outFrameG1[] = { 219,  32, 176, 178 };

void displayPreviewImage( u8 img[1536] )
{
    int x, y, cellOffset;
    int xp, xc;
    u8 c;
    
    for( y = 0; y < 48; y ++ )
    {
        cellOffset = ( ( y >> 3 ) * 256 ) + ( ( y & 0x7 ) << 2 );
        for( x = 0; x < 64; x ++ )
        {
            xp = ( x & 7 ) >> 1;
            xc = ( ( x >> 3 ) << 5 );
            c = img[ cellOffset + xp + xc ];
            printf( "%c", outPreviewG[ ( x & 1 ? c  >> 4 : c ) & 0xF ] );
        }
        printf( "\n" );
    }
}

u32 getu32( u8 *buf )
{
	u32 retVal = 0;

	retVal = retVal | ( buf[ 0 ] <<  0 );
	retVal = retVal | ( buf[ 1 ] <<  8 );
	retVal = retVal | ( buf[ 2 ] << 16 );
	retVal = retVal | ( buf[ 3 ] << 24 );

	return retVal;
}

u32 getu32inv( u8 *buf )
{
	u32 retVal = 0;

	retVal = retVal | ( buf[ 3 ] <<  0 );
	retVal = retVal | ( buf[ 2 ] <<  8 );
	retVal = retVal | ( buf[ 1 ] << 16 );
	retVal = retVal | ( buf[ 0 ] << 24 );

	return retVal;
}

u32 getFrameOffset( u8 *buf, u16 frm )
{
	u32 numBytes;

	numBytes = getu32( buf );

	if( frm > ( numBytes >> 2 ) )
		return 0;
	
	return ( getu32( &buf[ 4 + ( frm << 2 ) ] ) + 8 + numBytes );
}

u32 decodeLine( u8 *outB, u8 *inB, u32 useByte, u8 paper, u8 pen, u8 invflag )
{
	u32 offset = 0;
	u16 x = 0, i;
	u8 data;

	if( useByte == 0 ) // Set the full line to the current paper colour
		memset( outB, paper, 256 );
	else // Bytes in this line, read and deal with them
	{
		while( useByte != 0 )
		{
			if( ( useByte & 0x80000000 ) == 0x80000000 )
			{
				// This byte exists...
				data = inB[ offset++ ];

				for( i = 0; i < 8; i ++ )
				{
					if( ( data & 0x01 ) == 0x01 )
						outB[ x ] = invflag == 0 ? pen : paper;
					else
						outB[ x ] = invflag == 0 ? paper : pen;

					x ++;

					data >>= 1;
				}
			}
			else
			{
				memset( &outB[ x ], paper, 8 );
				x += 8;
			}

			useByte <<= 1;
		}

		if( x < 256 )
			memset( &outB[ x ], paper, 256 - x );
	}

	return offset;
}

void displayFrame( u8 *frmBuf, u16 frmNum )
{
	u8 colPaper, colLayer1, colLayer2;
	u32 frmOffset;
	u8 lEnc[192];
	u8 *buf;
	u8 lnePos, lneCount;
	u8 *outFrameG;
	u16 x, y;
	u32 byteUse;

	buf = (u8*) malloc( 256 * 192 );
	if( buf == NULL )
	{
		printf( "Error unable to allocate buffer for frame %d\n", (int)frmBuf );
		return;
	}

	frmOffset = getFrameOffset( frmBuf, 1 );

	printf( "Frame #%d offset %08X\n", frmNum, (unsigned int)frmOffset );

	colPaper  = frmBuf[ frmOffset ] & 0x01;
	colLayer1 = ( frmBuf[ frmOffset ] >> 1 ) & 0x03;
	colLayer2 = ( frmBuf[ frmOffset ] >> 3 ) & 0x03;

	printf( "Paper colour:   %s\n", ( colPaper == 0 ? "Black" : "White" ) );
	printf( "Layer 1 colour: %d\n", colLayer1 );
	printf( "Layer 2 colour: %d\n", colLayer2 );

	if( colPaper == 0 )
		outFrameG = outFrameG0;
	else
		outFrameG = outFrameG1;

	memset( buf, outFrameG[0], 192 << 8 );

	lnePos = 0;
	frmOffset ++;

	// Read layer 1 line information into lower nibble
	for( lneCount = 0; lneCount < 48; lneCount ++ )
	{
		lEnc[ lnePos++ ] = ( frmBuf[ frmOffset ] >> 0 ) & 0x03;
		lEnc[ lnePos++ ] = ( frmBuf[ frmOffset ] >> 2 ) & 0x03;
		lEnc[ lnePos++ ] = ( frmBuf[ frmOffset ] >> 4 ) & 0x03;
		lEnc[ lnePos++ ] = ( frmBuf[ frmOffset ] >> 6 ) & 0x03;
		frmOffset ++;
	}

	lnePos = 0;
	// Read layer 2 line information into upper nibble
	for( lneCount = 0; lneCount < 48; lneCount ++ )
	{
		lEnc[ lnePos++ ] |= ( frmBuf[ frmOffset ] << 4 ) & 0x30;
		lEnc[ lnePos++ ] |= ( frmBuf[ frmOffset ] << 2 ) & 0x30;
		lEnc[ lnePos++ ] |= ( frmBuf[ frmOffset ] >> 0 ) & 0x30;
		lEnc[ lnePos++ ] |= ( frmBuf[ frmOffset ] >> 2 ) & 0x30;
		frmOffset ++;
	}

	//read frame here...
	// First read layer 1.
	lnePos = 0;

	while( lnePos < 192 )
	{
		switch( lEnc[ lnePos ] & 0x03 )
		{
			case 0: // Skip this line
				byteUse = 0;
				printf( "Line %3d(%04X), Layer 1, Skip Frame [%08X]\toffset %08X\n", lnePos, lnePos, (unsigned int)byteUse, (unsigned int)frmOffset + 0x6a0 );
				break;
			case 1: // Coded
				byteUse = getu32inv( &frmBuf[ frmOffset ] );
				printf( "Line %3d(%04X), Layer 1, Coded      [%08X]\toffset %08X\n", lnePos, lnePos, (unsigned int)byteUse, (unsigned int)frmOffset + 0x6a0 );
				frmOffset += 4;
				frmOffset += decodeLine( &buf[ lnePos << 8 ], &frmBuf[ frmOffset ], byteUse, outFrameG[ 0 ], outFrameG[ colLayer1 ], 0 );
				break;
			case 2: // Inv Coded
				byteUse = getu32inv( &frmBuf[ frmOffset ] );
				printf( "Line %3d(%04X), Layer 1, Inv Coded  [%08X]\toffset %08X\n", lnePos, lnePos, (unsigned int)byteUse, (unsigned int)frmOffset + 0x6a0 );
				frmOffset += 4;
				frmOffset += decodeLine( &buf[ lnePos << 8 ], &frmBuf[ frmOffset ], byteUse, outFrameG[ colLayer1 ], outFrameG[ 0 ], 1 );
				break;
			case 3: // Full Line
				byteUse = 0xFFFFFFFF;
				printf( "Line %3d(%04X), Layer 1, Full Frame [%08X]\toffset %08X\n", lnePos, lnePos, (unsigned int)byteUse, (unsigned int)frmOffset + 0x6a0 );
				frmOffset += decodeLine( &buf[ lnePos << 8 ], &frmBuf[ frmOffset ], byteUse, outFrameG[ 0 ], outFrameG[ colLayer1 ], 0 );
				break;
		}

		lnePos ++;
	}

	//output frame here...
	for( y = 0; y < 192; y ++ )
	{
		for( x = 0; x < 256; x ++ )
		{
			printf( "%c", buf[ x + ( y << 8 ) ] );
		}
		printf( "\n" );
	}

}

void hexOut( char *buf, int len )
{
    int i;
    
    for( i = 0 ; i < len ; i ++ )
    {
        printf( "%02X ", buf[i] & 0xFF );
        
        if( ( i & 0xF ) == 0xF )
            printf( "\n" );
    }
}

int main(int argc, char* argv[])
{
  ppmHeader *pHead;
  FILE *fp;
  int f_len;
  char *f_buf;
  
  if(argc != 2)
  {
    printf("usage: %s <anim.ppm>\n", argv[0]);
    exit(0);
  }
 
  fp = fopen(argv[1],"rb");
  if(fp == NULL)
  {
    printf("input file not found\n");
    exit(1);
  }
 
  f_len = flength(fp);
  f_buf = malloc(f_len);
  if(f_buf == NULL)
  {
    fprintf(stderr, "not enough memory\n");
    exit(1);
  }
 
  if(fread(f_buf, f_len, 1, fp) != 1)
  {
    fprintf(stderr, "file read failure\n");
    exit(1);
  }

  pHead = (ppmHeader *) f_buf;

  printHeaderInfo( pHead );
  
  displayPreviewImage( pHead->previewBitmap );
  
  printf( "\n" );

  displayFrame( &f_buf[ 0x6a0 ], 1 );

  printf( "\n" );
  
  hexOut( &f_buf[ 0x6a0 ], 256 );
  
  printf( "\n" );
  
  hexOut( &f_buf[ f_len - 256 ], 256 );
  
  printf("finished..\n");
  free( f_buf);
  fclose(fp);
 
  return 0;
}