OpenCores
URL https://opencores.org/ocsvn/zet86/zet86/trunk

Subversion Repositories zet86

[/] [zet86/] [trunk/] [soc/] [bios/] [vgabios.c] - Diff between revs 49 and 52

Only display areas with differences | Details | Blame | View Log

Rev 49 Rev 52
#include "vgabios.h"
#include "vgabios.h"
 
 
/* Declares */
/* Declares */
static Bit8u          read_byte();
static Bit8u          read_byte();
static Bit16u         read_word();
static Bit16u         read_word();
static void           write_byte();
static void           write_byte();
static void           write_word();
static void           write_word();
static Bit8u          inb();
static Bit8u          inb();
static Bit16u         inw();
static Bit16u         inw();
static void           outb();
static void           outb();
static void           outw();
static void           outw();
 
 
static Bit16u         get_SS();
static Bit16u         get_SS();
 
 
// Output
// Output
static void           printf();
static void           printf();
 
 
static Bit8u find_vga_entry();
static Bit8u find_vga_entry();
 
 
static void memsetb();
static void memsetb();
static void memsetw();
static void memsetw();
static void memcpyb();
static void memcpyb();
static void memcpyw();
static void memcpyw();
 
 
static void biosfn_set_video_mode();
static void biosfn_set_video_mode();
static void biosfn_set_cursor_shape();
static void biosfn_set_cursor_shape();
static void biosfn_set_cursor_pos();
static void biosfn_set_cursor_pos();
static void biosfn_get_cursor_pos();
static void biosfn_get_cursor_pos();
static void biosfn_scroll();
static void biosfn_scroll();
static void biosfn_read_char_attr();
static void biosfn_read_char_attr();
static void biosfn_write_char_attr();
static void biosfn_write_char_attr();
static void biosfn_write_char_only();
static void biosfn_write_char_only();
static void biosfn_write_teletype();
static void biosfn_write_teletype();
static void biosfn_load_text_8_16_pat();
static void biosfn_load_text_8_16_pat();
static void biosfn_write_string();
static void biosfn_write_string();
extern Bit8u video_save_pointer_table[];
extern Bit8u video_save_pointer_table[];
 
 
// This is for compiling with gcc2 and gcc3
// This is for compiling with gcc2 and gcc3
#define ASM_START #asm
#define ASM_START #asm
#define ASM_END   #endasm
#define ASM_END   #endasm
 
 
ASM_START
ASM_START
 
 
MACRO SET_INT_VECTOR
MACRO SET_INT_VECTOR
  push ds
  push ds
  xor ax, ax
  xor ax, ax
  mov ds, ax
  mov ds, ax
  mov ax, ?3
  mov ax, ?3
  mov ?1*4, ax
  mov ?1*4, ax
  mov ax, ?2
  mov ax, ?2
  mov ?1*4+2, ax
  mov ?1*4+2, ax
  pop ds
  pop ds
MEND
MEND
 
 
ASM_END
ASM_END
 
 
ASM_START
ASM_START
.text
.text
.rom
.rom
.org 0
.org 0
 
 
use16 8086
use16 8086
 
 
vgabios_start:
vgabios_start:
.byte   0x55, 0xaa      /* BIOS signature, required for BIOS extensions */
.byte   0x55, 0xaa      /* BIOS signature, required for BIOS extensions */
 
 
.byte   0x40            /* BIOS extension length in units of 512 bytes */
.byte   0x40            /* BIOS extension length in units of 512 bytes */
 
 
 
 
vgabios_entry_point:
vgabios_entry_point:
 
 
  jmp vgabios_init_func
  jmp vgabios_init_func
 
 
vgabios_name:
vgabios_name:
.ascii  "Zet/Bochs VGABios"
.ascii  "Zet/Bochs VGABios"
.ascii  " "
.ascii  " "
.byte   0x00
.byte   0x00
 
 
// Info from Bart Oldeman
// Info from Bart Oldeman
.org 0x1e
.org 0x1e
.ascii  "IBM"
.ascii  "IBM"
.byte   0x00
.byte   0x00
 
 
vgabios_version:
vgabios_version:
#ifndef VGABIOS_VERS
#ifndef VGABIOS_VERS
.ascii  "current-cvs"
.ascii  "current-cvs"
#else
#else
.ascii VGABIOS_VERS
.ascii VGABIOS_VERS
#endif
#endif
.ascii  " "
.ascii  " "
 
 
vgabios_date:
vgabios_date:
.ascii  VGABIOS_DATE
.ascii  VGABIOS_DATE
.byte   0x0a,0x0d
.byte   0x0a,0x0d
.byte   0x00
.byte   0x00
 
 
vgabios_copyright:
vgabios_copyright:
.ascii  "(C) 2003 the LGPL VGABios developers Team"
.ascii  "(C) 2003 the LGPL VGABios developers Team"
.byte   0x0a,0x0d
.byte   0x0a,0x0d
.byte   0x00
.byte   0x00
 
 
vgabios_license:
vgabios_license:
.ascii  "This VGA/VBE Bios is released under the GNU LGPL"
.ascii  "This VGA/VBE Bios is released under the GNU LGPL"
.byte   0x0a,0x0d
.byte   0x0a,0x0d
.byte   0x0a,0x0d
.byte   0x0a,0x0d
.byte   0x00
.byte   0x00
 
 
vgabios_website:
vgabios_website:
.ascii  "Please visit :"
.ascii  "Please visit :"
.byte   0x0a,0x0d
.byte   0x0a,0x0d
;;.ascii  " . http://www.plex86.org"
;;.ascii  " . http://www.plex86.org"
;;.byte 0x0a,0x0d
;;.byte 0x0a,0x0d
.ascii  " . http://zet.aluzina.org"
.ascii  " . http://zet.aluzina.org"
.byte   0x0a,0x0d
.byte   0x0a,0x0d
.ascii  " . http://bochs.sourceforge.net"
.ascii  " . http://bochs.sourceforge.net"
.byte   0x0a,0x0d
.byte   0x0a,0x0d
.ascii  " . http://www.nongnu.org/vgabios"
.ascii  " . http://www.nongnu.org/vgabios"
.byte   0x0a,0x0d
.byte   0x0a,0x0d
.byte   0x0a,0x0d
.byte   0x0a,0x0d
.byte   0x00
.byte   0x00
 
 
 
 
;; ========================================================
;; ========================================================
;;
;;
;; Init Entry point
;; Init Entry point
;;
;;
;; ========================================================
;; ========================================================
vgabios_init_func:
vgabios_init_func:
 
 
;; init vga card
;; init vga card
  call init_vga_card
  call init_vga_card
 
 
;; init basic bios vars
;; init basic bios vars
  call init_bios_area
  call init_bios_area
 
 
