Annotation of qemu/roms/vgabios/vgabios.c, revision 1.1.1.2

1.1       root        1: // ============================================================================================
                      2: /*
                      3:  * vgabios.c
                      4:  */
                      5: // ============================================================================================
                      6: //  
                      7: //  Copyright (C) 2001-2008 the LGPL VGABios developers Team
                      8: //
                      9: //  This library is free software; you can redistribute it and/or
                     10: //  modify it under the terms of the GNU Lesser General Public
                     11: //  License as published by the Free Software Foundation; either
                     12: //  version 2 of the License, or (at your option) any later version.
                     13: //
                     14: //  This library is distributed in the hope that it will be useful,
                     15: //  but WITHOUT ANY WARRANTY; without even the implied warranty of
                     16: //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     17: //  Lesser General Public License for more details.
                     18: //
                     19: //  You should have received a copy of the GNU Lesser General Public
                     20: //  License along with this library; if not, write to the Free Software
                     21: //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
                     22: // 
                     23: // ============================================================================================
                     24: //  
                     25: //  This VGA Bios is specific to the plex86/bochs Emulated VGA card. 
                     26: //  You can NOT drive any physical vga card with it. 
                     27: //     
                     28: // ============================================================================================
                     29: //  
                     30: //  This file contains code ripped from :
                     31: //   - rombios.c of plex86 
                     32: //
                     33: //  This VGA Bios contains fonts from :
                     34: //   - fntcol16.zip (c) by Joseph Gil avalable at :
                     35: //      ftp://ftp.simtel.net/pub/simtelnet/msdos/screen/fntcol16.zip
                     36: //     These fonts are public domain 
                     37: //
                     38: //  This VGA Bios is based on information taken from :
                     39: //   - Kevin Lawton's vga card emulation for bochs/plex86
                     40: //   - Ralf Brown's interrupts list available at http://www.cs.cmu.edu/afs/cs/user/ralf/pub/WWW/files.html
                     41: //   - Finn Thogersons' VGADOC4b available at http://home.worldonline.dk/~finth/
                     42: //   - Michael Abrash's Graphics Programming Black Book
                     43: //   - Francois Gervais' book "programmation des cartes graphiques cga-ega-vga" edited by sybex
                     44: //   - DOSEMU 1.0.1 source code for several tables values and formulas
                     45: //
                     46: // Thanks for patches, comments and ideas to :
                     47: //   - [email protected]
                     48: //
                     49: // ============================================================================================
                     50: 
                     51: #include "vgabios.h"
                     52: 
                     53: #ifdef VBE
                     54: #include "vbe.h"
                     55: #endif
                     56: 
                     57: #define USE_BX_INFO
                     58: 
                     59: /* Declares */
                     60: static Bit8u          read_byte();
                     61: static Bit16u         read_word();
                     62: static void           write_byte();
                     63: static void           write_word();
                     64: static Bit8u          inb();
                     65: static Bit16u         inw();
                     66: static void           outb();
                     67: static void           outw();
                     68: 
                     69: static Bit16u         get_SS();
                     70: 
                     71: // Output
                     72: static void           printf();
                     73: static void           unimplemented();
                     74: static void           unknown();
                     75: 
                     76: static Bit8u find_vga_entry();
                     77: 
                     78: static void memsetb();
                     79: static void memsetw();
                     80: static void memcpyb();
                     81: static void memcpyw();
                     82: 
                     83: static void biosfn_set_video_mode();
                     84: static void biosfn_set_cursor_shape();
                     85: static void biosfn_set_cursor_pos();
                     86: static void biosfn_get_cursor_pos();
                     87: static void biosfn_set_active_page();
                     88: static void biosfn_scroll();
                     89: static void biosfn_read_char_attr();
                     90: static void biosfn_write_char_attr();
                     91: static void biosfn_write_char_only();
                     92: static void biosfn_write_pixel();
                     93: static void biosfn_read_pixel();
                     94: static void biosfn_write_teletype();
                     95: static void biosfn_perform_gray_scale_summing();
                     96: static void biosfn_load_text_user_pat();
                     97: static void biosfn_load_text_8_14_pat();
                     98: static void biosfn_load_text_8_8_pat();
                     99: static void biosfn_load_text_8_16_pat();
                    100: static void biosfn_load_gfx_8_8_chars();
                    101: static void biosfn_load_gfx_user_chars();
                    102: static void biosfn_load_gfx_8_14_chars();
                    103: static void biosfn_load_gfx_8_8_dd_chars();
                    104: static void biosfn_load_gfx_8_16_chars();
                    105: static void biosfn_get_font_info();
                    106: static void biosfn_alternate_prtsc();
                    107: static void biosfn_switch_video_interface();
                    108: static void biosfn_enable_video_refresh_control();
                    109: static void biosfn_write_string();
                    110: static void biosfn_read_state_info();
                    111: static void biosfn_read_video_state_size();
                    112: static Bit16u biosfn_save_video_state();
                    113: static Bit16u biosfn_restore_video_state();
                    114: extern Bit8u video_save_pointer_table[];
                    115: 
                    116: // This is for compiling with gcc2 and gcc3
                    117: #define ASM_START #asm
                    118: #define ASM_END   #endasm
                    119: 
                    120: ASM_START
                    121: 
                    122: MACRO SET_INT_VECTOR
                    123:   push ds
                    124:   xor ax, ax
                    125:   mov ds, ax
                    126:   mov ax, ?3
                    127:   mov ?1*4, ax
                    128:   mov ax, ?2
                    129:   mov ?1*4+2, ax
                    130:   pop ds
                    131: MEND
                    132: 
                    133: ASM_END
                    134: 
                    135: ASM_START
                    136: .text
                    137: .rom
                    138: .org 0
                    139: 
                    140: use16 386
                    141: 
                    142: vgabios_start:
                    143: .byte  0x55, 0xaa      /* BIOS signature, required for BIOS extensions */
                    144: 
                    145: .byte  0x40            /* BIOS extension length in units of 512 bytes */
                    146: 
                    147: 
                    148: vgabios_entry_point:
                    149:            
                    150:   jmp vgabios_init_func
                    151: 
                    152: #ifdef PCIBIOS
                    153: .org 0x18
                    154: .word vgabios_pci_data
                    155: #endif
                    156: 
                    157: // Info from Bart Oldeman
                    158: .org 0x1e
                    159: .ascii  "IBM"
                    160: .byte   0x00
                    161: 
                    162: vgabios_name:
                    163: .ascii "Plex86/Bochs VGABios"
                    164: #ifdef PCIBIOS
                    165: .ascii " (PCI)"
                    166: #endif
                    167: .ascii " "
                    168: .byte  0x00
                    169: 
                    170: vgabios_version:
                    171: #ifndef VGABIOS_VERS
                    172: .ascii "current-cvs"
                    173: #else
                    174: .ascii VGABIOS_VERS
                    175: #endif
                    176: .ascii " "
                    177: 
                    178: vgabios_date:
                    179: .ascii  VGABIOS_DATE
                    180: .byte   0x0a,0x0d
                    181: .byte  0x00
                    182: 
                    183: vgabios_copyright:
                    184: .ascii "(C) 2008 the LGPL VGABios developers Team"
                    185: .byte  0x0a,0x0d
                    186: .byte  0x00
                    187: 
                    188: vgabios_license:
                    189: .ascii "This VGA/VBE Bios is released under the GNU LGPL"
                    190: .byte  0x0a,0x0d
                    191: .byte  0x0a,0x0d
                    192: .byte  0x00
                    193: 
                    194: vgabios_website:
                    195: .ascii "Please visit :"
                    196: .byte  0x0a,0x0d
                    197: ;;.ascii  " . http://www.plex86.org"
                    198: ;;.byte        0x0a,0x0d
                    199: .ascii " . http://bochs.sourceforge.net"
                    200: .byte  0x0a,0x0d
                    201: .ascii " . http://www.nongnu.org/vgabios"
                    202: .byte  0x0a,0x0d
                    203: .byte  0x0a,0x0d
                    204: .byte  0x00
                    205: 
                    206: #ifdef PCIBIOS
                    207: vgabios_pci_data:
                    208: .ascii "PCIR"
                    209: #ifdef CIRRUS
                    210: .word 0x1013
                    211: .word 0x00b8 // CLGD5446
                    212: #else
1.1.1.2 ! root      213: #ifdef PCI_VID
        !           214: .word PCI_VID
        !           215: .word PCI_DID
        !           216: #else
1.1       root      217: #error "Unknown PCI vendor and device id"
                    218: #endif
