Annotation of qemu/roms/vgabios/vgabios.c, revision 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.