Newer
Older
ubixos / src / sys / graphics / objgfx30.cpp
/*******************************************************
$Id$
*******************************************************/

#include "objgfx30.h"
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ubixos/types.h>
// TGfx0 constructor

TGfx0::TGfx0(void) {
  DataState = og_None;
  Buffer = NULL;
  LineOfs = NULL;
  pal = NULL;
  xRes = 0;
  yRes = 0;
  MaxX = 0;
  MaxY = 0;
  bSize = 0;
  lSize = 0;
  TransparentColor = 0;
  BPP = 0;
  RedShifter = 0;
  GreenShifter = 0;
  BlueShifter = 0;
  RedFieldPosition = 0;
  GreenFieldPosition = 0;
  BlueFieldPosition = 0;
  return;
} // TGfx0::TGfx0()

bool
TGfx0::alias(TGfx0& SrcObject, UInt32 x1, UInt32 y1, UInt32 x2, UInt32 y2) {
  UInt32 tmp;
  if (DataState==og_Owner) return FALSE;

  if (x2<x1) {
    tmp= x2;
    x2 = x1;
    x1 = tmp;
  } // if
  if (y2<y1) {
    tmp= y2;
    y2 = y1;
    y1 = tmp;
  } // if 
  Owner = &SrcObject;
  Buffer =((unsigned char *)(SrcObject.Buffer)+x1*((SrcObject.BPP+7) >> 3));
  LineOfs=((UInt32 *)SrcObject.LineOfs)+y1;
  pal = SrcObject.pal;
  xRes = SrcObject.xRes;
  yRes = SrcObject.yRes;
  MaxX = (x2-x1);
  MaxY = (y2-y1);
  bSize = 0;
  lSize = 0;
  TransparentColor = SrcObject.TransparentColor;
  DataState = og_Aliasing;
  BPP = SrcObject.BPP;
  // For 8bpp modes the next part doesn't matter
  RedFieldPosition = SrcObject.RedFieldPosition;
  GreenFieldPosition = SrcObject.GreenFieldPosition;
  BlueFieldPosition = SrcObject.BlueFieldPosition;
  // The next part is only used by 15/16bpp
  RedShifter = SrcObject.RedShifter;
  GreenShifter = SrcObject.GreenShifter;
  BlueShifter = SrcObject.BlueShifter;
  return TRUE;
} // TGfx0::alias

void
TGfx0::arc(UInt32 x_center, UInt32 y_center, UInt32 radius, 
           UInt32 s_angle, UInt32 e_angle, UInt32 colour) {
  Int32 p;
  UInt32 x, y, tmp;
  double alpha;
  
  if (radius==0) {
    putPixel(x_center, y_center, colour);
    return;
  } // if

  s_angle%=361;
  e_angle%=361;

  if (s_angle>e_angle) {
    tmp = s_angle;
    s_angle = e_angle;
    e_angle = tmp;
  } // if
  
  x = 0;
  y = radius;
  p = 3-2*radius;
  
  while (x<=y) {
    alpha = RadToDeg(atan(x/y));
    if ((alpha>=s_angle) && (alpha<=e_angle))
      putPixel(x_center-x, y_center-y, colour);
    if ((90-alpha>=s_angle) && (90-alpha<=e_angle))
      putPixel(x_center-y, y_center-x, colour);
    if ((90+alpha>=s_angle) && (90+alpha<=e_angle))
      putPixel(x_center-y, y_center+x,colour);
    if ((180-alpha>=s_angle) && (180-alpha<=e_angle))
      putPixel(x_center-x, y_center+y,colour);
    if ((180+alpha>=s_angle) && (180+alpha<=e_angle))
      putPixel(x_center+x, y_center+y,colour);
    if ((270-alpha>=s_angle) && (270-alpha<=e_angle))
      putPixel(x_center+y, y_center+x,colour);
    if ((270+alpha>=s_angle) && (270+alpha<=e_angle))
      putPixel(x_center+y, y_center-x,colour);
    if ((360-alpha>=s_angle) && (360-alpha<=e_angle))
      putPixel(x_center+x, y_center-y,colour);
    if (p<0) p+=4*x+6;
    else {
      p+=4*(x-y)+10;
      y--;
    }
    x++;
  } // while
} // TGfx0::arc

void 
TGfx0::bar(Int32 x1, Int32 y1, Int32 x2, Int32 y2, UInt32 colour) {
  Int32 yy;
  Int32 tmp;

  if (x2<x1) {
    tmp= x2;
    x2 = x1;
    x1 = tmp;
  } // if
  if (y2<y1) {
    tmp= y2;
    y2 = y1;
    y1 = tmp;
  } // if 

  if ((y2<0) || (y1>(Int32)MaxY)) return;
  if (y1<0) y1=0;
  if (y2>(Int32)MaxY) y2=MaxY;
  for (yy=y1; yy<=y2; yy++)
    hLine(x1,x2,yy,colour);
} // TGfx0::bar

