
#ifdef ZOTSDL
#include "zotsdl.h"
#else
#include "zotpalm.h"
#endif

#include "zot.h"

UInt32 PcxFileOff = 0;
UInt32 PcxFileLen = 0;
UInt8 *PcxFileBuf = NULL;

UInt8 *_LoadPCX ( UInt8 *buf, UInt8 *Palette, UInt32 *XSize, UInt32 *YSize,
		  UInt8 *Blk );

/*
Function: EncodeRun
 Description:
	Encodes a run length and a data value and writes them to
	  a PCX file.  This routine has been adapted from the ZSoft
	  PCX documentation.  The routine returns a non-zero value
	  in the event of an error (typically disk full).
*/

static int EncodeRun ( int Val, int RunLength, FILE * File ) {

  if ( RunLength ) {
    if ((RunLength == 1) && (0xC0 != (0xC0 & Val))) {
      /* run of 1 with color index < 0xC0 so no encoding */
      if (EOF == fputc(Val, File)) {
	return 1;
      }
    } else {
      if (EOF == fputc(0xC0 | RunLength, File)) {
	return 1;
      }
      if (EOF == fputc(Val, File)) {
	return 1;
      }
    }
  }

  return 0;
}

/*
Function: EncodePCXLine
 Description:
	Takes a line of byte data and run-length encodes it in PCX
	  format.  This routine has been adapted from the ZSoft PCX
	  documentation.  The routine returns a non-zero value in
	  the event of an error (typically disk full).
*/
static int EncodePCXLine ( UInt8 *LineBuffer,
			   unsigned Length,
			   FILE *File,
			   UInt8 depth, UInt16 mask, UInt8 shift, UInt8 scale )
{
	int OldVal;
	int NewVal;
	int Count;
	unsigned LengthCounter;
	UInt16 *LineBuffer16 = (UInt16*) LineBuffer;
	
	/* start us off */
	if ( depth == 8 ) {
	  OldVal = *LineBuffer++;
	} else {
	  OldVal = *LineBuffer16++;
	  OldVal = ByteSwap16 ( OldVal );
	  OldVal >>= shift;
	  OldVal &= mask;
	  OldVal <<= scale;
	}

	LengthCounter = 1;
	Count = 1;
	
	while (LengthCounter < Length) {

	  if ( depth == 8 ) {
	    NewVal = *LineBuffer++;
	  } else {
	    NewVal = *LineBuffer16++;
	    NewVal = ByteSwap16 ( NewVal );
	    NewVal >>= shift;
	    NewVal &= mask;
	    NewVal <<= scale;
	  }

		if (NewVal == OldVal) {
			/* we've found a run */
			Count++;
			if (Count == 63) {
				/* this run is at least 63 long, so save off what we */
				/* have so far */
				if (EncodeRun(OldVal, Count, File)) {
					return 1; /* error */
				}
				Count = 0;
			}
		} else {
			/* no run */
			if (Count) {
				/* save off the run we were working on */
				if (EncodeRun(OldVal, Count, File)) {
					return 1;
				}
			}
			OldVal = NewVal;
			Count = 1;
		}
		LengthCounter++;
	}
	
	/* save off last run */
	if (Count) {
		if (EncodeRun(OldVal, Count, File)) {
			return 1;
		}
	}
	
	return 0;
}


