Page 1 of 2

Graphics mode

Posted: Sun Mar 05, 2006 2:51 pm
by ajanh
hi every body...
i want to know how can i write a char in graphics mode with
simple assembly IRQ please be carefull writing a char not put a pixel
becasue i tried to write a char with assembly 0x10 int
and function 0x0e,i wrote the char but it gave me black background
on my blue one

Re:Graphics mode

Posted: Sun Mar 05, 2006 4:02 pm
by Brendan
Hi,
ajanh wrote:i want to know how can i write a char in graphics mode with
simple assembly IRQ please be carefull writing a char not put a pixel
becasue i tried to write a char with assembly 0x10 int
and function 0x0e,i wrote the char but it gave me black background
on my blue one
If you're using a standard VGA mode (e.g. mode 0x12 or 0x13) you might be able to use the write character and attribute at cursor or the write character at cursor BIOS functions (instead of the teletype output function).

If you're not using a standard VGA mode (for e.g. you've used VBE to set an SVGA mode) then you should write your own routines to draw characters - IIRC the VBE standard says that support for any of the BIOS character output routines is optional (so character output might work in some modes on some video cards, but not on all video cards).

I'd recommend writing your own routines to draw characters anyway - the BIOS functions are too slow.


Cheers,

Brendan

Re:Graphics mode

Posted: Sun Mar 05, 2006 5:01 pm
by earlz
plus with your own routine it should be very easy to add new fonts and change them

it shouldn't be too hard to do

all you have to do is make a font
the font format should be bitmaps of each character so every bit represents 1 pixel and if it is set then you draw the foreground color if its not then draw background

then just use plot(curx*8+x_draw,cury*8+y_draw) assuming you are using 8x8 characters(like most text modes) you just have a while loop and every time x_draw gets to 8(which you advance each pixel) you advance y_draw and set x_draw to 0
then when both y_draw and x_draw is 8 you advance curx BY ONE and if its a new line then you advance cury BY ONE

and voila

Re:Graphics mode

Posted: Sun Mar 05, 2006 5:56 pm
by Brendan
Hi,
Jordan3 wrote:all you have to do is make a font
the font format should be bitmaps of each character so every bit represents 1 pixel and if it is set then you draw the foreground color if its not then draw background
It's much easier to use the BIOS's fonts (which are in the same format). For example:

Code: Select all

   mov bh,3               ;Get address for first half of BIOS 8 * 8 character font
   mov ax,0x1130
   int 0x10               ;es:bp = address of BIOS 8 * 8 characters (first half)
   clr eax                  ;Make sure high 16 bits of [ieax] are clear
   movzx ebx,bp               ;ebx = real mode offset (with high 16 bits cleared)
   mov ax,es               ;eax = real mode segment (with high 16 bits cleared)
   shl eax,4               ;eax = real mode segment base address
   add eax,ebx               ;eax = 32 bit address of font data
   mov [fontAddress8x8_firstHalf],eax      ;Set the 32 bit font address
For drawing characters there's different ways to do it, with different performance. The first thing I'd do is use a double buffer (draw the characters into RAM, and then when everything is ready copy from RAM into display memory). To speed this up I like to keep track of which lines have been changed and then only copy changed lines from RAM into display memory.

For 256 colour modes I'd consider getting rid of the inner loop of the character drawing code completely by using a lookup table and some bit fiddling. For example:

Code: Select all

bitMaskTable:
    db 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF   ;0x00
    db 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00   ;0x01
    db 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0xFF   ;0x02
    db 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00   ;0x03
    db 0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0xFF,0xFF   ;0x04
    <- more ->
    db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00   ;0xFF

;Input
; edx = foreground colour packed into each byte
; esi = address of font data for character
;
;Output
; edi = address for next character

drawCharacter:
    push edi
    clr ecx                                      ;ecx = number of first character row

.nextRow:
    movzx eax,[esi+ecx]                          ;eax = bit pattern for this row
    mov ebx,[bitMaskTable+eax*8 ]                ;ebx = bit mask for first dword
    mov eax,[bitMaskTable+eax*8+4]               ;eax = bit mask for second dword
    and [edi],ebx                                ;Clear bits in first dword
    and [edi+4],eax                              ;Clear bits in second dword
    not ebx                                      ;ebx = inverted bit mask for first dword
    not eax                                      ;eax = inverted bit mask for second dword
    and ebx,edx                                  ;ebx = foreground colour data for first dword
    and eax,edx                                  ;eax = foreground colour data for second dword
    or [edi],edx                                 ;Set first dword foreground bits to colour
    or [edi+4],esi                               ;Set second dword foreground bits to colour

    inc ecx                                      ;ecx = number of next character row
    add edi,[number_of_bytes_per_screen_line]    ;edi = address of next line
    cmp ecx,8                                    ;Have all character rows been done?
    jb .nextRow                                  ; no, keep going

    pop edi
    add edi,8
    ret
For the "normal" method, you end up with 64 conditional branches (one per bit) that the CPU can't predict correctly. Mis-predicted branches make peformance suck, and writing one byte/pixel at a time doesn't help much either.


Cheers,

Brendan

Re:Graphics mode

Posted: Sun Mar 05, 2006 6:07 pm
by Dex4u
You can take a look at some code i wrote, call "CdPod", it for vesa 640x480 32bpp, but by changing it abit it will work for any graphic mode.
http://www.dex4u.com/images/cdpod.zip

Re:Graphics mode

