Article 5945 of alt.sources:
Path: jac.zko.dec.com!crl.dec.com!crl.dec.com!bloom-beacon.mit.edu!uhog.mit.edu!news.mathworks.com!europa.chnt.gtegsc.com!news.sprintlink.net!news.clark.net!rahul.net!a2i!flash.us.com!flash.us.com!not-for-mail
From: dclunie@flash.us.com
Newsgroups: alt.sources
Subject: PATCH: XV-3.10 reads PhotoCD
Followup-To: alt.graphics.pixutils
Date: 16 Jun 1995 01:24:39 +0300
Organization: Her Master's Voice
Lines: 1808
Message-ID: <3rqbv7$aff@flash.ksapax>
Reply-To: dclunie@flash.us.com
NNTP-Posting-Host: flash.ksapax

Patch-name: xv-3.10-magpic2pcd.patchnew

Patch to xv-3.10 to allow PhotoCD images to be imported.

Released 15 Jun 1995, dclunie@flash.us.com.

Replaces earlier similar patches including:

	- xv-3.00-pcd.patch
	- xv-3.00-pcd.patchnew
	- xv-3.10a-pcd.patch

none of which should be applied.

NB. If you have previously applied the magic pic patch from
Japan (Patch.magpic2.PhotoCD.XV310a) then you must use an
alternative version of this patch to include the additional
capabilities and avoid messing with the magic pic stuff. That
patch is called xv-310-magpic2pcd.patchnew, and accompanies
this one.

To apply this patch:

	% cd xv-3.10
	% patch -p1 <../xv-3.10-pcd.patchnew

diff -c -r xv-3.10/Imakefile xv-3.10pcd/Imakefile
*** xv-3.10/Imakefile	Thu Dec 22 22:12:21 1994
--- xv-3.10pcd/Imakefile	Thu Jun 15 19:44:57 1995
***************
*** 133,139 ****
  PDS = -DDOPDS
  #endif
  
- 
  #if defined(SCOArchitecture)
  SCO= -Dsco -DPOSIX -DNO_RANDOM 
  SYS_LIBRARIES=        -lm -lc -lx 
--- 133,138 ----
***************
*** 157,163 ****
  	xvdial.c xvgraf.c xvsunras.c xvjpeg.c xvps.c xvpopup.c xvdflt.c \
  	xvtiff.c xvtiffwr.c xvpds.c xvrle.c xviris.c xvgrab.c vprintf.c \
  	xvbrowse.c xvtext.c xvpcx.c xviff.c xvtarga.c xvxpm.c xvcut.c \
! 	xvxwd.c xvfits.c
  
  OBJS1 =	xv.o xvevent.o xvroot.o xvmisc.o xvimage.o xvcolor.o xvsmooth.o \
  	xv24to8.o xvgif.o xvpm.o xvinfo.o xvctrl.o xvscrl.o xvalg.o \
--- 156,162 ----
  	xvdial.c xvgraf.c xvsunras.c xvjpeg.c xvps.c xvpopup.c xvdflt.c \
  	xvtiff.c xvtiffwr.c xvpds.c xvrle.c xviris.c xvgrab.c vprintf.c \
  	xvbrowse.c xvtext.c xvpcx.c xviff.c xvtarga.c xvxpm.c xvcut.c \
! 	xvxwd.c xvfits.c xvpcd.c
  
  OBJS1 =	xv.o xvevent.o xvroot.o xvmisc.o xvimage.o xvcolor.o xvsmooth.o \
  	xv24to8.o xvgif.o xvpm.o xvinfo.o xvctrl.o xvscrl.o xvalg.o \
***************
*** 165,171 ****
  	xvdial.o xvgraf.o xvsunras.o xvjpeg.o xvps.o xvpopup.o xvdflt.o \
  	xvtiff.o xvtiffwr.o xvpds.o xvrle.o xviris.o xvgrab.o vprintf.o \
  	xvbrowse.o xvtext.o xvpcx.o xviff.o xvtarga.o xvxpm.o xvcut.o \
! 	xvxwd.o xvfits.o
  
  SRCS2=	bggen.c
  OBJS2=	bggen.o
--- 164,170 ----
  	xvdial.o xvgraf.o xvsunras.o xvjpeg.o xvps.o xvpopup.o xvdflt.o \
  	xvtiff.o xvtiffwr.o xvpds.o xvrle.o xviris.o xvgrab.o vprintf.o \
  	xvbrowse.o xvtext.o xvpcx.o xviff.o xvtarga.o xvxpm.o xvcut.o \
! 	xvxwd.o xvfits.o xvpcd.o
  
  SRCS2=	bggen.c
  OBJS2=	bggen.o
diff -c -r xv-3.10/Makefile xv-3.10pcd/Makefile
*** xv-3.10/Makefile	Thu Dec 22 22:47:29 1994
--- xv-3.10pcd/Makefile	Thu Jun 15 19:42:51 1995
***************
*** 30,37 ****
  ### Installation locations
  BINDIR = /usr/local/bin
  MANDIR = /usr/local/man/man1
! MANSUF = 1
  LIBDIR = /usr/local/lib
  
  
  buildit: all
--- 30,42 ----
  ### Installation locations
  BINDIR = /usr/local/bin
  MANDIR = /usr/local/man/man1
! MANSUFFIX = 1
  LIBDIR = /usr/local/lib
+ INSTALL = install
+ INSTPGMFLAGS = -s
+ INSTBINFLAGS = -m 0755
+ INSTLIBFLAGS = -m 0644
+ INSTMANFLAGS = -m 0444
  
  
  buildit: all
***************
*** 187,193 ****
  	xvdial.o xvgraf.o xvsunras.o xvjpeg.o xvps.o xvpopup.o xvdflt.o \
  	xvtiff.o xvtiffwr.o xvpds.o xvrle.o xviris.o xvgrab.o vprintf.o \
  	xvbrowse.o xvtext.o xvpcx.o xviff.o xvtarga.o xvxpm.o xvcut.o \
! 	xvxwd.o xvfits.o
  
  MISC = README INSTALL CHANGELOG IDEAS
  
--- 192,198 ----
  	xvdial.o xvgraf.o xvsunras.o xvjpeg.o xvps.o xvpopup.o xvdflt.o \
  	xvtiff.o xvtiffwr.o xvpds.o xvrle.o xviris.o xvgrab.o vprintf.o \
  	xvbrowse.o xvtext.o xvpcx.o xviff.o xvtarga.o xvxpm.o xvcut.o \
! 	xvxwd.o xvfits.o xvpcd.o
  
  MISC = README INSTALL CHANGELOG IDEAS
  
***************
*** 228,239 ****
  
  
  install: all
! 	cp xv bggen vdcomp xcmap xvpictoppm $(BINDIR)
! 	cp docs/xv.man     $(MANDIR)/xv.$(MANSUF)
! 	cp docs/bggen.man  $(MANDIR)/bggen.$(MANSUF)
! 	cp docs/xcmap.man  $(MANDIR)/xcmap.$(MANSUF)
! 	cp docs/xvp2p.man  $(MANDIR)/xvpictoppm.$(MANSUF)
! 	cp docs/xvdocs.ps* $(LIBDIR)
  
  tar:
  	tar cvf xv.tar Makefile* Imakefile *.c *.h bits \
--- 233,248 ----
  
  
  install: all
! 	$(INSTALL) -c $(INSTPGMFLAGS) $(INSTBINFLAGS)  xv $(BINDIR)
! 	$(INSTALL) -c $(INSTPGMFLAGS) $(INSTBINFLAGS)  bggen $(BINDIR)
! 	$(INSTALL) -c $(INSTPGMFLAGS) $(INSTBINFLAGS)  vdcomp $(BINDIR)
! 	$(INSTALL) -c $(INSTPGMFLAGS) $(INSTBINFLAGS)  xcmap $(BINDIR)
! 	$(INSTALL) -c $(INSTPGMFLAGS) $(INSTBINFLAGS)  xvpictoppm $(BINDIR)
! 	$(INSTALL) -c $(INSTMANFLAGS) docs/xv.man $(MANDIR)/xv.$(MANSUFFIX)
! 	$(INSTALL) -c $(INSTMANFLAGS) docs/bggen.man $(MANDIR)/bggen.$(MANSUFFIX)
! 	$(INSTALL) -c $(INSTMANFLAGS) docs/xcmap.man $(MANDIR)/xcmap.$(MANSUFFIX)
! 	$(INSTALL) -c $(INSTMANFLAGS) docs/xvp2p.man $(MANDIR)/xvpictoppm.$(MANSUFFIX)
! 	$(INSTALL) -c $(INSTLIBFLAGS) docs/xvdocs.ps $(LIBDIR)
  
  tar:
  	tar cvf xv.tar Makefile* Imakefile *.c *.h bits \
diff -c -r xv-3.10/Makefile.std xv-3.10pcd/Makefile.std
*** xv-3.10/Makefile.std	Thu Dec 22 22:12:21 1994
--- xv-3.10pcd/Makefile.std	Thu Jun 15 19:43:17 1995
***************
*** 30,37 ****
  ### Installation locations
  BINDIR = /usr/local/bin
  MANDIR = /usr/local/man/man1
! MANSUF = 1
  LIBDIR = /usr/local/lib
  
  
  buildit: all
