
/* SimStructs Selected Simula structs for AMOS hackers
   Versions: Simula 2, OM 1.1 

Objects as loaded with Td Load are based on the OBJECT struct which
points to a STATIC_LAYER struct for each block.  Each block points to
a SIMPLE_OBJECT_TP (template) struct.
When an object is instanciated using Td Object, an OBJECT_FRAME_DETAILS
struct is built.  This points to a FRAME_LAYER struct for each block. */

/*
   Nameing conventions for graphic entities
   Each piece of data has the following attributes:

   Transformation Stage           Raw     (generalised object)
                   Wld     (in world coordinates)
                   Rot     (rotated world coords)
                   Cr      (Collapsed and rotated)
                   Vew     (in viewing coordinates)
                   Scr     (in screen coordinates)
                   Clp     (Scr clipped)

  Lifetime         Map     (lasts as long as a map)
                   Seq     (lasts for a sequence of frames)
                   Frm     (lasts for one frame)

  Entity class     Ob      (object)
                   Eg      (Edge)

  Type             Pt      (point)
                   Ln      (line)
                   Fa      (face, ie 1 or more sides)
                   Tp      (simple object template)
                   Ras     (raster)
                   Lyr     (layer)
                   Sid     (side, ie a bounded plane)
                   Sur     (surface)
                   Mount   (layers mounted on side)

  Dimension        2d
                   3d

  Other                 App/Application (data or space for use by applications)
*/

typedef struct OFLs {
 struct OFLs           *Pred,*Succ;     /* linked list ptrs */
 struct OFDs           *frame;
 struct ORS           *ob_ref;
   USHORT            size;         /* of the frame */
   UBYTE            status;
          } OBJECT_FRAME_LIST;

/* Values for status */
#define OFL_FREE      0  /* will be in free list */
#define OFL_ACTIVE      1  /* in live list */
#define OFL_SLEEPING      2  /* in live list */

typedef struct {
  /* the plane codes mean:
     0          work plane not used
     1,2,3,4 (...)  work plane blasted into gplane plane code-1 */
  UBYTE    plane0gplane,plane1gplane;
          } OBJECT_INSTANCE;

#define IMAGE_LIMIT_SIGN_BIT      0x80000000 /* change this if we are not using B32's */
typedef struct {
  B32      xoffset,yoffset;
  B32      maxx,maxy;
          } IMAGE_LIMITS;

/* This struct allows the B32's in IMAGE_LIMITS to be read as SHORTS */
#define SIMAGE_LIMIT_SIGN_BIT      0x8000 /* change this if we are not using B32's */

/* Note the d's are the dummy hi-byte variables */
#ifdef AMIGA_SIM
typedef struct {
  SHORT      d1,xoffset,d2,yoffset;
  SHORT      d3,maxx,d4,maxy;
     } SIMAGE_LIMITS;
#endif

#ifdef PC_SIM
typedef struct {
  SHORT      xoffset,d1,yoffset,d2;
  SHORT      maxx,d3,maxy,d4;
     } SIMAGE_LIMITS;
#endif

#ifdef ST_SIM
typedef struct {
  SHORT      d1,xoffset,d2,yoffset;
  SHORT      d3,maxx,d4,maxy;
     } SIMAGE_LIMITS;
#endif

typedef struct {
  LINE2D_REF     **face;       /* the face                */
  PLANEWORD       plane_word;     /* a planepick bit pair for each line in the face */
  SIDEWORD       side_word;       /* a bit set for each side in the face */
  UBYTE        flags;       /* see above */
          } TP_FACE_DETAILS;

typedef struct {
 LINE2D_REF      *RawMapObLns2d;    /* the 2d line offsets  */
 UBYTE         *RawMapTpSidPts;    /* 3 (+1 wrap around) continious clockwise point #'s from each side */
 UBYTE         *RawMapSidFa;    /* start of vector which converts calculated visible side word to face# */
 TP_FACE_DETAILS   *RawMapFaDtl;    /* details of faces, plane-words etc */
 USHORT        line_count;     /* # lines in the template */
/* these counts at TOW are not used at run time */
 USHORT        face_count;     /* # faces in the template */
 USHORT        faceline_count;    /* # facelines in the template */
 UBYTE          point_count;    /* # points required for the template */
 UBYTE          RawMapTpSidT;    /* 1<<side# for each side to be regarded as a top side of the template */
 UBYTE          RawMapTpSidB;    /* 1<<side# for each side to be regarded as a bottom side of the template */
 UBYTE          mx_lines_per_face;    /* used in calculating edge space    */
 UBYTE          side_count;     /* #sides in template */
 USHORT        seg_face_dtl;
 USHORT        seg_lines;
 USHORT        seg_sidface;
 USHORT        seg_sidpt;
#if STRUCTS_V1
 UB32          Version;         /* Simula version number */
 UBYTE      padding[12];
#endif
          } SIMPLE_OBJECT_TP;

