/* Copyright © 1995-1996 : David Atkinson */
/* V1.22  Init.c */

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <fcntl.h>
#include <string.h>
#include <time.h>

#include <hold/extra.h>
#include <hold/mowd.h>

#include <exec/types.h>
#include <exec/libraries.h>
#include <exec/io.h>
#include <exec/ports.h>

#include <graphics/gfxbase.h>
#include <graphics/displayinfo.h>
#include <graphics/gfx.h>
#include <graphics/videocontrol.h>

#ifdef(V3)
#include <graphics/modeid.h>
#endif

#include <utility/tagitem.h>

#include <intuition/intuition.h>
#include <intuition/screens.h>

#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/graphics_protos.h>
#include <clib/dos_protos.h>
#include <clib/diskfont_protos.h>

#define NFRAMES 100000
#define NSCREENS 12

extern void handler(int);
extern void alert(TEXT *);
extern void clean_local(void);
#ifdef TEST
extern void write_log(TEXT *,SHORT);
#endif

extern struct MsgPort *aport;
extern SHORT Prilevel;

void op_liblob(void);
void chose_mode(LONG);
void get_palette(int);
void bit_init(void);
void acquire_bits(int);
void get_editor(void);
void opttext(void);
void back_drop(void);
void viewstart(void);
void ras_init(void);
void viewportstart(void);
LONG scrtime(void);
void changepri(LONG);

struct Library *IntuitionBase = 0;
struct Library *WorkbenchBase = 0;
struct GfxBase *GfxBase = NULL;
struct Library *DiskfontBase = 0;
struct Library *ConsoleDevice = NULL;
struct GfxBase *wb = NULL;
struct IOStdReq ioreq;
struct TextFont *font_ptr = NULL;
struct TextFont *cfontptr = NULL;
struct BitMap ft_bitmap;
struct BitMap sec_bitmap;
struct BitMap thd_bitmap;
struct ViewPort ft_viewport;
struct ViewPort sec_viewport;
struct View ft_view;
struct View sec_view;
struct RastPort ft_rastport;
struct RastPort sec_rastport;
struct RastPort thd_rastport;
struct RasInfo ft_rasinfo;
struct RasInfo sec_rasinfo;
struct RasInfo thd_rasinfo;
/* For 2.0+ Wb */
struct ViewExtra *ft_vextra=NULL;
struct ViewExtra *sec_vextra=NULL;
struct MonitorSpec *monspec=NULL;
struct ViewPortExtra *vpone_extra=NULL;
struct ViewPortExtra *vptwo_extra=NULL;
struct DimensionInfo dimquery;
struct MonitorInfo monstuff;
struct DisplayInfo distuff;
struct Screen *my_screen = NULL;
struct Window *my_window = NULL;

UWORD vpone_col[COLOURS],vptwo_col[COLOURS];
UWORD wb_version = 37;               /* WorkBench version, fixed at 37 for now  */
UBYTE *keybufptr = NULL;             /* Keyboard buffer */
ULONG modeID = 0;
UWORD colour_table[VYOUS][COLOURS];  /* Colour Palette */
TEXT editor[MAXCHARPATH];            /* Editor Buffer */
TEXT choices[NUMOFOPT][SLENGTH];     /* Options */
struct ColorMap *cm = NULL;          /* Color map pointer for view one */
struct ColorMap *cmtwo = NULL;       /* Colour map pointer for view two */
LONG Refresh=0L;

struct TextAttr opt_font =
{
  "helvetica.font",
  13,
  FS_NORMAL,
  FPF_DISKFONT | FPF_DESIGNED
};

struct TextAttr code_font =
{
  "topaz.font",
  8,
  FS_NORMAL,
  FPF_ROMFONT
};

struct TagItem NSTags[2] =
{
  {SA_DisplayID,(ULONG) NULL},
  {TAG_DONE,(ULONG) NULL}
};

struct ExtNewScreen Escreen=
{
  0,            /* LeftEdge  Should always be 0. */
  0,            /* TopEdge   Top of the display.*/
  640,          /* Width  */
  512,          /* Height */
  4,            /* Depth     16 colours. */
  0,            /* DetailPen Text should be drawn with colour reg. 0 */
  1,            /* BlockPen  Blocks should be drawn with colour reg. 1 */
  HIRES|SPRITES,
  CUSTOMSCREEN | NS_EXTENDED, /* Type      Customized screen. */
  NULL,         /* Font      Default font. */
  NULL,         /* Title     The screen' title. */
  NULL,         /* Gadget    Must for the moment be NULL. */
  NULL,         /* BitMap    No special CustomBitMap. */
  NULL          /* TagItems */
};

