/* WBdump.c - fast EX-800 workbench print dump (c) 1987 DJH

	It seemed to me that the Amiga JX-80 driver was vastly inefficient
  for full screen dumps; so I wrote this routine to see how fast I could
  press my Epson EX-800. The EX is JX-80 compatable, although MUCH faster.
  This program will create beautiful Workbench snapshots in 29-53 seconds,
  depending on mode. Contrast this with the 3 min 48 sec as produced by
  DumpRPort. In all fairness however, this routine does not attempt to
  remain faithful to the actual onscreen colors; no dithering, etc.

  PRINT OPTIMIZATIONS OVER PRT:
	1) Bidirectional graphic printing supported. Despite what the RKM
           sez, it sped up several modes by around 20%; and the graphics
           are blur-free.
        2) Blank colors don't even THINK about getting printed!
        3) Built-in Epson aspect ratios preserved; sharper & faster print
        4) Background color is assumed white, saving ribbon
        5) Remaining colors are ribbon primaries, avoiding color mixing

	A substantial amount of time in this pgm is spent just performing
  ReadPixel()'s. Feel free to optimize this; Compare running this program
  normally, vs. saving the processed output to RAM: and printing the result
  via "copy ram:fspec to PAR:". I got THIRTEEN SECOND pictures this way!

	This program is just a (useful) kernel; it should still work with
  the Epson JX-80, although I have no way of actually testing this. Have Fun!

  BENCHMARKS : (printer=Epson EX-800, test screen : NewZAP 3.0 (4-color WB)

  MODE : 0 Single-Density		: 32 sec
  	 1 Double-Density		: 39 sec (good mode)
	 2 High-Speed Double-Density	: 29 sec
	 3 Quad-Density			: 29 sec
	 4 CRT-I			: 53 sec
	 5 Plotter			: 39 sec
	 6 CRT-II			: 48 sec (default mode)
	 7 Double-Density Plotter	: 44 sec (slightly better than 1)

  USAGE : WBDump [filespec,mode,overstrike]
  DEFAULTS : WBDump par:,DEFAULT_MODE,1
*/


#define DEFAULT_MODE 0x06 /* CRT-II is a nice size */

void *GfxBase,*IntuitionBase;

color_table[] = { 0x00,0x00,0x02,0x01 }; /* stick to YMCB for speed */

UBYTE init_sequence[] = { 0x1b,0x40,0x1b,0x33,0x18,0x1b,0x55,0x30 },
      set_grafix[] = { 0x1b,0x2a,DEFAULT_MODE,0x80,0x2 },
      set_color[] = { 0x1b,0x72,0x00 },
      cr[] = { 0x0d },
      lf[] = { 0x0a };

struct FileHandle *fp;

main(argc,argv)
int argc;
char *argv[];
{
  struct Window *window;
  struct NewWindow nw;
  struct Screen *wbscreen;

  if (argc>=2)
   if (*argv[1]=='?') {
     puts("WBDump Usage : WBDump [filename,mode,overstrike]");
     exit(0);
   }
   else puts("WBDump : (c) 1987 John Hodgson");

  GfxBase=OpenLibrary("graphics.library",0);
  IntuitionBase=OpenLibrary("intuition.library",0);

  setmem(&nw,sizeof(nw),0);

  nw.Height=20; nw.Width=20; /* goal is inconspicuous */
  nw.Flags=SIMPLE_REFRESH|BORDERLESS|BACKDROP;
  nw.Type=WBENCHSCREEN; /* 'cuz we want the WB Screen ptr */

  /* open window just long enough to find WorkBench */

  if (!(window=OpenWindow(&nw))) exit(0);
  wbscreen=window->WScreen; CloseWindow(window);
  
  if (argc>=2) fp=Open(argv[1],MODE_NEWFILE);
    else fp=Open("par:",MODE_NEWFILE);
  if (argc>=3) set_grafix[2]=argv[2][0]-'0';

  if (!fp) goto cleanup;

  Write(fp,&init_sequence[0],sizeof(init_sequence));
  Pack_Bytes(wbscreen,(argc==4) ? argv[3][0]-'0' : 1);

  Close(fp);

cleanup:
  CloseLibrary(IntuitionBase);
  CloseLibrary(GfxBase);
}

Pack_Bytes(screen,overstrike)
struct Screen *screen;
short overstrike;
{
  short cols=screen->BitMap.BytesPerRow*8,
        rows=screen->BitMap.Rows,
        colorcnt=1<<screen->BitMap.Depth,
        i,k,x,y,bit,pixel,hits;

  UBYTE *rowcolor[32];

  setmem(&rowcolor[0],sizeof(rowcolor),0);

  for (i=1;i<colorcnt;i++) /* no need to allocate BG color */
    if (!(rowcolor[i]=AllocMem(cols,MEMF_PUBLIC))) goto cleanup;
  
  for (y=0;y<rows;y+=8) {

    for (i=1;i<colorcnt;i++) setmem(rowcolor[i],cols,0);

    for (x=hits=0;x<cols;x++)
      for (i=0,bit=7;i<8;i++,bit--) {
        pixel=ReadPixel(&screen->RastPort,x,y+i);
        if (pixel) { /* BG color takes care of itself */
          rowcolor[pixel][x]|=1<<bit;
          hits|=1<<pixel;
        }
      }

    for (i=1;i<colorcnt;i++) /* skip backgrnd color; white paper's fine */
      if (hits & 1<<i) {
        set_color[2]=color_table[i];
        for (k=0;k<overstrike;k++) { /* optional overstrike for BOLD colors */
          Write(fp,&set_color[0],sizeof(set_color));
          Write(fp,&set_grafix[0],sizeof(set_grafix));
          Write(fp,rowcolor[i],cols);
          Write(fp,&cr[0],sizeof(cr));
        }
      }
    Write(fp,&lf[0],sizeof(lf));
  }

cleanup:
  for (i=1;i<colorcnt;i++) if (rowcolor[i]) FreeMem(rowcolor[i],cols);
}
