[FIXED] VESA & VGA graphics

DOS specific questions.
Post Reply
DOS386
Posts: 798
Joined: Jul 02, 2005 20:55

[FIXED] VESA & VGA graphics

Post by DOS386 »

Is the VESA graphics working now or not ?

I tested on a LAPTOP (800x600) and no success.
640*480 neither worked.

The only working method was 320*200*8bit using BIOS calls and
DOSMEMPUT.

Is it possible to access the 640*480*4bit mode using BIOS only,
no SCREEN command or graf libraries ?

EDIT: Seems fixed by now [2006/08/01]
Last edited by DOS386 on Aug 01, 2006 5:34, edited 1 time in total.
yetifoot
Posts: 1710
Joined: Sep 11, 2005 7:08
Location: England
Contact:

Post by yetifoot »

It's not been working for me since 0.13 or 0.14.

I had to use the DJGPP functions last time i wanted to use VESA modes.
DrV
Site Admin
Posts: 2116
Joined: May 27, 2005 18:39
Location: Midwestern USA
Contact:

Post by DrV »

Well, the VESA part should be working, but the ISR routines are still broken somehow, so the graphics statements probably won't work on "real" DOS.

If you really need 640x480x4bpp, you can use BIOS mode 0x12 - mjs wrote a driver for it (src/gfxlib2/dos/libfb_gfx_driver_bios.c) if you want to check out how it works. However, it's a pain to code for this mode because it's planar.
DOS386
Posts: 798
Joined: Jul 02, 2005 20:55

Broken graphics

Post by DOS386 »

Thanks.
Well, the VESA part should be working, but the ISR routines are still broken
somehow, so the graphics statements probably won't work on "real" DOS.
Hmm... what are the "ISR" routines ?

The fact is that VESA does NOT work on my "real" [Free-]DOS.

Is there a chance that it will be fixed one day ?

If you really need 640x480x4bpp, you can use BIOS mode 0x12 - mjs wrote a driver for it (src/gfxlib2/dos/libfb_gfx_driver_bios.c) if you want to check out how it works.
Hmm... I had a look. It is too complicated and contains support for
other modes also (?). Is there a more simple example how to use
this mode "640x480x4bpp, you can use BIOS mode 0x12" ?
The "320x200x8bpp" is so simple :-)
However, it's a pain to code for this mode because it's planar.
??? Can't imagine how a graph mode can be "planar" ...
yetifoot
Posts: 1710
Joined: Sep 11, 2005 7:08
Location: England
Contact:

Post by yetifoot »

I just dug up my old code for 8-bit VESA. This is horrible, disgusting, dirty code that needs a full rewrite, but it works under real dos, and maybe it will help someone get started.

For 0.15 DOS only

Code: Select all

' This code is dirty dirty dirty, it was just cobbled together
' from some old bits and bobs, and needs a FULL checkup.  It just demonstrates
' a way to get to 8-bit VESA modes under DOS.  I checked it with 0.15 and it
' works for me on DOS, but the compiled exe does not run on windows.
' I can't remember much about how i made it but I remember it came in part from
' some GPL code from FalconsEye, and the VESA (2.0?) Docs.

Option Explicit

#define _BORLAND_DOS_REGS 1  // djgpp specific switch

#include "dos\pc.bi"
#include "dos\dos.bi"
#include "dos\go32.bi"
#include "dos\dpmi.bi"

' No nearptr.bi on 0.15
Declare Function __djgpp_nearptr_enable cdecl Alias "__djgpp_nearptr_enable" () As Integer	' Returns 0 if feature not avail
Declare Sub __djgpp_nearptr_disable cdecl Alias "__djgpp_nearptr_disable" ()	' Enables protection
extern __djgpp_selector_limit Alias "__djgpp_selector_" As Integer	' Limit on CS and on DS if prot
extern __djgpp_base_address Alias "__djgpp_base_address" As Integer	' Used in calculation below

' Conflicts with crt.bi
type size_t as uinteger
declare function memcpy cdecl alias "memcpy" (byval as any ptr, byval as any ptr, byval as size_t) as any ptr

#define __djgpp_conventional_base (-__djgpp_base_address)

Type YFVESA_T
  w As Integer
  h As Integer
  vmem As uByte ptr