1.1.1.2 ! root      219: #endif
1.1       root      220: .word 0 // reserved
                    221: .word 0x18 // dlen
                    222: .byte 0 // revision
                    223: .byte 0x0 // class,hi: vga display
                    224: .word 0x300 // class,lo: vga display
                    225: .word 0x40 // bios size
                    226: .word 1 // revision
                    227: .byte 0 // intel x86 data
                    228: .byte 0x80 // last image
                    229: .word 0 // reserved
                    230: #endif
                    231: 
                    232: 
                    233: ;; ============================================================================================
                    234: ;;
                    235: ;; Init Entry point
                    236: ;;
                    237: ;; ============================================================================================
                    238: vgabios_init_func:
                    239: 
                    240: ;; init vga card
                    241:   call init_vga_card
                    242: 
                    243: ;; init basic bios vars
                    244:   call init_bios_area
                    245: 
                    246: #ifdef VBE  
                    247: ;; init vbe functions
                    248:   call vbe_init  
                    249: #endif
                    250: 
                    251: ;; set int10 vect
                    252:   SET_INT_VECTOR(0x10, #0xC000, #vgabios_int10_handler)
                    253: 
                    254: #ifdef CIRRUS
                    255:   call cirrus_init
                    256: #endif
                    257: 
                    258: ;; display splash screen
                    259:   call _display_splash_screen
                    260: 
                    261: ;; init video mode and clear the screen
                    262:   mov ax,#0x0003
                    263:   int #0x10
                    264: 
                    265: ;; show info
                    266:   call _display_info
                    267: 
                    268: #ifdef VBE  
                    269: ;; show vbe info
                    270:   call vbe_display_info  
                    271: #endif
                    272: 
                    273: #ifdef CIRRUS
                    274: ;; show cirrus info
                    275:   call cirrus_display_info
                    276: #endif
                    277: 
                    278:   retf
                    279: ASM_END
                    280: 
                    281: /*
                    282:  *  int10 handled here
                    283:  */
                    284: ASM_START
                    285: vgabios_int10_handler:
                    286:   pushf
                    287: #ifdef DEBUG
                    288:   push es
                    289:   push ds
                    290:   pusha
                    291:   mov   bx, #0xc000
                    292:   mov   ds, bx
                    293:   call _int10_debugmsg
                    294:   popa
                    295:   pop ds
                    296:   pop es
                    297: #endif
                    298:   cmp   ah, #0x0f
                    299:   jne   int10_test_1A
                    300:   call  biosfn_get_video_mode
                    301:   jmp   int10_end
                    302: int10_test_1A:
                    303:   cmp   ah, #0x1a
                    304:   jne   int10_test_0B
                    305:   call  biosfn_group_1A
                    306:   jmp   int10_end
                    307: int10_test_0B:
                    308:   cmp   ah, #0x0b
                    309:   jne   int10_test_1103
                    310:   call  biosfn_group_0B
                    311:   jmp   int10_end
                    312: int10_test_1103:
                    313:   cmp   ax, #0x1103
                    314:   jne   int10_test_12
                    315:   call  biosfn_set_text_block_specifier
                    316:   jmp   int10_end
                    317: int10_test_12:
                    318:   cmp   ah, #0x12
                    319:   jne   int10_test_101B
                    320:   cmp   bl, #0x10
                    321:   jne   int10_test_BL30
                    322:   call  biosfn_get_ega_info
                    323:   jmp   int10_end
                    324: int10_test_BL30:
                    325:   cmp   bl, #0x30
                    326:   jne   int10_test_BL31
                    327:   call  biosfn_select_vert_res
                    328:   jmp   int10_end
                    329: int10_test_BL31:
                    330:   cmp   bl, #0x31
                    331:   jne   int10_test_BL32
                    332:   call  biosfn_enable_default_palette_loading
                    333:   jmp   int10_end
                    334: int10_test_BL32:
                    335:   cmp   bl, #0x32
                    336:   jne   int10_test_BL33
                    337:   call  biosfn_enable_video_addressing
                    338:   jmp   int10_end
                    339: int10_test_BL33:
                    340:   cmp   bl, #0x33
                    341:   jne   int10_test_BL34
                    342:   call  biosfn_enable_grayscale_summing
                    343:   jmp   int10_end
                    344: int10_test_BL34:
                    345:   cmp   bl, #0x34
                    346:   jne   int10_normal
                    347:   call  biosfn_enable_cursor_emulation
                    348:   jmp   int10_end
                    349: int10_test_101B:
                    350:   cmp   ax, #0x101b
                    351:   je    int10_normal
                    352:   cmp   ah, #0x10
                    353: #ifndef VBE
                    354:   jne   int10_normal
                    355: #else
                    356:   jne   int10_test_4F
                    357: #endif
                    358:   call  biosfn_group_10
                    359:   jmp   int10_end
                    360: #ifdef VBE
                    361: int10_test_4F:
                    362:   cmp   ah, #0x4f
                    363:   jne   int10_normal
                    364:   cmp   al, #0x03
                    365:   jne   int10_test_vbe_05
                    366:   call  vbe_biosfn_return_current_mode
                    367:   jmp   int10_end
                    368: int10_test_vbe_05:
                    369:   cmp   al, #0x05
                    370:   jne   int10_test_vbe_06
                    371:   call  vbe_biosfn_display_window_control
                    372:   jmp   int10_end
                    373: int10_test_vbe_06:
                    374:   cmp   al, #0x06
                    375:   jne   int10_test_vbe_07
                    376:   call  vbe_biosfn_set_get_logical_scan_line_length
                    377:   jmp   int10_end
                    378: int10_test_vbe_07:
                    379:   cmp   al, #0x07
                    380:   jne   int10_test_vbe_08
                    381:   call  vbe_biosfn_set_get_display_start
                    382:   jmp   int10_end
                    383: int10_test_vbe_08:
                    384:   cmp   al, #0x08
                    385:   jne   int10_test_vbe_0A
                    386:   call  vbe_biosfn_set_get_dac_palette_format
                    387:   jmp   int10_end
                    388: int10_test_vbe_0A:
                    389:   cmp   al, #0x0A
                    390:   jne   int10_normal
                    391:   call  vbe_biosfn_return_protected_mode_interface
                    392:   jmp   int10_end
                    393: #endif
                    394: 
                    395: int10_normal:
                    396:   push es
                    397:   push ds
                    398:   pusha
                    399: 
                    400: ;; We have to set ds to access the right data segment
                    401:   mov   bx, #0xc000
                    402:   mov   ds, bx
                    403:   call _int10_func
                    404: 
                    405:   popa
                    406:   pop ds
                    407:   pop es
                    408: int10_end:
                    409:   popf
                    410:   iret
                    411: ASM_END
                    412: 
                    413: #include "vgatables.h"
                    414: #include "vgafonts.h"
                    415: 
                    416: /*
                    417:  * Boot time harware inits 
                    418:  */
                    419: ASM_START
                    420: init_vga_card:
                    421: ;; switch to color mode and enable CPU access 480 lines
                    422:   mov dx, #0x3C2
                    423:   mov al, #0xC3
                    424:   outb dx,al
                    425: 
                    426: ;; more than 64k 3C4/04
                    427:   mov dx, #0x3C4
                    428:   mov al, #0x04
                    429:   outb dx,al
                    430:   mov dx, #0x3C5
                    431:   mov al, #0x02
                    432:   outb dx,al
                    433: 
                    434: #if defined(USE_BX_INFO) || defined(DEBUG)
                    435:   mov  bx, #msg_vga_init
                    436:   push bx
                    437:   call _printf
                    438: #endif
                    439:   inc  sp
                    440:   inc  sp
                    441:   ret
                    442: 
                    443: #if defined(USE_BX_INFO) || defined(DEBUG)
                    444: msg_vga_init:
                    445: .ascii "VGABios $Id$"
                    446: .byte 0x0d,0x0a,0x00
                    447: #endif
                    448: ASM_END
                    449: 
                    450: // --------------------------------------------------------------------------------------------
                    451: /*
                    452:  *  Boot time bios area inits 
                    453:  */
                    454: ASM_START
                    455: init_bios_area:
                    456:   push  ds
                    457:   mov   ax, # BIOSMEM_SEG
                    458:   mov   ds, ax
                    459: 
                    460: ;; init detected hardware BIOS Area
                    461:   mov   bx, # BIOSMEM_INITIAL_MODE
                    462:   mov   ax, [bx]
                    463:   and   ax, #0xffcf
                    464: ;; set 80x25 color (not clear from RBIL but usual)
                    465:   or    ax, #0x0020
                    466:   mov   [bx], ax
                    467: 
                    468: ;; Just for the first int10 find its children
                    469: 
                    470: ;; the default char height
                    471:   mov   bx, # BIOSMEM_CHAR_HEIGHT
                    472:   mov   al, #0x10
                    473:   mov   [bx], al
                    474: 
                    475: ;; Clear the screen 
                    476:   mov   bx, # BIOSMEM_VIDEO_CTL
                    477:   mov   al, #0x60
                    478:   mov   [bx], al
                    479: 
                    480: ;; Set the basic screen we have
                    481:   mov   bx, # BIOSMEM_SWITCHES
                    482:   mov   al, #0xf9
                    483:   mov   [bx], al
                    484: 
                    485: ;; Set the basic modeset options
                    486:   mov   bx, # BIOSMEM_MODESET_CTL
                    487:   mov   al, #0x51
                    488:   mov   [bx], al
                    489: 
                    490: ;; Set the  default MSR
                    491:   mov   bx, # BIOSMEM_CURRENT_MSR
                    492:   mov   al, #0x09
                    493:   mov   [bx], al
                    494: 
                    495:   pop ds
                    496:   ret
                    497: 
                    498: _video_save_pointer_table:
                    499:   .word _video_param_table
                    500:   .word 0xc000
                    501: 
                    502:   .word 0 /* XXX: fill it */
                    503:   .word 0
                    504: 
                    505:   .word 0 /* XXX: fill it */
                    506:   .word 0
                    507: 
                    508:   .word 0 /* XXX: fill it */
                    509:   .word 0
                    510: 
                    511:   .word 0 /* XXX: fill it */
                    512:   .word 0
                    513: 
                    514:   .word 0 /* XXX: fill it */
                    515:   .word 0
                    516: 
                    517:   .word 0 /* XXX: fill it */
                    518:   .word 0
                    519: 
                    520: ASM_END
                    521: 
                    522: // --------------------------------------------------------------------------------------------
                    523: /*
                    524:  *  Boot time Splash screen
                    525:  */
                    526: static void display_splash_screen()
                    527: {
                    528: }
                    529: 
                    530: // --------------------------------------------------------------------------------------------
                    531: /*
                    532:  *  Tell who we are
                    533:  */
                    534: 
                    535: static void display_info()
                    536: {
                    537: ASM_START
                    538:  mov ax,#0xc000
                    539:  mov ds,ax
                    540:  mov si,#vgabios_name
                    541:  call _display_string
                    542:  mov si,#vgabios_version
                    543:  call _display_string
                    544:  
                    545:  ;;mov si,#vgabios_copyright
                    546:  ;;call _display_string
                    547:  ;;mov si,#crlf
                    548:  ;;call _display_string
                    549: 
                    550:  mov si,#vgabios_license
                    551:  call _display_string
                    552:  mov si,#vgabios_website
                    553:  call _display_string
                    554: ASM_END
                    555: }
                    556: 
                    557: static void display_string()
                    558: {
                    559:  // Get length of string
                    560: ASM_START
                    561:  mov ax,ds
                    562:  mov es,ax
                    563:  mov di,si
                    564:  xor cx,cx
                    565:  not cx
                    566:  xor al,al
                    567:  cld
                    568:  repne 
                    569:   scasb
                    570:  not cx
                    571:  dec cx
                    572:  push cx
                    573: 
                    574:  mov ax,#0x0300
                    575:  mov bx,#0x0000
                    576:  int #0x10
                    577:  
                    578:  pop cx
                    579:  mov ax,#0x1301
                    580:  mov bx,#0x000b
                    581:  mov bp,si
                    582:  int #0x10
                    583: ASM_END
                    584: }
                    585: 
                    586: // --------------------------------------------------------------------------------------------
                    587: #ifdef DEBUG
                    588: static void int10_debugmsg(DI, SI, BP, SP, BX, DX, CX, AX, DS, ES, FLAGS)
                    589:   Bit16u DI, SI, BP, SP, BX, DX, CX, AX, ES, DS, FLAGS;
                    590: {
                    591:  // 0E is write char...
                    592:  if(GET_AH()!=0x0E)
                    593:   printf("vgabios call ah%02x al%02x bx%04x cx%04x dx%04x\n",GET_AH(),GET_AL(),BX,CX,DX);
                    594: }
                    595: #endif
                    596: 
                    597: // --------------------------------------------------------------------------------------------
                    598: /*
                    599:  * int10 main dispatcher
                    600:  */
                    601: static void int10_func(DI, SI, BP, SP, BX, DX, CX, AX, DS, ES, FLAGS)
                    602:   Bit16u DI, SI, BP, SP, BX, DX, CX, AX, ES, DS, FLAGS;
                    603: {
                    604: 
                    605:  // BIOS functions
                    606:  switch(GET_AH())
                    607:   {
                    608:    case 0x00:
                    609:      biosfn_set_video_mode(GET_AL());
                    610:      switch(GET_AL()&0x7F)
                    611:       {case 6: 
                    612:         SET_AL(0x3F);
                    613:         break;
                    614:        case 0:
                    615:        case 1:
                    616:        case 2:
                    617:        case 3:
                    618:        case 4:
                    619:        case 5:
                    620:        case 7:
                    621:         SET_AL(0x30);
                    622:         break;
                    623:       default:
                    624:         SET_AL(0x20);
                    625:       }
                    626:      break;
                    627:    case 0x01:
                    628:      biosfn_set_cursor_shape(GET_CH(),GET_CL());
                    629:      break;
                    630:    case 0x02:
                    631:      biosfn_set_cursor_pos(GET_BH(),DX);
                    632:      break;
                    633:    case 0x03:
                    634:      biosfn_get_cursor_pos(GET_BH(),&CX,&DX);
                    635:      break;
                    636:    case 0x04:
                    637:      // Read light pen pos (unimplemented)
                    638: #ifdef DEBUG
                    639:      unimplemented();
                    640: #endif
                    641:      AX=0x00;
                    642:      BX=0x00;
                    643:      CX=0x00;
                    644:      DX=0x00;
                    645:      break;
                    646:    case 0x05:
                    647:      biosfn_set_active_page(GET_AL());
                    648:      break;
                    649:    case 0x06:
                    650:      biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_UP);
                    651:      break;
                    652:    case 0x07:
                    653:      biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_DOWN);
                    654:      break;
                    655:    case 0x08:
                    656:      biosfn_read_char_attr(GET_BH(),&AX);
                    657:      break;
                    658:    case 0x09:
                    659:      biosfn_write_char_attr(GET_AL(),GET_BH(),GET_BL(),CX);
                    660:      break;
                    661:    case 0x0A:
                    662:      biosfn_write_char_only(GET_AL(),GET_BH(),GET_BL(),CX);
                    663:      break;
                    664:    case 0x0C:
                    665:      biosfn_write_pixel(GET_BH(),GET_AL(),CX,DX);
                    666:      break;
                    667:    case 0x0D:
                    668:      biosfn_read_pixel(GET_BH(),CX,DX,&AX);
                    669:      break;
                    670:    case 0x0E:
                    671:      // Ralf Brown Interrupt list is WRONG on bh(page)
                    672:      // We do output only on the current page !
                    673:      biosfn_write_teletype(GET_AL(),0xff,GET_BL(),NO_ATTR);
                    674:      break;
                    675:    case 0x10:
                    676:      // All other functions of group AH=0x10 rewritten in assembler
                    677:      biosfn_perform_gray_scale_summing(BX,CX);
                    678:      break;
                    679:    case 0x11:
                    680:      switch(GET_AL())
                    681:       {
                    682:        case 0x00:
                    683:        case 0x10:
                    684:         biosfn_load_text_user_pat(GET_AL(),ES,BP,CX,DX,GET_BL(),GET_BH());
                    685:         break;
                    686:        case 0x01:
                    687:        case 0x11:
                    688:         biosfn_load_text_8_14_pat(GET_AL(),GET_BL());
                    689:         break;
                    690:        case 0x02:
                    691:        case 0x12:
                    692:         biosfn_load_text_8_8_pat(GET_AL(),GET_BL());
                    693:         break;
                    694:        case 0x04:
                    695:        case 0x14:
                    696:         biosfn_load_text_8_16_pat(GET_AL(),GET_BL());
                    697:         break;
                    698:        case 0x20:
                    699:         biosfn_load_gfx_8_8_chars(ES,BP);
                    700:         break;
                    701:        case 0x21:
                    702:         biosfn_load_gfx_user_chars(ES,BP,CX,GET_BL(),GET_DL());
                    703:         break;
                    704:        case 0x22:
                    705:         biosfn_load_gfx_8_14_chars(GET_BL());
                    706:         break;
                    707:        case 0x23:
                    708:         biosfn_load_gfx_8_8_dd_chars(GET_BL());
                    709:         break;
                    710:        case 0x24:
                    711:         biosfn_load_gfx_8_16_chars(GET_BL());
                    712:         break;
                    713:        case 0x30:
                    714:         biosfn_get_font_info(GET_BH(),&ES,&BP,&CX,&DX);
                    715:         break;
                    716: #ifdef DEBUG
                    717:        default:
                    718:         unknown();
                    719: #endif
                    720:       }
                    721:      
                    722:      break;
                    723:    case 0x12:
                    724:      switch(GET_BL())
                    725:       {
                    726:        case 0x20:
                    727:         biosfn_alternate_prtsc();
                    728:         break;
                    729:        case 0x35:
                    730:         biosfn_switch_video_interface(GET_AL(),ES,DX);
                    731:         SET_AL(0x12);
                    732:         break;
                    733:        case 0x36:
                    734:         biosfn_enable_video_refresh_control(GET_AL());
                    735:         SET_AL(0x12);
                    736:         break;
                    737: #ifdef DEBUG
                    738:        default:
                    739:         unknown();
                    740: #endif
                    741:       }
                    742:      break;
                    743:    case 0x13:
                    744:      biosfn_write_string(GET_AL(),GET_BH(),GET_BL(),CX,GET_DH(),GET_DL(),ES,BP);
                    745:      break;
                    746:    case 0x1B:
                    747:      biosfn_read_state_info(BX,ES,DI);
                    748:      SET_AL(0x1B);
                    749:      break;
                    750:    case 0x1C:
                    751:      switch(GET_AL())
                    752:       {
                    753:        case 0x00:
                    754:         biosfn_read_video_state_size(CX,&BX);
                    755:         break;
                    756:        case 0x01:
                    757:         biosfn_save_video_state(CX,ES,BX);
                    758:         break;
                    759:        case 0x02:
                    760:         biosfn_restore_video_state(CX,ES,BX);
                    761:         break;
                    762: #ifdef DEBUG
                    763:        default:
                    764:         unknown();
                    765: #endif
                    766:       }
                    767:      SET_AL(0x1C);
                    768:      break;
                    769: 
                    770: #ifdef VBE 
                    771:    case 0x4f:
                    772:      if (vbe_has_vbe_display()) {
                    773:        switch(GET_AL())
                    774:        {
                    775:          case 0x00:
                    776:           vbe_biosfn_return_controller_information(&AX,ES,DI);
                    777:           break;
                    778:          case 0x01:
                    779:           vbe_biosfn_return_mode_information(&AX,CX,ES,DI);
                    780:           break;
                    781:          case 0x02:
                    782:           vbe_biosfn_set_mode(&AX,BX,ES,DI);
                    783:           break;
                    784:          case 0x04:
                    785:           vbe_biosfn_save_restore_state(&AX, CX, DX, ES, &BX);
                    786:           break;
                    787:          case 0x09:
                    788:           //FIXME
                    789: #ifdef DEBUG
                    790:           unimplemented();
                    791: #endif
                    792:           // function failed
                    793:           AX=0x100;
                    794:           break;
                    795:          case 0x0A:
                    796:           //FIXME
                    797: #ifdef DEBUG
                    798:           unimplemented();
                    799: #endif
                    800:           // function failed
                    801:           AX=0x100;
                    802:           break;
                    803:          default:
                    804: #ifdef DEBUG
                    805:           unknown();
                    806: #endif                  
                    807:           // function failed
                    808:           AX=0x100;
                    809:           }
                    810:         }
                    811:         else {
                    812:           // No VBE display
                    813:           AX=0x0100;
                    814:           }
                    815:         break;
                    816: #endif
                    817: 
                    818: #ifdef DEBUG
                    819:    default:
                    820:      unknown();
                    821: #endif
                    822:   }
                    823: }
                    824: 
                    825: // ============================================================================================
                    826: // 
                    827: // BIOS functions
                    828: // 
                    829: // ============================================================================================
                    830: 
                    831: static void biosfn_set_video_mode(mode) Bit8u mode; 
                    832: {// mode: Bit 7 is 1 if no clear screen
                    833: 
                    834:  // Should we clear the screen ?
                    835:  Bit8u noclearmem=mode&0x80;
                    836:  Bit8u line,mmask,*palette,vpti;
                    837:  Bit16u i,twidth,theightm1,cheight;
                    838:  Bit8u modeset_ctl,video_ctl,vga_switches;
                    839:  Bit16u crtc_addr;
                    840:  
                    841: #ifdef VBE
                    842:  if (vbe_has_vbe_display()) { 
                    843:    dispi_set_enable(VBE_DISPI_DISABLED);
                    844:   }
                    845: #endif // def VBE
                    846:  
                    847:  // The real mode
                    848:  mode=mode&0x7f;
                    849: 
                    850:  // find the entry in the video modes
                    851:  line=find_vga_entry(mode);
                    852: 
                    853: #ifdef DEBUG
                    854:  printf("mode search %02x found line %02x\n",mode,line);
                    855: #endif
                    856: 
                    857:  if(line==0xFF)
                    858:   return;
                    859: 
                    860:  vpti=line_to_vpti[line];
                    861:  twidth=video_param_table[vpti].twidth;
                    862:  theightm1=video_param_table[vpti].theightm1;
                    863:  cheight=video_param_table[vpti].cheight;
                    864:  
                    865:  // Read the bios vga control
                    866:  video_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL);
                    867: 
                    868:  // Read the bios vga switches
                    869:  vga_switches=read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES);
                    870: 
                    871:  // Read the bios mode set control
                    872:  modeset_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
                    873: 
                    874:  // Then we know the number of lines
                    875: // FIXME
                    876: 
                    877:  // if palette loading (bit 3 of modeset ctl = 0)
                    878:  if((modeset_ctl&0x08)==0)
                    879:   {// Set the PEL mask
                    880:    outb(VGAREG_PEL_MASK,vga_modes[line].pelmask);
                    881: 
                    882:    // Set the whole dac always, from 0
                    883:    outb(VGAREG_DAC_WRITE_ADDRESS,0x00);
                    884: 
                    885:    // From which palette
                    886:    switch(vga_modes[line].dacmodel)
                    887:     {case 0:
                    888:       palette=&palette0;
                    889:       break;
                    890:      case 1:
                    891:       palette=&palette1;
                    892:       break;
                    893:      case 2:
                    894:       palette=&palette2;
                    895:       break;
                    896:      case 3:
                    897:       palette=&palette3;
                    898:       break;
                    899:     }
                    900:    // Always 256*3 values
                    901:    for(i=0;i<0x0100;i++)
                    902:     {if(i<=dac_regs[vga_modes[line].dacmodel])
                    903:       {outb(VGAREG_DAC_DATA,palette[(i*3)+0]);
                    904:        outb(VGAREG_DAC_DATA,palette[(i*3)+1]);
                    905:        outb(VGAREG_DAC_DATA,palette[(i*3)+2]);
                    906:       }
                    907:      else
                    908:       {outb(VGAREG_DAC_DATA,0);
                    909:        outb(VGAREG_DAC_DATA,0);
                    910:        outb(VGAREG_DAC_DATA,0);
                    911:       }
                    912:     }
                    913:    if((modeset_ctl&0x02)==0x02)
                    914:     {
                    915:      biosfn_perform_gray_scale_summing(0x00, 0x100);
                    916:     }
                    917:   }
                    918: 
                    919:  // Reset Attribute Ctl flip-flop
                    920:  inb(VGAREG_ACTL_RESET);
                    921: 
                    922:  // Set Attribute Ctl
                    923:  for(i=0;i<=0x13;i++)
                    924:   {outb(VGAREG_ACTL_ADDRESS,i);
                    925:    outb(VGAREG_ACTL_WRITE_DATA,video_param_table[vpti].actl_regs[i]);
                    926:   }
                    927:  outb(VGAREG_ACTL_ADDRESS,0x14);
                    928:  outb(VGAREG_ACTL_WRITE_DATA,0x00);
                    929: 
                    930:  // Set Sequencer Ctl
                    931:  outb(VGAREG_SEQU_ADDRESS,0);
                    932:  outb(VGAREG_SEQU_DATA,0x03);
                    933:  for(i=1;i<=4;i++)
                    934:   {outb(VGAREG_SEQU_ADDRESS,i);
                    935:    outb(VGAREG_SEQU_DATA,video_param_table[vpti].sequ_regs[i - 1]);
                    936:   }
                    937: 
                    938:  // Set Grafx Ctl
                    939:  for(i=0;i<=8;i++)
                    940:   {outb(VGAREG_GRDC_ADDRESS,i);
                    941:    outb(VGAREG_GRDC_DATA,video_param_table[vpti].grdc_regs[i]);
                    942:   }
                    943: 
                    944:  // Set CRTC address VGA or MDA 
                    945:  crtc_addr=vga_modes[line].memmodel==MTEXT?VGAREG_MDA_CRTC_ADDRESS:VGAREG_VGA_CRTC_ADDRESS;
                    946: 
                    947:  // Disable CRTC write protection
                    948:  outw(crtc_addr,0x0011);
                    949:  // Set CRTC regs
                    950:  for(i=0;i<=0x18;i++)
                    951:   {outb(crtc_addr,i);
                    952:    outb(crtc_addr+1,video_param_table[vpti].crtc_regs[i]);
                    953:   }
                    954: 
                    955:  // Set the misc register
                    956:  outb(VGAREG_WRITE_MISC_OUTPUT,video_param_table[vpti].miscreg);
                    957: 
                    958:  // Enable video
                    959:  outb(VGAREG_ACTL_ADDRESS,0x20);
                    960:  inb(VGAREG_ACTL_RESET);
                    961: 
                    962:  if(noclearmem==0x00)
                    963:   {
                    964:    if(vga_modes[line].class==TEXT)
                    965:     {
                    966:      memsetw(vga_modes[line].sstart,0,0x0720,0x4000); // 32k
                    967:     }
                    968:    else
                    969:     {
                    970:      if(mode<0x0d)
                    971:       {
                    972:        memsetw(vga_modes[line].sstart,0,0x0000,0x4000); // 32k
                    973:       }
                    974:      else
                    975:       {
                    976:        outb( VGAREG_SEQU_ADDRESS, 0x02 );
                    977:        mmask = inb( VGAREG_SEQU_DATA );
                    978:        outb( VGAREG_SEQU_DATA, 0x0f ); // all planes
                    979:        memsetw(vga_modes[line].sstart,0,0x0000,0x8000); // 64k
                    980:        outb( VGAREG_SEQU_DATA, mmask );
                    981:       }
                    982:     }
                    983:   }
                    984: 
                    985:  // Set the BIOS mem
                    986:  write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE,mode);
                    987:  write_word(BIOSMEM_SEG,BIOSMEM_NB_COLS,twidth);
                    988:  write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE,*(Bit16u *)&video_param_table[vpti].slength_l);
                    989:  write_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS,crtc_addr);
                    990:  write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS,theightm1);
                    991:  write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,cheight);
                    992:  write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60|noclearmem));
                    993:  write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES,0xF9);
                    994:  write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)&0x7f);
                    995: 
                    996:  // FIXME We nearly have the good tables. to be reworked
                    997:  write_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX,0x08);    // 8 is VGA should be ok for now
                    998:  write_word(BIOSMEM_SEG,BIOSMEM_VS_POINTER, video_save_pointer_table);
                    999:  write_word(BIOSMEM_SEG,BIOSMEM_VS_POINTER+2, 0xc000);
                   1000: 
                   1001:  // FIXME
                   1002:  write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x00); // Unavailable on vanilla vga, but...
                   1003:  write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x00); // Unavailable on vanilla vga, but...
                   1004:  
                   1005:  // Set cursor shape
                   1006:  if(vga_modes[line].class==TEXT)
                   1007:   {
                   1008:    biosfn_set_cursor_shape(0x06,0x07);
                   1009:   }
                   1010: 
                   1011:  // Set cursor pos for page 0..7
                   1012:  for(i=0;i<8;i++)
                   1013:   biosfn_set_cursor_pos(i,0x0000);
                   1014: 
                   1015:  // Set active page 0
                   1016:  biosfn_set_active_page(0x00);
                   1017: 
                   1018:  // Write the fonts in memory
                   1019:  if(vga_modes[line].class==TEXT)
                   1020:   { 
                   1021: ASM_START
                   1022:   ;; copy and activate 8x16 font
                   1023:   mov ax, #0x1104
                   1024:   mov bl, #0x00
                   1025:   int #0x10
                   1026:   mov ax, #0x1103
                   1027:   mov bl, #0x00
                   1028:   int #0x10
                   1029: ASM_END
                   1030:   }
                   1031: 
                   1032:  // Set the ints 0x1F and 0x43
                   1033: ASM_START
                   1034:  SET_INT_VECTOR(0x1f, #0xC000, #_vgafont8+128*8)
                   1035: ASM_END
                   1036: 
                   1037:   switch(cheight)
                   1038:    {case 8:
                   1039: ASM_START
                   1040:      SET_INT_VECTOR(0x43, #0xC000, #_vgafont8)
                   1041: ASM_END
                   1042:      break;
                   1043:     case 14:
                   1044: ASM_START
                   1045:      SET_INT_VECTOR(0x43, #0xC000, #_vgafont14)
                   1046: ASM_END
                   1047:      break;
                   1048:     case 16:
                   1049: ASM_START
                   1050:      SET_INT_VECTOR(0x43, #0xC000, #_vgafont16)
                   1051: ASM_END
                   1052:      break;
                   1053:    }
                   1054: }
                   1055: 
                   1056: // --------------------------------------------------------------------------------------------
                   1057: static void biosfn_set_cursor_shape (CH,CL) 
                   1058: Bit8u CH;Bit8u CL; 
                   1059: {Bit16u cheight,curs,crtc_addr;
                   1060:  Bit8u modeset_ctl;
                   1061: 
                   1062:  CH&=0x3f;
                   1063:  CL&=0x1f;
                   1064: 
                   1065:  curs=(CH<<8)+CL;
                   1066:  write_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE,curs);
                   1067: 
                   1068:  modeset_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
                   1069:  cheight = read_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT);
                   1070:  if((modeset_ctl&0x01) && (cheight>8) && (CL<8) && (CH<0x20))
                   1071:   {
                   1072:    if(CL!=(CH+1))
                   1073:     {
                   1074:      CH = ((CH+1) * cheight / 8) -1;
                   1075:     }
                   1076:    else
                   1077:     {
                   1078:      CH = ((CL+1) * cheight / 8) - 2;
                   1079:     }
                   1080:    CL = ((CL+1) * cheight / 8) - 1;
                   1081:   }
                   1082: 
                   1083:  // CTRC regs 0x0a and 0x0b
                   1084:  crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
                   1085:  outb(crtc_addr,0x0a);
                   1086:  outb(crtc_addr+1,CH);
                   1087:  outb(crtc_addr,0x0b);
                   1088:  outb(crtc_addr+1,CL);
                   1089: }
                   1090: 
                   1091: // --------------------------------------------------------------------------------------------
                   1092: static void biosfn_set_cursor_pos (page, cursor) 
                   1093: Bit8u page;Bit16u cursor;
                   1094: {
                   1095:  Bit8u xcurs,ycurs,current;
                   1096:  Bit16u nbcols,nbrows,address,crtc_addr;
                   1097: 
                   1098:  // Should not happen...
                   1099:  if(page>7)return;
                   1100: 
                   1101:  // Bios cursor pos
                   1102:  write_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*page, cursor);
                   1103: 
                   1104:  // Set the hardware cursor
                   1105:  current=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
                   1106:  if(page==current)
                   1107:   {
                   1108:    // Get the dimensions
                   1109:    nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
                   1110:    nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
                   1111: 
                   1112:    xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
                   1113:  
                   1114:    // Calculate the address knowing nbcols nbrows and page num
                   1115:    address=SCREEN_IO_START(nbcols,nbrows,page)+xcurs+ycurs*nbcols;
                   1116:    
                   1117:    // CRTC regs 0x0e and 0x0f
                   1118:    crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
                   1119:    outb(crtc_addr,0x0e);
                   1120:    outb(crtc_addr+1,(address&0xff00)>>8);
                   1121:    outb(crtc_addr,0x0f);
                   1122:    outb(crtc_addr+1,address&0x00ff);
                   1123:   }
                   1124: }
                   1125: 
                   1126: // --------------------------------------------------------------------------------------------
                   1127: static void biosfn_get_cursor_pos (page,shape, pos) 
                   1128: Bit8u page;Bit16u *shape;Bit16u *pos;
                   1129: {
                   1130:  Bit16u ss=get_SS();
                   1131: 
                   1132:  // Default
                   1133:  write_word(ss, shape, 0);
                   1134:  write_word(ss, pos, 0);
                   1135: 
                   1136:  if(page>7)return;
                   1137:  // FIXME should handle VGA 14/16 lines
                   1138:  write_word(ss,shape,read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE));
                   1139:  write_word(ss,pos,read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_POS+page*2));
                   1140: }
                   1141: 
                   1142: // --------------------------------------------------------------------------------------------
                   1143: static void biosfn_set_active_page (page) 
                   1144: Bit8u page;
                   1145: {
                   1146:  Bit16u cursor,dummy,crtc_addr;
                   1147:  Bit16u nbcols,nbrows,address;
                   1148:  Bit8u mode,line;
                   1149: 
                   1150:  if(page>7)return;
                   1151: 
                   1152:  // Get the mode
                   1153:  mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
                   1154:  line=find_vga_entry(mode);
                   1155:  if(line==0xFF)return;
                   1156: 
                   1157:  // Get pos curs pos for the right page 
                   1158:  biosfn_get_cursor_pos(page,&dummy,&cursor);
                   1159: 
                   1160:  if(vga_modes[line].class==TEXT)
                   1161:   {
                   1162:    // Get the dimensions
                   1163:    nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
                   1164:    nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
                   1165:  
                   1166:    // Calculate the address knowing nbcols nbrows and page num
                   1167:    address=SCREEN_MEM_START(nbcols,nbrows,page);
                   1168:    write_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START,address);
                   1169: 
                   1170:    // Start address
                   1171:    address=SCREEN_IO_START(nbcols,nbrows,page);
                   1172:   }
                   1173:  else
                   1174:   {
                   1175:    address = page * (*(Bit16u *)&video_param_table[line_to_vpti[line]].slength_l);
                   1176:   }
                   1177: 
                   1178:  // CRTC regs 0x0c and 0x0d
                   1179:  crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
                   1180:  outb(crtc_addr,0x0c);
                   1181:  outb(crtc_addr+1,(address&0xff00)>>8);
                   1182:  outb(crtc_addr,0x0d);
                   1183:  outb(crtc_addr+1,address&0x00ff);
                   1184: 
                   1185:  // And change the BIOS page
                   1186:  write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE,page);
                   1187: 
                   1188: #ifdef DEBUG
                   1189:  printf("Set active page %02x address %04x\n",page,address);
                   1190: #endif
                   1191: 
                   1192:  // Display the cursor, now the page is active
                   1193:  biosfn_set_cursor_pos(page,cursor);
                   1194: }
                   1195: 
                   1196: // --------------------------------------------------------------------------------------------
                   1197: static void vgamem_copy_pl4(xstart,ysrc,ydest,cols,nbcols,cheight)
                   1198: Bit8u xstart;Bit8u ysrc;Bit8u ydest;Bit8u cols;Bit8u nbcols;Bit8u cheight;
                   1199: {
                   1200:  Bit16u src,dest;
                   1201:  Bit8u i;
                   1202: 
                   1203:  src=ysrc*cheight*nbcols+xstart;
                   1204:  dest=ydest*cheight*nbcols+xstart;
                   1205:  outw(VGAREG_GRDC_ADDRESS, 0x0105);
                   1206:  for(i=0;i<cheight;i++)
                   1207:   {
                   1208:    memcpyb(0xa000,dest+i*nbcols,0xa000,src+i*nbcols,cols);
                   1209:   }
                   1210:  outw(VGAREG_GRDC_ADDRESS, 0x0005);
                   1211: }
                   1212: 
                   1213: // --------------------------------------------------------------------------------------------
                   1214: static void vgamem_fill_pl4(xstart,ystart,cols,nbcols,cheight,attr)
                   1215: Bit8u xstart;Bit8u ystart;Bit8u cols;Bit8u nbcols;Bit8u cheight;Bit8u attr;
                   1216: {
                   1217:  Bit16u dest;
                   1218:  Bit8u i;
                   1219: 
                   1220:  dest=ystart*cheight*nbcols+xstart;
                   1221:  outw(VGAREG_GRDC_ADDRESS, 0x0205);
                   1222:  for(i=0;i<cheight;i++)
                   1223:   {
                   1224:    memsetb(0xa000,dest+i*nbcols,attr,cols);
                   1225:   }
                   1226:  outw(VGAREG_GRDC_ADDRESS, 0x0005);
                   1227: }
                   1228: 
                   1229: // --------------------------------------------------------------------------------------------
                   1230: static void vgamem_copy_cga(xstart,ysrc,ydest,cols,nbcols,cheight)
                   1231: Bit8u xstart;Bit8u ysrc;Bit8u ydest;Bit8u cols;Bit8u nbcols;Bit8u cheight;
                   1232: {
                   1233:  Bit16u src,dest;
                   1234:  Bit8u i;
                   1235: 
                   1236:  src=((ysrc*cheight*nbcols)>>1)+xstart;
                   1237:  dest=((ydest*cheight*nbcols)>>1)+xstart;
                   1238:  for(i=0;i<cheight;i++)
                   1239:   {
                   1240:    if (i & 1)
                   1241:      memcpyb(0xb800,0x2000+dest+(i>>1)*nbcols,0xb800,0x2000+src+(i>>1)*nbcols,cols);
                   1242:    else
                   1243:      memcpyb(0xb800,dest+(i>>1)*nbcols,0xb800,src+(i>>1)*nbcols,cols);
                   1244:   }
                   1245: }
                   1246: 
                   1247: // --------------------------------------------------------------------------------------------
                   1248: static void vgamem_fill_cga(xstart,ystart,cols,nbcols,cheight,attr)
                   1249: Bit8u xstart;Bit8u ystart;Bit8u cols;Bit8u nbcols;Bit8u cheight;Bit8u attr;
                   1250: {
                   1251:  Bit16u dest;
                   1252:  Bit8u i;
                   1253: 
                   1254:  dest=((ystart*cheight*nbcols)>>1)+xstart;
                   1255:  for(i=0;i<cheight;i++)
                   1256:   {
                   1257:    if (i & 1)
                   1258:      memsetb(0xb800,0x2000+dest+(i>>1)*nbcols,attr,cols);
                   1259:    else
                   1260:      memsetb(0xb800,dest+(i>>1)*nbcols,attr,cols);
                   1261:   }
                   1262: }
                   1263: 
                   1264: // --------------------------------------------------------------------------------------------
                   1265: static void biosfn_scroll (nblines,attr,rul,cul,rlr,clr,page,dir)
                   1266: Bit8u nblines;Bit8u attr;Bit8u rul;Bit8u cul;Bit8u rlr;Bit8u clr;Bit8u page;Bit8u dir;
                   1267: {
                   1268:  // page == 0xFF if current
                   1269: 
                   1270:  Bit8u mode,line,cheight,bpp,cols;
                   1271:  Bit16u nbcols,nbrows,i;
                   1272:  Bit16u address;
                   1273: 
                   1274:  if(rul>rlr)return;
                   1275:  if(cul>clr)return;
                   1276: 
                   1277:  // Get the mode
                   1278:  mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
                   1279:  line=find_vga_entry(mode);
                   1280:  if(line==0xFF)return;
                   1281: 
                   1282:  // Get the dimensions
                   1283:  nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
                   1284:  nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
                   1285: 
                   1286:  // Get the current page
                   1287:  if(page==0xFF)
                   1288:   page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
                   1289: 
                   1290:  if(rlr>=nbrows)rlr=nbrows-1;
                   1291:  if(clr>=nbcols)clr=nbcols-1;
                   1292:  if(nblines>nbrows)nblines=0;
                   1293:  cols=clr-cul+1;
                   1294: 
                   1295:  if(vga_modes[line].class==TEXT)
                   1296:   {
                   1297:    // Compute the address
                   1298:    address=SCREEN_MEM_START(nbcols,nbrows,page);
                   1299: #ifdef DEBUG
                   1300:    printf("Scroll, address %04x (%04x %04x %02x)\n",address,nbrows,nbcols,page);
                   1301: #endif
                   1302: 
                   1303:    if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
                   1304:     {
                   1305:      memsetw(vga_modes[line].sstart,address,(Bit16u)attr*0x100+' ',nbrows*nbcols);
                   1306:     }
                   1307:    else
                   1308:     {// if Scroll up
                   1309:      if(dir==SCROLL_UP)
                   1310:       {for(i=rul;i<=rlr;i++)
                   1311:         {
                   1312:          if((i+nblines>rlr)||(nblines==0))
                   1313:           memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(Bit16u)attr*0x100+' ',cols);
                   1314:          else
                   1315:           memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i+nblines)*nbcols+cul)*2,cols);
                   1316:         }
                   1317:       }
                   1318:      else
                   1319:       {for(i=rlr;i>=rul;i--)
                   1320:         {
                   1321:          if((i<rul+nblines)||(nblines==0))
                   1322:           memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(Bit16u)attr*0x100+' ',cols);
                   1323:          else
                   1324:           memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i-nblines)*nbcols+cul)*2,cols);
                   1325:          if (i>rlr) break;
                   1326:         }
                   1327:       }
                   1328:     }
                   1329:   }
                   1330:  else
                   1331:   {
                   1332:    // FIXME gfx mode not complete
                   1333:    cheight=video_param_table[line_to_vpti[line]].cheight;
                   1334:    switch(vga_modes[line].memmodel)
                   1335:     {
                   1336:      case PLANAR4:
                   1337:      case PLANAR1:
                   1338:        if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
                   1339:         {
                   1340:          outw(VGAREG_GRDC_ADDRESS, 0x0205);
                   1341:          memsetb(vga_modes[line].sstart,0,attr,nbrows*nbcols*cheight);
                   1342:          outw(VGAREG_GRDC_ADDRESS, 0x0005);
                   1343:         }
                   1344:        else
                   1345:         {// if Scroll up
                   1346:          if(dir==SCROLL_UP)
                   1347:           {for(i=rul;i<=rlr;i++)
                   1348:             {
                   1349:              if((i+nblines>rlr)||(nblines==0))
                   1350:               vgamem_fill_pl4(cul,i,cols,nbcols,cheight,attr);
                   1351:              else
                   1352:               vgamem_copy_pl4(cul,i+nblines,i,cols,nbcols,cheight);
                   1353:             }
                   1354:           }
                   1355:          else
                   1356:           {for(i=rlr;i>=rul;i--)
                   1357:             {
                   1358:              if((i<rul+nblines)||(nblines==0))
                   1359:               vgamem_fill_pl4(cul,i,cols,nbcols,cheight,attr);
                   1360:              else
                   1361:               vgamem_copy_pl4(cul,i,i-nblines,cols,nbcols,cheight);
                   1362:              if (i>rlr) break;
                   1363:             }
                   1364:           }
                   1365:         }
                   1366:        break;
                   1367:      case CGA:
                   1368:        bpp=vga_modes[line].pixbits;
                   1369:        if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
                   1370:         {
                   1371:          memsetb(vga_modes[line].sstart,0,attr,nbrows*nbcols*cheight*bpp);
                   1372:         }
                   1373:        else
                   1374:         {
                   1375:          if(bpp==2)
                   1376:           {
                   1377:            cul<<=1;
                   1378:            cols<<=1;
                   1379:            nbcols<<=1;
                   1380:           }
                   1381:          // if Scroll up
                   1382:          if(dir==SCROLL_UP)
                   1383:           {for(i=rul;i<=rlr;i++)
                   1384:             {
                   1385:              if((i+nblines>rlr)||(nblines==0))
                   1386:               vgamem_fill_cga(cul,i,cols,nbcols,cheight,attr);
                   1387:              else
                   1388:               vgamem_copy_cga(cul,i+nblines,i,cols,nbcols,cheight);
                   1389:             }
                   1390:           }
                   1391:          else
                   1392:           {for(i=rlr;i>=rul;i--)
                   1393:             {
                   1394:              if((i<rul+nblines)||(nblines==0))
                   1395:               vgamem_fill_cga(cul,i,cols,nbcols,cheight,attr);
                   1396:              else
                   1397:               vgamem_copy_cga(cul,i,i-nblines,cols,nbcols,cheight);
                   1398:              if (i>rlr) break;
                   1399:             }
                   1400:           }
                   1401:         }
                   1402:        break;
                   1403: #ifdef DEBUG
                   1404:      default:
                   1405:        printf("Scroll in graphics mode ");
                   1406:        unimplemented();
                   1407: #endif
                   1408:     }
                   1409:   }
                   1410: }
                   1411: 
                   1412: // --------------------------------------------------------------------------------------------
                   1413: static void biosfn_read_char_attr (page,car) 
                   1414: Bit8u page;Bit16u *car;
                   1415: {Bit16u ss=get_SS();
                   1416:  Bit8u xcurs,ycurs,mode,line;
                   1417:  Bit16u nbcols,nbrows,address;
                   1418:  Bit16u cursor,dummy;
                   1419: 
                   1420:  // Get the mode
                   1421:  mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
                   1422:  line=find_vga_entry(mode);
                   1423:  if(line==0xFF)return;
                   1424: 
                   1425:  // Get the cursor pos for the page
                   1426:  biosfn_get_cursor_pos(page,&dummy,&cursor);
                   1427:  xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
                   1428: 
                   1429:  // Get the dimensions
                   1430:  nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
                   1431:  nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
                   1432: 
                   1433:  if(vga_modes[line].class==TEXT)
                   1434:   {
                   1435:    // Compute the address
                   1436:    address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
                   1437: 
                   1438:    write_word(ss,car,read_word(vga_modes[line].sstart,address));
                   1439:   }
                   1440:  else
                   1441:   {
                   1442:    // FIXME gfx mode
                   1443: #ifdef DEBUG
                   1444:    unimplemented();
                   1445: #endif
                   1446:   }
                   1447: }
                   1448: 
                   1449: // --------------------------------------------------------------------------------------------
                   1450: static void write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight)
                   1451: Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;Bit8u cheight;
                   1452: {
                   1453:  Bit8u i,j,mask;
                   1454:  Bit8u *fdata;
                   1455:  Bit16u addr,dest,src;
                   1456: 
                   1457:  switch(cheight)
                   1458:   {case 14:
                   1459:     fdata = &vgafont14;
                   1460:     break;
                   1461:    case 16:
                   1462:     fdata = &vgafont16;
                   1463:     break;
                   1464:    default:
                   1465:     fdata = &vgafont8;
                   1466:   }
                   1467:  addr=xcurs+ycurs*cheight*nbcols;
                   1468:  src = car * cheight;
                   1469:  outw(VGAREG_SEQU_ADDRESS, 0x0f02);
                   1470:  outw(VGAREG_GRDC_ADDRESS, 0x0205);
                   1471:  if(attr&0x80)
                   1472:   {
                   1473:    outw(VGAREG_GRDC_ADDRESS, 0x1803);
                   1474:   }
                   1475:  else
                   1476:   {
                   1477:    outw(VGAREG_GRDC_ADDRESS, 0x0003);
                   1478:   }
                   1479:  for(i=0;i<cheight;i++)
                   1480:   {
                   1481:    dest=addr+i*nbcols;
                   1482:    for(j=0;j<8;j++)
                   1483:     {
                   1484:      mask=0x80>>j;
                   1485:      outw(VGAREG_GRDC_ADDRESS, (mask << 8) | 0x08);
                   1486:      read_byte(0xa000,dest);
                   1487:      if(fdata[src+i]&mask)
                   1488:       {
                   1489:        write_byte(0xa000,dest,attr&0x0f);
                   1490:       }
                   1491:      else
                   1492:       {
                   1493:        write_byte(0xa000,dest,0x00);
                   1494:       }
                   1495:     }
                   1496:   }
                   1497: ASM_START
                   1498:   mov dx, # VGAREG_GRDC_ADDRESS
                   1499:   mov ax, #0xff08
                   1500:   out dx, ax
                   1501:   mov ax, #0x0005
                   1502:   out dx, ax
                   1503:   mov ax, #0x0003
                   1504:   out dx, ax
                   1505: ASM_END
                   1506: }
                   1507: 
                   1508: // --------------------------------------------------------------------------------------------
                   1509: static void write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp)
                   1510: Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;Bit8u bpp;
                   1511: {
                   1512:  Bit8u i,j,mask,data;
                   1513:  Bit8u *fdata;
                   1514:  Bit16u addr,dest,src;
                   1515: 
                   1516:  fdata = &vgafont8;
                   1517:  addr=(xcurs*bpp)+ycurs*320;
                   1518:  src = car * 8;
                   1519:  for(i=0;i<8;i++)
                   1520:   {
                   1521:    dest=addr+(i>>1)*80;
                   1522:    if (i & 1) dest += 0x2000;
                   1523:    mask = 0x80;
                   1524:    if (bpp == 1)
                   1525:     {
                   1526:      if (attr & 0x80)
                   1527:       {
                   1528:        data = read_byte(0xb800,dest);
                   1529:       }
                   1530:      else
                   1531:       {
                   1532:        data = 0x00;
                   1533:       }
                   1534:      for(j=0;j<8;j++)
                   1535:       {
                   1536:        if (fdata[src+i] & mask)
                   1537:         {
                   1538:          if (attr & 0x80)
                   1539:           {
                   1540:            data ^= (attr & 0x01) << (7-j);
                   1541:           }
                   1542:          else
                   1543:           {
                   1544:            data |= (attr & 0x01) << (7-j);
                   1545:           }
                   1546:         }
                   1547:        mask >>= 1;
                   1548:       }
                   1549:      write_byte(0xb800,dest,data);
                   1550:     }
                   1551:    else
                   1552:     {
                   1553:      while (mask > 0)
                   1554:       {
                   1555:        if (attr & 0x80)
                   1556:         {
                   1557:          data = read_byte(0xb800,dest);
                   1558:         }
                   1559:        else
                   1560:         {
                   1561:          data = 0x00;
                   1562:         }
                   1563:        for(j=0;j<4;j++)
                   1564:         {
                   1565:          if (fdata[src+i] & mask)
                   1566:           {
                   1567:            if (attr & 0x80)
                   1568:             {
                   1569:              data ^= (attr & 0x03) << ((3-j)*2);
                   1570:             }
                   1571:            else
                   1572:             {
                   1573:              data |= (attr & 0x03) << ((3-j)*2);
                   1574:             }
                   1575:           }
                   1576:          mask >>= 1;
                   1577:         }
                   1578:        write_byte(0xb800,dest,data);
                   1579:        dest += 1;
                   1580:       }
                   1581:     }
                   1582:   }
                   1583: }
                   1584: 
                   1585: // --------------------------------------------------------------------------------------------
                   1586: static void write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols)
                   1587: Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;
                   1588: {
                   1589:  Bit8u i,j,mask,data;
                   1590:  Bit8u *fdata;
                   1591:  Bit16u addr,dest,src;
                   1592: 
                   1593:  fdata = &vgafont8;
                   1594:  addr=xcurs*8+ycurs*nbcols*64;
                   1595:  src = car * 8;
                   1596:  for(i=0;i<8;i++)
                   1597:   {
                   1598:    dest=addr+i*nbcols*8;
                   1599:    mask = 0x80;
                   1600:    for(j=0;j<8;j++)
                   1601:     {
                   1602:      data = 0x00;
                   1603:      if (fdata[src+i] & mask)
                   1604:       {
                   1605:        data = attr;
                   1606:       }
                   1607:      write_byte(0xa000,dest+j,data);
                   1608:      mask >>= 1;
                   1609:     }
                   1610:   }
                   1611: }
                   1612: 
                   1613: // --------------------------------------------------------------------------------------------
                   1614: static void biosfn_write_char_attr (car,page,attr,count) 
                   1615: Bit8u car;Bit8u page;Bit8u attr;Bit16u count;
                   1616: {
                   1617:  Bit8u cheight,xcurs,ycurs,mode,line,bpp;
                   1618:  Bit16u nbcols,nbrows,address;
                   1619:  Bit16u cursor,dummy;
                   1620: 
                   1621:  // Get the mode
                   1622:  mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
                   1623:  line=find_vga_entry(mode);
                   1624:  if(line==0xFF)return;
                   1625: 
                   1626:  // Get the cursor pos for the page
                   1627:  biosfn_get_cursor_pos(page,&dummy,&cursor);
                   1628:  xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
                   1629: 
                   1630:  // Get the dimensions
                   1631:  nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
                   1632:  nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
                   1633: 
                   1634:  if(vga_modes[line].class==TEXT)
                   1635:   {
                   1636:    // Compute the address
                   1637:    address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
                   1638: 
                   1639:    dummy=((Bit16u)attr<<8)+car;
                   1640:    memsetw(vga_modes[line].sstart,address,dummy,count);
                   1641:   }
                   1642:  else
                   1643:   {
                   1644:    // FIXME gfx mode not complete
                   1645:    cheight=video_param_table[line_to_vpti[line]].cheight;
                   1646:    bpp=vga_modes[line].pixbits;
                   1647:    while((count-->0) && (xcurs<nbcols))
                   1648:     {
                   1649:      switch(vga_modes[line].memmodel)
                   1650:       {
                   1651:        case PLANAR4:
                   1652:        case PLANAR1:
                   1653:          write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
                   1654:          break;
                   1655:        case CGA:
                   1656:          write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
                   1657:          break;
                   1658:        case LINEAR8:
                   1659:          write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
                   1660:          break;
                   1661: #ifdef DEBUG
                   1662:        default:
                   1663:          unimplemented();
                   1664: #endif
                   1665:       }
                   1666:      xcurs++;
                   1667:     }
                   1668:   }
                   1669: }
                   1670: 
                   1671: // --------------------------------------------------------------------------------------------
                   1672: static void biosfn_write_char_only (car,page,attr,count)
                   1673: Bit8u car;Bit8u page;Bit8u attr;Bit16u count;
                   1674: {
                   1675:  Bit8u cheight,xcurs,ycurs,mode,line,bpp;
                   1676:  Bit16u nbcols,nbrows,address;
                   1677:  Bit16u cursor,dummy;
                   1678: 
                   1679:  // Get the mode
                   1680:  mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
                   1681:  line=find_vga_entry(mode);
                   1682:  if(line==0xFF)return;
                   1683: 
                   1684:  // Get the cursor pos for the page
                   1685:  biosfn_get_cursor_pos(page,&dummy,&cursor);
                   1686:  xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
                   1687: 
                   1688:  // Get the dimensions
                   1689:  nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
                   1690:  nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
                   1691: 
                   1692:  if(vga_modes[line].class==TEXT)
                   1693:   {
                   1694:    // Compute the address
                   1695:    address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
                   1696: 
                   1697:    while(count-->0)
                   1698:     {write_byte(vga_modes[line].sstart,address,car);
                   1699:      address+=2;
                   1700:     }
                   1701:   }
                   1702:  else
                   1703:   {
                   1704:    // FIXME gfx mode not complete
                   1705:    cheight=video_param_table[line_to_vpti[line]].cheight;
                   1706:    bpp=vga_modes[line].pixbits;
                   1707:    while((count-->0) && (xcurs<nbcols))
                   1708:     {
                   1709:      switch(vga_modes[line].memmodel)
                   1710:       {
                   1711:        case PLANAR4:
                   1712:        case PLANAR1:
                   1713:          write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
                   1714:          break;
                   1715:        case CGA:
                   1716:          write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
                   1717:          break;
                   1718:        case LINEAR8:
                   1719:          write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
                   1720:          break;
                   1721: #ifdef DEBUG
                   1722:        default:
                   1723:          unimplemented();
                   1724: #endif
                   1725:       }
                   1726:      xcurs++;
                   1727:     }
                   1728:   }
                   1729: }
                   1730: 
                   1731: // --------------------------------------------------------------------------------------------
                   1732: ASM_START
                   1733: biosfn_group_0B:
                   1734:   cmp   bh, #0x00
                   1735:   je    biosfn_set_border_color
                   1736:   cmp   bh, #0x01
                   1737:   je    biosfn_set_palette
                   1738: #ifdef DEBUG
                   1739:   call  _unknown
                   1740: #endif
                   1741:   ret
                   1742: biosfn_set_border_color:
                   1743:   push  ax
                   1744:   push  bx
                   1745:   push  cx
                   1746:   push  dx
                   1747:   mov   dx, # VGAREG_ACTL_RESET
                   1748:   in    al, dx
                   1749:   mov   dx, # VGAREG_ACTL_ADDRESS
                   1750:   mov   al, #0x00
                   1751:   out   dx, al
                   1752:   mov   al, bl
                   1753:   and   al, #0x0f
                   1754:   test  al, #0x08
                   1755:   jz    set_low_border
                   1756:   add   al, #0x08
                   1757: set_low_border:
                   1758:   out   dx, al
                   1759:   mov   cl, #0x01
                   1760:   and   bl, #0x10
                   1761: set_intensity_loop:
                   1762:   mov   dx, # VGAREG_ACTL_ADDRESS
                   1763:   mov   al, cl
                   1764:   out   dx, al
                   1765:   mov   dx, # VGAREG_ACTL_READ_DATA
                   1766:   in    al, dx
                   1767:   and   al, #0xef
                   1768:   or    al, bl
                   1769:   mov   dx, # VGAREG_ACTL_ADDRESS
                   1770:   out   dx, al
                   1771:   inc   cl
                   1772:   cmp   cl, #0x04
                   1773:   jne   set_intensity_loop
                   1774:   mov   al, #0x20
                   1775:   out   dx, al
                   1776:   pop   dx
                   1777:   pop   cx
                   1778:   pop   bx
                   1779:   pop   ax
                   1780:   ret
                   1781: biosfn_set_palette:
                   1782:   push  ax
                   1783:   push  bx
                   1784:   push  cx
                   1785:   push  dx
                   1786:   mov   dx, # VGAREG_ACTL_RESET
                   1787:   in    al, dx
                   1788:   mov   cl, #0x01
                   1789:   and   bl, #0x01
                   1790: set_cga_palette_loop:
                   1791:   mov   dx, # VGAREG_ACTL_ADDRESS
                   1792:   mov   al, cl
                   1793:   out   dx, al
                   1794:   mov   dx, # VGAREG_ACTL_READ_DATA
                   1795:   in    al, dx
                   1796:   and   al, #0xfe
                   1797:   or    al, bl
                   1798:   mov   dx, # VGAREG_ACTL_ADDRESS
                   1799:   out   dx, al
                   1800:   inc   cl
                   1801:   cmp   cl, #0x04
                   1802:   jne   set_cga_palette_loop
                   1803:   mov   al, #0x20
                   1804:   out   dx, al
                   1805:   pop   dx
                   1806:   pop   cx
                   1807:   pop   bx
                   1808:   pop   ax
                   1809:   ret
                   1810: ASM_END
                   1811: 
                   1812: // --------------------------------------------------------------------------------------------
                   1813: static void biosfn_write_pixel (BH,AL,CX,DX) Bit8u BH;Bit8u AL;Bit16u CX;Bit16u DX;
                   1814: {
                   1815:  Bit8u mode,line,mask,attr,data;
                   1816:  Bit16u addr;
                   1817: 
                   1818:  // Get the mode
                   1819:  mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
                   1820:  line=find_vga_entry(mode);
                   1821:  if(line==0xFF)return;
                   1822:  if(vga_modes[line].class==TEXT)return;
                   1823: 
                   1824:  switch(vga_modes[line].memmodel)
                   1825:   {
                   1826:    case PLANAR4:
                   1827:    case PLANAR1:
                   1828:      addr = CX/8+DX*read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
                   1829:      mask = 0x80 >> (CX & 0x07);
                   1830:      outw(VGAREG_GRDC_ADDRESS, (mask << 8) | 0x08);
                   1831:      outw(VGAREG_GRDC_ADDRESS, 0x0205);
                   1832:      data = read_byte(0xa000,addr);
                   1833:      if (AL & 0x80)
                   1834:       {
                   1835:        outw(VGAREG_GRDC_ADDRESS, 0x1803);
                   1836:       }
                   1837:      write_byte(0xa000,addr,AL);
                   1838: ASM_START
                   1839:      mov dx, # VGAREG_GRDC_ADDRESS
                   1840:      mov ax, #0xff08
                   1841:      out dx, ax
                   1842:      mov ax, #0x0005
                   1843:      out dx, ax
                   1844:      mov ax, #0x0003
                   1845:      out dx, ax
                   1846: ASM_END
                   1847:      break;
                   1848:    case CGA:
                   1849:      if(vga_modes[line].pixbits==2)
                   1850:       {
                   1851:        addr=(CX>>2)+(DX>>1)*80;
                   1852:       }
                   1853:      else
                   1854:       {
                   1855:        addr=(CX>>3)+(DX>>1)*80;
                   1856:       }
                   1857:      if (DX & 1) addr += 0x2000;
                   1858:      data = read_byte(0xb800,addr);
                   1859:      if(vga_modes[line].pixbits==2)
                   1860:       {
                   1861:        attr = (AL & 0x03) << ((3 - (CX & 0x03)) * 2);
                   1862:        mask = 0x03 << ((3 - (CX & 0x03)) * 2);
                   1863:       }
                   1864:      else
                   1865:       {
                   1866:        attr = (AL & 0x01) << (7 - (CX & 0x07));
                   1867:        mask = 0x01 << (7 - (CX & 0x07));
                   1868:       }
                   1869:      if (AL & 0x80)
                   1870:       {
                   1871:        data ^= attr;
                   1872:       }
                   1873:      else
                   1874:       {
                   1875:        data &= ~mask;
                   1876:        data |= attr;
                   1877:       }
                   1878:      write_byte(0xb800,addr,data);
                   1879:      break;
                   1880:    case LINEAR8:
                   1881:      addr=CX+DX*(read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8);
                   1882:      write_byte(0xa000,addr,AL);
                   1883:      break;
                   1884: #ifdef DEBUG
                   1885:    default:
                   1886:      unimplemented();
                   1887: #endif
                   1888:   }
                   1889: }
                   1890: 
                   1891: // --------------------------------------------------------------------------------------------
                   1892: static void biosfn_read_pixel (BH,CX,DX,AX) Bit8u BH;Bit16u CX;Bit16u DX;Bit16u *AX;
                   1893: {
                   1894:  Bit8u mode,line,mask,attr,data,i;
                   1895:  Bit16u addr;
                   1896:  Bit16u ss=get_SS();
                   1897: 
                   1898:  // Get the mode
                   1899:  mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
                   1900:  line=find_vga_entry(mode);
                   1901:  if(line==0xFF)return;
                   1902:  if(vga_modes[line].class==TEXT)return;
                   1903: 
                   1904:  switch(vga_modes[line].memmodel)
                   1905:   {
                   1906:    case PLANAR4:
                   1907:    case PLANAR1:
                   1908:      addr = CX/8+DX*read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
                   1909:      mask = 0x80 >> (CX & 0x07);
                   1910:      attr = 0x00;
                   1911:      for(i=0;i<4;i++)
                   1912:       {
                   1913:        outw(VGAREG_GRDC_ADDRESS, (i << 8) | 0x04);
                   1914:        data = read_byte(0xa000,addr) & mask;
                   1915:        if (data > 0) attr |= (0x01 << i);
                   1916:       }
                   1917:      break;
                   1918:    case CGA:
                   1919:      addr=(CX>>2)+(DX>>1)*80;
                   1920:      if (DX & 1) addr += 0x2000;
                   1921:      data = read_byte(0xb800,addr);
                   1922:      if(vga_modes[line].pixbits==2)
                   1923:       {
                   1924:        attr = (data >> ((3 - (CX & 0x03)) * 2)) & 0x03;
                   1925:       }
                   1926:      else
                   1927:       {
                   1928:        attr = (data >> (7 - (CX & 0x07))) & 0x01;
                   1929:       }
                   1930:      break;
                   1931:    case LINEAR8:
                   1932:      addr=CX+DX*(read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8);
                   1933:      attr=read_byte(0xa000,addr);
                   1934:      break;
                   1935:    default:
                   1936: #ifdef DEBUG
                   1937:      unimplemented();
                   1938: #endif
                   1939:      attr = 0;
                   1940:   }
                   1941:  write_word(ss,AX,(read_word(ss,AX) & 0xff00) | attr);
                   1942: }
                   1943: 
                   1944: // --------------------------------------------------------------------------------------------
                   1945: static void biosfn_write_teletype (car, page, attr, flag) 
                   1946: Bit8u car;Bit8u page;Bit8u attr;Bit8u flag;
                   1947: {// flag = WITH_ATTR / NO_ATTR
                   1948: 
                   1949:  Bit8u cheight,xcurs,ycurs,mode,line,bpp;
                   1950:  Bit16u nbcols,nbrows,address;
                   1951:  Bit16u cursor,dummy;
                   1952: 
                   1953:  // special case if page is 0xff, use current page
                   1954:  if(page==0xff)
                   1955:   page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
                   1956: 
                   1957:  // Get the mode
                   1958:  mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
                   1959:  line=find_vga_entry(mode);
                   1960:  if(line==0xFF)return;
                   1961: 
                   1962:  // Get the cursor pos for the page
                   1963:  biosfn_get_cursor_pos(page,&dummy,&cursor);
                   1964:  xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
                   1965: 
                   1966:  // Get the dimensions
                   1967:  nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
                   1968:  nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
                   1969: 
                   1970:  switch(car)
                   1971:   {
                   1972:    case 7:
                   1973:     //FIXME should beep
                   1974:     break;
                   1975: 
                   1976:    case 8:
                   1977:     if(xcurs>0)xcurs--;
                   1978:     break;
                   1979: 
                   1980:    case '\r':
                   1981:     xcurs=0;
                   1982:     break;
                   1983: 
                   1984:    case '\n':
                   1985:     ycurs++;
                   1986:     break;
                   1987: 
                   1988:    case '\t':
                   1989:     do
                   1990:      {
                   1991:       biosfn_write_teletype(' ',page,attr,flag);
                   1992:       biosfn_get_cursor_pos(page,&dummy,&cursor);
                   1993:       xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
                   1994:      }while(xcurs%8==0);
                   1995:     break;
                   1996: 
                   1997:    default:
                   1998: 
                   1999:     if(vga_modes[line].class==TEXT)
                   2000:      {
                   2001:       // Compute the address  
                   2002:       address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
                   2003: 
                   2004:       // Write the char 
                   2005:       write_byte(vga_modes[line].sstart,address,car);
                   2006: 
                   2007:       if(flag==WITH_ATTR)
                   2008:        write_byte(vga_modes[line].sstart,address+1,attr);
                   2009:      }
                   2010:     else
                   2011:      {
                   2012:       // FIXME gfx mode not complete
                   2013:       cheight=video_param_table[line_to_vpti[line]].cheight;
                   2014:       bpp=vga_modes[line].pixbits;
                   2015:       switch(vga_modes[line].memmodel)
                   2016:        {
                   2017:         case PLANAR4:
                   2018:         case PLANAR1:
                   2019:           write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
                   2020:           break;
                   2021:         case CGA:
                   2022:           write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
                   2023:           break;
                   2024:         case LINEAR8:
                   2025:           write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
                   2026:           break;
                   2027: #ifdef DEBUG
                   2028:         default:
                   2029:           unimplemented();
                   2030: #endif
                   2031:        }
                   2032:      }
                   2033:     xcurs++;
                   2034:   }
                   2035: 
                   2036:  // Do we need to wrap ?
                   2037:  if(xcurs==nbcols)
                   2038:   {xcurs=0;
                   2039:    ycurs++;
                   2040:   }
                   2041: 
                   2042:  // Do we need to scroll ?
                   2043:  if(ycurs==nbrows)
                   2044:   {
                   2045:    if(vga_modes[line].class==TEXT)
                   2046:     {
1.1.1.2 ! root     2047:      address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+(ycurs-1)*nbcols)*2;
        !          2048:      attr=read_byte(vga_modes[line].sstart,address+1);
        !          2049:      biosfn_scroll(0x01,attr,0,0,nbrows-1,nbcols-1,page,SCROLL_UP);
1.1       root     2050:     }
                   2051:    else
                   2052:     {
                   2053:      biosfn_scroll(0x01,0x00,0,0,nbrows-1,nbcols-1,page,SCROLL_UP);
                   2054:     }
                   2055:    ycurs-=1;
                   2056:   }
