Rotation

Source code

//========================================================
// Rotation transformation without filtering
// QUAGLIOZZI ERIC - Copyright 2007
//========================================================

/*
   Usable for low res (72 dpi) and double res (144 dpi)
   bitmap using 8 and 16 bits colors.
 ---------------------------------------------------------
 | Do not use with other resolutions, may system crash ! |
 ---------------------------------------------------------
*/

#if defined(_MSC_VER)     // If compiling with VC++...

    #define private        static __inline
    #define longint        __int64
    
#elif defined(__GNUC__)  // If compiling with GCC...

    #define private        static inline
    #define longint        long long int
    
#else

    #error "Unknown Compiler!"
    
#endif

#include "MathLibFixed.c"

//-------------------- Types -----------------------------


typedef unsigned long Call68KFuncType(const void * emulStateP,
                                      unsigned long trapOrFunction,
                                      const void * argsOnStackP,
                                      unsigned long argsSizeAndwantA0);

typedef unsigned long NativeFuncType(const void * emulStateP,
                                     void * userData68KP,
                                     Call68KFuncType * call68KFuncP);

typedef struct _ParamsType
  {    
    long                  SIN;            // SIN(o) format 32 bits IP:FP
    long                  COS;            // COS(o) format 32 bits IP:FP
    short                 WS;             // Width-height source & destination
    short                 HS;
    short                 WD;
    short                 HD;
    short                 Bitdepth;       //Bitdepth
    short                 Resolution;     //resolution
    short                 X0;             // X0 and Y0 16 bits format
    short                 Y0;           
    unsigned char         * pSrc;         // bitmap source pointer
    unsigned char         * pDest;        // bitmap destination pointer
  }
    ParamsType;


//--------------------- Rotate Function ------------------


unsigned long RotateFunc(const void * emulStateP, void * userData68KP,
                                         Call68KFuncType * call68KFuncP)
{
  ParamsType    * p;           //pointer to params structure
  long            cos, sin;
  unsigned char * src;
  unsigned char * dest;
  unsigned char * P1;          //Vars for computations
  unsigned char * P2;
  short   ws, hs, wd, hd;
  short   wslimit, wdlimit;
  short   is, js, id, jd;
  short   x0, y0;
  short   density, bitdepth;
  long    FixedR1;

  // Do local copy of params

  p=(ParamsType *) userData68KP;
  cos=p->COS; 
  sin=p->SIN;
  
  // change angle sign because dest to source
  sin=-sin;
  density=p->Resolution;       // density (same for both bitmap)
  bitdepth=p->Bitdepth;        // bithdepth = 1 pour 8 bits et 2 pour 16 bits
  x0=(p->X0)<<(density-1); 
  y0=(p->Y0)<<(density-1); 
  src=p->pSrc; 
  dest=p->pDest; 

  // get bitmap infos
  ws=(p->WS)<<(density-1);     // W and H for each bitmap
  wslimit=ws<<(bitdepth-1);
  if (wslimit & 0x0001) wslimit += 1;
  hs=(p->HS)<<(density-1);
  wd=(p->WD)<<(density-1);     // W and H for each bitmap
  wdlimit=wd<<(bitdepth-1);
  if (wdlimit & 0x0001) wdlimit += 1;
  hd=(p->HD)<<(density-1);

  //perform rotation
  P2=dest;
  if (bitdepth==1)
   {
    for (jd=0;jd<hd;jd++)  
    {
      for (id=0; id<wd; id++)
       {
          // compute pixel source coord. 
          FixedR1 = FPS_MUL(cos, IntToFixedPoint(jd-y0));
          FixedR1 = FixedR1 - FPS_MUL(sin, IntToFixedPoint(id-x0));
          js=y0+FixedPointToInt(FixedR1) ;
          FixedR1 = FPS_MUL(cos, IntToFixedPoint(id-x0));
          FixedR1 = FixedR1 + FPS_MUL(sin, IntToFixedPoint(jd-y0));
          is=x0+FixedPointToInt(FixedR1) ;
          // ensure it is inside the source bitmap
          if ((js>=0)&&(js<hs)&&(is>=0)&&(is<ws))
          {
             //couleur pixel dest = couleur pixel source
             P1=src+js*wslimit;
             P2[id]=P1[is];
          } 
       }
      P2+=wdlimit;
    }
   } // End of 8 bits case
  else
   {
    for (jd=0;jd<hd;jd++)  
    {
      for (id=0; id<wd; id++)
       {
          // compute pixel source coord. 
          FixedR1 = FPS_MUL(cos, IntToFixedPoint(jd-y0));
          FixedR1 = FixedR1 - FPS_MUL(sin, IntToFixedPoint(id-x0));
          js=y0+FixedPointToInt(FixedR1);
          FixedR1 = FPS_MUL(cos, IntToFixedPoint(id-x0));
          FixedR1 = FixedR1 + FPS_MUL(sin, IntToFixedPoint(jd-y0));
          is=x0+FixedPointToInt(FixedR1);
          // ensure it is inside the source bitmap
          if ((js>=0)&&(js<hs)&&(is>=0)&&(is<ws))
          {
             //couleur pixel dest = couleur pixel source
             P1=src+(long)js*(long)wslimit;
             P2[(id<<1)]=P1[(is<<1)];
             P2[(id<<1)+1]=P1[(is<<1)+1];
          } 
       }
      P2+=wdlimit;
    }
   } // End of 16 bits case 
  return 0;
}

//========================================================

//========================================================
// "MathLibFixed.c" file content
// Contenu du fichier "MathLibFixed.c"
//========================================================

// We use 20:12 fixed point computation

#define FixedPoint  12  

//--------------- Fixed point unsigned A/B ---------------
private long FPUS_DIV(long a, long b)
{
  longint A, B, R;
  int     i,n;
  R=0; A=a; B=b; n=0;
  //ensure A<B for this algorythm
  while(A>B)
  { B=B<<1;
    n+=1;  }
  n=n+1+FixedPoint;
  //div computation
  for (i=0; i<n; i++)
  {
   R=R<<1;
   if (A>B) { A=A-B; R+=1; }
   A=A<<1;    
  }
  return (long)(R);
}

//---------------- Fixed point signed A/B ----------------

private long FPS_DIV(long a, long b)
{
  longint A, B, R;
  int     i,n;
  char    sA, sB;
  // Absolute A and B values
  if (a<0) 
   { A = -a;  sA=0xFF; }
  else
   { A = a;  sA=0x00; }
  if (b<0) 
   { B = -b;  sB=0xFF; }
  else
   { B = b;  sB=0x00; }
  sA = sA ^ sB;
  R=0; n=0;
  //ensure A<B for this algorythm
  while(A>B)
  { B=B<<1;
    n+=1;  }
  n=n+1+FixedPoint;
  //div computation
  for (i=0; i<n; i++)
  {
   R=R<<1;
   if (A>B) { A=A-B; R+=1; }
   A=A<<1;    
  }
  //take care of sign
  if (sA != 0) R=-R;
  return (long)(R);
}

//------------------- Fixed point signed A*B -------------

private long FPS_MUL(long a, long b)
{
  return (long)(((longint) a * (longint) b)>>FixedPoint );
}


//------------------- FixedPointToInt --------------------
// extract the I part of fixed point and format it to int (16 bits)


#define FixedPointToInt(fixedPointnum) \
    ( (int) ( (long)(fixedPointnum)>>FixedPoint)  )


//------------------- IntToFixedPoint --------------------
// convert an int (16 bits) to fixed point 20:12 format

#define IntToFixedPoint(intnum) \
    ( (long)(intnum)<<FixedPoint )