VGA Programming in Mode 13h ----------------------------------------------------------------------------- This article will describe how to program VGA graphics Mode 13h using assembly language. Mode 13h is the 320x200x256 graphics mode, and is fast and very convenient from a programmers perspective. The video buffer begins at address A000:0000 and ends at address A000:F9FF. This means the buffer is 64000 bytes long and that each pixel in mode 13h is represented by one byte. It is easy to set up mode 13h and the video buffer in assembly language: mov ax,0013h ; Int 10 - Video BIOS Services int 10h ; ah = 00 - Set Video Mode ; al = 13 - Mode 13h (320x200x256) mov ax,0A000h ; point segment register es to A000h mov es,ax ; we can now access the video buffer as ; offsets from register es At the end of your program, you will probably want to restore the text mode. Here's how: mov ax,0003h ; Int 10 - Video BIOS Services int 10h ; ah = 00 - Set Video Mode ; al = 03 - Mode 03h (80x25x16 text) Accessing a specific pixel int the buffewr is also very easy: ; bx = x coordinate ; ax = y coordinate imul ax, 320 ; multiply y coord by 320 to get row add bx,ax ; add this with the x coord to get offset mov cx,es:[bx] ; now pixel x,y can be accessed as es:[bx] Hmm... That was easy, but that multiplication is slow and we should get rid of it. Thats easy to do too, simply by using bit shifting instead of multiplication. Shifting a number to the left is the same as multiplying by 2. We want to multiply by 320, which is not a multiple of 2, but 320 = 256 + 64, and 256 and 64 are both even multiples of 2. So a faster way to access a pixel is: ; bx = x coordinate ; ax = y coordinate mov cx,bx ; copy bx to cx, to save it temporatily shl cx,8 ; shift left by 8, which is the same as ; multiplying by 2^8 = 256 shl bx,6 ; now shift left by 6, which is the same as ; multiplying by 2^6 = 64 add bx,cx ; now add those two together, whis is ; effectively multiplying by 320 add bx,ax ; finally add the x coord to this value mov cx,es:[bx] ; now pixel x,y can be accessed as es:[bx] Well, the code is a little bit longer and looks more complicated, but I can guarantee its much faster. To plot colors, we use a color look-up table. This look-up table is a 768 (3x256) array. Each index of the table is really the offset index*3. The 3 bytes at each index hold the corresponding values (0-63) of the red, green, and blue components. This gives a total of 262144 total possible colors. However, since the table is only 256 elements big, only 256 different colors are possible at a given time. Changing the color palette is accomplished through the use of the I/O ports of the VGA card: Port 03C7h is the Palette Register Read port. Port 03C8h is the Palette Register Write port Port 03C9h is the Palette Data port Here is how to change the color palette: ; ax = palette index ; bl = red component (0-63) ; cl = green component (0-63) ; dl = blue component (0-63) mov dx,03C8h ; 03c8h = Palette Register Write port out dx,ax ; choose index mov dx,03C9h ; 03c8h = Palette Data port out dx,al mov bl,al ; set red value out dx,al mov cl,al ; set green value out dx,al mov dl,al ; set blue value Thats all there is to it. Reading the color palette is similar: ; ax = palette index ; bl = red component (0-63) ; cl = green component (0-63) ; dl = blue component (0-63) mov dx,03C7h ; 03c7h = Palette Register Read port out dx,ax ; choose index mov dx,03C9h ; 03c8h = Palette Data port in al,dx mov bl,al ; get red value in al,dx mov cl,al ; get green value in al,dx mov dl,al ; get blue value Now all we need to know is how to plot a pixel of a certain color at a certain location. Its very easy, given what we already know: ; bx = x coordinate ; ax = y coordinate ; dx = color (0-255) mov cx,bx ; copy bx to cx, to save it temporatily shl cx,8 ; shift left by 8, which is the same as ; multiplying by 2^8 = 256 shl bx,6 ; now shift left by 6, which is the same as ; multiplying by 2^6 = 64 add bx,cx ; now add those two together, whis is ; effectively multiplying by 320 add bx,ax ; finally add the x coord to this value mov es:[bx],dx ; copy color dx into memory location ; thats all there is to it Ok, we now know how to set up Mode 13h, set up the video buffer, plot a pixel, and edit the color palette. My next article will go on to show how to draw lines, utilize the vertical retrace for smoother rendering, and anything else i can figure out by that time... ----------------------------------------------------------------------------- Copyright (C) 1998 Bill T. (billasm@usa.net)