--- 30,42 ----
  ### Installation locations
  BINDIR = /usr/local/bin
  MANDIR = /usr/local/man/man1
! MANSUFFIX = 1
  LIBDIR = /usr/local/lib
+ INSTALL = install
+ INSTPGMFLAGS = -s
+ INSTBINFLAGS = -m 0755
+ INSTLIBFLAGS = -m 0644
+ INSTMANFLAGS = -m 0444
  
  
  buildit: all
***************
*** 187,193 ****
  	xvdial.o xvgraf.o xvsunras.o xvjpeg.o xvps.o xvpopup.o xvdflt.o \
  	xvtiff.o xvtiffwr.o xvpds.o xvrle.o xviris.o xvgrab.o vprintf.o \
  	xvbrowse.o xvtext.o xvpcx.o xviff.o xvtarga.o xvxpm.o xvcut.o \
! 	xvxwd.o xvfits.o
  
  MISC = README INSTALL CHANGELOG IDEAS
  
--- 192,198 ----
  	xvdial.o xvgraf.o xvsunras.o xvjpeg.o xvps.o xvpopup.o xvdflt.o \
  	xvtiff.o xvtiffwr.o xvpds.o xvrle.o xviris.o xvgrab.o vprintf.o \
  	xvbrowse.o xvtext.o xvpcx.o xviff.o xvtarga.o xvxpm.o xvcut.o \
! 	xvxwd.o xvfits.o xvpcd.o
  
  MISC = README INSTALL CHANGELOG IDEAS
  
***************
*** 228,239 ****
  
  
  install: all
! 	cp xv bggen vdcomp xcmap xvpictoppm $(BINDIR)
! 	cp docs/xv.man     $(MANDIR)/xv.$(MANSUF)
! 	cp docs/bggen.man  $(MANDIR)/bggen.$(MANSUF)
! 	cp docs/xcmap.man  $(MANDIR)/xcmap.$(MANSUF)
! 	cp docs/xvp2p.man  $(MANDIR)/xvpictoppm.$(MANSUF)
! 	cp docs/xvdocs.ps* $(LIBDIR)
  
  tar:
  	tar cvf xv.tar Makefile* Imakefile *.c *.h bits \
--- 233,248 ----
  
  
  install: all
! 	$(INSTALL) -c $(INSTPGMFLAGS) $(INSTBINFLAGS)  xv $(BINDIR)
! 	$(INSTALL) -c $(INSTPGMFLAGS) $(INSTBINFLAGS)  bggen $(BINDIR)
! 	$(INSTALL) -c $(INSTPGMFLAGS) $(INSTBINFLAGS)  vdcomp $(BINDIR)
! 	$(INSTALL) -c $(INSTPGMFLAGS) $(INSTBINFLAGS)  xcmap $(BINDIR)
! 	$(INSTALL) -c $(INSTPGMFLAGS) $(INSTBINFLAGS)  xvpictoppm $(BINDIR)
! 	$(INSTALL) -c $(INSTMANFLAGS) docs/xv.man $(MANDIR)/xv.$(MANSUFFIX)
! 	$(INSTALL) -c $(INSTMANFLAGS) docs/bggen.man $(MANDIR)/bggen.$(MANSUFFIX)
! 	$(INSTALL) -c $(INSTMANFLAGS) docs/xcmap.man $(MANDIR)/xcmap.$(MANSUFFIX)
! 	$(INSTALL) -c $(INSTMANFLAGS) docs/xvp2p.man $(MANDIR)/xvpictoppm.$(MANSUFFIX)
! 	$(INSTALL) -c $(INSTLIBFLAGS) docs/xvdocs.ps $(LIBDIR)
  
  tar:
  	tar cvf xv.tar Makefile* Imakefile *.c *.h bits \
diff -c -r xv-3.10/README.pcd xv-3.10pcd/README.pcd
*** xv-3.10/README.pcd	Thu Jun 15 21:44:58 1995
--- xv-3.10pcd/README.pcd	Thu Jun 15 21:33:12 1995
***************
*** 0 ****
--- 1,128 ----
+ Copyright 1993,1994,1995 David Clunie, Riyadh, Saudi Arabia.
+ 
+ PCD patch for XV 3.10 Release Notes 15 June 95.
+ 
+ See also the progress notes at the end of this file.
+ 
+ These patches allow xv to read Kodak photocd files and choose which of the
+ 5 available resolutions one wants to view.
+ 
+ When a photocd file is loaded, a dialog box asks which resolution you
+ would like. The visual schnauzer builds thumbnails by reading the lowest
+ resolution image. The selected resolution can be selected from the
+ command line with the -pcd option:
+ 
+ 	[-pcd 0|1|2|3|4]
+ 
+ where:
+ 
+ 	0=192*128,	base/16 resolution
+ 	1=384*256,	base/4 resolution
+ 	2=768*512,	base resolution
+ 	3=1536*1024,	4base resolution
+ 	4=3072*2048	16base resolution.
+ 
+ Note that the Pro format is not supported, only because I don't have
+ a Pro disk to test ... if anyone wants to mail me one I will add
+ support.
+ 
+ The command line option allows loops without the dialog box popping up, eg.:
+ 
+ 	xv -pcd 1 -wloop -wait 10 *.pcd
+ 
+ The code is pretty crude and was written quickly for a specific purpose and
+ has not really been cleaned up. It is poorly structured, full of debugging
+ codes and verbose comments, and there is very little attempt at optimizing
+ things. No profiling has been done.
+ 
+ There is not yet support for overview files, nor is there a facility to
+ use the higher resolution chroma planes from when viewing lower resolution
+ images.
+ 
+ It's only claim to fame is that it works and produces reasonable looking
+ images.
+ 
+ The outline of this is shamelessly derived from xvpbm.c to read the
+ file, and xvtiffwr.c to handle the popup window and X stuff (X never
+ has been my forte !), and the PhotoCD format information (though not
+ the code) was found in Hadmut Danisch's (danisch@ira.uka.de) hpcdtoppm
+ program in which he has reverse engineered the format by studying
+ hex dumps of PhotoCDs ! After all who can afford the Kodak developer's
+ kit, which none of us have seen yet ? Am I even allowed to mention these
+ words (Kodak, PhotoCD) ? I presume they are registered trade marks.
+ 
+ PS. I have no idea how Halmut worked out the YCC <-> RGB conversion
+ factors, but I have calculated them from his tables and the results
+ look good enough to me. It is not perfect though, and any information
+ on correct way to do this would be appreciated.
+ 
+ Sooner or later I will get around to trying to read overview files, using
+ the higher resolution chroma maps (what Hadmut calls "overskip"), and get
+ the colour tables right !
+ 
+ Feel free to send me comments or improvements, or even better, more
+ information about the photo CD format ... hopefully someone who really
+ knows what they are doing will tidy it up or do a neater job.
+ 
+ david (dclunie@flash.us.com) (now living in sunny Saudi Arabia !)
+ 
+ ---------
+ 
+ The trace #define in xvpcd.c is now in the right place, and the ansi
+ prototype for the magnify function has been fixed. Colin made me switch to xvbcopy() which seems like a good idea for System V victims.
+ 
+ Still haven't fixed the colour tables. Supposedly they are a bit green. I
+ just bought a Mac so I thought I might run some photoCD images through
+ Adobe Photoshop and compare the colours with the xv patch. Stay tuned.
+ 
+ ---------
+ 
+ Date: Wed, 22 Dec 1993 16:09:52 --1000
+ From: colinc@fitmail.fit.qut.edu.au (Colin Canfield )
+ 
+ I have done some more work using your patch I thought you might be intested in.
+ The major change was adding a size parameter to the LoadPCD; either -1 to mean
+ the popup or else the size you desired. This allows batch mode processing,
+ specifically xv -pcd <size> <filename>, and the visual schnauzer can work in 
+ quick mode (ie. you don't have to select each image size when it is building 
+ the icons)
+ 
+ I have added an xbm file for the file type but haven't drawn an icon for it,
+ this is in bitmaps/br_pcd.xbm. I will just send you the new files.
+ 
+ ---------
+ 
+ From: andrew@andrew.triumf.ca (Andrew Daviel)
+ Date: 16 Feb 1995 23:32:21 GMT
+ 
+ This is David Clunie's patch for xv-3.00 tuned a bit to work
+ on xv-3.10. The code's all the same except for replacing 
+ "trace" with "fprintf" in xvpcd.c and adding an "unsigned" qualifier to 
+ keep my compiler (gcc) happy. Oh yes, changed RFT_PCD to 20 as
+ John Bradley has now used 15 through 19.
+ 
+ ---------
+ 
+ From: dclunie@flash.us.com (David A. Clunie)
+ Date: Thu Jun 15 14:43:46 GMT+0300 1995
+ 
+ Andrew's patch didn't include Colin's browser changes, so I redid the
+ xv-3.10 update from scratch ... it seems pretty much the same as
+ Andrew's changes. I also edited the Imakefile and Makefiles in order
+ to support the PCD changes, as well as make the install process a
+ little more flexible, with options to strip and set modes and so on.
+ Also made RFT_PCD 25 so as not to conflict with magpic patch from Japan
+ by Ikemoto Masahiro <ikeyan@airlab.cs.ritsumei.ac.jp>, and used his
+ bitmap icon for pcd files.
+ 
+ Now there are two versions of the patch, one which should be applied
+ to the xv-3.10 distribution.
+ 
+ The other should be applied to xv-3.10 AFTER Ikemoto Masahiro's 
+ Patch.magpic2.PhotoCD.XV319a, in order to add the browser features to
+ the latter, as well as fixing a Makefile typo (was xcpcd.c not xvpcd.c)
+ and including unistd.h for the SEEK_xxx constants in the magicpic
+ stuff.
+ 
+ 
+ 
Common subdirectories: xv-3.10/bits and xv-3.10pcd/bits
Common subdirectories: xv-3.10/docs and xv-3.10pcd/docs
Common subdirectories: xv-3.10/jpeg and xv-3.10pcd/jpeg
Common subdirectories: xv-3.10/tiff and xv-3.10pcd/tiff
Common subdirectories: xv-3.10/unsupt and xv-3.10pcd/unsupt
Common subdirectories: xv-3.10/vms and xv-3.10pcd/vms
diff -c -r xv-3.10/xv.c xv-3.10pcd/xv.c
*** xv-3.10/xv.c	Thu Dec 22 22:12:15 1994
--- xv-3.10pcd/xv.c	Thu Jun 15 19:46:07 1995
***************
*** 78,83 ****
--- 78,84 ----
  
  static int    force8     = 0;   /* force 8-bit mode */
  static int    force24    = 0;   /* force 24-bit mode */