/* A way of identifing flat layers: value for side_count */
#define FLAT_TEMPLATE_SIDE_COUNT           2

/* The order of Ave,Src1 and Src2 is important. (see r8.c) */
typedef struct {
 SPOINT2D   *Ave;           /* has to be 1st member */
 SPOINT2D   *Src1,*Src2;
          } AVERAGE_TRIPPLE;

typedef struct       {
 SLINE2D_REF        *Lines2d;
 SOB_EDGE        *StandardEdge;          /* unclipped */
 AVERAGE_TRIPPLE     *Code;             /* tripples for calculating averages */
 USHORT          seg_3pl;
 USHORT          seg_lines;
 USHORT          seg_edge;
 SPOINT2D       *ScrSeqSurPt2d;          /* dfn time add of reusable point vector (relocation only) */
#if STRUCTS_V1
 UB32            Version;        /* Simula version number */
 UBYTE           padding[12];
#endif
          } SURFACE_DETAILS;

/* The table made out of these links sides with surfaces. Each entry
   associates one side with a surface and contains pointers to the frame's
   2d points which are on the corners of the sides. */
typedef struct {
 SURFACE_DETAILS    *RawMapSur2d;       /* Surface for this side */
 USHORT         ScrSeqPt2dCorOff[4];   /* point#'s *sizeof(OB_POINT2D). Add to a (UBYTE *)frame_layer->ScrFrmObPt2d to get the addresses of the corner points */
 B32           ZVis;          /* max view depth for surface to be visible */
          } SIDSUR_LINK;


typedef struct {
 USHORT        RawMapMountIndex;    /* (Not used after compile time) absolute index into the mount words for 1st mount word in this layer */
 B32           ZVis1,ZVis2;         /* limits on Z for layer to be visable */
 SIMPLE_OBJECT_TP  *RawMapTp;       /* the pro forma for the simple object that goes in this layer */
 USHORT        mx_edge_bytes;       /* make this much room in the frame for this layer's calculated edges */
 USHORT        p0;                  /* the point# of the point that is to be treated as point 0 in the template to which this layer points */
 UBYTE         RawMapObPt3dPosRefNo;/* the reference point # */
 SIDEWORD      SurSidMask;          /* bit set for each side (in the template) which has a surface  */
 SIDEWORD      XsideMask;           /* mask with bit set for every uncovered side */
 USHORT        SidSurLinkIndex;     /* index into table of particulars linking sides with surfaces */
 UBYTE         animators[MX_ANIMATORS_PER_LAYER];
#if STRUCTS_V1
 /* Flat layers only:
    Because flat layers can be non convex the clockwise points are not
    template specific (as they are for convex layers) but layer specific.
    The RawMapSidPts pointers in flat layers (and only flat layers) point
    here. */
#if (MX_ANIMATORS_PER_LAYER&1)
 UBYTE          byte_pad;
#endif
 UBYTE          RawMapFlatSid0Pts[4];
 UBYTE          RawMapFlatSid1Pts[4];
 UBYTE          ColorComb;          /* instance color comb code for OM */
 UBYTE          padding[6];
#if !(MX_ANIMATORS_PER_LAYER&1)
 UBYTE          byte_pad;
#endif
#endif
          } STATIC_LAYER;

/* Meaning of the bits in the flags member of TP_FACE_DETAILS.   See g1a.h
   for some other relevant defines */
#define FACE_P0          1
#define FACE_P1          2
#define FACE_P1_EQ_P0         4

typedef struct {
 UWORD          *plane;         /* not yet: start of intersect within tween raster */
 UBYTE           padding[8];
               } BACKTWEEN;

typedef struct {
 struct FLS     *layer;                               /* the tween layer (which points back to this tween) */
 UWORD          *plane;                               /* start of tween raster */
 UBYTE           padding[8];
 BACKTWEEN       BackTween[MX_BACKTWEENS_PER_TWEEN];
               } TWEEN;

/* DLFlags bits in the FRAME_LAYER type */
#define DLF_TWEEN             1
#define DLF_BACK              2
#define DLF_BACK0             4