void 
TGfx0::circle(Int32 x_center, Int32 y_center, UInt32 radius, UInt32 colour) {
  Int32 x, y, d;
  x = 0;
  y = radius;
  d = 2*(1-radius);
  while (y>=0) {
    putPixel(x_center+x,y_center+y,colour);
    putPixel(x_center+x,y_center-y,colour);
    putPixel(x_center-x,y_center+y,colour);
    putPixel(x_center-x,y_center-y,colour);
    if (d + y > 0) {
      y--;
      d -= 2*y+1;
    } // if
    if (x > d) {
      x++;
      d += 2*x+1;
    } // if
  } // while
} // TGfx0::circle

void 
TGfx0::clear(UInt32 colour) {
  UInt32 height;
  if ((Buffer==NULL) || (LineOfs==NULL)) return;
  asm("cld\n");
  switch (BPP) {
    case 8:
      asm(
          "  add (%%esi), %%edi  \n"      // add edi, [esi]
          "  mov %%ecx, %%esi    \n"      // mov esi, ecx
          "  inc %%edx           \n"      // inc edx (MaxY)
          "  inc %%ebx           \n"      // inc ebx (MaxX)
          "  sub %%edx, %%esi    \n"      // sub esi, edx
          "  mov %%al, %%ah      \n"      // mov ah, al
          "  mov %%ax, %%cx      \n"      // mov cx, ax
          "  shl $16, %%eax      \n"      // shl eax, 16
          "  mov %%cx, %%ax      \n"      // mov ax, cx
      "loop8:                    \n"
          "  push %%edx          \n"
          "  mov %%edx, %%ecx    \n"      // mov ecx, edx
          "  and $3, %%edx       \n"      // and edx, 3
          "  shr $2, %%ecx       \n"      // shr ecx, 2
          " rep                  \n"
          " stosl                \n"      
          "  mov %%edx, %%ecx    \n"      // mov ecx, edx
          " rep                  \n"
          " stosb                \n"      
          "  pop %%edx           \n"
          "  add %%esi, %%edi    \n"      // add edi, esi
          "  dec %%ebx           \n"
          "   jnz loop8          \n"
        :
        : "D" (Buffer), "S" (LineOfs),           // %0, %1
          "a" (colour), "b" (MaxY),              // %2, %3
          "c" (xRes), "d" (MaxX)                 // %4, %5
      );
      break;
    case 15:
    case 16:
      asm(
          "  add (%%esi), %%edi  \n"      // add edi, [esi]
          "  mov %%ecx, %%esi    \n"      // mov esi, ecx
          "  inc %%edx           \n"      // inc edx (MaxX)
          "  inc %%ebx           \n"      // inc ebx (MaxY)
          "  sub %%edx, %%esi    \n"      // sub esi, edx
          "  sub %%edx, %%esi    \n"      // sub esi, edx // adjust for pix size
          "  mov %%ax, %%cx      \n"      // mov cx, ax
          "  shl $16, %%eax      \n"      // shl eax, 16
          "  mov %%cx, %%ax      \n"      // mov ax, cx
      "loop16:                   \n"
          "  mov %%edx, %%ecx    \n"      // mov ecx, edx
          "  shr $1, %%ecx       \n"      // shr ecx, 1
          " rep                  \n"
          " stosl                \n"      
          "  jnc noc16           \n"
          " stosw                \n"
      "noc16:                    \n"
          "  add %%esi, %%edi    \n"      // add edi, esi
          "  dec %%ebx           \n"
          "   jnz loop16         \n"
        :
        : "D" (Buffer), "S" (LineOfs),           // %0, %1
          "a" (colour), "b" (MaxY),              // %2, %3
          "c" (xRes), "d" (MaxX)                 // %4, %5
      );
      break;
    case 24:
      asm(
          "  add (%%esi), %%edi  \n"      // add edi, [esi]
          "  mov %%ecx, %%esi    \n"      // mov esi, ecx
          "  inc %%edx           \n"      // inc edx (MaxX)
          "  inc %%ebx           \n"      // inc ebx (MaxY)
          "  sub %%edx, %%esi    \n"      // sub esi, edx // adjust for pix size
          "  mov %%ebx, %6       \n"      // mov height, ebx
          "  sub %%edx, %%esi    \n"      // sub esi, edx // adjust for pix size
          "  mov %%eax, %%ebx    \n"      // mov ebx, eax
          "  sub %%edx, %%esi    \n"      // sub esi, edx // adjust for pix size
          "  shr $16, %%ebx      \n"      // shr ebx, 16
      "oloop24:                  \n"
          "  mov %%edx, %%ecx    \n"      // mov ecx, edx
      "iloop24:                  \n"
          "  mov %%ax,(%%edi)    \n"      // mov [edi],ax
          "  movb %%bl,2(%%edi)  \n"      // mov [edi+2],bl
          "  add $3, %%edi       \n"      // add edi, 3
          "  dec %%ecx           \n"      // dec ecx
          "   jnz iloop24        \n"
          "  add %%esi, %%edi    \n"      // add edi, esi
          "  decl %6             \n"      // dec height
          "   jnz oloop24        \n"
        :
        : "D" (Buffer), "S" (LineOfs),           // %0, %1
          "a" (colour), "b" (MaxY),              // %2, %3
          "c" (xRes), "d" (MaxX),                // %4, %5
          "g" (height)                           // %6
        );
      break;
    case 32:
      asm(
          "  add (%%esi), %%edi  \n"      // add edi, [esi]
          "  mov %%ecx, %%esi    \n"      // mov esi, ecx
          "  inc %%edx           \n"      // inc edx (MaxX)
          "  inc %%ebx           \n"      // inc ebx (MaxY)
          "  mov %%edx, %%ecx    \n"      // mov ecx, edx
          "  shl $2, %%ecx       \n"      // shl ecx, 2
          "  sub %%ecx, %%esi    \n"      // sub esi, ecx // adjust for pix size
      "loop32:                   \n"
          "  mov %%edx, %%ecx    \n"      // mov ecx, edx
          " rep                  \n"
          " stosl                \n"      
          "  add %%esi, %%edi    \n"      // add edi, esi
          "  dec %%ebx           \n"
          "   jnz loop32         \n"
        :
        : "D" (Buffer), "S" (LineOfs),           // %0, %1
          "a" (colour), "b" (MaxY),              // %2, %3
          "c" (xRes), "d" (MaxX)                 // %4, %5
     );
  }
} // TGfx0::clear