/* Take a linear bitmap and a palette as input and saves the
 * linear bitmap as a PCX file with the specified name.
 * The bitmap will be saved as a version 5 format PCX file with
 * a palette.
*/
int SavePCX ( char *Filename, UInt8 *Image,
	      UInt32 Width, UInt32 Height, UInt8 *Palette,
	      UInt8 bpp16 )
{
  PCX_HEADER PCXHeader;
  void *File;
  int ColorIndex;
  int i;
  UInt32 Result;
  unsigned LineCounter;
  UInt8  * Data;
  int PalData;
	
  //RASSERT(Filename != NULL);
  //RASSERT(Image != NULL);
  //RASSERT(Palette != NULL);
	
  /* fill in PCX header */
  PCXHeader.Manufacturer 	= 10;
  PCXHeader.Version		= 5;
  PCXHeader.Encoding		= 1;
  PCXHeader.BitsPerPixel	= 8;
  PCXHeader.XMin		= 0;
  PCXHeader.YMin		= 0;
  PCXHeader.XMax		= ByteSwap16 ( Width - 1 );
  PCXHeader.YMax		= ByteSwap16 ( Height - 1 );
  PCXHeader.HDpi          	= ByteSwap16 ( Width + 1 );
  PCXHeader.VDpi		= ByteSwap16 ( Height + 1 );
  PCXHeader.Reserved		= 0;
  if ( bpp16 ) {
    PCXHeader.NPlanes		= 3;
  } else {
    PCXHeader.NPlanes		= 1; 
  }
  PCXHeader.BytesPerLine	= ByteSwap16 ( (Width + 1) & 0xFFFE ); /* make even */
  PCXHeader.PaletteInfo	= ByteSwap16 ( 1 );
  PCXHeader.HScreenSize	= ByteSwap16 ( Width );
  PCXHeader.VScreenSize	= ByteSwap16 ( Height );

  /* our palette is bigger */
  if ( bpp16 ) {
    // 16bpp -- no palette stored
  } else {
    // 8bpp palette
    for (ColorIndex = 0; ColorIndex < 16; ColorIndex++) {
      PCXHeader.ColorMap[ColorIndex][0] = Palette[ColorIndex*3+0];
      PCXHeader.ColorMap[ColorIndex][1] = Palette[ColorIndex*3+1];
      PCXHeader.ColorMap[ColorIndex][2] = Palette[ColorIndex*3+2];
    }
  }

  for (i = 0; i < sizeof(PCXHeader.Pad); i++) {
    PCXHeader.Pad[i] = 0;
  }
	
  /* open file */
  File = fopen ( Filename, "wb" );
  if (File == NULL) {
    DEBUGS ( "Couldn't create PCX file" );
    //SndPlaySystemSound ( sndError );
    return 1; /* error */
  }
	
  /* write header to file */
  Result = (UInt32) fwrite ( (char*) &PCXHeader, sizeof ( PCX_HEADER ),
			     1, File );
  if ( Result != 1 ) {
    /* write error */
    fclose ( File );
    DEBUGS ( "Couldn't write PCX header" );
    //SndPlaySystemSound ( sndError );
    return 1;
  }
	
  /* encode data */
  Data = Image;
  for ( LineCounter = 0; LineCounter < Height; LineCounter++ ) {

    if ( bpp16 ) {

      /* in 16bpp mode, encode a red line, then a green line, then
       * a blue line
       */
      // RGB == R5 G6 B5
      // c = ( r << 11 ) | ( g << 5 ) | b;

      /* --- RED --- */
      /* encode the line itself */
      if ( EncodePCXLine ( Data, Width, File, 16, 0x1F, 11, 3 ) ) {
	fclose ( File );
	DEBUGS ( "Couldn't encode PCX line" );
	//SndPlaySystemSound ( sndError );
	return 1; /* file write error */
      }
      /* handle odd width since BytesPerLine must be even */
      if ( Width & 1 ) {
	if ( fputc ( 0, File ) != 0 ) {
	  fclose ( File );
	  DEBUGS ( "Couldn't end PCX odd line" );
	  //SndPlaySystemSound ( sndError );
	  return 1; /* file write error */
	}
      }

      /* --- GREEN --- */
      /* encode the line itself */
      if ( EncodePCXLine ( Data, Width, File, 16, 0x3F, 5, 2 ) ) {
	fclose ( File );
	DEBUGS ( "Couldn't encode PCX line" );
	//SndPlaySystemSound ( sndError );
	return 1; /* file write error */
      }
      /* handle odd width since BytesPerLine must be even */
      if ( Width & 1 ) {
	if ( fputc ( 0, File ) != 0 ) {
	  fclose ( File );
	  DEBUGS ( "Couldn't end PCX odd line" );
	  //SndPlaySystemSound ( sndError );
	  return 1; /* file write error */
	}
      }

      /* --- BLUE --- */
      /* encode the line itself */
      if ( EncodePCXLine ( Data, Width, File, 16, (UInt16) 0x001F, 0, 3 ) ) {
	fclose ( File );
	DEBUGS ( "Couldn't encode PCX line" );
	//SndPlaySystemSound ( sndError );
	return 1; /* file write error */
      }
      /* handle odd width since BytesPerLine must be even */
      if ( Width & 1 ) {
	if ( fputc ( 0, File ) != 0 ) {
	  fclose ( File );
	  DEBUGS ( "Couldn't end PCX odd line" );
	  //SndPlaySystemSound ( sndError );
	  return 1; /* file write error */
	}
      }

      Data += ( Width * 2 );

    } else {

      /* in 8bpp mode, just encode each line
       */

      /* encode the line itself */
      if ( EncodePCXLine ( Data, Width, File, 8, 0, 0, 0 ) ) {
	fclose ( File );
	DEBUGS ( "Couldn't encode PCX line" );
	//SndPlaySystemSound ( sndError );
	return 1; /* file write error */
      }
      /* handle odd width since BytesPerLine must be even */
      if ( Width & 1 ) {
	if ( fputc ( 0, File ) != 0 ) {
	  fclose ( File );
	  DEBUGS ( "Couldn't end PCX odd line" );
	  //SndPlaySystemSound ( sndError );
	  return 1; /* file write error */
	}
      }

      Data += Width;

    } // bpp16?

  } // for each line
	
  if ( bpp16 ) {
    /* no palette stored for 16bpp mode */
  } else {

    /* write palette
     */
    fputc ( 12, File );	/* palette marker */
    for (ColorIndex = 0; ColorIndex < 256; ColorIndex++) {
      PalData = Palette[ColorIndex*3+0];
      Result = fputc(PalData, File);
      if (Result != PalData) {
	fclose ( File );
	DEBUGS ( "Couldn't write PCX palette 1" );
	//SndPlaySystemSound ( sndError );
	return 1; /* write error */
      }
      PalData = Palette[ColorIndex*3+1];
      Result = fputc(PalData, File);
      if (Result != PalData) {
	fclose ( File );
	DEBUGS ( "Couldn't write PCX palette 2" );
	//SndPlaySystemSound ( sndError );
	return 1; /* write error */
      }
      PalData = Palette[ColorIndex*3+2];
      Result = fputc(PalData, File);
      if (Result != PalData) {
	fclose ( File );
	DEBUGS ( "Couldn't write PCX palette 3" );
	//SndPlaySystemSound ( sndError );
	return 1; /* write error */
      }
    }

  } // bpp16 palette store?

  /* close and exit */
  fclose ( File );
  return 0;
}

