// [Author] - Drunkie
// [Description] - A graphics driver that provides C-style functions for GPU
// [Documentation] - http://goo.gl/DHhYb


#define GL

// Font
#define GL_FONT_LUCIDA_CONSOLE 0
#define GL_FONT_COURIER_NEW 1
#define GL_FONT_TREBUCHET 2
#define GL_FONT_ARIAL 3
#define GL_FONT_TIMES_NEW_ROMAN 4
#define GL_FONT_COOLVETICA 5
#define GL_FONT_AKBAR 6
#define GL_FONT_CSD 7

// Buffer
#define GL_BUFFER_FRONT 0
#define GL_BUFFER_BACK 1
#define GL_BUFFER_SPRITE 1
#define GL_BUFFER_VERTEX 2

// Coordinate pipe
#define GL_CPIPE_DIRECT 0
#define GL_CPIPE_RESOLUTION 1
#define GL_CPIPE_0_1 2
#define GL_CPIPE_N1_1 3
#define GL_CPIPE_N256_256 4

// Vertex pipe
#define GL_VPIPE_XY 0
#define GL_VPIPE_YZ 1
#define GL_VPIPE_XZ 2
#define GL_VPIPE_XYZPROJ 3
#define GL_VPIPE_XYTRANSFORM 4
#define GL_VPIPE_XYZTRANSFORM 5

// denable / ddisable
#define GL_VERTEX_BUFFER 0
#define GL_VERTEX_ZSORT 1
#define GL_VERTEX_LIGHTING 2
#define GL_VERTEX_CULLING 3
#define GL_VERTEX_DCULLING 4
#define GL_VERTEX_TEXTURING 5

// Fillmode
#define GL_FILL_SOLID 0
#define GL_FILL_WIREFRAME 1
#define GL_FILL_TEXTURE 2

// Cullmode
#define GL_CULL_FRONT 0
#define GL_CULL_BACK 1

// Lightmode
#define GL_LIGHT_FRONT 1
#define GL_LIGHT_BACK -1

// Horizontal font
#define GL_ALIGN_LEFT 0
#define GL_ALIGN_CENTER 1
#define GL_ALIGN_RIGHT 2

// Vertical font
#define GL_VALIGN_TOP 0
#define GL_VALIGN_MIDDLE 1
#define GL_VALIGN_BOTTOM 2

// Compatibility
#define glSetTexture glBindTexture
#define glWriteFmt glWriteFormat
#define glFontHAlign glFontAlign


// Clear
void glClear( float r, float g, float b ) {
    mov #GL_BG.r,r; mov #GL_BG.g,g; mov #GL_BG.b,b; mov #GL_BG.a,255;
    dclrscr GL_BG;
}
void glClear4( float r, float g, float b, float a ) {
    mov #GL_BG.r,r; mov #GL_BG.g,g; mov #GL_BG.b,b; mov #GL_BG.a,a;
    dclrscr GL_BG;
}
void glClearTexture() {
    dclrtex;
}
void glHWClear( float n ) {
    mov #regHWClear,n;
}

// Color
void glColor( float r, float g, float b ) {
    mov #GL_FG.r,r; mov #GL_FG.g,g; mov #GL_FG.b,b; mov #GL_FG.a,255;
    dcolor GL_FG;
}
void glColor4( float r, float g, float b, float a ) {
    mov #GL_FG.r,r; mov #GL_FG.g,g; mov #GL_FG.b,b; mov #GL_FG.a,a;
    dcolor GL_FG;
}
void glBrightness( float r, float g, float b, float a ) {
    mov #regBrightnessR,r;
    mov #regBrightnessG,g;
    mov #regBrightnessB,b;
    mov #regBrightnessW,a;
}
void glContrast( float r, float g, float b, float a ) {
    mov #regContrastR,r;
    mov #regContrastG,g;
    mov #regContrastB,b;
    mov #regContrastW,a;
}
void glShade( float n ) {
    dshade n;
}
void glShadeNorm( float n ) {
    dshadenorm n;
}