1.1.1.2 ! root     2057: 
1.1       root     2058:  // Set the cursor for the page
                   2059:  cursor=ycurs; cursor<<=8; cursor+=xcurs;
                   2060:  biosfn_set_cursor_pos(page,cursor);
                   2061: }
                   2062: 
                   2063: // --------------------------------------------------------------------------------------------
                   2064: ASM_START
                   2065: biosfn_get_video_mode:
                   2066:   push  ds
                   2067:   mov   ax, # BIOSMEM_SEG
                   2068:   mov   ds, ax
                   2069:   push  bx
                   2070:   mov   bx, # BIOSMEM_CURRENT_PAGE
                   2071:   mov   al, [bx]
                   2072:   pop   bx
                   2073:   mov   bh, al
                   2074:   push  bx
                   2075:   mov   bx, # BIOSMEM_VIDEO_CTL
                   2076:   mov   ah, [bx]
                   2077:   and   ah, #0x80
                   2078:   mov   bx, # BIOSMEM_CURRENT_MODE
                   2079:   mov   al, [bx]
                   2080:   or    al, ah
                   2081:   mov   bx, # BIOSMEM_NB_COLS
                   2082:   mov   ah, [bx]
                   2083:   pop   bx
                   2084:   pop   ds
                   2085:   ret
                   2086: ASM_END
                   2087: 
                   2088: // --------------------------------------------------------------------------------------------
                   2089: ASM_START
                   2090: biosfn_group_10:
                   2091:   cmp   al, #0x00
                   2092:   jne   int10_test_1001
                   2093:   jmp   biosfn_set_single_palette_reg
                   2094: int10_test_1001:
                   2095:   cmp   al, #0x01
                   2096:   jne   int10_test_1002
                   2097:   jmp   biosfn_set_overscan_border_color
                   2098: int10_test_1002:
                   2099:   cmp   al, #0x02
                   2100:   jne   int10_test_1003
                   2101:   jmp   biosfn_set_all_palette_reg
                   2102: int10_test_1003:
                   2103:   cmp   al, #0x03
                   2104:   jne   int10_test_1007
                   2105:   jmp   biosfn_toggle_intensity
                   2106: int10_test_1007:
                   2107:   cmp   al, #0x07
                   2108:   jne   int10_test_1008
                   2109:   jmp   biosfn_get_single_palette_reg
                   2110: int10_test_1008:
                   2111:   cmp   al, #0x08
                   2112:   jne   int10_test_1009
                   2113:   jmp   biosfn_read_overscan_border_color
                   2114: int10_test_1009:
                   2115:   cmp   al, #0x09
                   2116:   jne   int10_test_1010
                   2117:   jmp   biosfn_get_all_palette_reg
                   2118: int10_test_1010:
                   2119:   cmp   al, #0x10
                   2120:   jne   int10_test_1012
                   2121:   jmp  biosfn_set_single_dac_reg
                   2122: int10_test_1012:
                   2123:   cmp   al, #0x12
                   2124:   jne   int10_test_1013
                   2125:   jmp   biosfn_set_all_dac_reg
                   2126: int10_test_1013:
                   2127:   cmp   al, #0x13
                   2128:   jne   int10_test_1015
                   2129:   jmp   biosfn_select_video_dac_color_page
                   2130: int10_test_1015:
                   2131:   cmp   al, #0x15
                   2132:   jne   int10_test_1017
                   2133:   jmp   biosfn_read_single_dac_reg
                   2134: int10_test_1017:
                   2135:   cmp   al, #0x17
                   2136:   jne   int10_test_1018
                   2137:   jmp   biosfn_read_all_dac_reg
                   2138: int10_test_1018:
                   2139:   cmp   al, #0x18
                   2140:   jne   int10_test_1019
                   2141:   jmp   biosfn_set_pel_mask
                   2142: int10_test_1019:
                   2143:   cmp   al, #0x19
                   2144:   jne   int10_test_101A
                   2145:   jmp   biosfn_read_pel_mask
                   2146: int10_test_101A:
                   2147:   cmp   al, #0x1a
                   2148:   jne   int10_group_10_unknown
                   2149:   jmp   biosfn_read_video_dac_state
                   2150: int10_group_10_unknown:
                   2151: #ifdef DEBUG
                   2152:   call  _unknown
                   2153: #endif
                   2154:   ret
                   2155: 
                   2156: biosfn_set_single_palette_reg:
                   2157:   cmp   bl, #0x14
                   2158:   ja    no_actl_reg1
                   2159:   push  ax
                   2160:   push  dx
                   2161:   mov   dx, # VGAREG_ACTL_RESET
                   2162:   in    al, dx
                   2163:   mov   dx, # VGAREG_ACTL_ADDRESS
                   2164:   mov   al, bl
                   2165:   out   dx, al
                   2166:   mov   al, bh
                   2167:   out   dx, al
                   2168:   mov   al, #0x20
                   2169:   out   dx, al
                   2170:   pop   dx
                   2171:   pop   ax
                   2172: no_actl_reg1:
                   2173:   ret
                   2174: ASM_END
                   2175: 
                   2176: // --------------------------------------------------------------------------------------------
                   2177: ASM_START
                   2178: biosfn_set_overscan_border_color:
                   2179:   push  bx
                   2180:   mov   bl, #0x11
                   2181:   call  biosfn_set_single_palette_reg
                   2182:   pop   bx
                   2183:   ret
                   2184: ASM_END
                   2185: 
                   2186: // --------------------------------------------------------------------------------------------
                   2187: ASM_START
                   2188: biosfn_set_all_palette_reg:
                   2189:   push  ax
                   2190:   push  bx
                   2191:   push  cx
                   2192:   push  dx
                   2193:   mov   bx, dx
                   2194:   mov   dx, # VGAREG_ACTL_RESET
                   2195:   in    al, dx
                   2196:   mov   cl, #0x00
                   2197:   mov   dx, # VGAREG_ACTL_ADDRESS
                   2198: set_palette_loop:
                   2199:   mov   al, cl
                   2200:   out   dx, al
                   2201:   seg   es
                   2202:   mov   al, [bx]
                   2203:   out   dx, al
                   2204:   inc   bx
                   2205:   inc   cl
                   2206:   cmp   cl, #0x10
                   2207:   jne   set_palette_loop
                   2208:   mov   al, #0x11
                   2209:   out   dx, al
                   2210:   seg   es
                   2211:   mov   al, [bx]
                   2212:   out   dx, al
                   2213:   mov   al, #0x20
                   2214:   out   dx, al
                   2215:   pop   dx
                   2216:   pop   cx
                   2217:   pop   bx
                   2218:   pop   ax
                   2219:   ret
                   2220: ASM_END
                   2221: 
                   2222: // --------------------------------------------------------------------------------------------
                   2223: ASM_START
                   2224: biosfn_toggle_intensity:
                   2225:   push  ax
                   2226:   push  bx
                   2227:   push  dx
                   2228:   mov   dx, # VGAREG_ACTL_RESET
                   2229:   in    al, dx
                   2230:   mov   dx, # VGAREG_ACTL_ADDRESS
                   2231:   mov   al, #0x10
                   2232:   out   dx, al
                   2233:   mov   dx, # VGAREG_ACTL_READ_DATA
                   2234:   in    al, dx
                   2235:   and   al, #0xf7
                   2236:   and   bl, #0x01
                   2237:   shl   bl, 3
                   2238:   or    al, bl
                   2239:   mov   dx, # VGAREG_ACTL_ADDRESS
                   2240:   out   dx, al
                   2241:   mov   al, #0x20
                   2242:   out   dx, al
                   2243:   pop   dx
                   2244:   pop   bx
                   2245:   pop   ax
                   2246:   ret
                   2247: ASM_END
                   2248: 
                   2249: // --------------------------------------------------------------------------------------------
                   2250: ASM_START
                   2251: biosfn_get_single_palette_reg:
                   2252:   cmp   bl, #0x14
                   2253:   ja    no_actl_reg2
                   2254:   push  ax
                   2255:   push  dx
                   2256:   mov   dx, # VGAREG_ACTL_RESET
                   2257:   in    al, dx
                   2258:   mov   dx, # VGAREG_ACTL_ADDRESS
                   2259:   mov   al, bl
                   2260:   out   dx, al
                   2261:   mov   dx, # VGAREG_ACTL_READ_DATA
                   2262:   in    al, dx
                   2263:   mov   bh, al
                   2264:   mov   dx, # VGAREG_ACTL_RESET
                   2265:   in    al, dx
                   2266:   mov   dx, # VGAREG_ACTL_ADDRESS
                   2267:   mov   al, #0x20
                   2268:   out   dx, al
                   2269:   pop   dx
                   2270:   pop   ax
                   2271: no_actl_reg2:
                   2272:   ret
                   2273: ASM_END
                   2274: 
                   2275: // --------------------------------------------------------------------------------------------
                   2276: ASM_START
                   2277: biosfn_read_overscan_border_color:
                   2278:   push  ax
                   2279:   push  bx
                   2280:   mov   bl, #0x11
                   2281:   call  biosfn_get_single_palette_reg
                   2282:   mov   al, bh
                   2283:   pop   bx
                   2284:   mov   bh, al
                   2285:   pop   ax
                   2286:   ret
                   2287: ASM_END
                   2288: 
                   2289: // --------------------------------------------------------------------------------------------
                   2290: ASM_START
                   2291: biosfn_get_all_palette_reg:
                   2292:   push  ax
                   2293:   push  bx
                   2294:   push  cx
                   2295:   push  dx
                   2296:   mov   bx, dx
                   2297:   mov   cl, #0x00
                   2298: get_palette_loop:
                   2299:   mov   dx, # VGAREG_ACTL_RESET
                   2300:   in    al, dx
                   2301:   mov   dx, # VGAREG_ACTL_ADDRESS
                   2302:   mov   al, cl
                   2303:   out   dx, al
                   2304:   mov   dx, # VGAREG_ACTL_READ_DATA
                   2305:   in    al, dx
                   2306:   seg   es
                   2307:   mov   [bx], al
                   2308:   inc   bx
                   2309:   inc   cl
                   2310:   cmp   cl, #0x10
                   2311:   jne   get_palette_loop
                   2312:   mov   dx, # VGAREG_ACTL_RESET
                   2313:   in    al, dx
                   2314:   mov   dx, # VGAREG_ACTL_ADDRESS
                   2315:   mov   al, #0x11
                   2316:   out   dx, al
                   2317:   mov   dx, # VGAREG_ACTL_READ_DATA
                   2318:   in    al, dx
                   2319:   seg   es
                   2320:   mov   [bx], al
                   2321:   mov   dx, # VGAREG_ACTL_RESET
                   2322:   in    al, dx
                   2323:   mov   dx, # VGAREG_ACTL_ADDRESS
                   2324:   mov   al, #0x20
                   2325:   out   dx, al
                   2326:   pop   dx
                   2327:   pop   cx
                   2328:   pop   bx
                   2329:   pop   ax
                   2330:   ret
                   2331: ASM_END
                   2332: 
                   2333: // --------------------------------------------------------------------------------------------
                   2334: ASM_START
                   2335: biosfn_set_single_dac_reg:
                   2336:   push  ax
                   2337:   push  dx
                   2338:   mov   dx, # VGAREG_DAC_WRITE_ADDRESS
                   2339:   mov   al, bl
                   2340:   out   dx, al
                   2341:   mov   dx, # VGAREG_DAC_DATA
                   2342:   pop   ax
                   2343:   push  ax
                   2344:   mov   al, ah
                   2345:   out   dx, al
                   2346:   mov   al, ch
                   2347:   out   dx, al
                   2348:   mov   al, cl
                   2349:   out   dx, al
                   2350:   pop   dx
                   2351:   pop   ax
                   2352:   ret
                   2353: ASM_END
                   2354: 
                   2355: // --------------------------------------------------------------------------------------------
                   2356: ASM_START
                   2357: biosfn_set_all_dac_reg:
                   2358:   push  ax
                   2359:   push  bx
                   2360:   push  cx
                   2361:   push  dx
                   2362:   mov   dx, # VGAREG_DAC_WRITE_ADDRESS
                   2363:   mov   al, bl
                   2364:   out   dx, al
                   2365:   pop   dx
                   2366:   push  dx
                   2367:   mov   bx, dx
                   2368:   mov   dx, # VGAREG_DAC_DATA
                   2369: set_dac_loop:
                   2370:   seg   es
                   2371:   mov   al, [bx]
                   2372:   out   dx, al
                   2373:   inc   bx
                   2374:   seg   es
                   2375:   mov   al, [bx]
                   2376:   out   dx, al
                   2377:   inc   bx
                   2378:   seg   es
                   2379:   mov   al, [bx]
                   2380:   out   dx, al
                   2381:   inc   bx
                   2382:   dec   cx
                   2383:   jnz   set_dac_loop
                   2384:   pop   dx
                   2385:   pop   cx
                   2386:   pop   bx
                   2387:   pop   ax
                   2388:   ret
                   2389: ASM_END
                   2390: 
                   2391: // --------------------------------------------------------------------------------------------
                   2392: ASM_START
                   2393: biosfn_select_video_dac_color_page:
                   2394:   push  ax
                   2395:   push  bx
                   2396:   push  dx
                   2397:   mov   dx, # VGAREG_ACTL_RESET
                   2398:   in    al, dx
                   2399:   mov   dx, # VGAREG_ACTL_ADDRESS
                   2400:   mov   al, #0x10
                   2401:   out   dx, al
                   2402:   mov   dx, # VGAREG_ACTL_READ_DATA
                   2403:   in    al, dx
                   2404:   and   bl, #0x01
                   2405:   jnz   set_dac_page
                   2406:   and   al, #0x7f
                   2407:   shl   bh, 7
                   2408:   or    al, bh
                   2409:   mov   dx, # VGAREG_ACTL_ADDRESS
                   2410:   out   dx, al
                   2411:   jmp   set_actl_normal
                   2412: set_dac_page:
                   2413:   push  ax
                   2414:   mov   dx, # VGAREG_ACTL_RESET
                   2415:   in    al, dx
                   2416:   mov   dx, # VGAREG_ACTL_ADDRESS
                   2417:   mov   al, #0x14
                   2418:   out   dx, al
                   2419:   pop   ax
                   2420:   and   al, #0x80
                   2421:   jnz   set_dac_16_page
                   2422:   shl   bh, 2
                   2423: set_dac_16_page:
                   2424:   and   bh, #0x0f
                   2425:   mov   al, bh
                   2426:   out   dx, al
                   2427: set_actl_normal:
                   2428:   mov   al, #0x20
                   2429:   out   dx, al
                   2430:   pop   dx
                   2431:   pop   bx
                   2432:   pop   ax
                   2433:   ret
                   2434: ASM_END
                   2435: 
                   2436: // --------------------------------------------------------------------------------------------
                   2437: ASM_START
                   2438: biosfn_read_single_dac_reg:
                   2439:   push  ax
                   2440:   push  dx
                   2441:   mov   dx, # VGAREG_DAC_READ_ADDRESS
                   2442:   mov   al, bl
                   2443:   out   dx, al
                   2444:   pop   ax
                   2445:   mov   ah, al
                   2446:   mov   dx, # VGAREG_DAC_DATA
                   2447:   in    al, dx
                   2448:   xchg  al, ah
                   2449:   push  ax
                   2450:   in    al, dx
                   2451:   mov   ch, al
                   2452:   in    al, dx
                   2453:   mov   cl, al
                   2454:   pop   dx
                   2455:   pop   ax
                   2456:   ret
                   2457: ASM_END
                   2458: 
                   2459: // --------------------------------------------------------------------------------------------
                   2460: ASM_START
                   2461: biosfn_read_all_dac_reg:
                   2462:   push  ax
                   2463:   push  bx
                   2464:   push  cx
                   2465:   push  dx
                   2466:   mov   dx, # VGAREG_DAC_READ_ADDRESS
                   2467:   mov   al, bl
                   2468:   out   dx, al
                   2469:   pop   dx
                   2470:   push  dx
                   2471:   mov   bx, dx
                   2472:   mov   dx, # VGAREG_DAC_DATA
                   2473: read_dac_loop:
                   2474:   in    al, dx
                   2475:   seg   es
                   2476:   mov   [bx], al
                   2477:   inc   bx
                   2478:   in    al, dx
                   2479:   seg   es
                   2480:   mov   [bx], al
                   2481:   inc   bx
                   2482:   in    al, dx
                   2483:   seg   es
                   2484:   mov   [bx], al
                   2485:   inc   bx
                   2486:   dec   cx
                   2487:   jnz   read_dac_loop
                   2488:   pop   dx
                   2489:   pop   cx
                   2490:   pop   bx
                   2491:   pop   ax
                   2492:   ret
                   2493: ASM_END
                   2494: 
                   2495: // --------------------------------------------------------------------------------------------
                   2496: ASM_START
                   2497: biosfn_set_pel_mask:
                   2498:   push  ax
                   2499:   push  dx
                   2500:   mov   dx, # VGAREG_PEL_MASK
                   2501:   mov   al, bl
                   2502:   out   dx, al
                   2503:   pop   dx
                   2504:   pop   ax
                   2505:   ret
                   2506: ASM_END
                   2507: 
                   2508: // --------------------------------------------------------------------------------------------
                   2509: ASM_START
                   2510: biosfn_read_pel_mask:
                   2511:   push  ax
                   2512:   push  dx
                   2513:   mov   dx, # VGAREG_PEL_MASK
                   2514:   in    al, dx
                   2515:   mov   bl, al
                   2516:   pop   dx
                   2517:   pop   ax
                   2518:   ret
                   2519: ASM_END
                   2520: 
                   2521: // --------------------------------------------------------------------------------------------
                   2522: ASM_START
                   2523: biosfn_read_video_dac_state:
                   2524:   push  ax
                   2525:   push  dx
                   2526:   mov   dx, # VGAREG_ACTL_RESET
                   2527:   in    al, dx
                   2528:   mov   dx, # VGAREG_ACTL_ADDRESS
                   2529:   mov   al, #0x10
                   2530:   out   dx, al
                   2531:   mov   dx, # VGAREG_ACTL_READ_DATA
                   2532:   in    al, dx
                   2533:   mov   bl, al
                   2534:   shr   bl, 7
                   2535:   mov   dx, # VGAREG_ACTL_RESET
                   2536:   in    al, dx
                   2537:   mov   dx, # VGAREG_ACTL_ADDRESS
                   2538:   mov   al, #0x14
                   2539:   out   dx, al
                   2540:   mov   dx, # VGAREG_ACTL_READ_DATA
                   2541:   in    al, dx
                   2542:   mov   bh, al
                   2543:   and   bh, #0x0f
                   2544:   test  bl, #0x01
                   2545:   jnz   get_dac_16_page
                   2546:   shr   bh, 2
                   2547: get_dac_16_page:
                   2548:   mov   dx, # VGAREG_ACTL_RESET
                   2549:   in    al, dx
                   2550:   mov   dx, # VGAREG_ACTL_ADDRESS
                   2551:   mov   al, #0x20
                   2552:   out   dx, al
                   2553:   pop   dx
                   2554:   pop   ax
                   2555:   ret
                   2556: ASM_END
                   2557: 
                   2558: // --------------------------------------------------------------------------------------------
                   2559: static void biosfn_perform_gray_scale_summing (start,count) 
                   2560: Bit16u start;Bit16u count;
                   2561: {Bit8u r,g,b;
                   2562:  Bit16u i;
                   2563:  Bit16u index;
                   2564: 
                   2565:  inb(VGAREG_ACTL_RESET);
                   2566:  outb(VGAREG_ACTL_ADDRESS,0x00);
                   2567: 
                   2568:  for( index = 0; index < count; index++ ) 
                   2569:   {
                   2570:    // set read address and switch to read mode
                   2571:    outb(VGAREG_DAC_READ_ADDRESS,start);
                   2572:    // get 6-bit wide RGB data values
                   2573:    r=inb( VGAREG_DAC_DATA );
                   2574:    g=inb( VGAREG_DAC_DATA );
                   2575:    b=inb( VGAREG_DAC_DATA );
                   2576: 
                   2577:    // intensity = ( 0.3 * Red ) + ( 0.59 * Green ) + ( 0.11 * Blue )
                   2578:    i = ( ( 77*r + 151*g + 28*b ) + 0x80 ) >> 8;
                   2579: 
                   2580:    if(i>0x3f)i=0x3f;
                   2581:  
                   2582:    // set write address and switch to write mode
                   2583:    outb(VGAREG_DAC_WRITE_ADDRESS,start);
                   2584:    // write new intensity value
                   2585:    outb( VGAREG_DAC_DATA, i&0xff );
                   2586:    outb( VGAREG_DAC_DATA, i&0xff );
                   2587:    outb( VGAREG_DAC_DATA, i&0xff );
                   2588:    start++;
                   2589:   }  
                   2590:  inb(VGAREG_ACTL_RESET);
                   2591:  outb(VGAREG_ACTL_ADDRESS,0x20);
                   2592: }
                   2593: 
                   2594: // --------------------------------------------------------------------------------------------
                   2595: static void get_font_access()
                   2596: {
                   2597: ASM_START
                   2598:  mov dx, # VGAREG_SEQU_ADDRESS
                   2599:  mov ax, #0x0100
                   2600:  out dx, ax
                   2601:  mov ax, #0x0402
                   2602:  out dx, ax
                   2603:  mov ax, #0x0704
                   2604:  out dx, ax
                   2605:  mov ax, #0x0300
                   2606:  out dx, ax
                   2607:  mov dx, # VGAREG_GRDC_ADDRESS
                   2608:  mov ax, #0x0204
                   2609:  out dx, ax
                   2610:  mov ax, #0x0005
                   2611:  out dx, ax
                   2612:  mov ax, #0x0406
                   2613:  out dx, ax
                   2614: ASM_END
                   2615: }
                   2616: 
                   2617: static void release_font_access()
                   2618: {
                   2619: ASM_START
                   2620:  mov dx, # VGAREG_SEQU_ADDRESS
                   2621:  mov ax, #0x0100
                   2622:  out dx, ax
                   2623:  mov ax, #0x0302
                   2624:  out dx, ax
                   2625:  mov ax, #0x0304
                   2626:  out dx, ax
                   2627:  mov ax, #0x0300
                   2628:  out dx, ax
                   2629:  mov dx, # VGAREG_READ_MISC_OUTPUT
                   2630:  in  al, dx
                   2631:  and al, #0x01
                   2632:  shl al, 2
                   2633:  or  al, #0x0a
                   2634:  mov ah, al
                   2635:  mov al, #0x06
                   2636:  mov dx, # VGAREG_GRDC_ADDRESS
                   2637:  out dx, ax
                   2638:  mov ax, #0x0004
                   2639:  out dx, ax
                   2640:  mov ax, #0x1005
                   2641:  out dx, ax
                   2642: ASM_END
                   2643: }
                   2644: 
                   2645: ASM_START
                   2646: idiv_u:
                   2647:   xor dx,dx
                   2648:   div bx
                   2649:   ret
                   2650: ASM_END
                   2651: 
                   2652: static void set_scan_lines(lines) Bit8u lines;
                   2653: {
                   2654:  Bit16u crtc_addr,cols,page,vde;
                   2655:  Bit8u crtc_r9,ovl,rows;
                   2656: 
                   2657:  crtc_addr = read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
                   2658:  outb(crtc_addr, 0x09);
                   2659:  crtc_r9 = inb(crtc_addr+1);
                   2660:  crtc_r9 = (crtc_r9 & 0xe0) | (lines - 1);
                   2661:  outb(crtc_addr+1, crtc_r9);
                   2662:  if(lines==8)
                   2663:   {
                   2664:    biosfn_set_cursor_shape(0x06,0x07);
                   2665:   }
                   2666:  else
                   2667:   {
                   2668:    biosfn_set_cursor_shape(lines-4,lines-3);
                   2669:   }
                   2670:  write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT, lines);
                   2671:  outb(crtc_addr, 0x12);
                   2672:  vde = inb(crtc_addr+1);
                   2673:  outb(crtc_addr, 0x07);
                   2674:  ovl = inb(crtc_addr+1);
                   2675:  vde += (((ovl & 0x02) << 7) + ((ovl & 0x40) << 3) + 1);
                   2676:  rows = vde / lines;
                   2677:  write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS, rows-1);
                   2678:  cols = read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
                   2679:  write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE, rows * cols * 2);
                   2680: }
                   2681: 
                   2682: static void biosfn_load_text_user_pat (AL,ES,BP,CX,DX,BL,BH) Bit8u AL;Bit16u ES;Bit16u BP;Bit16u CX;Bit16u DX;Bit8u BL;Bit8u BH;
                   2683: {
                   2684:  Bit16u blockaddr,dest,i,src;
                   2685: 
                   2686:  get_font_access();
                   2687:  blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
                   2688:  for(i=0;i<CX;i++)
                   2689:   {
                   2690:    src = BP + i * BH;
                   2691:    dest = blockaddr + (DX + i) * 32;
                   2692:    memcpyb(0xA000, dest, ES, src, BH);
                   2693:   }
                   2694:  release_font_access();
                   2695:  if(AL>=0x10)
                   2696:   {
                   2697:    set_scan_lines(BH);
                   2698:   }
                   2699: }
                   2700: 
                   2701: static void biosfn_load_text_8_14_pat (AL,BL) Bit8u AL;Bit8u BL;
                   2702: {
                   2703:  Bit16u blockaddr,dest,i,src;
                   2704: 
                   2705:  get_font_access();
                   2706:  blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
                   2707:  for(i=0;i<0x100;i++)
                   2708:   {
                   2709:    src = i * 14;
                   2710:    dest = blockaddr + i * 32;
                   2711:    memcpyb(0xA000, dest, 0xC000, vgafont14+src, 14);
                   2712:   }
                   2713:  release_font_access();
                   2714:  if(AL>=0x10)
                   2715:   {
                   2716:    set_scan_lines(14);
                   2717:   }
                   2718: }
                   2719: 
                   2720: static void biosfn_load_text_8_8_pat (AL,BL) Bit8u AL;Bit8u BL;
                   2721: {
                   2722:  Bit16u blockaddr,dest,i,src;
                   2723: 
                   2724:  get_font_access();
                   2725:  blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
                   2726:  for(i=0;i<0x100;i++)
                   2727:   {
                   2728:    src = i * 8;
                   2729:    dest = blockaddr + i * 32;
                   2730:    memcpyb(0xA000, dest, 0xC000, vgafont8+src, 8);
                   2731:   }
                   2732:  release_font_access();
                   2733:  if(AL>=0x10)
                   2734:   {
                   2735:    set_scan_lines(8);
                   2736:   }
                   2737: }
                   2738: 
                   2739: // --------------------------------------------------------------------------------------------
                   2740: ASM_START
                   2741: biosfn_set_text_block_specifier:
                   2742:   push  ax
                   2743:   push  dx
                   2744:   mov   dx, # VGAREG_SEQU_ADDRESS
                   2745:   mov   ah, bl
                   2746:   mov   al, #0x03
                   2747:   out   dx, ax
                   2748:   pop   dx
                   2749:   pop   ax
                   2750:   ret
                   2751: ASM_END
                   2752: 
                   2753: // --------------------------------------------------------------------------------------------
                   2754: static void biosfn_load_text_8_16_pat (AL,BL) Bit8u AL;Bit8u BL;
                   2755: {
                   2756:  Bit16u blockaddr,dest,i,src;
                   2757: 
                   2758:  get_font_access();
                   2759:  blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
                   2760:  for(i=0;i<0x100;i++)
                   2761:   {
                   2762:    src = i * 16;
                   2763:    dest = blockaddr + i * 32;
                   2764:    memcpyb(0xA000, dest, 0xC000, vgafont16+src, 16);
                   2765:   }
                   2766:  release_font_access();
                   2767:  if(AL>=0x10)
                   2768:   {
                   2769:    set_scan_lines(16);
                   2770:   }
                   2771: }
                   2772: 
                   2773: static void biosfn_load_gfx_8_8_chars (ES,BP) Bit16u ES;Bit16u BP;
                   2774: {
                   2775: #ifdef DEBUG
                   2776:  unimplemented();
                   2777: #endif
                   2778: }
                   2779: static void biosfn_load_gfx_user_chars (ES,BP,CX,BL,DL) Bit16u ES;Bit16u BP;Bit16u CX;Bit8u BL;Bit8u DL;
                   2780: {
                   2781: #ifdef DEBUG
                   2782:  unimplemented();
                   2783: #endif
                   2784: }
                   2785: static void biosfn_load_gfx_8_14_chars (BL) Bit8u BL;
                   2786: {
                   2787: #ifdef DEBUG
                   2788:  unimplemented();
                   2789: #endif
                   2790: }
                   2791: static void biosfn_load_gfx_8_8_dd_chars (BL) Bit8u BL;
                   2792: {
                   2793: #ifdef DEBUG
                   2794:  unimplemented();
                   2795: #endif
                   2796: }
                   2797: static void biosfn_load_gfx_8_16_chars (BL) Bit8u BL;
                   2798: {
                   2799: #ifdef DEBUG
                   2800:  unimplemented();
                   2801: #endif
                   2802: }
                   2803: // --------------------------------------------------------------------------------------------
                   2804: static void biosfn_get_font_info (BH,ES,BP,CX,DX) 
                   2805: Bit8u BH;Bit16u *ES;Bit16u *BP;Bit16u *CX;Bit16u *DX;
                   2806: {Bit16u ss=get_SS();
                   2807:  
                   2808:  switch(BH)
                   2809:   {case 0x00:
                   2810:     write_word(ss,ES,read_word(0x00,0x1f*4));
                   2811:     write_word(ss,BP,read_word(0x00,(0x1f*4)+2));
                   2812:     break;
                   2813:    case 0x01:
                   2814:     write_word(ss,ES,read_word(0x00,0x43*4));
                   2815:     write_word(ss,BP,read_word(0x00,(0x43*4)+2));
                   2816:     break;
                   2817:    case 0x02:
                   2818:     write_word(ss,ES,0xC000);
                   2819:     write_word(ss,BP,vgafont14);
                   2820:     break;
                   2821:    case 0x03:
                   2822:     write_word(ss,ES,0xC000);
                   2823:     write_word(ss,BP,vgafont8);
                   2824:     break;
                   2825:    case 0x04:
                   2826:     write_word(ss,ES,0xC000);
                   2827:     write_word(ss,BP,vgafont8+128*8);
                   2828:     break;
                   2829:    case 0x05:
                   2830:     write_word(ss,ES,0xC000);
                   2831:     write_word(ss,BP,vgafont14alt);
                   2832:     break;
                   2833:    case 0x06:
                   2834:     write_word(ss,ES,0xC000);
                   2835:     write_word(ss,BP,vgafont16);
                   2836:     break;
                   2837:    case 0x07:
                   2838:     write_word(ss,ES,0xC000);
                   2839:     write_word(ss,BP,vgafont16alt);
                   2840:     break;
                   2841:    default:
                   2842:     #ifdef DEBUG
                   2843:      printf("Get font info BH(%02x) was discarded\n",BH);
                   2844:     #endif
                   2845:     return;
                   2846:   }
                   2847:  // Set byte/char of on screen font
                   2848:  write_word(ss,CX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT));
                   2849: 
                   2850:  // Set Highest char row
                   2851:  write_word(ss,DX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS));
                   2852: }
                   2853: 
                   2854: // --------------------------------------------------------------------------------------------
                   2855: ASM_START
                   2856: biosfn_get_ega_info:
                   2857:   push  ds
                   2858:   push  ax
                   2859:   mov   ax, # BIOSMEM_SEG
                   2860:   mov   ds, ax
                   2861:   xor   ch, ch
                   2862:   mov   bx, # BIOSMEM_SWITCHES
                   2863:   mov   cl, [bx]
                   2864:   and   cl, #0x0f
                   2865:   mov   bx, # BIOSMEM_CRTC_ADDRESS
                   2866:   mov   ax, [bx]
                   2867:   mov   bx, #0x0003
                   2868:   cmp   ax, # VGAREG_MDA_CRTC_ADDRESS
                   2869:   jne   mode_ega_color
                   2870:   mov   bh, #0x01
                   2871: mode_ega_color:
                   2872:   pop   ax
                   2873:   pop   ds
                   2874:   ret
                   2875: ASM_END
                   2876: 
                   2877: // --------------------------------------------------------------------------------------------
                   2878: static void biosfn_alternate_prtsc()
                   2879: {
                   2880: #ifdef DEBUG
                   2881:  unimplemented();
                   2882: #endif
                   2883: }
                   2884: 
                   2885: // --------------------------------------------------------------------------------------------
                   2886: ASM_START
                   2887: biosfn_select_vert_res:
                   2888: 
                   2889: ; res : 00 200 lines, 01 350 lines, 02 400 lines
                   2890: 
                   2891:   push  ds
                   2892:   push  bx
                   2893:   push  dx
                   2894:   mov   dl, al
                   2895:   mov   ax, # BIOSMEM_SEG
                   2896:   mov   ds, ax
                   2897:   mov   bx, # BIOSMEM_MODESET_CTL
                   2898:   mov   al, [bx]
                   2899:   mov   bx, # BIOSMEM_SWITCHES
                   2900:   mov   ah, [bx]
                   2901:   cmp   dl, #0x01
                   2902:   je    vert_res_350
                   2903:   jb    vert_res_200
                   2904:   cmp   dl, #0x02
                   2905:   je    vert_res_400
                   2906: #ifdef DEBUG
                   2907:   mov   al, dl
                   2908:   xor   ah, ah
                   2909:   push  ax
                   2910:   mov   bx, #msg_vert_res
                   2911:   push  bx
                   2912:   call  _printf
                   2913:   add   sp, #4
                   2914: #endif
                   2915:   jmp   set_retcode
                   2916: vert_res_400:
                   2917: 
                   2918:   ; reset modeset ctl bit 7 and set bit 4
                   2919:   ; set switches bit 3-0 to 0x09
                   2920: 
                   2921:   and   al, #0x7f
                   2922:   or    al, #0x10
                   2923:   and   ah, #0xf0
                   2924:   or    ah, #0x09
                   2925:   jnz   set_vert_res
                   2926: vert_res_350:
                   2927: 
                   2928:   ; reset modeset ctl bit 7 and bit 4
                   2929:   ; set switches bit 3-0 to 0x09
                   2930: 
                   2931:   and   al, #0x6f
                   2932:   and   ah, #0xf0
                   2933:   or    ah, #0x09
                   2934:   jnz   set_vert_res
                   2935: vert_res_200:
                   2936: 
                   2937:   ; set modeset ctl bit 7 and reset bit 4
                   2938:   ; set switches bit 3-0 to 0x08
                   2939: 
                   2940:   and   al, #0xef
                   2941:   or    al, #0x80
                   2942:   and   ah, #0xf0
                   2943:   or    ah, #0x08
                   2944: set_vert_res:
                   2945:   mov   bx, # BIOSMEM_MODESET_CTL
                   2946:   mov   [bx], al
                   2947:   mov   bx, # BIOSMEM_SWITCHES
                   2948:   mov   [bx], ah
                   2949: set_retcode:
                   2950:   mov   ax, #0x1212
                   2951:   pop   dx
                   2952:   pop   bx
                   2953:   pop   ds
                   2954:   ret
                   2955: 
                   2956: #ifdef DEBUG
                   2957: msg_vert_res:
                   2958: .ascii "Select vert res (%02x) was discarded"
                   2959: .byte 0x0d,0x0a,0x00
                   2960: #endif
                   2961: 
                   2962: 
                   2963: biosfn_enable_default_palette_loading:
                   2964:   push  ds
                   2965:   push  bx
                   2966:   push  dx
                   2967:   mov   dl, al
                   2968:   and   dl, #0x01
                   2969:   shl   dl, 3
                   2970:   mov   ax, # BIOSMEM_SEG
                   2971:   mov   ds, ax
                   2972:   mov   bx, # BIOSMEM_MODESET_CTL
                   2973:   mov   al, [bx]
                   2974:   and   al, #0xf7
                   2975:   or    al, dl
                   2976:   mov   [bx], al
                   2977:   mov   ax, #0x1212
                   2978:   pop   dx
                   2979:   pop   bx
                   2980:   pop   ds
                   2981:   ret
                   2982: 
                   2983: 
                   2984: biosfn_enable_video_addressing:
                   2985:   push  bx
                   2986:   push  dx
                   2987:   mov   bl, al
                   2988:   and   bl, #0x01
                   2989:   xor   bl, #0x01
                   2990:   shl   bl, 1
                   2991:   mov   dx, # VGAREG_READ_MISC_OUTPUT
                   2992:   in    al, dx
                   2993:   and   al, #0xfd
                   2994:   or    al, bl
                   2995:   mov   dx, # VGAREG_WRITE_MISC_OUTPUT
                   2996:   out   dx, al
                   2997:   mov   ax, #0x1212
                   2998:   pop   dx
                   2999:   pop   bx
                   3000:   ret
                   3001: 
                   3002: 
                   3003: biosfn_enable_grayscale_summing:
                   3004:   push  ds
                   3005:   push  bx
                   3006:   push  dx
                   3007:   mov   dl, al
                   3008:   and   dl, #0x01
                   3009:   xor   dl, #0x01
                   3010:   shl   dl, 1
                   3011:   mov   ax, # BIOSMEM_SEG
                   3012:   mov   ds, ax
                   3013:   mov   bx, # BIOSMEM_MODESET_CTL
                   3014:   mov   al, [bx]
                   3015:   and   al, #0xfd
                   3016:   or    al, dl
                   3017:   mov   [bx], al
                   3018:   mov   ax, #0x1212
                   3019:   pop   dx
                   3020:   pop   bx
                   3021:   pop   ds
                   3022:   ret
                   3023: 
                   3024: 
                   3025: biosfn_enable_cursor_emulation:
                   3026:   push  ds
                   3027:   push  bx
                   3028:   push  dx
                   3029:   mov   dl, al
                   3030:   and   dl, #0x01
                   3031:   xor   dl, #0x01
                   3032:   mov   ax, # BIOSMEM_SEG
                   3033:   mov   ds, ax
                   3034:   mov   bx, # BIOSMEM_MODESET_CTL
                   3035:   mov   al, [bx]
                   3036:   and   al, #0xfe
                   3037:   or    al, dl
                   3038:   mov   [bx], al
                   3039:   mov   ax, #0x1212
                   3040:   pop   dx
                   3041:   pop   bx
                   3042:   pop   ds
                   3043:   ret
                   3044: ASM_END
                   3045: 
                   3046: // --------------------------------------------------------------------------------------------
                   3047: static void biosfn_switch_video_interface (AL,ES,DX) Bit8u AL;Bit16u ES;Bit16u DX;
                   3048: {
                   3049: #ifdef DEBUG
                   3050:  unimplemented();
                   3051: #endif
                   3052: }
                   3053: static void biosfn_enable_video_refresh_control (AL) Bit8u AL;
                   3054: {
                   3055: #ifdef DEBUG
                   3056:  unimplemented();
                   3057: #endif
                   3058: }
                   3059: 
                   3060: // --------------------------------------------------------------------------------------------
                   3061: static void biosfn_write_string (flag,page,attr,count,row,col,seg,offset) 
                   3062: Bit8u flag;Bit8u page;Bit8u attr;Bit16u count;Bit8u row;Bit8u col;Bit16u seg;Bit16u offset;
                   3063: {
                   3064:  Bit16u newcurs,oldcurs,dummy;
                   3065:  Bit8u car,carattr;
                   3066: 
                   3067:  // Read curs info for the page
                   3068:  biosfn_get_cursor_pos(page,&dummy,&oldcurs);
                   3069: 
                   3070:  // if row=0xff special case : use current cursor position
                   3071:  if(row==0xff)
                   3072:   {col=oldcurs&0x00ff;
                   3073:    row=(oldcurs&0xff00)>>8;
                   3074:   }
                   3075: 
                   3076:  newcurs=row; newcurs<<=8; newcurs+=col;
                   3077:  biosfn_set_cursor_pos(page,newcurs);
                   3078:  
                   3079:  while(count--!=0)
                   3080:   {
                   3081:    car=read_byte(seg,offset++);
                   3082:    if((flag&0x02)!=0)
                   3083:     attr=read_byte(seg,offset++);
                   3084: 
                   3085:    biosfn_write_teletype(car,page,attr,WITH_ATTR);
                   3086:   }
                   3087:  
                   3088:  // Set back curs pos 
                   3089:  if((flag&0x01)==0)
                   3090:   biosfn_set_cursor_pos(page,oldcurs);
                   3091: }
                   3092: 
                   3093: // --------------------------------------------------------------------------------------------
                   3094: ASM_START
                   3095: biosfn_group_1A:
                   3096:   cmp   al, #0x00
                   3097:   je    biosfn_read_display_code
                   3098:   cmp   al, #0x01
                   3099:   je    biosfn_set_display_code
                   3100: #ifdef DEBUG
                   3101:   call  _unknown
                   3102: #endif
                   3103:   ret
                   3104: biosfn_read_display_code:
                   3105:   push  ds
                   3106:   push  ax
                   3107:   mov   ax, # BIOSMEM_SEG
                   3108:   mov   ds, ax
                   3109:   mov   bx, # BIOSMEM_DCC_INDEX
                   3110:   mov   al, [bx]
                   3111:   mov   bl, al
                   3112:   xor   bh, bh
                   3113:   pop   ax
                   3114:   mov   al, ah
                   3115:   pop   ds
                   3116:   ret
                   3117: biosfn_set_display_code:
                   3118:   push  ds
                   3119:   push  ax
                   3120:   push  bx
                   3121:   mov   ax, # BIOSMEM_SEG
                   3122:   mov   ds, ax
                   3123:   mov   ax, bx
                   3124:   mov   bx, # BIOSMEM_DCC_INDEX
                   3125:   mov   [bx], al
                   3126: #ifdef DEBUG
                   3127:   mov   al, ah
                   3128:   xor   ah, ah
                   3129:   push  ax
                   3130:   mov   bx, #msg_alt_dcc
                   3131:   push  bx
                   3132:   call  _printf
                   3133:   add   sp, #4
                   3134: #endif
                   3135:   pop   bx
                   3136:   pop   ax
                   3137:   mov   al, ah
                   3138:   pop   ds
                   3139:   ret
                   3140: 
                   3141: #ifdef DEBUG
                   3142: msg_alt_dcc:
                   3143: .ascii "Alternate Display code (%02x) was discarded"
                   3144: .byte 0x0d,0x0a,0x00
                   3145: #endif
                   3146: ASM_END
                   3147: 
                   3148: // --------------------------------------------------------------------------------------------
                   3149: static void biosfn_read_state_info (BX,ES,DI) 
                   3150: Bit16u BX;Bit16u ES;Bit16u DI;
                   3151: {
                   3152:  // Address of static functionality table
                   3153:  write_word(ES,DI+0x00,&static_functionality);
                   3154:  write_word(ES,DI+0x02,0xC000);
                   3155: 
                   3156:  // Hard coded copy from BIOS area. Should it be cleaner ?
                   3157:  memcpyb(ES,DI+0x04,BIOSMEM_SEG,0x49,30);
                   3158:  memcpyb(ES,DI+0x22,BIOSMEM_SEG,0x84,3);
                   3159:  
                   3160:  write_byte(ES,DI+0x25,read_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX));
                   3161:  write_byte(ES,DI+0x26,0);
                   3162:  write_byte(ES,DI+0x27,16);
                   3163:  write_byte(ES,DI+0x28,0);
                   3164:  write_byte(ES,DI+0x29,8);
                   3165:  write_byte(ES,DI+0x2a,2);
                   3166:  write_byte(ES,DI+0x2b,0);
                   3167:  write_byte(ES,DI+0x2c,0);
                   3168:  write_byte(ES,DI+0x31,3);
                   3169:  write_byte(ES,DI+0x32,0);
                   3170:  
                   3171:  memsetb(ES,DI+0x33,0,13);
                   3172: }
                   3173: 
                   3174: // --------------------------------------------------------------------------------------------
                   3175: // --------------------------------------------------------------------------------------------
                   3176: static Bit16u biosfn_read_video_state_size2 (CX) 
                   3177:      Bit16u CX;
                   3178: {
                   3179:     Bit16u size;
                   3180:     size = 0;
                   3181:     if (CX & 1) {
                   3182:         size += 0x46;
                   3183:     }
                   3184:     if (CX & 2) {
                   3185:         size += (5 + 8 + 5) * 2 + 6;
                   3186:     }
                   3187:     if (CX & 4) {
                   3188:         size += 3 + 256 * 3 + 1;
                   3189: }
                   3190:     return size;
                   3191: }
                   3192: 
                   3193: static void biosfn_read_video_state_size (CX, BX) 
                   3194:      Bit16u CX; Bit16u *BX;
                   3195: {
                   3196:     Bit16u ss=get_SS();
                   3197:     write_word(ss, BX, biosfn_read_video_state_size2(CX));
                   3198: }
                   3199: 
                   3200: static Bit16u biosfn_save_video_state (CX,ES,BX) 
                   3201:      Bit16u CX;Bit16u ES;Bit16u BX;
                   3202: {
                   3203:     Bit16u i, v, crtc_addr, ar_index;
                   3204: 
                   3205:     crtc_addr = read_word(BIOSMEM_SEG, BIOSMEM_CRTC_ADDRESS);
                   3206:     if (CX & 1) {
                   3207:         write_byte(ES, BX, inb(VGAREG_SEQU_ADDRESS)); BX++;
                   3208:         write_byte(ES, BX, inb(crtc_addr)); BX++;
                   3209:         write_byte(ES, BX, inb(VGAREG_GRDC_ADDRESS)); BX++;
                   3210:         inb(VGAREG_ACTL_RESET);
                   3211:         ar_index = inb(VGAREG_ACTL_ADDRESS);
                   3212:         write_byte(ES, BX, ar_index); BX++;
                   3213:         write_byte(ES, BX, inb(VGAREG_READ_FEATURE_CTL)); BX++;
                   3214: 
                   3215:         for(i=1;i<=4;i++){
                   3216:             outb(VGAREG_SEQU_ADDRESS, i);
                   3217:             write_byte(ES, BX, inb(VGAREG_SEQU_DATA)); BX++;
                   3218:         }
                   3219:         outb(VGAREG_SEQU_ADDRESS, 0);
                   3220:         write_byte(ES, BX, inb(VGAREG_SEQU_DATA)); BX++;
                   3221: 
                   3222:         for(i=0;i<=0x18;i++) {
                   3223:             outb(crtc_addr,i);
                   3224:             write_byte(ES, BX, inb(crtc_addr+1)); BX++;
                   3225:         }
                   3226: 
                   3227:         for(i=0;i<=0x13;i++) {
                   3228:             inb(VGAREG_ACTL_RESET);
                   3229:             outb(VGAREG_ACTL_ADDRESS, i | (ar_index & 0x20));
                   3230:             write_byte(ES, BX, inb(VGAREG_ACTL_READ_DATA)); BX++;
                   3231:         }
                   3232:         inb(VGAREG_ACTL_RESET);
                   3233: 
                   3234:         for(i=0;i<=8;i++) {
                   3235:             outb(VGAREG_GRDC_ADDRESS,i);
                   3236:             write_byte(ES, BX, inb(VGAREG_GRDC_DATA)); BX++;
                   3237:         }
                   3238: 
                   3239:         write_word(ES, BX, crtc_addr); BX+= 2;
                   3240: 
                   3241:         /* XXX: read plane latches */
                   3242:         write_byte(ES, BX, 0); BX++;
                   3243:         write_byte(ES, BX, 0); BX++;
                   3244:         write_byte(ES, BX, 0); BX++;
                   3245:         write_byte(ES, BX, 0); BX++;
                   3246:     }
                   3247:     if (CX & 2) {
                   3248:         write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE)); BX++;
                   3249:         write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)); BX += 2;
                   3250:         write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE)); BX += 2;
                   3251:         write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)); BX += 2;
                   3252:         write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)); BX++;
                   3253:         write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT)); BX += 2;
                   3254:         write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL)); BX++;
                   3255:         write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES)); BX++;
                   3256:         write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)); BX++;
                   3257:         write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE)); BX += 2;
                   3258:         for(i=0;i<8;i++) {
                   3259:             write_word(ES, BX, read_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*i));
                   3260:             BX += 2;
                   3261:         }
                   3262:         write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START)); BX += 2;
                   3263:         write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE)); BX++;
                   3264:         /* current font */
                   3265:         write_word(ES, BX, read_word(0, 0x1f * 4)); BX += 2;
                   3266:         write_word(ES, BX, read_word(0, 0x1f * 4 + 2)); BX += 2;
                   3267:         write_word(ES, BX, read_word(0, 0x43 * 4)); BX += 2;
                   3268:         write_word(ES, BX, read_word(0, 0x43 * 4 + 2)); BX += 2;
                   3269:     }
                   3270:     if (CX & 4) {
                   3271:         /* XXX: check this */
                   3272:         write_byte(ES, BX, inb(VGAREG_DAC_STATE)); BX++; /* read/write mode dac */
                   3273:         write_byte(ES, BX, inb(VGAREG_DAC_WRITE_ADDRESS)); BX++; /* pix address */
                   3274:         write_byte(ES, BX, inb(VGAREG_PEL_MASK)); BX++;
                   3275:         // Set the whole dac always, from 0
                   3276:         outb(VGAREG_DAC_WRITE_ADDRESS,0x00);
                   3277:         for(i=0;i<256*3;i++) {
                   3278:             write_byte(ES, BX, inb(VGAREG_DAC_DATA)); BX++;
                   3279:         }
                   3280:         write_byte(ES, BX, 0); BX++; /* color select register */
                   3281:     }
                   3282:     return BX;
                   3283: }
                   3284: 
                   3285: static Bit16u biosfn_restore_video_state (CX,ES,BX) 
                   3286:      Bit16u CX;Bit16u ES;Bit16u BX;
                   3287: {
                   3288:     Bit16u i, crtc_addr, v, addr1, ar_index;
                   3289: 
                   3290:     if (CX & 1) {
                   3291:         // Reset Attribute Ctl flip-flop
                   3292:         inb(VGAREG_ACTL_RESET);
                   3293: 
                   3294:         crtc_addr = read_word(ES, BX + 0x40);
                   3295:         addr1 = BX;
                   3296:         BX += 5;
                   3297:         
                   3298:         for(i=1;i<=4;i++){
                   3299:             outb(VGAREG_SEQU_ADDRESS, i);
                   3300:             outb(VGAREG_SEQU_DATA, read_byte(ES, BX)); BX++;
                   3301:         }
                   3302:         outb(VGAREG_SEQU_ADDRESS, 0);
                   3303:         outb(VGAREG_SEQU_DATA, read_byte(ES, BX)); BX++;
                   3304: 
                   3305:         // Disable CRTC write protection
                   3306:         outw(crtc_addr,0x0011);
                   3307:         // Set CRTC regs
                   3308:         for(i=0;i<=0x18;i++) {
                   3309:             if (i != 0x11) {
                   3310:                 outb(crtc_addr,i);
                   3311:                 outb(crtc_addr+1, read_byte(ES, BX));
                   3312:             }
                   3313:             BX++;
                   3314:         }
                   3315:         // select crtc base address
                   3316:         v = inb(VGAREG_READ_MISC_OUTPUT) & ~0x01;
                   3317:         if (crtc_addr = 0x3d4)
                   3318:             v |= 0x01;
                   3319:         outb(VGAREG_WRITE_MISC_OUTPUT, v);
                   3320: 
                   3321:         // enable write protection if needed
                   3322:         outb(crtc_addr, 0x11);
                   3323:         outb(crtc_addr+1, read_byte(ES, BX - 0x18 + 0x11));
                   3324:         
                   3325:         // Set Attribute Ctl
                   3326:         ar_index = read_byte(ES, addr1 + 0x03);
                   3327:         inb(VGAREG_ACTL_RESET);
                   3328:         for(i=0;i<=0x13;i++) {
                   3329:             outb(VGAREG_ACTL_ADDRESS, i | (ar_index & 0x20));
                   3330:             outb(VGAREG_ACTL_WRITE_DATA, read_byte(ES, BX)); BX++;
                   3331:         }
                   3332:         outb(VGAREG_ACTL_ADDRESS, ar_index);
                   3333:         inb(VGAREG_ACTL_RESET);
                   3334:         
                   3335:         for(i=0;i<=8;i++) {
                   3336:             outb(VGAREG_GRDC_ADDRESS,i);
                   3337:             outb(VGAREG_GRDC_DATA, read_byte(ES, BX)); BX++;
                   3338:         }
                   3339:         BX += 2; /* crtc_addr */
                   3340:         BX += 4; /* plane latches */
                   3341:         
                   3342:         outb(VGAREG_SEQU_ADDRESS, read_byte(ES, addr1)); addr1++;
                   3343:         outb(crtc_addr, read_byte(ES, addr1)); addr1++;
                   3344:         outb(VGAREG_GRDC_ADDRESS, read_byte(ES, addr1)); addr1++;
                   3345:         addr1++;
                   3346:         outb(crtc_addr - 0x4 + 0xa, read_byte(ES, addr1)); addr1++;
                   3347:     }
                   3348:     if (CX & 2) {
                   3349:         write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE, read_byte(ES, BX)); BX++;
                   3350:         write_word(BIOSMEM_SEG,BIOSMEM_NB_COLS, read_word(ES, BX)); BX += 2;
                   3351:         write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE, read_word(ES, BX)); BX += 2;
                   3352:         write_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS, read_word(ES, BX)); BX += 2;
                   3353:         write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS, read_byte(ES, BX)); BX++;
                   3354:         write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT, read_word(ES, BX)); BX += 2;
                   3355:         write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL, read_byte(ES, BX)); BX++;
                   3356:         write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES, read_byte(ES, BX)); BX++;
                   3357:         write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL, read_byte(ES, BX)); BX++;
                   3358:         write_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE, read_word(ES, BX)); BX += 2;
                   3359:         for(i=0;i<8;i++) {
                   3360:             write_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*i, read_word(ES, BX));
                   3361:             BX += 2;
                   3362:         }
                   3363:         write_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START, read_word(ES, BX)); BX += 2;
                   3364:         write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE, read_byte(ES, BX)); BX++;
                   3365:         /* current font */
                   3366:         write_word(0, 0x1f * 4, read_word(ES, BX)); BX += 2;
                   3367:         write_word(0, 0x1f * 4 + 2, read_word(ES, BX)); BX += 2;
                   3368:         write_word(0, 0x43 * 4, read_word(ES, BX)); BX += 2;
                   3369:         write_word(0, 0x43 * 4 + 2, read_word(ES, BX)); BX += 2;
                   3370:     }
                   3371:     if (CX & 4) {
                   3372:         BX++;
                   3373:         v = read_byte(ES, BX); BX++;
                   3374:         outb(VGAREG_PEL_MASK, read_byte(ES, BX)); BX++;
                   3375:         // Set the whole dac always, from 0
                   3376:         outb(VGAREG_DAC_WRITE_ADDRESS,0x00);
                   3377:         for(i=0;i<256*3;i++) {
                   3378:             outb(VGAREG_DAC_DATA, read_byte(ES, BX)); BX++;
                   3379:         }
                   3380:         BX++;
                   3381:         outb(VGAREG_DAC_WRITE_ADDRESS, v);
                   3382:     }
                   3383:     return BX;
                   3384: }
                   3385: 
                   3386: // ============================================================================================
                   3387: //
                   3388: // Video Utils
                   3389: //
                   3390: // ============================================================================================
                   3391:  
                   3392: // --------------------------------------------------------------------------------------------
                   3393: static Bit8u find_vga_entry(mode) 
                   3394: Bit8u mode;
                   3395: {
                   3396:  Bit8u i,line=0xFF;
                   3397:  for(i=0;i<=MODE_MAX;i++)
                   3398:   if(vga_modes[i].svgamode==mode)
                   3399:    {line=i;
                   3400:     break;
                   3401:    }
                   3402:  return line;
                   3403: }
                   3404: 
                   3405: /* =========================================================== */
                   3406: /*
                   3407:  * Misc Utils
                   3408: */
                   3409: /* =========================================================== */
                   3410: 
                   3411: // --------------------------------------------------------------------------------------------
                   3412: static void memsetb(seg,offset,value,count)
                   3413:   Bit16u seg;
                   3414:   Bit16u offset;
                   3415:   Bit16u value;
                   3416:   Bit16u count;
                   3417: {
                   3418: ASM_START
                   3419:   push bp
                   3420:   mov  bp, sp
                   3421: 
                   3422:     push ax
                   3423:     push cx
                   3424:     push es
                   3425:     push di
                   3426: 
                   3427:     mov  cx, 10[bp] ; count
                   3428:     cmp  cx, #0x00
                   3429:     je   memsetb_end
                   3430:     mov  ax, 4[bp] ; segment
                   3431:     mov  es, ax
                   3432:     mov  ax, 6[bp] ; offset
                   3433:     mov  di, ax
                   3434:     mov  al, 8[bp] ; value
                   3435:     cld
                   3436:     rep
                   3437:      stosb
                   3438: 
                   3439: memsetb_end:
                   3440:     pop di
                   3441:     pop es
                   3442:     pop cx
                   3443:     pop ax
                   3444: 
                   3445:   pop bp
                   3446: ASM_END
                   3447: }
                   3448: 
                   3449: // --------------------------------------------------------------------------------------------
                   3450: static void memsetw(seg,offset,value,count)
                   3451:   Bit16u seg;
                   3452:   Bit16u offset;
                   3453:   Bit16u value;
                   3454:   Bit16u count;
                   3455: {
                   3456: ASM_START
                   3457:   push bp
                   3458:   mov  bp, sp
                   3459: 
                   3460:     push ax
                   3461:     push cx
                   3462:     push es
                   3463:     push di
                   3464: 
                   3465:     mov  cx, 10[bp] ; count
                   3466:     cmp  cx, #0x00
                   3467:     je   memsetw_end
                   3468:     mov  ax, 4[bp] ; segment
                   3469:     mov  es, ax
                   3470:     mov  ax, 6[bp] ; offset
                   3471:     mov  di, ax
                   3472:     mov  ax, 8[bp] ; value
                   3473:     cld
                   3474:     rep
                   3475:      stosw
                   3476: 
                   3477: memsetw_end:
                   3478:     pop di
                   3479:     pop es
                   3480:     pop cx
                   3481:     pop ax
                   3482: 
                   3483:   pop bp
                   3484: ASM_END
                   3485: }
                   3486: 
                   3487: // --------------------------------------------------------------------------------------------
                   3488: static void memcpyb(dseg,doffset,sseg,soffset,count)
                   3489:   Bit16u dseg;
                   3490:   Bit16u doffset;
                   3491:   Bit16u sseg;
                   3492:   Bit16u soffset;
                   3493:   Bit16u count;
                   3494: {
                   3495: ASM_START
                   3496:   push bp
                   3497:   mov  bp, sp
                   3498: 
                   3499:     push ax
                   3500:     push cx
                   3501:     push es
                   3502:     push di
                   3503:     push ds
                   3504:     push si
                   3505: 
                   3506:     mov  cx, 12[bp] ; count
                   3507:     cmp  cx, #0x0000
                   3508:     je   memcpyb_end
                   3509:     mov  ax, 4[bp] ; dsegment
                   3510:     mov  es, ax
                   3511:     mov  ax, 6[bp] ; doffset
                   3512:     mov  di, ax
                   3513:     mov  ax, 8[bp] ; ssegment
                   3514:     mov  ds, ax
                   3515:     mov  ax, 10[bp] ; soffset
                   3516:     mov  si, ax
                   3517:     cld
                   3518:     rep
                   3519:      movsb
                   3520: 
                   3521: memcpyb_end:
                   3522:     pop si
                   3523:     pop ds
                   3524:     pop di
                   3525:     pop es
                   3526:     pop cx
                   3527:     pop ax
                   3528: 
                   3529:   pop bp
                   3530: ASM_END
                   3531: }
                   3532: 
                   3533: // --------------------------------------------------------------------------------------------
                   3534: static void memcpyw(dseg,doffset,sseg,soffset,count)
                   3535:   Bit16u dseg;
                   3536:   Bit16u doffset;
                   3537:   Bit16u sseg;
                   3538:   Bit16u soffset;
                   3539:   Bit16u count;
                   3540: {
                   3541: ASM_START
                   3542:   push bp
                   3543:   mov  bp, sp
                   3544: 
                   3545:     push ax
                   3546:     push cx
                   3547:     push es
                   3548:     push di
                   3549:     push ds
                   3550:     push si
                   3551: 
                   3552:     mov  cx, 12[bp] ; count
                   3553:     cmp  cx, #0x0000
                   3554:     je   memcpyw_end
                   3555:     mov  ax, 4[bp] ; dsegment
                   3556:     mov  es, ax
                   3557:     mov  ax, 6[bp] ; doffset
                   3558:     mov  di, ax
                   3559:     mov  ax, 8[bp] ; ssegment
                   3560:     mov  ds, ax
                   3561:     mov  ax, 10[bp] ; soffset
                   3562:     mov  si, ax
                   3563:     cld
                   3564:     rep
                   3565:      movsw
                   3566: 
                   3567: memcpyw_end:
                   3568:     pop si
                   3569:     pop ds
                   3570:     pop di
                   3571:     pop es
                   3572:     pop cx
                   3573:     pop ax
                   3574: 
                   3575:   pop bp
                   3576: ASM_END
                   3577: }
                   3578: 
                   3579: /* =========================================================== */
                   3580: /*
                   3581:  * These functions where ripped from Kevin's rombios.c
                   3582: */
                   3583: /* =========================================================== */
                   3584: 
                   3585: // --------------------------------------------------------------------------------------------
                   3586: static Bit8u
                   3587: read_byte(seg, offset)
                   3588:   Bit16u seg;
                   3589:   Bit16u offset;
                   3590: {
                   3591: ASM_START
                   3592:   push bp
                   3593:   mov  bp, sp
                   3594: 
                   3595:     push bx
                   3596:     push ds
                   3597:     mov  ax, 4[bp] ; segment
                   3598:     mov  ds, ax
                   3599:     mov  bx, 6[bp] ; offset
                   3600:     mov  al, [bx]
                   3601:     ;; al = return value (byte)
                   3602:     pop  ds
                   3603:     pop  bx
                   3604: 
                   3605:   pop  bp
                   3606: ASM_END
                   3607: }
                   3608: 
                   3609: // --------------------------------------------------------------------------------------------
                   3610: static Bit16u
                   3611: read_word(seg, offset)
                   3612:   Bit16u seg;
                   3613:   Bit16u offset;
                   3614: {
                   3615: ASM_START
                   3616:   push bp
                   3617:   mov  bp, sp
                   3618: 
                   3619:     push bx
                   3620:     push ds
                   3621:     mov  ax, 4[bp] ; segment
                   3622:     mov  ds, ax
                   3623:     mov  bx, 6[bp] ; offset
                   3624:     mov  ax, [bx]
                   3625:     ;; ax = return value (word)
                   3626:     pop  ds
                   3627:     pop  bx
                   3628: 
                   3629:   pop  bp
                   3630: ASM_END
                   3631: }
                   3632: 
                   3633: // --------------------------------------------------------------------------------------------
                   3634: static void
                   3635: write_byte(seg, offset, data)
                   3636:   Bit16u seg;
                   3637:   Bit16u offset;
                   3638:   Bit8u  data;
                   3639: {
                   3640: ASM_START
                   3641:   push bp
                   3642:   mov  bp, sp
                   3643: 
                   3644:     push ax
                   3645:     push bx
                   3646:     push ds
                   3647:     mov  ax, 4[bp] ; segment
                   3648:     mov  ds, ax
                   3649:     mov  bx, 6[bp] ; offset
                   3650:     mov  al, 8[bp] ; data byte
                   3651:     mov  [bx], al  ; write data byte
                   3652:     pop  ds
                   3653:     pop  bx
                   3654:     pop  ax
                   3655: 
                   3656:   pop  bp
                   3657: ASM_END
                   3658: }
                   3659: 
                   3660: // --------------------------------------------------------------------------------------------
                   3661: static void
                   3662: write_word(seg, offset, data)
                   3663:   Bit16u seg;
                   3664:   Bit16u offset;
                   3665:   Bit16u data;
                   3666: {
                   3667: ASM_START
                   3668:   push bp
                   3669:   mov  bp, sp
                   3670: 
                   3671:     push ax
                   3672:     push bx
                   3673:     push ds
                   3674:     mov  ax, 4[bp] ; segment
                   3675:     mov  ds, ax
                   3676:     mov  bx, 6[bp] ; offset
                   3677:     mov  ax, 8[bp] ; data word
                   3678:     mov  [bx], ax  ; write data word
                   3679:     pop  ds
                   3680:     pop  bx
                   3681:     pop  ax
                   3682: 
                   3683:   pop  bp
                   3684: ASM_END
                   3685: }
                   3686: 
                   3687: // --------------------------------------------------------------------------------------------
                   3688:  Bit8u
                   3689: inb(port)
                   3690:   Bit16u port;
                   3691: {
                   3692: ASM_START
                   3693:   push bp
                   3694:   mov  bp, sp
                   3695: 
                   3696:     push dx
                   3697:     mov  dx, 4[bp]
                   3698:     in   al, dx
                   3699:     pop  dx
                   3700: 
                   3701:   pop  bp
                   3702: ASM_END
                   3703: }
                   3704: 
                   3705:   Bit16u
                   3706: inw(port)
                   3707:   Bit16u port;
                   3708: {
                   3709: ASM_START
                   3710:   push bp
                   3711:   mov  bp, sp
                   3712: 
                   3713:     push dx
                   3714:     mov  dx, 4[bp]
                   3715:     in   ax, dx
                   3716:     pop  dx
                   3717: 
                   3718:   pop  bp
                   3719: ASM_END
                   3720: }
                   3721: 
                   3722: // --------------------------------------------------------------------------------------------
                   3723:   void
                   3724: outb(port, val)
                   3725:   Bit16u port;
                   3726:   Bit8u  val;
                   3727: {
                   3728: ASM_START
                   3729:   push bp
                   3730:   mov  bp, sp
                   3731: 
                   3732:     push ax
                   3733:     push dx
                   3734:     mov  dx, 4[bp]
                   3735:     mov  al, 6[bp]
                   3736:     out  dx, al
                   3737:     pop  dx
                   3738:     pop  ax
                   3739: 
                   3740:   pop  bp
                   3741: ASM_END
                   3742: }
                   3743: 
                   3744: // --------------------------------------------------------------------------------------------
                   3745:   void
                   3746: outw(port, val)
                   3747:   Bit16u port;
                   3748:   Bit16u  val;
                   3749: {
                   3750: ASM_START
                   3751:   push bp
                   3752:   mov  bp, sp
                   3753: 
                   3754:     push ax
                   3755:     push dx
                   3756:     mov  dx, 4[bp]
                   3757:     mov  ax, 6[bp]
                   3758:     out  dx, ax
                   3759:     pop  dx
                   3760:     pop  ax
                   3761: 
                   3762:   pop  bp
                   3763: ASM_END
                   3764: }
                   3765: 
                   3766: Bit16u get_SS()
                   3767: {
                   3768: ASM_START
                   3769:   mov  ax, ss
                   3770: ASM_END
                   3771: }
                   3772: 
                   3773: #ifdef DEBUG
                   3774: void unimplemented()
                   3775: {
                   3776:  printf("--> Unimplemented\n");
                   3777: }
                   3778: 
                   3779: void unknown()
                   3780: {
                   3781:  printf("--> Unknown int10\n");
                   3782: }
                   3783: #endif
                   3784: 
                   3785: // --------------------------------------------------------------------------------------------
                   3786: #if defined(USE_BX_INFO) || defined(DEBUG) || defined(CIRRUS_DEBUG)
                   3787: void printf(s)
                   3788:   Bit8u *s;
                   3789: {
                   3790:   Bit8u c, format_char;
                   3791:   Boolean  in_format;
                   3792:   unsigned format_width, i;
                   3793:   Bit16u  *arg_ptr;
                   3794:   Bit16u   arg_seg, arg, digit, nibble, shift_count;
                   3795: 
                   3796:   arg_ptr = &s;
                   3797:   arg_seg = get_SS();
                   3798: 
                   3799:   in_format = 0;
                   3800:   format_width = 0;
                   3801: 
                   3802:   while (c = read_byte(0xc000, s)) {
                   3803:     if ( c == '%' ) {
                   3804:       in_format = 1;
                   3805:       format_width = 0;
                   3806:       }
                   3807:     else if (in_format) {
                   3808:       if ( (c>='0') && (c<='9') ) {
                   3809:         format_width = (format_width * 10) + (c - '0');
                   3810:         }
                   3811:       else if (c == 'x') {
                   3812:         arg_ptr++; // increment to next arg
                   3813:         arg = read_word(arg_seg, arg_ptr);
                   3814:         if (format_width == 0)
                   3815:           format_width = 4;
                   3816:         i = 0;
                   3817:         digit = format_width - 1;
                   3818:         for (i=0; i<format_width; i++) {
                   3819:           nibble = (arg >> (4 * digit)) & 0x000f;
                   3820:           if (nibble <= 9)
                   3821:             outb(0x0500, nibble + '0');
                   3822:           else
                   3823:             outb(0x0500, (nibble - 10) + 'A');
                   3824:           digit--;
                   3825:           }
                   3826:         in_format = 0;
                   3827:         }
                   3828:       //else if (c == 'd') {
                   3829:       //  in_format = 0;
                   3830:       //  }
                   3831:       }
                   3832:     else {
                   3833:       outb(0x0500, c);
                   3834:       }
                   3835:     s ++;
                   3836:     }
                   3837: }
                   3838: #endif
                   3839: 
