News:

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

VESA - Bankswitching problems

Started by blaalb2, March 29, 2012, 06:46:10 AM

Previous topic - Next topic

blaalb2

Hello all.

I know it's very oldschool, but maybe some can help me  :8)

I use a 8:8:8 Color Mode, 112h (640x480x32).


MOV AX, 640
MOV BX, 479
MUL BX
ADD AX, 639
MOV BX, 4
MUL BX
MOV var, DX


The problem is to get the correct bank.

The math:
offset = (screenwidth * y + x) * 4
bank = offset / FFFFh

The logic:
after a mul, DX holds the high word, AX the low word. So DX have to be my bank, but it doesn't work  ::)

So, where is my braincrash?

Greetz,
blaalb

dedndave

i don't recall the orginization for mode 112h   :P
but, if you are using 8:8:8, then each pixel uses 3 bytes, eh ?
you may have to multiply by 3

also, there is a thing called "granularity"
the banks are set up differently for different modes

here is a little document i found with a quick google search...
http://www.opferman.net/Text/svga.txt

i guess you already know that VESA is old stuff   :red
are you programming for win95/98 ?

MichaelW

#2
Here is the relevant information returned by the Return VBE Mode Information function for the mode 112h for my Matrox G400, which AFAIK is typical:

Mode supports banking of the frame buffer.
Host memory window A is relocatable.
Host memory window A is readable.
Host memory window A is writeable.
Host memory window B is NOT relocatable.
Host memory window B is NOT readable.
Host memory window B is NOT writeable.
Frame buffer memory granularity in KB = 64
Host memory window size in KB =  64
Host memory window A segment = A000
Host memory window B segment = 0
Banking function offset = 7153
Banking function segment = C000

Bytes per scan line = 2560
X resolution = 640
Y resolution = 480
Bits per pixel = 32

Memory model type = Direct color

Red mask size = 8
Red field position = 16
Green mask size = 8
Green field position = 8
Blue mask size = 8
Blue field position = 0
Reserved mask size = 8
Reserved mask position = 24


The key points are that there is only one host memory window (A), with a size and granularity of 64KB, and there are 32 bits per pixel.
eschew obfuscation

blaalb2

@dedndave:
I think * 4 is correct, because the Mode is 32bpp.

Granularity and WinSize is 64KB, so the bankmul is 1.

@MichaelW:
Thanks for the vbemodeinfos, i have checked them before i was trying to get the correct bank, because of the bankmul (wingran / winsize).

QuoteThe key points are that there is only one host memory window (A), with a size and granularity of 64KB, and there are 32 bits per pixel.

I don't understand this. What it say?

----------

If we let all the VESA stuff apart and look just on the math and code, the problem rest.

640 x 479 + 639 = 307199

307199 * 4 = 1228796

After this, AX = 49148 / DX = 2.

1228796 / 65536 = 18.xxx

18 * 65536 =  1179648

1179648 + 49148 = 1228769

Why is in DX the value 2 after the mul operation? Where is my failure, or, how can i get most optimized the bank? Can't i get the bank through the mul operation? I know i can get the bank by div offset / 65535, thats not the problem. but i think i can get the correct value through mul. This saves a extra div ....



FORTRANS

Hi,

   Here is some of the the code I use for VESA modes.
And the information for the computer I am using to post.

Regards,

Steve N.


VESA version number  2.0  OEM String:  Matrox Graphics Inc.
Capabilities of the video environment;
0 = DAC is fixed width, 1 = DAC width is switchable. 1
Number of 64kb memory blocks on board 512

Supported VESA video modes.
0100 0101 0102 0103 0110 0111 0112 0113 0114 0115 010A

Information for VESA video mode 0112
Mode attributes         009B               LFBWnVGAGr Co    1 Hw
  Window A attributes    07        Window B attributes     00
Window granularity      64 KB     Window size             64 KB
  Window A start segment A000      Window B start segment  0000
Window function pointer C000:7153
Bytes per scan line     2560
APA Resolution          640 x 480  Character Cell   8 x 16
Number of planes        1         Bits per pixel   32 8:8:8:8 24,16,8,0
Memory model type       6 Direct Color   DC Mode Information RP
Number of banks         1         Bank size 0 KB
Additional image pages  12


   Code fragment  to test for correct page/bank.