// Texture
void glBindTexture( char* str ) {
    dxtexture str;
}
void glTexture( float id ) {
    dtexture id;
}
void glTextureSize( float n ) {
    mov #regTexSize,n;
}
void glTextureDataPtr( float n ) {
    mov #regTexDataPtr,n;
}
void glTextureDataSize( float n ) {
    mov #regTexDataSz,n;
}
void glTextureRotation( float n ) {
    mov #regTexRotation,n;
}
void glTextureScale( float n ) {
    mov #regTexScale,n;
}
void glTextureCenterUV( float u, float v ) {
    mov #regTexCenterU,u;
    mov #regTexCenterV,v;
}
void glTextureOffsetUV( float u, float v ) {
    mov #regTexOffsetU,u;
    mov #regTexOffsetV,v;
}

// Frame
void glSleep( float ms ) {
    div ms,1000;
    timer #GL_CURTIME;
    sub #GL_CURTIME,#GL_TIMESTAMP;
    if (*GL_CURTIME <= ms) {
        mov #regHWClear,0;
        dexit;
    }
    timer #GL_TIMESTAMP;
}
void glExit() {
    dexit;
}

// Pipeline
void glCoordPipe( float c ) {
    dcpipe c;
}
void glVertexPipe( float v ) {
    dvxpipe v;
}

// Hardware
void glReset( float n ) {
    mov #regReset,n;
}
void glHalt( float n ) {
    mov #regHalt,n;
}
void glRAMReset( float n ) {
    mov #regRAMReset,n;
}
void glHScale( float n ) {
    mov #regHScale,n;
}
void glVScale( float n ) {
    mov #regVScale,n;
}
void glHWScale( float n ) {
    mov #regHWScale,n;
}
void glHWRotate( float n ) {
    mov #regRotation,n;
}

// Offset
void glOffset( float x, float y ) {
    mov #GL_V1.x,x; mov #GL_V1.y,y;
    dmove GL_V1;
}
float glOffsetX() {
    preserve eax;
    mov eax,#regOffsetX;
}
float glOffsetY() {
    preserve eax;
    mov eax,#regOffsetY;
}
void glCenter( float x, float y ) {
    mov #regCenterX,x;
    mov #regCenterY,y;
}

// Async
void glAsyncReset( float n ) {
    mov #regAsyncReset,n;
}
void glAsyncClk( float n ) {
    mov #regAsyncClk,n;
}
void glAsyncFreq( float n ) {
    mov #regAsyncFreq,n;
}
void glEntryPoint( float idx, float ptr ) {
    dentrypoint idx,ptr;
}
void glBegin() {
    dbegin;
}
void glEnd() {
    dend;
}
void glSwap() {
    dswap;
}
void glSync() {
    dvsync;
}

// Cursor
void glCursor( float n ) {
    mov #regCursor,n;
}
float glCursorX() {
    preserve eax;
    mov eax,#regCursorX;
}
float glCursorY() {
    preserve eax;
    mov eax,#regCursorY;
}

// Circle
void glCircleQuality( float n ) {
    mov #regCircleQuality,n;
}
void glCircleStart( float n ) {
    mov #regCircleStart,n;
}
void glCircleEnd( float n ) {
    mov #regCircleEnd,n;
}

// Screen scaling
void glScreenScale( float n ) {
    mov #regScale,n;
}
void glScreenScaleX( float x ) {
    mov #regScaleX,x;
}
void glScreenScaleY( float y ) {
    mov #regScaleY,y;
}

