/**************************************************************************
 PCXVIEW - by Lee Hamel (Patch), hamell@cx.pdx.edu, *Avalanche* coder
 July 14th, 1993
**************************************************************************/

#include <stdio.h>

typedef struct {
		char    manufacturer;
		char    version;
		char    encoding;
		char    bits_per_pixel;
		int     xmin,ymin;
		int     xmax,ymax;
		int     hres;
		int     vres;
		char    palette[48];
		char    reserved;
		char    colour_planes;
		int     bytes_per_line;
		int     palette_type;
		char    filler[58];
	       } PCXHEAD;

PCXHEAD header;
unsigned int width,depth;
unsigned int bytes;
unsigned char palette[768];
FILE *fp;

void Read_PCX_Line(unsigned int vidoffset)
{
  unsigned char c, run;
  unsigned int n = 0;

  _asm
  {
    cld
    mov         di,[vidoffset]
  }

  do
  {
    c = fgetc(fp) & 0xff;
    /* if it's a run of bytes field */
    if ((c & 0xc0) == 0xc0)
    {
      /* and off the high bits */
      run = c & 0x3f;
      /* get the run byte */
      c = fgetc(fp);
      /* run the byte */
      n += run;
      _asm
      {
	mov     ax,0a000h
	mov     es,ax
	mov     al,[c]
	xor     ch,ch
	mov     cl,[run]
	rep     stosb
      }
    }
    else
    {
      n++;
      _asm
      {
	mov     ax,0a000h
	mov     es,ax
	mov     al,[c]
	stosb
      }
    }
  }
  while (n < bytes);
}

void Unpack_PCX_File(void)
{
  int i;

  for (i = 0; i < 768; i++)
    palette[i] = palette[i] >> 2;

  _asm {        mov     ax,0013h
		int     10h
		mov     ax,1012h
		xor     bx,bx
		mov     cx,256
		mov     dx,offset palette
		int     10h
       }

  /*
  _asm {
	 cld
	 mov    ax,0a000h
	 mov    es,ax
	 xor    di,di
	 xor    al,al
	 mov    ah,200

	 banger:        mov     cx,320
			rep     stosb
			inc     al
			dec     ah
			jnz     banger
       }
 */

  for (i = 0; i < depth; i++)
    Read_PCX_Line(i * 320);

  _asm {        xor     ax,ax
		int     16h
		mov     ax,0003h
		int     10h
       }
}

void main(int argc, char *argv[])
{
  if (argc > 1)
  {
    if ((fp = fopen(argv[1],"rb")) != NULL)
    {
      if (fread((char *)&header,1,sizeof(PCXHEAD),fp) == sizeof(PCXHEAD))
      {
	if (header.manufacturer == 0x0a && header.version == 5)
	{
	  if (!fseek(fp,-769L,SEEK_END))
	  {
	    if (fgetc(fp) == 0x0c && fread(palette,1,768,fp) == 768)
	    {
	      fseek(fp,128L,SEEK_SET);
	      width = header.xmax - header.xmin + 1;
	      depth = header.ymax - header.ymin + 1;
	      bytes = header.bytes_per_line;
	      /*
	      printf("Width = %d\n",width);
	      printf("Depth = %d\n",depth);
	      printf("Bytes = %d\n",bytes);
	      */
	      Unpack_PCX_File();
	    }
	    else printf("Error reading palette\n");
	  }
	  else printf("Error seeking to palette\n");
	}
	else printf("Not a 256 color PCX file\n");
      }
      else printf("Error reading %s\n",argv[1]);
      fclose(fp);
    }
    else printf("Error opening %s\n",argv[1]);
  }
}