;; set int10 vect
;; set int10 vect
  SET_INT_VECTOR(0x10, #0xC000, #vgabios_int10_handler)
  SET_INT_VECTOR(0x10, #0xC000, #vgabios_int10_handler)
 
 
;; display splash screen
;; display splash screen
  call _display_splash_screen
  call _display_splash_screen
 
 
;; init video mode and clear the screen
;; init video mode and clear the screen
  mov ax,#0x0003
  mov ax,#0x0003
  int #0x10
  int #0x10
 
 
;; show info
;; show info
  call _display_info
  call _display_info
 
 
  retf
  retf
ASM_END
ASM_END
 
 
/*
/*
 *  int10 handled here
 *  int10 handled here
 */
 */
ASM_START
ASM_START
vgabios_int10_handler:
vgabios_int10_handler:
  pushf
  pushf
  cmp   ah, #0x0f
  cmp   ah, #0x0f
  jne   int10_test_1A
  jne   int10_test_1A
  call  biosfn_get_video_mode
  call  biosfn_get_video_mode
  jmp   int10_end
  jmp   int10_end
int10_test_1A:
int10_test_1A:
int10_test_1103:
int10_test_1103:
  cmp   ax, #0x1103
  cmp   ax, #0x1103
  jne   int10_normal
  jne   int10_normal
  call  biosfn_set_text_block_specifier
  call  biosfn_set_text_block_specifier
  jmp   int10_end
  jmp   int10_end
 
 
int10_normal:
int10_normal:
  push es
  push es
  push ds
  push ds
  ;pusha ; we do this instead:
  ;pusha ; we do this instead:
 
 
  push ax
  push ax
  push cx
  push cx
  push dx
  push dx
  push bx
  push bx
  push sp
  push sp
  mov  bx, sp
  mov  bx, sp
  sseg
  sseg
    add  [bx], #10
    add  [bx], #10
  sseg
  sseg
    mov  bx, [bx+2]
    mov  bx, [bx+2]
  push bp
  push bp
  push si
  push si
  push di
  push di
 
 
;; We have to set ds to access the right data segment
;; We have to set ds to access the right data segment
  mov   bx, #0xc000
  mov   bx, #0xc000
  mov   ds, bx
  mov   ds, bx
 
 
  call _int10_func
  call _int10_func
 
 
  ; popa ; we do this instead:
  ; popa ; we do this instead:
  pop di
  pop di
  pop si
  pop si
  pop bp
  pop bp
  add sp, #2
  add sp, #2
  pop bx
  pop bx
  pop dx
  pop dx
  pop cx
  pop cx
  pop ax
  pop ax
 
 
  pop ds
  pop ds
  pop es
  pop es
int10_end:
int10_end:
  popf
  popf
  iret
  iret
ASM_END
ASM_END
 
 
#include "vgatables.h"
#include "vgatables.h"
#include "vgafonts.h"
#include "vgafonts.h"
 
 
/*
/*
 * Boot time harware inits
 * Boot time harware inits
 */
 */
ASM_START
ASM_START
init_vga_card:
init_vga_card:
;; switch to color mode and enable CPU access 480 lines
;; switch to color mode and enable CPU access 480 lines
  mov dx, #0x3C2
  mov dx, #0x3C2
  mov al, #0xC3
  mov al, #0xC3
  outb dx,al
  outb dx,al
 
 
;; more than 64k 3C4/04
;; more than 64k 3C4/04
  mov dx, #0x3C4
  mov dx, #0x3C4
  mov al, #0x04
  mov al, #0x04
  outb dx,al
  outb dx,al
  mov dx, #0x3C5
  mov dx, #0x3C5
  mov al, #0x02
  mov al, #0x02
  outb dx,al
  outb dx,al
 
 
#if defined(USE_BX_INFO) || defined(DEBUG)
#if defined(USE_BX_INFO) || defined(DEBUG)
  mov  bx, #msg_vga_init
  mov  bx, #msg_vga_init
  push bx
  push bx
  call _printf
  call _printf
#endif
#endif
;  inc  sp
;  inc  sp
;  inc  sp
;  inc  sp
  ret
  ret
 
 
#if defined(USE_BX_INFO) || defined(DEBUG)
#if defined(USE_BX_INFO) || defined(DEBUG)
msg_vga_init:
msg_vga_init:
.ascii "VGABios $Id: vgabios.c,v 1.9 2009-03-05 19:58:40 zeus Exp $"
.ascii "VGABios $Id: vgabios.c,v 1.66 2006/07/10 07:47:51 vruppert Exp $"
.byte 0x0d,0x0a,0x00
.byte 0x0d,0x0a,0x00
#endif
#endif
ASM_END
ASM_END
 
 
// --------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------
/*
/*
 *  Boot time bios area inits
 *  Boot time bios area inits
 */
 */
ASM_START
ASM_START
init_bios_area:
init_bios_area:
  push  ds
  push  ds
  mov   ax, # BIOSMEM_SEG
  mov   ax, # BIOSMEM_SEG
  mov   ds, ax
  mov   ds, ax
 
 
;; init detected hardware BIOS Area
;; init detected hardware BIOS Area
  mov   bx, # BIOSMEM_INITIAL_MODE
  mov   bx, # BIOSMEM_INITIAL_MODE
  mov   ax, [bx]
  mov   ax, [bx]
  and   ax, #0xffcf
  and   ax, #0xffcf
;; set 80x25 color (not clear from RBIL but usual)
;; set 80x25 color (not clear from RBIL but usual)
  or    ax, #0x0020
  or    ax, #0x0020
  mov   [bx], ax
  mov   [bx], ax
 
 
;; Just for the first int10 find its children
;; Just for the first int10 find its children
 
 
;; the default char height
;; the default char height
  mov   bx, # BIOSMEM_CHAR_HEIGHT
  mov   bx, # BIOSMEM_CHAR_HEIGHT
  mov   al, #0x10
  mov   al, #0x10
  mov   [bx], al
  mov   [bx], al
 
 
;; Clear the screen
;; Clear the screen
  mov   bx, # BIOSMEM_VIDEO_CTL
  mov   bx, # BIOSMEM_VIDEO_CTL
  mov   al, #0x60
  mov   al, #0x60
  mov   [bx], al
  mov   [bx], al
 
 
;; Set the basic screen we have
;; Set the basic screen we have
  mov   bx, # BIOSMEM_SWITCHES
  mov   bx, # BIOSMEM_SWITCHES
  mov   al, #0xf9
  mov   al, #0xf9
  mov   [bx], al
  mov   [bx], al
 
 
;; Set the basic modeset options
;; Set the basic modeset options
  mov   bx, # BIOSMEM_MODESET_CTL
  mov   bx, # BIOSMEM_MODESET_CTL
  mov   al, #0x51
  mov   al, #0x51
  mov   [bx], al
  mov   [bx], al
 
 
;; Set the  default MSR
;; Set the  default MSR
  mov   bx, # BIOSMEM_CURRENT_MSR
  mov   bx, # BIOSMEM_CURRENT_MSR
  mov   al, #0x09
  mov   al, #0x09
  mov   [bx], al
  mov   [bx], al
 
 
  pop ds
  pop ds
  ret
  ret
 
 
_video_save_pointer_table:
_video_save_pointer_table:
  .word _video_param_table
  .word _video_param_table
  .word 0xc000
  .word 0xc000
 
 
  .word 0 /* XXX: fill it */
  .word 0 /* XXX: fill it */
  .word 0
  .word 0
 
 
  .word 0 /* XXX: fill it */
  .word 0 /* XXX: fill it */
  .word 0
  .word 0
 
 
  .word 0 /* XXX: fill it */
  .word 0 /* XXX: fill it */
  .word 0
  .word 0
 
 
  .word 0 /* XXX: fill it */
  .word 0 /* XXX: fill it */
  .word 0
  .word 0
 
 
  .word 0 /* XXX: fill it */
  .word 0 /* XXX: fill it */
  .word 0
  .word 0
 
 
  .word 0 /* XXX: fill it */
  .word 0 /* XXX: fill it */
  .word 0
  .word 0
 
 
ASM_END
ASM_END
 
 
// --------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------
/*
/*
 *  Boot time Splash screen
 *  Boot time Splash screen
 */
 */
static void display_splash_screen()
static void display_splash_screen()
{
{
}
}
 
 
// --------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------
/*
/*
 *  Tell who we are
 *  Tell who we are
 */
 */
 
 
static void display_info()
static void display_info()
{
{
ASM_START
ASM_START
 mov ax,#0xc000
 mov ax,#0xc000
 mov ds,ax
 mov ds,ax
 mov si,#vgabios_name
 mov si,#vgabios_name
 call _display_string
 call _display_string
 mov si,#vgabios_version
 mov si,#vgabios_version
 call _display_string
 call _display_string
 
 
 ;;mov si,#vgabios_copyright
 ;;mov si,#vgabios_copyright
 ;;call _display_string
 ;;call _display_string
 ;;mov si,#crlf
 ;;mov si,#crlf
 ;;call _display_string
 ;;call _display_string
 
 
 mov si,#vgabios_license
 mov si,#vgabios_license
 call _display_string
 call _display_string
 mov si,#vgabios_website
 mov si,#vgabios_website
 call _display_string
 call _display_string
ASM_END
ASM_END
}
}
 
 
static void display_string()
static void display_string()
{
{
 // Get length of string
 // Get length of string
ASM_START
ASM_START
 mov ax,ds
 mov ax,ds
 mov es,ax
 mov es,ax
 mov di,si
 mov di,si
 xor cx,cx
 xor cx,cx
 not cx
 not cx
 xor al,al
 xor al,al
 cld
 cld
 repne
 repne
  scasb
  scasb
 not cx
 not cx
 dec cx
 dec cx
 push cx
 push cx
 
 
 mov ax,#0x0300
 mov ax,#0x0300
 mov bx,#0x0000
 mov bx,#0x0000
 int #0x10
 int #0x10
 
 
 pop cx
 pop cx
 mov ax,#0x1301
 mov ax,#0x1301
 mov bx,#0x000b
 mov bx,#0x000b
 mov bp,si
 mov bp,si
 int #0x10
 int #0x10
ASM_END
ASM_END
}
}
 
 
// --------------------------------------------------------
// --------------------------------------------------------
/*
/*
 * int10 main dispatcher
 * int10 main dispatcher
 */
 */
static void int10_func(DI, SI, BP, SP, BX, DX, CX, AX, DS, ES, FLAGS)
static void int10_func(DI, SI, BP, SP, BX, DX, CX, AX, DS, ES, FLAGS)
  Bit16u DI, SI, BP, SP, BX, DX, CX, AX, ES, DS, FLAGS;
  Bit16u DI, SI, BP, SP, BX, DX, CX, AX, ES, DS, FLAGS;
{
{
 // BIOS functions
 // BIOS functions
 switch(GET_AH())
 switch(GET_AH())
  {
  {
   case 0x00:
   case 0x00:
     biosfn_set_video_mode(GET_AL());
     biosfn_set_video_mode(GET_AL());
     switch(GET_AL()&0x7F)
     switch(GET_AL()&0x7F)
      {case 6:
      {case 6:
        SET_AL(0x3F);
        SET_AL(0x3F);
        break;
        break;
       case 0:
       case 0:
       case 1:
       case 1:
       case 2:
       case 2:
       case 3:
       case 3:
       case 4:
       case 4:
       case 5:
       case 5:
       case 7:
       case 7:
        SET_AL(0x30);
        SET_AL(0x30);
        break;
        break;
      default:
      default:
        SET_AL(0x20);
        SET_AL(0x20);
      }
      }
     break;
     break;
   case 0x01:
   case 0x01:
     biosfn_set_cursor_shape(GET_CH(),GET_CL());
     biosfn_set_cursor_shape(GET_CH(),GET_CL());
     break;
     break;
   case 0x02:
   case 0x02:
     biosfn_set_cursor_pos(GET_BH(),DX);
     biosfn_set_cursor_pos(GET_BH(),DX);
     break;
     break;
   case 0x03:
   case 0x03:
     biosfn_get_cursor_pos(GET_BH(),&CX,&DX);
     biosfn_get_cursor_pos(GET_BH(),&CX,&DX);
     break;
     break;
   case 0x06:
   case 0x06:
     biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_UP);
     biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_UP);
     break;
     break;
   case 0x07:
   case 0x07:
     biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_DOWN);
     biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_DOWN);
     break;
     break;
   case 0x08:
   case 0x08:
     biosfn_read_char_attr(GET_BH(),&AX);
     biosfn_read_char_attr(GET_BH(),&AX);
     break;
     break;
   case 0x09:
   case 0x09:
     biosfn_write_char_attr(GET_AL(),GET_BH(),GET_BL(),CX);
     biosfn_write_char_attr(GET_AL(),GET_BH(),GET_BL(),CX);
     break;
     break;
   case 0x0A:
   case 0x0A:
     biosfn_write_char_only(GET_AL(),GET_BH(),GET_BL(),CX);
     biosfn_write_char_only(GET_AL(),GET_BH(),GET_BL(),CX);
     break;
     break;
   case 0x0E:
   case 0x0E:
     // Ralf Brown Interrupt list is WRONG on bh(page)
     // Ralf Brown Interrupt list is WRONG on bh(page)
     // We do output only on the current page !
     // We do output only on the current page !
     biosfn_write_teletype(GET_AL(),0xff,GET_BL(),NO_ATTR);
     biosfn_write_teletype(GET_AL(),0xff,GET_BL(),NO_ATTR);
     break;
     break;
   case 0x11:
   case 0x11:
     switch(GET_AL())
     switch(GET_AL())
      {
      {
       case 0x04:
       case 0x04:
       case 0x14:
       case 0x14:
        biosfn_load_text_8_16_pat(GET_AL(),GET_BL());
        biosfn_load_text_8_16_pat(GET_AL(),GET_BL());
        break;
        break;
      }
      }
     break;
     break;
   case 0x13:
   case 0x13:
     biosfn_write_string(GET_AL(),GET_BH(),GET_BL(),CX,GET_DH(),GET_DL(),ES,BP);
     biosfn_write_string(GET_AL(),GET_BH(),GET_BL(),CX,GET_DH(),GET_DL(),ES,BP);
     break;
     break;
  }
  }
}
}
 
 
// ============================================================================================
// ============================================================================================
//
//
// BIOS functions
// BIOS functions
//
//
// ============================================================================================
// ============================================================================================
 
 
static void biosfn_set_video_mode(mode) Bit8u mode;
static void biosfn_set_video_mode(mode) Bit8u mode;
{// mode: Bit 7 is 1 if no clear screen
{// mode: Bit 7 is 1 if no clear screen
 
 
 // Should we clear the screen ?
 // Should we clear the screen ?
 Bit8u noclearmem=mode&0x80;
 Bit8u noclearmem=mode&0x80;
 Bit8u line,mmask,*palette,vpti;
 Bit8u line,mmask,*palette,vpti;
 Bit16u i,twidth,theightm1,cheight;
 Bit16u i,twidth,theightm1,cheight;
 Bit8u modeset_ctl,video_ctl,vga_switches;
 Bit8u modeset_ctl,video_ctl,vga_switches;
 Bit16u crtc_addr;
 Bit16u crtc_addr;
 
 
 // The real mode
 // The real mode
 mode=mode&0x7f;
 mode=mode&0x7f;
 
 
 // find the entry in the video modes
 // find the entry in the video modes
 line=find_vga_entry(mode);
 line=find_vga_entry(mode);
 
 
 if(line==0xFF)
 if(line==0xFF)
  return;
  return;
 
 
 vpti=line_to_vpti[line];
 vpti=line_to_vpti[line];
 twidth=video_param_table[vpti].twidth;
 twidth=video_param_table[vpti].twidth;
 theightm1=video_param_table[vpti].theightm1;
 theightm1=video_param_table[vpti].theightm1;
 cheight=video_param_table[vpti].cheight;
 cheight=video_param_table[vpti].cheight;
 
 
 // Read the bios vga control
 // Read the bios vga control
 video_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL);
 video_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL);
 
 
 // Read the bios vga switches
 // Read the bios vga switches
 vga_switches=read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES);
 vga_switches=read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES);
 
 
 // Read the bios mode set control
 // Read the bios mode set control
 modeset_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
 modeset_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
 
 
 // Then we know the number of lines
 // Then we know the number of lines