/* Declare and initialize your NewWindow structure: */
struct NewWindow back_window =
{
  0,            /* LeftEdge    x position of the window. */
  0,            /* TopEdge     y positio of the window. */
  640,           /* Width       640 pixels wide. */
  512,           /* Height      512 lines high. */
  0,             /* DetailPen   Text should be drawn with colour reg. 0 */
  1,             /* BlockPen    Blocks should be drawn with colour reg. 1 */
  IDCMP_MOUSEBUTTONS|IDCMP_ACTIVEWINDOW|IDCMP_INACTIVEWINDOW|IDCMP_RAWKEY,
  WFLG_SMART_REFRESH|WFLG_ACTIVATE|WFLG_RMBTRAP|WFLG_BORDERLESS,
  NULL,          /* FirstGadget No Custom Gadgets. */
  NULL,          /* CheckMark   Use Intuition's default CheckMark (v). */
  NULL,          /* Title       Title of the window. */
  NULL,          /* Screen      Connected to the Escreen  */
  NULL,          /* BitMap      No Custom BitMap. */
  0,             /* MinWidth    We do not need to care about these */
  0,             /* MinHeight   since we havent supplied the window with */
  0,             /* MaxWidth    a Sizing Gadget. */
  0,             /* MaxHeight */
  CUSTOMSCREEN   /* Type        Connected to the My custom Screen. */
};

struct TagItem voneTags[4] =
{
    { VTAG_ATTACH_CM_SET, (ULONG) NULL },
    { VTAG_VIEWPORTEXTRA_SET, (ULONG) NULL },
    { VTAG_NORMAL_DISP_SET, (ULONG) NULL },
    { VTAG_END_CM, (ULONG) NULL }
};

struct TagItem vtwoTags[4] =
{
    { VTAG_ATTACH_CM_SET, (ULONG) NULL },
    { VTAG_VIEWPORTEXTRA_SET,(ULONG) NULL },
    { VTAG_NORMAL_DISP_SET, (ULONG) NULL },
    { VTAG_END_CM, (ULONG) NULL }
};


/* void op_liblob(void)
   Opens up the amigas librarys, shuts down cpu datacaches, sets up modeid, opens
   console Device, sets up input handler, opens fonts and gets memory for  keyboard buffer.
   The OpenLibray routines not needed in Dice but needed in SAS/C */

void op_liblob()
{
SHORT result=0;

  /* Fix for 68030, when on low amount of memory (chip), get problem writing text
     to screen. See corresponding cpu command in cleanup */

  result=system("cpu nodatacache > NIL:");
  IntuitionBase = OpenLibrary("intuition.library",0);
  if (IntuitionBase==0)
    alert("Failed to open intuition library (op_liblob)\n");
  WorkbenchBase = OpenLibrary("workbench.library",37);
  if(WorkbenchBase==0)
    alert("Failed to open workbench library 37+ (op_liblob)\n");
  GfxBase = (struct GfxBase *) OpenLibrary( "graphics.library", 0 );
  if (GfxBase==0)
    alert("Failed to open graphics library (op_liblob)\n");
  wb_version = GfxBase->LibNode.lib_Version;
  if(wb_version < 37)
     alert("Sorry Need WorkBench Libraries 37+ To Run\n");

  DiskfontBase = OpenLibrary("diskfont.library", 0 );
  if (DiskfontBase==0)
    alert("Failed to open diskfont library (op_liblob)\n");
  wb = (struct GfxBase *) GfxBase;
  /* Open Console Device */
  if (0==OpenDevice("console.device",-1,(struct IORequest *) &ioreq, 0) ){
    ConsoleDevice = (struct Library *) ioreq.io_Device;
  }
  else{
    alert("Failed to open console device (op_liblob)\n");
  }
  signal(SIGINT,handler);
  keybufptr=(UBYTE *) malloc(KEYBUFF);
  if(keybufptr==NULL){
    alert("Failed to allocate memory for keyboard buffer (op_liblob)\n");
  }
  if( !(aport = CreateMsgPort()) ){
    alert("Failed to open message port\n");
  }
  font_ptr=OpenDiskFont(&opt_font);
  if(font_ptr==NULL){
    opt_font.ta_Name = "times.font";
    opt_font.ta_YSize = 11;
    font_ptr=OpenDiskFont(&opt_font);
  }
  if(font_ptr==NULL){
    opt_font.ta_Name = "courier.font";
    opt_font.ta_YSize = 11;
    font_ptr=OpenDiskFont(&opt_font);
  }
  if(font_ptr==NULL){                  /* PaniC - Find A font */
    opt_font.ta_Name = "napsa.font";
    opt_font.ta_YSize = 11;
    font_ptr=OpenDiskFont(&opt_font);
  }
  if(font_ptr==NULL){
     alert("Couldn't Open Font:  Need helvetica 13 or times 11 or courier 11 or napsa 11\n");
  }
  cfontptr = OpenFont(&code_font);
  if(cfontptr==NULL){
    alert("Couldn't Open topaz.font (8) (op_liblob)\n");
  }
  #ifdef TEST
    write_log("op_liblob PASSED\n",PRIONE);
  #endif
}

