Page 1 of 2

Mode 12h

Posted: Fri May 19, 2006 2:47 pm
by REV
Hi, I have no idea how bit-planes work or how to plot a pixel in Mode 12h. Is there someone who can fully explain to me how they work or a document that fully explains to me how they work?

Any help would be greatly appreciated.

Re:Mode 12h

Posted: Fri May 19, 2006 5:30 pm
by mystran
Yeah.

Basicly, for a black&white display, you have one bit per pixel, right? So things are really simple, because you have a two dimensional array. Now, if you think of color display, you have a three dimensional array instead: x, y, bitnumber.

In "regular" case, we have an array of lines, containing array of pixels on that line, containing array of bits. So what you think of as a color number, is really just an array of bits, if you think of it. It's used as a number yes, but bit is the smallest unit.

A bitplane system has an array of bit positions, array of lines, containing array of pixels on that line.

So instead of first finding a line, then a pixel on that line, and then the bit you want to modify, you start with the bit, and then find the line, and then the pixel.

But since you probably didn't understand it yet (I wouldn't understand it from the above) I'm going to provide a link to Amiga FAQ which explains the thing quite well:

http://oldwww.nvg.ntnu.no/amiga/amigafa ... html#SEC16

It calls bitplanes a 'planar' mode, and "regular" mode 'chunky' mode, and has nice ascii art for the 1D case (to avoid needing 3d graphics).

Re:Mode 12h

Posted: Tue May 23, 2006 12:02 pm
by REV
Hi, Yeha I undertsand what bit-planes are I guess they work just like binarys but how do I write a putpixel routine?

Like switching and related. Do I need to use inline assembly or the out function (which I do have written). I'm using this for my shell/GUI and this needs to be fast. What is the fastest way to plot a pixel in C? (Watcom C)

I know I have to do bank switching. I sorta know what that means but not fully.

(I'm very new to graphics programming, I'm better for the 'background stuff' but I would like to learn this now)

Re:Mode 12h

Posted: Tue May 23, 2006 1:56 pm
by crackers
You can put pixel by writting something from 0XA0000 to 0xA0000 + 64 KB which means that you have 64 KB memory of video card mapped to RAM. In low resolution it's sufficient for example in 13h mode resolution is 320x200, color depth is 256 so it's one byte ergo 320x200x1= 64 KB, but in higher resolutions, or modes which are using high or true color mapping 64 KB of memory is not enough. Solution to this problem are banks. By changing banks you can get access to others 64KB of video card memory. For example if you want to clear screen in 640x480x256 mode, you'll have to change bank 5 times (640x480 / 64KB = +-5) and after each change write zeros (or other number that was set to be black) to memory from 0xA0000 to 0xA0000 + 64KB.
If I made any mistake please correct me somebody.

Re:Mode 12h

Posted: Tue May 23, 2006 3:49 pm
by dc0d32
maybe you should have a look at modes.c by Chris Griese [spelling may be wrong], a link is provided in OSFAQ2. just search.

Re:Mode 12h

Posted: Tue May 23, 2006 5:10 pm
by mystran
If you do some kind of double buffering or whatever (like you probably should) then I suggest you keep your screen in a easier-to-process format in some array, and convert to bit-planes when you update the screen. It'll be faster too, because you can move data for several pixels to the graphics memory with a single write.

You can still update only certain ('dirty') regions if you don't want to update it all every time.

Re:Mode 12h

Posted: Thu May 25, 2006 8:09 am
by JAAman
crackers wrote: For example if you want to clear screen in 640x480x256 mode, you'll have to change bank 5 times (640x480 / 64KB = +-5) and after each change write zeros (or other number that was set to be black) to memory from 0xA0000 to 0xA0000 + 64KB.
If I made any mistake please correct me somebody.
640x480x256 doesnt use bit-planes, rather it uses banking -- these are 2 very different consepts, and they work in very different ways mode 0x12 uses bitplanes, most higher modes use banking (which is why so many people try to avoid standard VGA (640x480x16 -- mode 0x12))

with bit planes, there would be a separate bank for each bit (and you can map multiple banks in at once -- meaning only 1 bank change to clear the screen -- enable all 4 banks)

Re:Mode 12h

Posted: Fri May 26, 2006 8:48 am
by Dex4u
If you have vesa 1, its much simpler to use, this bit of code fill the screen with a color:

Code: Select all

 mov ax,4f02h  ;set vesa 1.0 screen mode
 mov bx,101h  ;640*480*256 ;look for the vesa number for graphic size
 int 10h
 
 mov dx,0xa000
 mov ds,dx              ;sets up registers
 call window
 rain:
 xor dx,dx      ;(pages-1)
 
 mouse:
 push dx
 call window
 xor bx,bx
 mov al, 0cch
 call dog
 pop dx
 cmp dx,4                ; devide the screen size by 64k, -1 and replace the 4 with the number.
 je rain
 inc dx
 mov ah,01h
 int 16h                   ; have we pressed a key,if no then loop
 jz mouse
 
 mov ax,0003h       ;back to text mode.
 int 10h
 
 mov ax,4c00h      ; This is just 
 int 21h                ; for test ,take it out in your OS 
 
 window:
 mov ax,4f05h    ;vesa 1 window select
 mov bx,0
 int 10h        ;dx is  the reqired window
 xor bx,bx
 ret
 
 dog:        ;(4*2^16)+45056 pixels
 mov [bx],al
 inc bx
 cmp bx,$00000
 jne dog
 ret
 

Re:Mode 12h

Posted: Fri May 26, 2006 9:15 am
by JAAman
did you forget to look at the title of the thread?
he specifically mentioned mode 0x12

and his question is about bit planes not banking!

you calculate which bit you want to change (multiply your row by 640, and add your column, and devide by 8 -- that is the byte, the remainder is the bit)

map all banks, and clear that bit

then you map in all banks that are used (mode 12h has 4 bits per pixel -- 1 for each bank, makes it easy -- the color contains the 4 bits needed -- just use it to select the bank)

then you set the bit -- your color will appear at the appropriate location


for performance reasons, its usually best to do more at once instead of one pixel at a time (less bank switching, which is a real performance killer)

Re:Mode 12h

Posted: Fri May 26, 2006 11:36 am
by Dex4u
JAAman wrote: did you forget to look at the title of the thread?
he specifically mentioned mode 0x12

and his question is about bit planes not banking!
Yes i read the title, but some time people think that it is, much easier to use mode 12h, than vesa, by pointing them to some easy code, it may help them with there problems.

If not, it gives board people like you, something to moan about.

Re:Mode 12h

Posted: Sun May 28, 2006 5:45 am
by Candy
Dex4u wrote: Yes i read the title, but some time people think that it is, much easier to use mode 12h, than vesa, by pointing them to some easy code, it may help them with there problems.
You don't solve their problems by telling to avoid them. You don't learn what the solution was if you never find out.

Re:Mode 12h

Posted: Sun May 28, 2006 6:41 am
by Dex4u
Candy wrote:
Dex4u wrote: Yes i read the title, but some time people think that it is, much easier to use mode 12h, than vesa, by pointing them to some easy code, it may help them with there problems.
You don't solve their problems by telling to avoid them. You don't learn what the solution was if you never find out.
Let take why people use or used mode 12h, that is to get 640x480 screen size in realmode.
So the problem is "how to get 640x480 screen size in realmode", if that is the case, and if he/she has vesa1, then they can get that screen size with the above code.
Problem solved.

Re:Mode 12h

Posted: Sun May 28, 2006 3:29 pm
by earlz
(multiply your row by 640, and add your column, and devide by 8 -- that is the byte, the remainder is the bit)
omg I love you I have been using a very slow for() loop to figure out stuff with bits

Re:Mode 12h

Posted: Fri Jun 02, 2006 10:59 am
by REV
So for example:

y = 8
x = 3
p = ((640 * 8) + 3) /8

p = 640.375

What do I do here now?

Re:Mode 12h

Posted: Fri Jun 02, 2006 11:17 am
by Candy
REV wrote: So for example:

y = 8
x = 3
p = ((640 * 8 ) + 3) /8

p = 640.375

What do I do here now?
You're not thinking integrally.

p = ((640 * 8 ) + 3 ) / 8 = 640
bitoffs = ((640 * 8 ) + 3) % 8 = 3

You need byte 640, bit 3. That has a bit value of (1<<3) == 8.

In short:

Code: Select all

int bitoffs = ((xres * y) + x);
int p = bitoffs >> 3;  // divide by 8
bitoffs &= 0x7;  // only the last 3 bits, the bit offset
char *vidmem = (char *)0xA0000;
vidmem[p] |= (1 << bitoffs);