// FIXME
// FIXME
 
 
 // if palette loading (bit 3 of modeset ctl = 0)
 // if palette loading (bit 3 of modeset ctl = 0)
 if((modeset_ctl&0x08)==0)
 if((modeset_ctl&0x08)==0)
  {// Set the PEL mask
  {// Set the PEL mask
   outb(VGAREG_PEL_MASK,vga_modes[line].pelmask);
   outb(VGAREG_PEL_MASK,vga_modes[line].pelmask);
 
 
   // Set the whole dac always, from 0
   // Set the whole dac always, from 0
   outb(VGAREG_DAC_WRITE_ADDRESS,0x00);
   outb(VGAREG_DAC_WRITE_ADDRESS,0x00);
 
 
   // From which palette
   // From which palette
   switch(vga_modes[line].dacmodel)
   switch(vga_modes[line].dacmodel)
    {case 0:
    {case 0:
      palette=&palette0;
      palette=&palette0;
      break;
      break;
     case 1:
     case 1:
      palette=&palette1;
      palette=&palette1;
      break;
      break;
     case 2:
     case 2:
      palette=&palette2;
      palette=&palette2;
      break;
      break;
     case 3:
     case 3:
      palette=&palette3;
      palette=&palette3;
      break;
      break;
    }
    }
   // Always 256*3 values
   // Always 256*3 values
   for(i=0;i<0x0100;i++)
   for(i=0;i<0x0100;i++)
    {if(i<=dac_regs[vga_modes[line].dacmodel])
    {if(i<=dac_regs[vga_modes[line].dacmodel])
      {outb(VGAREG_DAC_DATA,palette[(i*3)+0]);
      {outb(VGAREG_DAC_DATA,palette[(i*3)+0]);
       outb(VGAREG_DAC_DATA,palette[(i*3)+1]);
       outb(VGAREG_DAC_DATA,palette[(i*3)+1]);
       outb(VGAREG_DAC_DATA,palette[(i*3)+2]);
       outb(VGAREG_DAC_DATA,palette[(i*3)+2]);
      }
      }
     else
     else
      {outb(VGAREG_DAC_DATA,0);
      {outb(VGAREG_DAC_DATA,0);
       outb(VGAREG_DAC_DATA,0);
       outb(VGAREG_DAC_DATA,0);
       outb(VGAREG_DAC_DATA,0);
       outb(VGAREG_DAC_DATA,0);
      }
      }
    }
    }
  }
  }
 
 
 // Reset Attribute Ctl flip-flop
 // Reset Attribute Ctl flip-flop
 inb(VGAREG_ACTL_RESET);
 inb(VGAREG_ACTL_RESET);
 
 
 // Set Attribute Ctl
 // Set Attribute Ctl
 for(i=0;i<=0x13;i++)
 for(i=0;i<=0x13;i++)
  {outb(VGAREG_ACTL_ADDRESS,i);
  {outb(VGAREG_ACTL_ADDRESS,i);
   outb(VGAREG_ACTL_WRITE_DATA,video_param_table[vpti].actl_regs[i]);
   outb(VGAREG_ACTL_WRITE_DATA,video_param_table[vpti].actl_regs[i]);
  }
  }
 outb(VGAREG_ACTL_ADDRESS,0x14);
 outb(VGAREG_ACTL_ADDRESS,0x14);
 outb(VGAREG_ACTL_WRITE_DATA,0x00);
 outb(VGAREG_ACTL_WRITE_DATA,0x00);
 
 
 // Set Sequencer Ctl
 // Set Sequencer Ctl
 outb(VGAREG_SEQU_ADDRESS,0);
 outb(VGAREG_SEQU_ADDRESS,0);
 outb(VGAREG_SEQU_DATA,0x03);
 outb(VGAREG_SEQU_DATA,0x03);
 for(i=1;i<=4;i++)
 for(i=1;i<=4;i++)
  {outb(VGAREG_SEQU_ADDRESS,i);
  {outb(VGAREG_SEQU_ADDRESS,i);
   outb(VGAREG_SEQU_DATA,video_param_table[vpti].sequ_regs[i - 1]);
   outb(VGAREG_SEQU_DATA,video_param_table[vpti].sequ_regs[i - 1]);
  }
  }
 
 
 // Set Grafx Ctl
 // Set Grafx Ctl
 for(i=0;i<=8;i++)
 for(i=0;i<=8;i++)
  {outb(VGAREG_GRDC_ADDRESS,i);
  {outb(VGAREG_GRDC_ADDRESS,i);
   outb(VGAREG_GRDC_DATA,video_param_table[vpti].grdc_regs[i]);
   outb(VGAREG_GRDC_DATA,video_param_table[vpti].grdc_regs[i]);
  }
  }
 
 
 // Set CRTC address VGA or MDA
 // Set CRTC address VGA or MDA
 crtc_addr=vga_modes[line].memmodel==MTEXT?VGAREG_MDA_CRTC_ADDRESS:VGAREG_VGA_CRTC_ADDRESS;
 crtc_addr=vga_modes[line].memmodel==MTEXT?VGAREG_MDA_CRTC_ADDRESS:VGAREG_VGA_CRTC_ADDRESS;
 
 
 // Disable CRTC write protection
 // Disable CRTC write protection
 outw(crtc_addr,0x0011);
 outw(crtc_addr,0x0011);
 // Set CRTC regs
 // Set CRTC regs
 for(i=0;i<=0x18;i++)
 for(i=0;i<=0x18;i++)
  {outb(crtc_addr,i);
  {outb(crtc_addr,i);
   outb(crtc_addr+1,video_param_table[vpti].crtc_regs[i]);
   outb(crtc_addr+1,video_param_table[vpti].crtc_regs[i]);
  }
  }
 
 
 // Set the misc register
 // Set the misc register
 outb(VGAREG_WRITE_MISC_OUTPUT,video_param_table[vpti].miscreg);
 outb(VGAREG_WRITE_MISC_OUTPUT,video_param_table[vpti].miscreg);
 
 
 // Enable video
 // Enable video
 outb(VGAREG_ACTL_ADDRESS,0x20);
 outb(VGAREG_ACTL_ADDRESS,0x20);
 inb(VGAREG_ACTL_RESET);
 inb(VGAREG_ACTL_RESET);
 
 
 if(noclearmem==0x00)
 if(noclearmem==0x00)
  {
  {
   if(vga_modes[line].class==TEXT)
   if(vga_modes[line].class==TEXT)
    {
    {
     memsetw(vga_modes[line].sstart,0,0x0720,0x4000); // 32k
     memsetw(vga_modes[line].sstart,0,0x0720,0x4000); // 32k
    }
    }
   else
   else
    {
    {
     if(mode<0x0d)
     if(mode<0x0d)
      {
      {
       memsetw(vga_modes[line].sstart,0,0x0000,0x4000); // 32k
       memsetw(vga_modes[line].sstart,0,0x0000,0x4000); // 32k
      }
      }
     else
     else
      {
      {
       outb( VGAREG_SEQU_ADDRESS, 0x02 );
       outb( VGAREG_SEQU_ADDRESS, 0x02 );
       mmask = inb( VGAREG_SEQU_DATA );
       mmask = inb( VGAREG_SEQU_DATA );
       outb( VGAREG_SEQU_DATA, 0x0f ); // all planes
       outb( VGAREG_SEQU_DATA, 0x0f ); // all planes
       memsetw(vga_modes[line].sstart,0,0x0000,0x8000); // 64k
       memsetw(vga_modes[line].sstart,0,0x0000,0x8000); // 64k
       outb( VGAREG_SEQU_DATA, mmask );
       outb( VGAREG_SEQU_DATA, mmask );
      }
      }
    }
    }
  }
  }
 
 
 // Set the BIOS mem
 // Set the BIOS mem
 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE,mode);
 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE,mode);
 write_word(BIOSMEM_SEG,BIOSMEM_NB_COLS,twidth);
 write_word(BIOSMEM_SEG,BIOSMEM_NB_COLS,twidth);
 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE,*(Bit16u *)&video_param_table[vpti].slength_l);
 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE,*(Bit16u *)&video_param_table[vpti].slength_l);
 write_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS,crtc_addr);
 write_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS,crtc_addr);
 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS,theightm1);
 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS,theightm1);
 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,cheight);
 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,cheight);
 write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60|noclearmem));
 write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60|noclearmem));
 write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES,0xF9);
 write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES,0xF9);
 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)&0x7f);
 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)&0x7f);
 
 
 // FIXME We nearly have the good tables. to be reworked
 // FIXME We nearly have the good tables. to be reworked
 write_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX,0x08);    // 8 is VGA should be ok for now
 write_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX,0x08);    // 8 is VGA should be ok for now
 write_word(BIOSMEM_SEG,BIOSMEM_VS_POINTER, video_save_pointer_table);
 write_word(BIOSMEM_SEG,BIOSMEM_VS_POINTER, video_save_pointer_table);
 write_word(BIOSMEM_SEG,BIOSMEM_VS_POINTER+2, 0xc000);
 write_word(BIOSMEM_SEG,BIOSMEM_VS_POINTER+2, 0xc000);
 
 
 // FIXME
 // FIXME
 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x00); // Unavailable on vanilla vga, but...
 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x00); // Unavailable on vanilla vga, but...
 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x00); // Unavailable on vanilla vga, but...
 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x00); // Unavailable on vanilla vga, but...
 
 
 if(vga_modes[line].class==TEXT)
 if(vga_modes[line].class==TEXT)
  {
  {
   biosfn_set_cursor_shape(0x06,0x07);
   biosfn_set_cursor_shape(0x06,0x07);
  }
  }
 
 
 // Set cursor pos for page 0..7
 // Set cursor pos for page 0..7
 for(i=0;i<8;i++)
 for(i=0;i<8;i++)
  biosfn_set_cursor_pos(i,0x0000);
  biosfn_set_cursor_pos(i,0x0000);
 
 
 // Write the fonts in memory
 // Write the fonts in memory
 if(vga_modes[line].class==TEXT)
 if(vga_modes[line].class==TEXT)
  {
  {
ASM_START
ASM_START
  ;; copy and activate 8x16 font
  ;; copy and activate 8x16 font
  mov ax, #0x1104
  mov ax, #0x1104
  mov bl, #0x00
  mov bl, #0x00
  int #0x10
  int #0x10
  mov ax, #0x1103
  mov ax, #0x1103
  mov bl, #0x00
  mov bl, #0x00
  int #0x10
  int #0x10
ASM_END
ASM_END
  }
  }
}
}
 
 
// --------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------
static void biosfn_set_cursor_shape (CH,CL)
static void biosfn_set_cursor_shape (CH,CL)
Bit8u CH;Bit8u CL;
Bit8u CH;Bit8u CL;
{Bit16u cheight,curs,crtc_addr;
{Bit16u cheight,curs,crtc_addr;
 Bit8u modeset_ctl;
 Bit8u modeset_ctl;
 
 
 CH&=0x3f;
 CH&=0x3f;
 CL&=0x1f;
 CL&=0x1f;
 
 
 curs=(CH<<8)+CL;
 curs=(CH<<8)+CL;
 write_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE,curs);
 write_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE,curs);
 
 
 modeset_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
 modeset_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
 cheight = read_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT);
 cheight = read_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT);
 if((modeset_ctl&0x01) && (cheight>8) && (CL<8) && (CH<0x20))
 if((modeset_ctl&0x01) && (cheight>8) && (CL<8) && (CH<0x20))
  {
  {
   if(CL!=(CH+1))
   if(CL!=(CH+1))
    {
    {
     CH = ((CH+1) * cheight / 8) -1;
     CH = ((CH+1) * cheight / 8) -1;
    }
    }
   else
   else
    {
    {
     CH = ((CL+1) * cheight / 8) - 2;
     CH = ((CL+1) * cheight / 8) - 2;
    }
    }
   CL = ((CL+1) * cheight / 8) - 1;
   CL = ((CL+1) * cheight / 8) - 1;
  }
  }
 
 
 // CTRC regs 0x0a and 0x0b
 // CTRC regs 0x0a and 0x0b
 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
 outb(crtc_addr,0x0a);
 outb(crtc_addr,0x0a);
 outb(crtc_addr+1,CH);
 outb(crtc_addr+1,CH);
 outb(crtc_addr,0x0b);
 outb(crtc_addr,0x0b);
 outb(crtc_addr+1,CL);
 outb(crtc_addr+1,CL);
}
}
 
 
// --------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------
static void biosfn_set_cursor_pos (page, cursor)
static void biosfn_set_cursor_pos (page, cursor)
Bit8u page;Bit16u cursor;
Bit8u page;Bit16u cursor;
{
{
 Bit8u current;
 Bit8u current;
 Bit16u crtc_addr;
 Bit16u crtc_addr;
 
 
 // Should not happen...
 // Should not happen...
 if(page>7)return;
 if(page>7)return;
 
 
 // Bios cursor pos
 // Bios cursor pos
 write_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*page, cursor);
 write_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*page, cursor);
 
 
 // Set the hardware cursor
 // Set the hardware cursor
 current=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
 current=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
 if(page==current)
 if(page==current)
  {
  {
   // CRTC regs 0x0e and 0x0f
   // CRTC regs 0x0e and 0x0f
   crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
   crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
   outb(crtc_addr,0x0e);
   outb(crtc_addr,0x0e);
   outb(crtc_addr+1,(cursor&0xff00)>>8);
   outb(crtc_addr+1,(cursor&0xff00)>>8);
   outb(crtc_addr,0x0f);
   outb(crtc_addr,0x0f);
   outb(crtc_addr+1,cursor&0x00ff);
   outb(crtc_addr+1,cursor&0x00ff);
  }
  }
}
}
 
 
// --------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------
static void biosfn_get_cursor_pos (page,shape, pos)
static void biosfn_get_cursor_pos (page,shape, pos)
Bit8u page;Bit16u *shape;Bit16u *pos;
Bit8u page;Bit16u *shape;Bit16u *pos;
{
{
 Bit16u ss=get_SS();
 Bit16u ss=get_SS();
 
 
 // Default
 // Default
 write_word(ss, shape, 0);
 write_word(ss, shape, 0);
 write_word(ss, pos, 0);
 write_word(ss, pos, 0);
 
 
 if(page>7)return;
 if(page>7)return;
 // FIXME should handle VGA 14/16 lines
 // FIXME should handle VGA 14/16 lines
 write_word(ss,shape,read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE));
 write_word(ss,shape,read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE));
 write_word(ss,pos,read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_POS+page*2));
 write_word(ss,pos,read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_POS+page*2));
}
}
 
 
// --------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------
static void biosfn_scroll (nblines,attr,rul,cul,rlr,clr,page,dir)
static void biosfn_scroll (nblines,attr,rul,cul,rlr,clr,page,dir)
Bit8u nblines;Bit8u attr;Bit8u rul;Bit8u cul;Bit8u rlr;Bit8u clr;Bit8u page;Bit8u dir;
Bit8u nblines;Bit8u attr;Bit8u rul;Bit8u cul;Bit8u rlr;Bit8u clr;Bit8u page;Bit8u dir;
{
{
 // page == 0xFF if current
 // page == 0xFF if current
 
 
 Bit8u mode,line,cheight,bpp,cols;
 Bit8u mode,line,cheight,bpp,cols;
 Bit16u nbcols,nbrows,i;
 Bit16u nbcols,nbrows,i;
 Bit16u address;
 Bit16u address;
 
 
 if(rul>rlr)return;
 if(rul>rlr)return;
 if(cul>clr)return;
 if(cul>clr)return;
 
 
 // Get the mode
 // Get the mode
 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
 line=find_vga_entry(mode);
 line=find_vga_entry(mode);
 if(line==0xFF)return;
 if(line==0xFF)return;
 
 
 // Get the dimensions
 // Get the dimensions
 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
 
 
 // Get the current page
 // Get the current page
 if(page==0xFF)
 if(page==0xFF)
  page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
  page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
 
 
 if(rlr>=nbrows)rlr=nbrows-1;
 if(rlr>=nbrows)rlr=nbrows-1;
 if(clr>=nbcols)clr=nbcols-1;
 if(clr>=nbcols)clr=nbcols-1;
 if(nblines>nbrows)nblines=0;
 if(nblines>nbrows)nblines=0;
 cols=clr-cul+1;
 cols=clr-cul+1;
 
 
 if(vga_modes[line].class==TEXT)
 if(vga_modes[line].class==TEXT)
  {
  {
   // Compute the address
   // Compute the address
   address=SCREEN_MEM_START(nbcols,nbrows,page);
   address=SCREEN_MEM_START(nbcols,nbrows,page);
#ifdef DEBUG
#ifdef DEBUG
   printf("Scroll, address %04x (%04x %04x %02x)\n",address,nbrows,nbcols,page);
   printf("Scroll, address %04x (%04x %04x %02x)\n",address,nbrows,nbcols,page);
#endif
#endif
 
 
   if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
   if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
    {
    {
     memsetw(vga_modes[line].sstart,address,(Bit16u)attr*0x100+' ',nbrows*nbcols);
     memsetw(vga_modes[line].sstart,address,(Bit16u)attr*0x100+' ',nbrows*nbcols);
    }
    }
   else
   else
    {// if Scroll up
    {// if Scroll up
     if(dir==SCROLL_UP)
     if(dir==SCROLL_UP)
      {for(i=rul;i<=rlr;i++)
      {for(i=rul;i<=rlr;i++)
        {
        {
         if((i+nblines>rlr)||(nblines==0))
         if((i+nblines>rlr)||(nblines==0))
          memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(Bit16u)attr*0x100+' ',cols);
          memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(Bit16u)attr*0x100+' ',cols);
         else
         else
          memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i+nblines)*nbcols+cul)*2,cols);
          memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i+nblines)*nbcols+cul)*2,cols);
        }
        }
      }
      }
     else
     else
      {for(i=rlr;i>=rul;i--)
      {for(i=rlr;i>=rul;i--)
        {
        {
         if((i<rul+nblines)||(nblines==0))
         if((i<rul+nblines)||(nblines==0))
          memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(Bit16u)attr*0x100+' ',cols);
          memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(Bit16u)attr*0x100+' ',cols);
         else
         else
          memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i-nblines)*nbcols+cul)*2,cols);
          memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i-nblines)*nbcols+cul)*2,cols);
         if (i>rlr) break;
         if (i>rlr) break;
        }
        }
      }
      }
    }
    }
  }
  }
}
}
 
 
// --------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------
static void biosfn_read_char_attr (page,car)
static void biosfn_read_char_attr (page,car)
Bit8u page;Bit16u *car;
Bit8u page;Bit16u *car;
{Bit16u ss=get_SS();
{Bit16u ss=get_SS();
 Bit8u xcurs,ycurs,mode,line;
 Bit8u xcurs,ycurs,mode,line;
 Bit16u nbcols,nbrows,address;
 Bit16u nbcols,nbrows,address;
 Bit16u cursor,dummy;
 Bit16u cursor,dummy;
 
 
 // Get the mode
 // Get the mode
 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
 line=find_vga_entry(mode);
 line=find_vga_entry(mode);
 if(line==0xFF)return;
 if(line==0xFF)return;
 
 
 // Get the cursor pos for the page
 // Get the cursor pos for the page
 biosfn_get_cursor_pos(page,&dummy,&cursor);
 biosfn_get_cursor_pos(page,&dummy,&cursor);
 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
 
 
 // Get the dimensions
 // Get the dimensions
 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
 
 
 // Compute the address
 // Compute the address
 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
 
 
 write_word(ss,car,read_word(vga_modes[line].sstart,address));
 write_word(ss,car,read_word(vga_modes[line].sstart,address));
}
}
 
 
// --------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------
static void biosfn_write_char_attr (car,page,attr,count)
static void biosfn_write_char_attr (car,page,attr,count)
Bit8u car;Bit8u page;Bit8u attr;Bit16u count;
Bit8u car;Bit8u page;Bit8u attr;Bit16u count;
{
{
 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
 Bit16u nbcols,nbrows,address;
 Bit16u nbcols,nbrows,address;
 Bit16u cursor,dummy;
 Bit16u cursor,dummy;
 
 
 // Get the mode
 // Get the mode
 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
 line=find_vga_entry(mode);
 line=find_vga_entry(mode);
 if(line==0xFF)return;
 if(line==0xFF)return;
 
 
 // Get the cursor pos for the page
 // Get the cursor pos for the page
 biosfn_get_cursor_pos(page,&dummy,&cursor);
 biosfn_get_cursor_pos(page,&dummy,&cursor);
 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
 
 
 // Get the dimensions
 // Get the dimensions
 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
 
 
 // Compute the address
 // Compute the address
 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
 
 
 dummy=((Bit16u)attr<<8)+car;
 dummy=((Bit16u)attr<<8)+car;
 memsetw(vga_modes[line].sstart,address,dummy,count);
 memsetw(vga_modes[line].sstart,address,dummy,count);
}
}
 
 
// --------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------
static void biosfn_write_char_only (car,page,attr,count)
static void biosfn_write_char_only (car,page,attr,count)
Bit8u car;Bit8u page;Bit8u attr;Bit16u count;
Bit8u car;Bit8u page;Bit8u attr;Bit16u count;
{
{
 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
 Bit16u nbcols,nbrows,address;
 Bit16u nbcols,nbrows,address;
 Bit16u cursor,dummy;
 Bit16u cursor,dummy;
 
 
 // Get the mode
 // Get the mode
 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
 line=find_vga_entry(mode);
 line=find_vga_entry(mode);
 if(line==0xFF)return;
 if(line==0xFF)return;
 
 
 // Get the cursor pos for the page
 // Get the cursor pos for the page
 biosfn_get_cursor_pos(page,&dummy,&cursor);
 biosfn_get_cursor_pos(page,&dummy,&cursor);
 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
 
 
 // Get the dimensions
 // Get the dimensions
 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
 
 
 // Compute the address
 // Compute the address
 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
 
 
 while(count-->0)
 while(count-->0)
  {write_byte(vga_modes[line].sstart,address,car);
  {write_byte(vga_modes[line].sstart,address,car);
   address+=2;
   address+=2;
  }
  }
}
}
 
 
// --------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------
static void biosfn_write_teletype (car, page, attr, flag)
static void biosfn_write_teletype (car, page, attr, flag)
Bit8u car;Bit8u page;Bit8u attr;Bit8u flag;
Bit8u car;Bit8u page;Bit8u attr;Bit8u flag;
{// flag = WITH_ATTR / NO_ATTR
{// flag = WITH_ATTR / NO_ATTR
 
 
 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
 Bit16u nbcols,nbrows,address;
 Bit16u nbcols,nbrows,address;
 Bit16u cursor,dummy;
 Bit16u cursor,dummy;
 
 
 // special case if page is 0xff, use current page
 // special case if page is 0xff, use current page
 if(page==0xff)
 if(page==0xff)
  page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
  page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
 
 
 // Get the mode
 // Get the mode
 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
 line=find_vga_entry(mode);
 line=find_vga_entry(mode);
 if(line==0xFF)return;
 if(line==0xFF)return;
 
 
 // Get the cursor pos for the page
 // Get the cursor pos for the page
 biosfn_get_cursor_pos(page,&dummy,&cursor);
 biosfn_get_cursor_pos(page,&dummy,&cursor);
 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
 
 
 // Get the dimensions
 // Get the dimensions
 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
 
 
 switch(car)
 switch(car)
  {
  {
   case 7:
   case 7:
    //FIXME should beep
    //FIXME should beep
    break;
    break;
 
 
   case 8:
   case 8:
    if(xcurs>0)xcurs--;
    if(xcurs>0)xcurs--;
    break;
    break;
 
 
   case '\r':
   case '\r':
    xcurs=0;
    xcurs=0;
    break;
    break;
 
 
   case '\n':
   case '\n':
    ycurs++;
    ycurs++;
    break;
    break;
 
 
   case '\t':
   case '\t':
    do
    do
     {
     {
      biosfn_write_teletype(' ',page,attr,flag);
      biosfn_write_teletype(' ',page,attr,flag);
      biosfn_get_cursor_pos(page,&dummy,&cursor);
      biosfn_get_cursor_pos(page,&dummy,&cursor);
      xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
      xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
     }while(xcurs%8==0);
     }while(xcurs%8==0);
    break;
    break;
 
 
   default:
   default:
 
 
    if(vga_modes[line].class==TEXT)
    if(vga_modes[line].class==TEXT)
     {
     {
      // Compute the address
      // Compute the address
      address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
      address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
 
 
      // Write the char
      // Write the char
      write_byte(vga_modes[line].sstart,address,car);
      write_byte(vga_modes[line].sstart,address,car);
 
 
      if(flag==WITH_ATTR)
      if(flag==WITH_ATTR)
       write_byte(vga_modes[line].sstart,address+1,attr);
       write_byte(vga_modes[line].sstart,address+1,attr);
     }
     }
    xcurs++;
    xcurs++;
  }
  }
 
 
 // Do we need to wrap ?
 // Do we need to wrap ?
 if(xcurs==nbcols)
 if(xcurs==nbcols)
  {xcurs=0;
  {xcurs=0;
   ycurs++;
   ycurs++;
  }
  }
 
 
 // Do we need to scroll ?
 // Do we need to scroll ?
 if(ycurs==nbrows)
 if(ycurs==nbrows)
  {
  {
   if(vga_modes[line].class==TEXT)
   if(vga_modes[line].class==TEXT)
    {
    {
     biosfn_scroll(0x01,0x07,0,0,nbrows-1,nbcols-1,page,SCROLL_UP);
     biosfn_scroll(0x01,0x07,0,0,nbrows-1,nbcols-1,page,SCROLL_UP);
    }
    }
   ycurs-=1;
   ycurs-=1;
  }
  }
 
 
 // Set the cursor for the page
 // Set the cursor for the page
 cursor=ycurs; cursor<<=8; cursor+=xcurs;
 cursor=ycurs; cursor<<=8; cursor+=xcurs;
 biosfn_set_cursor_pos(page,cursor);
 biosfn_set_cursor_pos(page,cursor);
}
}
 
 
// --------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------
ASM_START
ASM_START
biosfn_get_video_mode:
biosfn_get_video_mode:
  push  ds
  push  ds
  mov   ax, # BIOSMEM_SEG
  mov   ax, # BIOSMEM_SEG
  mov   ds, ax
  mov   ds, ax
  push  bx
  push  bx
  mov   bx, # BIOSMEM_CURRENT_PAGE
  mov   bx, # BIOSMEM_CURRENT_PAGE
  mov   al, [bx]
  mov   al, [bx]
  pop   bx
  pop   bx
  mov   bh, al
  mov   bh, al
  push  bx
  push  bx
  mov   bx, # BIOSMEM_VIDEO_CTL
  mov   bx, # BIOSMEM_VIDEO_CTL
  mov   ah, [bx]
  mov   ah, [bx]
  and   ah, #0x80
  and   ah, #0x80
  mov   bx, # BIOSMEM_CURRENT_MODE
  mov   bx, # BIOSMEM_CURRENT_MODE
  mov   al, [bx]
  mov   al, [bx]
  or    al, ah
  or    al, ah
  mov   bx, # BIOSMEM_NB_COLS
  mov   bx, # BIOSMEM_NB_COLS
  mov   ah, [bx]
  mov   ah, [bx]
  pop   bx
  pop   bx
  pop   ds
  pop   ds
  ret
  ret