void 
TGfx0::clone(TGfx0& SrcObject) {
  TPixelFmt pixfmt;
  if (SrcObject.DataState==og_None) return;
  SrcObject.getPixFmt(pixfmt);
  create(SrcObject.MaxX+1,SrcObject.MaxY+1,pixfmt);
  if (pal!=NULL) memcpy(pal, SrcObject.pal, sizeof(TRGB)*256);
  copy(SrcObject);
} // TGfx0::clone

void 
TGfx0::copy(TGfx0& SrcObject) {
  UInt32 count, xCount, yCount;
  UInt32 xx, yy;
  UInt8  r, g, b;
  if ((Buffer==NULL) || (LineOfs==NULL)) return;
  if ((SrcObject.Buffer==NULL) || (SrcObject.LineOfs==NULL)) return;
  xCount = SrcObject.MaxX+1;
  if (xCount>MaxX+1) xCount=MaxX+1;
  yCount = SrcObject.MaxY+1;
  if (yCount>MaxY+1) yCount=MaxY+1;
  if ((BPP!=SrcObject.BPP) || (RedShifter!=SrcObject.RedShifter) ||
      (BlueShifter!=SrcObject.BlueShifter) || 
      (GreenShifter!=SrcObject.GreenShifter)) {
    for (yy=0; yy<=yCount-1; yy++)
      for (xx=0; xx<=xCount-1; xx++) {
        SrcObject.unpackRGB(SrcObject.getPixel(xx,yy),r,g,b);
        putPixel(xx,yy,RGB(r,g,b));
      } // for
  }  // if
  else
  {
    xCount *= ((BPP+7) >> 3); // adjust for bpp 
    for (count=0; count<=yCount-1; count++) ;
      memcpy(((char*)Buffer+LineOfs[count]),                        // dest
             ((char*)SrcObject.Buffer+SrcObject.LineOfs[count]),  // src
             xCount);                                               // len
  } // else
} // TGfx0::copy

