Example #1
0
boolean_t
vgahost_init (int max_width, int max_height, int max_bpp, boolean_t fixed_p,
	      int *argc, char *argv[])
{
  int sel;

  /* Grab a 64K selector for 0xA000:0000, for the frame buffer. */
  sel = __dpmi_segment_to_descriptor (0xA000);
  if (sel == -1)
    return FALSE;
  vga_window_selector = sel;
  vga_screen_selector = -1;  /* no value yet. */

  vesa_version = compute_vesa_version ();

#if defined (SAVE_VGA_STATE)

#if !defined (USE_VESA_STATE_SAVE)
  state_glue_funcp = vga_state_glue;
#else /* USE_VESA_STATE_SAVE */
#error "this will break with the mods to try switching to fullscreen and querying VESA version again...we might save the wrong kind of state!"
  if (vesa_version >= 0x100)  /* version 1.0 or greater? */
    state_glue_funcp = vesa_state_glue;
  else
    state_glue_funcp = vga_state_glue;
#endif /* USE_VESA_STATE_SAVE */

#endif

  /* Save the current VGA state, so we can clean up well when we exit. */
  save_vga_state ();

  /* WinNT appears to not show us a VESA driver unless we start in
   * full screen mode.  However, if we set a plain VGA graphics mode
   * it switches us to full screen mode.  If we didn't see a VESA
   * driver, this attempts to switch to fullscreen mode and then try
   * again.
   */
  if (vesa_version == 0 && !only_use_vga_p)
    {
      __dpmi_regs regs;

      dpmi_zero_regs (&regs);
      regs.x.ax = 0x12;  /* 640x480 VGA mode.  AH == 0x00.  Erase screen. */
      if (__dpmi_int (0x10, &regs) == 0)
	{
	  vesa_version = compute_vesa_version ();
	  restore_vga_state ();
	}
    }

  return TRUE;
}
Example #2
0
/* Empty clipboard, return non-zero if successful.  */
unsigned
empty_clipboard (void)
{
  __dpmi_regs regs;

  /* Calls Int 2Fh/AX=1702h
     Return Values   AX == 0: Error occurred
			<> 0: OK, Clipboard emptied */
  regs.x.ax = 0x1702;
  __dpmi_int (0x2f, &regs);
  return regs.x.ax;
}
Example #3
0
/* Close clipboard, return non-zero if successful.  */
unsigned
close_clipboard (void)
{
  __dpmi_regs regs;

  /* Calls Int 2Fh/AX=1708h
     Return Values   AX == 0: Error occurred
                        <> 0: OK */
  regs.x.ax = 0x1708;
  __dpmi_int (0x2f, &regs);
  return regs.x.ax;
}
Example #4
0
/*
 * Scroll region up a line
 * This is equivalent to deleting a line at the top of the region and pulling
 * everything below it up.
 */