typedef struct FLS {
 B32          layer_id;        /* contains 1<<layer# as defined in the text */
/* Points, sides, faces, edges, instances */
 UBYTE          point_count;     /* # points in this layer */
 OB_POINT3D      *RawMapObPts3d;     /* the raw 3d points for the layer */
 OB_POINT3D      *WldSeqObPt3d;     /* the 3d prepared points          */
 OB_POINT2D      *ScrFrmObPt2d;     /* the 2d point base for this layer */
 OB_POINT2D      *L,*R,*T,*B;      /* the points that were lefr,right,top and bottom last frame */
 UBYTE         *RawMapTpSidPts;     /* 3 (+1 wrap around) continious clockwise point #'s from each side */
 LINE2D_REF      *ScrSeqLyrLn2d;     /* the lines for this layer */
 SIDEWORD       CurSidWord;      /* the current side word for the layer */
 TP_FACE_DETAILS   *ClpSeqObFa2dDtlCur;   /* current face_details struct */
 TP_FACE_DETAILS   *RawMapTpFaDtl;     /* base of the template's TP_FACE_DETAILS structs for this layer */
 OB_EDGE      *ScrSeqObPt2dEdge;     /* calculated edge, good for a few frames */
 OBJECT_INSTANCE   *RawMapObInst;     /* the instance struct for this layer */
/* Redraw/recalc control */
 OB_POINT2D      *ScrFrmObPt2dPosRef;   /* the reference point used sometimes as an event origion */
 SHORT          VewSeqLastCalcX;     /* image position x at last recalc */
 SHORT          VewSeqLastCalcY;     /* image position y at last recalc */
 SHORT          VewFrmLastW;     /* width and height at last recalc */
 SHORT          VewFrmLastH;
 B32          ZVis1,ZVis2;     /* limits on Z for layer to be visable */
/* Concerning the image */
 USHORT        VewFrmLlclip;     /* #SPA pixels left clipped */
 USHORT        VewFrmTlclip;     /* #SPA pixels top clipped */
 UBYTE          ScrSeqRasIndent;     /* bit#<<COMP of leftmost image edge in any raster */
 IMAGE_LIMITS       VewFrmObImgLim;     /* image size (acurately) calculated on initial scan of layer prior to compiling draw list */
 RASTER_DETAILS    *ScrSeqObRas2d;     /* points to a raster if any          */
 RASTER_DETAILS    *ScrSeqObRas2dHelp;     /* points to the last raster used by the layer. Tried first when selecting a raster via alloc_raster. */
/* Hidden surface elimination */
#if STRUCTS_V1
 MOUNTWORD2      *RawMapLyrMountBase;   /* mount word base for the layer */
#else
 MOUNTWORD      *RawMapLyrMountBase;   /* mount word base for the layer */
#endif
 UBYTE         *RawMapTpSidFa;     /* start of vector which converts calculated visible side word to face# */
 UBYTE          RawMapTpSidCount;     /* # sides intemplate for this layer */
 SIDEWORD       XsideMask;        /* masks out sides completly covered by another layer(s) */
 SIDEWORD       SidMask;        /* bit set for every side in the layer */
/* Surface detail */
 /* Local copy of the surface/side link table needed for dynamically
    changing surfaces. */
 SIDSUR_LINK       SidSurLinkBase[MX_SIDE_NO+1]; /* one for each side */
 SIDEWORD       SurSidMask;      /* bit set for each side (in the template) which has a surface */
 SIDEWORD       SeqSurSidMask;     /* bit set for every currently visible side which has a surface */
 B32          rz;         /* approx depth of layer wrt view used to prune surfaces */
/* Status variables
   DANGER 68K: The next 2 UBYTEs, force_lc  and force_clip must together form a legal SHORT */
 UBYTE          force_lc;        /* set by the point calculator if a point is BEH so that z-clipping gets done */
 UBYTE          force_clip;      /* set by point calculator whenever a REGION bit gets set. Later we decide whether to line or area clip */
 UBYTE          B32limits;        /* TRUE if pre clipped image cannot be handled in 16 bits */
 UBYTE          lines_clipped;     /* this layer got line clipped so edge will not be valid  */
 UBYTE          valid_edge;      /* ScrSeqObPt2dEdge points to an edge which can be reused */
 UBYTE          ZVis;        /* TRUE if ref point for this layer is within Z range */
 UBYTE          Easy;        /* TRUE if no 2d or 3d clipping */
 UBYTE      Emanation;     /* TRUE if there is anything like a ray eminating from the layer */
/* Misc Template variables */
 UBYTE          RawMapTpSidT;     /* 1<<side# for each side to be regarded as a top side of the template */
 UBYTE          RawMapTpSidB;     /* 1<<side# for each side to be regarded as a bottom side of the template */
/* Animators */
 ANIMATOR      *Animators[MX_ANIMATORS_PER_LAYER];
 OB_POINT3D      *AniSeqObPt3d;     /* animated point base */
 B32         AniX,AniY,AniZ;     /* layer offsets set by the animator */
 UBYTE          AniEnBlock;      /* TRUE if layer animated using the ANI_EN_BLOCK method */
 UBYTE          AniFlag;        /* TRUE if layer currently animated */
/* Put new members here, later move them to approprate headings */
 UBYTE          OrRegion;        /* the OR of the region words for all the points in the layer */
 UBYTE          fd_flags;        /* copy of the current face_details->flags */
#if STRUCTS_V1
 UBYTE          DLFlags;         /* interlieve control flags. see TWEEN above */
 MOUNTWORD      BackLayers;      /* layers to be drawn behind interlieved layers */
 TWEEN         *Tween;           /* Chopped up layers, see r2,r5 */
 BACKTWEEN     *BackTween;       /* ditto */
 UBYTE          padding[6];
#endif
          } FRAME_LAYER;


