Instead of hooking INT 10 via INT 80 do this:
Put your ROM at C000:8000. Make C000:8003 just contain a RETF.
Read 3 bytes from C000:3.
Patch C000:3 with a JUMP to C000:c004.
Make C000:c004 do a far call to the target of the old C000:3
instruction. Then _replace_ interrupt 10h with your handler, _without_
worrying about backing it up.

Now make your handler generate INT 6Dh to call the "old" handler.

Why will this work? Because all 100^ VGA-compatible BIOSes must hook INT
10 and INT 6D and make them _both_ go to the same place. Since INT 10 is
what gets called by programs, we can simply hook that. Elpin's BIOS
isn't 100% compatible and instead of making INT 10 and INT 6D go to the
same handler, they made INT 10 go to code that does INT 6Dh and then
IRETs.

Thus instead of backing up the old INT 10 handler at INT 80, which can
interfer with some programs that use INT 80 too, do what I have
described above.

Now, here's how to find the target of the jump at C000:3:

the first byte will be either EBh or E9h. Those are JUMP instructions.
If it's EBh, the next byte is the target of the jump (its offset),
_AFTER_ the offset of the next instruction.

Thus if C000:3 contains EB 3B, the target of the jump is: 3B + 3 + 2, or
40. The 3 is the offset of the jump instruction and the 2 is the length
of it.

E9h is a jump instruction too that is allowed to be at offset 3. But the
instruction at offset 3 must be one or the other jump (if the BIOS is
VGA compatible).

What if it's E9h? Then get the next word (2-bytes, x86 endian).

Add 3 + 3 to that (still located at C000:3, but its length is now 6
bytes).

Thus if the bytes at C000:3 were E9 FA 00 then C000:3 jumps to offset
100.

So you need to write a program that reads the old VGA BIOS, reads the
first three bytes at offset 3 in the old VGA BIOS, _patches_ offset 3
with E9 FE BF (a jump to C000:C004), and then appends your VESA
extension ROM.

Your VESA extension ROM will have an origin of C004h. Its code segment
will be C000h.

You can change C004h to 8004h if you like; whatever.

But make it so that when the BIOS initializes the ROM, it doesn't do
anything. Instead make it so that when the VGA BIOS gets intialized, it
initializes your VESA extension.

Why is this necessary? Programs (including DOSEMU) expect to be able to
call C000:3 and _NOT_ any other ROMs to initialize the video subsystem.
This is only true if you do what I have said above; also requiring the
use of INT 80 (or any other INT) is won't be IBM VGA compatible and
hence won't work with, for example, a Windows DOS box.

I guess I can through some code together. Lemme know... if I must...