void ossscr(int top, int left, int bottom, int right, int blank_color)
{
    __dpmi_regs regs;

    regs.h.ch = top;
    regs.h.cl = left;
    regs.h.dh = bottom;
    regs.h.dl = right;
    regs.h.bh = blank_color;
    regs.x.ax = B_UPSCROLL_1;
    __dpmi_int(BIOSINT, &regs);
}
Example #5
0
int display_dos_init()
{
    __dpmi_regs r;
    /* Set char-smashed-together mode */
    r.x.ax = 0x1201;
    r.h.bl = 0x30;
    __dpmi_int(0x10, &r);
    r.x.ax = 0x0003;
    __dpmi_int(0x10, &r);

    /* Pointer to video memory */
    videomem = __dpmi_segment_to_descriptor(0xb800);
    /* Block cursor */
    _setcursortype(_SOLIDCURSOR);

    /* No windows by default */
    windows = 0;

    /* Check for Win95/Win98 */
    if (getenv("winbootdir") != NULL)
        windows = 1;
    /* Check for WinNT/Win2k */
    if ((getenv("OS") != NULL) && !strcmp(getenv("OS"), "Windows_NT"))
        windows = 2;

    lshift = rshift = 0;

    /* Save the old handler */
    _go32_dpmi_get_protected_mode_interrupt_vector(KBD_INT, &old_kb_handler);

    /* Create new handler, chain it to old */
    new_kb_handler.pm_offset = (int) kb_isr;
    new_kb_handler.pm_selector = _go32_my_cs();
    _go32_dpmi_chain_protected_mode_interrupt_vector(KBD_INT, &new_kb_handler);

    /* flush the keystroke buffer just in case */
    while (kbhit()) display_dos_getch();

    return -1;
}
Example #6
0
int GetCodePage (void)
{
#if (DOSX & DJGPP)     /* _osmajor/_osminor not set in crt0.o */
  _get_dos_version (0);
#endif

  if ((_osmajor << 8) + _osminor >= 0x303)
  {
#if (DOSX & DJGPP)
    __dpmi_regs reg;

    reg.d.eax = 0x6601;
    __dpmi_int (0x21, &reg);
    if (reg.x.flags & 1)
       return (0);
    return (reg.x.bx);

#elif (DOSX & PHARLAP)
    SWI_REGS reg;

    reg.eax = 0x6601;
    _dx_real_int (0x21, &reg);
    if (reg.flags & 1)
       return (0);
    return (WORD)reg.ebx;

#elif (DOSX & (DOS4GW|WDOSX))
    struct DPMI_regs reg;

    reg.r_ax = 0x6601;
    if (!dpmi_real_interrupt (0x21, &reg))
       return (0);
    return (WORD)reg.r_bx;

#elif (DOSX & POWERPAK)
    UNFINISHED();

#elif (DOSX == 0)       /* real-mode */
    union REGS reg;

    reg.x.ax = 0x6601;
    int86 (0x21, &reg, &reg);
    if (reg.x.cflag)
       return (0);
    return (reg.x.bx);

#else
  #error Unsupported target
#endif
  }
  return (0);
}
Example #7
0
File: cwpci.c Project: ezrec/cw2dmk
/* 1AB101
 * INT 1A - PCI BIOS v2.0c+ - INSTALLATION CHECK
 * See http://www.delorie.com/djgpp/doc/rbinter/id/81/23.html
 *
 * Check if PCI bus installed.  Returns 0 if OK, -1 if error
 * invoking the BIOS through DPMI or the BIOS is not present.
 */
