#include <rtgmaster/rtgmaster.h>
#include <pragmas/rtgmaster_pragmas.h>
#include <clib/rtgmaster_protos.h>
#include <rtgmaster/rtgsublibs.h>
#include <proto/graphics.h>
#include <intuition/screens.h>
#include <graphics/modeid.h>
#include <graphics/displayinfo.h>
#include <exec/execbase.h>
#include <exec/types.h>
#include <string.h>
#include <stdio.h>

/**********************************************************************
*                                                                     *
*                     rtgmaster game driver                           *
*                     Version 1.1                                     *
*                                                                     *
**********************************************************************/


#include "vid_rtgm.h"

#define NOPOINTER 0
#define POINTER 1
#define RTGMASTER 3
#define DOUBLEBUFFER 2
#define BLITTER 1
#define MOVE16 0

int rtgmpointer;
extern int rtgmtype;
int rtgmextravram;

struct ScreenReq *sr=0;
int modereq=0;

extern struct RTGMasterBase *RTGMasterBase; // Library Base of rtgmaster
extern struct ExecBase *SysBase; // ExecBase
extern struct RtgScreen *rtgm_scr; // The RtgScreen
extern void *rtgm_backingbuf; // Backing Buf of size of Screen
int pformat; // Pixelformat
int numbuf;

/*****************************************************************
* numbuf contains the number of allocated VRAM Buffers, this is  *
* needed by SwapBuffers to handle lvid->buffer correctly.        *
*****************************************************************/

int pmodetype;

/* To save the pcurrentmode->type for RTGM_Shutdown */

/*******************************************************************
* This structure is also found in the latest rtgmaster/rtgmaster.h *
* as RDCMPData. port should best not be used. It contains an       *
* IDCMP Messageport, but this port does not work for all WB        *
* Emulations. signal works for all WB Emulations, and contains the *
* 1<<UserPort->SigBit. *MouseX and *MouseY are the current         *
* Mousepositions (not MouseX, *MouseX, these are pointers !!!)     *
* This structure does not work with rtgPICA.library up to now, and *
* it needs at least rtgCGX.library V2.37 for CyberGraphX,Picasso96 *
* or Probench 3, at least rtgEGS.library V2.32 for EGS.
*******************************************************************/

extern struct RDCMPData *rtgport;
extern void *TheMap;

/*******************************************************************
* Video RAM Base Address of the Screen. This is ALWAYS the address *
* of the front buffer. If you use Doublebuffering, this variable   *
* will be set to the correct new value.                            *
*******************************************************************/

int convert;

/******************************************************************
* Is 0xd7<->'x' conversion needed ? (NOTE: This is only needed by *
* CyberGraphX 2, CyberGraphX 3 has an 'x', not a 0xd7. This code  *
* recognizes automatically, if conversion is needed or not.       *
******************************************************************/

extern void *extravram;

/******************************************************************
* If the rtgm_extravram variable is set to 1, one extra Buffer    *
* will be allocated and stored in this variable. numbuf will be   *
* set to the correct value.                                       *
******************************************************************/

extern int proc_type; // Is it a 040/060 ?
char BoardName[255]; // For the BoardName
extern int currentbuffer; // Current buffer for Doublebuffering

UWORD clearpointer[36] = {
 0x0, 0x0,
 0x0, 0x0,
 0x0, 0x0,
 0x0, 0x0,
 0x0, 0x0,
 0x0, 0x0,
 0x0, 0x0,
 0x0, 0x0,
 0x0, 0x0,
 0x0, 0x0,
 0x0, 0x0,
 0x0, 0x0,
 0x0, 0x0,
 0x0, 0x0,
 0x0, 0x0,
 0x0, 0x0,
 0x0, 0x0,
 0x0, 0x0
 };

extern __asm AmigaCC040(register __a0 APTR buffer,register __d0 int x,register __d1 int y,
        register __d2 int rows, register __a1 APTR dest,register __d3 int w,register __d4 int h);
extern __asm AmigaCC(register __a0 APTR buffer,register __d0 int x,register __d1 int y,
        register __d2 int rows, register __a1 APTR dest,register __d3 int w,register __d4 int h);
extern __asm MyCopy8(register __a0 APTR src,register __a1 APTR dest,register __d0 rowbytessrc,register __d1 rowbytesdest,
                    register __d2 srcx,register __d3 srcy,register __d4 width,register __d5 height);
extern __asm MyCopyBack8(register __a0 APTR src,register __a1 APTR dest,register __d0 rowbytessrc,register __d1 rowbytesdest,
                    register __d2 destx,register __d3 desty,register __d4 width,register __d5 height);