; Create DX:BX byte count for 24/32 bit color to point to the
; specified pixel.  Revised 22 August 2001.

        MOV     AX,[usY] ; AX = y
        XOR     DX,DX
        MOV     BX,[BytesPerScanLine]   ; Fix as suggested by Stefan Peichl
        MUL     BX                      ; DX:AX = bytes from usY
        MOV     CX,DX
        MOV     BX,AX                   ; CX:BX = bytes from usY

        XOR     DX,DX
        MOV     AX,[usX] ; AX = x
        MUL     [TrueSize]      ; Mul usX word by Bytes per pixel
                                ; DX:AX = bytes from usX

        ADD     BX,AX           ; Combine intermediate results
        ADC     DX,0
        ADD     DX,CX           ; Restore DX:BX identity

        CMP     DX,[CurPage]    ; In the right window bank?
        JE      SP112_1
        CALL SetPage
SP112_1:


   Code to change to proper page.


; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; DX = Implied segment / 64k bank
; 14 August 2001
        PUBLIC  SetPage
SETPAGE PROC    NEAR

        PUSH    BX      ; Save BX pointer within bank

        MOV     [CurPage],DX
        MOV     AX,[PageGran]
        MUL     DX
        MOV     DX,AX
        MOV     AX,4F05H ; VESA change bank
        MOV     BX,0
        INT     10H

        POP     BX

        RET
SETPAGE ENDP

dedndave

if i am not mistaken, the results of INT 10h, function 4F01h might be different for the same mode on different adapters
at any rate...

if you are using 32 bpp, you must multiply by 4   :P
there is no instruction to multiply DX:AX by 4
i suggest you multiply the X values by 4 before applying them

(640*4) * 479
+ (639*4)

to multiply these small values by 4, you can use SHL or let the assembler do it
and - don't forget to carry into DX after the ADD...

        mov     ax,640*4
        mov     bx,479
        mul     bx
        add     ax,639*4
        adc     dx,0


        mov     cx,640*4
        mov     ax,479
        mul     cx
        mov     cx,639
        shl     cx,1
        shl     cx,1
        add     ax,cx
        adc     dx,0


the last one is probably something like what you want   :bg

FORTRANS

Quote from: dedndave on March 29, 2012, 02:30:43 PM
if i am not mistaken, the results of INT 10h, function 4F01h might be different for the same mode on different adapters
at any rate...

Hi,

   Absolutly, different models of graphics cards have different
characteristics.  If I remember correctly (...) my Matrox card
has 32-bits per pixel and 64k granularity for mode 122H.  My
Western Digital card had 24-bits and 4K for the same mode
(640x480xRGB).

Regards,

Steve

MichaelW

Regarding the differences between adapters, at one time I did a small survey of display adapters that I had in my own systems, and in other systems that I had access to. The biggest difference that I encountered was in the number of modes supported. I found little or no variation in the details of the VESA-defined modes that I looked at, and little or no variation in the size and granularity of the host memory window and the number of host memory windows. And I basically ignored the OEM modes defined after VESA stopped defining new mode numbers (AFAIK the highest normal mode number that VESA defined was 11Bh).

This is crude, and I made some assumptions that may not be valid for some systems.

;==============================================================================
.model small,c
.386
.stack
;==============================================================================
.data
    err    db "X$"
.code
;==============================================================================
.startup
;==============================================================================

    mov ax, 4f02h
    mov bx, 112h
    int 10h
    .IF ax != 4fh
        mov ah, 9
        mov dx, OFFSET err
        int 21h
    .ENDIF

    push 0a000h
    pop es

    xor esi, esi        ; X
    xor edi, edi        ; Y

    .WHILE esi < 480

        ;-------------------------------------------
        ; frame_buffer_offset = 4 * (Y * width + X)
        ;-------------------------------------------

        mov eax, 640
        mul edi
        add eax, esi
        shl eax, 2
        push eax

        ;-------------------------------------
        ; bank = frame_buffer_offset / 0FFFFh
        ;-------------------------------------

        shr eax, 16

        mov dx, ax
        mov ax, 4f05h
        ;---------------------------------------------
        ; Assume that only host window A is supported
        ;---------------------------------------------
        xor bx, bx
        int 10h

        ;-----------------------------------------------------
        ; host_window_offset = frame_buffer_offset MOD 10000h
        ;-----------------------------------------------------

        pop eax
        mov ecx, 10000h
        cdq
        div ecx

        mov bx, dx
        mov eax, 0ffh
        mov es:[bx], eax

        inc esi
        inc edi

    .ENDW

    xor ah, ah
    int 16h

;==============================================================================
.exit
end