/*
 * --[ read ]-----------------------------------------------------------------
 */

static int PcxRead ( UInt8 *ptr, int n ) {
  int cnt = n;
  if ( PcxFileOff + (n) > PcxFileLen ) {
    //DEBUGS ( "bad pcxread offset %d", n );
    return -1;
  }
	
  // could use memcpy() here, but who cares.
  while (cnt--) {
    *ptr++ = PcxFileBuf [ PcxFileOff++ ];
  }

  return ( n );
}

static int PcxSeek ( int n, int where ) {
  int NewPos;

  switch (where) {
  case SEEK_SET: NewPos = n; break;
  case SEEK_CUR: NewPos = PcxFileOff + n; break;
  case SEEK_END: NewPos = PcxFileLen + n; break;
  }

  if (NewPos < 0) NewPos = 0;

  if (NewPos > PcxFileLen) NewPos = PcxFileLen;

  // printf("Seek %d: to %d (newpos = %d, len = %d)\n", where, n, NewPos, PcxFileLen);
  PcxFileOff = NewPos;

  return PcxFileOff;
}

/*
	Function: DecodePCXLine
    Description:
    	A module local function that decodes a lines-worth of data
        from a PCX file.
*/
static int DecodePCXLine ( UInt8 * LineBuffer, unsigned TotalBytes ) {
  unsigned Position;
  int Count;
  UInt8 Color;
  UInt8 RawData;
  int i;
	
  Position = 0;
	
  while ( Position < TotalBytes ) {

    //DEBUGU32 ( Position );

    if ( PcxRead ( &RawData, 1 ) != 1 ) {
      //DEBUGS ( "failed PCX Read" );
      //DEBUGU8 ( PcxFileOff );
      //DEBUGU8 ( PcxFileLen );
      return ( -1 );
    }
		
    if ( ( RawData & 0xC0 ) == 0xC0 ) {
      Count = RawData & 0x3F;
      if ( PcxRead ( &Color, 1 ) != 1) {
	//DEBUGS ( "failed PCX Read colour" );
	return ( -1 );
      }
    } else {
      Count = 1;
      Color = RawData;
    }
		
    for (i = 0; i < Count; i++) {
      LineBuffer[Position++] = Color;
    }

  }
	
  return 0;
}