extern __asm MyCopy16(register __a0 APTR src,register __a1 APTR dest,register __d0 rowbytessrc,register __d1 rowbytesdest,
                    register __d2 srcx,register __d3 srcy,register __d4 width,register __d5 height);
extern __asm MyCopyBack16(register __a0 APTR src,register __a1 APTR dest,register __d0 rowbytessrc,register __d1 rowbytesdest,
                    register __d2 destx,register __d3 desty,register __d4 width,register __d5 height);
extern __asm MyCopy24(register __a0 APTR src,register __a1 APTR dest,register __d0 rowbytessrc,register __d1 rowbytesdest,
                    register __d2 srcx,register __d3 srcy,register __d4 width,register __d5 height);
extern __asm MyCopyBack24(register __a0 APTR src,register __a1 APTR dest,register __d0 rowbytessrc,register __d1 rowbytesdest,
                    register __d2 destx,register __d3 desty,register __d4 width,register __d5 height);
extern __asm MyCopy32(register __a0 APTR src,register __a1 APTR dest,register __d0 rowbytessrc,register __d1 rowbytesdest,
                    register __d2 srcx,register __d3 srcy,register __d4 width,register __d5 height);
extern __asm MyCopyBack32(register __a0 APTR src,register __a1 APTR dest,register __d0 rowbytessrc,register __d1 rowbytesdest,
                    register __d2 destx,register __d3 desty,register __d4 width,register __d5 height);


void __asm RTGM_SetPalette(register __a0 viddef_t *lvid, register __a1 vmode_t *pcurrentmode, register __a2 unsigned char *palette);
struct RDCMPData __asm *RTGM_SetMode (register __a0 viddef_t *lvid, register __a1 vmode_t *pcurrentmode);
void __asm RTGM_CloseMode (register __a0 viddef_t *lvid, register __a1 vmode_t *pcurrentmode);
void __asm RTGM8_BeginDirectRect (register __a0 viddef_t *lvid, register __a1 struct vmode_s *pcurrentmode, register __d0 int x,register __d1 int y, register __a2 byte *pbitmap, register __d2 int width, register __d3 int height);
void __asm RTGM8_EndDirectRect (register __a0 viddef_t *lvid, register __a1 struct vmode_s *pcurrentmode, register __d0 int x, register __d1 int y, register __d2 int width, register __d3 int height);
void __asm RTGM8_SwapBuffers (register __a0 viddef_t *lvid, register __a1 vmode_t *pcurrentmode, register __a2 vrect_t *rects,register __d0 int wait);
void __asm RTGM16_BeginDirectRect (register __a0 viddef_t *lvid, register __a1 struct vmode_s *pcurrentmode, register __d0 int x,register __d1 int y, register __a2 byte *pbitmap, register __d2 int width, register __d3 int height);
void __asm RTGM16_EndDirectRect (register __a0 viddef_t *lvid, register __a1 struct vmode_s *pcurrentmode, register __d0 int x, register __d1 int y, register __d2 int width, register __d3 int height);
void __asm RTGM16_SwapBuffers (register __a0 viddef_t *lvid, register __a1 vmode_t *pcurrentmode, register __a2 vrect_t *rects,register __d0 int wait);
void __asm RTGM24_BeginDirectRect (register __a0 viddef_t *lvid, register __a1 struct vmode_s *pcurrentmode, register __d0 int x,register __d1 int y, register __a2 byte *pbitmap, register __d2 int width, register __d3 int height);
void __asm RTGM24_EndDirectRect (register __a0 viddef_t *lvid, register __a1 struct vmode_s *pcurrentmode, register __d0 int x, register __d1 int y, register __d2 int width, register __d3 int height);
void __asm RTGM24_SwapBuffers (register __a0 viddef_t *lvid, register __a1 vmode_t *pcurrentmode, register __a2 vrect_t *rects,register __d0 int wait);
void __asm RTGM32_BeginDirectRect (register __a0 viddef_t *lvid, register __a1 struct vmode_s *pcurrentmode, register __d0 int x,register __d1 int y, register __a2 byte *pbitmap, register __d2 int width, register __d3 int height);
void __asm RTGM32_EndDirectRect (register __a0 viddef_t *lvid, register __a1 struct vmode_s *pcurrentmode, register __d0 int x, register __d1 int y, register __d2 int width, register __d3 int height);
void __asm RTGM32_SwapBuffers (register __a0 viddef_t *lvid, register __a1 vmode_t *pcurrentmode, register __a2 vrect_t *rects,register __d0 int wait);

// INPUT : pixformats - Engine supported pixformats
// OUTPUT: A chained list of vmode_t structures with all the possibles screenmodes
// NOTE: vmode_t structures MUST be allocated with AllocVec function

