Programowanie w rozdzielczości 1024x768
Gawronxxl
W artykule chciałbym przedstawić jak programować w rozdzielczości 1024x768 w 256 kolorach przy pomocy procedur które sami napiszemy. Na wstępie dodam że duża cześć procedur będzie pisana przy pomocy wbudowanego asemblera w kompilator TP. A wiec zaczynamy. Życzę miłej lektury :D
Aby wyświetlić pixel lub narysować linie itp. trzeba najpierw zainicjować tryb 1024x768x256.
W tym celu posłużymy się funkcja 4F02h przerwania 10h. Przystępujemy do pisania procedurki inicjującej ten tryb :D.
Procedure Init1024x768x256;assembler;
Asm
mov ax, 4F02h
mov bx, 105h
int 10h
End;
I mały programik w tp z jej wykorzystaniem :D
uses crt;
Begin
Init1024x768x256;
repeat until keypressed;
End.
Hmmm. Ale co my tu mamy. Po uruchomieniu programu widzimy tylko ciemny ekran! Niestety tak wygląda ten tryb po inicjacji. Aby zobaczyć coś więcej musimy coś narysować! Lecz zanim przystąpimy do wyświetlania pikseli, rysowania linii, prostokątów itp. Powiem kilka słów o organizacji ekranu w tym trybie. Jak zapewne wiecie ekran w trybie 13h czyli o rozdzielczości 320x200 pikseli zajmuje w pamięci 320200=64000 bajtów i znajduje się pod adresem A000:F9FF czyli zajmuje niecały bufor wideo. To też dla wyjaśnienia powiem ze bufor wideo ma rozmiar 65536 bajtów czyli począwszy od adresu A000 do FFFF. Wyświetlanie piksela w tej rozdzielczości nie nastręcza problemów takich jak w 1024x768 bo nie wymaga przełączania banków (będę używał określenia bank lub bit plan), ale o tym za chwile.
Ekran przy rozdzielczości 1024x768 ma rozmiar 786432 bajty czyli znacznie więcej niż calu bufor wideo. Gdybyśmy nie przełączali banków ekranu maksymalny możliwy do wyświetlenia piksel miałby współrzędne 1023,64. W tym celu aby np wyświetlić piksel o współrzędnych 200,200 trzeba posłużyć się przełączaniem banków ekranu. Ekran w rozdzielczości 1024x768 ma ich 1024768/65536=12. Czyli licząc od zera do 11 daje 12 :P. Trochę zamotałem :D. Więcej nie będę opisywał tylko przystąpmy do pisania procedurki do wyświetlania pikseli :D. Oto ona.
Procedure PutPixel(x,y:word;kolor:byte);assembler;
Asm
{liczenie ofsetu}
mov ax, 1024
cmp ax, x
jz @000
jl @000
mov ax, 768
cmp ax, y
jz @000
jl @000
mov di, y
shl di, 10
add di, x
{sprawdzanie i zmiana aktywnego banku bit planu}
mov dx, y
shr dx, 6
cmp dx, BitPlan
jz @nie_zmieniaj {=}
mov ax, 4F05h
mov bx, 0
int 10h
mov BitPlan, dx
@nie_zmieniaj:
{wyswietlenie pixela}
mov ax, 0a000h
mov es, ax
mov al, kolor
mov byte ptr es:[di], al
@000:
End;
Nie będę opisywał dokładnie jej działania, ważne że działa i wyświetla piksel w rozdzielczości 1024x768x256 :D
Część 2 :D.
Jak obiecałem oto dalszy ciąg pisania procedurek i funkcji do obsługi rozdzielczości 1024x768 w 256 kolorach. No dobra, dobra nie będę już męczył zbędnym paplaniem tylko przechodzimy do sedna sprawy. Umiemy zainicjować tryb pracy w 1024x768x256, poza tym umiemy już wyświetlać piksele w tej rozdzielczości. Teraz napiszemy funkcje która będzie zwracać kolor piksela w punkcie x, y :D. Oto ona.
Function GetPixel(x,y:word):byte;assembler;
Asm
mov ax, 1024
cmp ax, x
jz @000
jl @000
mov ax, 768
cmp ax, y
jz @000
jl @000
mov di, y
shl di, 10
add di, x
mov dx, y
shr dx, 6
cmp BitPlan, dx
jz @nie_zmieniaj {=}
mov ax, 4F05h
mov bx, 0
int 10h
mov BitPlan, dx
@nie_zmieniaj:
mov ax, 0a000h
mov es, ax
mov al, byte ptr es:[di]
@000:
End;
I oto jest :D. Jeszcze jedno. PutPixel i GetPixel używają zmiennej BitPlan typu word którą należy wcześniej zdefiniować. Użyłem tu zmiennej do przechowywania aktywnego bit planu dlatego że jest to dużo szybsze rozwiązanie niż jego zmiana za każdym razem nawet kiedy kolejny rysowany piksel znajduje się w tym samym bit planie. Ok. Hmm, narysowanie czegoś z pojedynczych pikseli to strasznie monotonne zadanie, więc zróbmy procedurę do rysowania całych linii. Rysowanie linii z punktu x, y do punktu x1, y1 o podanym kolorze :D.
Procedure Line(x1,y1,x2,y2:word;kolor:byte);
var licznik,s,d1x,d1y,d2x,d2y,r_x,r_y,m,n:integer;
Function znak(liczba:integer):integer;assembler;
Asm
mov ax, liczba
cmp ax, 0
jg @001
jl @002
jz @003
@001:
mov ax, 1
jmp @000
@002:
mov ax, -1
jmp @000
@003:
mov ax, 0
@000:
End;
Begin
asm
mov ax, x2
mov bx, x1
sub ax, bx
mov r_x, ax
mov ax, y2
mov bx, y1
sub ax, bx
mov r_y, ax
mov d2y, 0
end;
d1x:=znak(r_x);
d1y:=znak(r_y);
d2x:=znak(r_x);
m:=abs(r_x);
n:=abs(r_y);
if (m<=n) then
begin
asm
mov d2x, 0
end;
d2y:=znak(r_y);
m:=abs(r_y);
n:=abs(r_x);
end;
asm
mov ax, m
shr ax, 1
mov s, ax
mov cx, m
inc cx
@petla:
mov ax, x1
mov bx, y1
mov dx, word ptr kolor
push ax
push bx
push dx
call PutPixel
mov ax, s
mov bx, n
add ax, bx
mov s, ax
cmp ax, m
jl @001
mov ax, s
mov bx, m
sub ax, bx
mov s, ax
mov ax, x1
mov bx, d1x
add ax, bx
mov x1, ax
mov ax, y1
mov bx, d1y
add ax, bx
mov y1, ax
jmp @000
@001:
mov ax, x1
mov bx, d2x
add ax, bx
mov x1, ax
mov ax, y1
mov bx, d2y
add ax, bx
mov y1, ax
@000:
loop @petla
end;
End;
Trochę bazgraniny było ale działa :D. Powiem jeszcze ze procedura line używa procedury PutPixel, ale to na pewno udało się wam zauważyć :P.
Na tym chwilowo kończę. Ale nie martwcie się już niedługo ciąg dalszy :D.
Artykuł będzie z czasem rozszerzany. Proszę o cierpliwość i wyrozumiałość.
Pozdrawiam Gawron.
A ja wam powiem, że po prostu opisuje on swoim językiem a nie typowym specjalistycznym językem, i tak jeden z ciekawszych artów o ASMie
Zawsze można zrobić jeszcze bardziej nieczytelna w samym asmie :D. Lub bardziej czytelna w Pascalu. A tu wybrałem takie poplątanie co by było wiadomo o co biega i żeby była w miarę szybka. Pozdrawiam i dalej myślę nad kolejnym rozszerzeniem art...
PS. tak właściwie ta procedura rysująca linię - nie lepiej byłoby użyć zamiast niej procedury pascala która wywoływałaby PutPixel? Bo obecna wersja jest, hm, lekko nieczytelna ;)
Ale się czepiacie :D Może te emotki i denerwują, ale sam się często ledwo powstrzymuje podczas pisania artów.
Tak czy inaczej nie przejmuj się moimi poprzednikami bo zapowiada się ciekawie (sam się zawsze zastanawiałem, kiedy jeszcze używałem pascala, jak to zrobić)
też mnie emotki uderzyły w treści...
Ale dretwy tekst :| Emoticony w artykule, heh...
do tego co to za tytuł artykułu - nie mówi prawie nic! popraw go, niech będzie opisowy, no i podpisuj się na końcu pracy, nie w tytule.
pamięć karty graficznej w trybie rzeczywistym zajmuje obszar od $A0000 do $AFFFF, plus obszar na tekst - $B0000-$B7FFF lub $B8000-$BFFFF. popraw te błędy i sprawdź, co to jest segment i offset.