Posted: Mon Mar 06, 2006 3:00 am
by Pype.Clicker
Dex4u wrote: You can take a look at some code i wrote, call "CdPod", it for vesa 640x480 32bpp, but by changing it abit it will work for any graphic mode.
http://www.dex4u.com/images/cdpod.zip
Don't take it bad, i know this code was build to fit on a single sector, and you made extraodinary work in that field, but yet, i'm not that convince that "changing it abit will work" for any other purpose.

For instance, a typical "drawtext" function will receive an array of ASCII char with e.g. "Hello World" and retrieve the appropriate font bits for 'H' and render the 'H', then for 'e', then for 'l', etc.
Your code instead, has "Play:" and "Stop:" directly encoded as a bitmap element (if i understand the code correctly), which means -- in some way -- that they are somehow like 32-pixels-wide single characters ...

Seeing something like

Code: Select all

;***********************************
; Draws the Pod.
;***********************************

        mov   edi,236*4+640*4*125 
        add   edi,edx
Pod:
        xor   ecx,ecx
        mov   ebx,245
button2:
        mov   cl,14
        mov   al,0x2d
letsloop1:
        stosd
        add   eax,15
        loop  letsloop1
        mov   cl,130
        rep   stosd
        mov   cl,14
letsloop2:
        stosd
        sub   eax,15
        loop  letsloop2
        add   edi,640*4-158*4
        dec   ebx
        jnz   button2
also reminds me of the time where i was trying to understand 3D maths by looking at hand-optimized ASM code for gourauld and phong shading from democoders.
I'm not sure the above code would even helped me to write a "fillrect (x1,y1,x2,y2, color) -- but it's certainly very compact and efficient, i won't deny it.


i was about to point you towards the FAQ but i realise we still have to write that part. If anyone is willing to take it, it's yours :P

Re:Graphics mode

Posted: Mon Mar 06, 2006 2:26 pm
by Dex4u
Maybe your right Pype.Clicker, but i thought it may give a idea that you test for a bit, if its a 1 you put pixel, if a 0 you move pointer by one pixel (or put a differant colored pixel in), The other above code was not there when i put the link, on seeing it, i tryed to deleting the post, but it did not seem to work.

Re:Graphics mode

Posted: Mon Mar 06, 2006 6:45 pm
by Warrior
Well aside from "Graphics" mode being pretty vague, Dex4u gave me a pretty well explained here

It explains things like just plotting pixels on the screen but I don't think you should be thinking at fonts at this level yet. I think you should implement the lower level functions first and efficiently then try to port an existing solution like Freetype or just implement your own.

Hope I helped some.

Re:Graphics mode

Posted: Tue Mar 07, 2006 4:01 am
by Pype.Clicker
Pype.Clicker wrote: i was about to point you towards the FAQ but i realise we still have to write that part. If anyone is willing to take it, it's yours :P
updated the FAQ with basic informations about plotting pixels, drawing rectangles and characters ...

Re:Graphics mode

Posted: Wed Mar 15, 2006 5:00 pm
by Rob
I've written a (self-contained) sample that illustrates some basic stuff (especially font writing):

http://www.mega-tokyo.com/forum/index.php?board=1;action=display;threadid=9169

At the moment my code has 64 conditional branches per character (to determine a new line). Which is actually not too smart. That can actually be done a lot smarter without any jumps (with or without lookup tables)

Re:Graphics mode

Posted: Thu Mar 16, 2006 2:24 am
by Pype.Clicker
i remember some project of mine where fonts were actually code, consisting of "stosb" bytes for pixels to be drawn, "inc di" for pixels to be skipped and "add di,dx" for end of lines. That made fonts sensibly larger than bitmaps, but faster to render (at least on that good old pentium). With today architectures, i think i would rather orient towards RLE encoding if i had to do a bitmap font renderer.

At least, i'd make sure it can take "antialiasing pixels" into account right from the start (which a bitmap may have more trouble to handle).

Re:Graphics mode

Posted: Thu Mar 16, 2006 2:55 am
by Rob
Agreed, I wouldn't use 1 bit fonts like my example does now. However, it is a nice "system" to use during boot and perhaps exception handling.

If you want to do serious graphics in your OS a proper font (probably scalable as well) will be important. And of coures in that case your characters will (should) have different widths.

Re:Graphics mode

Posted: Thu Mar 16, 2006 1:39 pm
by Dex4u
We all want great looking antialiasing and scalable fonts in our OS, but coding them so they look right and work is not easy.
I do not see many hobby OS with them implemented, even MenuetOS does not have them.

Re:Graphics mode

Posted: Thu Mar 16, 2006 1:57 pm
by Rob
If you are going to do graphics then it's weird people don't add at least proper bitmapped fonts (those are freely available). It should be easy to implement in C(++) [performance might be not so good though], especially if you've setup the basics as I've demonstrated with my code.

But it isn't as easy as plain old textmode, that's for sure.

Re:Graphics mode

Posted: Thu Mar 16, 2006 3:00 pm
by Dex4u
You miss understood what i was saying, "bitmapped" are easy to code and common.
A bitmapped font (the simpler of the two) is like a BMP image. It's stored as a matrix (or grid) of pixel values, and is displayed exactly as it's written -- no interpretation is involved. It's a perfect copy, but as a result, it can't be resized without a significant loss of quality.
But "scalable" are harder to code right and not so common in hobby OS:
A scalable font, on the other hand, is stored in the same manner as a vectored graphic. Rather than being mapped pixel by pixel, a scalable font's "stylistic information" is saved in its data file. This information includes the angles of each character's curves, and how they're proportioned. Because no actual picture exists, it's up to the program that reads in the font to construct it for display. This adds some processing overhead, but the end result is well worth it. Scalable fonts can be resized without losing any quality, and often have smooth (or antialiased) edges.