vmode_t __asm *RTGM_Init(register __d0 int pixformats,register __d1 int type, register __d2 int pointer, register __d3 int extra, register __a0 struct MyMode *mymode)
{
 int width,height;
 vmode_t *video,*oldvideo=NULL,*firstvideo=NULL;
 struct RtgLibs *SubLib;
 struct ScreenMode *SMList;
 char *q;

 // First open rtgmaster.library of at least V14.

 rtgmtype=type;
 rtgmpointer=pointer;
 rtgmextravram=extra;
 currentbuffer=0;
 proc_type=0;
 RTGMasterBase = (struct RTGMasterBase *)OpenLibrary("rtgmaster.library",14);

 pformat=pixformats;
 modereq=0;
 if (RTGMasterBase)
 {

  // Get the List of Screenmodes

  SubLib=RTGMasterBase->Libraries;
  SMList=SubLib->SMList;
  while (strstr(SMList->Name,"TestScreen")) SMList=(struct ScreenMode *)(SMList->ScrNode).mln_Succ;
  while((SMList->ScrNode).mln_Succ!=0)
  {
   // As long as there is still a valid screenmode

   SMList=(struct ScreenMode *)(SMList->ScrNode).mln_Succ;
   if (((SMList->ChunkySupport&4)&&(pixformats&RGB16))||((SMList->ChunkySupport&32)&&(pixformats&BGR24))||((SMList->ChunkySupport&2)&&(pixformats&RGB24))||((SMList->ChunkySupport&256)&&(pixformats&RGBA32))||((SMList->ChunkySupport&32768)&&(pixformats&&BGRA32))||((SMList->ChunkySupport&1)&&(pixformats&ARGB32))||((SMList->ChunkySupport&16384)&&(pixformats&BGR16PC))||((SMList->ChunkySupport&8192)&&(pixformats&RGB16PC))||((SMList->ChunkySupport&4096)&&(pixformats&BGR15PC))||((SMList->ChunkySupport&2048)&&(pixformats&RGB15PC))||((SMList->ChunkySupport&64)&&(pixformats&BGR16))||((SMList->ChunkySupport&128)&&(pixformats&BGR15))||((SMList->ChunkySupport&8)&&(pixformats&RGB15))||((SMList->ChunkySupport&512)&&(pixformats&LUT8)))
   {

    // If the Screenmode supports 8 Bit (Bit 9 set) and
    // if the engine supports LUT8

    // Get Width and height

    char *hilf;
    width=(SMList->StandardOverscan).Width;
    height=(SMList->StandardOverscan).Height;
    if (!strstr(SMList->Name,"TestScreen"))
    {
     // Get Boardname for later Screenmode comparision...
     int TrueColor;
     TrueColor=0;

     strcpy(&BoardName[0],SMList->Name);
     hilf=strstr(&BoardName[0],":");
     hilf[0]='\0';

     // Set Maximum resolutions :
     // No Maximum for 8 Bit
     // 640x480 for 16 Bit
     // 320x240 for 24 Bit

     if ((SMList->ChunkySupport&1)||(SMList->ChunkySupport&32768)||(SMList->ChunkySupport&256)||(SMList->ChunkySupport&2)||(SMList->ChunkySupport&32)) TrueColor=1;
     if ((width>=320)&&(height>=200)&&(((width<=640)&&(height<=480))||(SMList->ChunkySupport&512))&&(((width<=320)&&(height<=240))||(!(TrueColor))))
     {
      // Now transform rtgmaster Screenmode format to AmigaQuake
      // Screenmode Format

      if (video=AllocVec(sizeof(vmode_t),MEMF_PUBLIC|MEMF_CLEAR))
      {
       if (firstvideo) oldvideo->pnext=video;
       else firstvideo=video;
       oldvideo=video;
       video->ID = SMList->ModeID;
       video->width= width;
       video->height= height;

       // Set rowbytes according to Screen-Depth

       if (SMList->ChunkySupport&512) video->rowbytes=video->width;
       else if (SMList->ChunkySupport&1) video->rowbytes=4*(video->width);
       else if (SMList->ChunkySupport&32768) video->rowbytes=4*(video->width);
       else if (SMList->ChunkySupport&256) video->rowbytes=4*(video->width);
       else if (SMList->ChunkySupport&2) video->rowbytes=3*(video->width);
       else if (SMList->ChunkySupport&32) video->rowbytes=3*(video->width);
       else video->rowbytes=2*(video->width);
       video->setpalette = &RTGM_SetPalette;
       video->setmode = &RTGM_SetMode;
       video->closemode= &RTGM_CloseMode;

       // Set Swapbuffers function according to Screen-Depth

       if (SMList->ChunkySupport&512) video->swapbuffers = &RTGM8_SwapBuffers;
       else if (SMList->ChunkySupport&1) video->swapbuffers= &RTGM32_SwapBuffers;
       else if (SMList->ChunkySupport&32768) video->swapbuffers= &RTGM32_SwapBuffers;
       else if (SMList->ChunkySupport&256) video->swapbuffers= &RTGM32_SwapBuffers;
       else if (SMList->ChunkySupport&2) video->swapbuffers= &RTGM24_SwapBuffers;
       else if (SMList->ChunkySupport&32) video->swapbuffers= &RTGM24_SwapBuffers;
       else video->swapbuffers=&RTGM16_SwapBuffers;

       video->sendkeyevents=&Sys_SendKeyEvents;

       // Set BeginDirectRect Function according to Screen-Depth

       if (SMList->ChunkySupport&512) video->begindirectrect = &RTGM8_BeginDirectRect;
       else if (SMList->ChunkySupport&1) video->begindirectrect= &RTGM32_BeginDirectRect;
       else if (SMList->ChunkySupport&32768) video->begindirectrect= &RTGM32_BeginDirectRect;
       else if (SMList->ChunkySupport&256) video->begindirectrect= &RTGM32_BeginDirectRect;
       else if (SMList->ChunkySupport&2) video->begindirectrect= &RTGM24_BeginDirectRect;
       else if (SMList->ChunkySupport&32) video->begindirectrect= &RTGM24_BeginDirectRect;
       else video->begindirectrect=&RTGM16_BeginDirectRect;

       // Set EndDirectRect Function according to Screen-Depth

       if (SMList->ChunkySupport&512) video->enddirectrect = &RTGM8_EndDirectRect;
       else if (SMList->ChunkySupport&1) video->enddirectrect= &RTGM32_EndDirectRect;
       else if (SMList->ChunkySupport&32768) video->enddirectrect= &RTGM32_EndDirectRect;
       else if (SMList->ChunkySupport&256) video->enddirectrect= &RTGM32_EndDirectRect;
       else if (SMList->ChunkySupport&2) video->enddirectrect= &RTGM24_EndDirectRect;
       else if (SMList->ChunkySupport&32) video->enddirectrect= &RTGM24_EndDirectRect;
       else video->enddirectrect=&RTGM16_EndDirectRect;

       // Set video-type according to Pixelformat

       if (SMList->ChunkySupport&512) video->type=PIXFMT_LUT8;
       else if (SMList->ChunkySupport&4) video->type=PIXFMT_RGB16;
       else if (SMList->ChunkySupport&8) video->type=PIXFMT_RGB15;
       else if (SMList->ChunkySupport&64) video->type=PIXFMT_BGR16;
       else if (SMList->ChunkySupport&128) video->type=PIXFMT_BGR15;
       else if (SMList->ChunkySupport&2048) video->type=PIXFMT_RGB15PC;
       else if (SMList->ChunkySupport&4096) video->type=PIXFMT_BGR15PC;
       else if (SMList->ChunkySupport&8192) video->type=PIXFMT_RGB16PC;
       else if (SMList->ChunkySupport&16384) video->type=PIXFMT_BGR16PC;
       else if (SMList->ChunkySupport&1) video->type=PIXFMT_ARGB32;
       else if (SMList->ChunkySupport&32768) video->type=PIXFMT_BGRA32;
       else if (SMList->ChunkySupport&256) video->type=PIXFMT_RGBA32;
       else if (SMList->ChunkySupport&2) video->type=PIXFMT_RGB24;
       else if (SMList->ChunkySupport&32) video->type=PIXFMT_BGR24;
                        
       if (rtgmtype==DOUBLEBUFFER) {
                                video->numpages=2;
                                video->direct=1;
                        }
       else if (rtgmtype==BLITTER) {
       video->numpages=1;
       video->direct=1;
                        }
       else  {
       video->numpages=1;
       video->direct=1;

                        }

/*****************************************************
* This is direct draw, but only one buffer currently *
* (under some WB Emulations, including CyberGraphX,  *
* DBuffering is a bit flickering currently)          *
*****************************************************/

// And the name of the Screenmode...
// BoardName replaced with RtgMaster:

       strcpy(video->name,"RTGMaster:");
       hilf=strstr(SMList->Name,":");
       hilf+=2;
       strcat(video->name,hilf);
       hilf=video->name;
       q=hilf;
       convert=0;

/****************************************************************
* The next lines of code convert the 0xd7 char of CyberGraphX 2 *
* to an 'x'. I could not test this code, as there is no 0xd7    *
* under CyberGraphX 3. Under CyberGraphX 3 the normal 'x' is    *
* used. But the code should work...                             *
* convert is set, if a conversion was needed. It is used by the *
* SetMode function, so that Screenmodes are correctly found.    *
****************************************************************/

       while (*hilf!=0)
       {
        if (*hilf=='×')
        {
         *q++='x';
         convert=1;
         *hilf++;
        }
        else *q++=*hilf++;
       }
       *q++=0;
      }
     }
    }
   }
  }
 }
 if (mymode)
 {
  struct TagItem rtag[] = {
    smr_MinWidth,       320,
    smr_MinHeight,      200,
    smr_MaxWidth,       640,
    smr_MaxHeight,      512,
    smr_ChunkySupport,  512,
    smr_PlanarSupport,  128,
    smr_ProgramUsesC2P, 0,
    TAG_DONE,           NULL
  };

  char  *hilf;

  modereq=1;
  rtag[0].ti_Data=mymode->minwidth;
  rtag[1].ti_Data=mymode->minheight;
  rtag[2].ti_Data=mymode->maxwidth;
  rtag[3].ti_Data=mymode->maxheight;
  rtag[4].ti_Data=mymode->support;
  sr=RtgScreenModeReq(rtag);
  width=sr->Width;
  height=sr->Height;
  if (((sr->ScreenMode)->ChunkySupport)==0) return(0);
  video=firstvideo;
  {
   SMList=sr->ScreenMode;
   video->ID = SMList->ModeID;
   video->width= width;
   video->height= height;

   // Set rowbytes according to Screen-Depth

   width=(SMList->StandardOverscan).Width;
   if (SMList->ChunkySupport&512) video->rowbytes=width;
   else if (SMList->ChunkySupport&1) video->rowbytes=4*(width);
   else if (SMList->ChunkySupport&32768) video->rowbytes=4*(width);
   else if (SMList->ChunkySupport&256) video->rowbytes=4*(width);
   else if (SMList->ChunkySupport&2) video->rowbytes=3*(width);
   else if (SMList->ChunkySupport&32) video->rowbytes=3*(width);
   else video->rowbytes=2*(width);
   video->setpalette = &RTGM_SetPalette;
   video->setmode = &RTGM_SetMode;
   video->closemode= &RTGM_CloseMode;

   // Set Swapbuffers function according to Screen-Depth

   if (SMList->ChunkySupport&512) video->swapbuffers = &RTGM8_SwapBuffers;
   else if (SMList->ChunkySupport&1) video->swapbuffers= &RTGM32_SwapBuffers;
   else if (SMList->ChunkySupport&32768) video->swapbuffers= &RTGM32_SwapBuffers;
   else if (SMList->ChunkySupport&256) video->swapbuffers= &RTGM32_SwapBuffers;
   else if (SMList->ChunkySupport&2) video->swapbuffers= &RTGM24_SwapBuffers;
   else if (SMList->ChunkySupport&32) video->swapbuffers= &RTGM24_SwapBuffers;
   else video->swapbuffers=&RTGM16_SwapBuffers;
   video->sendkeyevents=&Sys_SendKeyEvents;

   // Set BeginDirectRect Function according to Screen-Depth

   if (SMList->ChunkySupport&512)
   {
    video->begindirectrect = &RTGM8_BeginDirectRect;
   }
   else if (SMList->ChunkySupport&1) video->begindirectrect= &RTGM32_BeginDirectRect;
   else if (SMList->ChunkySupport&32768) video->begindirectrect= &RTGM32_BeginDirectRect;
   else if (SMList->ChunkySupport&256) video->begindirectrect= &RTGM32_BeginDirectRect;
   else if (SMList->ChunkySupport&2) video->begindirectrect= &RTGM24_BeginDirectRect;
   else if (SMList->ChunkySupport&32) video->begindirectrect= &RTGM24_BeginDirectRect;
   else video->begindirectrect=&RTGM16_BeginDirectRect;

   // Set EndDirectRect Function according to Screen-Depth

   if (SMList->ChunkySupport&512) video->enddirectrect = &RTGM8_EndDirectRect;
   else if (SMList->ChunkySupport&1) video->enddirectrect= &RTGM32_EndDirectRect;
   else if (SMList->ChunkySupport&32768) video->enddirectrect= &RTGM32_EndDirectRect;
   else if (SMList->ChunkySupport&256) video->enddirectrect= &RTGM32_EndDirectRect;
   else if (SMList->ChunkySupport&2) video->enddirectrect= &RTGM24_EndDirectRect;
   else if (SMList->ChunkySupport&32) video->enddirectrect= &RTGM24_EndDirectRect;
   else video->enddirectrect=&RTGM16_EndDirectRect;

   // Set video-type according to Pixelformat

   if (SMList->ChunkySupport&512) video->type=PIXFMT_LUT8;
   else if (SMList->ChunkySupport&4) video->type=PIXFMT_RGB16;
   else if (SMList->ChunkySupport&8) video->type=PIXFMT_RGB15;
   else if (SMList->ChunkySupport&64) video->type=PIXFMT_BGR16;
   else if (SMList->ChunkySupport&128) video->type=PIXFMT_BGR15;
   else if (SMList->ChunkySupport&2048) video->type=PIXFMT_RGB15PC;
   else if (SMList->ChunkySupport&4096) video->type=PIXFMT_BGR15PC;
   else if (SMList->ChunkySupport&8192) video->type=PIXFMT_RGB16PC;
   else if (SMList->ChunkySupport&16384) video->type=PIXFMT_BGR16PC;
   else if (SMList->ChunkySupport&1) video->type=PIXFMT_ARGB32;
   else if (SMList->ChunkySupport&32768) video->type=PIXFMT_BGRA32;
   else if (SMList->ChunkySupport&256) video->type=PIXFMT_RGBA32;
   else if (SMList->ChunkySupport&2) video->type=PIXFMT_RGB24;
   else if (SMList->ChunkySupport&32) video->type=PIXFMT_BGR24;

   if (rtgmtype==DOUBLEBUFFER) {
                                video->numpages=2;
                                video->direct=1;
                        }
   else if (rtgmtype==BLITTER) {
   video->numpages=1;
   video->direct=1;
                        }
   else  {
   video->numpages=1;
   video->direct=1;

                        }

/*****************************************************
* This is direct draw, but only one buffer currently *
* (under some WB Emulations, including CyberGraphX,  *
* DBuffering is a bit flickering currently)          *
*****************************************************/

// And the name of the Screenmode...
// BoardName replaced with RtgMaster:

   strcpy(video->name,"RTGMaster:");
   hilf=strstr(SMList->Name,":");
   hilf+=2;
   strcat(video->name,hilf);
   hilf=video->name;
   q=hilf;
   convert=0;

/****************************************************************
* The next lines of code convert the 0xd7 char of CyberGraphX 2 *
* to an 'x'. I could not test this code, as there is no 0xd7    *
* under CyberGraphX 3. Under CyberGraphX 3 the normal 'x' is    *
* used. But the code should work...                             *
* convert is set, if a conversion was needed. It is used by the *
* SetMode function, so that Screenmodes are correctly found.    *
****************************************************************/

   while (*hilf!=0)
   {
    if (*hilf=='×')
    {
     *q++='x';
     convert=1;
     *hilf++;
    }
    else *q++=*hilf++;
   }
   *q++=0;
 }
 }
 // Is this a 040/060 ?

 proc_type=SysBase->AttnFlags&AFF_68040;
 if (!(SMList->ChunkySupport)) return(0);
 else return(firstvideo);
}