void
TGfx0::copyBuf(Int32 DestX, Int32 DestY, 
               TGfx0& SrcObject, Int32 x1, Int32 y1, Int32 x2, Int32 y2) {
  UInt32 pixmap[256];
  Int32 xx,yy,count,xCount, yCount;
  UInt32 bm;        // bit multiplyer
  UInt8 r, g, b;
  
  if ((Buffer==NULL) || (LineOfs==NULL)) return;
  if ((SrcObject.Buffer==NULL) || (SrcObject.LineOfs==NULL)) return;
  
  if ((DestX>(Int32)MaxX) || (DestY>(Int32)MaxY)) return;
  
  if (x1>x2) {
    xx = x1;
    x1 = x2;
    x2 = xx;
  } // if
  if (y1>y2) {
    yy = y1;
    y1 = y2;
    y2 = yy;
  } // if

  xCount = abs(x2-x1)+1;
  yCount = abs(y2-y1)+1;
  
  if (DestX+xCount>(Int32)MaxX+1) xCount=MaxX-DestX+1;
  if (DestY+yCount>(Int32)MaxY+1) yCount=MaxY-DestY+1;

  if (DestX<0) {
    xCount += DestX;
    x1 -= DestX;
    DestX = 0;
  } // if
 
  if (DestY<0) {
    yCount += DestY;
    y1 -= DestY;
    DestY = 0;
  } // if
 
  if ((DestX+xCount<0) || (DestY+yCount<0)) return;

  if ((BPP!=SrcObject.BPP) || (RedShifter!=SrcObject.RedShifter) ||
      (BlueShifter!=SrcObject.BlueShifter) ||
      (GreenShifter!=SrcObject.GreenShifter)) {
    if (SrcObject.BPP==8) {
      for (xx=0; xx<256; xx++) 
        pixmap[xx] = RGB(SrcObject.pal[xx].red,
                         SrcObject.pal[xx].green,
                         SrcObject.pal[xx].blue);
      for (yy=0; yy<=yCount-1; yy++) 
        for (xx=0; xx<=xCount-1; xx++)
          putPixel(DestX+xx,DestY+yy,pixmap[SrcObject.getPixel(x1+xx,y1+yy)]); 
 
    } // if srcobject->bpp
    else
    {
      for (yy=0; yy<=yCount-1; yy++)
        for (xx=0; xx<=xCount-1; xx++) {
          SrcObject.unpackRGB(SrcObject.getPixel(x1+xx,y1+yy),r,g,b);
          putPixel(DestX+xx,DestY+yy,RGB(r,g,b));
        } // for
    } // else
  } // if
  else
  {
    bm = (BPP+7) >> 3;
    x1 *= bm;
    DestX *= bm;
    xCount *= bm;
    for (count=0; count<=yCount-1; count++) {
      memcpy(((char*)Buffer+LineOfs[DestY+count]+DestX),               // dest
             ((char*)SrcObject.Buffer+SrcObject.LineOfs[y1+count]+x1), // src
             xCount);                                                  // len
    
    }
  } // else
} // TGfx0::copyBuf

bool 
TGfx0::create(UInt32 _xRes, UInt32 _yRes,TPixelFmt _pixformat) {
  /*
   *  constructor TGfx0::create()
   *  Allocates memory for a buffer of size _xRes by _yRes with
   *  the pixel format defined in _pixformat.  Allocates memory
   *  for pal and LineOfs.
   */
  UInt32 yy;
  if (DataState==og_Owner) {
    if (Buffer!=NULL) free(Buffer);
    if (LineOfs!=NULL) free(LineOfs);
    if (pal!=NULL) free(pal);
  }  // if datastate
  BPP = _pixformat.BPP;
  bSize=_xRes*_yRes*((BPP+7) >> 3);
  Buffer = malloc(bSize);
  if (Buffer==NULL) return FALSE;
  memset(Buffer,0,bSize);
  lSize = _yRes*sizeof(UInt32);
  LineOfs = (UInt32*)malloc(lSize);
  if (LineOfs == NULL) return FALSE;
  pal = (TRGB*)malloc(256*sizeof(TRGB));
  if (pal == NULL) return FALSE;
  memset(pal,0,sizeof(TRGB)*256);
  MaxX=_xRes-1;
  xRes=_xRes*((BPP+7) >> 3);
  MaxY=_yRes-1;
  yRes=_yRes;
  LineOfs[0]=0;
  for (yy=1; yy<=MaxY; yy++)
    LineOfs[yy]=LineOfs[yy-1]+xRes;
  DataState = og_Owner;
  // For 8bpp modes the next part doesn't matter 
  RedFieldPosition=_pixformat.RedFieldPosition;
  GreenFieldPosition=_pixformat.GreenFieldPosition;
  BlueFieldPosition=_pixformat.BlueFieldPosition;
  // The next part is only used by 15/16hpp 
  RedShifter=8-_pixformat.RedMaskSize;
  GreenShifter=8-_pixformat.GreenMaskSize;
  BlueShifter=8-_pixformat.BlueMaskSize; 
  Owner = this;
  return TRUE;
} // TGfx0::create

UInt8
TGfx0::getBPP(void) {
  return BPP;
} // TGfx0::getBPP

void*
TGfx0::getBufferPtr(void) {
  return Buffer;
} // TGfx0::getBufferPtr

og_DataState
TGfx0::getDataState(void) {
  return DataState;
} // TGfx0::getDataState(void)

UInt32*
TGfx0::getLineOfsPtr(void) {
  return LineOfs;
} // TGfx0::getLineOfsPtr

TRGB *
TGfx0::getPalPtr(void) {
  return pal;
} // TGfx0::getPalPtr
UInt32 

TGfx0::getMaxX(void) {
  return MaxX;
} // TGfx0::getMaxX

UInt32 
TGfx0::getMaxY(void) {
  return MaxY;
} // TGfx0::getMaxY