ASM_END
ASM_END
 
 
// --------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------
static void get_font_access()
static void get_font_access()
{
{
ASM_START
ASM_START
 mov dx, # VGAREG_SEQU_ADDRESS
 mov dx, # VGAREG_SEQU_ADDRESS
 mov ax, #0x0100
 mov ax, #0x0100
 out dx, ax
 out dx, ax
 mov ax, #0x0402
 mov ax, #0x0402
 out dx, ax
 out dx, ax
 mov ax, #0x0704
 mov ax, #0x0704
 out dx, ax
 out dx, ax
 mov ax, #0x0300
 mov ax, #0x0300
 out dx, ax
 out dx, ax
 mov dx, # VGAREG_GRDC_ADDRESS
 mov dx, # VGAREG_GRDC_ADDRESS
 mov ax, #0x0204
 mov ax, #0x0204
 out dx, ax
 out dx, ax
 mov ax, #0x0005
 mov ax, #0x0005
 out dx, ax
 out dx, ax
 mov ax, #0x0406
 mov ax, #0x0406
 out dx, ax
 out dx, ax
ASM_END
ASM_END
}
}
 
 
static void release_font_access()
static void release_font_access()
{
{
ASM_START
ASM_START
 mov dx, # VGAREG_SEQU_ADDRESS
 mov dx, # VGAREG_SEQU_ADDRESS
 mov ax, #0x0100
 mov ax, #0x0100
 out dx, ax
 out dx, ax
 mov ax, #0x0302
 mov ax, #0x0302
 out dx, ax
 out dx, ax
 mov ax, #0x0304
 mov ax, #0x0304
 out dx, ax
 out dx, ax
 mov ax, #0x0300
 mov ax, #0x0300
 out dx, ax
 out dx, ax
 mov dx, # VGAREG_READ_MISC_OUTPUT
 mov dx, # VGAREG_READ_MISC_OUTPUT
 in  al, dx
 in  al, dx
 and al, #0x01
 and al, #0x01
 push cx
 push cx
 mov cl,*2
 mov cl,*2
 shl al,cl
 shl al,cl
 pop cx
 pop cx
 or  al, #0x0a
 or  al, #0x0a
 mov ah, al
 mov ah, al
 mov al, #0x06
 mov al, #0x06
 mov dx, # VGAREG_GRDC_ADDRESS
 mov dx, # VGAREG_GRDC_ADDRESS
 out dx, ax
 out dx, ax
 mov ax, #0x0004
 mov ax, #0x0004
 out dx, ax
 out dx, ax
 mov ax, #0x1005
 mov ax, #0x1005
 out dx, ax
 out dx, ax
ASM_END
ASM_END
}
}
 
 
ASM_START
ASM_START
idiv_u:
idiv_u:
  xor dx,dx
  xor dx,dx
  div bx
  div bx
  ret
  ret
