/* ST-400 Scanner Programm */
#include <exec/exec.h>
#include <exec/types.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <graphics/rastport.h>
#include <stdio.h>
#include <string.h>
#include <functions.h>

#define ST400ID 3
#define ST400LUN 96
#define DEV_NAME (char*)"scsi.device" /* <- change for other SCSI controller */
#define FORM 0x464f524d
#define ILBM 0x494c424d
#define BMHD 0x424d4844
#define BODY 0x424f4459
#define DIR_READ  1
#define DIR_WRITE 0

struct MsgPort *HCPort;
struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct DosBase *DosBase;
struct IntuiMessage *Message;
struct Window *win;
struct Screen *scr;
struct Viewport *vp;
struct RastPort *rp;
struct MsgPort *diskport;
struct IOStdReq *diskreq;
ULONG MessageClass;
USHORT Code;
long openerror;
ULONG memneed=0;
UWORD memwidth, memheight;
UBYTE memgray;
UBYTE *memptr;
USHORT *imgptrf, *imgptrz;

UBYTE numbits_16[]={0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4};
UBYTE numbits[256];
UBYTE graystep[]={0,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1};
UBYTE bitval[]={128,64,32,16,8,4,2,1};
UBYTE invbitval[]={127,191,223,239,247,251,253,254};
UBYTE sk,mf;
UWORD vx,vy,wx1,wy1,wx2,wy2;

/* Variables for Heath File Requester */
char *str_filenam[100];
char *str_cmdline[110];
char *def_name[50] = "";
char *def_dir[50] = "";


/* Interface Viariables for Assembly Routines */
volatile UBYTE *p0,*p1,*p2,*p3,*p4;
volatile UWORD cnt;
volatile ULONG v1;

typedef struct DefWindow /*might be scanner dependent*/
{  ULONG dummy1;
   UWORD dummy2;
   UWORD wpsize;
   UBYTE winnr;
   UBYTE dummy3;
   UWORD resx;
   UWORD resy;
   UWORD cornerx;
   UWORD cornery;
   UWORD width;
   UWORD height;
   UBYTE dummy4;
   UBYTE threshold;
   UBYTE size;     /* temporary storage, ignored by scanner */
   UBYTE halftone;
   UBYTE bitspixel;
   UBYTE dummy5;
   UWORD dummy6;
   ULONG dummy7;
};

typedef struct SCSICmd  /* included here because */
{   UWORD  *scsi_Data;	/* header file missing in Aztec C 5.0 */	
    ULONG   scsi_Length;	
    ULONG   scsi_Actual;	
    UBYTE  *scsi_Command;	
    UWORD   scsi_CmdLength;	
    UWORD   scsi_CmdActual;	
    UBYTE   scsi_Flags;		
    UBYTE   scsi_Status;	
};


struct DefWindow winpar= /*default values */
{  0,0,32,	/*dummy1, dummy2, wpsize*/
   1,0,		/*winnr, dummy3*/
   200,200,	/*resx, resy*/
   0,0,0,0,	/*cornerx, cornery, width, height*/
   0,32,5,	/*dummy4, threshold, size*/
   0,1,		/*halftone, bitspixel*/
   0,0,0	/*dummy5,6,7*/
};

/* Scanner specific sizes and commands */

UWORD cornerxval[]={  22,  33,  44, 266, 399, 535};
UWORD corneryval[]={   6,   6,   6,   6,   6,   6};
UWORD widthval[]=  {1164,2496,3312,1168,1760,2336};
UWORD heightval[]= {2336,3504,4672,1656,2484,3312};

UBYTE cmd_scan[]={0x1b,ST400LUN,0,0,0,0};
UBYTE cmd_read[]={0x28,ST400LUN,0,0,0,0,0,0,0,0};
UBYTE cmd_dwin[]={0x24,ST400LUN,0,0,0,0,0,0,40,0};
UBYTE cmd_mdon[]={0x15,ST400LUN,0,0,0,128};
UBYTE cmd_mdoff[]={0x15,ST400LUN,0,0,0,0};
UBYTE cmd_inqu[]={0x12,ST400LUN,0,0,96,0};


int prefdatei,sdatei,qdatei,wdatei;
unsigned int i;  
unsigned int len;
unsigned char a;

/* IFF-ILBM Constants */

UBYTE iff_cmap_bw[]=
{'C','M','A','P',0,0,0,6,0,0,0,255,255,255};

UBYTE iff_cmap_gray[]=
{'C','M','A','P',0,0,0,48,0,0,0,16,16,16,32,32,32,48,48,48,64,64,64,80,80,80,
 96,96,96,112,112,112,128,128,128,144,144,144,160,160,160,176,176,176,
 192,192,192,208,208,208,224,224,224,240,240,240};

ULONG iff_head[]={FORM,0,ILBM,BMHD,20,0,0,0,0x00000101,0x02800200};

ULONG iff_body[]={BODY,0};


/* Struktures for Windows and Menus */

struct TextAttr textattr=
{ "topaz.FONT",
   8,
   FS_NORMAL,
   FPF_ROMFONT
};

/* Struktures for Gadgets */

USHORT zvect2[]={0,0, 0,12, 12,12, 12,0, 0,0,
                -1,-1, -1,11, 11,11, 11,-1, -1,-1};
USHORT zvect1[]={0,0, 0,10, 10,10, 10,0, 0,0};

USHORT imagedataf[]=
{ 0xfff0,
  0xfff0,
  0xc030,
  0xdff0,
  0xdff0,
  0xc0f0,
  0xdff0,
  0xdff0,
  0xdff0,
  0xdff0,
  0xfff0,
  0xfff0,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000};
USHORT imagedataz[]=
{ 0xfff0,
  0xfff0,
  0xc030,
  0xff70,
  0xfef0,
  0xfdf0,
  0xfbf0,
  0xf7f0,
  0xeff0,
  0xc030,
  0xfff0,
  0xfff0,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000,
  0x0000};

struct Image fullimage=
{ 0,0,
  16,16,4,
  NULL,
  15,0,
  NULL
};

struct Image zoomimage=
{ 0,0,
  16,16,4,
  NULL,
  15,0,
  NULL
};

struct Border vborder;

struct Border hborder;


struct PropInfo hprop=
{ FREEHORIZ|AUTOKNOB,
  0,0,
  0xffff,0xffff,
  0,0,
  0,0,
  0,0
};

struct PropInfo vprop=
{ FREEVERT|AUTOKNOB,
  0,0,
  0xffff,0xffff,
  0,0,
  0,0,
  0,0
};

struct Gadget hgad=
{ NULL,
  0,483,
  624,15,
  0,
  GADGIMMEDIATE|RELVERIFY,
  PROPGADGET,
  &hborder,
  NULL,
  NULL,
  0,
  &hprop,
  2,
  NULL
};

struct Gadget vgad=
{ &hgad,
  625,11,
  15,470,
  0,
  GADGIMMEDIATE|RELVERIFY,
  PROPGADGET,
  &vborder,
  NULL,
  NULL,
  0,
  &vprop,
  1,
  NULL
};

struct Gadget zgad=
{ &vgad,
  627,485,
  12,12,
  GADGHIMAGE|GADGIMAGE,
  TOGGLESELECT|GADGIMMEDIATE|RELVERIFY,
  BOOLGADGET,
  &fullimage,
  &zoomimage,
  NULL,
  0,
  NULL,
  0,
  NULL
};

/* Struktures for Window and Screen */

struct NewScreen ns=
{
  0,0,
  640,512,
  4,
  8,1,
  HIRES|LACE,
  CUSTOMSCREEN,
  &textattr,
  (UBYTE *)"Siemens ST 400 Scanner Program © FChK 1991",
  NULL,
  NULL
};

struct NewWindow nw=
{ 0,10,
  640,500,
  8,1,
  CLOSEWINDOW|MENUPICK|GADGETUP|GADGETDOWN|MOUSEBUTTONS,
  WINDOWCLOSE|BACKDROP|BORDERLESS|ACTIVATE|SMART_REFRESH,
  &zgad,
  NULL,
  (UBYTE *)"",
  NULL,
  NULL,
  0,0,
  0,0,
  CUSTOMSCREEN
};

/* AHA-Requester Strukturen */

