GFXLIB - Librarias graficas
Com que entao estao fartos do BGI !!! Queriam 256 cores, mas nao percebem
nada de como fazer o vosso BGI driver. Aqueles jogos todos que usam 320x200
com aquelas 256 maravilhosas cores. Como sera que se faz aquilo !?
Ah uns anos atras um comecava assim a minha investigacao das placas de
video, modos VESA, DAC's, VGA Registers, por ai fora. Como resultado agora
cada vez que quero uma libraria grafico para o modo 13h normalmente ate a
faco de olhos fechados (nao eh bem assim.. mas sempre eh um efeito mais
dramatico!).
Neste conjunto de artigos vamos desenvolver uma libraria grafica em Pascal
com ASM. Se nao sabem ASM aconselho-vos vivamente a aprender.
(HINT MODE ON)
Os que nao sabem pascal...bom...(no comments). So para adocar a boca a
alguns a nossa pikena lib vai ter as seguintes caracteristicas :
Tudo isto usando pascal e asm (para o 386 e superiores).
Esta libraria eh shareware e se a kiserem usar teram de me pagar 10.000$00
por cada copia do programa vendido. Faco descontos para kem kiser uma licensa
ilimitada. Por exemplo neste caso em vez de ser 10.000$00 por copia... e
devido ao numero ilimitado de copias, sao so 7500$00 por copia!
HAHAAHAHAHA Gotcha. Nopes... esta lib eh GreetWare se a usarem na totalidade
ou parcialmente ou mesmo ke a usem so para ver como eu escrevo mal assembler
ao menos deem-se ao trabalho de mandar um emailzito a agradecer/mandar
vir/flames/ice picks/C-4 etc. Eh a unica maneira ke tenho de saber se valeu a
pena o esforco ou nao.
Comecemos entao que ja se faz tarde...(05:42 AM... ainda eh cedo..demasiado
cedo ate...) ...
Esta lib por enquanto so vai suportar o modo 13h. Nao desanimem... se eu vir
que o ppl gosta desta o suficiente eu ate escrevo os artigos para a passar
para VESA.
(Rotten Emotional Blackmailing (c) Copyright 1978 Codewiz's Mother)
Em primeiro lugar temos de por a placa grafica no mode 13h.. o BIOS uma das
poucas coisas que faz bem e ajudar a mudar o modo das placas graficas. Por
isso vamos usa-lo...
Agora o problema eh desenhar... hmm... bom... entao e que tal umas rotinas
de putpixel e de getpixel ? (ena deixa lah ver o meu mail... olha! o razer
escrever um testamento sobre putpixeis... ora porra... bom... kem nao perceber
a minha explicacao pode ir ver a dele...)
Como ja deve saber o modo 13h tem 320 pixeis de comprimento e 200 pixeis de
altura. Alem desta capacidade para ter 64000 pixeis no ecran o modo 13h tem
outra caracteristica que ajuda muito. Como cada pixel tem uma de 256 cores
possiveis, os tipos que criaram a placa VGA acharam que era cool se dessem um
byte para cada pixel e ate seria mais giro se o endecamento dos pixeis na
memoria de video fosse linear!
E se assim os engenheiros pensaram... melhor os tecnicos o implementaram, a
memoria de video para os modos graficos geralmente comeca no segmento A000h e
o modo 13h nao eh excepcao. Temos portanto 10000h bytes de memoria video...mas
destes apenas FA00h estao no ecran.
Bom... temos agora um problema converter as coordenadas de um pixel que sao
em 2D para um endereco linear (ou seja 1D). Eh simples... se virem bem..
o primeiro pixel tem as coordenadas (0,0) e o seu indereco eh 0000h. O pixel
(3,0) tem como endereco 0003h, e o pixel (0,1) tem como endereco 0140h e o
pixel (3,1) tem como endereco 0143h.
A equacao que nos dah os pixeis na memoria de video eh esta
addr=y*320+x
Quando se optimiza deve-se comecar por optimizar o algoritmo e so depois
optimizar para o computador em causa. Infelizmente nao ah outra maneira de
calcular o endereco. Vamos entao optimizar para os PC's.
Primeiro passemos aquela coisa para assembler...assumindo que :
Por acaso 320 = 64+256 ...bom isto ja dah para usar shl's e shr's. Quem nao
sabe trabalhar com bits sugiro que vah aprender, sem isso nao vai muito longe
na programacao..
Mas aquele xchg podia ser um add... assim
Agora que temos o sacana do endereco... ja podemos ler e escrever pixeis.
No proximo capitulo falaremos dos ecrans virtuais. Ate lah ..
"Desconfiem sempre de um byte mal alinhado. Nunca se sabe por onde
andou antes de voces o encontrarem!"
-CodeWiz
-----------------------------------------
by CodeWiz
*Talvez alguem queira fazer um tutorial sobre isso para por aki na zine*
(HINT MODE OFF)
procedure GfxGoGfxMode; assembler;
asm
mov ax, 0013h { AH = 00h - Funcao SetMode | AL = 13h - Modo video desejado}
int 10h { 10h - Servicos de video do BIOS }
end;
procedure GfxGoTxtMode; assembler;
asm
mov ax, 0003h { AH = 00h - Funcao SetMode | AL = 03h - Modo video desejado}
int 10h { 10h - Servicos de video do BIOS }
end;
Bom, estas rotinas mudam o modo grafico e por agora sao tudo o que
precisamos para comecar a desenhar no modo grafico.
Entrada : Saida :
AX = Y ES:DI = Pixel Addr
BX = X
(os timings sao para o 486)
procedure GfxCalcPixAddrESDI; assembler;
asm
mov dx, 0140h { (1) 320 em decimal }
mul dx { (15+-2) AX = Y*320 }
add ax, bx { (1) AX = Y*320+X }
mov di, ax { (1) DI = AX }
mov ax, 0A000h { (1) }
mov es, ax { (1) ES:DI = Endereco do Pixel }
end;
Esta rotina leva na melhor das hipoteses (depende do DX e nao me apetece
fazer os calculos para saber) 18 ticks a executar. Not good! Na pior das
hopoteses 22 ticks. That sucks!
procedure GfxCalcPixAddrESDI; assembler;
asm
mov dx, ax { (1) DX = Y }
shl ax, 8 { (2) AX = Y*256 }
shl dx, 6 { (2) DX = Y*64 }
add ax, dx { (1) AX = Y*256+Y*64 }
add ax, bx { (1) AX = Y*320+X }
mov di, ax { (1) DI = AX }
mov ax, 0A000h { (1) }
mov es, ax { (1) ES:DI = Endereco do Pixel }
end;
Bom agora ja so temos 10 Ticks. Mas ainda se pode descer mais...
procedure GfxCalcPixAddrESDI; assembler;
asm
mov dx, ax { (1) DX = Y }
xchg al, ah { (3) AX = Y*256 }
shl dx, 6 { (2) DX = Y*64 }
add ax, dx { (1) AX = Y*256+Y*64 }
add ax, bx { (1) AX = Y*320+X }
mov di, ax { (1) DI = AX }
mov ax, 0A000h { (1) }
mov es, ax { (1) ES:DI = Endereco do Pixel }
end;
(Eu tinha a certeza que este codigo era mais rapido mas ou a minha referencia
de ASM esta com bugs ou entao nao sei. Alguem me pode confirmar os timings dos
shl reg/mem, immed8 para um 486.)
procedure GfxCalcPixAddrESDI; assembler;
asm
add bh, al { (1) BX = X+Y*256 }
shl ax, 6 { (2) AX = Y*64 }
add ax, bx { (1) AX = X+Y*320 }
mov di, ax { (1) DI = AX }
mov ax, 0A000h { (1) }
mov es, ax { (1) ES:DI = Endereco do Pixel }
end;
Estamos agora com 8 ticks. Menos de metade da rotina inicial. Nada mau. E no
processo arranjamos maneira de nao estragar nenhum dos outros registos alem
dos que sao usados para dar a entrada de valores e a saida dos mesmos.
procedure GfxPutPixel(x,y : integer; color : byte); assembler;
asm
mov ax, [y] { AX = Y }
mov bx, [x] { BX = X }
add bh, al { BX = X+Y*256 }
shl ax, 6 { AX = Y*64 }
add ax, bx { AX = X+Y*320 }
mov di, ax { DI = AX }
mov ax, 0A000h { }
mov es, ax { ES:DI = Endereco do Pixel }
mov es:di, [color] { ES:DI = Color - One Painted Pixel Comin' Up! }
end;
function GfxGetPixel(x,y : integer) : byte; assembler;
asm
mov ax, [y] { AX = Y }
mov bx, [x] { BX = X }
add bh, al { BX = X+Y*256 }
shl ax, 6 { AX = Y*64 }
add ax, bx { AX = X+Y*320 }
mov di, ax { DI = AX }
mov ax, 0A000h { }
mov es, ax { ES:DI = Endereco do Pixel }
mov al, es:di { AL = Cor do Pixel }
end;
código - gfx.pas