UInt32 
TGfx0::getPixel(Int32 x, Int32 y) {
  UInt32 result;
  result = 42;
  if ((Buffer==NULL) || (LineOfs==NULL)) return TransparentColor;
  if ((x<0) || (x>(Int32)MaxX) || (y<0) || y>(Int32)MaxY) 
    return TransparentColor;
  switch (BPP) {
  case 8:
    asm(
       "  add  %%esi, %%edi   \n"  // add     edi, esi
       "  add  %%ecx, %%edi   \n"  // add     edi, ecx
       " movzbl (%%edi),%%eax \n"  // movzx   edx,byte ptr [edi]
       "  mov  %%eax, %3      \n"  // mov     result, eax
       :
       : "D" (Buffer), "S" (LineOfs[y]),    // %0, %1
         "c" (x), "m" (result)              // %2, %3  
       );
    break;
  case 15:
  case 16:
    asm(
       "  add  %%esi, %%edi   \n"  // add     edi, esi
       "  add  %%ecx, %%ecx   \n"  // add     ecx, ecx {adjust for pixel size}
       "  add  %%ecx, %%edi   \n"  // add     edi, ecx
       "  movzwl (%%edi),%%eax \n" // movzx   edx,word ptr [edi]
       "  mov  %%eax, %3      \n"  // mov     result, eax
       :
       : "D" (Buffer), "S" (LineOfs[y]),    // %0, %1
         "c" (x), "m" (result)              // %2, %3
       );
    break;
  case 24:
    asm(
       "  mov  %%ecx, %%eax   \n"  // mov     eax, ecx  - adjust for pixel size 
       "  add  %%ecx, %%ecx   \n"  // add     ecx, ecx  - adjust for pixel size
       "  add  %%eax, %%ecx   \n"  // add     ecx, eax  - adjust for pixel size
       "  add  %%esi, %%edi   \n"  // add     edi, esi
    //   "  add  (%%esi,%%ebx,4), %%edi \n" //  add     edi, [esi + ebx*4]
       "  add  %%ecx, %%edi   \n"  // add     edi, ecx
       "  movzwl (%%edi),%%eax \n" // edx,word ptr [edi]
       "  xor  %%eax, %%eax   \n"  
       "  mov  2(%%edi), %%al \n"  // mov     al, [edi+2]
       "  shl  $16, %%eax     \n"  // shl     eax, 16
       "  mov  (%%edi), %%ax  \n"  // mov     ax, [edi]
       "  mov  %%eax, %3      \n"  // mov     result, eax
       :
       : "D" (Buffer), "S" (LineOfs[y]), // %0, %1
         "c" (x), "m" (result)           // %2, %3
       );
    break;
  case 32:
    asm(
       "  shl  $2, %%ecx      \n"  // shl     ecx, 2 {adjust for pixel size}
     //  "  add  (%%esi,%%ebx,4), %%edi \n" //  add     edi, [esi + ebx*4]
       "  add  %%esi, %%edi   \n"  // add     edi, esi
       "  add  %%ecx, %%edi   \n"  // add     edi, ecx
       "  mov  (%%edi),%%eax  \n"  // eax,word ptr [edi]
       "  mov  %%eax, %3      \n"  // mov     result, eax
       :
       : "D" (Buffer), "S" (LineOfs[y]), // %0, %1
         "c" (x), "m" (result)           // %2, %3
       );
  } // switch
  return result;
} // TGfx0::getPixel

void
TGfx0::getPixFmt(TPixelFmt& pixfmt) {
  pixfmt.BPP=BPP;
  pixfmt.RedFieldPosition=RedFieldPosition;
  pixfmt.GreenFieldPosition=GreenFieldPosition;
  pixfmt.BlueFieldPosition=BlueFieldPosition;
  pixfmt.RedMaskSize=8-RedShifter;
  pixfmt.GreenMaskSize=8-GreenShifter;
  pixfmt.BlueMaskSize=8-BlueShifter;
} // TGfx0::getPixFmt

UInt32
TGfx0::getTransparentColor(void) {
  return TransparentColor;
} // TGfx0::getTransparentColor

void
TGfx0::hFlip(void) {

} // TGfx0::hFlip

