VOGONS


SVGA/VESA programming

Topic actions

First post, by WhiteFalcon

User metadata
Rank Newbie
Rank
Newbie

Not sure this question belongs here, but its the closes topic section of Vogons I could find. If there is DOS development section here, please, redirect me.

As I am trying to get further in DOS programming than I managed back in the day, I am learning to tackle SVGA. VESA support detection and a simple put pixel routine work well aready, a "PutImage" function basically too, but working in real mode on a real machine (P75 + S3Trio) means there is no way for double buffering. My plan is just to have a custom mouse cursor for a potential first person point'n'click adventure game, so nothing too demanding on the hardware. With the lack of a virtual screen, I am using the same old technique I remember working well in VGA 320x200: store the background, draw the image, delete the image. When done just like that it results in nothing visible most of the time of course, so I put in a call to a simple WaitRetrace function I used to use in VGA. And it looks great... unless you move the cursor to the top of the screen, there is a large vertical bar area where it just disappears. Apparently the cursor meets the vertical ray already on its way down drawing a new screen. For clarity, the loop is as follows:

{
UpdateXYCoordinatesFromMouse();
StoreBackground(x, y);
DrawImage(x, y);
WaitRetrace();
RestoreBackground(x, y);
}

The only way to cope with this is to rewrite my drawing routines also in asm, which is a tough challenge considering bank switching on demand is needed. Moreover it would not be a clean solution as on a slower machine the problem would appear again. I guess many game must have gone around it using protected mode and double buffering, but it seems to be at least some did not and offered much more "action" on the screen. I can come up with Death Gate, Little Big Adventure, Transport Tycoon, Oxyd, The Incredible Machine, Sim City 2000... maybe some of them were protected and just did not show the DOS4GW banner.

Is there (an easy) solution to that? Did anyone here programmed SVGA in DOS without a DOS extender and without addressing the gfx card type specifically?

Olivetti M4 P75, 32MB RAM, 4GB HDD, 8GB CF, SoundBlaster AWE 64, Gravis Ultrasound MAX, Roland SCC-1, Roland MT-32, Roland CM-64
Intel 486DX2/66Mhz, 16MB RAM, VGA Trident 512kB, 264MB HDD Quantum, 256MB CF, SoundBlaster 16 Pro (CT2910)

Reply 1 of 59, by Falcosoft

User metadata
Rank Oldbie
Rank
Oldbie
WhiteFalcon wrote on 2022-06-20, 05:47:

...
but working in real mode on a real machine (P75 + S3Trio) means there is no way for double buffering. My plan is just to have a custom mouse cursor for a potential first person point'n'click adventure game, so nothing too demanding on the hardware. With the lack of a virtual screen, I am using the same old technique I remember working well in VGA 320x200...

Hi,
This is not true. Even in real mode you can achieve hardware assisted double, or even triple buffering in some modes (depending on the size of available video memory). You do not need protected mode for this. The necessary functions have been available from VESA 1.2 (that version did not define linear frame buffer modes or protected mode interface yet). So the functions are available in case of banked modes and thus works from real mode programs.
1. You can query the available virtual screens for a given video mode by calling VESA Function 01h Return VBE Mode Information and looking at the byte value of NumberOfImagePages (at offset 29) in the returned ModeInfoBlock struct.
2. You can call VESA Function 06h - Set/Get Logical Scan Line Length to set the length of a logical/virtual scan line.
3. Then you can call VESA Function 07h - Set/Get Display Start to set the actual starting pixel of the virtual screen.
This way you can achieve virtual scrolling or double/triple/quad buffering depending on the size of the virtual area.
http://www.phatcode.net/res/221/files/vbe20.pdf

Website, Facebook, Youtube
Falcosoft Soundfont Midi Player + Munt VSTi + BassMidi VSTi
VST Midi Driver Midi Mapper

Reply 2 of 59, by WhiteFalcon

User metadata
Rank Newbie
Rank
Newbie

How did I miss that?? Thank you! Will have to look into that then. I want to keep the requirements low, but VESA 1.2 is totally okay and a 256kB gfx card wont cut it in 640x480x8 anyway. Would be nice to keep it down to 512Kb, but 2x640x480 = 600kB so I guess 1MB would be the requirement then.

Olivetti M4 P75, 32MB RAM, 4GB HDD, 8GB CF, SoundBlaster AWE 64, Gravis Ultrasound MAX, Roland SCC-1, Roland MT-32, Roland CM-64
Intel 486DX2/66Mhz, 16MB RAM, VGA Trident 512kB, 264MB HDD Quantum, 256MB CF, SoundBlaster 16 Pro (CT2910)

Reply 3 of 59, by root42

User metadata
Rank l33t
Rank
l33t
WhiteFalcon wrote on 2022-06-20, 07:45:

How did I miss that?? Thank you! Will have to look into that then. I want to keep the requirements low, but VESA 1.2 is totally okay and a 256kB gfx card wont cut it in 640x480x8 anyway. Would be nice to keep it down to 512Kb, but 2x640x480 = 600kB so I guess 1MB would be the requirement then.

You can keep to 640x400, which has the added bonus of higher refresh rate, albeit non-square pixels, depending on how you configure your screen... IIRC Links 386 used 640x400 as its default resolution, because it would work on most low-end VGA cards.

YouTube and Bonus
80486DX@33 MHz, 16 MiB RAM, Tseng ET4000 1 MiB, SnarkBarker & GUSar Lite, PC MIDI Card+X2+SC55+MT32, OSSC

Reply 4 of 59, by WhiteFalcon

User metadata
Rank Newbie
Rank
Newbie