void __asm RTGM_SetPalette(register __a0 viddef_t *lvid, register __a1 vmode_t *pcurrentmode, register __a2 unsigned char *palette)
{
        // Works nearly the same like under CyberGraphX, only the
        // Library function is another one...

        struct ColTable coltablex;
        int x;
        if (rtgm_scr) {
                coltablex.num_colors=256;
                coltablex.start_color=0;
                coltablex.pad1=0;
                coltablex.pad2=0;
                coltablex.pad3=0;
                for(x=0;x<256;x++) {
                        coltablex.color[x].red=palette[x*3]<<24|palette[x*3]<<16|palette[x*3]<<8|palette[x*3];
                        coltablex.color[x].green=palette[x*3+1]<<24|palette[x*3+1]<<16|palette[x*3+1]<<8|palette[x*3+1];
                        coltablex.color[x].blue=palette[x*3+2]<<24|palette[x*3+2]<<16|palette[x*3+2]<<8|palette[x*3+2];
                }

                // This is a function of rtgmaster.library...
                // Only set the Palette, if this is an 8 Bit Screen

                if (pcurrentmode->type==PIXFMT_LUT8) LoadRGBRtg(rtgm_scr,(ULONG *)&coltablex);
        }
}

//INPUT : viddef_t and vmode_t structures, IDCMP with the wanted IDCMPs
//OUTPUT : vidport or -1 Not Enough memory, -2 Unable to open screen, -3 Unable to open window