void
TGfx0::hLine(Int32 x1, Int32 x2, Int32 y, UInt32 colour) {
  Int32 tmp;

  if ((Buffer==NULL) || (LineOfs==NULL)) return;
  if ((UInt32)y>MaxY) return;
  if (x1>x2) {
    tmp= x1;
    x1 = x2;
    x2 = tmp;
  } // if
  if (x1<0) x1 = 0;
  if (x2>(Int32)MaxX) x1=MaxX;
  if (x2<x1) return;
  asm("cld \n");
  switch (BPP) {
  case 8:
    asm(
        "  add  %%ebx, %%edi  \n"          //  add      edi, ebx
        "  add  %%esi, %%edi  \n"          //  add      edi, esi
        "  and  $0xff, %%eax  \n"          //  and      eax, 0ffh
        "  sub  %%ebx, %%ecx  \n"          //  sub      ecx, ebx
        "  mov  %%al, %%ah    \n"          //  mov	ah, al
        "  inc  %%ecx         \n"          //  inc      ecx
        "  mov  %%eax, %%ebx  \n"          //  mov      ebx, eax
        "  shl  $16, %%ebx    \n"          //  shl      ebx, 16
        "  add  %%ebx, %%eax  \n"          //  add      eax, ebx

        "  mov  %%ecx, %%edx  \n"          //  mov      edx, ecx
        "  mov  $4, %%ecx     \n"          //  mov      ecx, 4
        "  sub  %%edi, %%ecx  \n"          //  sub      ecx, edi
        "  and  $3, %%ecx     \n"          //  and      ecx, 3
        "  sub  %%ecx, %%edx  \n"          //  sub      edx, ecx
        "   jle LEndBytes     \n"
        "  rep                \n"          
        "  stosb              \n"
        "  mov  %%edx, %%ecx  \n"          //  mov      ecx, edx
        "  and  $3, %%edx     \n"          //  and      edx, 3
        "  shr  $2, %%ecx     \n"          //  shr      ecx, 2
        "  rep                \n"
        "  stosl              \n"
    "LEndBytes:               \n"
        "  add  %%edx, %%ecx  \n"          //  add      ecx, edx
        "  rep                \n"
        "  stosb              \n"
        :
        : "D" (Buffer), "S" (LineOfs[y]),           // %0, %1
          "a" (colour), "b" (x1),                   // %2, %3
          "c" (x2) 
       );
    break;
  case 15:
  case 16:
    asm(
        "  sub  %%ebx, %%ecx  \n"          //  sub      ecx, ebx
        "  add  %%ebx, %%ebx  \n"          //  add      ebx, ebx - pix size
        "  inc  %%ecx         \n"          //  inc      ecx
        "  add  %%ebx, %%edi  \n"          //  add      edi, ebx
        "  add  %%esi, %%edi  \n"          //  add      edi, esi
        "  xor  %%edx, %%edx  \n"          //  xor      edx, edx
        "  mov  %%ax, %%dx    \n"          //  mov      dx, ax
        "  shl  $16, %%eax    \n"          //  shl      eax, 16
        "  add  %%edx, %%eax  \n"          //  add      eax, edx

        "  shr  $1, %%ecx     \n"          //  shr      ecx, 1
        "  rep                \n"
        "  stosl              \n"
        "   jnc hLnoc16       \n"
        "  stosw              \n"
        "hLnoc16:             \n"
        :
        : "D" (Buffer), "S" (LineOfs[y]),           // %0, %1
          "a" (colour), "b" (x1),                   // %2, %3
          "c" (x2)                                  // %4
    );
    break;
  case 24:
    break;
  case 32:
    break;
  } // switch
} // TGfx0::hLine

void 
TGfx0::putPixel(UInt32 x, UInt32 y, UInt32 colour) {
  if ((Buffer==NULL) || (LineOfs==NULL)) return;
  if ((x<0) || (x>MaxX) || (y<0) || y>MaxY) return;
  switch (BPP) {
  case 8:
    asm(
    // { Calculate offset, prepare the pixel to be drawn }
    //    "  add  (%%esi,%%ebx,4), %%edi \n" // add     edi, [esi + ebx * 4]
        "  add  %%esi, %%edi  \n"          // add     edi, esi
        "  mov  %3, %%eax     \n"          // mov     eax, colour
        "  add  %%ecx, %%edi  \n"          // add     edi, ecx
    // { Draw the pixel }
        "  mov  %%al, (%%edi) \n"          // mov     [edi], al
        :
        : "D" (Buffer), "S" (LineOfs[y]),           // %0, %1
          "c" (x), "m" (colour)                     // %2, %3
   );
   break;
   case 15:
   case 16:
     asm(
    // { Calculate offset, prepare the pixel to be drawn }
//        "  add  (%%esi,%%ebx,4), %%edi \n" // add     edi, [esi + ebx * 4]
        "  add  %%ecx, %%ecx  \n"  // add     ecx, ecx {adjust for pixel size}
        "  add  %%esi, %%edi  \n"  // add     edi, esi
        "  mov  %3, %%eax     \n"  // mov     eax, colour
        "  add  %%ecx, %%edi  \n"  // add     edi, ecx
    // { Draw the pixel }
        "  mov  %%ax, (%%edi) \n"  // mov     [edi], al
        :
        : "D" (Buffer), "S" (LineOfs[y]),        // %0, %1
          "c" (x), "m" (colour)                  // %2, %3
     );
     break;
   case 24:
     asm(
    // { Calculate offset, prepare the pixel to be drawn }
 //       "  add  (%%esi,%%ebx,4),%%edi \n" // add     edi, [esi + ebx * 4]
        "  add  %%esi, %%edi  \n"  // add     edi, esi
        "  add  %%ecx, %%edi  \n"  // add     edi, ecx
        "  add  %%ecx, %%edi  \n"  // add     edi, ecx {adjust for pixel size}
        "  add  %%ecx, %%edi  \n"  // add     edi, ecx {adjust for pixel size}
    // { Draw the pixel }
        "  mov  %%ax, (%%edi) \n"  // mov     [edi], ax
        "  shr  $16, %%eax    \n"  // shr     eax, 16
        "  mov  %%al, 2(%%edi)\n"  // mov     [edi+2],al
        :
        : "D" (Buffer), "S" (LineOfs[y]),        // %0, %1
          "c" (x), "a" (colour)                  // %2, %3
    );
    break;
  case 32:
     asm(
    // { Calculate offset, prepare the pixel to be drawn }
        "  shl  $2, %%ecx     \n"  // shl     eax, 2 {adjust for pixel size}
        "  add  %%esi, %%edi  \n"  // add     edi, esi
        "  add  %%ecx, %%edi  \n"  // add     edi, ecx
    // { Draw the pixel }
        "  mov  %%eax, (%%edi) \n" // mov     [edi], eax
        :
        : "D" (Buffer), "S" (LineOfs[y]),        // %0, %1
          "c" (x), "a" (colour)                  // %2, %3
    );
  } // switch
  return;
} // TGfx0::putPixel