void chose_mode(LONG Mtype){

  wb_version=37;   /* Fix it for now */
  if( wb_version<39 ){
    if(Mtype==UK){
      modeID = PAL_MONITOR_ID | HIRESLACE_KEY;
    }
    else{
      modeID = NTSC_MONITOR_ID | HIRESLACE_KEY;
    }
  }
  else{
    modeID = PAL_MONITOR_ID | HIRESLACE_KEY;
    #ifdef(V3)
    modeID = DBLPAL_MONITOR_ID | DBLPALHIRESFF_KEY;
    #endif
  }
  #ifdef TEST
    write_log("chose_mode PASSED\n",PRIONE);
  #endif
}

/* void get_palette(int)
   get_palette, reads in palette colours (long words) from
   specified file path number. Have to cast from int to UWORD
   for the palette arrays */

void get_palette(int palnum)
{
TEXT *palete_file;
FILE *fp=0;
int i,col_tab[COLOURS];

  switch(palnum){
    case(1):
      palete_file=MENUPALETE;
      break;
    case(2):
      palete_file=DEMPALETE;
      break;
    default:
      clean_local();
      alert("Incorrect Menu label (get_pallete)\n");
      break;
  }

  fp = fopen(palete_file,"r");
  if ( fp ){
    for(i=0;i<COLOURS;i++){
      fscanf(fp,"%x",&col_tab[i]);
      /*We have to cast */
      colour_table[palnum-1][i] = (UWORD) col_tab[i];
    }
    fclose( fp );
  }
  else {
    clean_local();
    alert("Couldn't open palette (get_pallete)\n");
  }
  #ifdef TEST
    write_log("get_pallete PASSED\n",PRIONE);
  #endif
}

void bit_init()
{
int loop;

/* The WaitBlits are a stab at trying to fix the text corruption problem */

  InitBitMap( &ft_bitmap, DEPTH, WIDTH, HEIGHT );
  for( loop = 0; loop < DEPTH; loop++ )
  {
    ft_bitmap.Planes[ loop ] = AllocRaster( WIDTH, HEIGHT );
    if( ft_bitmap.Planes[ loop ] == NULL )
      alert("Failed Bitmap allocation 1 (bit_init)\n");
    WaitBlit();
    BltClear( ft_bitmap.Planes[ loop ],
           RASSIZE( WIDTH, HEIGHT ), 0 );
  }
  WaitBlit();
  InitBitMap( &sec_bitmap, DEPTH, WIDTH, HEIGHT );
  for( loop = 0; loop < DEPTH; loop++ )
  {
    sec_bitmap.Planes[ loop ] = AllocRaster( WIDTH, HEIGHT );
    if( sec_bitmap.Planes[ loop ] == NULL )
      alert("Failed Bitmap allocation 2 (bit_init)\n");
    WaitBlit();
    BltClear( sec_bitmap.Planes[ loop ],
           RASSIZE( WIDTH, HEIGHT ), 0 );
  }
  WaitBlit();
  InitBitMap( &thd_bitmap, DEPTH, WIDTH, THDHITE );
  for( loop = 0; loop < DEPTH; loop++ )
  {
    thd_bitmap.Planes[ loop ] = AllocRaster( WIDTH, THDHITE );
    if( thd_bitmap.Planes[ loop ] == NULL )
      alert("Failed Bitmap allocation 3 (bit_init)\n");
    WaitBlit();
    BltClear( thd_bitmap.Planes[ loop ],
           RASSIZE( WIDTH, THDHITE ), 0 );
  }
  WaitBlit();
  #ifdef TEST
    write_log("bit_init PASSED\n",PRIONE);
  #endif
}