/*
Function: LoadPCX
 Description:
	Loads a PCX file into memory and converts it to PbImage
	  format.  The palette data for the PCX file is ignored.
*/
UInt8 *LoadPCX ( char *FileName, UInt8 *Palette,
		 UInt32 *XSize, UInt32 *YSize )
{
  UInt8 *p;
  UInt8 *buf;
  FILE *File;
  UInt32 size;
  UInt32 i;

  // printf("Reading pcx %s..\n",FileName); fflush(stdout);
  // RASSERT(FileName != NULL);
	
  /* read in header */
  if ( ! ( File = fopen ( FileName, READMODE ) ) ) {
    //SndPlaySystemSound ( sndError );
    DEBUGS ( "Can't fopen() pcx" );
    return ( NULL );
  }

  fseek ( File, 0, SEEK_END );
  size = ftell ( File );
  fseek ( File, 0, SEEK_SET );

  // fetch file
  buf = MemGluePtrNewL ( size );

  //zotlog ( "size %ld\n", size );

  if ( ! buf ) {
    DEBUGS ( "Couldn't alloc in pcx" );
    return ( NULL );
  }

  //MemSet ( buf, size, '\0' );

  PcxFileLen = size;
  PcxFileOff = 0;
  PcxFileBuf = buf;

  //DEBUGU8 ( PcxFileLen );

  i = fread ( (char*) buf, 1, size, File );
  if ( i < size ) {
    DEBUGS ( "pcx fread" );
#ifdef ZOTSDL
    if ( ferror ( File ) ) { 
      DEBUGS ( "ferror" );
    }
    if ( feof ( File ) ) {
      DEBUGS ( "feof" );
    }
    DEBUGS ( "Got" );
    DEBUGU8 ( i );
    DEBUGS ( "Of" );
    DEBUGU8 ( size );
    DEBUGS ( "errno" );
    //DEBUGU8 ( errno );
    DEBUGS ( strerror ( errno ) );
#endif
  }

  p = _LoadPCX ( buf, Palette, XSize, YSize, NULL );

  fclose ( File );
  //PcxCloseFile();

  return ( p );
}