struct IntuiText text_na=
{ 0,1,
  JAM2,
  4,7,
  &textattr,
  (UBYTE *)"",
  NULL
};

struct IntuiText text_aha=
{ 0,1,
  JAM2,
  7,4,
  &textattr,
  (UBYTE *)"OK!",
  NULL
};


/* Menüdaten und -strukturen */

struct IntuiText text5f=
{ 0,1,
  JAM2,
  1,1,
  &textattr,
  (UBYTE *)"   15",
  NULL
};

struct IntuiText text5e=
{ 0,1,
  JAM2,
  1,1,
  &textattr,
  (UBYTE *)"   14",
  NULL
};

struct IntuiText text5d=
{ 0,1,
  JAM2,
  1,1,
  &textattr,
  (UBYTE *)"   13",
  NULL
};

struct IntuiText text5c=
{ 0,1,
  JAM2,
  1,1,
  &textattr,
  (UBYTE *)"   12",
  NULL
};

struct IntuiText text5b=
{ 0,1,
  JAM2,
  1,1,
  &textattr,
  (UBYTE *)"   11",
  NULL
};

struct IntuiText text5a=
{ 0,1,
  JAM2,
  1,1,
  &textattr,
  (UBYTE *)"   10",
  NULL
};

struct IntuiText text59=
{ 0,1,
  JAM2,
  1,1,
  &textattr,
  (UBYTE *)"    9",
  NULL
};

struct IntuiText text58=
{ 0,1,
  JAM2,
  1,1,
  &textattr,
  (UBYTE *)"    8",
  NULL
};

struct IntuiText text57=
{ 0,1,
  JAM2,
  1,1,
  &textattr,
  (UBYTE *)"    7",
  NULL
};

struct IntuiText text56=
{ 0,1,
  JAM2,
  1,1,
  &textattr,
  (UBYTE *)"    6",
  NULL
};

struct IntuiText text55=
{ 0,1,
  JAM2,
  1,1,
  &textattr,
  (UBYTE *)"    5",
  NULL
};

struct IntuiText text54=
{ 0,1,
  JAM2,
  1,1,
  &textattr,
  (UBYTE *)"    4",
  NULL
};

struct IntuiText text53=
{ 0,1,
  JAM2,
  1,1,
  &textattr,
  (UBYTE *)"    3",
  NULL
};

struct IntuiText text52=
{ 0,1,
  JAM2,
  1,1,
  &textattr,
  (UBYTE *)"    2",
  NULL
};

struct IntuiText text51=
{ 0,1,
  JAM2,
  1,1,
  &textattr,
  (UBYTE *)"    1",
  NULL
};

struct IntuiText text50=
{ 0,1,
  JAM2,
  1,1,
  &textattr,
  (UBYTE *)"    0",
  NULL
};

struct IntuiText text41=
{ 0,1,
  JAM2,
  1,1,
  &textattr,
  (UBYTE *)"   16",
  NULL
};

struct IntuiText text40=
{ 0,1,
  JAM2,
  1,1,
  &textattr,
  (UBYTE *)"    2",
  NULL
};

struct IntuiText text31=
{ 0,1,
  JAM2,
  1,1,
  &textattr,
  (UBYTE *)"   DIN A4",
  NULL
};

struct IntuiText text30=
{ 0,1,
  JAM2,
  1,1,
  &textattr,
  (UBYTE *)"   DIN A5",
  NULL
};

struct IntuiText text22=
{ 0,1,
  JAM2,
  1,1,
  &textattr,
  (UBYTE *)"   400 DPI",
  NULL
};

struct IntuiText text21=
{ 0,1,
  JAM2,
  1,1,
  &textattr,
  (UBYTE *)"   300 DPI",
  NULL
};

struct IntuiText text20=
{ 0,1,
  JAM2,
  1,1,
  &textattr,
  (UBYTE *)"   200 DPI",
  NULL
};

struct IntuiText text15=
{ 0,1,
  JAM2,
  1,1,
  &textattr,
  (UBYTE *)"Exit Program",
  NULL
};

struct IntuiText text14=
{ 0,1,
  JAM2,
  1,1,
  &textattr,
  (UBYTE *)"Test Scanner",
  NULL
};

struct IntuiText text13=
{ 0,1,
  JAM2,
  1,1,
  &textattr,
  (UBYTE *)"Dither Ord",
  NULL
};

struct IntuiText text12=
{ 0,1,
  JAM2,
  1,1,
  &textattr,
  (UBYTE *)"Dither F-S",
  NULL
};

struct IntuiText text11=
{ 0,1,
  JAM2,
  1,1,
  &textattr,
  (UBYTE *)"Save IFF",
  NULL
};

struct IntuiText text10=
{ 0,1,
  JAM2,
  1,1,
  &textattr,
  (UBYTE *)"Read Scanner",
  NULL
};

struct IntuiText text03=
{ 0,1,
  JAM2,
  1,1,
  &textattr,
  (UBYTE *)"Not For Commercial Use",
  NULL
};

struct IntuiText text02=
{ 0,1,
  JAM2,
  1,1,
  &textattr,
  (UBYTE *)"Version 1.00",
  NULL
};


struct IntuiText text01=
{ 0,1,
  JAM2,
  1,1,
  &textattr,
  (UBYTE *)"Frank-Christian Krügel",
  NULL
};

struct IntuiText text00=
{ 0,1,
  JAM2,
  1,1,
  &textattr,
  (UBYTE *)"Program written by",
  NULL
};

struct MenuItem item5f=
{ NULL,
  40,70,
  40,10,
  ITEMTEXT|HIGHCOMP|ITEMENABLED|CHECKIT,
  0x7fff,
  (APTR)&text5f,
  NULL,
  0, 
  NULL,
  0
};

struct MenuItem item5e=
{ &item5f,
  40,60,
  40,10,
  ITEMTEXT|HIGHCOMP|ITEMENABLED|CHECKIT,
  0xbfff,
  (APTR)&text5e,
  NULL,
  0, 
  NULL,
  0
};

struct MenuItem item5d=
{ &item5e,
  40,50,
  40,10,
  ITEMTEXT|HIGHCOMP|ITEMENABLED|CHECKIT,
  0xdfff,
  (APTR)&text5d,
  NULL,
  0, 
  NULL,
  0
};

struct MenuItem item5c=
{ &item5d,
  40,40,
  40,10,
  ITEMTEXT|HIGHCOMP|ITEMENABLED|CHECKIT,
  0xefff,
  (APTR)&text5c,
  NULL,
  0, 
  NULL,
  0
};

struct MenuItem item5b=
{ &item5c,
  40,30,
  40,10,
  ITEMTEXT|HIGHCOMP|ITEMENABLED|CHECKIT,
  0xf7ff,
  (APTR)&text5b,
  NULL,
  0, 
  NULL,
  0
};

struct MenuItem item5a=
{ &item5b,
  40,20,
  40,10,
  ITEMTEXT|HIGHCOMP|ITEMENABLED|CHECKIT,
  0xfbff,
  (APTR)&text5a,
  NULL,
  0, 
  NULL,
  0
};

struct MenuItem item59=
{ &item5a,
  40,10,
  40,10,
  ITEMTEXT|HIGHCOMP|ITEMENABLED|CHECKIT,
  0xfdff,
  (APTR)&text59,
  NULL,
  0, 
  NULL,
  0
};

struct MenuItem item58=
{ &item59,
  40,0,
  40,10,
  ITEMTEXT|HIGHCOMP|ITEMENABLED|CHECKIT|CHECKED,
  0xfeff,
  (APTR)&text58,
  NULL,
  0, 
  NULL,
  0
};

struct MenuItem item57=
{ &item58,
  0,70,
  40,10,
  ITEMTEXT|HIGHCOMP|ITEMENABLED|CHECKIT,
  0xff7f,
  (APTR)&text57,
  NULL,
  0, 
  NULL,
  0
};

struct MenuItem item56=
{ &item57,
  0,60,
  40,10,
  ITEMTEXT|HIGHCOMP|ITEMENABLED|CHECKIT,
  0xffbf,
  (APTR)&text56,
  NULL,
  0, 
  NULL,
  0
};