typedef struct {
 /* The _bytes members give the size of things as they will be in the
    object frame, not as they are the static object */
#if STRUCTS_V1
 UB32          Version;         /* Simula version number */
#endif
 USHORT        frame_bytes;    /* ob frame size  */
 USHORT        point2d_bytes;    /* points size    */
 USHORT        line_bytes;     /* line size      */
 USHORT        layer_bytes;    /* total size of the layers */
 OB_POINT3D      *RawMapObPts3d;    /* the raw points */
 UB32          RawMapRadius;    /* in TRIG_RES units: radius of curcumsphere surounding all the points */
#if STRUCTS_V1
 MOUNTWORD2      *RawMapObLyrMounts;    /* the layers mounted on each side */
#else
 MOUNTWORD      *RawMapObLyrMounts;    /* the layers mounted on each side */
#endif
 OBJECT_INSTANCE   *RawMapObInstBase;    /* the base of the instance vector for this object */
 STATIC_LAYER      *RawMapObLyr3d;    /* pointer to 1st layer */
 UBYTE          nlayers;       /* the number of layers */
 UBYTE          event_origion;    /* the point passed to an event */
 SHORT          FirstDetector;    /* used unusually: see reloc.c. index into RawMapDetectors */
 UBYTE          AttributeCount;    /* the number of attributes declared in this object */
 COLWORD4       RawMapInstDomCols[MX_INSTANCES_PER_OBJECT]; /* indexed by instance# to yeild the 2 most dominant color of the object and the colors to be used in Projections (4 nibbles) */
 B32          RawMapSubResDepth;    /* aprox depth >which ob considered below screen resolution and approximation invoked */
 UBYTE          ApplicationData;    /* used unusually: see reloc.c. index into RawMapAppData */
 USHORT        seg_layers;     /* relocation offsets */
 USHORT        seg_inst;
 USHORT        seg_points;
 USHORT        seg_links;
 USHORT        seg_mounts;
 SIDSUR_LINK      *RawMapSidSurLinks;
 UBYTE          MasterLayer;    /* the most 'important' layer in an object. (greatest ZVis) */
 OB_POINT3D       UtilityPoints[MX_UTILITY_POINTS_PER_OBJECT]; /* points for misc use. event origions, docking positions etc (not auto calculated) */
#if STRUCTS_V1
 COLBITS        Palette[MX_BINOB_COLORS];
 UBYTE          padding[2];  /* 16 before Palette */
#endif
          } OBJECT;

typedef struct { /* for the pre-draw and draw lists (r4.c/r11.c) */
 B32          layer_id;         /* 1<<layer# */
 FRAME_LAYER      *layer;
 TP_FACE_DETAILS   *face_details;
          } DRAW_DETAILS;