+ static int    PcdSize    = -1;   /* force dialog to ask */
  
  /* used in DeleteCmd() and Quit() */
  static char  **mainargv;
***************
*** 277,282 ****
--- 278,285 ----
    tiffW = (Window) NULL;  tiffUp = 0;
  #endif
  
+   pcdW = (Window) NULL;  pcdUp = 0;
+ 
    imap = ctrlmap = gmap = browmap = cmtmap = 0;
  
    ch_offx = ch_offy = p_offx = p_offy = 0;
***************
*** 781,788 ****
    CreateTIFFW();
    XSetTransientForHint(theDisp, tiffW, dirW);
  #endif
    
-   
    LoadFishCursors();
    SetCursors(-1);
    
--- 784,794 ----
    CreateTIFFW();
    XSetTransientForHint(theDisp, tiffW, dirW);
  #endif
+ 
+   CreatePCDW();
+   XSetTransientForHint(theDisp, pcdW, dirW);
+ 
    
    LoadFishCursors();
    SetCursors(-1);
    
***************
*** 1360,1365 ****
--- 1366,1376 ----
      else if (!argcmp(argv[i],"-norm",      5,1,&autonorm));   /* norm */
      else if (!argcmp(argv[i],"-nostat",    4,1,&nostat));     /* nostat */
      else if (!argcmp(argv[i],"-owncmap",   2,1,&owncmap));    /* own cmap */
+     else if (!argcmp(argv[i],"-pcd",4,0,&pm))	/* pcd with size */
+  	{ if (i+1<argc) {
+  		PcdSize = atoi(argv[++i]); 
+  		}
+  	}
      else if (!argcmp(argv[i],"-perfect",   3,1,&perfect));    /* -perfect */
      else if (!argcmp(argv[i],"-poll",      3,1,&polling));    /* chk mod? */
  
***************
*** 1614,1619 ****
--- 1625,1631 ----
    printoption("[-/+norm]");
    printoption("[-/+nostat]");
    printoption("[-/+owncmap]");
+   printoption("[-pcd size(0=192*128,1=384*256,2=768*512,3=1536*1024,4=3072*2048)]");
    printoption("[-/+perfect]");
    printoption("[-/+poll]");
    printoption("[-preset #]");
***************
*** 2620,2625 ****
--- 2632,2640 ----
  	   strncmp((char *) magicno, "\004%!", (size_t) 3)==0)   rv = RFT_PS;
  #endif
  
+   else if (magicno[0]==0xff && magicno[1]==0xff &&
+            magicno[2]==0xff && magicno[3]==0xff) rv = RFT_PCD;
+ 
    return rv;
  }
  
***************
*** 2634,2640 ****
    /* if quick is set, we're being called to generate icons, or something
       like that.  We should load the image as quickly as possible.  Currently,
       this only affects the LoadPS routine, which, if quick is set, only
!      generates the page file for the first page of the document */
  
    int rv = 0;
  
--- 2649,2656 ----
    /* if quick is set, we're being called to generate icons, or something
       like that.  We should load the image as quickly as possible.  Currently,
       this only affects the LoadPS routine, which, if quick is set, only
!      generates the page file for the first page of the document .
! 	 Also now affects PCD which now only loads a thumbnail */
  
    int rv = 0;
  
***************
*** 2674,2679 ****
--- 2690,2705 ----
    case RFT_PS:      rv = LoadPS    (fname, pinfo, quick);    break;
  #endif
  
+   case RFT_PCD:      
+ 	if (quick == 1)
+ 		rv = LoadPCD(fname, pinfo, 0);  
+ 	else
+ 		rv = LoadPCD(fname, pinfo, PcdSize);  
+ 	break;
+ 
+ 	/* If quick is switched on use the smallest image size don't ask
+ 	*	the user.
+ 	*/
    }
    return rv;
  }
diff -c -r xv-3.10/xv.h xv-3.10pcd/xv.h
*** xv-3.10/xv.h	Thu Dec 22 22:12:15 1994
--- xv-3.10pcd/xv.h	Thu Jun 15 19:47:01 1995
***************
*** 8,15 ****
  #include "config.h"
  
  
! #define REVDATE   "Version 3.10  Rev: 12/16/94"
! #define VERSTR    "3.10"
  
  /*
   * uncomment the following, and modify for your site, but only if you've
--- 8,15 ----
  #include "config.h"
  
  
! #define REVDATE   "Version 3.10PCD  Rev: 15/Jun/95"
! #define VERSTR    "3.10PCD"
  
  /*
   * uncomment the following, and modify for your site, but only if you've
***************
*** 487,492 ****
--- 487,493 ----
  #define RFT_XPM      17
  #define RFT_XWD      18
  #define RFT_FITS     19
+ #define RFT_PCD      25
  
  /* definitions for page up/down, arrow up/down list control */
  #define LS_PAGEUP   0
***************
*** 1134,1140 ****
--- 1135,1145 ----
  WHERE int           tiffUp;       /* is tiffW mapped, or what? */
  #endif
  
+ /* stuff used for 'pcd' box */
+ WHERE Window        pcdW;
+ WHERE int           pcdUp;       /* is pcdW mapped, or what? */
  
+ 
  #undef WHERE
  
  
***************
*** 1604,1609 ****
--- 1609,1621 ----
  void  PSSaveParams         PARM((char *, int));
  void  PSResize             PARM((void));
  int   LoadPS               PARM((char *, PICINFO *, int));
+ 
+ /**************************** XVPCD.C ***************************/
+ int   LoadPCD              PARM((char *, PICINFO *, int));
+ void  CreatePCDW           PARM((void));
+ void  PCDDialog            PARM((int));
+ int   PCDCheckEvent        PARM((XEvent *));
+ void  PCDSetParamOptions   PARM((char *));
  
  /*************************** XVPOPUP.C ***************************/
  void  CenterMapWindow      PARM((Window, int, int, int, int));
diff -c -r xv-3.10/xvbrowse.c xv-3.10pcd/xvbrowse.c
*** xv-3.10/xvbrowse.c	Thu Dec 22 22:12:20 1994
--- xv-3.10pcd/xvbrowse.c	Thu Jun 15 19:39:13 1995
***************
*** 50,55 ****
--- 50,56 ----
  #include "bits/br_tiff"
  #include "bits/br_pds"
  #include "bits/br_ps"
+ #include "bits/br_pcd"
  #include "bits/br_iff"
  #include "bits/br_targa"
  #include "bits/br_xpm"
***************
*** 94,100 ****
  #define BF_XPM      25
  #define BF_XWD      26
  #define BF_FITS     27
! #define BF_MAX      28    /* # of built-in icons */
  
  #define ISLOADABLE(ftyp) (ftyp!=BF_DIR  && ftyp!=BF_CHR && ftyp!=BF_BLK && \
  			  ftyp!=BF_SOCK && ftyp!=BF_FIFO) 
--- 95,102 ----
  #define BF_XPM      25
  #define BF_XWD      26
  #define BF_FITS     27
! #define BF_PCD      28
! #define BF_MAX      29    /* # of built-in icons */
  
  #define ISLOADABLE(ftyp) (ftyp!=BF_DIR  && ftyp!=BF_CHR && ftyp!=BF_BLK && \
  			  ftyp!=BF_SOCK && ftyp!=BF_FIFO) 
***************
*** 524,531 ****
--- 526,535 ----
    bfIcons[BF_XPM] =MakePix1(br->win,br_xpm_bits, br_xpm_width, br_xpm_height);
    bfIcons[BF_XWD] =MakePix1(br->win,br_xwd_bits, br_xwd_width, br_xwd_height);
    bfIcons[BF_FITS]=MakePix1(br->win,br_fits_bits,br_fits_width,br_fits_height);
+   bfIcons[BF_PCD] =MakePix1(br->win,br_pcd_bits, br_pcd_width, br_pcd_height);
  
  
+ 
    /* check that they all got built */
    for (i=0; i<BF_MAX && bfIcons[i]; i++);
    if (i<BF_MAX) 