/* void aquire_bits(int)

   Take the picture number as an argument and loads in
   the bitmap accordingly */

void acquire_bits(int picnum)
{

int aplane,aline,fh,segment,tall,need;
TEXT picbuff[WIDTH*4], *pic_file;
UBYTE *bitptr=NULL;
struct BitMap the_bitmap;

  switch(picnum){
    case(1):
      pic_file=MENUPATH;
      the_bitmap = ft_bitmap;
      tall = HEIGHT;
      break;
    case(2):
      pic_file=DEMPATH;
      the_bitmap = sec_bitmap;
      tall = HEIGHT;
      break;
    case(3):
      pic_file=DUMPPATH;
      the_bitmap = thd_bitmap;
      tall = THDHITE;
      break;
    default:
      clean_local();
      alert("Incorrect picture number label");
      break;
  }

  need = tall/32;
  fh = open(pic_file,O_RDONLY);
  if (fh<0){
    clean_local();
    alert("Couldn't open data file\n");
  }
  for(aplane=0;aplane<DEPTH;aplane++){
    bitptr = (UBYTE *) (the_bitmap.Planes[aplane] );
    for(segment=0;segment<16;segment++){
      read(fh,picbuff,2560);
      if(segment<need){
        for(aline=0;aline<2560;aline++){
          *bitptr++ = (UBYTE) picbuff[aline];
        }
      }
    }
  }
  close(fh);
  #ifdef TEST
    write_log("acquire_bits PASSED\n",PRIONE);
  #endif
}

void get_editor(void){
FILE *edfp=NULL;

  edfp = fopen(EDITPATH,"r");
  if(edfp){
    fscanf(edfp,"%s",editor);
    fclose(edfp);
  }
  else{
    printf("Failed open data/editor.dat: Defaulting to sys:utilities/multiview \n");
    strcpy(editor,ONETWO);
  }
  #ifdef TEST
    write_log("get_editor PASSED\n",PRIONE);
  #endif
}

void opttext()
{
int line, letter;
int c;
FILE *fileptr=0;

  for(line=0;line<NUMOFOPT;line++){
     for(letter=0;letter<SLENGTH;letter++){
        choices[line][letter]='\0';
     }
  }
  line=0;
  letter=0;
  c=0;
  /* fopen sets fileptr point at position 0 on error */
  fileptr=fopen(OPTTPATH,"r");
  if(fileptr){
    while( (c!=EOF) && (letter<SLENGTH) && (line<NUMOFOPT) ){
      c= fgetc(fileptr);
      switch(c){
        case '\n' :
          choices[line][letter]= '\0';
          line++;
          letter=0;
          break;
        case EOF :
          break;
        default :
          if( (line>=NUMOFOPT) || (letter>=SLENGTH) ){
             #ifdef TEST
               write_log("Error caught in opttext\n",PRIONE);
             #endif
             c=EOF;
          }
          else{
            choices[line][letter]=c;
            letter++;
          }
          break;
      }
    }
    fclose(fileptr);
  }
  else{
    clean_local();
    alert("Couldn't open options file (opttext)\n");
  }
  #ifdef TEST
    write_log("opttext PASSED\n",PRIONE);
  #endif
}

void back_drop(void)
{
/* Open Screen  */
  Forbid();
  NSTags[0].ti_Data = modeID;
  Escreen.Extension = NSTags;
  if(wb_version<37)
    Escreen.ViewModes |= LACE;
  my_screen = (struct Screen *) OpenScreen( (struct NewScreen *) &Escreen );
  if (my_screen==NULL){
     Permit();
     clean_local();
     alert("Failed open screen (back_drop)\n");
  }
  back_window.Screen = my_screen;  /* Window uses my Screen */
  /* Open Window */
  my_window = (struct Window *) OpenWindow( &back_window );
  /* Have we opened the window succesfully? */
  if(my_window == NULL){
    Permit();
    clean_local();
    alert("Failed open window mouse.c (back_drop)\n");
  }
  Refresh = scrtime();
  Permit();
  #ifdef TEST
    write_log("back_drop PASSED\n",PRIONE);
  #endif
}

/* void viewstart(void)
   viewstart initialises the view structure and modes
   LACE, HIRES, 640*512. Note the view structue Dxoffsets
   and DyOffsets are initialised not necasarily set to 0,
   presently set to 129*44. (V1.3)  */

