#include <objgfx/objgfx30.h>
#include <objgfx/defpal.inc>
#include <sde/ogDisplay_UbixOS.h>
#include <lib/string.h>
#include <ubixos/schedule.h>

extern "C" {
  #include <lib/bioscall.h>
  #include <vmm/paging.h>
  #include <sys/video.h>
  }

/*
 *
 *              ogDisplay methods
 *
 */

void initVESAMode(uInt16 mode) {
  kprintf("Pre-initVESAMode\n");
  biosCall(0x10,0x4F02,mode,0x0,0x0,0x0,0x0,0x0,0x0);
  kprintf("Post-initVESAMode\n");
  return;
  }

ogDisplay_UbixOS::ogDisplay_UbixOS(void) {
  VESARec = (ogVESA_Rec *)0x11000;
  modeRec = (ogMode_Rec *)0x11200;
  getVESAInfo();
  return;
  } // ogDisplay_UbixOS::ogDisplay_UbixOS

void ogDisplay_UbixOS::getModeInfo(uInt16 mode) {
  kprintf("Pre-getModeInfo\n");
  biosCall(0x10,0x4F01,0x0,mode,0x0,0x0,0x0,0x1120,0x0);
  kprintf("Post-getModeInfo\n");
  return;
  } // ogDisplay_UbixOS::getModeInfo

void ogDisplay_UbixOS::getVESAInfo(void) {
  VESARec->VBESignature[0] = 'V'; // First off initialize the structure.
  VESARec->VBESignature[1] = 'B';
  VESARec->VBESignature[2] = 'E';
  VESARec->VBESignature[3] = '2';
  kprintf("Pre-getVESAInfo\n");
  biosCall(0x10,0x4F00,0x0,0x0,0x0,0x0,0x0,0x1100,0x0);
  kprintf("Post-getVESAInfo\n");
  return;
  } // ogDisplay_UbixOS::getVESAInfo

uInt16 ogDisplay_UbixOS::findMode(uInt32 _xRes, uInt32 _yRes, uInt32 _BPP) {
  uInt16 mode;

  if ((_xRes==320) && (_yRes==200) && (_BPP==8)) return 0x13;
  if ((VESARec==NULL) || (VESARec->VideoModePtr==NULL)) return 0;
  if (modeRec==NULL) return 0;
  for (mode = 0x100; mode < 0x1FF; mode++) {
    getModeInfo(mode);
    if ((modeRec->xRes>=_xRes) && (modeRec->yRes>=_yRes) &&
        (modeRec->BitsPerPixel==_BPP))
      return mode;
  }
  return 0;
  } // ogDisplay_UbixOS::findMode

void ogDisplay_UbixOS::setMode(uInt16 mode) {

  uInt32 size = 0x0, count = 0x0, i = 0x0;
  
  if (mode==0x13) {
 
    xRes = 320;
    yRes = 200;
    maxX = 319;
    maxY = 199;
    BPP  = 8;
 
    redFieldPosition = 0;
    greenFieldPosition = 0;
    blueFieldPosition = 0;
    alphaFieldPosition = 0;
    
    redShifter = 0;
    greenShifter = 0;
    blueShifter = 0;
    alphaFieldPosition = 0;

  } else {
    mode |= 0x4000;  // attempt lfb
    getModeInfo(mode);
    if (modeRec->physBasePtr == 0) return;
    buffer = (void *)modeRec->physBasePtr;
    size = modeRec->yRes*modeRec->BytesPerLine;
    
    xRes = modeRec->BytesPerLine;
    yRes = modeRec->yRes;
    maxX = modeRec->xRes-1;
    maxY = yRes-1;

    redFieldPosition = modeRec->RedFieldPosition;
    greenFieldPosition = modeRec->GreenFieldPosition;
    blueFieldPosition = modeRec->BlueFieldPosition;

    redShifter = 8-modeRec->RedMaskSize;
    greenShifter = 8-modeRec->GreenMaskSize;
    blueShifter = 8-modeRec->BlueMaskSize;

    BPP = modeRec->BitsPerPixel;
  }
  
  owner = this;
  dataState = ogALIASING;

  if ((lineOfs!=NULL) && (lSize!=0)) delete [] lineOfs;
  lSize = yRes*sizeof(uInt32);
  lineOfs = new uInt32[yRes];;
  if (lineOfs == NULL) return;
  lineOfs[0] = 0;
  for (count=1; count<yRes; count++)
    lineOfs[count] = lineOfs[count-1]+xRes;
  if (pal==NULL) pal = new ogRGBA[256];
  kmemcpy(pal, DEFAULT_PALETTE, sizeof(ogRGBA)*256);
  printfOff = 0;
  antiAlias=(BPP>8);
  if (BPP==8) setPal();
  initVESAMode(mode);
  for (i=0x0;i<((size)/4096);i++) {
    remapPage(modeRec->physBasePtr + (i * 0x1000),modeRec->physBasePtr + (i * 0x1000));
    }
  return;
  } // ogDisplay_UbixOS::setMode