struct MenuItem item55=
{ &item56,
  0,50,
  40,10,
  ITEMTEXT|HIGHCOMP|ITEMENABLED|CHECKIT,
  0xffdf,
  (APTR)&text55,
  NULL,
  0, 
  NULL,
  0
};

struct MenuItem item54=
{ &item55,
  0,40,
  40,10,
  ITEMTEXT|HIGHCOMP|ITEMENABLED|CHECKIT,
  0xffef,
  (APTR)&text54,
  NULL,
  0, 
  NULL,
  0
};

struct MenuItem item53=
{ &item54,
  0,30,
  40,10,
  ITEMTEXT|HIGHCOMP|ITEMENABLED|CHECKIT,
  0xfff7,
  (APTR)&text53,
  NULL,
  0, 
  NULL,
  0
};

struct MenuItem item52=
{ &item53,
  0,20,
  40,10,
  ITEMTEXT|HIGHCOMP|ITEMENABLED|CHECKIT,
  0xfffb,
  (APTR)&text52,
  NULL,
  0, 
  NULL,
  0
};

struct MenuItem item51=
{ &item52,
  0,10,
  40,10,
  ITEMTEXT|HIGHCOMP|ITEMENABLED|CHECKIT,
  0xfffd,
  (APTR)&text51,
  NULL,
  0, 
  NULL,
  0
};

struct MenuItem item50=
{ &item51,
  0,0,
  40,10,
  ITEMTEXT|HIGHCOMP|ITEMENABLED|CHECKIT,
  0xfffe,
  (APTR)&text50,
  NULL,
  0, 
  NULL,
  0
};


struct MenuItem item41=
{ NULL,
  0,10,
  80,10,
  ITEMTEXT|HIGHCOMP|ITEMENABLED|CHECKIT|COMMSEQ,
  0xfffd,
  (APTR)&text41,
  NULL,
  'g', 
  NULL,
  0
};

struct MenuItem item40=
{ &item41,
  0,0,
  80,10,
  ITEMTEXT|HIGHCOMP|ITEMENABLED|CHECKIT|CHECKED|COMMSEQ,
  0xfffe,
  (APTR)&text40,
  NULL,
  'z', 
  NULL,
  0
};


struct MenuItem item31=
{ NULL,
  0,10,
  112,10,
  ITEMTEXT|HIGHCOMP|ITEMENABLED|CHECKIT|COMMSEQ,
  0xfffd,
  (APTR)&text31,
  NULL,
  'b', 
  NULL,
  0
};

struct MenuItem item30=
{ &item31,
  0,0,
  112,10,
  ITEMTEXT|HIGHCOMP|ITEMENABLED|CHECKIT|CHECKED|COMMSEQ,
  0xfffe,
  (APTR)&text30,
  NULL,
  'a', 
  NULL,
  0
};


struct MenuItem item22=
{ NULL,
  0,20,
  120,10,
  ITEMTEXT|HIGHCOMP|ITEMENABLED|CHECKIT|COMMSEQ,
  0xfffb,
  (APTR)&text22,
  NULL,
  '3', 
  NULL,
  0
};

struct MenuItem item21=
{ &item22,
  0,10,
  120,10,
  ITEMTEXT|HIGHCOMP|ITEMENABLED|CHECKIT|COMMSEQ,
  0xfffd,
  (APTR)&text21,
  NULL,
  '3', 
  NULL,
  0
};


struct MenuItem item20=
{ &item21,
  0,0,
  120,10,
  ITEMTEXT|HIGHCOMP|ITEMENABLED|CHECKIT|CHECKED|COMMSEQ,
  0xfffe,
  (APTR)&text20,
  NULL,
  '2', 
  NULL,
  0
};


struct MenuItem item15=
{ NULL,
  0,50,
  176,10,
  ITEMTEXT|HIGHCOMP|ITEMENABLED|COMMSEQ,
  0,
  (APTR)&text15,
  NULL,
  'x',
  NULL,
  0
};

struct MenuItem item14=
{ &item15,
  0,40,
  176,10,
  ITEMTEXT|HIGHCOMP|ITEMENABLED|COMMSEQ,
  0,
  (APTR)&text14,
  NULL,
  't',
  NULL,
  0
};

struct MenuItem item13=
{ &item14,
  0,30,
  176,10,
  ITEMTEXT|HIGHCOMP|ITEMENABLED,
  0,
  (APTR)&text13,
  NULL,
  0,
  NULL,
  0
};

struct MenuItem item12=
{ &item13,
  0,20,
  176,10,
  ITEMTEXT|HIGHCOMP|ITEMENABLED,
  0,
  (APTR)&text12,
  NULL,
  0,
  NULL,
  0
};

struct MenuItem item11=
{ &item12,
  0,10,
  176,10,
  ITEMTEXT|HIGHCOMP|ITEMENABLED|COMMSEQ,
  0,
  (APTR)&text11,
  NULL,
  's',
  NULL,
  0
};
	
struct MenuItem item10=
{ &item11,
  0,0,
  176,10,
  ITEMTEXT|HIGHCOMP|ITEMENABLED|COMMSEQ,
  0,
  (APTR)&text10,
  NULL,
  'r',
  NULL,
  0
};

struct MenuItem item03=
{ NULL,
  0,30,
  160,10,
  ITEMTEXT|HIGHNONE|ITEMENABLED,
  0,
  (APTR)&text03,
  NULL,
  0,
  NULL,
  0
};

struct MenuItem item02=
{ &item03,
  0,20,
  160,10,
  ITEMTEXT|HIGHNONE|ITEMENABLED,
  0,
  (APTR)&text02,
  NULL,
  0,
  NULL,
  0
};

struct MenuItem item01=
{ &item02,
  0,10,
  160,10,
  ITEMTEXT|HIGHNONE|ITEMENABLED,
  0,
  (APTR)&text01,
  NULL,
  0,
  NULL,
  0
};

struct MenuItem item00=
{ &item01,
  0,0,
  160,10,
  ITEMTEXT|HIGHNONE|ITEMENABLED,
  0,
  (APTR)&text00,
  NULL,
  0,
  NULL,
  0
};


struct Menu menu5=
{ NULL,
  448,0,
  80,0,
  MENUENABLED,
  "Threshold",
  &item50
};

struct Menu menu4=
{ &menu5,
  336,0,
  88,8,
  MENUENABLED,
  "Gray Scale",
  &item40
};

struct Menu menu3=
{ &menu4,
  256,0,
  40,8,
  MENUENABLED,
  "Size",
  &item30
};

struct Menu menu2=
{ &menu3,
  160,0,
  88,8,
  MENUENABLED,
  "Resolution",
  &item20
};

struct Menu menu1=
{ &menu2,
  64,0,
  72,8,
  MENUENABLED,
  "Program",
  &item10
};

struct Menu menu0=
{ &menu1,
  0,0,
  40,8,
  MENUENABLED,
  "Info",
  &item00
};

/* Program Code */

/* Call of the Heath File Requester */

USHORT filerequest(char *titel)
{
struct Process	*OurTask;
struct Window	*old_pr_WindowPtr;

    OurTask = (struct Process *)FindTask((char *)0L);
    old_pr_WindowPtr = OurTask->pr_WindowPtr;
    OurTask->pr_WindowPtr = win;

    if (get_fname(win,win->WScreen,"Choose File",def_name,def_dir)==NULL)
    { OurTask->pr_WindowPtr = old_pr_WindowPtr;
      return(0);
    }
    else
    {
      OurTask->pr_WindowPtr = old_pr_WindowPtr;
      strcpy(str_filenam,def_dir);
      rfnam(str_filenam,def_name);
      return(1);
    }
} 


void MessReq(UBYTE *string)
{  ULONG dummy;
   text_na.IText=string;
   dummy=(ULONG)AutoRequest(win,&text_na,NULL,&text_aha,NULL,NULL,400L,60L);
}

void NotAvailable()
{  MessReq((UBYTE *)"Funktion not available!");
}

UBYTE DoScsi(UBYTE *cmd, UWORD cmdlen, UWORD *data, ULONG datalen, UBYTE flags)
{ struct SCSICmd scmd;
  scmd.scsi_Command=cmd;
  scmd.scsi_CmdLength=cmdlen;
  scmd.scsi_Data=data;
  scmd.scsi_Length=datalen;
  scmd.scsi_Flags=flags;
  diskreq->io_Length = sizeof(struct SCSICmd);
  diskreq->io_Data = &scmd;
  diskreq->io_Command = 28;
  DoIO(diskreq);
  return(scmd.scsi_Status);
}