1.1.1.2 ! root     3840: ASM_START
        !          3841:   ; get LFB address from PCI
        !          3842:   ; in - ax: PCI device vendor
        !          3843:   ; out - ax: LFB address (high 16 bit)
        !          3844:   ;; NOTE - may be called in protected mode
        !          3845: _pci_get_lfb_addr:
        !          3846:   push bx
        !          3847:   push cx
        !          3848:   push dx
        !          3849:   push eax
        !          3850:     mov bx, ax
        !          3851:     xor cx, cx
        !          3852:     mov dl, #0x00
        !          3853:     call pci_read_reg
        !          3854:     cmp ax, #0xffff
        !          3855:     jz pci_get_lfb_addr_fail
        !          3856:  pci_get_lfb_addr_next_dev:
        !          3857:     mov dl, #0x00
        !          3858:     call pci_read_reg
        !          3859:     cmp ax, bx ;; check vendor
        !          3860:     jz pci_get_lfb_addr_found
        !          3861:     add cx, #0x8
        !          3862:     cmp cx, #0x200 ;; search bus #0 and #1
        !          3863:     jb pci_get_lfb_addr_next_dev
        !          3864:  pci_get_lfb_addr_fail:
        !          3865:     xor dx, dx ;; no LFB
        !          3866:     jmp pci_get_lfb_addr_return
        !          3867:  pci_get_lfb_addr_found:
        !          3868:     mov dl, #0x10 ;; I/O space #0
        !          3869:     call pci_read_reg
        !          3870:     test ax, #0xfff1
        !          3871:     jz pci_get_lfb_addr_success
        !          3872:     mov dl, #0x14 ;; I/O space #1
        !          3873:     call pci_read_reg
        !          3874:     test ax, #0xfff1
        !          3875:     jnz pci_get_lfb_addr_fail
        !          3876:  pci_get_lfb_addr_success:
        !          3877:     shr eax, #16
        !          3878:     mov dx, ax ;; LFB address
        !          3879:  pci_get_lfb_addr_return:
        !          3880:   pop eax
        !          3881:   mov ax, dx
        !          3882:   pop dx
        !          3883:   pop cx
        !          3884:   pop bx
        !          3885:   ret
        !          3886: 
        !          3887:   ; read PCI register
        !          3888:   ; in - cx: device/function
        !          3889:   ; in - dl: register
        !          3890:   ; out - eax: value
        !          3891: pci_read_reg:
        !          3892:   mov eax, #0x00800000
        !          3893:   mov ax, cx
        !          3894:   shl eax, #8
        !          3895:   mov al, dl
        !          3896:   mov dx, #0xcf8
        !          3897:   out dx, eax
        !          3898:   add dl, #4
        !          3899:   in  eax, dx
        !          3900:   ret
        !          3901: ASM_END
        !          3902: 
1.1       root     3903: #ifdef VBE
                   3904: #include "vbe.c"
                   3905: #endif
                   3906: 
                   3907: #ifdef CIRRUS
                   3908: #include "clext.c"
                   3909: #endif
                   3910: 
                   3911: // --------------------------------------------------------------------------------------------
                   3912: 
                   3913: ASM_START 
                   3914: ;; DATA_SEG_DEFS_HERE
                   3915: ASM_END
                   3916: 
                   3917: ASM_START
                   3918: .ascii "vgabios ends here"
                   3919: .byte  0x00
                   3920: vgabios_end:
                   3921: .byte 0xCB
                   3922: ;; BLOCK_STRINGS_BEGIN
                   3923: ASM_END

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.