TV effect

Source code

//========================================================
//
// TV Effect  - QUAGLIOZZI ERIC - 2006
// 
//========================================================

/*
   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 ! |
 ---------------------------------------------------------
*/


#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 {
    char hb_object_header[14];
    short swTransparent;
    unsigned char    * pData;
    short w;
    short wl;
    short h;
    short bitdepth;
    unsigned char swTranspColorH;
    unsigned char swTranspColorL;
    unsigned char swTranspIndex;
} ImageData;


typedef struct {
    unsigned char RGB4[1024];
} PalmOSPalette;    


typedef struct {
    unsigned char Index[216];
} PalmOSInverse;    

typedef struct {
    char hb_object_header[14];
    short  DebugShort; //for debug and padding
    long   DebugLong;
    ImageData     * swImagePointer;
    PalmOSPalette * pPalmOSPalette;
    PalmOSInverse * pPalmOSInverse;
    unsigned short    Alpha;
    unsigned short  NBBrigthlines;  // nombre de lignes claires
    unsigned short  NBlines;        // nombre de lignes du motif
    unsigned short  Indexline;      // index première ligne dans motif
    unsigned char DkIndex;          // Index Palette Couleur foncée
    unsigned char DkRed;            // Composante Rouge Couleur foncée
    unsigned char DkGreen;          // Composante Verte Couleur foncée
    unsigned char DkBlue;           // Composante Bleue Couleur foncée
} TVEFFECT;    


typedef struct _ParamsType
  {
    TVEFFECT          * TV;
  } ParamsType;


//--------------- TV Effect Function ---------------------


unsigned long TVEffect(const void * emulStateP, void * userData68KP,
                                      Call68KFuncType * call68KFuncP)
{
  ParamsType     * p;                //pointer to params structure
  TVEFFECT       * pTV;              //pointeur HB++ objet clsTVEffect 
  PalmOSPalette  * Pal;              //pointeur palette Palm OS
  PalmOSInverse  * InvPal;           //pointeur inverse Palette
  ImageData      * lpImage;          //pointeur Image structure
  unsigned char  * P0;               //pointer to pixels;
  short          w,wl,h;
  short          i,j;
  unsigned short  id, AlphaFactor;
  unsigned short  R,G,B;
  unsigned long   Rd,Gd,Bd;
  unsigned short  RGB, lCount;
  unsigned char   Dark;
  
  // Do local copy of params

  p=(ParamsType *) userData68KP;
  pTV = p->TV;
  Pal   =pTV->pPalmOSPalette;
  InvPal = pTV->pPalmOSInverse;
  lpImage = pTV->swImagePointer;
  w = lpImage->w;
  wl = lpImage->wl;
  h = lpImage->h;
  AlphaFactor = pTV->Alpha;
  lCount=pTV->Indexline;
  
  if (lpImage->bitdepth==1)
   {
      P0=lpImage->pData;
      for (j=0;j<h;j++)  
      {
        if(lCount++<pTV->NBBrigthlines) { Dark=1; } else { Dark=0; }       
        for (i=0; i<w; i++)
         {
           //couleur pixel source * ALPHA
           id = P0[i]<<2;
           R=Pal->RGB4[id+1];
           G=Pal->RGB4[id+2];
           B=Pal->RGB4[id+3];
           Rd=R*AlphaFactor;
           Gd=G*AlphaFactor;
           Bd=B*AlphaFactor;
           //couleur courante * (255-ALPHA)
           if (Dark) id=pTV->DkIndex<<2; else  id=0;
           R=Pal->RGB4[id+1];
           G=Pal->RGB4[id+2];
           B=Pal->RGB4[id+3];
           Rd+=R*(255-AlphaFactor);
           Gd+=G*(255-AlphaFactor);
           Bd+=B*(255-AlphaFactor);
           //couleur finale  (comme coef<=255, on est sur qu'il tient sur un byte)       
           R=Rd>>8;
           G=Gd>>8;
           B=Bd>>8;
           //Retrouve la couleur indexée la plus proche       
           R=((R+26)*5)>>8;     // (x*5)>>8 est ~ x/51 pour retrouver index
           G=((G+26)*5)>>8;
           B=((B+26)*5)>>8;
           P0[i]= InvPal->Index[R*36+G*6+B];  // copy new color
         }
         P0+=wl;
         if(lCount>=pTV->NBlines) { lCount=0; }
      }
   }  // end of 8 bits case
  else
   {
      P0=lpImage->pData;
      for (j=0;j<h;j++)  
       {
         id = 0;
         if(lCount++<pTV->NBBrigthlines) { Dark=1; } else { Dark=0; }
         for (i=0; i<w; i++)
         {
           //couleur pixel source * ALPHA
           RGB = (P0[id]<<8)|P0[id+1];
           R=(RGB >> 11) & 0x001F;
           G=(RGB >> 5) & 0x003F;
           B= RGB & 0x001F;
           Rd=R*AlphaFactor;
           Gd=G*AlphaFactor;
           Bd=B*AlphaFactor;
           //couleur courante normalisée * (255-ALPHA)
           if (Dark)
           {    R=pTV->DkRed>>3; // (5 bits)
                G=pTV->DkGreen>>2; // (6 bits)
                B=pTV->DkBlue>>3; // (5 bits)
            }
            else
            {    R=0x1F; 
                G=0x3F;
                B=0x1F;
            }    
           Rd+=R*(255-AlphaFactor);
           Gd+=G*(255-AlphaFactor);
           Bd+=B*(255-AlphaFactor);
           //couleur finale (comme coef<=255, on est sur qu'il tient sur un byte)       
           R=Rd>>8;
           G=Gd>>8;
           B=Bd>>8;
           if (R > 0x001F) R=0x001F;
           if (G > 0x003F) G=0x003F;
           if (B > 0x001F) B=0x001F;
           //Affecte nouvelle couleur         
           P0[id]  = (R<<3)|(G>>3);
           P0[id+1]= (G<<5)|(B);
           id +=2;
         }
         P0+=wl;
         if(lCount>=pTV->NBlines) { lCount=0; }
      }
   } // end of 16 bits case
  return 0;
}

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



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

