Mode 12h

Programming, for all ages and all languages.
REV

Mode 12h

Post 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.
mystran

Re:Mode 12h

Post 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).
REV

Re:Mode 12h

Post 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)
crackers

Re:Mode 12h

Post 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.
dc0d32

Re:Mode 12h

Post 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.
mystran

Re:Mode 12h

Post 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.
JAAman

Re:Mode 12h

Post 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)
Dex4u

Re:Mode 12h

Post 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
 
JAAman

Re:Mode 12h

Post 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)
Dex4u

Re:Mode 12h

Post 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.
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Re:Mode 12h

Post 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.
Dex4u

Re:Mode 12h

Post 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.
earlz

Re:Mode 12h

Post 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
REV

Re:Mode 12h

Post by REV »

So for example:

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

p = 640.375

What do I do here now?
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Re:Mode 12h

Post 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);
Post Reply