int
pci_install_check(void)
{
  __dpmi_regs r;

  memset(&r, 0, sizeof(r));

  r.x.ax = 0xb101;
  r.d.edi = 0x0;

  if (__dpmi_int(0x1a, &r) != 0) {
    DEBUG_PCI( printf("pci_install_check: BIOS call failed\n"); )
    return -1;
Example #8
0
/* Return the WinOldAp support version, or 0x1700 if not supported.  */
unsigned
identify_winoldap_version (void)
{
  __dpmi_regs regs;

  /* Calls Int 2Fh/AX=1700h
     Return Values   AX == 1700H: Clipboard functions not available
                        <> 1700H: AL = Major version number
				  AH = Minor version number */
  regs.x.ax = 0x1700;
  __dpmi_int (0x2f, &regs);
  return regs.x.ax;
}
Example #9
0
void set_mouse_height(int h)
{
   __dpmi_regs reg;

   if (!mouse_state)
      return;

   poll_mouse();

   reg.x.ax = 8;
   reg.x.cx = 0;
   reg.x.dx = screen_h * h * 8 - 1;
   __dpmi_int(0x33, &reg);

   reg.x.ax = 15;
   reg.x.cx = 8;
   reg.x.dx = MAX(16/h, 1);
   __dpmi_int(0x33, &reg);

   set_mouse_pos(m_x, m_y*h/mouse_height);
   mouse_height = h;
}
Example #10
0
int
_ioctl_get_first_cluster(const char *pathname)
{
  __dpmi_regs r;

  /* See if the IOCTL GetFirstCluster call is supported.  */
  r.x.ax = 0x4411;	       /* query generic IOCTL capability by drive */
  r.h.bl = pathname[0] & 0x1f; /* drive number (1=A:) */
  r.x.cx = 0x871;
  __dpmi_int(0x21, &r);
  if ((r.x.flags & 1) == 0 && r.x.ax == 0)
    {
      r.x.ax = 0x440d;	       /* Generic IOCTL */
      r.x.cx = 0x0871;	       /* category code 08h, minor code 71h */
      r.x.bx = 1;	       /* pathname uses current OEM character set */
      r.x.ds = __tb >> 4;
      r.x.dx = __tb & 0x0f;
      _put_path(pathname);
      __dpmi_int(0x21, &r);
      if ((r.x.flags & 1) == 0)
	return ( ((int)r.x.dx << 16) + r.x.ax );
    }
Example #11
0
// Taken from Allegro - shame this functionality isn't exposed!
bool drive_exists (int drive)
{
   unsigned int old_drive;
   bool fRet = false;
   __dpmi_regs r;

   // get actual drive
   r.h.ah = 0x19;
   __dpmi_int(0x21, &r);
   old_drive = r.h.al;

   // see if the drive is assigned as a valid drive
   r.h.ah = 0x0E;
   r.h.dl = drive;
   __dpmi_int(0x21, &r);

   r.h.ah = 0x19;
   __dpmi_int(0x21, &r);

   if (r.h.al == drive) {
      // ok, now check if it is a logical drive
      r.x.ax = 0x440E;
      r.h.bl = drive+1;
      __dpmi_int(0x21, &r);

      if ((r.x.flags & 1) ||        // call failed
          (r.h.al == 0) ||          // has no logical drives
          (r.h.al == (drive+1)))    // not a logical drive
         fRet = true;
   }

   // now we set the old drive
   r.h.ah = 0x0E;
   r.h.dl = old_drive;
   __dpmi_int(0x21, &r);

   return fRet;
}
Example #12
0
/* initialize console */
void oss_con_init(void)
{
    int ega = 0;
    __dpmi_regs regs;

    regs.x.bx = regs.x.dx = 0;
    regs.h.ah = B_EGACGEN;
    regs.h.al = B_EGATEST;              /* Do we have an EGA/VGA? */
    __dpmi_int(BIOSINT, &regs);
    if (regs.h.dl) {
        ega = 1;
        row_max = regs.h.dl;            /* Yes: dl is number of rows - 1. */
    }
    else
        row_max = DEF_ROW_MAX;
    regs.h.ah = B_GETMODE;
    __dpmi_int(BIOSINT, &regs);
    col_max = regs.h.ah - 1;
    video_mode = regs.h.al;
    video_page = regs.h.bh;
    bios_flag = usebios;
    if (bios_flag) return;
    if (video_mode == MT25X80) {        /* Mono text mode? */
        __dpmi_int(BIOSEQUIP, &regs);
        if ((regs.x.ax & EQUIP_MONO) == EQUIP_MONO)
            /* Real mono system. */
            scrbase = 0xb0000;
    } else {
        /* If graphics mode or no EGA/VGA */
        if (video_mode > CT25X80 || !ega) {
            bios_flag = 1;
            return;
        }
        scrbase = 0xb8000;
    }
    if (video_page == 1)
        scrbase += 0x1000;
}
Example #13
0
/* mick_exit:
 *  Shuts down the mickey-mode driver.
 */
static void mick_exit(void)
{
   __dpmi_regs r;

   r.x.ax = 0x0C;                /* install NULL callback */
   r.x.cx = 0;
   r.x.dx = 0;
   r.x.es = 0;
   __dpmi_int(0x33, &r);

   #ifdef ALLEGRO_DJGPP
      _go32_dpmi_free_real_mode_callback(&mouse_seginfo);
   #endif
}
Example #14
0
/* Makes a call to the VESA driver, and returns TRUE iff successful. */
static boolean_t
vesa_call (int eax, __dpmi_regs *r)
{
  boolean_t success_p;

  if (only_use_vga_p)  /* only old-style VGA allowed? */
    success_p = FALSE;
  else
    {
      r->d.eax = eax;
      success_p = (__dpmi_int (0x10, r) == 0 && r->x.ax == VESA_SUCCESS);
    }

  return success_p;
}
Example #15
0
File: MAIN.C Project: ahelwer/UofC
/**
 * Initializes registers. Provided by VBETEST.C.
 **/
ModeInfoBlock *get_mode_info(int mode)
{
    static ModeInfoBlock info;
    __dpmi_regs r;

    /* Use the transfer buffer to store the results of VBE call */
    r.x.ax = 0x4F01;
    r.x.cx = mode;
    r.x.es = __tb / 16;
    r.x.di = 0;
    __dpmi_int(0x10, &r);
    if(r.h.ah) return 0;
    dosmemget(__tb, sizeof(ModeInfoBlock), &info);
    return &info;
}
Example #16
0
/* Compact clipboard data so that at least SIZE bytes is available.  */
unsigned
clipboard_compact (unsigned Size)
{
  __dpmi_regs regs;

  /* Calls Int 2Fh/AX=1709H with:
                     SI:CX = Desired memory size in bytes.
     Return Values   DX:AX == Number of bytes of largest block of free memory.
                           == 0 if error or no memory  */
  regs.x.ax = 0x1709;
  regs.x.si = Size >> 16;
  regs.x.cx = Size & 0xffff;
  __dpmi_int (0x2f, &regs);
  return ((unsigned)regs.x.dx << 16) | regs.x.ax;
}
Example #17
0
void set_mouse_pos(int x, int y)
{
   __dpmi_regs reg;

   if (!mouse_state)
      return;

   reg.x.ax = 4;
   reg.x.cx = x*8;
   reg.x.dx = y*8;
   __dpmi_int(0x33, &reg);

   m_x = x;
   m_y = y;
}
Example #18
0
/* Return the size of the clipboard data of format FORMAT.  */
unsigned
get_clipboard_data_size (unsigned Format)
{
  __dpmi_regs regs;

  /* Calls Int 2Fh/AX=1704h with:
		     DX = WinOldAp-Supported Clipboard format
     Return Values   DX:AX == Size of the data in bytes, including any
                              headers.
                           == 0 If data in this format is not in
			   the clipboard.  */
  regs.x.ax = 0x1704;
  regs.x.dx = Format;
  __dpmi_int (0x2f, &regs);
  return ( (((unsigned)regs.x.dx) << 16) | regs.x.ax);
}
Example #19
0
/* Free our clipboard buffer.  We always free it after use, because
   keeping it leaves less free conventional memory for subprocesses.
   The clipboard buffer tends to be large in size, because for small
   clipboard data sizes we use the DJGPP transfer buffer.  */
static void
free_xfer_buf (void)
{
  /* If the size is 0, we used DJGPP transfer buffer, so don't free.  */
  if (clipboard_xfer_buf_info.size)
    {
      __dpmi_regs regs;

      /* The NT DPMI host crashes us if we free DOS memory via
	 the DPMI service.  Work around by calling DOS free block.  */
      regs.h.ah = 0x49;
      regs.x.es = clipboard_xfer_buf_info.rm_segment;
      __dpmi_int (0x21, &regs);
      clipboard_xfer_buf_info.size = 0;
    }
}
Example #20
0
/*
 * Clear the given region of the screen
 */
void ossclr(int top, int left, int bottom, int right, int color)
{
    __dpmi_regs regs;

    /* if we're clearing an empty area, ignore it */
    if (top > bottom || left > right)
        return;

    regs.h.ch = top;
    regs.h.cl = left;
    regs.h.dh = bottom;
    regs.h.dl = right;
    regs.h.bh = color;
    regs.x.ax = B_CLEAR_REGION;
    __dpmi_int(BIOSINT, &regs);
}
Example #21
0
int ossvpg(char pg)
{
    int  ret;
    __dpmi_regs regs;
    
    if (pg == video_page) return(video_page);
    ret = video_page;
    video_page = pg;
    regs.h.ah = 5;
    regs.h.al = pg;
    __dpmi_int(BIOSINT, &regs);
    if (video_page == 1)
        scrbase += 0x1000;
    else
        scrbase -= 0x1000;
    return(ret);
}
Example #22
0
/*
 *   Calculate the current system time in milliseconds.  Returns a value
 *   relative to an arbitrary base time.  
 */
long os_get_sys_clock_ms(void)
{
    static unsigned long last_ticks;
    long curtime;

    /* get the current system clock reading in clock ticks */
#ifdef DJGPP
    __dpmi_regs regs;

    regs.h.ah = 0;
    __dpmi_int(0x1a, &regs);
    curtime = (regs.x.cx << 16) | regs.x.dx;
#else /* DJGPP */
    asm {
        push   bp
        mov    ah, 00h
        int    1ah
        pop    bp

        mov    word ptr [curtime], dx
        mov    word ptr [curtime+2], cx
    }
#endif /* DJGPP */

    /* 
     *   Check for clock rollover.  The clock resets to 0 ticks at midnight.
     *   If the new tick count is lower than the last tick count we read, add
     *   1573040 (the number of ticks in 24 hours) until it's greater.  This
     *   ensures that we have continuity between readings.  
     */
    while (curtime < last_ticks)
        curtime += 1573040;

    /* save the last tick count for checking rollover next time through */
    last_ticks = curtime;

    /* 
     *   Convert the tick count to milliseconds - there are 18.2065 ticks
     *   per second, hence 18.2065 ticks per 1000 milliseconds, hence
     *   1000/18.2065 milliseconds per tick.  This is approximately 55
     *   ticks per millisecond.  Return the result of the conversion.  
     */
    return curtime * 55;
}
Example #23
0
/* Saves the vga state into vga_state, allocating space as necessary. */
static void
save_vga_state (void)
{
  __dpmi_regs regs;

  /* Fetch the current mode number. */
  dpmi_zero_regs (&regs);
  regs.h.ah = 0xF;
  if (__dpmi_int (0x10, &regs) != -1)
    orig_vga_mode = regs.h.al & 0x7F;
  else
    orig_vga_mode = -1;

#if defined (SAVE_VGA_STATE)
  if (state_glue_funcp (COMPUTE_BUFFER_SIZE, &vga_state_size)
      && vga_state_size <= DOS_BUF_SIZE - DOS_MIN_STACK_SPACE
      && state_glue_funcp (SAVE_STATE, NULL))
    {
      if (vga_state != NULL)
	free (vga_state);
      vga_state = malloc (vga_state_size);
      if (vga_state != NULL)
	{
	  /* Save the state away in our memory space. */
	  movedata (dos_buf_selector, 0, dos_pm_ds, (unsigned) vga_state,
		    vga_state_size);
	}
    }

  /* Restore the VGA state because many BIOSes corrupt it when they
   * save it (from the INTER document).  This shouldn't be necessary
   * for VESA drivers, but it's conceivable some stupid VESA driver
   * calls one of the buggy BIOS routines which is known to need this.
   */
  {
    int save_orig_mode;

    save_orig_mode = orig_vga_mode;
    orig_vga_mode = -1;	/* Don't reset mode! */
    restore_vga_state ();
    orig_vga_mode = save_orig_mode;
  }
#endif
}
Example #24
0
void
vgahost_set_read_window (int window_num)
{
  if (window_num != vga_read_window && vga_current_mode->multi_window_p)
    {
      __dpmi_regs regs;

      /* Set up the write window to point to the right place. */
      dpmi_zero_regs (&regs);
      regs.x.ax = VESA_WINDOW_CONTROL;
      regs.x.bx = vga_current_mode->win_read;  /* BH == 0x00 */
      regs.x.dx = window_num;
      __dpmi_int (0x10, &regs);

      vga_read_window = window_num;
      if (vga_current_mode->win_read == vga_current_mode->win_write)
	vga_write_window = window_num;
    }
}
Example #25
0
int mouse_changed(int *x, int *y)
{
   __dpmi_regs reg;

   if (!mouse_state)
      return FALSE;

   reg.x.ax = 3;
   __dpmi_int(0x33, &reg);

   if (x)
      *x = reg.x.cx / 8;

   if (y)
      *y = reg.x.dx / 8;

   return (((reg.x.cx / 8) != m_x) || ((reg.x.dx / 8) != m_y) || 
	   (reg.x.bx != m_b) || (reg.x.bx));
}
Example #26
0
static int detect(void)
{
	__dpmi_regs regs;

	memset(&regs, 0, sizeof(regs));
	regs.x.ax = 0x4F14;

	if (__dpmi_int(0x10, &regs) != 0) {
		printf("Error calling dpmi_int()\n");
		return -1;
	}

	if (regs.x.ax == 0x004F && regs.x.bx == TSR_RUTACK1 && regs.x.cx == TSR_RUTACK2) {
		printf("Already installed\n");
		return -1;
	}

	return 0;
}
Example #27
0
/* FAT32_AbsReadWrite() is modified from TE_AbsReadWrite(). */
unsigned int FAT32_AbsReadWrite(char DosDrive, int count, ULONG sector,
									ULONG buffer, unsigned int ReadOrWrite)
{
	struct DRP {
		unsigned long  sectorNumber;
		unsigned short count;
		unsigned short offset;
		unsigned short segment;	/* transfer address */
	} diskReadPacket;

	struct {
		unsigned direction  : 1 ; /* low bit */
		unsigned reserved_1 : 12;
		unsigned write_type : 2 ;
		unsigned reserved_2 : 1 ;
	} mode_flags;

	diskReadPacket.sectorNumber	= sector;
	diskReadPacket.count		= count;
	diskReadPacket.segment		= FP_SEG(buffer);
	diskReadPacket.offset		= FP_OFF(buffer);
	/* Using transfer buffer */
	dosmemput(&diskReadPacket, sizeof(struct DRP), transfer_buffer);

	mode_flags.reserved_1 = 0;
	mode_flags.write_type = 0;
	mode_flags.direction  = (ReadOrWrite == READ) ? 0 : 1;
	mode_flags.reserved_2 = 0;

	DosDrive++;

	/* no inline asm for Turbo C 2.01! -ea */
	/* Turbo C also complains about packed bitfield structures -ea */
	regs.x.ax = 0x7305;
	regs.x.ds = FP_SEG(transfer_buffer);
	regs.x.bx = FP_OFF(transfer_buffer);
	regs.x.cx = 0xffff;
	regs.h.dl = DosDrive;
	regs.x.si = mode_flags.direction; /* | (mode_flags.write_type << 13); */
	__dpmi_int(0x21, &regs);
	return ((regs.x.flags&CARRY_FLAG) ? regs.x.ax : 0);
}
Example #28
0
void Sys_DetectWin95 (void)
{
	__dpmi_regs				r;

	r.x.ax = 0x160a;		/* Get Windows Version */
	__dpmi_int(0x2f, &r);

	if(r.x.ax || r.h.bh < 4)	/* Not windows or earlier than Win95 */
	{
		win95 = 0;
		lockmem = true;
		lockunlockmem = false;
		unlockmem = true;
		printf ("Win9X is absent\n");
	}
	else	if(r.x.ax || r.h.bh > 5)	/* A stupid Windows NT based OS attempt*/
	{
		win95 = 1;
		lockunlockmem = COM_CheckParm ("-winlockunlock");

		if (lockunlockmem)
			lockmem = true;
		else
			lockmem = COM_CheckParm ("-winlock");

		unlockmem = lockmem && !lockunlockmem;
		printf ("Windows NT, 2000, XP, Vista, 7 detected \n\nTHE GAME WILL NOT RUN IN XP!\n\nPlease use or compile the Win32 port, or use a DOS emulator\nsuch as DOSbox if you **really** want to play the DOS version.\n");
	}
	else
	{
		win95 = 1;
		printf ("Win9X is present!\n");
		lockunlockmem = COM_CheckParm ("-winlockunlock");

		if (lockunlockmem)
			lockmem = true;
		else
			lockmem = COM_CheckParm ("-winlock");

		unlockmem = lockmem && !lockunlockmem;
	}
}
Example #29
0
/* Open the clipboard, return non-zero if successful.  */
unsigned
open_clipboard (void)
{
  __dpmi_regs regs;

  /* Is WINOLDAP supported?  */
  /* Kludge alert!!  If WinOldAp is not supported, we return a 0,
     which is the same as ``Clipboard already open''.  Currently,
     this is taken as an error by all the functions that use
     `open_clipboard', but if somebody someday will use that ``open''
     clipboard, they will have interesting time debugging it...  */
  if (identify_winoldap_version () == 0x1700)
    return 0;

  /* Calls Int 2Fh/AX=1701h
     Return Values   AX == 0: Clipboard already open
			<> 0: Clipboard opened */
  regs.x.ax = 0x1701;
  __dpmi_int (0x2f, &regs);
  return regs.x.ax;
}
Example #30
0
static int driver_init(char *title, int w, int h, int depth_arg, int refresh_rate, int flags)
{
    int depth = MAX(8, depth_arg);
	int i;
	
	fb_dos_detect();
	
	if (flags & DRIVER_OPENGL)
		return -1;
	
	if ((w != 320) || (h != 240) || (depth != 8)) {
		return -1;
	}
	
	/* set base video mode */
	fb_dos.regs.x.ax = 0x13;
	__dpmi_int(0x10, &fb_dos.regs);
	
	/* tweak to Mode X */
	outportw(SC_INDEX, 0x0604);  /* disable chain4 */
	
	outportw(SC_INDEX, 0x0100);  /* synchronous reset */
	outportb(MISC_OUTPUT, 0xE3); /* select 25 MHz dot clock & 60 Hz scanning rate */
	outportw(SC_INDEX, 0x0300);  /* undo reset (restart sequencer) */
	
	outportb(CRTC_INDEX, 0x11);  /* VSync End reg contains register write protect bit */
	outportb(CRTC_INDEX+1, inportb(CRTC_INDEX+1) & 0x7F);	/* remove write protect on various CRTC registers */
	
	for (i = 0; i < CRT_PARM_LENGTH; i++) {
		outportw(CRTC_INDEX, CRTParams[i]);
	}

	refresh_rate = 60;

	fb_dos.update = driver_update;
	fb_dos.update_len = (unsigned int)end_of_driver_update - (unsigned int)driver_update;
	fb_dos.set_palette = fb_dos_vga_set_palette;

	return fb_dos_init(title, w, h, depth, refresh_rate, flags);
}