struct RDCMPData __asm *RTGM_SetMode (register __a0 viddef_t *lvid, register __a1 vmode_t *pcurrentmode) {


        struct ScreenReq myscreenreq;
        struct TagItem myscreentags[2]={rtg_Buffers,3,TAG_END,0};
        struct TagItem grdtags[]={grd_BytesPerRow,0,TAG_END,0};

        struct ScreenMode *SMList;
        struct RtgLibs *SubLib;

        numbuf=3;

        if ((rtgmextravram==0)&&((rtgmtype==DOUBLEBUFFER)||(rtgmtype==BLITTER)))
         {myscreentags[0].ti_Data=2;numbuf=2;}
        else if ((rtgmextravram==0)&&((rtgmtype==MOVE16)||(rtgmtype==MOVEM)||(rtgmtype==RTGMASTER)))
         {myscreentags[0].ti_Data=1;numbuf=1;}
        else if ((rtgmextravram==1)&&((rtgmtype==MOVE16)||(rtgmtype==MOVEM)||(rtgmtype==RTGMASTER)))
         {myscreentags[0].ti_Data=2;numbuf=2;}

        /*********************************************************************
        * Only the really needed VRAM Buffers will be allocated.
        *********************************************************************/


        // As we do not use the Screenmode-Requester of rtgmaster.library,
        // we have to "fake" a ScreenReq Structure...