void inquiry()
{ UBYTE string[96],inq_txt[45];

  DoScsi(&cmd_inqu,6,(UWORD *)&string,96,DIR_READ);
  strncpy(&inq_txt[0],&string[8],41);
  MessReq(&inq_txt[0]);
}

void p64to16(UBYTE *ptr, UWORD size)
{ UBYTE *p1,*p2;
  UWORD i;

  cnt=size;
  p0=ptr;
#asm
	movem.l	d0-d7/a0-a6,-(a7)
	move.w	_cnt,d7
	subq.w	#1,d7
	move.l	_p0,a0
	move.l	_p0,a1
slp:	move.w	(a0)+,d0
	lsr.w	#2,d0
	lsl.b	#4,d0
	lsr.w	#4,d0
	move.b	d0,(a1)+
	dbra	d7,slp
	movem.l (a7)+,d0-d7/a0-a6
#endasm
}

void clrscr(UBYTE *pl0, UBYTE *pl1, UBYTE *pl2, UBYTE *pl3)
{ p1=pl0; p2=pl1; p3=pl2; p4=pl3;
#asm
	movem.l	d5-d7/a0-a6,-(a7)
	move.l	_p1,a1
	move.l	_p2,a2
	move.l	_p3,a3
	move.l	_p4,a4
	move.w	#469,d5
clrlp0:	move.w	#38,d7
clrlp1:	clr.w	(a1)+
	clr.w	(a2)+
	clr.w	(a3)+
	clr.w	(a4)+
	dbra	d7,clrlp1
	lea.l	2(a1),a1
	lea.l	2(a2),a2
	lea.l	2(a3),a3
	lea.l	2(a4),a4
	dbra	d5,clrlp0
	movem.l	(a7)+,d5-d7/a0-a6
#endasm
}

void bwview(UBYTE *vp, UBYTE *pl0, UBYTE *pl1, UBYTE *pl2, UBYTE *pl3, ULONG vinc) 
{ p0=vp; p1=pl0; p2=pl1; p3=pl2; p4=pl3; v1=vinc;
#asm
	movem.l	d5-d7/a0-a6,-(a7)
	move.l	_p0,a0
	move.l	_p1,a1
	move.l	_p2,a2
	move.l	_p3,a3
	move.l	_p4,a4
	move.l	_v1,a5
	move.w	#469,d5
bwlp0:	move.l	a0,a6
	move.w	#38,d7
bwlp1:	move.w	(a6)+,d6
	move.w	d6,(a1)+
	clr.w	(a2)+
	clr.w	(a3)+
	clr.w	(a4)+
	dbra	d7,bwlp1
	lea.l	2(a1),a1
	lea.l	2(a2),a2
	lea.l	2(a3),a3
	lea.l	2(a4),a4
	adda.l	a5,a0
	dbra	d5,bwlp0
	movem.l	(a7)+,d5-d7/a0-a6
#endasm
}

void grayview(UBYTE *vp, UBYTE *pl0, UBYTE *pl1, UBYTE *pl2, UBYTE *pl3, ULONG vinc) 
{ p0=vp; p1=pl0; p2=pl1; p3=pl2; p4=pl3; v1=vinc;
#asm
	movem.l	d0-d7/a0-a6,-(a7)
	move.l	_p0,a0
	move.l	_p1,a1
	move.l	_p2,a2
	move.l	_p3,a3
	move.l	_p4,a4
	move.l	_v1,a5
	move.l  #$10000000,d6
	move.w	#469,d5
grlp0:	move.l	a0,a6
	move.w	#77,d7
grlp1:	move.l	(a6)+,d0
	add.l	d6,d0
	lsl.l	#1,d0
	roxl.b	#1,d4
	lsl.l	#1,d0
	roxl.b	#1,d3
	lsl.l	#1,d0
	roxl.b	#1,d2
	lsl.l	#1,d0
	roxl.b	#1,d1
	add.l	d6,d0
	lsl.l	#1,d0
	roxl.b	#1,d4
	lsl.l	#1,d0
	roxl.b	#1,d3
	lsl.l	#1,d0
	roxl.b	#1,d2
	lsl.l	#1,d0
	roxl.b	#1,d1
	add.l	d6,d0
	lsl.l	#1,d0
	roxl.b	#1,d4
	lsl.l	#1,d0
	roxl.b	#1,d3
	lsl.l	#1,d0
	roxl.b	#1,d2
	lsl.l	#1,d0
	roxl.b	#1,d1
	add.l	d6,d0
	lsl.l	#1,d0
	roxl.b	#1,d4
	lsl.l	#1,d0
	roxl.b	#1,d3
	lsl.l	#1,d0
	roxl.b	#1,d2
	lsl.l	#1,d0
	roxl.b	#1,d1
	add.l	d6,d0
	lsl.l	#1,d0
	roxl.b	#1,d4
	lsl.l	#1,d0
	roxl.b	#1,d3
	lsl.l	#1,d0
	roxl.b	#1,d2
	lsl.l	#1,d0
	roxl.b	#1,d1
	add.l	d6,d0
	lsl.l	#1,d0
	roxl.b	#1,d4
	lsl.l	#1,d0
	roxl.b	#1,d3
	lsl.l	#1,d0
	roxl.b	#1,d2
	lsl.l	#1,d0
	roxl.b	#1,d1
	add.l	d6,d0
	lsl.l	#1,d0
	roxl.b	#1,d4
	lsl.l	#1,d0
	roxl.b	#1,d3
	lsl.l	#1,d0
	roxl.b	#1,d2
	lsl.l	#1,d0
	roxl.b	#1,d1
	add.l	d6,d0
	lsl.l	#1,d0
	roxl.b	#1,d4
	lsl.l	#1,d0
	roxl.b	#1,d3
	lsl.l	#1,d0
	roxl.b	#1,d2
	lsl.l	#1,d0
	roxl.b	#1,d1
	move.b	d1,(a1)+
	move.b	d2,(a2)+
	move.b	d3,(a3)+
	move.b	d4,(a4)+
	dbra	d7,grlp1
	lea.l	2(a1),a1
	lea.l	2(a2),a2
	lea.l	2(a3),a3
	lea.l	2(a4),a4
	adda.l	a5,a0
	dbra	d5,grlp0
	movem.l	(a7)+,d0-d7/a0-a6
#endasm
}

void vplanesep(UBYTE *vp, UBYTE *pl0, UBYTE *pl1, UBYTE *pl2, UBYTE *pl3, UWORD count) 
{ p0=vp; p1=pl0; p2=pl1; p3=pl2; p4=pl3; cnt=count;
#asm
	movem.l	d0-d7/a0-a6,-(a7)
	move.w	_cnt,d7
	move.l	_p0,a0
	move.l	_p1,a1
	move.l	_p2,a2
	move.l	_p3,a3
	move.l	_p4,a4
	move.l  #$10000000,d6
 	subq.w	#1,d7
vplp:	move.l	(a0)+,d0
	add.l	d6,d0
	lsl.l	#1,d0
	roxl.b	#1,d4
	lsl.l	#1,d0
	roxl.b	#1,d3
	lsl.l	#1,d0
	roxl.b	#1,d2
	lsl.l	#1,d0
	roxl.b	#1,d1
	add.l	d6,d0
	lsl.l	#1,d0
	roxl.b	#1,d4
	lsl.l	#1,d0
	roxl.b	#1,d3
	lsl.l	#1,d0
	roxl.b	#1,d2
	lsl.l	#1,d0
	roxl.b	#1,d1
	add.l	d6,d0
	lsl.l	#1,d0
	roxl.b	#1,d4
	lsl.l	#1,d0
	roxl.b	#1,d3
	lsl.l	#1,d0
	roxl.b	#1,d2
	lsl.l	#1,d0
	roxl.b	#1,d1
	add.l	d6,d0
	lsl.l	#1,d0
	roxl.b	#1,d4
	lsl.l	#1,d0
	roxl.b	#1,d3
	lsl.l	#1,d0
	roxl.b	#1,d2
	lsl.l	#1,d0
	roxl.b	#1,d1
	add.l	d6,d0
	lsl.l	#1,d0
	roxl.b	#1,d4
	lsl.l	#1,d0
	roxl.b	#1,d3
	lsl.l	#1,d0
	roxl.b	#1,d2
	lsl.l	#1,d0
	roxl.b	#1,d1
	add.l	d6,d0
	lsl.l	#1,d0
	roxl.b	#1,d4
	lsl.l	#1,d0
	roxl.b	#1,d3
	lsl.l	#1,d0
	roxl.b	#1,d2
	lsl.l	#1,d0
	roxl.b	#1,d1
	add.l	d6,d0
	lsl.l	#1,d0
	roxl.b	#1,d4
	lsl.l	#1,d0
	roxl.b	#1,d3
	lsl.l	#1,d0
	roxl.b	#1,d2
	lsl.l	#1,d0
	roxl.b	#1,d1
	add.l	d6,d0
	lsl.l	#1,d0
	roxl.b	#1,d4
	lsl.l	#1,d0
	roxl.b	#1,d3
	lsl.l	#1,d0
	roxl.b	#1,d2
	lsl.l	#1,d0
	roxl.b	#1,d1
	move.b	d1,(a1)+
	move.b	d2,(a2)+
	move.b	d3,(a3)+
	move.b	d4,(a4)+
	dbra	d7,vplp
	movem.l	(a7)+,d0-d7/a0-a6
#endasm
}