void viewstart()
{
  /* 1.3 Wb */
  InitView(&ft_view);
  if(wb_version>=36){
    ft_view.DxOffset = 0; /* For 2.0+ have to get XY values from monitor database */
    ft_view.DyOffset = 0;
  }
  ft_view.Modes = LACE|HIRES|SPRITES;
  ft_view.ViewPort = &ft_viewport;
  InitView(&sec_view);
  sec_view.ViewPort =&sec_viewport;
  sec_view.Modes = LACE|HIRES|SPRITES;
  if(wb_version>=36){
    sec_view.DxOffset = 0;
    sec_view.DyOffset = 0;
  }
  /* 2.0+ Wb */
  if(wb_version>=36){
    ft_vextra=GfxNew(VIEW_EXTRA_TYPE);
    sec_vextra=GfxNew(VIEW_EXTRA_TYPE);
    if( ! ((ft_vextra == NULL) || (sec_vextra==NULL)) ){
      GfxAssociate(&ft_view, ft_vextra);
      ft_view.Modes  = LACE|HIRES|SPRITES|EXTEND_VSTRUCT;
      GfxAssociate(&sec_view, sec_vextra);
      sec_view.Modes = LACE|HIRES|SPRITES|EXTEND_VSTRUCT;
      if(monspec=OpenMonitor(NULL,modeID) ){
        ft_vextra->Monitor=monspec;
        sec_vextra->Monitor=monspec;
      }
      else{
        clean_local();
        alert("Could not get Monitor Spec (viewstart)\n");
      }
    }
    else{
       clean_local();
       alert("Could not allocate viewextra (viewstart)\n");
    }
  }
  #ifdef TEST
    write_log("viewstart PASSED\n",PRIONE);
  #endif
}

void ras_init()
{
  ft_rasinfo.BitMap = &ft_bitmap;
  ft_rasinfo.RxOffset = RX_OFFSET;
  ft_rasinfo.RyOffset = RY_OFFSET;
  ft_rasinfo.Next = NULL;
  InitRastPort(&ft_rastport);

  ft_rastport.BitMap=&ft_bitmap;
  ft_rastport.Mask = 0xFF;

  sec_rasinfo.BitMap = &sec_bitmap;
  sec_rasinfo.RxOffset = RX_OFFSET;
  sec_rasinfo.RyOffset = RY_OFFSET;
  sec_rasinfo.Next = NULL;
  InitRastPort(&sec_rastport);
  sec_rastport.BitMap=&sec_bitmap;
  sec_rastport.Mask = 0xFF;

  thd_rasinfo.BitMap = &thd_bitmap;
  thd_rasinfo.RxOffset = RX_OFFSET;
  thd_rasinfo.RyOffset = RY_OFFSET;
  thd_rasinfo.Next = NULL;
  InitRastPort(&thd_rastport);
  thd_rastport.BitMap=&thd_bitmap;
  #ifdef TEST
    write_log("ras_init PASSED\n",PRIONE);
  #endif
}

/* void viewportstart(void)
   Initiliases the viewport structure. DX and DY Offsets are
   set to 0 (by InitVPort) (wb1.3).  I have selected hires and interlace
   modes. Remember to initialise the colour table before issuing
   this function. */