        // Set the Screen-Depth according to the Pixelformat

        if (pcurrentmode->type==PIXFMT_LUT8) myscreenreq.Depth=8;
        else if ((pcurrentmode->type==PIXFMT_ARGB32)||(pcurrentmode->type==PIXFMT_BGRA32)||(pcurrentmode->type==PIXFMT_RGBA32)||(pcurrentmode->type==PIXFMT_RGB24)||(pcurrentmode->type==PIXFMT_BGR24)) myscreenreq.Depth=24;
        else myscreenreq.Depth=16;

        pmodetype=pcurrentmode->type;

        // Normally the Screenmode-Requester sets the flags, as we do not use the
        // Screenmode-Requester of rtgmaster, we have to do this ourselves...

        myscreenreq.Flags=14;
        myscreenreq.Overscan=0;
        currentbuffer=0;

        // The Screenmode-entry of ScreenReq is a bit difficult to find
        // (i identify it by name !!!)

        if (RTGMasterBase)
        {
         int found;
         found=0;
         SubLib=RTGMasterBase->Libraries;
         SMList=SubLib->SMList;
         while(((SMList->ScrNode).mln_Succ!=0)&&(!(found)))
         {
          SMList=(struct ScreenMode *)(SMList->ScrNode).mln_Succ;
          if (((SMList->ChunkySupport&512)||(SMList->ChunkySupport&1)||(SMList->ChunkySupport&4)||(SMList->ChunkySupport&64)||(SMList->ChunkySupport&2048)||(SMList->ChunkySupport&128)||(SMList->ChunkySupport&4096)||(SMList->ChunkySupport&8192)||(SMList->ChunkySupport&16384)||(SMList->ChunkySupport&32768)||(SMList->ChunkySupport&256)||(SMList->ChunkySupport&2)||(SMList->ChunkySupport&32)||(SMList->ChunkySupport&8))&&((pformat&LUT8)||(pformat&ARGB32)||(pformat&BGR16)||(pformat&BGR15)||(pformat&RGB16)||(pformat&BGR24)||(pformat&RGB24)||(pformat&RGBA32)||(pformat&BGRA32)||(pformat&BGR16PC)||(pformat&RGB16PC)||(pformat&BGR15PC)||(pformat&RGB15PC)||(pformat&RGB15))&&(!strstr(SMList->Name,"TestScreen")))
          {
           // Replace RtgMaster: again with BoardName: and compare
           // Screenmodes

           char hilf[255];
           char *hilf2;
           char *q;
           strcpy(&hilf[0],BoardName);
           hilf2=strstr(pcurrentmode->name,":");
           strcat(&hilf[0],": ");
           hilf2++;
           strcat(&hilf[0],hilf2);

           hilf2=&hilf[0];
           q=hilf2;
           while (*hilf2!=0)
           {
            if ((*hilf2=='x')&&convert)
            {
             *q++='×';
             *hilf2++;
             // Only convert back, if conversion is needed. Conversion is
             // NOT needed for CyberGraphX 3 for example. CyberGraphX 3
             // already uses a "normal" 'x'.
            }
            else *q++=*hilf2++;
           }
           *q++=0;
           if (!(stricmp(SMList->Name,&hilf[0])))
           {
            myscreenreq.ScreenMode=SMList;
            myscreenreq.Width=SMList->StandardOverscan.Width;
            myscreenreq.Height=SMList->StandardOverscan.Height;
            found=1;
           }
          }
         }
        if (!(rtgm_scr=OpenRtgScreen(&myscreenreq,myscreentags))) return(-2);
        }
        if (rtgmpointer==0)
                RtgSetPointer(rtgm_scr,clearpointer,16,16,-15,-7);
        // Lock it and get Video RAM Base Address
        TheMap=LockRtgScreen(rtgm_scr);