UInt8 *_LoadPCX ( UInt8 *buf, UInt8 *Palette, UInt32 *XSize, UInt32 *YSize,
		  UInt8 *Blk )
{
  UInt8 * LineBuffer;
  UInt8 * LinearDataPointer;
  UInt16 * LinearDataPointer16;
  PCX_HEADER PCXHeader;
  UInt16 LineCounter;
  UInt16 WidthCounter;
  int Result;
  UInt16 TotalBytes;
  int ColorIndex;
	
  // printf("Reading header ..\n"); fflush(stdout);
  /* read in header */
  Result = PcxRead( (UInt8*)&PCXHeader, sizeof(PCXHeader) );
  if ( Result != sizeof ( PCXHeader ) ) {
    DEBUGS ( "PCX Read Result fail" );
    return ( NULL );
  }
  // endian swap header..

  //DEBUGU32 ( *((UInt32*)(&PCXHeader)) );

#ifdef SF_LITTLEENDIAN
  // no swap needed
#else
  PCXHeader.XMin = ByteSwap16(PCXHeader.XMin);
  PCXHeader.YMin = ByteSwap16(PCXHeader.YMin);
  PCXHeader.XMax = ByteSwap16(PCXHeader.XMax);
  PCXHeader.YMax = ByteSwap16(PCXHeader.YMax);
  PCXHeader.HDpi = ByteSwap16(PCXHeader.HDpi);
  PCXHeader.VDpi = ByteSwap16(PCXHeader.VDpi);
  PCXHeader.BytesPerLine = ByteSwap16(PCXHeader.BytesPerLine);
  PCXHeader.PaletteInfo = ByteSwap16(PCXHeader.PaletteInfo);
  PCXHeader.HScreenSize = ByteSwap16(PCXHeader.HScreenSize);
  PCXHeader.VScreenSize = ByteSwap16(PCXHeader.VScreenSize);
#endif

  /* compute size of image and scanline size */
  *XSize = PCXHeader.XMax - PCXHeader.XMin + 1;
  *YSize = PCXHeader.YMax - PCXHeader.YMin + 1;
  TotalBytes = PCXHeader.NPlanes * PCXHeader.BytesPerLine;

  // dump
  //DEBUGU8 ( PCXHeader.HScreenSize );
  //DEBUGU8 ( PCXHeader.VScreenSize );
  //DEBUGU8 ( PCXHeader.NPlanes );
  //DEBUGU8 ( PCXHeader.XMax );
  //DEBUGU8 ( PCXHeader.YMax );
  //DEBUGU8 ( PCXHeader.BytesPerLine );
  //DEBUGS ( "--" );
	
  // printf("xsize= %d, ysize= %d, (total bytes = %d)\n", *XSize, *YSize, TotalBytes); fflush(stdout);
  /* allocate scanline buffer */

  LineBuffer = (UInt8 *) MemGluePtrNewL ( TotalBytes );

  if ( LineBuffer == NULL ) {
    DEBUGS ( "PCX linebuffer NULL" );
    return NULL;
  }

  // if you pass in Blk, it !damn! well better be the right size ..
  if (Blk == NULL) {
    // printf("linear buffer... (%d bytes)\n", *XSize * *YSize - 1); fflush(stdout);
    /* allocate and fill in PbImage data structure */

    if ( PCXHeader.NPlanes == 3 ) {
      Blk = (UInt8*) MemGluePtrNewL ( *XSize * *YSize * 2 );
    } else {
      Blk = (UInt8*) MemGluePtrNewL ( *XSize * *YSize );
    }

    if ( Blk == NULL ) {
      MemPtrFree ( LineBuffer );
      DEBUGS ( "PCX Blk NULL" );
      return ( NULL );
    }
  }

  /* decode data */
  LinearDataPointer = Blk;
  LinearDataPointer16 = (UInt16*) Blk;
	
  if ( PCXHeader.NPlanes == 3 ) {

    for ( LineCounter = 0; LineCounter < *YSize; LineCounter++ ) {

#if 0
      {
	UInt16 x;
	for ( x = 0; x < *XSize; x++ ) {
	  LinearDataPointer16 [ x ] = 0;
	}
      }

      LinearDataPointer16 [ 5 ] = 37;
      LinearDataPointer16 [ 6 ] = 37;
      LinearDataPointer16 [ 7 ] = 37;

      LinearDataPointer16 [ 9 ] = 37;
      LinearDataPointer16 [ 10 ] = 37;
      LinearDataPointer16 [ 11 ] = 37;
#endif

#if 1
      /* --RED-- */

      // decode into linebuffer
      Result = DecodePCXLine ( LineBuffer, TotalBytes );

      if (Result != 0) {
	MemPtrFree ( LineBuffer );
	MemPtrFree ( Blk ); 
	return NULL;
      }
		
      // copy line into screen buffer
      for (WidthCounter = 0; WidthCounter < *XSize; WidthCounter++) {
 	LinearDataPointer16 [ WidthCounter ] =
	  ((UInt16)(LineBuffer [ PCXHeader.XMin + WidthCounter ])) << 11;
      }

      /* --GREEN-- */

      // decode into linebuffer
      Result = DecodePCXLine ( LineBuffer, TotalBytes );

      if (Result != 0) {
	MemPtrFree ( LineBuffer );
	MemPtrFree ( Blk ); 
	return NULL;
      }
		
      // copy line into screen buffer
      for (WidthCounter = 0; WidthCounter < *XSize; WidthCounter++) {
	LinearDataPointer16 [ WidthCounter ] |=
	  ((UInt16)(LineBuffer [ PCXHeader.XMin + WidthCounter ])) << 5;
      }

      /* --BLUE-- */

      // decode into linebuffer
      Result = DecodePCXLine ( LineBuffer, TotalBytes );

      if (Result != 0) {
	MemPtrFree ( LineBuffer );
	MemPtrFree ( Blk ); 
	return NULL;
      }
		
      // copy line into screen buffer
      for (WidthCounter = 0; WidthCounter < *XSize; WidthCounter++) {
	LinearDataPointer16 [ WidthCounter ] |=
	  ((UInt16)(LineBuffer [ PCXHeader.XMin + WidthCounter ]));

	// done, so correct for endianness
	LinearDataPointer16 [ WidthCounter ] =
	  ByteSwap16 ( LinearDataPointer16 [ WidthCounter ] );
      }

#endif

      /* --DONE-- */
      LinearDataPointer16 += PCXHeader.HScreenSize;

    } // for

  } else {

    /* 8bpp mode */

    for ( LineCounter = 0; LineCounter < *YSize; LineCounter++ ) {

      //DEBUGU8 ( LineCounter );

      // decode into linebuffer
      Result = DecodePCXLine ( LineBuffer, TotalBytes );

      if (Result != 0) {
	MemPtrFree ( LineBuffer );
	MemPtrFree ( Blk ); 
	DEBUGS ( "Couldn't decode line" );
	//DEBUGU32 ( TotalBytes );
	return ( NULL );
      }
		
      // copy line into screen buffer
      for (WidthCounter = 0; WidthCounter < *XSize; WidthCounter++) {
	LinearDataPointer [ WidthCounter ] =
	  LineBuffer[PCXHeader.XMin + WidthCounter];
      }

      LinearDataPointer += *XSize;

    } // for

  } // bpp16?
	
  // printf("free line buffer...\n"); fflush(stdout);
  MemPtrFree ( LineBuffer );
	
  /* if the caller doesn't want palette information, just return */
  if (Palette == NULL) {
    // printf("no palette, done...\n"); fflush(stdout);
    return Blk;
  }
	
  // printf("find palette ...\n"); fflush(stdout);
  /* get the palette */
  if (PCXHeader.Version != 5) {

    //DEBUGS ( "Palette = 16 colours" );

    /* if the PCX file doesn't support the 256-color palette */
    /* use the 16-color palette instead */
    for (ColorIndex = 0; ColorIndex < 16; ColorIndex++) {
      Palette[ColorIndex*3+0] = PCXHeader.ColorMap[ColorIndex][0];
      Palette[ColorIndex*3+1] = PCXHeader.ColorMap[ColorIndex][1];
      Palette[ColorIndex*3+2] = PCXHeader.ColorMap[ColorIndex][2];
    }
    for (ColorIndex = 16; ColorIndex < 256; ColorIndex++) {
      Palette[ColorIndex*3+0] = 0;
      Palette[ColorIndex*3+1] = 0;
      Palette[ColorIndex*3+2] = 0;
    }

  } else {
    char by;

    PcxSeek(-((256 * 3) + 1), SEEK_END);

    PcxRead ( (UInt8*) &by, 1);
    Result = (int) by;

    if (Result != 12) {
      /* this doesn't have a 256-color palette, */
      /* so use the 16-color one */
      for (ColorIndex = 0; ColorIndex < 16; ColorIndex++) {
	//DEBUGS ( "Palette = 16 colours" );
	/* copy entries and divide by four since PCX colors */
	/* can range from 0 to 255 and VGA colors can only */
	/* go as high as 63 */
	Palette[ColorIndex*3+0] = PCXHeader.ColorMap[ColorIndex][0];
	Palette[ColorIndex*3+1] = PCXHeader.ColorMap[ColorIndex][1];
	Palette[ColorIndex*3+2] = PCXHeader.ColorMap[ColorIndex][2];
      }
      for (ColorIndex = 16; ColorIndex < 256; ColorIndex++) {
	Palette[ColorIndex*3+0] = 0;
	Palette[ColorIndex*3+1] = 0;
	Palette[ColorIndex*3+2] = 0;
      }
    } else {
      //DEBUGS ( "Palette = 256 colours" );
      /* read in the palette in one chunk */
      if ( PcxRead ( Palette, sizeof(UInt8) * 256 * 3) != sizeof(UInt8)*256*3) {
	DEBUGS ( "Bad palette!" );
	MemPtrFree ( Blk );
	return NULL;
      }
    }
  }
	
  return Blk;
}