ASM_END
ASM_END
 
 
static void set_scan_lines(lines) Bit8u lines;
static void set_scan_lines(lines) Bit8u lines;
{
{
 Bit16u crtc_addr,cols,page,vde;
 Bit16u crtc_addr,cols,page,vde;
 Bit8u crtc_r9,ovl,rows;
 Bit8u crtc_r9,ovl,rows;
 
 
 crtc_addr = read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
 crtc_addr = read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
 outb(crtc_addr, 0x09);
 outb(crtc_addr, 0x09);
 crtc_r9 = inb(crtc_addr+1);
 crtc_r9 = inb(crtc_addr+1);
 crtc_r9 = (crtc_r9 & 0xe0) | (lines - 1);
 crtc_r9 = (crtc_r9 & 0xe0) | (lines - 1);
 outb(crtc_addr+1, crtc_r9);
 outb(crtc_addr+1, crtc_r9);
/*
/*
 if(lines==8)
 if(lines==8)
  {
  {
   biosfn_set_cursor_shape(0x06,0x07);
   biosfn_set_cursor_shape(0x06,0x07);
  }
  }
 else
 else
  {
  {
   biosfn_set_cursor_shape(lines-4,lines-3);
   biosfn_set_cursor_shape(lines-4,lines-3);
  }
  }
*/
*/
 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT, lines);
 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT, lines);
 outb(crtc_addr, 0x12);
 outb(crtc_addr, 0x12);
 vde = inb(crtc_addr+1);
 vde = inb(crtc_addr+1);
 outb(crtc_addr, 0x07);
 outb(crtc_addr, 0x07);
 ovl = inb(crtc_addr+1);
 ovl = inb(crtc_addr+1);
 vde += (((ovl & 0x02) << 7) + ((ovl & 0x40) << 3) + 1);
 vde += (((ovl & 0x02) << 7) + ((ovl & 0x40) << 3) + 1);
 rows = vde / lines;
 rows = vde / lines;
 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS, rows-1);
 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS, rows-1);
 cols = read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
 cols = read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE, rows * cols * 2);
 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE, rows * cols * 2);
}
}
 
 
// --------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------
ASM_START
ASM_START
biosfn_set_text_block_specifier:
biosfn_set_text_block_specifier:
  push  ax
  push  ax
  push  dx
  push  dx
  mov   dx, # VGAREG_SEQU_ADDRESS
  mov   dx, # VGAREG_SEQU_ADDRESS
  mov   ah, bl
  mov   ah, bl
  mov   al, #0x03
  mov   al, #0x03
  out   dx, ax
  out   dx, ax
  pop   dx
  pop   dx
  pop   ax
  pop   ax
  ret
  ret