void fplanesep(UBYTE *vp, UBYTE *pl0, UBYTE *pl1, UBYTE *pl2, UBYTE *pl3, UWORD count) 
{ p0=vp; p1=pl0; p2=pl1; p3=pl2; p4=pl3; cnt=count;
#asm
	movem.l	d0-d7/a0-a6,-(a7)
	move.w	_cnt,d7
	move.l	_p0,a0
	move.l	_p1,a1
	move.l	_p2,a2
	move.l	_p3,a3
	move.l	_p4,a4
 	subq.w	#1,d7
fplp:	move.l	(a0)+,d0
	lsl.l	#1,d0
	roxl.b	#1,d4
	lsl.l	#1,d0
	roxl.b	#1,d3
	lsl.l	#1,d0
	roxl.b	#1,d2
	lsl.l	#1,d0
	roxl.b	#1,d1
	lsl.l	#1,d0
	roxl.b	#1,d4
	lsl.l	#1,d0
	roxl.b	#1,d3
	lsl.l	#1,d0
	roxl.b	#1,d2
	lsl.l	#1,d0
	roxl.b	#1,d1
	lsl.l	#1,d0
	roxl.b	#1,d4
	lsl.l	#1,d0
	roxl.b	#1,d3
	lsl.l	#1,d0
	roxl.b	#1,d2
	lsl.l	#1,d0
	roxl.b	#1,d1
	lsl.l	#1,d0
	roxl.b	#1,d4
	lsl.l	#1,d0
	roxl.b	#1,d3
	lsl.l	#1,d0
	roxl.b	#1,d2
	lsl.l	#1,d0
	roxl.b	#1,d1
	lsl.l	#1,d0
	roxl.b	#1,d4
	lsl.l	#1,d0
	roxl.b	#1,d3
	lsl.l	#1,d0
	roxl.b	#1,d2
	lsl.l	#1,d0
	roxl.b	#1,d1
	lsl.l	#1,d0
	roxl.b	#1,d4
	lsl.l	#1,d0
	roxl.b	#1,d3
	lsl.l	#1,d0
	roxl.b	#1,d2
	lsl.l	#1,d0
	roxl.b	#1,d1
	lsl.l	#1,d0
	roxl.b	#1,d4
	lsl.l	#1,d0
	roxl.b	#1,d3
	lsl.l	#1,d0
	roxl.b	#1,d2
	lsl.l	#1,d0
	roxl.b	#1,d1
	lsl.l	#1,d0
	roxl.b	#1,d4
	lsl.l	#1,d0
	roxl.b	#1,d3
	lsl.l	#1,d0
	roxl.b	#1,d2
	lsl.l	#1,d0
	roxl.b	#1,d1
	not.b	d1
	not.b	d2
	not.b	d3
	not.b	d4
	move.b	d1,(a1)+
	move.b	d2,(a2)+
	move.b	d3,(a3)+
	move.b	d4,(a4)+
	dbra	d7,fplp
	movem.l	(a7)+,d0-d7/a0-a6
#endasm
}

void scan()
{ ULONG memsize,blsize;
  short tabindex,blocks,rest,i,glin,rlin;
  UBYTE *rdptr;

  if (memptr) free(memptr);
  memneed=0;
  tabindex=((winpar.resx/100)-2)+(winpar.size-4)*3;
  winpar.cornerx=cornerxval[tabindex];
  winpar.cornery=corneryval[tabindex];
  winpar.width=widthval[tabindex];
  winpar.height=heightval[tabindex];
  memsize=(winpar.halftone)?((ULONG)winpar.width*(ULONG)winpar.height)>>1:
                            ((ULONG)winpar.width*(ULONG)winpar.height)>>3;
  if ((memptr=(UBYTE*)malloc(memsize))==NULL) 
    MessReq((UBYTE*)"Nicht genug Speicher für diese Einstellung!");
  else 
  { memneed=memsize;
    memwidth=winpar.width;
    memheight=winpar.height;
    memgray=winpar.halftone;
    rdptr=memptr;
    if (!(winpar.halftone))
    { DoScsi(&cmd_mdon,6,NULL,0,0);
      Delay(100);
      DoScsi(&cmd_dwin,10,&winpar,40,DIR_WRITE);
      DoScsi(&cmd_scan,6,NULL,0,0);
      blocks=memsize/0x8000;
      rest=memsize%0x8000;
      cmd_read[7]=128; cmd_read[8]=0;
      for (i=0;i<blocks;i++) 
      { DoScsi(&cmd_read,10,rdptr,0x8000,DIR_READ);
        rdptr+=0x8000;
      }
      cmd_read[7]=(rest>>8)&0xff; cmd_read[8]=rest&0xff;
      DoScsi(&cmd_read,10,rdptr,rest,DIR_READ);
      rdptr+=rest;
    }
    else
    { glin=winpar.height;
      rlin=0x200000L/(ULONG)winpar.width; 
      do 
      { if (rlin>glin) rlin=glin;
        winpar.height=rlin;
        glin-=rlin;
        DoScsi(&cmd_mdon,6,NULL,0,0);
        Delay(100);
        DoScsi(&cmd_dwin,10,&winpar,40,DIR_WRITE);
        DoScsi(&cmd_scan,6,NULL,0,0);
	winpar.cornery+=rlin;
        blsize=((ULONG)winpar.height*(ULONG)winpar.width)>>1;
        blocks=blsize/0x4000;
        rest=blsize%0x4000;
        cmd_read[7]=128; cmd_read[8]=0;
        for (i=0;i<blocks;i++) 
        { DoScsi(&cmd_read,10,rdptr,0x8000,DIR_READ);
          p64to16(rdptr,0x4000);
          rdptr+=0x4000;
        }
        cmd_read[7]=(rest>>7)&0xff; cmd_read[8]=(rest<<1)&0xff;
        DoScsi(&cmd_read,10,rdptr,rest<<1,DIR_READ);
        p64to16(rdptr,rest);
	rdptr+=rest;
      } while (glin);
    }
    DoScsi(&cmd_mdoff,6,NULL,0,0); 
  }
}  
    