// 2D graphics
void glCircle( float x, float y, float radius ) {
    mov #GL_V1.x,x; mov #GL_V1.y,y;
    dcircle GL_V1,radius;
}
void glRect( float x, float y, float dx, float dy ) {
    mov #GL_V1.x,x; mov #GL_V1.y,y;
    mov #GL_V2.x,dx; mov #GL_V2.y,dy;
    drect GL_V1,GL_V2;
}
void glRectWH( float x, float y, float w, float h ) {
    mov #GL_V1.x,x; mov #GL_V1.y,y;
    mov #GL_V2.x,w; mov #GL_V2.y,h;
    drectwh GL_V1,GL_V2;
}
void glORect( float x, float y, float dx, float dy ) {
    mov #GL_V1.x,x; mov #GL_V1.y,y;
    mov #GL_V2.x,dx; mov #GL_V2.y,dy;
    dorect GL_V1,GL_V2;
}
void glORectWH( float x, float y, float w, float h ) {
    mov #GL_V1.x,x; mov #GL_V1.y,y;
    mov #GL_V2.x,w; mov #GL_V2.y,h;
    dorectwh GL_V1,GL_V2;
}
void glPixel( float x, float y ) {
    mov #GL_V1.x,x; mov #GL_V1.y,y;
    dpixel GL_V1,GL_FG;
}
void glLine( float x, float y, float dx, float dy ) {
    mov #GL_V1.x,x; mov #GL_V1.y,y;
    mov #GL_V2.x,dx; mov #GL_V2.y,dy;
    dline GL_V1,GL_V2;
}
void glLineWidth( float w ) {
    dsetwidth w;
}
void glPoly2D( float* buffer, float count ) {
    dvxdata_2f buffer,count;
}


// Text
void glFont( float id ) {
    dsetfont id;
}
void glFontAlign( float n ) {
    mov #regFontHalign,n;
}
void glFontVAlign( float n ) {
    mov #regFontValign,n;
}
void glFontSize( float n ) {
    dsetsize n;
}
float glTextWidth( char* str ) {
    preserve eax;
    dtextwidth eax,str;
}
float glTextHeight( char* str ) {
    preserve eax;
    dtextheight eax,str;
}
void glWriteString( float x, float y, char* str ) {
    mov #GL_V1.x,x; mov #GL_V1.y,y;
    dwrite GL_V1,str;
}
void glWriteFloat( float x, float y, float n ) {
    mov #GL_V1.x,x; mov #GL_V1.y,y;
    dwritef GL_V1,n;
}
void glWriteInt( float x, float y, float n ) {
    mov #GL_V1.x,x; mov #GL_V1.y,y;
    dwritei GL_V1,n;
}
void glWriteFormat( float x, float y, char* str ) {
    mov #GL_V1.x,x; mov #GL_V1.y,y;
    dwritefmt GL_V1,str;
}
float glParamList() {
    preserve eax;
    mov eax,#regParamList;
}