void ogDisplay_UbixOS::setPal(void) {
  uInt32 c;
  if (BPP!=8) return;
 // outportb(0x3c8,0);
  for (c=0; c<256; c++) {
 //    outportb(0x3c9,pal[c].red >> 2);
 //   outportb(0x3c9,pal[c].green >> 2);
 //   outportb(0x3c9,pal[c].blue >> 2);
  } // for
  return;
} // ogDisplay_UbixOS::setPal

bool
ogDisplay_UbixOS::ogAlias(ogSurface& SrcObject, uInt32 x1, uInt32 y1, uInt32 x2, uInt32 y2) {
  return false;
} // ogDisplay_UbixOS::ogAlias

bool
ogDisplay_UbixOS::ogCreate(uInt32 _xRes, uInt32 _yRes,ogPixelFmt _pixFormat) {
  uInt16 mode;
  mode = 0x111;
  setMode(mode);
  /*
  mode = findMode(_xRes, _yRes, _pixFormat.BPP);
  if ((mode == 0) && ((_pixFormat.BPP==24) || (_pixFormat.BPP==32))) {
    if (_pixFormat.BPP==24) _pixFormat.BPP=32; else _pixFormat.BPP=24;
    mode=findMode(_xRes,_yRes,_pixFormat.BPP);
  } // if
  if (mode!=0) setMode(mode);
  */
  return (mode!=0);
} // ogDisplay_UbixOS::ogCreate

bool
ogDisplay_UbixOS::ogClone(ogSurface& SrcObject) {
  return false;
} // ogDisplay_UbixOS::ogClone

void
ogDisplay_UbixOS::ogCopyPal(ogSurface& SrcObject) {
  ogSurface::ogCopyPal(SrcObject);
  setPal();
  return;
} // ogDisplay_UbixOS::ogCopyPal

bool
ogDisplay_UbixOS::ogLoadPal(const char *palfile) {
  bool result;
  if ((result = ogSurface::ogLoadPal(palfile))==true) setPal();
  return result;
} // ogDisplay_UbixOS::ogLoadPal

void
ogDisplay_UbixOS::ogSetRGBPalette(uInt8 colour, uInt8 red, uInt8 green, uInt8 blue) {
  if (pal==NULL) return;
  ogSurface::ogSetRGBPalette(colour,red,green,blue);
//  outportb(0x3c8,colour);
//  outportb(0x3c9,red >> 2);
//  outportb(0x3c9,green >> 2);
//  outportb(0x3c9,blue >> 2);
  
  return;
} // ogDisplay_UbixOS::ogSetRGBPalette

ogDisplay_UbixOS::~ogDisplay_UbixOS(void) {
//mji  delete VESARec;
//mji  delete modeRec;
  return;
} // ogDisplay_UbixOS::~ogDisplay_UbixOS