A good idea to fit it in 512kB even with double buffering! 640x400 is a good resolution, its just that the plan was to use 640x400 for the viewport and the bottom 80 for inventory.

Olivetti M4 P75, 32MB RAM, 4GB HDD, 8GB CF, SoundBlaster AWE 64, Gravis Ultrasound MAX, Roland SCC-1, Roland MT-32, Roland CM-64
Intel 486DX2/66Mhz, 16MB RAM, VGA Trident 512kB, 264MB HDD Quantum, 256MB CF, SoundBlaster 16 Pro (CT2910)

Reply 5 of 59, by WhiteFalcon

User metadata
Rank Newbie
Rank
Newbie
Falcosoft wrote on 2022-06-20, 07:22:
Hi, This is not true. Even in real mode you can achieve hardware assisted double, or even triple buffering in some modes (depen […]
Show full quote

Hi,
This is not true. Even in real mode you can achieve hardware assisted double, or even triple buffering in some modes (depending on the size of available video memory). You do not need protected mode for this. The necessary functions have been available from VESA 1.2 (that version did not define linear frame buffer modes or protected mode interface yet). So the functions are available in case of banked modes and thus works from real mode programs.
1. You can query the available virtual screens for a given video mode by calling VESA Function 01h Return VBE Mode Information and looking at the byte value of NumberOfImagePages (at offset 29) in the returned ModeInfoBlock struct.
2. You can call VESA Function 06h - Set/Get Logical Scan Line Length to set the length of a logical/virtual scan line.
3. Then you can call VESA Function 07h - Set/Get Display Start to set the actual starting pixel of the virtual screen.
This way you can achieve virtual scrolling or double/triple/quad buffering depending on the size of the virtual area.
http://www.phatcode.net/res/221/files/vbe20.pdf

It seems that the virtual screen functions are available only from VESA 2.0 up, my S3 Trio with VESA 1.2 probably wont even return the info in the mode struct. I wrote the struct definition following the VESA 1.2 specification which is why I even missed those fields connected with the offscreen memory. I am testing it now in DOSBox set to "vesa_oldvbe" which returns 1.2 as version, same as my old PC. And "OffScreenMemSize" is giving me 0 for mode 0x101 (640x480x8). A workaround could be UniVBE perhaps. But the mentioned games do work for me even without UniVBE on VESA 1.2 so there has to be a way..

Olivetti M4 P75, 32MB RAM, 4GB HDD, 8GB CF, SoundBlaster AWE 64, Gravis Ultrasound MAX, Roland SCC-1, Roland MT-32, Roland CM-64
Intel 486DX2/66Mhz, 16MB RAM, VGA Trident 512kB, 264MB HDD Quantum, 256MB CF, SoundBlaster 16 Pro (CT2910)

Reply 6 of 59, by root42

User metadata
Rank l33t
Rank
l33t
WhiteFalcon wrote on 2022-06-20, 08:46:

It seems that the virtual screen functions are available only from VESA 2.0 up, my S3 Trio with VESA 1.2 probably wont even return the info in the mode struct. I wrote the struct definition following the VESA 1.2 specification which is why I even missed those fields connected with the offscreen memory. I am testing it now in DOSBox set to "vesa_oldvbe" which returns 1.2 as version, same as my old PC. And "OffScreenMemSize" is giving me 0 for mode 0x101 (640x480x8). A workaround could be UniVBE perhaps. But the mentioned games do work for me even without UniVBE on VESA 1.2 so there has to be a way..

There is always the possibility of inaccuracies in DOSBox. I think it could be wise to test with a real VGA card on a machine, e.g. with UniVBE. If you have a retro PC available, that is...

YouTube and Bonus
80486DX@33 MHz, 16 MiB RAM, Tseng ET4000 1 MiB, SnarkBarker & GUSar Lite, PC MIDI Card+X2+SC55+MT32, OSSC

Reply 7 of 59, by root42

User metadata
Rank l33t
Rank
l33t
WhiteFalcon wrote on 2022-06-20, 07:58:

A good idea to fit it in 512kB even with double buffering! 640x400 is a good resolution, its just that the plan was to use 640x400 for the viewport and the bottom 80 for inventory.

Well, if you haven't produced any assets yet, you can still change the design to something like 340 : 60 or so, which is roughly the same aspect ration between viewport and inventory.

Alternatively you could hide the inventory and only show it when the mouse cursor touches the bottom of the screen...

YouTube and Bonus
80486DX@33 MHz, 16 MiB RAM, Tseng ET4000 1 MiB, SnarkBarker & GUSar Lite, PC MIDI Card+X2+SC55+MT32, OSSC

Reply 8 of 59, by WhiteFalcon

User metadata
Rank Newbie
Rank
Newbie

Of course, I do, but not at hand. My aim is for it to work on the real PC, using DOSBox only as an alternative as I only have access to the real PC a few times per year.

True with 640x400, yet now facing the problem with maybe no access to double buffering and perhaps no way to solve it another way on VESA 1.2.. Kind of took away my enthusiasm 🙁

Olivetti M4 P75, 32MB RAM, 4GB HDD, 8GB CF, SoundBlaster AWE 64, Gravis Ultrasound MAX, Roland SCC-1, Roland MT-32, Roland CM-64
Intel 486DX2/66Mhz, 16MB RAM, VGA Trident 512kB, 264MB HDD Quantum, 256MB CF, SoundBlaster 16 Pro (CT2910)

Reply 9 of 59, by root42

User metadata
Rank l33t
Rank
l33t

I think you can do double buffering in 640x400 IF the VBE mode returns at least eight 64KiB banks of video memory (512KiB). You can use function 07h to set the screen start to flip back and forth between the pages (or even implement soft scrolling vertically).

6.9 Function 07h - Set/Get Display Start […]
Show full quote

6.9 Function 07h - Set/Get Display Start

This function selects the pixel to be displayed in the upper left corner of the
display from the logical page. This function can be used to pan and scroll
around logical screens that are larger than the displayed screen. This function
can also be used to rapidly switch between two different displayed screens for
double buffered animation effects.

Input: AH = 4Fh Super VGA support
AL = 07h Display Start Control
BH = 00h Reserved and must be 0
BL = 00h Select Display Start
CX = First Displayed Pixel in Scan Line
DX = First Displayed Scan Line

Output: AX = Status

Input: AH = 4Fh Super VGA support
AL = 07h Display Start Control
BL = 01h Return Display Start

Output: AX = Status
BH = 00h Reserved and will be 0
CX = First Displayed Pixel in Scan Line
DX = First Displayed Scan Line

YouTube and Bonus
80486DX@33 MHz, 16 MiB RAM, Tseng ET4000 1 MiB, SnarkBarker & GUSar Lite, PC MIDI Card+X2+SC55+MT32, OSSC

Reply 10 of 59, by Falcosoft

User metadata
Rank Oldbie
Rank
Oldbie
WhiteFalcon wrote on 2022-06-20, 08:46:

It seems that the virtual screen functions are available only from VESA 2.0 up, my S3 Trio with VESA 1.2 probably wont even return the info in the mode struct. I wrote the struct definition following the VESA 1.2 specification which is why I even missed those fields connected with the offscreen memory. I am testing it now in DOSBox set to "vesa_oldvbe" which returns 1.2 as version, same as my old PC. And "OffScreenMemSize" is giving me 0 for mode 0x101 (640x480x8). A workaround could be UniVBE perhaps. But the mentioned games do work for me even without UniVBE on VESA 1.2 so there has to be a way..

Hi,
No. Look at the ModeInfoBlock definition in the documentation:

ModeInfoBlock struc ; Mandatory information for all VBE revisions ModeAttributes dw ? ; mode attributes WinAAttributes db ? ; wi […]
Show full quote

ModeInfoBlock struc
; Mandatory information for all VBE revisions
ModeAttributes dw ? ; mode attributes
WinAAttributes db ? ; window A attributes
WinBAttributes db ? ; window B attributes
WinGranularity dw ? ; window granularity
WinSize dw ? ; window size
WinASegment dw ? ; window A start segment
WinBSegment dw ? ; window B start segment
WinFuncPtr dd ? ; real mode pointer to window function
BytesPerScanLine dw ? ; bytes per scan line
; Mandatory information for VBE 1.2 and above
XResolution dw ? ; horizontal resolution in pixels or characters
YResolution dw ? ; vertical resolution in pixels or characters
XCharSize db ? ; character cell width in pixels
YCharSize db ? ; character cell height in pixels
NumberOfPlanes db ? ; number of memory planes
BitsPerPixel db ? ; bits per pixel
NumberOfBanks db ? ; number of banks
MemoryModel db ? ; memory model type
BankSize db ? ; bank size in KB
NumberOfImagePages db ? ; number of images
Reserved db 1 ; reserved for page function
RedMaskSize db ? ; size of direct color red mask in bits
RedFieldPosition db ? ; bit position of lsb of red mask
GreenMaskSize db ? ; size of direct color green mask in bits
GreenFieldPosition db ? ; bit position of lsb of green mask
BlueMaskSize db ? ; size of direct color blue mask in bits
BlueFieldPosition db ? ; bit position of lsb of blue mask
RsvdMaskSize db ? ; size of direct color reserved mask in bits
RsvdFieldPosition db ? ; bit position of lsb of reserved mask
DirectColorModeInfo db ? ; direct color mode attributes
; Mandatory information for VBE 2.0 and above
PhysBasePtr dd ? ; physical address for flat memory frame buffer
Reserved dd 0 ; Reserved - always set to 0
Reserved dw 0 ; Reserved - always set to 0
; Mandatory information for VBE 3.0 and above
LinBytesPerScanLine dw ? ; bytes per scan line for linear modes
BnkNumberOfImagePages db ? ; number of images for banked modes
LinNumberOfImagePages db ? ; number of images for linear modes
LinRedMaskSize db ? ; size of direct color red mask (linear modes)
LinRedFieldPosition db ? ; bit position of lsb of red mask (linear modes)
LinGreenMaskSize db ? ; size of direct color green mask (linear modes)
LinGreenFieldPositiondb ? ; bit position of lsb of green mask (linear modes)
LinBlueMaskSize db ? ; size of direct color blue mask (linear modes)
LinBlueFieldPosition db ? ; bit position of lsb of blue mask (linear modes)
LinRsvdMaskSize db ? ; size of direct color reserved mask (linear modes)
LinRsvdFieldPosition db ? ; bit position of lsb of reserved mask (linear modes)
MaxPixelClock dd ? ; maximum pixel clock (in Hz) for graphics mode
Reserved db 189 dup (?) ; remainder of ModeInfoBlock
ModeInfoBlock ends

As you can see NumberOfImagePages field belongs to the " Mandatory information for VBE 1.2 and above" block.
But as you have written right "OffScreenMemSize" blongs to the "VESA 2.0 and above" block and is only meaningful in case of linear frame buffer modes. But you do not need this field to use virtual resolutions from real mode.
As a test you can try this real mode Turbo Pascal test program that was written to test Nvidia Maxwell/Pascal+ GPU bug. It uses Function 07 explicitly. It should work in DosBox or with your VESA 1.2 S3 card.
Download FALCO_VBEVSTST.zip from the first post:
NVIDIA Kepler/Maxwell/Pascal VESA Bios Bug (workaround found)

Or you can also use Univbe's video mode tests without activating Univbe itself. Press spacebar until you get to the virtual scrolling test when you are testing a Banked vide0 mode.
download/file.php?id=41407

Or try the best 😀
Here is a full real mode program that uses Vesa 1.2 640x480 256 color mode and uses as many virtual pages as available to achieve smooth animation (but it will be slow on a Pentium 75):
https://falcosoft.hu/rotary_engine.zip

Ps: I have tested and all the above programs/tests work in vesa_oldvbe mode of DosBox...
So the point is you can use the virtual resolution related functions in VESA 1.2 and you do not need the"OffScreenMemSize" field for anything (which for the record has not been mentioned by me at all so I do not understand why you tried to use it). You only need the
" NumberOfImagePages" field to determine if virtual resolutions are available in VESA 1.2 modes.

Website, Facebook, Youtube
Falcosoft Soundfont Midi Player + Munt VSTi + BassMidi VSTi
VST Midi Driver Midi Mapper

Reply 11 of 59, by WhiteFalcon

User metadata
Rank Newbie
Rank
Newbie
Falcosoft wrote on 2022-06-20, 09:54:
Hi, No. Look at the ModeInfoBlock definition in the documentation: […]
Show full quote

Hi,
No. Look at the ModeInfoBlock definition in the documentation:

ModeInfoBlock struc ; Mandatory information for all VBE revisions ModeAttributes dw ? ; mode attributes WinAAttributes db ? ; wi […]
Show full quote

ModeInfoBlock struc
; Mandatory information for all VBE revisions
ModeAttributes dw ? ; mode attributes
WinAAttributes db ? ; window A attributes
WinBAttributes db ? ; window B attributes
WinGranularity dw ? ; window granularity
WinSize dw ? ; window size
WinASegment dw ? ; window A start segment
WinBSegment dw ? ; window B start segment
WinFuncPtr dd ? ; real mode pointer to window function
BytesPerScanLine dw ? ; bytes per scan line
; Mandatory information for VBE 1.2 and above
XResolution dw ? ; horizontal resolution in pixels or characters
YResolution dw ? ; vertical resolution in pixels or characters
XCharSize db ? ; character cell width in pixels
YCharSize db ? ; character cell height in pixels
NumberOfPlanes db ? ; number of memory planes
BitsPerPixel db ? ; bits per pixel
NumberOfBanks db ? ; number of banks
MemoryModel db ? ; memory model type
BankSize db ? ; bank size in KB
NumberOfImagePages db ? ; number of images
Reserved db 1 ; reserved for page function
RedMaskSize db ? ; size of direct color red mask in bits
RedFieldPosition db ? ; bit position of lsb of red mask
GreenMaskSize db ? ; size of direct color green mask in bits
GreenFieldPosition db ? ; bit position of lsb of green mask
BlueMaskSize db ? ; size of direct color blue mask in bits
BlueFieldPosition db ? ; bit position of lsb of blue mask
RsvdMaskSize db ? ; size of direct color reserved mask in bits
RsvdFieldPosition db ? ; bit position of lsb of reserved mask
DirectColorModeInfo db ? ; direct color mode attributes
; Mandatory information for VBE 2.0 and above
PhysBasePtr dd ? ; physical address for flat memory frame buffer
Reserved dd 0 ; Reserved - always set to 0
Reserved dw 0 ; Reserved - always set to 0
; Mandatory information for VBE 3.0 and above
LinBytesPerScanLine dw ? ; bytes per scan line for linear modes
BnkNumberOfImagePages db ? ; number of images for banked modes
LinNumberOfImagePages db ? ; number of images for linear modes
LinRedMaskSize db ? ; size of direct color red mask (linear modes)
LinRedFieldPosition db ? ; bit position of lsb of red mask (linear modes)
LinGreenMaskSize db ? ; size of direct color green mask (linear modes)
LinGreenFieldPositiondb ? ; bit position of lsb of green mask (linear modes)
LinBlueMaskSize db ? ; size of direct color blue mask (linear modes)
LinBlueFieldPosition db ? ; bit position of lsb of blue mask (linear modes)
LinRsvdMaskSize db ? ; size of direct color reserved mask (linear modes)
LinRsvdFieldPosition db ? ; bit position of lsb of reserved mask (linear modes)
MaxPixelClock dd ? ; maximum pixel clock (in Hz) for graphics mode
Reserved db 189 dup (?) ; remainder of ModeInfoBlock
ModeInfoBlock ends

As you can see NumberOfImagePages field belongs to the " Mandatory information for VBE 1.2 and above" block.
But as you have written right "OffScreenMemSize" blongs to the "VESA 2.0 and above" block and is only meaningful in case of linear frame buffer modes. But you do not need this field to use virtual resolutions from real mode.
As a test you can try this real mode Turbo Pascal test program that was written to test Nvidia Maxwell/Pascal+ GPU bug. It uses Function 07 explicitly. It should work in DosBox or with your VESA 1.2 S3 card.
Download FALCO_VBEVSTST.zip from the first post:
NVIDIA Kepler/Maxwell/Pascal VESA Bios Bug (workaround found)

Or you can also use Univbe's video mode tests without activating Univbe itself. Press spacebar until you get to the virtual scrolling test when you are testing a Banked vide0 mode.
download/file.php?id=41407

Or try the best 😀
Here is a full real mode program that uses Vesa 1.2 640x480 256 color mode and uses as many virtual pages as available to achieve smooth animation (but it will be slow on a Pentium 75):
https://falcosoft.hu/rotary_engine.zip

Ps: I have tested and all the above programs/tests work in vesa_oldvbe mode of DosBox...
So the point is you can use the virtual resolution related functions in VESA 1.2 and you do not need the"OffScreenMemSize" field for anything (which for the record has not been mentioned by me at all so I do not understand why you tried to use it). You only need the
" NumberOfImagePages" field to determine if virtual resolutions are available in VESA 1.2 modes.

Neat! Thank you for the tips and examples, I will try it on my real PC when I get the chance again. And also here in DOSBox. As you apparently have experiences with this, how do you go about using it for double buffering? I mean you probably set the start offset from 0 to 307200 and back (for 640x480) and it should be possible to use and alternation of the method I mentioned in the first post, storing the background and restoring after the flip. But how about the banks, does the second screen start on a bank boundary, i.e. 307200? Or do you need to just consider it all as one piece of memory which will make the bank calculation for PutImage/Sprite a bit more complicated? I am somewhat afraid the latter is the case, which will again make it a bit over my head. Nevertheless it would make it completely flicker free.

Olivetti M4 P75, 32MB RAM, 4GB HDD, 8GB CF, SoundBlaster AWE 64, Gravis Ultrasound MAX, Roland SCC-1, Roland MT-32, Roland CM-64
Intel 486DX2/66Mhz, 16MB RAM, VGA Trident 512kB, 264MB HDD Quantum, 256MB CF, SoundBlaster 16 Pro (CT2910)

Reply 12 of 59, by WhiteFalcon

User metadata
Rank Newbie
Rank
Newbie
root42 wrote on 2022-06-20, 09:24:

I think you can do double buffering in 640x400 IF the VBE mode returns at least eight 64KiB banks of video memory (512KiB). You can use function 07h to set the screen start to flip back and forth between the pages (or even implement soft scrolling vertically).

6.9 Function 07h - Set/Get Display Start […]
Show full quote

6.9 Function 07h - Set/Get Display Start

This function selects the pixel to be displayed in the upper left corner of the
display from the logical page. This function can be used to pan and scroll
around logical screens that are larger than the displayed screen. This function
can also be used to rapidly switch between two different displayed screens for
double buffered animation effects.

Input: AH = 4Fh Super VGA support
AL = 07h Display Start Control
BH = 00h Reserved and must be 0
BL = 00h Select Display Start
CX = First Displayed Pixel in Scan Line
DX = First Displayed Scan Line

Output: AX = Status

Input: AH = 4Fh Super VGA support
AL = 07h Display Start Control
BL = 01h Return Display Start

Output: AX = Status
BH = 00h Reserved and will be 0
CX = First Displayed Pixel in Scan Line
DX = First Displayed Scan Line

Agree, it should be doable with 512kB in theory. This page switching is totally new for me, didnt have much experience with ModeX (where this is a must) if any at all. And it also depends if VESA 1.2 supports it, which seems to be the case.

Olivetti M4 P75, 32MB RAM, 4GB HDD, 8GB CF, SoundBlaster AWE 64, Gravis Ultrasound MAX, Roland SCC-1, Roland MT-32, Roland CM-64
Intel 486DX2/66Mhz, 16MB RAM, VGA Trident 512kB, 264MB HDD Quantum, 256MB CF, SoundBlaster 16 Pro (CT2910)

Reply 13 of 59, by WhiteFalcon

User metadata
Rank Newbie
Rank
Newbie
Falcosoft wrote on 2022-06-20, 09:54:
Hi, No. Look at the ModeInfoBlock definition in the documentation: […]
Show full quote
WhiteFalcon wrote on 2022-06-20, 08:46:

It seems that the virtual screen functions are available only from VESA 2.0 up, my S3 Trio with VESA 1.2 probably wont even return the info in the mode struct. I wrote the struct definition following the VESA 1.2 specification which is why I even missed those fields connected with the offscreen memory. I am testing it now in DOSBox set to "vesa_oldvbe" which returns 1.2 as version, same as my old PC. And "OffScreenMemSize" is giving me 0 for mode 0x101 (640x480x8). A workaround could be UniVBE perhaps. But the mentioned games do work for me even without UniVBE on VESA 1.2 so there has to be a way..

Hi,
No. Look at the ModeInfoBlock definition in the documentation:

ModeInfoBlock struc ; Mandatory information for all VBE revisions ModeAttributes dw ? ; mode attributes WinAAttributes db ? ; wi […]
Show full quote

ModeInfoBlock struc
; Mandatory information for all VBE revisions
ModeAttributes dw ? ; mode attributes
WinAAttributes db ? ; window A attributes
WinBAttributes db ? ; window B attributes
WinGranularity dw ? ; window granularity
WinSize dw ? ; window size
WinASegment dw ? ; window A start segment
WinBSegment dw ? ; window B start segment
WinFuncPtr dd ? ; real mode pointer to window function
BytesPerScanLine dw ? ; bytes per scan line
; Mandatory information for VBE 1.2 and above
XResolution dw ? ; horizontal resolution in pixels or characters
YResolution dw ? ; vertical resolution in pixels or characters
XCharSize db ? ; character cell width in pixels
YCharSize db ? ; character cell height in pixels
NumberOfPlanes db ? ; number of memory planes
BitsPerPixel db ? ; bits per pixel
NumberOfBanks db ? ; number of banks
MemoryModel db ? ; memory model type
BankSize db ? ; bank size in KB
NumberOfImagePages db ? ; number of images
Reserved db 1 ; reserved for page function
RedMaskSize db ? ; size of direct color red mask in bits
RedFieldPosition db ? ; bit position of lsb of red mask
GreenMaskSize db ? ; size of direct color green mask in bits
GreenFieldPosition db ? ; bit position of lsb of green mask
BlueMaskSize db ? ; size of direct color blue mask in bits
BlueFieldPosition db ? ; bit position of lsb of blue mask
RsvdMaskSize db ? ; size of direct color reserved mask in bits
RsvdFieldPosition db ? ; bit position of lsb of reserved mask
DirectColorModeInfo db ? ; direct color mode attributes
; Mandatory information for VBE 2.0 and above
PhysBasePtr dd ? ; physical address for flat memory frame buffer
Reserved dd 0 ; Reserved - always set to 0
Reserved dw 0 ; Reserved - always set to 0
; Mandatory information for VBE 3.0 and above
LinBytesPerScanLine dw ? ; bytes per scan line for linear modes
BnkNumberOfImagePages db ? ; number of images for banked modes
LinNumberOfImagePages db ? ; number of images for linear modes
LinRedMaskSize db ? ; size of direct color red mask (linear modes)
LinRedFieldPosition db ? ; bit position of lsb of red mask (linear modes)
LinGreenMaskSize db ? ; size of direct color green mask (linear modes)
LinGreenFieldPositiondb ? ; bit position of lsb of green mask (linear modes)
LinBlueMaskSize db ? ; size of direct color blue mask (linear modes)
LinBlueFieldPosition db ? ; bit position of lsb of blue mask (linear modes)
LinRsvdMaskSize db ? ; size of direct color reserved mask (linear modes)
LinRsvdFieldPosition db ? ; bit position of lsb of reserved mask (linear modes)
MaxPixelClock dd ? ; maximum pixel clock (in Hz) for graphics mode
Reserved db 189 dup (?) ; remainder of ModeInfoBlock
ModeInfoBlock ends

As you can see NumberOfImagePages field belongs to the " Mandatory information for VBE 1.2 and above" block.
But as you have written right "OffScreenMemSize" blongs to the "VESA 2.0 and above" block and is only meaningful in case of linear frame buffer modes. But you do not need this field to use virtual resolutions from real mode.
As a test you can try this real mode Turbo Pascal test program that was written to test Nvidia Maxwell/Pascal+ GPU bug. It uses Function 07 explicitly. It should work in DosBox or with your VESA 1.2 S3 card.
Download FALCO_VBEVSTST.zip from the first post:
NVIDIA Kepler/Maxwell/Pascal VESA Bios Bug (workaround found)

Or you can also use Univbe's video mode tests without activating Univbe itself. Press spacebar until you get to the virtual scrolling test when you are testing a Banked vide0 mode.
download/file.php?id=41407

Or try the best 😀
Here is a full real mode program that uses Vesa 1.2 640x480 256 color mode and uses as many virtual pages as available to achieve smooth animation (but it will be slow on a Pentium 75):
https://falcosoft.hu/rotary_engine.zip

Ps: I have tested and all the above programs/tests work in vesa_oldvbe mode of DosBox...
So the point is you can use the virtual resolution related functions in VESA 1.2 and you do not need the"OffScreenMemSize" field for anything (which for the record has not been mentioned by me at all so I do not understand why you tried to use it). You only need the
" NumberOfImagePages" field to determine if virtual resolutions are available in VESA 1.2 modes.

Tried the three programs you posted, the rotary thingy is very cool, even not considering your expert-level VESA access! And after some more reading it seems that while you can access more of the memory, hence have another screen buffer, you access it as a chunk of memory with bank switches, which seems to be rather complex to work with. I was happy to be able to eke out a working PutImage function, albeit a slower one, now this turns it on its head 😒
The vbetest reports 2MB VRAM and also a linear framebuffer! But that is either a thingy of DOSBox or the program runs in protected mode. Can imagine accessing the linear framebuffer from real mode.

Olivetti M4 P75, 32MB RAM, 4GB HDD, 8GB CF, SoundBlaster AWE 64, Gravis Ultrasound MAX, Roland SCC-1, Roland MT-32, Roland CM-64
Intel 486DX2/66Mhz, 16MB RAM, VGA Trident 512kB, 264MB HDD Quantum, 256MB CF, SoundBlaster 16 Pro (CT2910)

Reply 14 of 59, by root42

User metadata
Rank l33t
Rank
l33t
WhiteFalcon wrote on 2022-06-20, 13:13:

Tried the three programs you posted, the rotary thingy is very cool, even not considering your expert-level VESA access! And after some more reading it seems that while you can access more of the memory, hence have another screen buffer, you access it as a chunk of memory with bank switches, which seems to be rather complex to work with. I was happy to be able to eke out a working PutImage function, albeit a slower one, now this turns it on its head 😒
The vbetest reports 2MB VRAM and also a linear framebuffer! But that is either a thingy of DOSBox or the program runs in protected mode. Can imagine accessing the linear framebuffer from real mode.

I haven't read into the details of accessing the framebuffer. But wouldn't it be simply a case of computing the linear address and then doing addr >> 16 to get the bank number?

YouTube and Bonus
80486DX@33 MHz, 16 MiB RAM, Tseng ET4000 1 MiB, SnarkBarker & GUSar Lite, PC MIDI Card+X2+SC55+MT32, OSSC

Reply 15 of 59, by RetroGamer4Ever

User metadata
Rank Oldbie
Rank
Oldbie

The few games I was able to get working with VESA graphics were so much easier on the eyes than the regular graphics. TIE Fighter, especially, as the craft looked smoother and had a more life-life feel. I think Dark Forces may have had a hidden VESA mode, as when I played it in Windows and moved the DOS screen into a Windowed mode, the graphics suddenly got far better looking, as a VESA title should have looked.

Reply 16 of 59, by Falcosoft

User metadata
Rank Oldbie
Rank
Oldbie
WhiteFalcon wrote on 2022-06-20, 11:03:

Neat! Thank you for the tips and examples, I will try it on my real PC when I get the chance again. And also here in DOSBox. As you apparently have experiences with this, how do you go about using it for double buffering? I mean you probably set the start offset from 0 to 307200 and back (for 640x480) and it should be possible to use and alternation of the method I mentioned in the first post, storing the background and restoring after the flip. But how about the banks, does the second screen start on a bank boundary, i.e. 307200? Or do you need to just consider it all as one piece of memory which will make the bank calculation for PutImage/Sprite a bit more complicated? I am somewhat afraid the latter is the case, which will again make it a bit over my head. Nevertheless it would make it completely flicker free.

Hi,
Actually selecting banks/windows is more simple than you think. You should not calculate addresses all the time. There is VESA function 05h Display Window Control. Notice that 'Window' is a different concept to multiple display pages. It works only in Banked video modes to overcome the 64K limit of the real mode video segment. This function has to be used in every mode where the mode requires more than 64K to present the full resolution regardless virtual pages are used or not.
Back to the point: VESA function 05h needs to be used only in the lowest level in your Putpixel (or similar routine). Namely:

 
mov ax, 0a000h
mov es, ax ; es segment register stores video segment all the time.
...
...
PUTPIXEL PROC ; on enter dx contains original Window number (0 at start)
push dx
mov ax, word ptr[Y_coordinate]
mul word ptr [modeinfo.BytesPerScanLine] ; scanline in bytes. If you use Function 06h to set a different virtual width then you should use the value returned in BX instead.
mov di, ax
add di, word ptr[X_coordinate]
adc dx,0
pop cx
cmp dx,cx
je @NOWINDOWCHANGE
mov ax,4f05h ;Window number = dx and Window number is already in dx !
xor bx, bx ;bh=function(0) bl=Window A(0)
int 10h
@NOWINDOWCHANGE:
mov al, byte ptr[Color]
stosb ;Store al at address ES:DI
ret
PUTPIXEL ENDP

The above code should work regardless you set the virtual display width to 2x the screen width for double buffering or you use 2x the screen height (2x scan lines).
BTW there is a description in VBE 3.0. documentation how triple buffering works. The idea is the same for double buffering it is just more simple:

Using Hardware Triple Buffering Hardware triple buffering is supported in the VBE/Core specification by allowing the application […]
Show full quote

Using Hardware Triple Buffering
Hardware triple buffering is supported in the VBE/Core specification by allowing the application
to schedule a display start address change, and then providing a function that can be called to
determine the status of the last scheduled display start address change. VBE Function 4F07h is
used for this, along with subfunctions 02h and 04h. To implement hardware triple buffering you
would use the following steps:
1. Display from the first visible buffer, and render to the second hidden buffer.
2. Schedule a display start address change for the second hidden buffer that you just
finished rendering (4F07h, 02h), and start rendering immediately to the third hidden
buffer. CRT controller is currently displaying from the first buffer.
3. Before scheduling the display start address change for the third hidden buffer, wait
until the last scheduled change has occurred (4F07h, 04h returns not 0). Schedule
display start address change for the third hidden buffer and immediately begin
rendering to the first hidden buffer. CRT controller is currently displaying from the
second buffer.
4. Repeat step 3 over and over cycling though each of the buffers.

The point is: for 640x480 double buffering you can either define an 1280x480 virtual screen with the help of Function 06h or use a 640x960 virtual screen.
In the first case your page 1 is from x=0 and your page 2 is from x=640.
In the second case your page 1 is from y=0 and your page 2 is from y=480.
In both cases you can use Function 07h to switch between page 1 and page 2.
While your page 1 is visible you draw on page 2 and vice versa.

Website, Facebook, Youtube
Falcosoft Soundfont Midi Player + Munt VSTi + BassMidi VSTi
VST Midi Driver Midi Mapper

Reply 17 of 59, by Falcosoft

User metadata
Rank Oldbie
Rank
Oldbie

I have written a little demonstration program in x86 assembly illustrating all the concepts we discussed above. You can compile it with TASM or JWASM. Set your linker to output a com file.
It uses 640x480 256 color VESA 1.2 banked video mode. It also sets and uses a 1280x960 virtual resolution for 4 different buffers. It draws a full Mandelbrot set across the 4 buffers.
After the program finished drawing you can press a key 4 times to display the content of the 4 different buffers. It requires at least 2MB video memory (works in DosBox). No error checking , contains magic constants etc. but I think it can help understand how banked mode virtual resolutions and hardware double/triple/quad buffering work.

Filename
VESAMAN.zip
File size
1.45 KiB
Downloads
49 downloads
File license
Public domain
.286
MANDEL SEGMENT
assume cs:mandel,ds:mandel,ss:mandel
org 100h
START:

mov ax,0a000h
mov es,ax
mov ax,4f02h
mov bx,101h
int 10h ; sets 640x480 256 color mode

mov ax,4f06h
mov bx,0
mov cx,1280 ; sets virtual scanline width to 1280 px. Notice that you do not have to define height, but DX returns the maximum possible height.
int 10h


fld dword ptr [initb]
fstp dword ptr [b]
mov word ptr[loop1],0
jmp @A1
@L1:
inc word ptr [loop1]
@A1:
fld dword ptr[b]
fadd dword ptr[lp]
fstp dword ptr[b]
fld dword ptr[inita]
fstp dword ptr[a]
mov word ptr[loop2],0
jmp @A2
@L2:
inc word ptr [loop2]
@A2:
fld dword ptr[a]
fadd dword ptr[lp2]
fstp dword ptr[a]
CALL ITERATE

cmp bx,word ptr [maxi]
jae @NOPUT
CALL PUTPIXEL
@NOPUT:
cmp word ptr[loop2],1279
jne @L2
cmp word ptr[loop1],959
jne @L1

xor ax,ax ;wait for keypress
int 16h
mov ax,4f07h ;this block sets lower left page 2
xor bx,bx
mov bl,00h
mov cx,0
mov dx,480
int 10h

xor ax,ax ;wait for keypress
int 16h
Show last 109 lines
            mov ax,4f07h  ;this block sets lower right page 3
xor bx,bx
mov bl,00h
mov cx,640
mov dx,480
int 10h

xor ax,ax ;wait for keypress
int 16h
mov ax,4f07h ;this block sets upper right page 4
xor bx,bx
mov bl,00h
mov cx,640
mov dx,0
int 10h

xor ax,ax ;wait for keypress
int 16h
mov ax,4f07h ;this block sets back original upper left page 1
xor bx,bx
mov bl,00h
mov cx,0
mov dx,0
int 10h

xor ax,ax
int 16h
mov ax,3
int 10h
mov ax,4c00h
INT 21h


ITERATE PROC
fld dword ptr [a]
fld dword ptr [b]
fild dword ptr [bout]
xor bx,bx
fldz
fldz
fldz
fldz
@ITER:
fmul st,st(3)
fadd st,st(0)
fadd st,st(5)
fincstp
fsub st,st(1)
fadd st,st(5)
fst st(2)
fmul st,st(0)
inc bx
fst st(6)
fdecstp
fst st(2)
fmul st(2),st
fdecstp
fadd st,st(3)
fcomp st(5)
fnstsw ax
and ah,41h
jz @OK
cmp bx,word ptr[maxi]
jb @ITER
@OK:
finit
ret
ITERATE ENDP


PUTPIXEL PROC
push dx
mov ax,1280
mul word ptr[loop1]
mov di,ax
add di,word ptr[loop2]
adc dx,0
pop cx
cmp dx,cx
je @NOPAGING
push bx
mov ax,4f05h ;Window number=dx
mov bx,00h ;bh=function(0) bl=window(0)
int 10h
pop bx
@NOPAGING:
add bl,byte ptr[color]
mov es:[di],bl
ret
PUTPIXEL ENDP




b :DD ?
a :DD ?
loop1:DW ?
loop2:DW ?
initb:DD -1.2
inita:DD -2.4
lp :DD 0.0025
lp2 :DD 0.0025
bout :DD 4
maxi :DW 100
color:DB -2


MANDEL ENDS
END START

Website, Facebook, Youtube
Falcosoft Soundfont Midi Player + Munt VSTi + BassMidi VSTi
VST Midi Driver Midi Mapper

Reply 18 of 59, by WhiteFalcon

User metadata
Rank Newbie
Rank
Newbie
root42 wrote on 2022-06-20, 13:28:
WhiteFalcon wrote on 2022-06-20, 13:13:

Tried the three programs you posted, the rotary thingy is very cool, even not considering your expert-level VESA access! And after some more reading it seems that while you can access more of the memory, hence have another screen buffer, you access it as a chunk of memory with bank switches, which seems to be rather complex to work with. I was happy to be able to eke out a working PutImage function, albeit a slower one, now this turns it on its head 😒
The vbetest reports 2MB VRAM and also a linear framebuffer! But that is either a thingy of DOSBox or the program runs in protected mode. Can imagine accessing the linear framebuffer from real mode.

I haven't read into the details of accessing the framebuffer. But wouldn't it be simply a case of computing the linear address and then doing addr >> 16 to get the bank number?

If that was the case I guess it would cancel out the benefits of the linearity 😀 What you described is the standard bank-based access I am using now.

Olivetti M4 P75, 32MB RAM, 4GB HDD, 8GB CF, SoundBlaster AWE 64, Gravis Ultrasound MAX, Roland SCC-1, Roland MT-32, Roland CM-64
Intel 486DX2/66Mhz, 16MB RAM, VGA Trident 512kB, 264MB HDD Quantum, 256MB CF, SoundBlaster 16 Pro (CT2910)

Reply 19 of 59, by WhiteFalcon

User metadata
Rank Newbie
Rank
Newbie
RetroGamer4Ever wrote on 2022-06-20, 13:32:

The few games I was able to get working with VESA graphics were so much easier on the eyes than the regular graphics. TIE Fighter, especially, as the craft looked smoother and had a more life-life feel. I think Dark Forces may have had a hidden VESA mode, as when I played it in Windows and moved the DOS screen into a Windowed mode, the graphics suddenly got far better looking, as a VESA title should have looked.

Isnt that more like that when you run a DOS game in a sall window, the pixels are much smaller hence make it all look crisper, cleaner? VESA is just the standard for accessing higher resolutions and more colors on old gfx cards.

Olivetti M4 P75, 32MB RAM, 4GB HDD, 8GB CF, SoundBlaster AWE 64, Gravis Ultrasound MAX, Roland SCC-1, Roland MT-32, Roland CM-64
Intel 486DX2/66Mhz, 16MB RAM, VGA Trident 512kB, 264MB HDD Quantum, 256MB CF, SoundBlaster 16 Pro (CT2910)