#include <stdio.h>
#include <stdlib.h>
#include <dos.h>
#include <io.h>
#include <fcntl.h>
#include <alloc.h>
#include <vbe.h>

extern unsigned int vbe_mode;
extern unsigned long bytes_per_scanline;
extern void far (*win_func)();
extern unsigned long win_size, tail;
extern unsigned char num_win;

unsigned int x_res, y_res;
unsigned int win_granularity;
unsigned long image_size;

unsigned long egacolor[16] = {
       0x000000l, 0x0000AAl, 0x00AA00l, 0x00AAAAl,
       0xAA0000l, 0xAA00AAl, 0xAA5500l, 0xAAAAAAl,
       0x555555l, 0x5555FFl, 0x55FF55l, 0x55FFFFl,
       0xFF5555l, 0xFF55FFl, 0xFFFF55l, 0xFFFFFFl
};


int vbeGetInfo(struct VbeInfoBlock *vbe_info)
{
       struct REGPACK regs;

       regs.r_ax = 0x4f00;
       regs.r_es = FP_SEG(vbe_info);
       regs.r_di = FP_OFF(vbe_info);
       intr(0x10, &regs);
}


int vbeGetModeInfo(int mode, struct ModeInfoBlock *mode_info)
{
       struct REGPACK regs;

       regs.r_ax = 0x4f01;
       regs.r_cx = mode;
       regs.r_es = FP_SEG(mode_info);
       regs.r_di = FP_OFF(mode_info);
       intr(0x10, &regs);
}


int vbeSetMode(int mode)
{
       union REGS regs;

       regs.x.ax = 0x4f02;
       regs.x.bx = mode;
       int86(0x10, &regs, &regs);
}


int vbeSetLogicalLineLength(int length)
{
       struct REGPACK regs;

       regs.r_ax = 0x4f06;
       regs.r_bx = 0x0000;
       regs.r_cx = length;
       intr(0x10, &regs);

       bytes_per_scanline = (unsigned long)_BX;
}


int vbeGetLogicalLineLength(void)
{
       struct REGPACK regs;

       regs.r_ax = 0x4f06;
       regs.r_bx = 0x0001;
       intr(0x10, &regs);
       return _CX;
}


int vbeSetDisplayStart(int x, int y, int vbsync)
{
       struct REGPACK regs;

       regs.r_ax = 0x4f07;
       regs.r_bx = 0x0000 | (vbsync << 7);
       regs.r_cx = x;
       regs.r_dx = y;
       intr(0x10, &regs);
}


int vbeGetDisplayStart(void)
{
       struct REGPACK regs;

       regs.r_ax = 0x4f07;
       regs.r_bx = 0x0001;
       intr(0x10, &regs);
}


extern int cur_height[], cur_type;
extern unsigned long far *cursor[];
extern unsigned long txt_fgcol;

int vbeInit(int mode, int set_mode)
{
       struct ModeInfoBlock modeinfo;
       union REGS regs;
       int i, retval;

       vbe_mode = mode;

       if(set_mode) {
               regs.x.ax = 0x4f02;
               regs.x.bx = vbe_mode;
               int86(0x10, &regs, &regs);
               retval = _AX;
               if(retval != 0x004F) return retval;
       }

       vbeGetModeInfo(mode, &modeinfo);

       x_res = modeinfo.XResolution;
       y_res = modeinfo.YResolution;
       bytes_per_scanline = (unsigned long)modeinfo.BytesPerScanLine;
       win_granularity = modeinfo.WinGranularity;
       win_size = (unsigned long)modeinfo.WinSize * 1024L;
       win_func = modeinfo.WinFuncPtr;

       image_size = (unsigned long)bytes_per_scanline * (unsigned long)y_res;
       num_win = (unsigned char)(image_size / win_size);
       tail = image_size - ((unsigned long)num_win * win_size);

       for(i = 0; i < (8 * cur_height[cur_type]); i++)
               cursor[cur_type][i] = txt_fgcol;

       return retval;
}


int vbeExit(void)
{
       union REGS regs;

       regs.x.ax = 0x0003;
       int86(0x10, &regs, &regs);
}