void view(UWORD x, UWORD y, UBYTE zoom)
{ UBYTE *vptr;
  UBYTE *plptr[4];
  ULONG vinc;
  ULONG vicr[13];
  UWORD i,j,k,n1,n2,zeile;
  UBYTE linebuf[1000];

  for (i=0;i<4;i++) plptr[i]=(UBYTE *)(rp->BitMap->Planes[i]+1680);
  vptr=(memgray)?
       (UBYTE*)(memptr+(((memwidth>>1)*y)+(x>>1))):
       (UBYTE*)(memptr+(((memwidth>>3)*y)+(x>>3)));
  vinc=(memgray)?(ULONG)(memwidth>>1):(ULONG)(memwidth>>3);
  if (zoom)
  { if ((memheight/4)<470) sk=4;
    else if ((memheight/8)<470) sk=8;
    else if ((memheight/12)<470) sk=12;
    vptr=memptr;
    vicr[0]=0; vicr[1]=vinc;
    for (i=2;i<13;i++) vicr[i]=vicr[i-1]+vinc;
    clrscr(plptr[0],plptr[1],plptr[2],plptr[3]);
    zeile=0; vx=vy=0;
    if (memgray)
    switch (sk)
    { case 4: while(zeile<memheight)
              { zeile+=4;
                for (i=0;i<(memwidth>>1);i+=4)
                { n1=n2=0; j=i;
                  for (k=0;k<4;k++)
                  { n1+=((*(vptr+j  )>>4)+(*(vptr+j  )&15)+(*(vptr+j+1)>>4)+(*(vptr+j+1)&15));
                    n2+=((*(vptr+j+2)>>4)+(*(vptr+j+2)&15)+(*(vptr+j+3)>>4)+(*(vptr+j+3)&15));
                    j+=vinc;
                  }
                  linebuf[i>>2]=(n1&0xf0)|(n2>>4);
                }
                vplanesep(&linebuf[0],plptr[0],plptr[1],plptr[2],plptr[3],memwidth>>5);
                plptr[0]+=80; plptr[1]+=80; plptr[2]+=80; plptr[3]+=80;
                vptr+=vicr[4];
              } 
              break;
      case 8: while(zeile<memheight)
              { zeile+=8;
                for (i=0;i<(memwidth>>1);i+=8)
                { n1=n2=0; j=i;
                  for (k=0;k<8;k++)
                  { n1+=((*(vptr+j  )>>4)+(*(vptr+j  )&15)+(*(vptr+j+1)>>4)+(*(vptr+j+1)&15)
                        +(*(vptr+j+2)>>4)+(*(vptr+j+2)&15)+(*(vptr+j+3)>>4)+(*(vptr+j+3)&15));
                    n2+=((*(vptr+j+4)>>4)+(*(vptr+j+4)&15)+(*(vptr+j+5)>>4)+(*(vptr+j+5)&15)
                        +(*(vptr+j+6)>>4)+(*(vptr+j+6)&15)+(*(vptr+j+7)>>4)+(*(vptr+j+7)&15));
                    j+=vinc;
                  }
                  linebuf[i>>3]=((n1>>2)&0xf0)|((n2>>6)&0x0f);
                }
                vplanesep(&linebuf[0],plptr[0],plptr[1],plptr[2],plptr[3],memwidth>>6);
                plptr[0]+=80; plptr[1]+=80; plptr[2]+=80; plptr[3]+=80;
                vptr+=vicr[8];
              } 
              break;
      case 12:while(zeile<memheight)
              { zeile+=12;
                for (i=0;i<(memwidth>>1);i+=12)
                { n1=n2=0; j=i;
                  for (k=0;k<12;k++)
                  { n1+=((*(vptr+j   )>>4)+(*(vptr+j   )&15)+(*(vptr+j+ 1)>>4)+(*(vptr+j+ 1)&15)
                        +(*(vptr+j+ 2)>>4)+(*(vptr+j+ 2)&15)+(*(vptr+j+ 3)>>4)+(*(vptr+j+ 3)&15)
                        +(*(vptr+j+ 4)>>4)+(*(vptr+j+ 4)&15)+(*(vptr+j+ 5)>>4)+(*(vptr+j+ 5)&15));
                    n2+=((*(vptr+j+ 6)>>4)+(*(vptr+j+ 6)&15)+(*(vptr+j+ 7)>>4)+(*(vptr+j+ 7)&15)
                        +(*(vptr+j+ 8)>>4)+(*(vptr+j+ 8)&15)+(*(vptr+j+ 9)>>4)+(*(vptr+j+ 9)&15)
                        +(*(vptr+j+10)>>4)+(*(vptr+j+10)&15)+(*(vptr+j+11)>>4)+(*(vptr+j+11)&15));
                    j+=vinc;
                  }
                  linebuf[i/12]=(((n1/144)<<4)&0xf0)|((n2/144)&0x0f);
                }
                vplanesep(&linebuf[0],plptr[0],plptr[1],plptr[2],plptr[3],memwidth/96);
                plptr[0]+=80; plptr[1]+=80; plptr[2]+=80; plptr[3]+=80;
                vptr+=vicr[12];
              } 
              break;
    }
    else
    switch (sk)
    { case 4: while(zeile<memheight)
              { zeile+=4;
                for (i=0;i<(memwidth>>3);i++)
                { n1=numbits[(*(vptr+i        ))>>4]+numbits[(*(vptr+i+vicr[1]))>>4]
                    +numbits[(*(vptr+i+vicr[2]))>>4]+numbits[(*(vptr+i+vicr[3]))>>4];
                  if (n1==16) n1=15;
                  n2=numbits[(*(vptr+i        ))&15]+numbits[(*(vptr+i+vicr[1]))&15]
                    +numbits[(*(vptr+i+vicr[2]))&15]+numbits[(*(vptr+i+vicr[3]))&15];
                  if (n2==16) n2=15;
                  linebuf[i]=(~((n1<<4)|n2));
                }
                vplanesep(&linebuf[0],plptr[0],plptr[1],plptr[2],plptr[3],memwidth>>5);
                plptr[0]+=80; plptr[1]+=80; plptr[2]+=80; plptr[3]+=80;
                vptr+=vicr[4];
              } 
              break;
      case 8: while(zeile<memheight)
              { zeile+=8;
                for (i=0;i<(memwidth>>3);i+=2)
                { n1=(numbits[(*(vptr+i        ))]
                     +numbits[(*(vptr+i+vicr[1]))]
                     +numbits[(*(vptr+i+vicr[2]))]
                     +numbits[(*(vptr+i+vicr[3]))]
                     +numbits[(*(vptr+i+vicr[4]))]
                     +numbits[(*(vptr+i+vicr[5]))]
                     +numbits[(*(vptr+i+vicr[6]))]
                     +numbits[(*(vptr+i+vicr[7]))])>>2;
                  if (n1==16) n1=15;
                  n2=(numbits[(*(vptr+i+1        ))]
                     +numbits[(*(vptr+i+1+vicr[1]))]
                     +numbits[(*(vptr+i+1+vicr[2]))]
                     +numbits[(*(vptr+i+1+vicr[3]))]
                     +numbits[(*(vptr+i+1+vicr[4]))]
                     +numbits[(*(vptr+i+1+vicr[5]))]
                     +numbits[(*(vptr+i+1+vicr[6]))]
                     +numbits[(*(vptr+i+1+vicr[7]))])>>2;
                  if (n2==16) n2=15;
                  linebuf[i>>1]=(~((n1<<4)|n2));
                }
                vplanesep(&linebuf[0],plptr[0],plptr[1],plptr[2],plptr[3],memwidth>>6);
                plptr[0]+=80; plptr[1]+=80; plptr[2]+=80; plptr[3]+=80;
                vptr+=vicr[8];
              } 
              break;
      case 12:while(zeile<memheight)
              { zeile+=12;
                for (i=0;i<(memwidth>>3);i+=3)
                { n1=(numbits[(*(vptr+i           ))]
                     +numbits[(*(vptr+i+  vicr[ 1]))]
                     +numbits[(*(vptr+i+  vicr[ 2]))]
                     +numbits[(*(vptr+i+  vicr[ 3]))]
                     +numbits[(*(vptr+i+  vicr[ 4]))]
                     +numbits[(*(vptr+i+  vicr[ 5]))]
                     +numbits[(*(vptr+i+  vicr[ 6]))]
                     +numbits[(*(vptr+i+  vicr[ 7]))]
                     +numbits[(*(vptr+i+  vicr[ 8]))]
                     +numbits[(*(vptr+i+  vicr[ 9]))]
                     +numbits[(*(vptr+i+  vicr[10]))]
                     +numbits[(*(vptr+i+  vicr[11]))]
                     +numbits[(*(vptr+i+1         ))>>4]
                     +numbits[(*(vptr+i+1+vicr[ 1]))>>4]
                     +numbits[(*(vptr+i+1+vicr[ 2]))>>4]
                     +numbits[(*(vptr+i+1+vicr[ 3]))>>4]
                     +numbits[(*(vptr+i+1+vicr[ 4]))>>4]
                     +numbits[(*(vptr+i+1+vicr[ 5]))>>4]
                     +numbits[(*(vptr+i+1+vicr[ 6]))>>4]
                     +numbits[(*(vptr+i+1+vicr[ 7]))>>4]
                     +numbits[(*(vptr+i+1+vicr[ 8]))>>4]
                     +numbits[(*(vptr+i+1+vicr[ 9]))>>4]
                     +numbits[(*(vptr+i+1+vicr[10]))>>4]
                     +numbits[(*(vptr+i+1+vicr[11]))>>4]);
                  n2=(numbits[(*(vptr+i+2         ))]
                     +numbits[(*(vptr+i+2+vicr[ 1]))]
                     +numbits[(*(vptr+i+2+vicr[ 2]))]
                     +numbits[(*(vptr+i+2+vicr[ 3]))]
                     +numbits[(*(vptr+i+2+vicr[ 4]))]
                     +numbits[(*(vptr+i+2+vicr[ 5]))]
                     +numbits[(*(vptr+i+2+vicr[ 6]))]
                     +numbits[(*(vptr+i+2+vicr[ 7]))]
                     +numbits[(*(vptr+i+2+vicr[ 8]))]
                     +numbits[(*(vptr+i+2+vicr[ 9]))]
                     +numbits[(*(vptr+i+2+vicr[10]))]
                     +numbits[(*(vptr+i+2+vicr[11]))]
                     +numbits[(*(vptr+i+1         ))&15]
                     +numbits[(*(vptr+i+1+vicr[ 1]))&15]
                     +numbits[(*(vptr+i+1+vicr[ 2]))&15]
                     +numbits[(*(vptr+i+1+vicr[ 3]))&15]
                     +numbits[(*(vptr+i+1+vicr[ 4]))&15]
                     +numbits[(*(vptr+i+1+vicr[ 5]))&15]
                     +numbits[(*(vptr+i+1+vicr[ 6]))&15]
                     +numbits[(*(vptr+i+1+vicr[ 7]))&15]
                     +numbits[(*(vptr+i+1+vicr[ 8]))&15]
                     +numbits[(*(vptr+i+1+vicr[ 9]))&15]
                     +numbits[(*(vptr+i+1+vicr[10]))&15]
                     +numbits[(*(vptr+i+1+vicr[11]))&15]);
                  n1=n1/9;
                  n2=n2/9;
                  if (n1==16) n1=15;
                  if (n2==16) n2=15;
                  linebuf[i/3]=(~((n1<<4)|n2));
                }
                vplanesep(&linebuf[0],plptr[0],plptr[1],plptr[2],plptr[3],memwidth/96);
                plptr[0]+=80; plptr[1]+=80; plptr[2]+=80; plptr[3]+=80;
                vptr+=vicr[12];
              } 
              break;
    }    
  }
  else
  { vx=x&0xfff0; vy=y&0xfffe; sk=1;
    if (memgray) grayview(vptr,plptr[0],plptr[1],plptr[2],plptr[3],vinc); 
    else bwview(vptr,plptr[0],plptr[1],plptr[2],plptr[3],vinc); 
  } 
}