End Type

Type SVGA_dos_vbe_vgainfo Field = 1
  VESASignature(0 To 3) As Byte ' /* VESA 4-byte signature              */
  VESAVersion As uShort         ' /* VBE version number                 */
  OEMStringPtr As uInteger      ' /* Pointer to OEM string              */
  Capabilities(0 To 3) As uByte ' /* Capabilities of video card         */
  VideoModePtr As uInteger      ' /* Pointer to supported modes         */
  TotalMemory As uShort         ' /* Number of 64kb memory blocks       */
  OEMSoftwareRev As uShort      ' /* VBE software revision              */
  OEMVendorNamePtr As uInteger  ' /* Pointer to vendor name string      */
  OEMProductNamePtr As uInteger ' /* Pointer to product name string     */
  OEMProductRevPtr As uInteger  ' /* Pointer to product revision string */
  Reserved(0 To 221) As Byte    ' /* Reserved as working space          */
  OEMData(0 To 255) As Byte     ' /* Data area for OEM strings          */
End Type

Type SVGA_dos_vbe_modeinfo
  ModeAttributes As Short         '/* Mode attributes                  */
  WinAAttributes As Byte          '/* Window A attributes              */
  WinBAttributes As Byte          '/* Window B attributes              */
  WinGranularity As Short         '/* Window granularity in k          */
  WinSize As Short                '/* Window size in k                 */
  WinASegment As Short            '/* Window A segment                 */
  WinBSegment As Short            '/* Window B segment                 */
  WinFuncPtr As Any ptr           '/* Pointer to window function       */
  BytesPerScanLine As Short       '/* Bytes per scanline               */
  XResolution As Short            '/* Horizontal resolution            */
  YResolution As Short            '/* Vertical resolution              */
  XCharSize As Byte               '/* Character cell width             */
  YCharSize As Byte               '/* Character cell height            */
  NumberOfPlanes As Byte          '/* Number of memory planes          */
  BitsPerPixel As Byte            '/* Bits per pixel                   */
  NumberOfBanks As Byte           '/* Number of CGA style banks        */
  MemoryModel As Byte             '/* Memory model type                */
  BankSize As Byte                '/* Size of CGA style banks          */
  NumberOfImagePages As Byte      '/* Number of images pages           */
  res1 As Byte                    '/* Reserved                         */
  RedMaskSize As Byte             '/* Size of direct color red mask    */
  RedFieldPosition As Byte        '/* Bit posn of lsb of red mask      */
  GreenMaskSize As Byte           '/* Size of direct color green mask  */
  GreenFieldPosition As Byte      '/* Bit posn of lsb of green mask    */
  BlueMaskSize As Byte            '/* Size of direct color blue mask   */
  BlueFieldPosition As Byte       '/* Bit posn of lsb of blue mask     */
  RsvdMaskSize As Byte            '/* Size of direct color res mask    */
  RsvdFieldPosition As Byte       '/* Bit posn of lsb of res mask      */
  DirectColorModeInfo As Byte     '/* Direct color mode attributes     */
  ' VESA 2.0 variables
  PhysBasePtr As Long             '/* physical address for flat frame buffer */
  OffScreenMemOffset As Long      '/* pointer to start of off screen memory */
  OffScreenMemSize As Short       '/* amount of off screen memory in 1k units */
  res2(0 To 205) As Byte          '/* Pad to 256 byte block size       */
End Type

Dim Shared yfvesa As YFVESA_T
Dim Shared SVGA_dos_console As uByte ptr
Dim Shared gran As Short
Dim Shared gran2 As Short

Function SVGA_DOSDetectVBE(vbeinfo As SVGA_dos_vbe_vgainfo ptr) As Integer
  Dim regs As __dpmi_regs
  Dim sig As String
    
    vbeinfo->VESASignature(0) = Asc("V")
    vbeinfo->VESASignature(1) = Asc("B")
    vbeinfo->VESASignature(2) = Asc("E")
    vbeinfo->VESASignature(3) = Asc("2")
    
    regs.x.ax = &H4F00
    regs.x.di = __tb AND &H0F
    regs.x.es = (__tb shr 4) AND &HFFFF
    
    dosmemput(vbeinfo, sizeof(SVGA_dos_vbe_vgainfo), __tb)
    __dpmi_int(&H10, @regs)
    dosmemget(__tb, sizeof(SVGA_dos_vbe_vgainfo), vbeinfo)
    
    sig += chr(vbeinfo->VESASignature(0))
    sig += chr(vbeinfo->VESASignature(1))
    sig += chr(vbeinfo->VESASignature(2))
    sig += chr(vbeinfo->VESASignature(3))
    Print sig
    return regs.h.ah