UInt32 
TGfx0::RGB(UInt8 red, UInt8 green, UInt8 blue) {
  UInt32 lastclr;
  lastclr=0;
  switch (BPP) {
  case 8:
    asm(
      "  movl  $256,%%ecx     \n"
      "  movl  $256*3+1,%%ebx \n"
      "  xor   %%eax,%%eax    \n"
      "lop:                   \n"
      "  pushl %%eax          \n"
      "  mov   (%%esi),%%al   \n"
      "  incl  %%esi          \n"
      "  sub   %1,%%al        \n"
      "  jns   abs1           \n"
      "  neg   %%al           \n"
      "abs1:                  \n"
      "  movl   %%eax,%%edi   \n"
      "  mov   (%%esi),%%al   \n"
      "  incl  %%esi          \n"
      "  sub   %2,%%al        \n"
      "  jns   abs2           \n"
      "  neg   %%al           \n"
      "abs2:                  \n"
      "  addl  %%eax,%%edi    \n"
      "  mov   (%%esi),%%al   \n"
      "  incl  %%esi          \n"
      "  sub   %3,%%al        \n"
      "  jns   abs3           \n"
      "  neg   %%al           \n"
      "abs3:                  \n"
      "  addl  %%eax,%%edi    \n"
      "  popl  %%eax          \n"
      "  cmpl  %%ebx,%%edi    \n"
      "  jae   no_good_match  \n"
      "  movl  %%edi,%%ebx    \n"
      "  movl  %%eax,%4       \n"
      "no_good_match:         \n"
      "  incl  %%eax          \n"
      "  decl  %%ecx          \n"
      "  jnz   lop            \n"
      : 
      : "S" (pal), "m" (red), "m" (green), "m" (blue), "m" (lastclr)
      );
    break;
  case 15:
  case 16:
    asm(
      "  xor  %%eax, %%eax    \n"
      "  xor  %%ebx, %%ebx    \n"
      "  xor  %%ecx, %%ecx    \n"
      "  mov  %0, %%al        \n"  // mov al, red
      "  mov  %3, %%cl        \n"  // mov cl, RedShifter
      "  shr  %%cl, %%al      \n"  // shr al, cl
      "  mov  %4, %%cl        \n"  // mov cl, RedFieldPosition
      "  shl  %%cl, %%eax     \n"  // shl eax, cl
      "  mov  %%eax, %%ebx    \n"  // mov ebx, eax
      "  xor  %%eax, %%eax    \n"  // xor eax, eax
      "  mov  %1, %%al        \n"  // mov al, green
      "  mov  %5, %%cl        \n"  // mov cl, GreenShifter
      "  shr  %%cl, %%al      \n"  // shr al, cl
      "  mov  %6, %%cl        \n"  // mov cl, GreenFieldPosition
      "  shl  %%cl, %%eax     \n"  // shl eax, cl
      "  or   %%eax, %%ebx    \n"  // or eax, ebx
      "  xor  %%eax, %%eax    \n"  // xor eax, eax
      "  mov  %2, %%al        \n"  // mov al, blue
      "  mov  %7, %%cl        \n"  // mov cl, BlueShifter
      "  shr  %%cl, %%al      \n"  // shr al, cl
      "  mov  %8, %%cl        \n"  // mov cl, BlueFieldPosition
      "  shl  %%cl, %%eax     \n"  // shl eax, cl
      "  or   %%ebx, %%eax    \n"  // or eax, ebx
      "  mov  %%eax, %9       \n"  // mov lastclr, eax
      : 
      : "m" (red), "m" (green), "m" (blue),           // %0, %1, %2
        "m" (RedShifter), "m" (RedFieldPosition),     // %3, %4
        "m" (GreenShifter), "m" (GreenFieldPosition), // %5, %6
        "m" (BlueShifter), "m" (BlueFieldPosition),   // %7, %8
        "m" (lastclr)                                 // %9
    );
    break;
  case 24:
  case 32:
    asm(
      "  xor  %%eax, %%eax    \n"  // xor     eax, eax
      "  xor  %%ebx, %%ebx    \n"  // xor     ebx, ebx
      "  xor  %%ecx, %%ecx    \n"  // xor     ecx, ecx

      "  mov  %0, %%al        \n"  // mov     al, red
      "  mov  %3, %%cl        \n"  // mov    cl, RedFieldPosition
      "  shl  %%cl, %%eax     \n"  // shl     eax, cl
      "  mov  %%eax, %%ebx    \n"  // mov     ebx, eax
      "  xor  %%eax, %%eax    \n"  // xor     eax, eax
      "  mov  %1, %%al        \n"  // mov     al, green
      "  mov  %4, %%cl        \n"  // mov     cl, GreenFieldPosition
      "  shl  %%cl, %%eax     \n"  // shl     eax, cl
      "  or   %%eax, %%ebx    \n"  // or      ebx, eax
      "  xor  %%eax, %%eax    \n"  // xor     eax, eax
      "  mov  %2, %%al        \n"  // mov     al, blue
      "  mov  %5, %%cl        \n"  // mov     cl, BlueFieldPosition
      "  shl  %%cl, %%eax     \n"  // shl     eax, cl
      "  or   %%ebx, %%eax    \n"  // or      eax, ebx
      "  mov  %%eax, %6       \n"  // mov     lastclr, eax
      :
      : "m" (red), "m" (green), "m" (blue),  // %0, %1, %2
        "m" (RedFieldPosition),              // %3
        "m" (GreenFieldPosition),            // %4
        "m" (BlueFieldPosition),             // %5
        "m" (lastclr)                        // %6
    );
  } // switch
  //asm("": "=a" (lastclr));
  return lastclr;
} // TGfx0::RGB

