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
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 ?
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.
@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 ....
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
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
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
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
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.
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.
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
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.
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.
i still have a couple tridents - lol
and - a few thai no-namers
i have a pile of the diamond s-3 cards :P
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.
Hi,
In a strict real mode situation, you have no choice in using the
bank switch function. Slow or not, it's what you must use.
Steve N.
probably why VESA died :P
HI Dave,
Doubtful. In protected mode you can use flat addresses.
More likely, if dead, it was lack of support from M$ and Linux
developers. My Windows 2000 system does not support VESA
in a command prompt, whereas DOS and OS/2's VDM both
allow VESA modes on the same hardware. (Throw in the
"unreal mode" for good luck if needed!)
Cheers,
Steve N.