ASM_END
ASM_END
 
 
// --------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------
static void biosfn_load_text_8_16_pat (AL,BL) Bit8u AL;Bit8u BL;
static void biosfn_load_text_8_16_pat (AL,BL) Bit8u AL;Bit8u BL;
{
{
 Bit16u blockaddr,dest,i,src;
 Bit16u blockaddr,dest,i,src;
 
 
 get_font_access();
 get_font_access();
 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
 for(i=0;i<0x100;i++)
 for(i=0;i<0x100;i++)
  {
  {
   src = i * 16;
   src = i * 16;
   dest = blockaddr + i * 32;
   dest = blockaddr + i * 32;
   memcpyb(0xA000, dest, 0xC000, vgafont16+src, 16);
   memcpyb(0xA000, dest, 0xC000, vgafont16+src, 16);
  }
  }
 release_font_access();
 release_font_access();
 if(AL>=0x10)
 if(AL>=0x10)
  {
  {
   set_scan_lines(16);
   set_scan_lines(16);
  }
  }
}
}
 
 
// --------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------
static void biosfn_write_string (flag,page,attr,count,row,col,seg,offset)
static void biosfn_write_string (flag,page,attr,count,row,col,seg,offset)
Bit8u flag;Bit8u page;Bit8u attr;Bit16u count;Bit8u row;Bit8u col;Bit16u seg;Bit16u offset;
Bit8u flag;Bit8u page;Bit8u attr;Bit16u count;Bit8u row;Bit8u col;Bit16u seg;Bit16u offset;
{
{
 Bit16u newcurs,oldcurs,dummy;
 Bit16u newcurs,oldcurs,dummy;
 Bit8u car,carattr;
 Bit8u car,carattr;
 
 
 // Read curs info for the page
 // Read curs info for the page
 biosfn_get_cursor_pos(page,&dummy,&oldcurs);
 biosfn_get_cursor_pos(page,&dummy,&oldcurs);
 
 
 // if row=0xff special case : use current cursor position
 // if row=0xff special case : use current cursor position
 if(row==0xff)
 if(row==0xff)
  {col=oldcurs&0x00ff;
  {col=oldcurs&0x00ff;
   row=(oldcurs&0xff00)>>8;
   row=(oldcurs&0xff00)>>8;
  }
  }
 
 
 newcurs=row; newcurs<<=8; newcurs+=col;
 newcurs=row; newcurs<<=8; newcurs+=col;
 biosfn_set_cursor_pos(page,newcurs);
 biosfn_set_cursor_pos(page,newcurs);
 
 
 while(count--!=0)
 while(count--!=0)
  {
  {
   car=read_byte(seg,offset++);
   car=read_byte(seg,offset++);
   if((flag&0x02)!=0)
   if((flag&0x02)!=0)
    attr=read_byte(seg,offset++);
    attr=read_byte(seg,offset++);
 
 
   biosfn_write_teletype(car,page,attr,WITH_ATTR);
   biosfn_write_teletype(car,page,attr,WITH_ATTR);
  }
  }
 
 
 // Set back curs pos
 // Set back curs pos
 if((flag&0x01)==0)
 if((flag&0x01)==0)
  biosfn_set_cursor_pos(page,oldcurs);
  biosfn_set_cursor_pos(page,oldcurs);
}
}
 
 
// ============================================================================================
// ============================================================================================
//
//
// Video Utils
// Video Utils
//
//
// ============================================================================================
// ============================================================================================
 
 
// --------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------
static Bit8u find_vga_entry(mode)
static Bit8u find_vga_entry(mode)
Bit8u mode;
Bit8u mode;
{
{
 Bit8u i,line=0xFF;
 Bit8u i,line=0xFF;
 for(i=0;i<=MODE_MAX;i++)
 for(i=0;i<=MODE_MAX;i++)
  if(vga_modes[i].svgamode==mode)
  if(vga_modes[i].svgamode==mode)
   {line=i;
   {line=i;
    break;
    break;
   }
   }
 return line;
 return line;
}
}
 
 
// --------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------
static void memsetw(seg,offset,value,count)
static void memsetw(seg,offset,value,count)
  Bit16u seg;
  Bit16u seg;
  Bit16u offset;
  Bit16u offset;
  Bit16u value;
  Bit16u value;
  Bit16u count;
  Bit16u count;
{
{
ASM_START
ASM_START
  push bp
  push bp
  mov  bp, sp
  mov  bp, sp
 
 
    push ax
    push ax
    push cx
    push cx
    push es
    push es
    push di
    push di
 
 
    mov  cx, 10[bp] ; count
    mov  cx, 10[bp] ; count
    cmp  cx, #0x00
    cmp  cx, #0x00
    je   memsetw_end
    je   memsetw_end
    mov  ax, 4[bp] ; segment
    mov  ax, 4[bp] ; segment
    mov  es, ax
    mov  es, ax
    mov  ax, 6[bp] ; offset
    mov  ax, 6[bp] ; offset
    mov  di, ax
    mov  di, ax
    mov  ax, 8[bp] ; value
    mov  ax, 8[bp] ; value
    cld
    cld
    rep
    rep
     stosw
     stosw
 
 
memsetw_end:
memsetw_end:
    pop di
    pop di
    pop es
    pop es
    pop cx
    pop cx
    pop ax
    pop ax
 
 
  pop bp
  pop bp
ASM_END
ASM_END
}
}
 
 
// --------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------
static void memcpyb(dseg,doffset,sseg,soffset,count)
static void memcpyb(dseg,doffset,sseg,soffset,count)
  Bit16u dseg;
  Bit16u dseg;
  Bit16u doffset;
  Bit16u doffset;
  Bit16u sseg;
  Bit16u sseg;
  Bit16u soffset;
  Bit16u soffset;
  Bit16u count;
  Bit16u count;
{
{
ASM_START
ASM_START
  push bp
  push bp
  mov  bp, sp
  mov  bp, sp
 
 
    push ax
    push ax
    push cx
    push cx
    push es
    push es
    push di
    push di
    push ds
    push ds
    push si
    push si
 
 
    mov  cx, 12[bp] ; count
    mov  cx, 12[bp] ; count
    cmp  cx, #0x0000
    cmp  cx, #0x0000
    je   memcpyb_end
    je   memcpyb_end
    mov  ax, 4[bp] ; dsegment
    mov  ax, 4[bp] ; dsegment
    mov  es, ax
    mov  es, ax
    mov  ax, 6[bp] ; doffset
    mov  ax, 6[bp] ; doffset
    mov  di, ax
    mov  di, ax
    mov  ax, 8[bp] ; ssegment
    mov  ax, 8[bp] ; ssegment
    mov  ds, ax
    mov  ds, ax
    mov  ax, 10[bp] ; soffset
    mov  ax, 10[bp] ; soffset
    mov  si, ax
    mov  si, ax
    cld
    cld
    rep
    rep
     movsb
     movsb
 
 
memcpyb_end:
memcpyb_end:
    pop si
    pop si
    pop ds
    pop ds
    pop di
    pop di
    pop es
    pop es
    pop cx
    pop cx
    pop ax
    pop ax
 
 
  pop bp
  pop bp
ASM_END
ASM_END
}
}
 
 
// --------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------
static void memcpyw(dseg,doffset,sseg,soffset,count)
static void memcpyw(dseg,doffset,sseg,soffset,count)
  Bit16u dseg;
  Bit16u dseg;
  Bit16u doffset;
  Bit16u doffset;
  Bit16u sseg;
  Bit16u sseg;
  Bit16u soffset;
  Bit16u soffset;
  Bit16u count;
  Bit16u count;
{
{
ASM_START
ASM_START
  push bp
  push bp
  mov  bp, sp
  mov  bp, sp
 
 
    push ax
    push ax
    push cx
    push cx
    push es
    push es
    push di
    push di
    push ds
    push ds
    push si
    push si
 
 
    mov  cx, 12[bp] ; count
    mov  cx, 12[bp] ; count
    cmp  cx, #0x0000
    cmp  cx, #0x0000
    je   memcpyw_end
    je   memcpyw_end
    mov  ax, 4[bp] ; dsegment
    mov  ax, 4[bp] ; dsegment
    mov  es, ax
    mov  es, ax
    mov  ax, 6[bp] ; doffset
    mov  ax, 6[bp] ; doffset
    mov  di, ax
    mov  di, ax
    mov  ax, 8[bp] ; ssegment
    mov  ax, 8[bp] ; ssegment
    mov  ds, ax
    mov  ds, ax
    mov  ax, 10[bp] ; soffset
    mov  ax, 10[bp] ; soffset
    mov  si, ax
    mov  si, ax
    cld
    cld
    rep
    rep
     movsw
     movsw
 
 
memcpyw_end:
memcpyw_end:
    pop si
    pop si
    pop ds
    pop ds
    pop di
    pop di
    pop es
    pop es
    pop cx
    pop cx
    pop ax
    pop ax
 
 
  pop bp
  pop bp
ASM_END
ASM_END
}
}
 
 
// --------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------
static Bit8u
static Bit8u
read_byte(seg, offset)
read_byte(seg, offset)
  Bit16u seg;
  Bit16u seg;
  Bit16u offset;
  Bit16u offset;
{
{
ASM_START
ASM_START
  push bp
  push bp
  mov  bp, sp
  mov  bp, sp
 
 
    push bx
    push bx
    push ds
    push ds
    mov  ax, 4[bp] ; segment
    mov  ax, 4[bp] ; segment
    mov  ds, ax
    mov  ds, ax
    mov  bx, 6[bp] ; offset
    mov  bx, 6[bp] ; offset
    mov  al, [bx]
    mov  al, [bx]
    ;; al = return value (byte)
    ;; al = return value (byte)
    pop  ds
    pop  ds
    pop  bx
    pop  bx
 
 
  pop  bp
  pop  bp
ASM_END
ASM_END
}
}
 
 
// --------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------
static Bit16u
static Bit16u
read_word(seg, offset)
read_word(seg, offset)
  Bit16u seg;
  Bit16u seg;
  Bit16u offset;
  Bit16u offset;
{
{
ASM_START
ASM_START
  push bp
  push bp
  mov  bp, sp
  mov  bp, sp
 
 
    push bx
    push bx
    push ds
    push ds
    mov  ax, 4[bp] ; segment
    mov  ax, 4[bp] ; segment
    mov  ds, ax
    mov  ds, ax
    mov  bx, 6[bp] ; offset
    mov  bx, 6[bp] ; offset
    mov  ax, [bx]
    mov  ax, [bx]
    ;; ax = return value (word)
    ;; ax = return value (word)
    pop  ds
    pop  ds
    pop  bx
    pop  bx
 
 
  pop  bp
  pop  bp
ASM_END
ASM_END
}
}
 
 
// --------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------
static void
static void
write_byte(seg, offset, data)
write_byte(seg, offset, data)
  Bit16u seg;
  Bit16u seg;
  Bit16u offset;
  Bit16u offset;
  Bit8u  data;
  Bit8u  data;
{
{
ASM_START
ASM_START
  push bp
  push bp
  mov  bp, sp
  mov  bp, sp
 
 
    push ax
    push ax
    push bx
    push bx
    push ds
    push ds
    mov  ax, 4[bp] ; segment
    mov  ax, 4[bp] ; segment
    mov  ds, ax
    mov  ds, ax
    mov  bx, 6[bp] ; offset
    mov  bx, 6[bp] ; offset
    mov  al, 8[bp] ; data byte
    mov  al, 8[bp] ; data byte
    mov  [bx], al  ; write data byte
    mov  [bx], al  ; write data byte
    pop  ds
    pop  ds
    pop  bx
    pop  bx
    pop  ax
    pop  ax
 
 
  pop  bp
  pop  bp
ASM_END
ASM_END
}
}
 
 
// --------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------
static void
static void
write_word(seg, offset, data)
write_word(seg, offset, data)
  Bit16u seg;
  Bit16u seg;
  Bit16u offset;
  Bit16u offset;
  Bit16u data;
  Bit16u data;
{
{
ASM_START
ASM_START
  push bp
  push bp
  mov  bp, sp
  mov  bp, sp
 
 
    push ax
    push ax
    push bx
    push bx
    push ds
    push ds
    mov  ax, 4[bp] ; segment
    mov  ax, 4[bp] ; segment
    mov  ds, ax
    mov  ds, ax
    mov  bx, 6[bp] ; offset
    mov  bx, 6[bp] ; offset
    mov  ax, 8[bp] ; data word
    mov  ax, 8[bp] ; data word
    mov  [bx], ax  ; write data word
    mov  [bx], ax  ; write data word
    pop  ds
    pop  ds
    pop  bx
    pop  bx
    pop  ax
    pop  ax
 
 
  pop  bp
  pop  bp
ASM_END
ASM_END
}
}
 
 
// --------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------
 Bit8u
 Bit8u