End Function

Function SVGA_DOSGetVBEModeInfo(ByVal mode As uShort, modeinfo As SVGA_dos_vbe_modeinfo ptr) As Integer
  Dim regs As __dpmi_regs
  
    regs.x.ax = &H4F01
    regs.x.cx = mode
    regs.x.di= __tb AND &H0F
    regs.x.es = (__tb shr 4) AND &HFFFF
    __dpmi_int(&H10, @regs)
    dosmemget(__tb, sizeof(SVGA_dos_vbe_modeinfo), modeinfo)
    Gran = modeinfo->WinGranularity
    Gran2 = modeinfo->WinSize
    return regs.h.ah
End Function

#define SVGA_MAX_VBEMODES 1000
Function VESA_GetMode(w As Integer, h As Integer, b As Integer) As Integer
  Dim vbeinfo As SVGA_dos_vbe_vgainfo
  Dim modeinfo As SVGA_dos_vbe_modeinfo
  Dim i As Integer
  
    If SVGA_DOSDetectVBE(@vbeinfo) <> 0 Then Return 0
    
    While i < &HFFFF
      SVGA_DOSGetVBEModeInfo(i, @modeinfo)
      If modeinfo.XResolution = w AND modeinfo.YResolution = h AND modeinfo.BitsPerPixel = b Then Return i
      i += 1
    Wend                
    Return 0
End Function

Sub SVGA_DOSSetGDisplayMode(ByVal disp_mode As uInteger)
  Dim regs As REGS
    regs.x.eax=&H4f02
    regs.x.ebx=disp_mode
    int86(&H10,@regs,@regs)
End Sub

Sub VESA_Init8(w As Integer, h As Integer)
  Dim mode As Integer
    yfvesa.vmem = CAllocate(w * h)
    yfvesa.w = w
    yfvesa.h = h
    
    mode = VESA_GetMode(w, h, 8)
    Print Hex$(mode)
    
    If mode <> 0 Then
      SVGA_DOSSetGDisplayMode mode
    End If
    
    SVGA_dos_console = Cptr(uByte ptr, &HA0000 + __djgpp_conventional_base)
    
    __djgpp_nearptr_enable()
End Sub

Sub VESA_End()
  Dim regs As __dpmi_regs
    __djgpp_nearptr_disable()
    regs.x.ax = 3
    __dpmi_int(&H10, @regs)
    DeAllocate(yfvesa.vmem)
End Sub

Sub SVGA_DOSSetColor(cindex As uByte, redval As uByte, greenval As uByte, blueval As uByte)
  outp(&H03c6, &HFF)
  outp(&H03c8, cindex)
  outp(&H03c9, redval)
  outp(&H03c9, greenval)
  outp(&H03c9, blueval)
End Sub

Sub SVGA_pixelput(x As Integer, y As Integer, vari As uByte)
  if x < 0 Then x = 0
  if y < 0 Then y = 0
  if x > yfvesa.w - 1 Then x = yfvesa.w - 1
  if y > yfvesa.h - 1 Then y = yfvesa.h - 1
  yfvesa.vmem[(y * yfvesa.w) + x] = vari
End Sub

Sub SVGA_DOSSetWindow(ByVal w_num As uInteger)
  'Dim regs As REGS
  'regs.x.eax=&H4f05
  'regs.x.ebx=0
  'regs.x.edx=w_num
  'int86(&H10,@regs,@regs)
  Dim regs As __dpmi_regs
  regs.x.ax = &H4f05
  regs.x.dx = w_num
  __dpmi_int(&H10, @regs)
End Sub