Jeroen Janssen wrote:
> 
> Don't know if anyone else is interested in this, but I attached the plex vbe bios 
>nasm
> file (containing the things I've been working on today).
> 
> Doesn't do very much at the moment:
> * hooks up into int 10h and intercepts vbe calls
> * vbe call 00 and 01 are (partly) supported; just enough for the scitech lfbprof 
>example
> to detect the vbe & to see that there's an available mode.
> 
> --
> Best regards,
> 
>                  Jeroen Janssen
> ---
> It is said that whosoever the gods wish to destroy, they first make mad. In
> fact, whosoever the gods wish to destroy, they first hand the equivalent of
> a stick with a fizzing fuse and Acme Dynamite Company written on the side.
> It's more interesting, and doesn't take so long.
>         -- (Terry Pratchett, Soul Music)
> 
>   ------------------------------------------------------------------------
> ;
> ; plex86 VESA Bios Extension (VBE)
> ; Copyright (C) 2001 Jeroen Janssen
> ;
> ; $Id: plex_vbe.nasm,v 1.5 2001/06/16 22:20:04 japj Exp $
> ;
> ; This library is free software; you can redistribute it and/or
> ; modify it under the terms of the GNU Lesser General Public
> ; License as published by the Free Software Foundation; either
> ; version 2 of the License, or (at your option) any later version.
> ;
> ; This library is distributed in the hope that it will be useful,
> ; but WITHOUT ANY WARRANTY; without even the implied warranty of
> ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> ; Lesser General Public License for more details.
> ;
> ; You should have received a copy of the GNU Lesser General Public
> ; License along with this library; if not, write to the Free Software
> ; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
> ;
> ;
> ; This is a plex86 extension bios that is intented to provide VBE support for plex86.
> ;
> ; compile with:
> ;       nasm -f bin plex_vbe.nasm
> ;
> ; use with plex (from config file):
> ;       load-rom: file=../bios/plex_vbe, address=0xc8000
> ;
> ;
> ; you can (partly) test this bios using the lfbprof.exe at :
> ;  ftp://ftp.scitechsoft.com/devel/docs/lfbprof.zip
> ;
> ; (NOTE that the current bios implementation allows for the lfbprof example to list
> ;  *one* available mode (640x480), but you can't set that mode yet).
> 
> ;=========================================================
> ; Needed VBE structures:
> 
> ; The VBE Information Block (used by function 0x4F00)
> struc   VBEInfoBlock
>         .signature              resb 4
>         .version                resw 1
>         .oemstringptr           resd 1
>         .capabilities           resb 4
>         .videomodeptr           resd 1
>         .totalmemory            resw 1
>         .oemversion             resw 1
>         .oemvendornameptr       resd 1
>         .oemproductnameptr      resd 1
>         .oemproductrevptr       resd 1
>         .reserved               resb 222
>         .oemdata                resb 256
> endstruc
> 
> struc   ModeInfoBlock
> ; Mandatory info for all VBE revisions
>         .ModeAttributes         resw 1
>         .WinAAttributes         resb 1
>         .WinBAttributes         resb 1
>         .WinGranularity         resw 1
>         .WinSize                resw 1
>         .WinASegment            resw 1
>         .WinBSegment            resw 1
>         .WinFuncPtr             resd 1
>         .BytesPerScanLine       resw 1
> ; Mandatory information for VBE 1.2 and above
>         .XResolution            resw 1
>         .YResolution            resw 1
>         .XCharSize              resb 1
>         .YCharSize              resb 1
>         .NumberOfPlanes         resb 1
>         .BitsPerPixel           resb 1
>         .NumberOfBanks          resb 1
>         .MemoryModel            resb 1
>         .BankSize               resb 1
>         .NumberOfImagePages     resb 1
>         .Reserved1              resb 1
> ; Direct Color fields (required for direct/6 and YUV/7 memory models)
>         .RedMaskSize            resb 1
>         .RedFieldPosition       resb 1
>         .GreenMaskSize          resb 1
>         .GreenFieldPosition     resb 1
>         .BlueMaskSize           resb 1
>         .BlueFieldPosition      resb 1
>         .RsvdMaskSize           resb 1
>         .RsvdFieldPosition      resb 1
>         .DirectColorModeInfo    resb 1
> ; Mandatory info for VBE 2.0 and above
>         .PhysBasePtr            resd 1
>         .Reserved2              resd 1
>         .Reserved3              resw 1
> ; Mandatory info for VBE 3.0 and above
> ; fillin
> endstruc
> 
> BITS 16
> org 0
> ;
> ; extension/expansion bios rom header:
> ; offset        value
> ; 0             0x55
> ; 1             0xaa
> ; 2             ROM length in 512-byte blocks
> ; 3             ROM initialization entry point (FAR CALL)
> 
> bios_extension_header:
>         db      0x55,0xAA
>         db      ((bios_end - bios_extension_header) + 511)/512
>         jmp     bios_init
> 
> ; expansion bios initialization routine
> ; this is where the int 10h is hooked up to the vbe_int_10h
> bios_init:
>         pusha
>         push    ds
>         push    es
> 
>         ; es is 0 segment for addressing interrupt tabel
>         xor     dx,dx
>         mov     es,dx
> 
>         ; prepare data segment register with current code segment
>         push cs
>         pop ds
> 
>         cli
>         ; save old 0x10 handler to 0x80
>         mov     ax,[es:0x10*4]
>         mov     [es:0x80*4],ax
> 
>         mov     ax,[es:0x10*4+2]
>         mov     [es:0x80*4+2],ax
> 
>         ; put new int 10h in place
>         push    cs
>         pop     ax
>         mov     [es:0x10*4 +2],ax
>         mov     ax,vbe_int_10h
>         mov     [es:0x10*4],ax
> 
>         sti
>         ; put some info about our extension bios
>         cld
>         mov     si, extension_bios_string
>         call    print_string
> 
>         pop     es
>         pop     ds
>         popa
>         retf    ; return from ROM extension init
> 
> ; The main VBE interrupt 10h handler
> vbe_int_10h:
>         cmp     ah,0x4f ; check for VBE function
>         je      vbe_func
>         int     0x80    ; reroute to old int 10h handler
>         iret
> 
> vbe_func:
>         push    ds
> 
>         push    cs
>         pop     ds
>         cmp     al,0    ; return vbe controller info
>         je      vbe_func_00
>         cmp     al,1    ; return vbe mode information
>         je      vbe_func_01
> 
>         jmp     vbe_exit_unsup
> 
> ; Return VBE Controller Information
> ; ax    = 0x4f00
> ; es:di = pointer to VBEInfoBlock buffer
> 
> vbe_func_00:
>         push    eax
> 
>         ; make sure signature contains 'VESA'
>         mov     eax,'VESA'
>         mov     [es:di + VBEInfoBlock.signature],eax
> 
>         ; make sure version contains 2.0
>         mov     word [es:di +VBEInfoBlock.version],0x0200
> 
>         ; make sure the videomode pointer is set correctly
>         mov     ax,ds
>         mov     word [es:di + VBEInfoBlock.videomodeptr + 2],ax
>         mov     ax, video_mode_block
>         mov     word [es:di + VBEInfoBlock.videomodeptr],ax
> 
>         pop     eax
> 
> ; generic VBE return
> ; al = 0x4f     function supported
> ; al!= 0x4f     unsupported function
> ; ah = 0x00     call successfull
> ; ah = 0x01     call failed
> ; ah = 0x02     call unsupported in current hardware config
> ; ah = 0x03     call invalid in current video mode
> vbe_exit_ok:
>         pop     ds
>         ; vbe func succeeded
>         mov     al,0x4f
>         mov     ah,0
>         iret
> 
> vbe_exit_unsup:
>         pop     ds
>         mov     al,0x0
>         iret
> 
> ; Return VBE Mode Information
> ; ax    = 0x4f01
> ; cx    = mode number
> ; es:di = pointer to ModeInfoBlock structure
> 
> vbe_func_01:
>         push    ds
>         push    si
>         push    cx
> 
>         ; since we only have one mode available yet, copy it using movsb
>         mov     cx,ModeInfoBlock_size
>         push    cs
>         pop     ds
>         mov     si,mode_info_block_1
>         cld
>         rep     movsb
> 
>         pop     cx
>         pop     si
>         pop     ds
>         jmp     vbe_exit_ok
> 
> 
> ; ds:si zero terminated string ptr
> print_string:
>         push    ax
> print_loop:
>         lodsb
>         or      al,al
>         jz      print_string_end
>         mov     ah,0x0e
>         int     0x10
>         jmp     print_loop
> 
> print_string_end:
>         pop     ax
>         ret
> 
> extension_bios_string:
>         db      'Plex86 VESA Bios Extension (VBE)', 0x0a,0x0d
>         db      ' ($Id: plex_vbe.nasm,v 1.5 2001/06/16 22:20:04 japj Exp $)'
>         db      0x0a,0x0d,0
> 
> video_mode_block:
>         ;       D8=0    not a vesa defined VBE mode
>         ;       D9-D12  reserved (0)
>         ;       D11=0   use current bios default refresh rate
>         ;       D12-13  reserved for VBE/AF (must be 0)
>         ;       D14=1   use Linear/Flat Frame Buffer
>         ;       D15=0   clear display memory
>         ;       111111
>         ;       5432109876543210
>         dw      0100000000000001b       ; mode 1
>         dw      0xffff                  ; end of mode list
> 
> ; mode info block for mode 1
> mode_info_block_1:
>         istruc ModeInfoBlock
>         ;                                               5432109876543210
>         at ModeInfoBlock.ModeAttributes,        dw      0000000010011011
>         at ModeInfoBlock.XResolution,           dw      640
>         at ModeInfoBlock.YResolution,           dw      480
>         at ModeInfoBlock.NumberOfPlanes,        db      1
>         at ModeInfoBlock.BitsPerPixel,          db      8
>         at ModeInfoBlock.MemoryModel,           db      4
> 
>         iend
> 
> bios_end:

Reply via email to