inb(port)
inb(port)
  Bit16u port;
  Bit16u port;
{
{
ASM_START
ASM_START
  push bp
  push bp
  mov  bp, sp
  mov  bp, sp
 
 
    push dx
    push dx
    mov  dx, 4[bp]
    mov  dx, 4[bp]
    in   al, dx
    in   al, dx
    pop  dx
    pop  dx
 
 
  pop  bp
  pop  bp
ASM_END
ASM_END
}
}
 
 
  Bit16u
  Bit16u
inw(port)
inw(port)
  Bit16u port;
  Bit16u port;
{
{
ASM_START
ASM_START
  push bp
  push bp
  mov  bp, sp
  mov  bp, sp
 
 
    push dx
    push dx
    mov  dx, 4[bp]
    mov  dx, 4[bp]
    in   ax, dx
    in   ax, dx
    pop  dx
    pop  dx
 
 
  pop  bp
  pop  bp
ASM_END
ASM_END
}
}
 
 
// --------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------
  void
  void
outb(port, val)
outb(port, val)
  Bit16u port;
  Bit16u port;
  Bit8u  val;
  Bit8u  val;
{
{
ASM_START
ASM_START
  push bp
  push bp
  mov  bp, sp
  mov  bp, sp
 
 
    push ax
    push ax
    push dx
    push dx
    mov  dx, 4[bp]
    mov  dx, 4[bp]
    mov  al, 6[bp]
    mov  al, 6[bp]
    out  dx, al
    out  dx, al
    pop  dx
    pop  dx
    pop  ax
    pop  ax
 
 
  pop  bp
  pop  bp
ASM_END
ASM_END
}
}
 
 
// --------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------
  void
  void