eschew obfuscation

blaalb2

Thanks a lot for all help and code snippets  :U

My working write pixel procedure:
  MOV CX, SCRWidth
  SHL CX, 2
  MOV AX, YPos
  MUL CX
  MOV CX, XPos
  SHL CX, 2
  ADD AX, CX
  ADC DX, 0
  MOV DI, AX

  CMP DX, Bank
  JE @@NoBankSwitch
  MOV Bank, DX

  MOV AX, $4F05
  XOR BX, BX
  INT 10h

@@NoBankSwitch:
  MOV AH, Green
  MOV AL, Blue
  MOV [ES:DI], AX
  LEA DI, [DI+2]
  MOV AL, Red
  MOV [ES:DI], AL


It is usable or can i more optimize this routine?
A000h -> ES is a extra procedure, saves 2 more instructions per pixel.

----------

One think i don't understand is this instruction:
ADC DX, 0

It handles the carry Flag, that's what i understand. But what it does really? Without this instructions, not all pixels get written.

----------

@dedndave:

Quotei guess you already know that VESA is old stuff   
are you programming for win95/98 ?

We learn Pascal in informatics. I was thinking, VESA for graphics output is okay for pascal, because it's old stuff too.

FORTRANS

Quote from: blaalb2 on March 30, 2012, 01:35:12 PM
One think i don't understand is this instruction:
ADC DX, 0

It handles the carry Flag, that's what i understand. But what it does really? Without this instructions, not all pixels get written.

Hi,

   ADC is the mnemonic for ADd with Carry.  It will add the second
operand to the first operand and add in the carry flag as well.  So
ADC DX,0 is adding one to the contents of DX if the carry flag is set
and not changing DX if the carry flag is not set.  It alows an add to
extend (propagate) to more than one register.  It perfroms the carry
from one register to another as one would perform carries fron one
column to the next higher in manual pencil and paper addition.

HTH,

Steve N.

dedndave

  MOV CX, SCRWidth
  SHL CX, 2


in this case, the SHL is unnecessary, as SCRWidth is a constant
for constants that are known at assembly-time, you can let the assembler do the calculation...

first, SCRWidth should be an EQUate, if it isn't already
SCRWidth EQU 640

then, the assembler can calculate "4 times" for you
  MOV CX, 4*SCRWidth

Steve did a nice job of explaining what ADC does
but, i might add this...

  ADD AX, CX
  ADC DX, 0


this code allows you to treat the values in DX:AX as a single large (32-bit) value when adding CX to it

if BX:CX contained another 32-bit value...
  ADD AX, CX
  ADC DX, BX


you can extend precision like that forever   :P
adding SI:BX:CX to DI:DX:AX
  ADD AX, CX
  ADC DX, BX
  ADC DI, SI


and, there is the subtract equiv - SBB (subtract with borrow)
to subtract SI:BX:CX from DI:DX:AX
  SUB AX, CX
  SBB DX, BX
  SBB DI, SI

FORTRANS

Quote from: MichaelW on March 30, 2012, 06:45:26 AM
Regarding the differences between adapters, at one time I did a small survey of display adapters that I had in my own systems, and in other systems that I had access to. The biggest difference that I encountered was in the number of modes supported. I found little or no variation in the details of the VESA-defined modes that I looked at, and little or no variation in the size and granularity of the host memory window and the number of host memory windows.

Hi,

  (Un)fortunately, I had the one manufacturer's (Western Digital,
Paradise) adapter that had a granularity other than 64k.  (That I
know of.)  And I helped another programmer to support my system
with his program.  So I ended up checking a few more parameters
than most people.  I think 32-bit RGB is the default now, but earlier
cards tended to be a mix of 24 and 32-bit RGB.  And there was a
case of RGB and BGR byte ordering as well.

Cheers,

Steve N.

sinsi

There was a Trident card years ago with a window size of 128K (A000-BFFF) that messed me up for a while.
I had a Paradise card with 4K granularity and an ATI card with 16K granularity.
Light travels faster than sound, that's why some people seem bright until you hear them.

dedndave

i still have a couple tridents - lol
and - a few thai no-namers
i have a pile of the diamond s-3 cards   :P

Farabi

If you re going to use the bank switch for pixel operation, I suggest dont do it since bank switch is very slow, use bank switch only for the Bliting function.
Those who had universe knowledges can control the world by a micro processor.
http://www.wix.com/farabio/firstpage

"Etos siperi elegi"