News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

I would like faster DOS graphics

Started by ChrisLeslie, April 02, 2006, 05:30:04 AM

Previous topic - Next topic

ChrisLeslie

I am writing some simple code in graphics mode via ah=0, int10h. Mode set is al=12h which gives a 640x480 screen resolution. My problem is that writing pixels to screen is very slow using ah=0Ch, int 10h. My guess is that drawing lines by this means is about 40-50 times slower than equivalent GUI line drawing in Windows. Is there a more direct method for drawing pixels rather than the BIOS routine. I have tried addressing 0A00h but can't get to draw a pixel.
Does anybody know a faster alternative means to using BIOS int 10h to do DOS graphics?

Chris

Dinosaur

Chris

The routine in the zip file enclosed works well for me.
I call it from basic in a fast weighing sytem.
It is not my code but it may help you understand the method.

Regards

[attachment deleted by admin]

MichaelW

Chris,

I am guessing that your attempt to write directly to the display buffer failed because you were writing to only a single bit plane. A standard VGA has 256KB of display memory that is logically segmented into four bit planes of 64KB each. The display memory is accessed (read or write) through a single 64KB window in the host address space at segment address A000h. For mode 12h, there are 640 * 480 = 307200 pixels, and each pixel requires 4 bits to store the pixel color, so 307200 / 2 = 153600 bytes are required, with 153600 / 4 = 38400 bytes in each bit plane.

The attachment uses the most direct method I know of to write a single pixel for mode 12h. On my system this method, encapsulated in a procedure, can write a pixel in about 40% of the time required by the BIOS function. For drawing lines (of a uniform color) you could do all of the setup outside of your run loop, changing only the bit mask and the pixel byte address, and performing the dummy write, within the loop. It might be worth noting that in his book Programmer's Guide to the EGA and VGA Cards, Richard F. Ferraro precedes the dummy write with a dummy read of the same address, and writes the value read. I don't recall seeing a reason for this, but I'm guessing that it has something to do with caching.

If you are willing to drop down to 320x200, you could get a large speed increase by using mode 13h. In this mode the VGA still uses four bit planes, but the hardware handles all of the bit plane stuff automatically, so each pixel is represented by a single byte, and the entire buffer fits into a single 64000-byte segment. I included a mode 13h SetPixel procedure for reference, and on my system it is something like 50 times faster than the mode 12h SetPixel procedure.




[attachment deleted by admin]
eschew obfuscation

ChrisLeslie

Thankyou MichaelW

Thanks for the code example. I tried using the mode 13h method and I do indeed get very fast line drawing but the resolution is too poor - looks like a chunky toy!  :lol 
With the mode 12h I can draw pixels but the addresses must be screwed up somehow so far because there is a gap between horizontal adjacent pixels. Vertical pixels do not have gaps. From what I can tell with the speed, it still is not be fast enough for satisfactory screen refreshing. I shall keep on trying. :wink

Regards  :U

Chris


ChrisLeslie

Problem found.  :red
I was trying to do mode 12h in a DOS full screen in WinXP. I cannot access io ports, therefore I cannot read/write to the registers with in/out. :lol
Don't you just hate Microsoft sometimes. :boohoo:

Chris

raymond

I haven't played with that for many years. When I started accessing the video card directly, I spent a few dollars and purchased a book explaining all the details when I still had a 386SX 16MHz box. Only then could I perform adequate work.

For instance I remember that, when scrolling text on the screen with the DOS functions in the 12h mode, I could actually see the scrolling taking place. After I wrote a procedure to "draw" the text myself (using the same character bitmap as DOS), the text seemed to be displayed INSTANTANEOUSLY. I couldn't measure the gain in speed but it was certainly much better than 40%.

The other thing I learned the hard way was that different video cards had different paging systems. Some were 64k while others were 4k. DOS functions were available to retrieve this info before you would start writing to video memory. I had to put in code to cover both cases so that my app would work on other computers.

Have fun

Raymond
When you assume something, you risk being wrong half the time
http://www.ray.masmcode.com

MichaelW

Chris,

You cannot access the VGA I/O ports under Windows XP, from a DOS app? I seem to recall testing the VGA I/O ports from a DOS app running full screen under Windows XP, and I don't recall a problem. I can run the program I posted and the one in the attachment full screen under Windows 2000 without problems, but they will hang if I run them in a window.

The attachment contains a mode 12h horizontal line procedure that uses, AFAIK, the fastest method possible for the hardware. The procedure could be optimized a little better, but I doubt that the speed could be increased significantly.



[attachment deleted by admin]
eschew obfuscation

ChrisLeslie

MichaelW

The hline procedure works fine in a full screen, very fast  :U 
For some reason the setpixel proc leaves gaps in horizontal lines. I shall examine the procs for how it is done later when I get some time.  ::)

Thanks very much for your help
Chris

MichaelW

I determined that the problem with the method used in the set pixel procedure was the last minute change I made eliminating the dummy read before the dummy write. The value written does not matter, because the color data is being provided by the Set/Reset register, but without the dummy read the method will work correctly only for single pixels. In the time I spend on it I could not determine what was happening, but I now think it has something to do with the value loaded into the internal 32-bit processor latch, or some other internal register.

eschew obfuscation

Mark Jones

Quote from: ChrisLeslie on April 04, 2006, 11:54:44 PM
I cannot access io ports, therefore I cannot read/write to the registers with in/out. :lol

Can't WinIO bypass this limitation in XP console box? See their FAQ: http://www.internals.com/faq_main.htm
The MASM demo made in the Workshop (I believe) can access any I/O range, not just COM1-4 and LPT port addresses. I hope we're thinking of the same thing (I am still a noob!) :green   But the main code for the test file is as follows:


    invoke InitializeWinIo
    print ustr$(eax),13,10

    invoke MapPhysToLin, 400h, 256, ADDR hPhysMem
    mov   ebx, eax
    print uhex$(ebx),"h",13,10
   
    movzx eax, WORD PTR[ebx]   ; Base I/O address of first serial port
    print uhex$(eax),"h",13,10
    movzx eax, WORD PTR[ebx+8] ; Base I/O address of first parallel port
    print uhex$(eax),"h",13,10

    invoke UnmapPhysicalMemory, hPhysMem, ebx
   
    print uhex$(inp(379h)),"h",13,10
   
    invoke ShutdownWinIo

    inkey "Press any key to exit..."
"To deny our impulses... foolish; to revel in them, chaos." MCJ 2003.08

ChrisLeslie

MichaelW
The "hline" procedure, which is optimised for horizontal lines, works so fast that I can fill a whole screen in an instant. If I modify it to draw pixels, and then write another procedure to draw lines using the pixels, it works not as fast, but faster then using entirely bios interrupts. :thumbu

Mark
To quote from your link:
QuoteUnder Windows NT/2000, user mode applications are completely prohibited from accessing I/O ports. Any attempt to access an I/O port from a ring 3 application is terminated with a protection fault.
:eek
Somehow the VGA port addresses can be written to by the above procedure using my WinXP in full screen mode.
I'm not complaining, but certainly learning every day  :bg

Chris