        // Get a background Buffer in Video Memory
        lvid->numpages=1;
        if ((rtgmtype==MOVE16)||(rtgmtype==MOVEM)||(rtgmtype==RTGMASTER))
        {
         if (pcurrentmode->type==PIXFMT_LUT8) {lvid->buffer=AllocMem(lvid->width*lvid->height,MEMF_FAST|MEMF_CLEAR);}
         else if ((pcurrentmode->type==PIXFMT_ARGB32)||(pcurrentmode->type==PIXFMT_BGRA32)||(pcurrentmode->type==PIXFMT_RGBA32)) lvid->buffer=AllocMem(lvid->width*lvid->height*4,MEMF_FAST|MEMF_CLEAR);
         else if ((pcurrentmode->type==PIXFMT_RGB24)||(pcurrentmode->type==PIXFMT_BGR24)) lvid->buffer=AllocMem(lvid->width*lvid->height*3,MEMF_FAST|MEMF_CLEAR);
         else lvid->buffer=AllocMem(lvid->width*lvid->height*2,MEMF_FAST|MEMF_CLEAR);
        }
        if (rtgmtype==DOUBLEBUFFER) {
         lvid->buffer=GetBufAdr(rtgm_scr,1);
         lvid->numpages=2;
        }
        else if (rtgmtype==BLITTER)
        {
         lvid->buffer=GetBufAdr(rtgm_scr,1);
        }
        if ((rtgmextravram==1)&&(rtgmtype!=MOVE16)&&(rtgmtype!=MOVEM)&&(rtgmtype!=RTGMASTER)) extravram=GetBufAdr(rtgm_scr,2);
        else if (rtgmextravram==1) extravram=GetBufAdr(rtgm_scr,1);