//-------------- Global Macros and constants -------------

#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

#define Read68KUnaligned32(addr)            \
  (((((unsigned char *)(addr))[0]) << 24) | \
  ((((unsigned char *)(addr))[1]) << 16) |  \
  ((((unsigned char *)(addr))[2]) << 8) |   \
  ((((unsigned char *)(addr))[3])))        // For endianness conversions


#define Read68KUnaligned16(addr)            \
  (((((unsigned char *)(addr))[0]) << 8) | \
  ((((unsigned char *)(addr))[1])))        // For endianness conversions




#define Write68KUnaligned32(addr, value) \
    (((unsigned char *)(addr))[0] = (unsigned char)((unsigned long)(value) >> 24), \
     ((unsigned char *)(addr))[1] = (unsigned char)((unsigned long)(value) >> 16), \
     ((unsigned char *)(addr))[2] = (unsigned char)((unsigned long)(value) >> 8), \
     ((unsigned char *)(addr))[3] = (unsigned char)((unsigned long)(value)))


#define Write68KUnaligned16(addr, value) \
    (((unsigned char *)(addr))[0] = (unsigned char)((unsigned int)(value) >> 8), \
     ((unsigned char *)(addr))[1] = (unsigned char)((unsigned int)(value)))


#define EndianSwap16(n) (((((unsigned int) n) << 8) & 0xFF00) | \
                         ((((unsigned int) n) >> 8) & 0x00FF))

#define EndianSwap32(n) (((((unsigned long) n) << 24) & 0xFF000000) | \
                         ((((unsigned long) n) <<  8) & 0x00FF0000) | \
                         ((((unsigned long) n) >>  8) & 0x0000FF00) | \
                         ((((unsigned long) n) >> 24) & 0x000000FF))





//---------- Math Fixed Point Functions and macros -------


#define FixedPoint    12   // We use 20:12 fixed point computation

//>>>> 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) \
    ( (short) ( (long)(fixedPointnum)>>FixedPoint)  )


//>>>> IntToFixedPoint <<<<
// convert an int (16 bits) to fixed point format

#define IntToFixedPoint(intnum) \
    ( (long)(intnum)<<FixedPoint )
    
//some constants
const long ONEFixedPoint = 1<< FixedPoint;       // "1.0" au format fixed point
const long HalfFixedPoint = 1<< (FixedPoint-1);  // "0.5" au format fixed point