void 
TGfx0::setRGBPalette(UInt8 colour, UInt8 red, UInt8 green, UInt8 blue) {
  if (!pal) return;
  pal[colour].red = red;
  pal[colour].green = green;
  pal[colour].blue = blue;
  return;
} // TGfx0::setRGBPalette

void 
TGfx0::unpackRGB(UInt32 colour, UInt8& red, UInt8& green, UInt8& blue) {
  switch (BPP) {
  case 8:
    if (!pal) {
      red = 0;
      green = 0;
      blue = 0;
      return;
    }
    if (colour>255) colour=colour & 255;
    red   = pal[colour].red;
    green = pal[colour].green;
    blue  = pal[colour].blue; 
    break;
  case 15:
  case 16:
    red   = ((colour >> RedFieldPosition) << RedShifter);
    green = ((colour >> GreenFieldPosition) << GreenShifter);
    blue  = ((colour >> BlueFieldPosition) << BlueShifter);
    if ((red) && (RedShifter)) red+=(1 << RedShifter)-1;
    if ((green) && (GreenShifter)) green+=(1 << GreenShifter)-1;
    if ((blue) && (BlueShifter)) blue+=(1 << BlueShifter)-1;
    break;
  case 24:
  case 32:
    red   = colour >> RedFieldPosition;
    green = colour >> GreenFieldPosition;
    blue  = colour >> BlueFieldPosition;
    break;
  default:
    red   = 0;
    green = 0;
    blue  = 0;
  }
  return;
} // TGfx0:unpackRGB

void
TGfx0::vFlip(void) {
  return;
} // TGfx0::vFlip

TGfx0::~TGfx0(void) {
  if (DataState == og_Owner) {
    if (pal!=NULL) free(pal);
    if (Buffer!=NULL) free(Buffer);
    if (LineOfs!=NULL) free(LineOfs);
  }  // if datastate
  pal    = NULL;
  LineOfs= NULL;
  Buffer = NULL;
  bSize  = 0;
  lSize  = 0;
  DataState = og_None;
  return;
} // TGfx0::~TGfx0()

/*
 *
 *              TSCREEN METHODS     
 *
 */

TScreen::TScreen(void) {
  InGraphics = FALSE;
  VESARec = NULL;
  ModeRec = NULL;
  return;
}

TScreen::~TScreen(void) {
  return;
}