***************
*** 3020,3025 ****
--- 3024,3030 ----
      case RFT_XPM:      bf->ftype = BF_XPM;      break;
      case RFT_XWD:      bf->ftype = BF_XWD;      break;
      case RFT_FITS:     bf->ftype = BF_FITS;     break;
+     case RFT_PCD:      bf->ftype = BF_PCD;     break;
      }
    }
  }
***************
*** 3567,3572 ****
--- 3572,3578 ----
    case RFT_XPM:      strcat(str,"XPM file");              break;
    case RFT_XWD:      strcat(str,"XWD file");              break;
    case RFT_FITS:     strcat(str,"FITS file");             break;
+   case RFT_PCD:      strcat(str,"Photo CD file");         break;
    default:           strcat(str,"file of unknown type");  break;
    }
    
***************
*** 4747,4752 ****
--- 4753,4769 ----
      sprintf(src, "%s%s/bozo", dstp, THUMBDIR);
      DIRCreatedFile(src);
    }
+ 
+ 
+   if (!cpymode) {
+     /* clear all lit files in the source folder (as they've been moved)
+        note:  this won't be the optimal behavior if any files failed to
+        move, but screw it, that's not going to happen too often... */
+ 
+     for (i=0; i<srcBr->bfLen; i++) srcBr->bfList[i].lit = 0;
+     srcBr->numlit = 0;
+   }
+ 
  
  
    /* clear all files in the destination folder */
diff -c -r xv-3.10/xvevent.c xv-3.10pcd/xvevent.c
*** xv-3.10/xvevent.c	Thu Dec 22 22:12:17 1994
--- xv-3.10pcd/xvevent.c	Thu Jun 15 19:49:03 1995
***************
*** 155,160 ****
--- 155,161 ----
  {
    static int wasInfoUp=0, wasCtrlUp=0, wasDirUp=0, wasGamUp=0, wasPsUp=0;
    static int wasJpegUp=0, wasTiffUp=0;
+   static int wasPcdUp=0;
  
    static int mainWKludge=0;  /* force first mainW expose after a mainW config
  				to redraw all of mainW */
***************
*** 233,238 ****
--- 234,241 ----
      if (TIFFCheckEvent(event)) break;   /* event has been processed */
  #endif
  
+     if (PCDCheckEvent(event)) break;    /* event has been processed */
+ 
      if (GamCheckEvent (event)) break;   /* event has been processed */
      if (BrowseCheckEvent (event, &retval, &done)) break;   /* event eaten */
      if (TextCheckEvent   (event, &retval, &done)) break;   /* event eaten */
***************
*** 359,364 ****
--- 362,369 ----
        else if (client_event->window == tiffW) TIFFDialog(0);
  #endif
  
+      else if (client_event->window == pcdW) PCDDialog(0);
+ 
        else if (client_event->window == mainW) Quit(0);
      }
    }
***************
*** 538,543 ****
--- 543,550 ----
  #ifdef HAVE_TIFF
  	if (wasTiffUp) { TIFFDialog(wasTiffUp);  wasTiffUp=0; }
  #endif
+ 
+ 	if (wasPcdUp)  { PCDDialog(wasPcdUp);    wasPcdUp=0; }
        }
      }
    }
***************
*** 576,581 ****
--- 583,590 ----
  #ifdef HAVE_TIFF
  	  if (tiffUp) { wasTiffUp = tiffUp;  TIFFDialog(0); }
  #endif
+ 
+ 	  if (pcdUp) { wasPcdUp = pcdUp;  PCDDialog(0); }
  	}
        }
      }
***************
*** 1147,1152 ****
--- 1156,1163 ----
      if (TIFFCheckEvent(event)) break;
  #endif
      
+     if (PCDCheckEvent(event)) break;    /* event has been processed */
+ 
      if (GamCheckEvent (event)) break;
      if (BrowseCheckEvent (event, &retval, &done)) break;
      if (TextCheckEvent   (event, &retval, &done)) break;
***************
*** 1366,1371 ****
--- 1377,1384 ----
      if (TIFFCheckEvent(event)) break;
  #endif
  
+     if (PCDCheckEvent(event)) break;
+ 
      if (GamCheckEvent (event)) break;
      if (BrowseCheckEvent (event, &retval, &done)) break;
      if (TextCheckEvent   (event, &retval, &done)) break;
***************
*** 2369,2374 ****
--- 2382,2389 ----
  #ifdef HAVE_TIFF
    if (tiffUp) TIFFDialog(0);  /* close tiff window */
  #endif
+ 
+   if (pcdUp) PCDDialog(0);    /* close pcd window */
  
    ClosePopUp();
  
diff -c -r xv-3.10/xvmisc.c xv-3.10pcd/xvmisc.c
*** xv-3.10/xvmisc.c	Thu Dec 22 22:12:15 1994
--- xv-3.10pcd/xvmisc.c	Thu Jun 15 19:49:37 1995
***************
*** 520,525 ****
--- 520,527 ----
      if (tiffW) XDestroyWindow(theDisp, tiffW);
  #endif
  
+     if (pcdW) XDestroyWindow(theDisp, pcdW);
+ 
      /* if NOT using stdcmap for images, free stdcmap */
      if (colorMapMode != CM_STDCMAP) { 
        int j;
***************
*** 716,721 ****
--- 718,725 ----
  #ifdef HAVE_TIFF
    if (tiffW) XDefineCursor(theDisp, tiffW, otherc);
  #endif
+   
+   if (pcdW) XDefineCursor(theDisp, pcdW, otherc);
  }
  
  