UInt8 *pcx_load_from_buffer ( UInt8 *buf, UInt32 len,
			      UInt8 *Palette,
			      UInt32 *XSize, UInt32 *YSize )
{
  PcxFileLen = len;
  PcxFileOff = 0;
  PcxFileBuf = buf;

  return ( _LoadPCX ( buf, Palette, XSize, YSize, NULL ) );
}

#ifndef ZOTSDL
UInt8 *pcx_load_from_resource ( UInt32 type, UInt32 num, UInt8 *Palette,
				UInt32 *XSize, UInt32 *YSize )
{
  UInt8 *picbits;
  MemHandle pich;
  UInt8 *pic;

  //WinSetCoordinateSystem ( kCoordinatesDouble );

  pich = DmGetResource ( type, num );

  if ( ! pich ) {
    DEBUGS ( "Couldn't get rsrc" );
    return ( NULL );
  }

  picbits = MemHandleLock ( pich );

  if ( ! picbits ) {
    DEBUGS ( "Couldn't lock" );
    return ( NULL );
  }

  pic = pcx_load_from_buffer ( picbits, MemHandleSize ( pich ),
			       Palette, XSize, YSize );

  if ( ! pic ) {
    DEBUGS ( "Couldn't get pic bits!" );
    return ( NULL );
  }

  return ( pic );
}
#endif