Sub SVGARefresh()
  Dim As Integer i, npixels, tempwin
  Dim As uByte ptr isource
  
    tempwin = 0
    npixels = yfvesa.w * yfvesa.h
    isource = yfvesa.vmem
    While (npixels > 0)
      SVGA_DOSSetWindow(tempwin)
      if npixels > 65536 Then
        memcpy(SVGA_dos_console,isource,65536)
      else  
        memcpy(SVGA_dos_console,isource,npixels)
      End If
      npixels -= 65536
      isource += 65536
      tempwin += 1
    Wend
End Sub

Dim As Integer x, y

VESA_Init8(800, 600)

SVGA_DOSSetColor(0, 0, 0, 255)
SVGA_DOSSetColor(1, 255, 0, 0)
SVGA_DOSSetColor(2, 255, 255, 255)

Sleep 2000

For y = 16 To 200
  For x = 16 To 200
    SVGA_pixelput(x, y, 1)
  Next x
Next y

For y = 216 To 400
  For x = 216 To 400
    SVGA_pixelput(x, y, 2)
  Next x
Next y

SVGARefresh()

Sleep 2000

VESA_End()
Print Gran
Print Gran2
Print "OK!"
coderJeff
Site Admin
Posts: 4386
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Post by coderJeff »

I made a gui demo that runs on dos using vesa modes here: Binary only: guidemo_dos.zip
It will also run on win98/winxp. This particular demo will allow switching resolutions and color depths.

An explanation of how I did it for the demo is here:
http://www.freebasic.net/forum/viewtopi ... 3600#23600

I have actually tried three different methods:
1) Move the screen update code out of the timer ISR (as in the gui demo) and explicitly call it from the user code
2) Move the screen update code out of the timer ISR and call it from the driver unlock hook. This could be a very real solution to the DOS vesa problem assuming appropriate use of screenlock/unlock'ing in the user code.
3) Leave the screen update code in the timer ISR but only update one bank of video memory per interrupt. (looked horrible, but worked, barely)

I'm not an export on this stuff, I just put together something that worked for me. I certainly was not considering compatibility with QB or that the way the screen gets updated is different from windows and lower res modes.

Of course, making these changes requires recompiling a couple of modules in the dos port of the gfxlib.
DOS386
Posts: 798
Joined: Jul 02, 2005 20:55

VESA graphics

Post by DOS386 »

Thanks for 2 previous posts. I'll study them.

Further:

There is Rayer's VESATEST

http://www.volny.cz/rayer/programm/programe.htm

For me it is very reliable - works on every PC, incl. the laptop
mentioned above (up to 800x600x24bits).

Unfortunately it is closed source now, but one could ask the autor if
he could release the source or make it useable from FreeBASIC some
way. By now it is a TEST only.
DrV
Site Admin
Posts: 2116
Joined: May 27, 2005 18:39
Location: Midwestern USA
Contact:

Re: Broken graphics

Post by DrV »

StopTCPA wrote:??? Can't imagine how a graph mode can be "planar" ...
All VGA modes except 0x13 (320x240x8, chain-4 instead of planar) are planar - for example, in a 4-bit mode, each of the 4 bits for one pixel is split up into a different plane. There are a couple of VGA registers that allow you to pick which plane to read from and which plane(s) to write to. The reason behind this is probably related to the fact that an entire 640x480x4bpp image can't be mapped into a single 64k block.
DOS386
Posts: 798
Joined: Jul 02, 2005 20:55

Planar graphics

Post by DOS386 »

Thanks.

Does it mean that with 640x480x4bpp there are 4 banks.
every of them 38'400 bytes long (640*480/8), and I have to write
1 bit to every of them to place 1 pixel to the screen ???

The 320x200x8bpp mode has one simple screen buffer :-)
,but low resolution :-(

Hope you catch the BUG in the VESA code soon. :-)
Antoni
Posts: 1393
Joined: May 27, 2005 15:40
Location: Barcelona, Spain

Re: Planar graphics

Post by Antoni »

StopTCPA wrote: Does it mean that with 640x480x4bpp there are 4 banks.
every of them 38'400 bytes long (640*480/8), and I have to write
1 bit to every of them to place 1 pixel to the screen ???
You can too program the latches and other funny things in the VGA hardware to make block reads and writes. Besides it, programming a Soundblaster is a child's game. Better wait for the full SVGA implementation or use a lib
Post Reply