UWORD s2px(UWORD x)
{ int t;
  t=x*sk+vx;
  if (t>=memwidth) t=memwidth-1;
  if (t<0) t=0;
  return((UWORD)t);
}

UWORD s2py(UWORD y)
{ int t;
  t=y*sk+vy;
  if (t>=memheight) t=memheight-1;
  if (t<0) t=0;
  return((UWORD)t);
}

UWORD p2sx(UWORD x)
{ int t;
  t=(x-vx)/sk;
  if (t>=624) t=623;
  if (t<0) t=0;
  return((UWORD)t);
}

UWORD p2sy(UWORD y)
{ int t;
  t=(y-vy)/sk;
  if (t>=470) t=469;
  if (t<0) t=0;
  return((UWORD)t);
}

void drawbox()
{ struct RastPort *wrp;
  int a,b,c,d;
  
  a=p2sx(wx1); b=p2sy(wy1)+10;
  c=p2sx(wx2); d=p2sy(wy2)+10; 
  { 
    wrp=win->RPort;
    SetWrMsk(wrp,8);
    SetAPen(wrp,8);
    SetDrMd(wrp,COMPLEMENT|JAM1);
    SetDrPt(wrp,0xcccc);
    Move(wrp,a,b);
    Draw(wrp,a,d);
    Draw(wrp,c,d);
    Draw(wrp,c,b);
    Draw(wrp,a,b);
    SetWrMsk(wrp,1);
    SetAPen(wrp,1);
    SetDrMd(wrp,COMPLEMENT|JAM1);
    SetDrPt(wrp,0x3333);
    Move(wrp,a,b);
    Draw(wrp,a,d);
    Draw(wrp,c,d);
    Draw(wrp,c,b);
    Draw(wrp,a,b);
    SetWrMsk(wrp,15);
  }
}

void save()
{ int qdatei;
  ULONG totlen,bmlen;
  UWORD width,height,i,t;
  ULONG startofs;
  UBYTE *saveptr;
  UBYTE planes[4000];
  UBYTE sf;

  sf=(memgray)?1:3;
  if (mf==2)
  { if (wx1>wx2) {t=wx2; wx2=wx1; wx1=t;}
    if (wy1>wy2) {t=wy2; wy2=wy1; wy1=t;}
    width=(wx2-wx1);
    height=(wy2-wy1);
    startofs=wy1*(memwidth>>sf)+(wx1>>sf);
  }
  else 
  { width=memwidth;
    height=memheight;
    startofs=0;
  }

  filerequest("IFF File");
  qdatei=creat(str_filenam,1);
  bmlen=(memgray)?(width*height>>1):(width*height>>3);
  totlen=bmlen+40+((memgray)?56:14);
  iff_head[1]=totlen; 
  iff_head[5]=(width<<16)|height;
  iff_head[7]=(memgray)?0x04000000:0x01000000;
  iff_body[1]=bmlen;
  write(qdatei,&iff_head[0],sizeof(iff_head));
  if (memgray) write(qdatei,iff_cmap_gray,sizeof(iff_cmap_gray));
  else write(qdatei,iff_cmap_bw,sizeof(iff_cmap_bw));
  write(qdatei,iff_body,sizeof(iff_body));
  saveptr=memptr+startofs;
  if (memgray) for (i=0;i<height;i++)
  { fplanesep(saveptr,&planes[0],&planes[width>>3],&planes[2*(width>>3)],&planes[3*(width>>3)],(width>>3));
    write(qdatei,&planes[0],width>>1);
    saveptr+=(memwidth>>1);
  }
  else for (i=0;i<height;i++)
  { write(qdatei,saveptr,width>>3);
    saveptr+=(memwidth>>3);
  } 
  close(qdatei); 
}

void floyd()
{ signed short lbuf[2][4000];
  UBYTE *grptr,*bwptr;
  USHORT i,j;
  signed short f,g;
  char wtitel[20];

  g=(signed short)(winpar.threshold/4);
  for (i=0;i<4000;i++) lbuf[0][i]=lbuf[1][i]=0;
  grptr=bwptr=memptr;
  for (i=0;i<memheight;i++)
  { for (j=0;j<memwidth;j++)
    { if (j&1) lbuf[0][j]=(signed short)(  (*(grptr+(j>>1)))     &15)+lbuf[1][j];
      else     lbuf[0][j]=(signed short)(( (*(grptr+(j>>1))) >>4)&15)+lbuf[1][j];
    }
    for (j=0;j<(memwidth>>3);j++) *(bwptr+j)=0;
    for (j=0;j<memwidth;j++)
    { if (lbuf[0][j]<g) 
      { f=lbuf[0][j];
        *(bwptr+(j>>3))|=bitval[j&7];
      }
      else f=lbuf[0][j]-15;
      lbuf[1][j]=(f+f+f)/8;
      lbuf[1][j+1]=f-2*lbuf[1][j];
      lbuf[0][j+1]+=((f+f+f)/8);
    }
    grptr+=(memwidth>>1);
    bwptr+=(memwidth>>3);
    if (!(i%100)) 
    { sprintf(&wtitel,"Dithering %03d %%",i*100/memheight);
      SetWindowTitles(win,&wtitel[0],(UBYTE *)-1);
    }
  }
  memneed=(memwidth*memheight)>>3;
  memgray=0;
  if (!(memptr=(UBYTE *)realloc(memptr,memneed)))
  { memneed=0;
    MessReq((UBYTE *)"Nicht mehr genug Speicher da!");
  }
  SetWindowTitles(win,NULL,(UBYTE *)-1);
}