typedef struct OFDs {
 /* The point sets take the script defined points through the 2 and 3d
    transformations as follows:
    Dimensions Input       Output   Transformation
    3d-3d      RawMap       AniSeq   copy from script points to frame at frame setup
    3d-3d      AniSeq       AniSeq   animation applied (ANI_POINTS not block layer translation)
    3d-3d      AniSeq       WldSeq   orientation of object on map (mobiles)
    3d-2d      WldSeq       ScrFrm   rotated and translated wrt view and projected onto (usually 16bit) screen with (X,Y)_SCREEN_ORIG as point (0,0)
 */
 OB_POINT3D      *RawMapObPt3d;     /* exactly as defined in script (not held in the frame) */
 OB_POINT3D      *AniSeqObPt3d;     /* as RawMap but as modified by any animators */
 OB_POINT3D      *WldSeqObPt3d;     /* as AniSeq but as oriented in the world */
 OB_POINT2D      *ScrFrmObPt2d;     /* the projected 2d points          */
 LINE2D_REF      *ScrSeqObLn2d;     /* the unclipped lines          */
 FRAME_LAYER      *ScrSeqObLyr2d;     /* ptr to the first in the vector of frame layers (held in the frame) */
 FRAME_LAYER      *ScrSeqObLyrs[MX_LAYERS_PER_OBJECT+1];    /* pointers to the layers */
#if STRUCTS_V1
 MOUNTWORD2       ClpSeqObLyrMounts[MX_LAYERS_PER_OBJECT]; /* vector of mounts indexed by layer# assembled at the same time as the pre-draw-list */
#else
 MOUNTWORD       ClpSeqObLyrMounts[MX_LAYERS_PER_OBJECT]; /* vector of mounts indexed by layer# assembled at the same time as the pre-draw-list */
#endif
 DRAW_DETAILS       draw_list[MX_LAYERS_PER_OBJECT+1];        /* list of layers etc sorted into drawing order */
 DRAW_DETAILS      *LastDlEntry;
 UBYTE          nlayers;        /* the number of layers       */
 SHORT          alpha_lock;      /* the value of alpha when layers last calculated */
 SHORT          theta_lock;      /* the value of theta when layers last calculated */
 UBYTE          Recalc;        /* TRUE if frame is to be recalculated, FALSE if simply redrawn */
 UBYTE          valid_dl;        /* TRUE if we can reuse the draw list from last frame and hence avoid calling form_draw_list() */
 UBYTE          x_update_threshold;   /* amount total w can change before recalc */
 UBYTE          y_update_threshold;   /* amount total h can change before recalc */
 struct ORS      *RawMapObRef;     /* the object_ref responsible for this frame    */
 UBYTE          ZVis;        /* TRUE if any layer of object is in front of the cutoff plane */
 UBYTE          VisLayerCount;     /* bumped when a layer actually gets displayed */
 OB_POINT2D      *WldSeqEventOrig2d;     /* the point passed to the event handler cause_event() */
 struct AMs      *ActiveMobile;     /* any active mobile controling this object instance */
 UBYTE          AniCount;        /* count of layers currently animated */
 DETECTOR_REF      *FirstDetector;     /* points to the detector vector in the object */
 ATTRIBUTE      *SeqAttributes;     /* the set of attributes local to this object instance */
 ATTRIBUTE      *SeqAttributeEnd;     /* byte after the last attribute */
 UBYTE          RawMapDomCol1;     /* the predominant color for the object with the above instance's colors */
 UBYTE          RawMapDomCol2;     /* the 2nd most dominant color */
 UBYTE          XSpreadOKCount;     /* countdown: TRUE if the 2 following are valid */
 OB_POINT3D      *ScrFrmObPt2dXL;     /* the point we take as being leftmost in projection for small objects */
 OB_POINT3D      *ScrFrmObPt2dXR;     /* the point we take as being rightmost in projection for small objects */
 OBJECT_FRAME_LIST *OFL;
 OBJECT       *RawMapObject;     /* the object of which this frame is an instance */
/* colors of dots depicting an object on a Projection */
 UBYTE          RawMapProjCol1;     /* in front of view plane */
 UBYTE          RawMapProjCol2;     /* behind view plane */
 UBYTE          FirstReject;     /* contains a region bit set indicating position wrt viewing pyramid (r8.c) */
 FRAME_LAYER      *MasterLayer;     /* the most 'important' layer in an object */
 UBYTE          BackupRaster;     /* TRUE if object is using the backup raster and is therefore not a candidate for redraw */
#if STRUCTS_V1
 UBYTE          padding[16];
#endif
          } OBJECT_FRAME_DETAILS;