outw(port, val)
outw(port, val)
  Bit16u port;
  Bit16u port;
  Bit16u  val;
  Bit16u  val;
{
{
ASM_START
ASM_START
  push bp
  push bp
  mov  bp, sp
  mov  bp, sp
 
 
    push ax
    push ax
    push dx
    push dx
    mov  dx, 4[bp]
    mov  dx, 4[bp]
    mov  ax, 6[bp]
    mov  ax, 6[bp]
    out  dx, ax
    out  dx, ax
    pop  dx
    pop  dx
    pop  ax
    pop  ax
 
 
  pop  bp
  pop  bp
ASM_END
ASM_END
}
}
 
 
Bit16u get_SS()
Bit16u get_SS()
{
{
ASM_START
ASM_START
  mov  ax, ss
  mov  ax, ss
ASM_END
ASM_END
}
}
 
 
void printf(s)
void printf(s)
  Bit8u *s;
  Bit8u *s;
{
{
  Bit8u c, format_char;
  Bit8u c, format_char;
  Boolean  in_format;
  Boolean  in_format;
  unsigned format_width, i;
  unsigned format_width, i;
  Bit16u  *arg_ptr;
  Bit16u  *arg_ptr;
  Bit16u   arg_seg, arg, digit, nibble, shift_count;
  Bit16u   arg_seg, arg, digit, nibble, shift_count;
 
 
  arg_ptr = &s;
  arg_ptr = &s;
  arg_seg = get_SS();
  arg_seg = get_SS();
 
 
  in_format = 0;
  in_format = 0;
  format_width = 0;
  format_width = 0;
 
 
  while (c = read_byte(0xc000, s)) {
  while (c = read_byte(0xc000, s)) {
    if ( c == '%' ) {
    if ( c == '%' ) {
      in_format = 1;
      in_format = 1;
      format_width = 0;
      format_width = 0;
      }
      }
    else if (in_format) {
    else if (in_format) {
      if ( (c>='0') && (c<='9') ) {
      if ( (c>='0') && (c<='9') ) {
        format_width = (format_width * 10) + (c - '0');
        format_width = (format_width * 10) + (c - '0');
        }
        }
      else if (c == 'x') {
      else if (c == 'x') {
        arg_ptr++; // increment to next arg
        arg_ptr++; // increment to next arg
        arg = read_word(arg_seg, arg_ptr);
        arg = read_word(arg_seg, arg_ptr);
        if (format_width == 0)
        if (format_width == 0)
          format_width = 4;
          format_width = 4;
        i = 0;
        i = 0;
        digit = format_width - 1;
        digit = format_width - 1;
        for (i=0; i<format_width; i++) {
        for (i=0; i<format_width; i++) {
          nibble = (arg >> (4 * digit)) & 0x000f;
          nibble = (arg >> (4 * digit)) & 0x000f;
          if (nibble <= 9)
          if (nibble <= 9)
            outb(0x0500, nibble + '0');
            outb(0x0500, nibble + '0');
          else
          else
            outb(0x0500, (nibble - 10) + 'A');
            outb(0x0500, (nibble - 10) + 'A');
          digit--;
          digit--;
          }
          }
        in_format = 0;
        in_format = 0;
        }
        }
      //else if (c == 'd') {
      //else if (c == 'd') {
      //  in_format = 0;
      //  in_format = 0;
      //  }
      //  }
      }
      }
    else {
    else {
      outb(0x0500, c);
      outb(0x0500, c);
      }
      }
    s ++;
    s ++;
    }
    }
}
}
 
 
// --------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------
 
 
ASM_START
ASM_START
;; DATA_SEG_DEFS_HERE
;; DATA_SEG_DEFS_HERE
ASM_END
ASM_END
 
 
ASM_START
ASM_START
.ascii "vgabios ends here"
.ascii "vgabios ends here"
.byte  0x00
.byte  0x00
vgabios_end:
vgabios_end:
.byte 0xCB
.byte 0xCB
;; BLOCK_STRINGS_BEGIN
;; BLOCK_STRINGS_BEGIN
ASM_END
ASM_END
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.