diff -c -r xv-3.10/xvpcd.c xv-3.10pcd/xvpcd.c
*** xv-3.10/xvpcd.c	Thu Jun 15 21:44:28 1995
--- xv-3.10pcd/xvpcd.c	Thu Jun 15 19:50:05 1995
***************
*** 0 ****
--- 1,1026 ----
+ #define trace (void)
+ 
+ /*
+  * xvpcd.c - load routine for 'PhotoCD' format pictures
+  *
+  * LoadPCD(fname, pinfo, size)  -  loads a PhotoCD file
+  *
+  * This routine will popup a choice of which of the 5 available resolutions
+  * the user wants to choose, then load it as a 24 bit image.
+  *
+  * Copyright 1993 David Clunie, Melbourne, Australia.
+  *
+  * The outline of this is shamelessly derived from xvpbm.c to read the
+  * file, and xvtiffwr.c to handle the popup window and X stuff (X never
+  * has been my forte !), and the PhotoCD format information (though not
+  * the code) was found in Hadmut Danisch's (danisch@ira.uka.de) hpcdtoppm
+  * program in which he has reverse engineered the format by studying
+  * hex dumps of PhotoCDs ! After all who can afford the Kodak developer's
+  * kit, which none of us have seen yet ? Am I even allowed to mention these
+  * words (Kodak, PhotoCD) ? I presume they are registered trade marks.
+  *
+  * PS. I have no idea how Halmut worked out the YCC <-> RGB conversion
+  * factors, but I have calculated them from his tables and the results
+  * look good enough to me.
+  *
+  * Added size parameter to allow the schnautzer to create thumnails
+  * without requesting the size every time.
+  */
+ 
+ #include "xv.h"
+ #include <memory.h>
+ 
+ /* comments on error handling:
+    a truncated file is not considered a Major Error.  The file is loaded, the
+    rest of the pic is filled with 0's.
+ 
+    not being able to malloc is a Fatal Error.  The program is aborted. */
+ 
+ 
+ #ifdef __STDC__
+ static void magnify(int, int, int, int, int, unsigned char *);
+ static int pcdError(char *, char *);
+ static int gethuffdata(char *, char *, char *, int, int);
+ #else
+ static void magnify();
+ static int pcdError();
+ static int gethuffdata();
+ #endif
+ 
+ #define wcurfactor 16		/* Call WaitCursor() every n rows */
+ 
+ static char *bname;
+ 
+ static int size;                /* Set by window routines */
+ 
+ static int leaveitup;		/* Cleared by docmd() when OK or CANCEL pressed */
+ static int goforit;             /* Set to 1 if OK or 0 if CANCEL */
+ 
+ static FILE  *fp;
+ 
+ 
+ /*******************************************/
+ int LoadPCD(fname, pinfo,theSize)
+      char    *fname;
+      PICINFO *pinfo;
+ 	 int	theSize;
+ /* The size should be -1 for the popup to ask otherwise fast is assumed */
+ /*******************************************/
+ {
+   /* returns '1' on success */
+ 
+   int    c, c1;
+   int    rv;
+   long   offset;
+   int    mag;
+ 
+   byte *pic24, *luma, *chroma1, *chroma2, *ptr, *lptr, *c1ptr, *c2ptr;
+   int   w, h;
+   int   row, col;
+ 
+   int   huffplanes;
+ 
+   bname = BaseName(fname);
+ 
+   pinfo->pic     = (byte *) NULL;
+   pinfo->comment = (char *) NULL;
+ 
+ 
+   /* open the file */
+   fp=fopen(fname,"r");
+   if (!fp) return (pcdError(bname, "can't open file"));
+ 
+ /* base/16
+ 	- plain data starts at sector 1+2+1=4
+ 	  (numbered from 0, ie. the 5th sector)
+ 	- luma 192*128 = 24576 bytes (12 sectors)
+ 	  + chroma1 96*64 = 6144 bytes (3 sectors)
+ 	  + chroma2 96*64 = 6144 bytes (3 sectors)
+ 	  = total 18 sectors
+ 
+ 	- NB. "Plain" data is interleaved - 2 luma rows 192 wide,
+ 	  then 1 of each of the chroma rows 96 wide !
+ 
+    base/4
+ 	- plain data starts at sector 1+2+1+18+1=23
+ 	- luma 384*256 = 98304 bytes (48 sectors)
+ 	  + chroma1 192*128 = 24576 bytes (12 sectors)
+ 	  + chroma2 192*128 = 24576 bytes (12 sectors)
+ 	  = total 72 sectors
+ 
+ 	- NB. "Plain" data is interleaved - 2 luma rows 384 wide,
+ 	  then 1 of each of the chroma rows 192 wide !
+ 
+    base
+ 	- plain data starts at sector 1+2+1+18+1+72+1=96
+ 
+ 	- luma 768*512 = 393216 bytes (192 sectors)
+ 	  + chroma1 384*256 = 98304 bytes (48 sectors)
+ 	  + chroma2 384*256 = 98304 bytes (48 sectors)
+ 	  = total 288 sectors
+ 
+ 	- NB. "Plain" data is interleaved - 2 luma rows 768 wide,
+ 	  then 1 of each of the chroma rows 384 wide !
+ 
+    4base
+ 	- plain data for base is read
+ 	- luma data interpolated *2
+ 	- chroma data interpolated *4
+ 
+ 	- cd_offset is 1+2+1+18+1+72+1+288=384
+ 	- at cd_offset+4 (388) is huffman table
+ 	- at cd_offset+5 (389) is 4base luma plane
+ 
+ 	(the sector at cd_offset+3 seems to contain 256 words each of
+ 	which is an offset presumably to the sector containing certain
+ 	rows ? rows/4 given 1024 possible rows. The rest of this sector
+ 	is filled with zeroes)
+ 
+ 
+    16base
+ 	- plain data for base is read
+ 	- luma data interpolated *2
+ 	- chroma data interpolated *4
+ 
+ 	- cd_offset is 1+2+1+18+1+72+1+288=384
+ 	- at cd_offset+4 (388) is huffman table for 4 base
+ 	- at cd_offset+5 (389) is 4base luma plane
+ 	- luma plane interpolated *2
+ 
+ 	- cd_offset is set to current position (should be start of sector)
+ 	- at cd_offset+12 is huffman table for 16 base
+ 	- at cd_offset+14 is 16 base luma & 2 chroma planes which are read
+           (note that the luma plane comes first, with a sync pattern
+            announcing each row from 0 to 2047, then the two chroma planes
+            are interleaved by row, the row # being even from 0 to 2046, with
+            each row containing 1536 values, the chroma1 row coming first,
+            finally followed by a sync pattern with a row of 2048 announcing
+            the end (its plane seems to be set to 3, ie. chroma2)
+ 	- chroma planes interpolated *2
+ 
+ 	(the sector at cd_offset+10 & 11 seem to contain 1024 pairs of words
+         the first for luma and the second for chroma, each of
+ 	which is an offset presumably to the sector containing certain
+ 	rows ? rows/2 given 2048 possible rows)
+ 
+ Not yet implemented:
+ 
+ In order to do overskip for base and 4base, one has to reach the chroma
+ data for 16 base:
+ 
+ 	- for 4base, after reading the 4base luma plane (and presumably
+ 	  skipping the chroma planes) one sets cd_offset to the start of
+ 	  the "current" sector
+ 
+ 	- for base, one has to skip the 4base data first:
+ 	- cd_offset is set to 384
+ 	- at (cd_offset+3 sectors)[510] is a 16 bit word high byte 1st
+ 	  containing an offset to the beginning of the 16base stuff
+ 	  though there is then a loop until >30 0xff's start a sector !
+ 
+ 	- being now positioned after the end of the 4base stuff,
+ 	- at (cd_offset+10 sectors)[2] is a 16 bit word high byte 1st
+ 	  containing an offset to the chroma planes.
+ 	- at cd_offset+12 is the set of huffman tables
+ 
+ 	- for base, the 16base chroma planes are then halved
+ */
+ 
+   PCDSetParamOptions(bname);
+   if (theSize == -1)
+   {
+     PCDDialog(1);                   /* Open PCD Dialog box */
+     SetCursors(-1);                 /* Somebody has already set it to wait :( */
+     leaveitup=1;
+     goforit=0;
+     /* block until the popup window gets closed */
+     while (leaveitup) {
+       int i;
+       XEvent event;
+       XNextEvent(theDisp, &event);
+       HandleEvent(&event, &i);
+     }
+     /* At this point goforit and size will have been set */
+     if (!goforit) {
+       /* nothing allocated so nothing needs freeing */
+       return 0;
+     }
+     WaitCursor();
+   }
+   else 
+   {
+     size = theSize;
+     goforit = 1;
+   }
+ 
+   switch (size) {
+   case 0:
+     pinfo->w=192;
+     pinfo->h=128;
+     offset=4*0x800;
+     mag=1;
+     huffplanes=0;
+     sprintf(pinfo->fullInfo, "PhotoCD, base/16 resolution");
+     break;
+   case 1:
+     pinfo->w=384;
+     pinfo->h=256;
+     offset=23*0x800;
+     mag=1;
+     huffplanes=0;
+     sprintf(pinfo->fullInfo, "PhotoCD, base/4 resolution");
+     break;
+   case 2:
+   default:
+     pinfo->w=768;
+     pinfo->h=512;
+     offset=96*0x800;
+     mag=1;
+     huffplanes=0;
+     sprintf(pinfo->fullInfo, "PhotoCD, base resolution");
+     break;
+   case 3:
+     pinfo->w=1536;
+     pinfo->h=1024;
+     offset=96*0x800;
+     mag=2;
+     huffplanes=1;
+     sprintf(pinfo->fullInfo, "PhotoCD, 4base resolution");
+     break;
+   case 4:
+     pinfo->w=3072;
+     pinfo->h=2048;
+     offset=96*0x800;
+     mag=4;
+     huffplanes=2;
+     sprintf(pinfo->fullInfo, "PhotoCD, 16base resolution");
+     break;
+   }
+ 
+   /* allocate 24-bit image */
+   pinfo->pic = (byte *) calloc(pinfo->w*pinfo->h*3,1);
+   if (!pinfo->pic) FatalError("couldn't malloc '24 bit rgb plane'");
+ 
+   pinfo->type = PIC24;
+   sprintf(pinfo->shrtInfo, "%dx%d PhotoCD.", pinfo->w, pinfo->h);
+   pinfo->colType = F_FULLCOLOR;
+   pinfo->frmType = -1;
+ 
+   if (fseek(fp,offset,0) == -1)
+     return pcdError(bname,"Can't find start of data.");
+ 
+   w = pinfo->w;  h = pinfo->h;
+   pic24 = pinfo->pic;
+ 
+   luma=(byte *) calloc(w*h,1);
+   if (!luma) FatalError("couldn't malloc 'luma plane'");
+   chroma1=(byte *) calloc(w*h/4,1);
+   if (!chroma1) FatalError("couldn't malloc 'chroma1 plane'");
+   chroma2=(byte *) calloc(w*h/4,1);
+   if (!chroma2) FatalError("couldn't malloc 'chroma2 plane'");
+ 
+   /* Read 2 luma rows length w, then one of each chroma rows w/2 */
+   /* If a mag factor is active, the small image is read into the */
+   /* top right hand corner of the larger allocated image */
+ 
+   for (row=0,lptr=luma,c1ptr=chroma1,c2ptr=chroma2; row <h/mag;
+        row+=2,lptr+=w*2,c1ptr+=w/2,c2ptr+=w/2) {
+     if (fread(lptr, 1, w/mag, fp) != w/mag) {
+       pcdError(bname,"Luma plane too short.");
+       break;
+     }
+     if (fread(lptr+w, 1, w/mag, fp) != w/mag) {
+       pcdError(bname,"Luma plane too short.");
+       break;
+     }
+     if (fread(c1ptr, 1, w/2/mag, fp) != w/2/mag) {
+       pcdError(bname,"Chroma1 plane too short.");
+       break;
+     }
+     if (fread(c2ptr, 1, w/2/mag, fp) != w/2/mag) {
+       pcdError(bname,"Chroma2 plane too short.");
+       break;
+     }
+     if (row%wcurfactor == 0) WaitCursor();
+   }
+ 
+   if (huffplanes) {
+     if (fseek(fp,388*0x800,0) == -1) {
+       return pcdError(bname,"Can't find start of huffman tables.");
+     }
+     magnify(2,h/mag,w/mag,h,w,luma);
+     magnify(2,h/2/mag,w/2/mag,h/2,w/2,chroma1);
+     magnify(2,h/2/mag,w/2/mag,h/2,w/2,chroma2);
+ 
+     /* doesn't really touch the chroma planes which aren't present in 4base */
+     gethuffdata(luma,chroma1,chroma2,w,h/mag*2);
+     /* if only doing 4base should probably fetch 16bases chroma planes here */
+ 
+     if (huffplanes == 2) {
+       /* This depends on gethuffdata() having grabbed things in 0x800 sectors */
+       /* AND still being positioned in the "last" sector of the data */
+       /* (cf. Hadmut's code which is positioned at start of the next sector) */
+       long offset=ftell(fp)/0x800+13;
+       trace(stderr,"New offset=%ld\n",(long)offset);
+       if (fseek(fp,offset*0x800,0) == -1) {
+         return pcdError(bname,"Can't find start of huffman tables.");
+       }
+       magnify(2,h/2,w/2,h,w,luma);
+       magnify(2,h/4,w/4,h/2,w/2,chroma1);
+       magnify(2,h/4,w/4,h/2,w/2,chroma2);
+ 
+       gethuffdata(luma,chroma1,chroma2,w,h);
+     }
+   }
+ 
+   ptr=pic24; lptr=luma; c1ptr=chroma1; c2ptr=chroma2;
+   for (row=0; row < h; row++) {
+     byte *rowc1ptr, *rowc2ptr;
+     rowc1ptr=c1ptr;
+     rowc2ptr=c2ptr;
+     for (col=0; col < w; col++) {
+       int r,g,b;
+       int y =*lptr++;
+       int c1=*c1ptr;
+       int c2=*c2ptr;
+ 
+       r = (5564 * y + 2048 + 7461 * c2 - 1022138)/4096;
+       g = (5564 * y + 2048 + 274934 - 1762 * c1 + 520268 - 3798 * c2)/4096; 
+       b = (5564 * y + 2048 + 9085 * c1 - 1417185)/4096;
+ 
+       if (r > 255) r=255;
+       if (r < 0 ) r=0;
+       if (g > 255) g=255;
+       if (g < 0 ) g=0;
+       if (b > 255) b=255;
+       if (b < 0 ) b=0;
+ 
+       *ptr++=r;
+       *ptr++=g;
+       *ptr++=b;
+       if (col%2) { ++c1ptr; ++c2ptr; }
+     }
+     if (row%2 == 0) { c1ptr=rowc1ptr; c2ptr=rowc2ptr; }
+     if (row%wcurfactor == 0) WaitCursor();
+   }
+ 
+   free(luma); free(chroma1); free(chroma2);
+ 
+   rv = 1;
+ 
+   fclose(fp);
+ 
+   if (!rv) {
+     if (pinfo->pic) free(pinfo->comment);
+     if (pinfo->comment) free(pinfo->comment);
+     pinfo->pic     = (byte *) NULL;
+     pinfo->comment = (char *) NULL;
+   }
+ 
+   return rv;
+ }  
+ 
+ 
+ /*******************************************/
+ 
+ /* derived from Hadmut Danisch's interpolate() */
+ 
+ static void
+ magnify(mag,h,w,mh,mw,p)
+ int mag;	/* power of 2 by which to magnify in place */
+ int h,w;	/* the "start" unmag'd dimensions of the data in the array */
+ int mh,mw;	/* the real (maximum) dimensions of the array */
+ unsigned char *p;	/* pointer to the data */
+ {
+   int x,y,yi;
+   unsigned char *optr,*nptr,*uptr;  /* MUST be unsigned, else averaging fails */
+ 
+   while (mag > 1) {
+ 
+     /* create every 2nd new row from 0 */
+     /*  even pixels being equal to the old, odd ones averaged with successor */
+     /*  special case being the last column which is just set equal to the */
+     /*  second last) ... */
+ 
+     for(y=0;y<h;y++) {
+       yi=h-1-y;
+       optr=p+  yi*mw + (w-1);	          /* last pixel of an old row */
+       nptr=p+2*yi*mw + (2*w - 2);         /* last pixel of a new row */
+ 
+       nptr[0]=nptr[1]=optr[0];            /* special cases */
+ 
+       for(x=1;x<w;x++) {
+         optr--; nptr-=2;                  /* next lower pixel(s) */
+         nptr[0]=optr[0];                  /* even pixels duped */
+         nptr[1]=(((int)optr[0])+
+                  ((int)optr[1])+1)>>1;    /* odd averaged */
+       }
+     }
+ 
+     /* Fill in odd rows, as average of prior & succeeding rows, with */
+     /* even pixels average of one column, odd pixels average of two */
+ 
+     for(y=0;y<h-1;y++) {                  /* all but the last old row */
+       optr=p + 2*y*mw;                    /* start of the new "even" rows */
+       nptr=optr+mw;                       /* start of the next empty row */
+       uptr=nptr+mw;                       /* start of the next again (even) */
+ 
+       for(x=0;x<w-1;x++) {                /* for all cols except the last */
+         nptr[0]=(((int)optr[0])+
+                  ((int)uptr[0])+1)>>1;    /* even pixels */
+         nptr[1]=(((int)optr[0])+
+                  ((int)optr[2])+
+                  ((int)uptr[0])+
+                  ((int)uptr[2])+2)>>2;    /* odd pixels */
+         nptr+=2; optr+=2; uptr+=2;
+       }
+       *(nptr++)=(((int)*(optr++))+
+                  ((int)*(uptr++))+1)>>1;  /* 2nd last pixel */
+       *(nptr++)=(((int)*(optr++))+
+                  ((int)*(uptr++))+1)>>1;  /* last pixel */
+     }
+ 
+     xvbcopy(p + (2*h-2)*mw,                 /* 2nd last row */
+           p + (2*h-1)*mw,                 /* the last row */
+           2*w);                           /* length of a new row */
+ 
+     h*=2; w*=2;
+     mag>>=1;	/* Obviously mag must be a power of 2 ! */
+   }
+ }
+ 
+ 
+ /*******************************************/
+ static int pcdError(fname, st)
+      char *fname, *st;
+ {
+   SetISTR(ISTR_WARNING,"%s:  %s", fname, st);
+   return 0;
+ }
+ 
+ 
+ /**** Stuff for PCDDialog box ****/
+ 
+ #define TWIDE 380
+ #define THIGH 160
+ #define T_NBUTTS 2
+ #define T_BOK    0
+ #define T_BCANC  1
+ #define BUTTH    24
+ 
+ static void drawTD    PARM((int, int, int, int));
+ static void clickTD   PARM((int, int));
+ static void doCmd     PARM((int));
+ static void PCDSetParams PARM((void));
+ 
+ /* local variables */
+ static BUTT  tbut[T_NBUTTS];
+ static RBUTT *resnRB;
+ 
+ 
+ 
+ /***************************************************/
+ void CreatePCDW()
+ {
+   int	     y;
+ 
+   pcdW = CreateWindow("xv pcd", "XVpcd", NULL, 
+ 		       TWIDE, THIGH, infofg, infobg, 0);
+   if (!pcdW) FatalError("can't create pcd window!");
+ 
+   XSelectInput(theDisp, pcdW, ExposureMask | ButtonPressMask | KeyPressMask);
+ 
+   BTCreate(&tbut[T_BOK], pcdW, TWIDE-140-1, THIGH-10-BUTTH-1, 60, BUTTH, 
+ 	   "Ok", infofg, infobg, hicol, locol);
+ 
+   BTCreate(&tbut[T_BCANC], pcdW, TWIDE-70-1, THIGH-10-BUTTH-1, 60, BUTTH, 
+ 	   "Cancel", infofg, infobg, hicol, locol);
+ 
+   y = 55;
+   resnRB = RBCreate(NULL, pcdW, 36, y,   "192*128   Base/16",
+            infofg, infobg,hicol,locol);
+   RBCreate(resnRB, pcdW, 36, y+18,       "384*256   Base/4",
+            infofg, infobg,hicol,locol);
+   RBCreate(resnRB, pcdW, 36, y+36,       "768*512   Base",
+            infofg, infobg, hicol, locol);
+   RBCreate(resnRB, pcdW, TWIDE/2, y,     "1536*1024 4Base",
+            infofg, infobg, hicol, locol);
+   RBCreate(resnRB, pcdW, TWIDE/2, y+18,  "3072*2048 16Base",
+            infofg, infobg, hicol, locol);
+ #ifdef CRAP
+   RBCreate(resnRB, pcdW, TWIDE/2, y+36,  "Other",
+            infofg, infobg, hicol, locol);
+ #endif
+ 
+   XMapSubwindows(theDisp, pcdW);
+ }
+   
+ 
+ /***************************************************/
+ void PCDDialog(vis)
+ int vis;
+ {
+   if (vis) {
+     CenterMapWindow(pcdW, tbut[T_BOK].x + tbut[T_BOK].w/2,
+ 		    tbut[T_BOK].y + tbut[T_BOK].h/2, TWIDE, THIGH);
+   }
+   else     XUnmapWindow(theDisp, pcdW);
+   pcdUp = vis;
+ }
+ 
+ 
+ /***************************************************/
+ int PCDCheckEvent(xev)
+ XEvent *xev;
+ {
+   /* check event to see if it's for one of our subwindows.  If it is,
+      deal accordingly, and return '1'.  Otherwise, return '0' */
+ 
+   int rv;
+   rv = 1;
+ 
+   if (!pcdUp) return 0;
+ 
+   if (xev->type == Expose) {
+     int x,y,w,h;
+     XExposeEvent *e = (XExposeEvent *) xev;
+     x = e->x;  y = e->y;  w = e->width;  h = e->height;
+ 
+     if (e->window == pcdW)       drawTD(x, y, w, h);
+     else rv = 0;
+   }
+ 
+   else if (xev->type == ButtonPress) {
+     XButtonEvent *e = (XButtonEvent *) xev;
+     int x,y;
+     x = e->x;  y = e->y;
+ 
+     if (e->button == Button1) {
+       if      (e->window == pcdW)     clickTD(x,y);
+       else rv = 0;
+     }  /* button1 */
+     else rv = 0;
+   }  /* button press */
+ 
+ 
+   else if (xev->type == KeyPress) {
+     XKeyEvent *e = (XKeyEvent *) xev;
+     char buf[128];  KeySym ks;  XComposeStatus status;  
+     int stlen;
+ 	
+     stlen = XLookupString(e,buf,128,&ks,&status);
+     buf[stlen] = '\0';
+ 
+     RemapKeyCheck(ks, buf, &stlen);
+ 
+     if (e->window == pcdW) {
+       if (stlen) {
+ 	if (buf[0] == '\r' || buf[0] == '\n') { /* enter */
+ 	  FakeButtonPress(&tbut[T_BOK]);
+ 	}
+ 	else if (buf[0] == '\033') {            /* ESC */
+ 	  FakeButtonPress(&tbut[T_BCANC]);
+ 	}
+       }
+     }
+     else rv = 0;
+   }
+   else rv = 0;
+ 
+   if (rv==0 && (xev->type == ButtonPress || xev->type == KeyPress)) {
+     XBell(theDisp, 50);
+     rv = 1;   /* eat it */
+   }
+ 
+   return rv;
+ }
+ 
+ 
+ /***************************************************/
+ void PCDSetParamOptions(fname)
+ char *fname;
+ {
+   int cur;
+   cur = RBWhich(resnRB);
+ 
+   RBSetActive(resnRB,0,1);
+   RBSetActive(resnRB,1,1);
+   RBSetActive(resnRB,2,1);
+   RBSetActive(resnRB,3,1);
+   RBSetActive(resnRB,4,1);
+   RBSetActive(resnRB,5,0);
+ }
+ 
+ 
+ /***************************************************/
+ static void drawTD(x,y,w,h)
+ int x,y,w,h;
+ {
+   char *title  = "Load PhotoCD file...";
+   int  i;
+   XRectangle xr;
+ 
+   xr.x = x;  xr.y = y;  xr.width = w;  xr.height = h;
+   XSetClipRectangles(theDisp, theGC, 0,0, &xr, 1, Unsorted);
+ 
+   XSetForeground(theDisp, theGC, infofg);
+   XSetBackground(theDisp, theGC, infobg);
+ 
+   for (i=0; i<T_NBUTTS; i++) BTRedraw(&tbut[i]);
+ 
+   ULineString(pcdW, resnRB->x-16, resnRB->y-10-DESCENT, "Resolution");
+   RBRedraw(resnRB, -1);
+ 
+   XDrawString(theDisp, pcdW, theGC, 20, 19, title, strlen(title));
+ 
+   XSetClipMask(theDisp, theGC, None);
+ }
+ 
+ 
+ /***************************************************/
+ static void clickTD(x,y)
+ int x,y;
+ {
+   int i;
+   BUTT *bp;
+ 
+   /* check BUTTs */
+ 
+   /* check the RBUTTS first, since they don't DO anything */
+   if ( (i=RBClick(resnRB, x,y)) >= 0) { 
+     (void) RBTrack(resnRB, i);
+     return;
+   }
+ 
+ 
+   for (i=0; i<T_NBUTTS; i++) {
+     bp = &tbut[i];
+     if (PTINRECT(x, y, bp->x, bp->y, bp->w, bp->h)) break;
+   }
+ 
+   if (i<T_NBUTTS) {  /* found one */
+     if (BTTrack(bp)) doCmd(i);
+   }
+ }
+ 
+ 
+ 
+ /***************************************************/
+ static void doCmd(cmd)
+ int cmd;
+ {
+   leaveitup=0;
+   goforit=0;
+   switch (cmd) {
+   case T_BOK:  	PCDSetParams();
+                 goforit=1;
+   case T_BCANC:	PCDDialog(0);
+                 break;
+ 
+   default:	break;
+   }
+ }
+ 
+ 
+ /*******************************************/
+ static void PCDSetParams()
+ {
+   switch (RBWhich(resnRB)) {
+   case 0: size = 0;      break;
+   case 1: size = 1;      break;
+   case 2: size = 2;      break;
+   case 3: size = 3;      break;
+   case 4: size = 4;      break;
+   case 5: size = 0;      break;
+   default: size = 0;     break;
+   }
+ }
+ 
+ typedef char schar;  /* signed char */
+ 
+ typedef int ihufftab;  /* Must be signed */
+ 
+ static ihufftab *hufftable[3];
+ static int hufflength[3];
+ 
+ /*
+ 
+ Read the Huffman tables which consist of an unsigned byte # of entries
+ (less 1) followed by up to 256 entries, each of which is a series of 4
+ unsigned bytes - length, highseq, lowseq, and key.
+ 
+ Store the huffman table into tree type structure:
+ 
+ 	int ihufftab[n of entries*2]
+ 
+ Each entry consists of two words (the 1st for zero and the 2nd for one).
+ 
+ If the word is negative, then subtract it from the current pointer to
+ get the next entry (ie. it is the negative offset from the current
+ position*2 in order to skip entries not words) with which to make a decision.
+ 
+ If the word is not negative, then the low 8 bits contain the value (which
+ is supposed to be a signed char) and the rest of the word is zero.
+ 
+ */
+ 
+ static ihufftab *
+ gethufftable(alength)
+ int *alength;
+ {
+   unsigned num,i,offset;
+ 
+   ihufftab *hufftab,*huffptr,*hufftop;
+ 
+   num=fgetc(fp)+1;
+ 
+   trace(stderr,"gethufftable: hufftab length %u\n",num);
+ 
+   if ((hufftab=(ihufftab *)malloc(2*num*sizeof(ihufftab))) == 0) {
+     fprintf(stderr,"Can't allocate hufftab length %u\n",num);
+     exit(1);
+   }
+   for (i=0,huffptr=hufftab; i<2*num; i++)
+     *huffptr++=0;  /* Fill value is zero */
+ 
+   hufftop=hufftab;
+ 
+   for (i=0,offset=1; i<num; i++,offset+=4){
+     unsigned length=fgetc(fp);
+     unsigned msbseq=fgetc(fp);
+     unsigned lsbseq=fgetc(fp);
+     unsigned codeword=msbseq<<8|lsbseq;
+     unsigned value =fgetc(fp);
+     {
+       unsigned j;
+       huffptr=hufftab;
+       for (j=0; j<16; j++) {
+         int bit=codeword & 0x8000;
+         codeword<<=1;
+ 
+         if (j == length) {
+           if (bit) *++huffptr=value;
+           else *huffptr=value;
+         }
+         else {
+           if (j < length) {
+             if (bit) {
+               ++huffptr;
+             }
+             if (*huffptr >= 0) {
+               hufftop+=2;
+               if (hufftop-hufftab >2*num) {
+                 fprintf(stderr,"Table overflow\n");
+                 exit(1);
+               }
+               *huffptr=-(hufftop-huffptr);
+             }
+             huffptr-=*huffptr;
+           }
+         }
+       }
+     }
+   }
+ 
+   *alength=num;
+   return hufftab;
+ }
+ 
+ /* WORDTYPE & char buffer must be unsigned else */
+ /* fills with sign bit not 0 on right shifts */
+ typedef unsigned int WORDTYPE;
+ typedef int SWORDTYPE;
+ #define WORDSIZE sizeof(WORDTYPE)
+ #define NBYTESINBUF 0x800
+ 
+ static unsigned char buffer[NBYTESINBUF];
+ static int bitsleft=0;
+ static int bytesleft=0;
+ static unsigned char *bufptr;
+ static WORDTYPE word;
+ 
+ /* assume WORDTYPE is 32 bit word */
+ #define issync()  ((word & 0xffffff00) == 0xfffffe00)
+ #define skiptosync()  { while (!issync()) (void)getbit(); }
+ 
+ static void
+ dumpbuffer()
+ {
+   int i,left;
+   unsigned char *ptr=buffer;
+ 
+   fprintf(stderr,"dumpbuffer: bytesleft=%d bitsleft= %d word=0x%08lx\n",
+     bytesleft,bitsleft,(unsigned long)word);
+   for (left=NBYTESINBUF; left>0; left-=16) {
+     fprintf(stderr,"%05d  ",left);
+     for (i=0; i<8; i++) {
+       fprintf(stderr,"%02x",*ptr++);
+       fprintf(stderr,"%02x ",*ptr++);
+     }
+     fprintf(stderr,"\n");
+   }
+ }
+ 
+ static void
+ loadbuffer()
+ {
+   trace(stderr,"loadbuffer: start at sector %ld\n",(long)ftell(fp)/0x800
+ );
+   if ((bytesleft=fread(buffer,1,NBYTESINBUF,fp)) == 0) {
+     fprintf(stderr,"Truncation error\n");
+     exit(1);
+   }
+   bufptr=buffer;
+   trace(stderr,"loadbuffer: Loaded buffer with %d bytes\n",bytesleft);
+   /* dumpbuffer(); */
+ }
+ 
+ static void
+ loadbyte()
+ {
+   trace(stderr,"loadbyte: start bytesleft=%d bitsleft= %d word=0x%08lx\n",
+     bytesleft,bitsleft,(unsigned long)word);
+   if (bytesleft <= 0) loadbuffer();
+   --bytesleft;
+   word|=(WORDTYPE)(*bufptr++)<<(sizeof(WORDTYPE)*8-8-bitsleft);
+   bitsleft+=8;
+   trace(stderr,"loadbyte: done  bytesleft=%d bitsleft= %d word=0x%08lx\n",
+     bytesleft,bitsleft,(unsigned long)word);
+ }
+ 
+ static int
+ getbit()
+ {
+   int bit;
+ 
+   trace(stderr,"getbit:   start bytesleft=%d bitsleft= %d word=0x%08lx\n",
+     bytesleft,bitsleft,(unsigned long)word);
+ 
+   while (bitsleft <= 0) loadbyte();
+   --bitsleft;
+   bit=(SWORDTYPE)(word)<0;  /* assumes word is signed */
+   /* bit=word>>(sizeof(WORDTYPE)*8-1); */
+   word<<=1;
+ 
+   trace(stderr,"getbit:   done  bytesleft=%d bitsleft= %d word=0x%08lx\n",
+     bytesleft,bitsleft,(unsigned long)word);
+   trace(stderr,"getbit:   done  bit=%d\n",bit);
+ 
+   return bit;
+ }
+ 
+ static WORDTYPE
+ getnn(nn)
+ int nn;
+ {
+   WORDTYPE value;
+ 
+   trace(stderr,"getnn:    start nn=%d\n",nn);
+   trace(stderr,"getnn:    start bytesleft=%d bitsleft= %d word=0x%08lx\n",
+     bytesleft,bitsleft,(unsigned long)word);
+ 
+   while (bitsleft <= nn) loadbyte();
+   bitsleft-=nn;
+   value=word>>(sizeof(WORDTYPE)*8-nn);
+   word<<=nn;
+ 
+   trace(stderr,"getnn:    done  bytesleft=%d bitsleft= %d word=0x%08lx\n",
+     bytesleft,bitsleft,(unsigned long)word);
+   trace(stderr,"getnn:    done  value=0x%08lx\n",(unsigned long)value);
+ 
+   return value;
+ }
+ 
+ static WORDTYPE
+ isnn(nn)
+ int nn;
+ {
+   WORDTYPE value;
+ 
+   trace(stderr,"isnn:     start nn=%d\n",nn);
+   trace(stderr,"isnn:     start bytesleft=%d bitsleft= %d word=0x%08lx\n",
+     bytesleft,bitsleft,(unsigned long)word);
+ 
+   while (bitsleft <= nn) loadbyte();
+   value=word>>(sizeof(WORDTYPE)*8-nn);
+ 
+   trace(stderr,"isnn:     done  bytesleft=%d bitsleft= %d word=0x%08lx\n",
+     bytesleft,bitsleft,(unsigned long)word);
+   trace(stderr,"isnn:     done  value=0x%08lx\n",(unsigned long)value);
+ 
+   return value;
+ }
+ 
+ static void
+ skipnn(nn)
+ int nn;
+ {
+   trace(stderr,"skipnn:   start nn=%d\n",nn);
+   trace(stderr,"skipnn:   start bytesleft=%d bitsleft= %d word=0x%08lx\n",
+     bytesleft,bitsleft,(unsigned long)word);
+ 
+   while (bitsleft <= nn) loadbyte();
+   bitsleft-=nn;
+   word<<=nn;
+ 
+   trace(stderr,"skipnn:   done  bytesleft=%d bitsleft= %d word=0x%08lx\n",
+     bytesleft,bitsleft,(unsigned long)word);
+ }
+ 
+ #define get1()    (getbit())
+ #define get2()    (getnn(2))
+ #define get8()    (getnn(8))
+ #define get13()    (getnn(13))
+ #define get16()    (getnn(16))
+ #define get24()    (getnn(24))
+ 
+ #define is8()    (isnn(8))
+ #define is16()    (isnn(16))
+ #define is24()    (isnn(24))
+ 
+ #define skip1()    (skipnn(1))
+ #define skip8()    (skipnn(8))
+ #define skip16()  (skipnn(16))
+ #define skip24()  (skipnn(24))
+ 
+ static int
+ gethuffdata(luma,chroma1,chroma2,realrowwidth,maxrownumber)
+ char *luma, *chroma1, *chroma2;
+ int realrowwidth;
+ int maxrownumber;
+ {
+     int row,plane,charcount;
+     int i;
+ 
+     trace(stderr,"gethuffdata: start\n");
+ 
+     /* should really only look for luma plane for 4base, but the */
+     /* there are zeroes in the rest of the sector that give both */
+     /* chroma tables 0 length */
+ 
+     for (i=0; i<3; i++) hufftable[i]=gethufftable(&hufflength[i]);
+ 
+     while (is24() != 0xfffffe) {
+       (void)get24();
+       trace(stderr,"Skipping for sync\n");
+     }
+     for (;;) {
+       ihufftab *huffstart;
+       schar    *pixelptr;
+ 
+       if (is24() == 0xfffffe) {
+         skip24();
+         trace(stderr,"Charcount=%d\n",charcount);
+         charcount=0;
+         plane=get2();
+         row=get13();
+         skip1();
+         trace(stderr,"Plane %d Row %d\n",plane,row);
+         if (row>=maxrownumber) {
+           trace(stderr,"Stopping at row %d\n",row);
+           break;
+         }
+         switch (plane) {
+           case 0:    huffstart=hufftable[0];
+                      pixelptr=luma+row*realrowwidth;
+                      trace(stderr,"Setting luma plane\n");
+                      break;
+           case 2:    huffstart=hufftable[1];
+                      pixelptr=chroma1+row/2*realrowwidth/2;
+                      trace(stderr,"Setting chroma1 plane\n");
+                      break;
+           case 3:    huffstart=hufftable[2];
+                      pixelptr=chroma2+row/2*realrowwidth/2;
+                      trace(stderr,"Setting chroma2 plane\n");
+                      break;
+           default:   fprintf(stderr,"Bad plane %d\n",plane);
+                      exit(1);
+         }
+         WaitCursor();
+       }
+       else {
+         ihufftab *huffptr=huffstart;
+         for (;;) {
+           int bit;
+           bit=get1();    /* never fails :) */
+           huffptr+=bit;    /* select entry 0 or entry 1 */
+           if (*huffptr < 0) {  /* flag to choose next entry */
+             huffptr-=*huffptr;
+           }
+           else {      /* found the value for the code */
+             schar value;
+             (*pixelptr)+=(schar)*huffptr;  /* in lower 8 bits */
+             /* probably don't need to mask with 0xff */
+             ++charcount;
+             trace(stderr,"[%d]=%d\n",charcount,(int)value);
+             break;
+           }
+         }
+       }
+     }
+     trace(stderr,"Out ... \n");
+ 
+     for (i=0; i<3; i++) if (hufftable[i]) free(hufftable[i]);
+ 
+     return 1;
+ }
diff -c -r xv-3.10/bits/br_pcd xv-3.10pcd/bits/br_pcd
*** xv-3.10/bits/br_pcd	Thu Jun 15 21:44:45 1995
--- xv-3.10pcd/bits/br_pcd	Thu Jun 15 21:31:53 1995
***************
*** 0 ****
--- 1,27 ----
+ #define br_pcd_width 48
+ #define br_pcd_height 48
+ static unsigned char br_pcd_bits[] = {
+    0xe0, 0xff, 0xff, 0xff, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x03, 0x00,
+    0x20, 0x00, 0x00, 0x00, 0x05, 0x00, 0x20, 0x00, 0x00, 0x00, 0x09, 0x00,
+    0x20, 0x00, 0x00, 0x00, 0x11, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00,
+    0x20, 0x00, 0x00, 0x00, 0x41, 0x00, 0x20, 0x00, 0x00, 0x00, 0x81, 0x00,
+    0x20, 0x00, 0x00, 0x00, 0x01, 0x01, 0x20, 0x00, 0x00, 0x00, 0xff, 0x03,
+    0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
+    0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x3f, 0x02,
+    0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x3f, 0x02,
+    0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x67, 0x00, 0xe0, 0x1c, 0x02,
+    0x20, 0x6f, 0x00, 0xf0, 0x3d, 0x02, 0x20, 0x6b, 0x00, 0xb0, 0x2d, 0x02,
+    0x20, 0x6b, 0x00, 0x33, 0x2c, 0x02, 0x20, 0x6b, 0x00, 0x33, 0x2c, 0x02,
+    0x20, 0xeb, 0x98, 0x37, 0x2c, 0x02, 0x20, 0xef, 0xbd, 0x37, 0x2c, 0x02,
+    0x20, 0x67, 0x2d, 0x33, 0x2c, 0x02, 0x20, 0x63, 0x2d, 0x33, 0x2c, 0x02,
+    0x20, 0x63, 0x2d, 0x33, 0x2c, 0x02, 0x20, 0x63, 0x2d, 0xb3, 0x2d, 0x02,
+    0x20, 0x63, 0x3d, 0xf7, 0x3d, 0x02, 0x20, 0x63, 0x19, 0xe6, 0x1c, 0x02,
+    0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x3f, 0x02,
+    0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x3f, 0x02,
+    0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
+    0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
+    0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
+    0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
+    0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
+    0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
+    0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x03};