void ordered()
{ UBYTE *grptr,*bwptr;
  USHORT i,j;
  char wtitel[20];
  UBYTE refmat[4][4]={{0,7,2,9},{11,4,13,6},{3,10,1,8},{14,7,12,5}};
  UBYTE v;

  grptr=bwptr=memptr;
  for (i=0;i<memheight;i++)
  { for (j=0;j<memwidth;j++)
    { v=(j&1)?(  (*grptr)     &15)
             :(( (*grptr) >>4)&15);
      if (v>refmat[j&3][i&3]) *bwptr&=invbitval[j&7];
      else *bwptr|=bitval[j&7];
      if ((j&7)==7) bwptr++;
      if (j&1) grptr++;
    }
    if (!(i%100)) 
    { sprintf(&wtitel,"Dithering %03d %%",i*100/memheight);
      SetWindowTitles(win,&wtitel[0],(UBYTE *)-1);
    }
  }
  memneed=(memwidth*memheight)>>3;
  memgray=0;
  if (!(memptr=(UBYTE *)realloc(memptr,memneed)))
  { memneed=0;
    MessReq((UBYTE *)"Nicht mehr genug Speicher da!");
  }
  SetWindowTitles(win,NULL,(UBYTE *)-1);
}

void main()
{
    USHORT i; 
    USHORT nr;
    UWORD mx,my;
    
    if ((IntuitionBase = (struct IntuitionBase *)
         OpenLibrary("intuition.library",0L)) == 0L)
    {    ende();
         exit(100L);
    }
    if ((GfxBase = (struct GfxBase *)
         OpenLibrary("graphics.library",0L))==0L)
    {    ende();
         exit(100L);
    }
    if ((DosBase = (struct DosBase *)
         OpenLibrary("dos.library",0L))==0L)
    {    ende();
         exit(100L);
    } 
    if (!(imgptrf=AllocMem(sizeof(imagedataf),MEMF_CHIP)))
    {    ende();
         exit(85L);
    }
    if (!(imgptrz=AllocMem(sizeof(imagedataz),MEMF_CHIP)))
    {    ende();
         exit(85L);
    }
    memcpy(imgptrf,&imagedataf,sizeof(imagedataf));
    memcpy(imgptrz,&imagedataz,sizeof(imagedataz));
    fullimage.ImageData=(USHORT *)imgptrf;
    zoomimage.ImageData=(USHORT *)imgptrz;
    if (!(scr=(struct Screen*)OpenScreen(&ns)))
    {    ende();
         exit(90L);
    }
    vp=&scr->ViewPort;
    rp=&scr->RastPort;
    for (i=0;i<16;i++)
    { SetRGB4(vp,i,graystep[i],graystep[i],graystep[i]); }
    nw.Screen=scr;
    if (!(win=(struct Window *)OpenWindow(&nw)))
    {    ende();
         exit(90L);
    }
    if(!(diskport=CreatePort(0L,0L)))
    {    ende();
         exit(80L);
    }
    if(!(diskreq=(struct IOStdReq *)CreateStdIO(diskport)))
    {    ende();
         exit(80L);
    }
    if(openerror=OpenDevice(DEV_NAME,ST400ID,diskreq,0L))
    {    ende();
         exit(80L);
    }
  memptr=NULL; 
  mf=0;
  SetMenuStrip(win,&menu0);
  for (i=0;i<256;i++) numbits[i]=numbits_16[i/16]+numbits_16[i&15];
  for(;;)
  {
   Wait((long)(1L<<win->UserPort->mp_SigBit));
   while (Message=(struct IntuiMessage *)GetMsg(win->UserPort))
    {
      MessageClass=Message->Class;
      Code=Message->Code;
      ReplyMsg(Message);
      if (MessageClass==MENUPICK) menu(Code);
      if (((MessageClass==GADGETUP))&&(memneed))
      { if (!(Message->IAddress->GadgetID))
        { vprop.VertBody=(zgad.Flags&SELECTED)?0xffff:470*65536/memheight;
          hprop.HorizBody=(zgad.Flags&SELECTED)?0xffff:624*65536/memwidth;
          vprop.VertPot=0;
          hprop.HorizPot=0;
        }
        view(hprop.HorizPot*(memwidth-624)/65536,vprop.VertPot*(memheight-470)/65536,(zgad.Flags&SELECTED));
        if (mf==2) drawbox();
        RefreshGadgets(&vgad,win,NULL);
      }
      if ((MessageClass==MOUSEBUTTONS)&&(Code&128)&&(memneed))
      { mx=win->MouseX; my=win->MouseY;
        if ((mx<624)&&(my>=10)&&(my<470))
        switch(mf)
        { case 0: wx1=s2px(mx)&0xfff8; wy1=s2py(my-10); mf=1; break;
          case 1: wx2=s2px(mx)&0xfff8; wy2=s2py(my-10); mf=2; 
                  drawbox(); break;
          case 2: mf=0; drawbox(); break;
        }
      }
      if (MessageClass==CLOSEWINDOW)
      { ende();
        exit(0L);
      } /* if */
     } /* while */
   } /* for */
} /* main */

menu(Code)
USHORT Code;
{
  USHORT num,item,subitem;
  num=MENUNUM(Code);
  item=ITEMNUM(Code);
  subitem=SUBNUM(Code);
  switch(num)
  {  case 0: break;                    /* Info */
     case 1: switch(item)              /* Programm */
             { case 0: scan();         /* Einlesen */
                       vprop.VertBody=(zgad.Flags&SELECTED)?0xffff:470*65536/memheight;
                       hprop.HorizBody=(zgad.Flags&SELECTED)?0xffff:624*65536/memwidth;
                       vprop.VertPot=0;
                       hprop.HorizPot=0;
                       RefreshGadgets(&zgad,win,NULL);
                       if (memneed)
                       { view(0,0,(zgad.Flags&SELECTED));
                         mf=0;
                       }
                       break;
               case 1: save(); /* Speichern */
                       break;
               case 2: if ((memgray)&&(memneed))
                       { floyd(); /* Dither */
                         if (memneed) view(hprop.HorizPot*(memwidth-624)/65536,
                                           vprop.VertPot*(memheight-470)/65536,
                                           (zgad.Flags&SELECTED));
                         if (mf==2) drawbox();
                       }
                       break;
               case 3: if ((memgray)&&(memneed))
                       { ordered(); /* Dither */
                         if (memneed) view(hprop.HorizPot*(memwidth-624)/65536,
                                           vprop.VertPot*(memheight-470)/65536,
                                           (zgad.Flags&SELECTED));
                         if (mf==2) drawbox();
                       }
                       break;
               case 4: inquiry();
                       break;
               case 5: ende();         /* Ende */
                       exit(0L);
                       break;
               }
             break;
     case 2: winpar.resx=100*(item+2);
             winpar.resy=winpar.resx;
             break;
     case 3: winpar.size=5-item;
             break;
     case 4: winpar.halftone=item<<1;
             winpar.bitspixel=item ? 8 : 1;
             break;
     case 5: winpar.threshold=item<<2;
             break;
  }
}


ende() {
  if (memptr) free(memptr);
  if(openerror==0)
  { CloseDevice(diskreq);
  }
  if(diskport)DeletePort(diskport);
  if(diskreq)DeleteStdIO(diskreq);
  if (win) { ClearMenuStrip(win); CloseWindow(win); }
  if (scr) CloseScreen(scr); 
  if (imgptrf) FreeMem(imgptrf,sizeof(imagedataf));
  if (imgptrz) FreeMem(imgptrz,sizeof(imagedataz));
  if (DosBase) CloseLibrary(DosBase);
  if (GfxBase) CloseLibrary(GfxBase);
  if (IntuitionBase) CloseLibrary(IntuitionBase);
}

