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

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

unix.superglobalmegacorp.com

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