void viewportstart()
{
UWORD *colorptr=NULL;

int loop;
ULONG size;

  for(loop=0;loop<COLOURS;loop++){
    vpone_col[loop]=colour_table[0][loop];
    vptwo_col[loop]=colour_table[1][loop];
  }
  InitVPort(&ft_viewport);
  ft_viewport.Next = NULL;
  ft_viewport.DWidth = WIDTH;
  ft_viewport.DHeight = HEIGHT;
  ft_viewport.Modes = LACE|HIRES|SPRITES;
  ft_viewport.RasInfo = &ft_rasinfo;
  /* 2.0+ */
  cm = (struct ColorMap *) GetColorMap( COLOURS * 2 );
  if(cm==NULL){
    clean_local();
    alert("Couldn't allocate first colour map (viewportstart)\n");
  }
  if(wb_version>=36){
    ft_viewport.Modes=LACE|HIRES|SPRITES|EXTEND_VSTRUCT;
    vpone_extra=GfxNew(VIEWPORT_EXTRA_TYPE);
    if(vpone_extra!=NULL){
      voneTags[1].ti_Data = (ULONG) vpone_extra;
      size = (ULONG) sizeof(monstuff);
      /* Get Monitor Details */
      if(GetDisplayInfoData(NULL,(UBYTE *) &monstuff,size,DTAG_MNTR,modeID) == 0){
        clean_local();
        alert("Couldn't access display database - MonitorInfo (viewportstart)\n");
      }
      size = (ULONG) sizeof(distuff);
      /* Get Display Details */
      if(GetDisplayInfoData(NULL,(UBYTE *) &distuff,size,DTAG_DISP,modeID) == 0){
        clean_local();
        alert("Couldn't access display database - MonitorInfo (viewportstart)\n");
      }
      /* Putting correct monitor positions */
      ft_view.DxOffset = sec_view.DxOffset = monstuff.ViewPosition.x;
      ft_view.DyOffset = sec_view.DyOffset = monstuff.ViewPosition.y;
      size = (ULONG) sizeof(dimquery);
      /* Get dimension details */
      if(GetDisplayInfoData(NULL,(UBYTE *) &dimquery,size,DTAG_DIMS,modeID) != 0){
        vpone_extra->DisplayClip = dimquery.Nominal;
        voneTags[2].ti_Data = (ULONG) FindDisplayInfo(modeID);
        if(voneTags[2].ti_Data == NULL){
          clean_local();
          alert("Could not get the DimensionInfo (viewportstart)\n");
        }
      }
      else{
        clean_local();
        alert("Could not get DimensionInfo (viewportstart)\n");
      }
    }
    else{
      clean_local();
      alert("Couldn't allocate viewport1 extra (viewportstart)\n");
    }
    voneTags[0].ti_Data = (ULONG) &ft_viewport;
    if( VideoControl(cm,voneTags)!=NULL ){
      clean_local();
      alert("Could not attach ft_viewport (viewportstart)\n");
    }
    LoadRGB4(&ft_viewport,vpone_col,16);
  }
  else{
    ft_viewport.ColorMap = cm;
  }
  InitVPort(&sec_viewport);
  sec_viewport.Next = NULL;
  sec_viewport.DWidth = WIDTH;
  sec_viewport.DHeight = HEIGHT;
  sec_viewport.Modes = HIRES|LACE|SPRITES;
  sec_viewport.RasInfo = &sec_rasinfo;
  cmtwo = (struct ColorMap *) GetColorMap( COLOURS * 2 ); /* Was X2 */
  if(cmtwo==NULL){
    clean_local();
    alert("Couldn't alloacte second color map (viewportstart)\n");
    }
  if(wb_version>=36){
    sec_viewport.Modes=LACE|HIRES|SPRITES|EXTEND_VSTRUCT;
    if(vptwo_extra = GfxNew(VIEWPORT_EXTRA_TYPE) ) {
      vtwoTags[1].ti_Data = (ULONG) vptwo_extra;
      vptwo_extra->DisplayClip = dimquery.Nominal;
      if( !(vtwoTags[2].ti_Data = (ULONG) FindDisplayInfo(modeID) ) ){
         clean_local();
         alert("Could not get the DisplayInfo (viewportstart)\n");
      }
    }
    else{
      clean_local();
      alert("Couldn't allocate viewport extra (viewportstart)\n");
    }
    vtwoTags[0].ti_Data = (ULONG) &sec_viewport;
    if( VideoControl(cmtwo,vtwoTags) ){
      clean_local();
      alert("Could not attach sec_viewport (viewportstart)\n");
    }
    LoadRGB4(&sec_viewport,vptwo_col,16);
  }
  else{
    sec_viewport.ColorMap = cmtwo;
    colorptr =(UWORD *) ft_viewport.ColorMap->ColorTable;
    for (loop=0;loop<COLOURS;loop++){
      *colorptr++ = colour_table[0][loop];
    }
    colorptr =(UWORD *) sec_viewport.ColorMap->ColorTable;
    for (loop=0;loop<COLOURS;loop++){
      *colorptr++ = colour_table[1][loop];
    }
  }
  #ifdef TEST
    write_log("viewportstart PASSED\n",PRIONE);
  #endif
}

LONG scrtime(void){
int frame;
LONG vpnow = 1L;
LONG botvp = 0L;

    for(frame=0;frame<NFRAMES;frame++){
      do {
          if(botvp<vpnow) botvp=vpnow;
          vpnow=VBeamPos();
          } while(vpnow>botvp);
    }
    botvp-=6;
    return botvp;
}

void changepri(LONG priority){
struct Task *this_task=NULL;

    Forbid();
      this_task=FindTask(NULL);
      SetTaskPri(this_task,priority);
    Permit();
}