typedef struct ODEs {
 OBJECT_FRAME_DETAILS         *frame;
 POINT3D             position;         /* absolute map position */
 POINT3D             wrtv;         /* with respect to unrotated view */
 B32                rz;          /* rotated z coord of the ref point of one of the object's layers (gives a rough idea of depth) */
 UBYTE                SubRes;         /* TRUE if small compared with screen resolution */
 B32                SubResDepth;      /* object SubRes when rz> this */
 struct ODEs            *Pred,*Succ;
 struct AMs /* ACTIVE_MOBILE */    *ActiveMobile;
 SHORT                ScrFrmSubresX;    /* the screen coords of any subres image */
 SHORT                ScrFrmSubresY;    /* ==SUBRES_OFF_SCREEN if not visible */
 MOB_CLASS_MASK           MobileClassMask;  /* 1<<(class#+1) or 1 for view, used in detectors */
 UBYTE                DormantFel;       /* TRUE if this object is a dormant field element */
 struct FDs            *Field;         /* if this ode was started by a field, this points to it. */
 UBYTE                NormShift;         /* shift to bring wrtv just inside 16 bit range */
 /* Space reserved for application data.  Allows an application to make
    use of the maintained ODE space. */
 UB32                ApplicationData[(MX_APPLICATION_DATA+3)>>2]; /* make sure exact # of UB32s */
 /* The following member (ApplicationCountdown) MUST follow ApplicationData (see r14.c) */
 UB32                ApplicationCountdown; /* (must immediatly follow ApplicationData) call process_application_mobile() when TheTime exceeds this */
 /* The following member provides a way for an application to tell whether
    an object contains an application maintained structure in ApplicationData */
 UBYTE                ApplicationDefined;
 VECTOR3D             RotDsp;         /* displacment of (0,0,0) due to rotation by (theta,alpha) */
 TRIG_RESULTS             Trig;         /* total rotation of object */
#if STRUCTS_V1
 UBYTE                padding[16];
#endif
          } OBJECT_DISPLAY_DETAILS;

/* special value for  ScrFrmSubresY */
#define SUBRES_OFF_SCREEN       0xffff
/* undefined NormShift guaranteed higher than ever used (applications) */
#define NS_INFINITY            255

typedef struct ORS {
 OBJECT_FRAME_DETAILS      *object_frame;   /* NULL if no current frame for this instantiation */
 MAPPOINTSIZE          basex,basey,basez;   /* where this object lives on the map         */
 OBJECT_INSTANCE      *instance;      /* its color instance base */
 OBJECT          *object;      /* the generic object               */
 B32             ZVis1,ZVis2;   /* limits on Z for object to be visable, more flexable here than in the object struct
                     Not used at present, we use the Z visibility of the layers */
 UBYTE             Flags;      /* see below */
 OBJECT_PALETTE       *palette;      /* colors for object when reffed with this ref */
 UBYTE             inst_no;      /* the instance# quoted in the Add statement */
 BYTE        object_name[MX_SYMBOL_NAME_LEN+1]; /* just that */
#if SMOS == ON
 struct ORS         *next;      /* SMOS - for redraw linked-list */
 struct ORS         *prev;      /* SMOS - for object removal */
 OBJECT_DISPLAY_DETAILS    *ode;      /* SMOS - access to ode */
 struct s_smos_stuff     *smos_stuff;      /* SMOS - extra bits to be */
                  /* included in this struct. */
                  /* Accessed via SMOS_STUFF */
                  /* macro. */
#endif
#if STRUCTS_V1
 UBYTE         padding[16];
#endif
          } OBJECT_REF;

#define LOG_N_QCs        2
#define LOG_RIGOUR_RANGE     6
#define RIGOUR_RANGE       ((1<<LOG_RIGOUR_RANGE)-1)

/* The QUALITY_CONTROL type gives values to parameters which affect the
   speed/quality tradeoff.  Different instances are chosen according to
   the value of the rigour variable which depends on the  frame rate error
   (between required and actual) fr_error. */

typedef struct {
 USHORT    Xrecalc;              /* # SPAs by which layer can change before recalc forced */
 USHORT    Yrecalc;
 USHORT    ThetaSigMask;              /* initalised as a significance level, converted to a mask */
 USHORT    AlphaSigMask;
 UBYTE      Linestyle;              /* SUPER, NEAT or BLIT lines (see line.c) */
 UBYTE      NeatDy;               /* SUPERLINEs for Dy (ras lines) <NeatDy) */
      /* Multiplication tables yielding aggregate thresholds for
         X,Y recalc on (index) n layers. */
 USHORT    FrameXRecalc[MX_LAYERS_PER_OBJECT];
 USHORT    FrameYRecalc[MX_LAYERS_PER_OBJECT];
          } QUALITY_CONTROL;