        if (pcurrentmode->type==PIXFMT_LUT8) rtgm_backingbuf=AllocMem(24*24,MEMF_FAST|MEMF_CLEAR);
        else if ((pcurrentmode->type==PIXFMT_RGB24)||(pcurrentmode->type==PIXFMT_BGR24)) rtgm_backingbuf=AllocMem(24*24*3,MEMF_FAST|MEMF_CLEAR);
        else if ((pcurrentmode->type==PIXFMT_ARGB32)||(pcurrentmode->type==PIXFMT_BGRA32)||(pcurrentmode->type==PIXFMT_RGBA32)) rtgm_backingbuf=AllocMem(24*24*4,MEMF_FAST|MEMF_CLEAR);
        else rtgm_backingbuf=AllocMem(24*24*2,MEMF_FAST|MEMF_CLEAR);

        GetRtgScreenData(rtgm_scr,grdtags);
        pcurrentmode->rowbytes=grdtags[0].ti_Data;
        lvid->rowbytes=grdtags[0].ti_Data;
        rtgport=RtgInitRDCMP(rtgm_scr);
        return (rtgport);
}

void __asm RTGM_CloseMode (register __a0 viddef_t *lvid, register __a1 vmode_t *pcurrentmode) {

       if (rtgm_backingbuf)
       {
        if (pcurrentmode->type==PIXFMT_LUT8)
        {
         FreeMem(rtgm_backingbuf,24*24);
        }
        else if ((pcurrentmode->type==PIXFMT_RGB24)||(pcurrentmode->type==PIXFMT_BGR24))
        {
         FreeMem(rtgm_backingbuf,24*24*3);
        }
        else if ((pcurrentmode->type==PIXFMT_ARGB32)||(pcurrentmode->type==PIXFMT_BGRA32)||(pcurrentmode->type==PIXFMT_RGBA32))
        {
         FreeMem(rtgm_backingbuf,24*24*4);
        }
        else
        {
         FreeMem(rtgm_backingbuf,24*24*2);
        }
       }
       if ((lvid->buffer)&&((rtgmtype==RTGMASTER)||(rtgmtype==MOVEM)||(rtgmtype==MOVE16)))
       {
       if (pcurrentmode->type==PIXFMT_LUT8)
        {
         FreeMem(lvid->buffer,lvid->width*lvid->height);
        }
        else if ((pcurrentmode->type==PIXFMT_RGB24)||(pcurrentmode->type==PIXFMT_BGR24))
        {
         FreeMem(lvid->buffer,lvid->width*lvid->height*3);
        }
        else if ((pcurrentmode->type==PIXFMT_ARGB32)||(pcurrentmode->type==PIXFMT_BGRA32)||(pcurrentmode->type==PIXFMT_RGBA32))
        {
         FreeMem(lvid->buffer,lvid->width*lvid->height*4);
        }
        else
        {
         FreeMem(lvid->buffer,lvid->width*lvid->height*2);
        }
       }
        if (rtgm_scr) {

                // Unlock the Screen and Close it

                UnlockRtgScreen(rtgm_scr);
                CloseRtgScreen(rtgm_scr);
                rtgm_scr=NULL;
        }
    FreeVec(pcurrentmode);
    if (sr) {FreeRtgScreenModeReq(sr);sr=0;}
    CloseLibrary((struct Library *)RTGMasterBase);
}