// 3D graphics
void glPoly3D( float* buffer, float count ) {

    if (*GL_MUPDATE == 1) {
        mov #GL_MUPDATE,0;
        mrotate GL_MROTATEMATRIX,GL_VROTATE;
        mtranslate GL_MTRANSLATEMATRIX,GL_VTRANSLATE;
        mscale GL_MSCALEMATRIX,GL_VSCALE;
        mmov GL_MMODELMATRIX,GL_MTRANSLATEMATRIX;
        mmul GL_MMODELMATRIX,GL_MROTATEMATRIX;
        mmul GL_MMODELMATRIX,GL_MSCALEMATRIX;
        mmov GL_MMODELVIEWMATRIX,GL_MVIEWMATRIX;
        mmul GL_MMODELVIEWMATRIX,GL_MMODELMATRIX;
        mload GL_MMODELVIEWMATRIX;
        mloadproj GL_MPROJECTIONMATRIX;
    }

    if (*GL_FILLMODE == GL_FILL_SOLID) {
        dvxdata_3f buffer,count;
    }
    else if (*GL_FILLMODE == GL_FILL_WIREFRAME) {
        dvxdata_3f_wf buffer,count;
    }
    else if (*GL_FILLMODE == GL_FILL_TEXTURE) {
        dvxdata_3f_tex buffer,count
    }
}
void glFlush() {
    dvxflush;
}
void glEnable( float n ) {
    denable n;
}
void glDisable( float n ) {
    ddisable n;
}
void glLightPos( float x, float y, float z ) {
    mov #GL_LIGHTPOS.x,x; mov #GL_LIGHTPOS.y,y; mov #GL_LIGHTPOS.z,z;
    dsetlight 0,GL_LIGHTDATA;
}
void glLightColor( float r, float g, float b, float a ) {
    mov #GL_LIGHTCOL.r,r; mov #GL_LIGHTCOL.g,g;
    mov #GL_LIGHTCOL.b,b; mov #GL_LIGHTCOL.a,a;
    dsetlight 0,GL_LIGHTDATA;
}
void glFillMode( float n ) {
    mov #GL_FILLMODE,n;
}
void glLookAt( float x, float y, float z, float tx, float ty, float tz, float ux, float uy, float uz ) {
    mov #GL_VLOOKAT_POS.x,x; mov #GL_VLOOKAT_POS.y,y; mov #GL_VLOOKAT_POS.z,z;
    mov #GL_VLOOKAT_TARG.x,tx; mov #GL_VLOOKAT_TARG.y,ty; mov #GL_VLOOKAT_TARG.z,tz;
    mov #GL_VLOOKAT_UP.x,ux; mov #GL_VLOOKAT_UP.y,uy; mov #GL_VLOOKAT_UP.z,uz;
    mlookat GL_MVIEWMATRIX,GL_VLOOKAT;
    mov #GL_MUPDATE,1;
}
void glPerspective( float fov, float asp, float znear, float zfar ) {
    mov #GL_VPERSPECTIVE.x,fov; mov #GL_VPERSPECTIVE.y,asp;
    mov #GL_VPERSPECTIVE.z,znear; mov #GL_VPERSPECTIVE.w,zfar;
    mperspective GL_MPROJECTIONMATRIX,GL_VPERSPECTIVE;
    mov #GL_MUPDATE,1;
}
void glRotate( float x, float y, float z, float w ) {
    mov #GL_VROTATE.x,x; mov #GL_VROTATE.y,y; mov #GL_VROTATE.z,z; mov #GL_VROTATE.w,w;
    mov #GL_MUPDATE,1;
}
void glTranslate( float x, float y, float z ) {
    mov #GL_VTRANSLATE.x,x; mov #GL_VTRANSLATE.y,y; mov #GL_VTRANSLATE.z,z;
    mov #GL_MUPDATE,1;
}
void glScale( float x, float y, float z ) {
    mov #GL_VSCALE.x,x; mov #GL_VSCALE.y,y; mov #GL_VSCALE.z,z;
    mov #GL_MUPDATE,1;
}
void glZOffset( float n ) {
    mov #regZOffset,n;
}
void glCullDistance( float n ) {
    mov #regCullDistance,n;
}
void glCullMode( float n ) {
    mov #regCullMode,n;
}
void glLightMode( float n ) {
    mov #regLightMode,n;
}
void glVertexArray( float n ) {
    mov #regVertexArray,n;
}

// Other
void glVertexMode( float n ) {
    mov #regVertexMode,n;
}
void glSetRenderTarget( float n ) {
    if (n == GL_BUFFER_FRONT) {
        dsetbuf_fbo;
    }
    else if (n == GL_BUFFER_BACK) {
        dsetbuf_spr;
    }
    else if (n == GL_BUFFER_VERTEX) {
        dsetbuf_vx;
    }
}
float glIndex() {
    preserve eax;
    mov eax,#regIndex;
}


// Allocated variables for GL
color GL_FG,255,255,255;
color GL_BG;
vec4f GL_V1;
vec4f GL_V2;

alloc GL_TIMESTAMP;
alloc GL_CURTIME;
alloc GL_FILLMODE;

GL_LIGHTDATA:
vec4f GL_LIGHTPOS,0,0,-10;
color GL_LIGHTCOL,255,255,255,1;

GL_VLOOKAT:
vec3f GL_VLOOKAT_POS,0,0,-10;
vec3f GL_VLOOKAT_TARG,0,0,0;
vec3f GL_VLOOKAT_UP,0,1,0;

matrix GL_MROTATEMATRIX;
matrix GL_MTRANSLATEMATRIX;
matrix GL_MSCALEMATRIX;
matrix GL_MPROJECTIONMATRIX;
matrix GL_MVIEWMATRIX;
matrix GL_MMODELMATRIX;
matrix GL_MMODELVIEWMATRIX;
alloc GL_MUPDATE,1;

vec4f GL_VROTATE;
vec4f GL_VTRANSLATE;
vec4f GL_VPERSPECTIVE;
vec4f GL_VSCALE,1,1,1,0;
