Programowanie
C++
Turbo Pascal
Delphi
Ver. 1.0 Beta, Nie masz kompilatora? Teraz możesz pisać skrypty ONLINE! Wersja podstawowa -nie zawiera wszystkich poleceń Pascala. Służy do nauki podstaw
Moduł do obsługi szybkiej grafiki VESA w Turbo Pascalu
Grafika 10eh
Część praktycznaPoniżej jest kod źródlowy modulu graficznego graph10Eh z objaśnieniami. Możesz troszkę pokopiować do siebie, żeby otrzymać szybką grafikę w trybie 320x200x16bitów. - Dochodzi do 500 klatek na sekundę. - Odtwarza pliki bmp. - Symuluje przezroczystość - Rysuje szybką linię - Potrafi robić print screeny Zapraszam do nauki KOD ŹRÓDLOWY: {$G+} UNIT Graph10E; INTERFACE USES Types, Fonts, Errors, Standard, MMX; CONST V_MaxEX=320; V_MaxEY=200; BrakZnaku:ARRAY[0..7] OF Byte= {(00, 66, 36, 24, 24, 36, 66, 00);} (0, 0, 0, 0, 0, 0, 0, 0); EkranRect:TRect= (X:0;Y:0;W:320;H:200); MMX_Enabled=FALSE; VerticalRetrace:Boolean=True; V_TextNormal:Boolean=True; VGA_Tryb:Boolean=FAlse; TYPE TEkran10Eh=RECORD Ekr1 : Pointer; Ekr2 : Pointer; END; TObraz=RECORD W, H : Word; TCol : Word; Transparent : Boolean; BMP : Pointer; BPP : Byte; Paleta : Pointer; END; TPicture =^TObraz; TBMPCaption = RECORD BM : Word; Size : Longint; rezerw : Longint; obraz_offset : Longint; info : Longint; Width : Longint; Height : Longint; LPO : Word; BPP : Word; kompresja : Longint; Size_Obr : Longint; HDPI : Longint; VDPI : Longint; Colors : Longint; UColors : Longint; END; TRGB = RECORD R, G, B : Byte; END; TPaleta = RECORD Color : ARRAY[0..255] OF TRGB; END; PPaleta =^TPaleta; VAR DefaultRect : TRect; V_Ekran : TEkran10Eh; FUNCTION V_RGB(r, g, b : Byte) : Word; {FUNCTION V_RGB(R, G, B:Byte):Word;} FUNCTION V_GetBuf(VAR Buf:TEkran10Eh):Byte; FUNCTION V_LoadBMP24(Buf:TPicture;CONST Fn:STRING):Boolean; PROCEDURE V_PrintScreen(CONST Fn:STRING); PROCEDURE V_ToRGB(c : Word; VAR r, g, b : Byte); {PROCEDURE V_ToRGB(Col:Word;VAR R, G, B:Byte);} PROCEDURE V_FreeBuf(VAR Buf:TEkran10Eh); PROCEDURE ShowCaptionBMP(CONST Fn:STRING); PROCEDURE V_VRet; PROCEDURE V_FillChar32(Dest:Pointer;Count:word; Value:Word); PROCEDURE V_FlipBuf(Buf : TEkran10Eh); PROCEDURE V_Set10Eh; PROCEDURE V_End10Eh; PROCEDURE V_ClearScreen(Buf:TEkran10Eh; Col:Word); PROCEDURE V_HLine(Buf:TEkran10Eh; X, Y, W:Integer;C:Word); PROCEDURE V_VLine(Buf:TEkran10Eh; X, Y, H:Integer;C:Word); PROCEDURE V_Pix(Buf:TEkran10Eh; X, Y:Integer;C:Word); PROCEDURE V_Line(Buf:TEkran10Eh; X1, Y1, X2, Y2:Integer;C:Word); PROCEDURE V_HLineAlpha1(Buf:TEkran10Eh; X, Y, W:Integer;C:Word;Alpha:Byte); PROCEDURE V_RozmyjEkran(Buf:TEkran10Eh; Speed:Byte); PROCEDURE V_KopiujObraz(Buf:TEkran10Eh; Obraz:TPicture; X, Y:Integer); PROCEDURE V_NewImage(VAR Picture:TPicture); PROCEDURE V_FreeImage(VAR Picture:TPicture); PROCEDURE V_WriteXY(Buf:TEkran10Eh;Font:PFont;X, Y:Integer;CONST S:STRING;C:Word;StepX:Byte); PROCEDURE V_CenterText(Buf:TEkran10Eh;Font:PFont;X, Y:Integer;CONST S:STRING;C:Word;StepX:Byte); PROCEDURE V_CopyLine(Buf:TEkran10Eh; Dest:Pointer; X, Y, W:Integer); PROCEDURE V_CopyFromLine(Buf:TEkran10Eh; Line:Pointer; X, Y, W:Integer); PROCEDURE V_LineX(X1, Y1, X2, Y2 : Integer; C: Word); PROCEDURE V_CreateMirroredBMP(VAR Source, Dest:TPicture); IMPLEMENTATION {FUNCTION V_RGB(r, g, b : Byte) : Word;ASSEMBLER; ASM Mov Al, [r] Shl Ax, 5 Mov Al, [g] Shl Ax, 3 And Al, 11100000b Shr [b], 3 Or Al, [b] END; PROCEDURE V_ToRGB(c : Word; VAR r, g, b : Byte); ASSEMBLER; ASM Mov Cx, Ds Mov Ax, [c] Lds Bx, [b] Mov [Bx], Al Shl BYTE PTR [Bx], 3 Shr Ax, 5 Lds Bx, [g] Mov [Bx], Al Shl BYTE PTR [Bx], 2 Shr Ax, 6 Lds Bx, [r] Mov [Bx], Al Shl BYTE PTR [Bx], 3 Mov Ds, Cx END; FUNCTION V_RGB(R, G, B:Byte):Word; BEGIN V_RGB:=(B SHR 3) OR ((G SHR 2) SHL 5) OR ((R SHR 3) SHL 11); END; {************************************************************************* PROCEDURE V_ToRGB(Col:Word;VAR R, G, B:Byte); BEGIN R:=(Col AND (31 SHL 11)) SHR 8; G:=(Col AND (63 SHL 5)) SHR 3; B:=BYTE(Col SHL 3); END; FUNCTION V_GetBuf(VAR Buf:TEkran10Eh):Byte; BEGIN Buf.EKR1:=NIL; Buf.EKR2:=NIL; V_GetBuf:=E_OK; IF MemAvail<128000 THEN BEGIN V_GetBuf:=E_PAMIEC; Exit; END; GetMem(Buf.EKR1, 64000); GetMem(Buf.EKR2, 64000); V_Ekran.EKR1:=Buf.EKR1; V_Ekran.EKR2:=Buf.EKR2; END; PROCEDURE V_FreeBuf(VAR Buf:TEkran10Eh); BEGIN FreeMem(Buf.EKR1, 64000); FreeMem(Buf.EKR2, 64000); Buf.EKR1:=NIL; Buf.EKR2:=NIL; V_Ekran.EKR1:=NIL; V_Ekran.EKR2:=NIL; END; PROCEDURE V_VRet; BEGIN IF VerticalRetrace THEN ASM Mov Dx, 3dah @Powrot: In Al, Dx Test Al, 00001000b Jnz @Powrot @Nie_Ma: In Al, Dx Test Al, 00001000b Jz @Nie_Ma END; END; PROCEDURE V_Move32(VAR Src;VAR Dest;Count, Offs: Word); ASSEMBLER; ASM Mov Cx, Count Mov Dx, Cx And Dx, 3 Shr Cx, 2 Push Ds Lds Si, Src Les Di, Dest Add Si, Offs Cld Db $F3,$66,$A5 Mov Cx, Dx Rep MovSb Pop Ds END; PROCEDURE V_FillChar32(Dest:Pointer;Count:word; Value:Word);ASSEMBLER; ASM Mov Ax, Value Mov Cx, Ax Db $66 Shl Ax, 16 Mov Ax, Cx Les Di, Dest Mov Cx, Count Mov Bx, Cx And Bx, 3 Shr Cx, 2 Cld Db $F3, $66, $AB Mov Cx, Bx Cld Rep Stosb END; PROCEDURE V_FlipBuf(Buf : TEkran10Eh); BEGIN IF VGA_Tryb THEN BEGIN ASM Mov AX, 4F05H Mov BX, 0 Mov DX, 0 Int 10H END; {KOPIOWANIE EKRANU WRAZ Z KONWERSJA NA TRYB 8-BITOWY} ASM Les Di, Buf.Ekr1 Mov Cx, 32000 Push Ds Mov Ax, $A000 Mov Ds, Ax Xor Si, Si @Petla: Mov Bx, Es:[Di] Inc Di Inc Di Mov Ax, Bx And Ax, 0000000000011100b Shr Ax, 2 Mov Dx, Bx And Dx, 0000011100000000b Shr Dx, 5 Or Ax, Dx And Bx, 1100000000000000b Shr Bx, 8 Or Ax, Bx Mov Bx, Si Inc Si Mov Byte Ptr Ds:[Bx], Al Loop @Petla Pop Ds Les Di, Buf.Ekr2 Mov Cx, 32000 Mov Si, 31999 Push Ds Mov Ax, $A000 Mov Ds, Ax @Petla2: Mov Bx, Es:[Di] Inc Di Inc Di Mov Ax, Bx And Ax, 0000000000011100b Shr Ax, 2 Mov Dx, Bx And Dx, 0000011100000000b Shr Dx, 5 Or Ax, Dx And Bx, 1100000000000000b Shr Bx, 8 Or Ax, Bx Mov Bx, Si Inc Si Mov Byte Ptr Ds:[Si], Al Loop @Petla2 Pop Ds END; END ELSE BEGIN ASM Mov AX, 4F05H Mov BX, 0 Mov DX, 0 Int 10H END; IF MMX_Enabled THEN BEGIN MMX_Move(Ptr($A000, 0), Buf.Ekr1, 64000); MMX_Move(Ptr($A000, 64000), Buf.Ekr2, 1536); END ELSE BEGIN V_Move32(Buf.Ekr1^, Ptr($A000, 0)^, 64000, 0); V_Move32(Buf.Ekr2^, Ptr($A000, 64000)^, 1536, 0); END; ASM Mov AX, 4F05H Mov BX, 0 Mov DX, 1 Int 10H END; {IF MMX_Enabled THEN MMX_Move(Ptr($A000, 0), Buf.Ekr2 , 62464 1536); ELSE} V_Move32(Buf.Ekr2^, Ptr($A000, 0)^, 62464, 1536); END; END; PROCEDURE UpString(VAR S:STRING); VAR i:Byte; BEGIN FOR i:=1 TO Byte(S[0]) DO S[i]:=UpCase(S[i]); END; PROCEDURE V_Set10Eh; VAR R, G, B:Byte; S:STRING; BEGIN IF (ParamCount>0) THEN BEGIN {DUZY PARAMETR} S:=ParamStr(1); UpString(S); END; IF (S='VGA') THEN BEGIN ASM Mov Ax, 13h Mov Bx, 0 Int 10h END; VGA_Tryb:=TRUE; {USTAWIANIE PALETY} FOR R:=0 TO 3 DO FOR G:=0 TO 7 DO FOR B:=0 TO 7 DO BEGIN PORT[$3c8]:=B OR (G SHL 3) OR (R SHL 6); PORT[$3c9]:=R SHL 4; PORT[$3c9]:=G SHL 3; PORT[$3c9]:=B SHL 3; END; END ELSE ASM Mov Ax, 4F02h Mov Bx, 10Eh Int 10h END; END; PROCEDURE V_End10Eh; ASSEMBLER; ASM Mov Ax, 4F02h Xor Bh, Bh Mov Bl, 03h Int 10h END; FUNCTION V_LoadBMP24(Buf:TPicture;CONST Fn:STRING):Boolean; VAR Capt : TBMPCaption; F : FILE; Size : Word; Temp : Word; I : Word; BTem : Pointer; Addx : Word; BMPx : Pointer; TC : Word; BEGIN {JESLI FUNKCJA SIE NIE ZAKONCZY POWODZENIEM ZWROCI False} V_LoadBMP24:=False; {JEZELI JESZCZE NIE MA UTWORZONEGO OBRAZKA TO WYCHODZI} IF Buf=NIL THEN Exit; {OTWIERA PODANY PLIK} Assign(F, Fn); {$I-} Reset(F, 1); {$I+} {JESLI NIE ZNALEZIONO PLIKU WYCHODZI} IF IOResult<>0 THEN Exit; {WCZYTUJE NAGLOWEK INFORMACYJNY} BlockRead(F, Capt, SizeOf(Capt)); {USTAWIA ROZMIAR OBRAZKA} Buf^.W:=Capt.Width; Buf^.H:=Capt.Height; {OBLICZANIE POTRZEBNYCH PAMIECI DLA OBRAZKA} {ORAZ DO BUFORA ODCZYTU Z DYSKU} Size:=Capt.Width*Capt.Height SHL 1; Temp:=Capt.Width SHL 1+Capt.Width; {W RAZIE POTRZEBY PRZYDZIELA PAMIEC DLA RYSUNKU} IF (Buf^.BMP=NIL) THEN BEGIN IF (MaxAvail>=Size) THEN GetMem(Buf^.BMP, Size) ELSE Exit; END; {JEZELI TO NIE JEST BITMAPA 24 BITOWA} IF Capt.BPP<>24 THEN BEGIN Close(F); Exit; END; {PRZESTAWIA WSKAZNIK PLIKU NA POCZATEK BITMAPY} Seek(F, Capt.Obraz_Offset); {PAMIEC DO ODCZYTU JEDNEJ LINII} IF MaxAvail GetMem(BTem, Temp); {USTAWIA WSKAZNIK BUFORU NA OSTATNIA LINIE} Addx:=(Capt.Height-1)*(Capt.Width SHL 1); {BUFOR POMOCNICZY DLA ASSEMBLERA} BMPx:=Buf^.BMP; {WCZYTUJE I PRZEKSZTALCA BITMAPE OD KONCA} FOR I:=Capt.Height-1 DOWNTO 0 DO BEGIN BlockRead(F, BTem^, Temp); ASM Push Ds Les Di, BMPx Add Di, Addx Lds Si, BTem Mov Cx, Word Ptr Capt.Width @Petla: Xor Ax, Ax Mov Al, [Si] Inc Si Xor Bx, Bx Mov Bl, [Si] Inc Si Xor Dx, Dx Mov Dl, [Si] Inc Si Shr Ax, 3 Shr Bx, 2 Shr Dx, 3 Shl Bx, 5 Shl Dx, 11 Or Ax, Bx Or Ax, Dx Mov Es:[Di], Ax Inc Di Inc Di Dec Cx Jnz @Petla Pop Ds END; Dec(Addx, (Capt.Width shl 1)); END; {OKRESLANIE KOLORU PRZEZROCZYSTEGO} {LEWY GORNY PIKSEL} ASM Les Di, BMPx Mov Ax, Es:[Di] Mov Tc, Ax END; {DOMYSLNY KOLOR PRZEZROCZYSTOSCI} Buf^.TCol:=Tc; {ZWALNIA PAMIEC OD BUFORA} FreeMem(BTem, Temp); {ZAMYKA PLIK} Close(F); {ZAZNACZA ZE WSZYSTKO SIE UDALO} V_LoadBMP24:=True; END; PROCEDURE V_ClearScreen(Buf:TEkran10Eh; Col:Word); BEGIN IF MMX_Enabled THEN BEGIN MMX_FillChar(Buf.Ekr1, 64000, Col); MMX_FillChar(Buf.Ekr2, 64000, Col); END ELSE BEGIN V_FillChar32(Buf.Ekr1, 64000, Col); V_FillChar32(Buf.Ekr2, 64000, Col); END; END; FUNCTION V_ObetnijHLine(VAR X1, Y1, W:Integer):Boolean; BEGIN V_ObetnijHLine:=TRUE; IF (Y1 (X1>=DefaultRect.X+DefaultRect.W) OR (W<=0) OR (X1+W<=DefaultRect.X) THEN Exit; IF X1 IF X1+W>DefaultRect.X+DefaultRect.W THEN W:=DefaultRect.W ELSE W:=W+(X1-DefaultRect.X); X1:=DefaultRect.X; END ELSE IF X1+W>DefaultRect.X+DefaultRect.W THEN W:=DefaultRect.X+DefaultRect.W-X1; V_ObetnijHLine:=FALSE; END; FUNCTION V_ObetnijVLine(VAR X1, Y1, H:Integer):Boolean; BEGIN V_ObetnijVLine:=TRUE; IF (X1 (X1>=DefaultRect.X+DefaultRect.W) OR (H<=0) OR (Y1+H<=DefaultRect.Y) THEN Exit; IF Y1 IF Y1+H>=DefaultRect.Y+DefaultRect.H THEN BEGIN H:=DefaultRect.Y+DefaultRect.H; Y1:=DefaultRect.Y; END ELSE BEGIN H:=H+Y1-DefaultRect.Y; Y1:=DefaultRect.Y; END; END ELSE IF Y1+H>DefaultRect.Y+DefaultRect.H THEN H:=DefaultRect.Y+DefaultRect.H-Y1; V_ObetnijVLine:=FALSE; END; PROCEDURE V_HLine(Buf:TEkran10Eh; X, Y, W:Integer;C:Word); VAR Ekr1, Ekr2:Pointer; BEGIN IF V_ObetnijHLine(X, Y, W) THEN Exit; Ekr1:=Buf.Ekr1; Ekr2:=Buf.Ekr2; ASM Mov Ax, Y Cmp Ax, 100 Ja @Drugi Les Di, Ekr1 Jmp @Dalej @Drugi: Les Di, Ekr2 Sub Ax, 100 @Dalej: Shl Ax, 7 Add Di, Ax Shl Ax, 2 Add Di, Ax Add Di, X Add Di, X Mov Cx, W Mov Bx, Cx And Bx, 1 Shr Cx, 1 Mov Ax, C Db $66 Shl Ax, 16 Mov Ax, C Cld Db $F3, $66, $AB Mov Cx, Bx Rep StosW END; END; PROCEDURE V_Pix(Buf:TEkran10Eh; X, Y:Integer;C:Word); VAR Ekr1, Ekr2:Pointer; BEGIN IF (X (Y Ekr1:=Buf.Ekr1; Ekr2:=Buf.Ekr2; ASM Mov Ax, Y Cmp Ax, 100 Ja @Drugi Les Bx, Ekr1 Jmp @Dalej @Drugi: Les Bx, Ekr2 Sub Ax, 100 @Dalej: Shl Ax, 7 Add Bx, Ax Shl Ax, 2 Add Bx, Ax Add Bx, X Add Bx, X Mov Ax, C Mov ES:[Bx], Ax END; END; PROCEDURE V_VLine(Buf:TEkran10Eh; X, Y, H:Integer;C:Word); VAR Ekr1, Ekr2:Pointer; BEGIN IF V_ObetnijVLine(X, Y, H) THEN Exit; Ekr1:=Buf.Ekr1; Ekr2:=Buf.Ekr2; ASM Mov Ax, Y Cmp Ax, 100 Jnb @ZaczynajOd2 Les Di, Ekr1 Mov Bx, Ax Shl Bx, 7 Add Di, Bx Shl Bx, 2 Add Di, Bx Add Di, X Add Di, X Jmp @DrawLine @ZaczynajOd2: Les Di, Ekr2 Mov Bx, Ax Sub Bx, 100 Shl Bx, 7 Add Di, Bx Shl Bx, 2 Add Di, Bx Add Di, X Add Di, X Xor Ax, Ax @DrawLine: Mov Cx, H Mov Dx, C Cld @Petla: Cmp Ax, 100 Jb @Dalej @Drugi: Les Di, Ekr2 Sub Ax, 100 Add Di, X Add Di, X @Dalej: Mov ES:[DI], Dx Add Di, 640 Inc Ax Loop @Petla END; END; {PROCEDURE V_Line(Buf:TEkran10Eh; X1, Y1, X2, Y2:Integer;C:Word); FUNCTION Znak(X:Integer):Integer; BEGIN IF X>0 THEN Znak:=1 ELSE IF X<0 THEN Znak:=-1 ELSE Znak:=0; END; PROCEDURE PrzytnijLinieX(VAR X1, Y1, X2, Y2:Integer; Rect:PRect); VAR a, b:Real; Granica:Integer; BEGIN Granica:=Rect^.X; {PRZECIECIE Z OSIA Z LEWEJ IF (X1 BEGIN {$Q- Y1:=(Y1+Round((Y2-Y1)*(Granica-X1)/(X2-X1))); X1:=Granica; {$Q+ END; Granica:=Rect^.X+Rect^.W; {PRZECIECIE Z OSIA Z PRAWE IF (X1 BEGIN {$Q- Y2:=(Y2+Round((Y2-Y1)*(X2-Granica)/(X2-X1))); X2:=Granica-1; {$ VAR l, s, d1x, d1y, d2x, d2y, rx, ry, m, n, MaxX, MaxY, MinX, MinY : Integer; Rect:TRect; a, b:Single; NY1, NX1, NX2, NY2 :Integer; BEGIN S_Move32(@DefaultRect, @Rect, SizeOf(TRect)); IF ((X1 ((Y1 IF (X1<>X2) AND (Y1<>Y2) THEN BEGIN {$Q- a:=(Y2-Y1)/(X2-X1); b:=((-X1)*(y2-y1)-(X2-X1)*(-X1))/(X2-X1); Y1:=-Round(a*Rect.X+b); Y2:=-Round(a*(Rect.X+Rect.W-1)+b); X1:=Round((b-Rect.Y)/a); X2:=Round((b-(Rect.Y+Rect.H-1))/a); {$Q+ END; IF Y1 IF Y2 IF X1 IF X2 PROCEDURE V_LineX(X1, Y1, X2, Y2 : Integer; C: Word); VAR P0, P1, tmp : Integer; EX1, EY1, EX2, EY2 : Integer; x, y : Integer; l, s, d1x, d1y, d2x, d2y, rx, ry, m, n, MaxX, MaxY, MinX, MinY : Integer; Rect:TRect; a : Single; Temp : Integer; FUNCTION Znak(X:Integer):Integer; BEGIN IF X>0 THEN Znak:=1 ELSE IF X<0 THEN Znak:=-1 ELSE Znak:=0; END; PROCEDURE Zamien(VAR a, b : Integer); VAR c : Integer; BEGIN c := a; a := b; b := c; END; FUNCTION ObliczKod(x, y : Integer) : Byte; BEGIN ObliczKod := (Byte(x < EX1 ) OR (Byte(EX2 < x ) SHL 1) OR (Byte(y < EY1 ) SHL 2) OR (Byte(EY2 < y ) SHL 3)); END; BEGIN S_Move32(@DefaultRect, @Rect, SizeOf(TRect)); EX1 := Rect.X; EY1 := Rect.Y; EX2 := Rect.X+Rect.W-1; EY2 := Rect.Y+Rect.H-1; { !!! ZROBIC !!! Wykrywanie przypadkow poziomych i pionowych linii. } IF x1=x2 THEN BEGIN IF y1>y2 THEN V_VLine(V_Ekran, x1, y2, y1-y2+1, C) ELSE V_VLine(V_Ekran, x1, y1, y2-y1+1, C); Exit; END; IF y1=y2 THEN BEGIN IF x1>x2 THEN V_HLine(V_Ekran, x2, y1, x1-x2+1, C) ELSE V_HLine(V_Ekran, x1, y1, x2-x1+1, C); Exit; END; WHILE (TRUE) DO BEGIN P0 := ObliczKod(x1, y1); P1 := ObliczKod(x2, y2); IF (P0 = 0) AND (P1 = 0) THEN Break ELSE IF (P0 AND P1) <> 0 THEN Exit ELSE BEGIN IF (P0 = 0) THEN BEGIN Zamien(x1, x2); Zamien(y1, y2); Zamien(P0, P1); END; IF (P0 AND 1 <> 0) THEN BEGIN Temp:=X2-X1;IF Temp=0 THEN Inc(Temp); y1 := y1+(LongInt((EX1-X1))*(Y2-Y1)) DIV Temp; x1 := EX1; END; IF (P0 AND 2 <> 0) THEN BEGIN Temp:=X2-X1;IF Temp=0 THEN Inc(Temp); y1 := y1+(LongInt((EX2-x1))*(y2-y1)) DIV Temp; x1 := EX2; END; IF (P0 AND 4 <> 0) THEN BEGIN Temp:=Y2-Y1;IF Temp=0 THEN Inc(Temp); x1 := X1+(LongInt((EY1-Y1))*(X2-X1)) DIV Temp; y1 := EY1; END; IF (P0 AND 8 <> 0) THEN BEGIN Temp:=Y2-Y1;IF Temp=0 THEN Inc(Temp); x1 := x1+((EY2-y1)*(x2-x1)) DIV Temp; y1 := EY2; END; END; END; rx:=X2-X1; ry:=Y2-Y1; d1x:=Znak(rx); d1y:=Znak(ry); d2x:=Znak(rx); d2y:=0; m:=ABS(rx); n:=ABS(ry); IF m<=n THEN BEGIN d2x:=0; d2y:=Znak(ry); m:=ABS(ry); n:=ABS(rx); END; s:=m SHR 1; FOR l:=0 TO m DO BEGIN ASM Mov Ax, Y1 Cmp Ax, 99 Ja @DrugiBufor Les Di, V_Ekran.Ekr1 Jmp @DrawPix @DrugiBufor: Les Di, V_Ekran.Ekr2 Sub Ax, 100 @DrawPix: Shl Ax, 7 Add Di, Ax Shl Ax, 2 Add Di, Ax Add Di, X1 Add Di, X1 Mov Ax, C Mov Es:[Di], Ax END; s:=s+n; IF s>=m THEN BEGIN s:=s-m; X1:=X1+d1x; Y1:=Y1+D1Y; END ELSE BEGIN X1:=X1+D2X; Y1:=Y1+d2y; END; END; END; PROCEDURE V_Line(Buf:TEkran10Eh; X1, Y1, X2, Y2:Integer;C:Word); FUNCTION Znak(X:Integer):Integer; BEGIN IF X>0 THEN Znak:=1 ELSE IF X<0 THEN Znak:=-1 ELSE Znak:=0; END; PROCEDURE PrzytnijLinieX(VAR X1, Y1, X2, Y2:Integer; Rect:PRect); VAR a, b:Real; Granica:Integer; X12, X22, Y22, Y12:LongInt; BEGIN X12:=X1; X22:=X2; Y12:=Y1; Y22:=21; Granica:=Rect^.X; {PRZECIECIE Z OSIA Z LEWEJ} IF (X1 BEGIN Y12:=(Y1+Round((Y2-Y1)*(Granica-X1)/(X2-X1))); X12:=Granica; END; Granica:=Rect^.X+Rect^.W; {PRZECIECIE Z OSIA Z PRAWEJ} IF (X1 BEGIN Y22:=(Y2+Round((Y2-Y1)*(X2-Granica)/(X2-X1))); X22:=Granica-1; END; X1:=X12; X2:=X22; Y1:=Y12; Y2:=Y12; END; PROCEDURE PrzytnijLinieY(VAR X1, Y1, X2, Y2:Integer; Rect:PRect); VAR a, b:Real; Granica:Integer; X12, X22, Y22, Y12:LongInt; BEGIN X12:=X1; X22:=X2; Y12:=Y1; Y22:=21; Granica:=Rect^.Y; {PRZECIECIE Z GORNA KRAWEDZIA} IF (Y1 BEGIN X12:=(X1+Round((X2-X1)*(Granica-Y1)/(Y2-Y1))); Y12:=Granica; END; Granica:=Rect^.Y+Rect^.H; {PRZECIECIE Z DOLNA KRAWEDZIA} IF (Y1 BEGIN X22:=(X2+Round((X2-X1)*(Y2-Granica)/(Y2-Y1))); Y22:=Granica-1; END; X1:=X12; X2:=X22; Y1:=Y12; Y2:=Y12; END; VAR l, s, d1x, d1y, d2x, d2y, rx, ry, m, n, MaxX, MaxY, MinX, MinY : Integer; Rect:TRect; BEGIN S_Move32(@DefaultRect, @Rect, SizeOf(TRect)); {OBCINANIE LINI DLA Y} IF Y1>Y2 THEN BEGIN MaxY:=Y1;Y1:=Y2;Y2:=MaxY;MaxX:=X1;X1:=X2;X2:=MaxX END; IF (Y1>Rect.Y+Rect.H-1) OR (Y2 {OBCINANIE LINI DLA X} IF X1>X2 THEN BEGIN MaxY:=Y1;Y1:=Y2;Y2:=MaxY;MaxX:=X1;X1:=X2;X2:=MaxX END; IF (X1>Rect.X+Rect.W-1) OR (X2 rx:=X2-X1; ry:=Y2-Y1; d1x:=Znak(rx); d1y:=Znak(ry); d2x:=Znak(rx); d2y:=0; m:=ABS(rx); n:=ABS(ry); IF m<=n THEN BEGIN d2x:=0; d2y:=Znak(ry); m:=ABS(ry); n:=ABS(rx); END; s:=m SHR 1; FOR l:=0 TO m DO BEGIN IF (Y1>=Rect.Y) AND (Y2 Mov Ax, Y1 Cmp Ax, 99 Ja @DrugiBufor Les Di, Buf.Ekr1 Jmp @DrawPix @DrugiBufor: Les Di, Buf.Ekr2 Sub Ax, 100 @DrawPix: Shl Ax, 7 Add Di, Ax Shl Ax, 2 Add Di, Ax Add Di, X1 Add Di, X1 Mov Ax, C Mov Es:[Di], Ax END; s:=s+n; IF s>=m THEN BEGIN s:=s-m; X1:=X1+d1x; Y1:=Y1+D1Y; END ELSE BEGIN X1:=X1+D2X; Y1:=Y1+d2y; END; END; END; PROCEDURE V_HLineAlpha1(Buf:TEkran10Eh; X, Y, W:Integer;C:Word;Alpha:Byte); BEGIN IF (W<1) OR V_ObetnijHLine(X, Y, W) THEN Exit; ASM Mov Ax, Y Cmp Ax, 100 Ja @Drugi Les Di, Buf.Ekr1 Jmp @Dalej @Drugi: Les Di, Buf.Ekr2 Sub Ax, 100 @Dalej: Shl Ax, 7 Add Di, Ax Shl Ax, 2 Add Di, Ax Add Di, X Add Di, X Mov Cx, W Cld @Petla: Push Cx Mov Cl, Alpha Mov Bx, Es:[Di] Mov Ax, C Mov Dx, Bx Shr Dx, 11 Shr Ax, 11 Add Dx, Ax Shr Dx, Cl Shl Dx, 11 Mov Es:[Di], Dx And Bx, 0000011111111111b Mov Ax, C And Ax, 0000011111111111b Mov Dx, Bx Shr Dx, 5 Shr Ax, 5 Add Dx, Ax Shr Dx, Cl Shl Dx, 5 Or Es:[Di], Dx And Bx, 0000000000011111b Mov Ax, C And Ax, 0000000000011111b Mov Dx, Bx Add Dx, Ax Shr Dx, Cl Or Es:[Di], Dx Inc Di Inc Di Pop Cx Loop @Petla END; END; PROCEDURE V_RozmyjEkran(Buf:TEkran10Eh; Speed:Byte); BEGIN ASM Xor Dx, Dx Mov Dl, Speed Les Di, Buf.Ekr1 Mov Cx, 32000 Cld @Petla: Mov Bx, Es:[Di] Mov Ax, Bx Shr Ax, 11 Sub Ax, Dx Jnb @NieZerujAx Xor Ax, Ax @NieZerujAx: Shl Ax, 11 Mov Es:[Di], Ax And Bx, 0000011111111111b Mov Ax, Bx Shr Ax, 6 Sub Ax, Dx Jnb @NieZerujAx2 Xor Ax, Ax @NieZerujAx2: Shl Ax, 6 Or Es:[Di], Ax And Bx, 0000000000011111b Sub Bx, Dx Jnb @NieZerujBx Xor Bx, Bx @NieZerujBx: Or Es:[Di], Bx Inc Di Inc Di Loop @Petla Les Di, Buf.Ekr2 Mov Cx, 32000 Cld @Petla2: Mov Bx, Es:[Di] Mov Ax, Bx Shr Ax, 11 Sub Ax, Dx Jnb @NieZerujAx2x Xor Ax, Ax @NieZerujAx2x: Shl Ax, 11 Mov Es:[Di], Ax And Bx, 0000011111111111b Mov Ax, Bx Shr Ax, 6 Sub Ax, Dx Jnb @NieZerujAx22 Xor Ax, Ax @NieZerujAx22: Shl Ax, 6 Or Es:[Di], Ax And Bx, 0000000000011111b Sub Bx, Dx Jnb @NieZerujBx2 Xor Bx, Bx @NieZerujBx2: Or Es:[Di], Bx Inc Di Inc Di Loop @Petla2 END; END; PROCEDURE V_KopiujObraz(Buf:TEkran10Eh; Obraz:TPicture; X, Y:Integer); CONST EW:Word=320; EH:Word=200; VAR Lx, Rx, Gy :Integer; LxE, RxE :Integer; DyE, GyE :Integer; Width, Height :Integer; CountY :Integer; OffX :Word; SiGy, DiGyE :Word; GyE2 :Word; Add2, TC :Word; BMPx :Pointer; BEGIN IF NOT Assigned(Obraz) OR NOT Assigned(Obraz^.BMP) THEN Exit; WITH Obraz^ DO BEGIN IF X<0 THEN BEGIN LxE:=0;Lx:=-X;END ELSE BEGIN LxE:=X;Lx:= 0;END; IF Y<0 THEN BEGIN GyE:=0;Gy:=-Y;END ELSE BEGIN GyE:=Y;Gy:= 0;END; BMPx:=Obraz^.BMP; IF BMPx=NIL THEN Exit; IF (Lx>=W) OR (Gy>=H) THEN EXIT; IF LxE+W>EW THEN BEGIN RxE:=0;Rx:=Lx+LxE+W-(EW+Lx);END ELSE BEGIN RxE:=EW+Lx-(W+LxE);Rx:=0;END; IF GyE+H-Gy>EH THEN DyE:=0 ELSE DyE:=EH+Gy-(GyE+H); OffX:=(LxE+RxE) SHL 1; IF EW-LxE-RxE>0 THEN Width :=EW-LxE-RxE ELSE Exit; IF EH-GyE-DyE>0 THEN Height:=EH-GyE-DyE ELSE Exit; CountY:=101-GyE; IF GyE>100 THEN GyE2:=GyE-100 ELSE GyE2:=GyE; IF CountY<=0 THEN BEGIN CountY:=0;Add2:=GyE2*(EW SHL 1);END ELSE Add2:=0; SiGy :=(Gy * W) SHL 1; DiGyE:=(GyE2 * EW) SHL 1; Lx:=Lx SHL 1; Rx:=Rx SHL 1; LxE:=LxE SHL 1; RxE:=RxE SHL 1; TC:=TCol; END; {Do With} IF Obraz^.Transparent THEN ASM Push Ds {DLA OBRAZU, JESLI WYCHODZI} {POZA EKRAN} Lds Si, BMPx Add Si, SiGy {DLA EKRANU, JESLI OBRAZ} {ZACZYNA SIE W PEWNYM MOMENCIE} Les Di, Buf.Ekr1 Add Di, LxE Add Di, DiGyE Cmp CountY, 0 Jnz @NoChangePointer Les Di, Buf.Ekr2 Mov CountY, 100 Add Di, LxE Add Di, Add2 @NoChangePointer: {ORAZ ILE DODATKOWO Rep MovSW} Mov Ax, Width {ILE LINI MA RYSOWAC} Cld Mov Cx, Height Inc Cx {PETLA GLOWNA PROCEDURY} {KOPIUJACEJ LINIE} @KopiujCalosc: Dec CountY Jz @ChangePointer Loop @KopiujWiersz Jmp @Koniec @ChangePointer: Les Di, Buf.Ekr2 Mov CountY, 100 Add Di, LxE Add Di, Add2 Loop @KopiujWiersz Jmp @Koniec @KopiujWiersz: Push Cx Mov Cx, Ax Add Si, Lx @XXX: Mov Dx, [SI] Cmp Dx, TC Je @NieKopiujTego Mov Es:[Di], Dx @NieKopiujTego: {ZMIANA ADRESOW Di i Si} Inc Di Inc Di Inc Si Inc Si Loop @XXX @NieKopiujReszty: Add Di, OffX Add Si, Rx Pop Cx Jmp @KopiujCalosc @Koniec: Pop Ds END ELSE ASM Push Ds {DLA OBRAZU, JESLI WYCHODZI} {POZA EKRAN} Lds Si, BMPx Add Si, SiGy {DLA EKRANU, JESLI OBRAZ} {ZACZYNA SIE W PEWNYM MOMENCIE} Les Di, Buf.Ekr1 Add Di, LxE Add Di, DiGyE Cmp CountY, 0 Jnz @NoChangePointer Les Di, Buf.Ekr2 Mov CountY, 100 Add Di, LxE Add Di, Add2 @NoChangePointer: {ORAZ ILE DODATKOWO Rep MovSW} Mov Ax, Width {ILE LINI MA RYSOWAC} Cld Mov Cx, Height Inc Cx {PETLA GLOWNA PROCEDURY} {KOPIUJACEJ LINIE} @KopiujCalosc: Dec CountY Jz @ChangePointer Loop @KopiujWiersz Jmp @Koniec @ChangePointer: Les Di, Buf.Ekr2 Mov CountY, 100 Add Di, LxE Add Di, Add2 Loop @KopiujWiersz Jmp @Koniec @KopiujWiersz: Push Cx Mov Cx, Ax Mov Bx, Ax And Bx, 1 Shr Cx, 1 Add Si, Lx {KOPIOWANIE METODA 32 BITOWA} Cld Db $F3,$66,$A5 Mov Cx, Bx Cld Rep MovSW Add Di, OffX Add Si, Rx Pop Cx Jmp @KopiujCalosc @Koniec: Pop Ds END; END; PROCEDURE V_NewImage(VAR Picture:TPicture); BEGIN Picture:=NIL; IF MaxAvail New(Picture); Picture^.W:=0; Picture^.H:=0; Picture^.TCol:=0; Picture^.Transparent:=False; Picture^.BMP:=NIL; Picture^.BPP:=16; Picture^.Paleta:=NIL; END; PROCEDURE V_FreeImage(VAR Picture:TPicture); BEGIN IF Picture=NIL THEN Exit; IF Picture^.BMP<>NIL THEN FreeMem(Picture^.BMP, Picture^.W*Picture^.H*2); Dispose(Picture); Picture:=NIL; END; PROCEDURE V_WriteXY(Buf:TEkran10Eh;Font:PFont;X, Y:Integer;CONST S:STRING;C:Word;StepX:Byte); VAR A, B, Count:Byte; Ex:Integer; Line:Pointer; DX0, DY:Integer; Change:Integer; Nr, SP, Temp:Byte; RectX:TRect; BEGIN S_Move32(@DefaultRect, @RectX, SizeOf(TRect)); IF (Font=NIL) OR (Font^.Wzor=NIL) OR (Font^.TabKon=NIL) OR (Font^.TabAscii=NIL) THEN Exit; {Ustalanie liczby wyswietlanych znakow} IF (RectX.W+RectX.X-1-X) Count:=(RectX.W+RectX.X-1-X) DIV StepX; IF Byte(S[0]) {Kiedy nic nie trzeba rysowac} IF (Y (Count*StepX DX0:=X; SP:=1; IF X SP:=((RectX.X-X) DIV StepX); IF ((RectX.X-X) MOD StepX<>0) THEN INC(SP); DX0:=RectX.X+StepX*SP-(RectX.X-X); INC(SP); END; FOR A:=SP TO Count DO BEGIN Change:=101-Y;IF Change<0 THEN Change:=0; IF Change>0 THEN Line:=Buf.Ekr1 ELSE Line:=Buf.Ekr2; Temp:=Font^.TabAscii^[BYTE(S[A])]; FOR B:=0 TO 7 DO BEGIN IF (B+Y>=RectX.Y+RectX.H) OR (B+Y IF Change>0 THEN BEGIN Dec(Change); IF Change=0 THEN Line:=Buf.Ekr2; END; IF (Temp>0) AND (Temp<=Font^.MaxL) THEN Nr:=Font^.Wzor^[Temp, B] ELSE Nr:=BrakZnaku[B]; IF NOT V_TextNormal THEN Nr:=NOT Nr; Ex:=B+Y; IF Ex>99 THEN DEC(Ex, 100); IF Ex>=100 THEN Break; IF Ex>=0 THEN ASM Les Di, Line Mov Ax, Ex Shl Ax, 7 Add Di, Ax Shl Ax, 2 Add Di, Ax Mov Ax, DX0 Shl Ax, 1 Add Di, Ax Mov Dl, Nr Mov Cx, 8 Mov Bl, 10000000b Mov Ax, C Cld @Rysowanie: Test Bl, Dl Jz @NoDraw Mov Es:[Di], Ax @NoDraw: Shr Bl, 1 Inc Di Inc Di Loop @Rysowanie END; END; Inc(DX0, StepX); END; END; PROCEDURE V_CenterText(Buf:TEkran10Eh;Font:PFont;X, Y:Integer;CONST S:STRING;C:Word;StepX:Byte); BEGIN V_WriteXY(Buf, Font, X-((BYTE(S[0])*StepX) SHR 1), Y, S, C, StepX); END; PROCEDURE V_CenterTextRect(Buf:TEkran10Eh;Font:PFont;Rect:TRect;X, Y:Integer;CONST S:STRING;C:Word;StepX:Byte); BEGIN V_WriteXY(Buf, Font, X-((BYTE(S[0])*StepX) SHR 1), Y, S, C, StepX); END; PROCEDURE V_CopyLine(Buf:TEkran10Eh; Dest:Pointer; X, Y, W:Integer); VAR Temp:Pointer; BEGIN IF Y<100 THEN Temp:=Buf.Ekr1 ELSE BEGIN Temp:=Buf.Ekr2;Y:=Y-100;END; ASM Mov Cx, W Shl Cx, 1 Mov Dx, Cx And Dx, 3 Shr Cx, 2 Push Ds Les Di, Dest Lds Si, Temp Mov Ax, Y Shl Ax, 7 Add Si, Ax Shl Ax, 2 Add Si, Ax Add Si, X Add Si, X Cld Db $F3,$66,$A5 Mov Cx, Dx Rep MovSb Pop Ds END; END; PROCEDURE V_CopyFromLine(Buf:TEkran10Eh; Line:Pointer; X, Y, W:Integer); VAR Temp:Pointer; BEGIN IF Y<100 THEN Temp:=Buf.Ekr1 ELSE BEGIN Temp:=Buf.Ekr2;Y:=Y-100;END; IF X+W>=320 THEN W:=320-X; ASM Mov Cx, W Shl Cx, 1 Mov Dx, Cx And Dx, 3 Shr Cx, 2 Push Ds Les Di, Temp Lds Si, Line Mov Ax, Y Shl Ax, 7 Add Di, Ax Shl Ax, 2 Add Di, Ax Add Di, X Add Di, X Cld Db $F3,$66,$A5 Mov Cx, Dx Rep MovSb Pop Ds END; END; PROCEDURE V_CreateMirroredBMP(VAR Source, Dest:TPicture); VAR Temp : Pointer; Tmp : Pointer; Needed : Word; W, H : Integer; BEGIN IF NOT Assigned(Source) OR NOT Assigned(Source^.BMP) THEN Exit; IF NOT Assigned(Dest) THEN V_NewImage(Dest); W:=Source^.W; H:=Source^.H; Needed:=2*W*H; Dest^:=Source^; Tmp:=Source^.BMP; IF MaxAvail>=Needed THEN BEGIN GetMem(Temp, Needed); Dest^.BMP:=Temp; END ELSE Exit; ASM Push Ds Les Di, Temp Lds Si, Tmp Mov Cx, H @kopiujpion: Push Cx Mov Cx, W Add Di, Cx Add Di, Cx @kopiujpoziom: Dec Di Dec Di Mov Ax,Ds:[Si] Mov Es:[Di], Ax Inc Si Inc Si Loop @kopiujpoziom Mov Cx, W Add Di, Cx Add Di, Cx Pop Cx Loop @kopiujpion Pop Ds END; END; PROCEDURE V_PrintScreen(CONST Fn:STRING); TYPE TByteArr= ARRAY [ 0..0] OF Byte; TWordArr= ARRAY [ 0..0] OF Word; VAR BMPCapt : TBMPCaption; F:FILE; Line:Pointer; Temp:Pointer; i, j:Integer; R, G, B:Byte; BEGIN WITH BMPCapt DO BEGIN BM:=Byte('M') SHL 8 OR Byte('B'); Size:=SizeOf(TBMPCaption)+V_MaxEX*V_MaxEy*3; rezerw:=0; obraz_offset:=SizeOf(TBMPCaption); info:=40; Width:=V_MaxEX; Height:=V_MaxEY; LPO:=1; BPP:=24; kompresja:=0; Size_Obr:=V_MaxEX*V_MaxEy*3; HDPI:=96; VDPI:=96; Colors:=0; UColors:=0; END; GetMem(Line, V_MaxEX*2); GetMem(Temp, V_MaxEX*3); Assign(F, Fn); Rewrite(F, 1); BlockWrite(F, BMPCapt, SizeOf(TBMPCaption)); FOR i:= V_MaxEY-1 DOWNTO 0 DO BEGIN V_CopyLine(V_Ekran, Line, 0, i, V_MaxEX*2); FOR j:=0 TO V_MaxEX-1 DO BEGIN V_ToRGB(TWordArr(Line^)[j], R, G, B); TByteArr(Temp^)[j*3]:=B; TByteArr(Temp^)[j*3+1]:=G; TByteArr(Temp^)[j*3+2]:=R; END; BlockWrite(F, Temp^, V_MaxEX*3); END; FreeMem(Line, V_MaxEX*2); FreeMem(Temp, V_MaxEX*3); Close(F); END; PROCEDURE ShowCaptionBMP(CONST Fn:STRING); VAR BMPCapt : TBMPCaption; F:FILE; BEGIN Assign(F, Fn); Reset(F, 1); BlockRead(F, BMPCapt, SizeOf(TBMPCaption)); Close(F); WITH BMPCapt DO BEGIN WriteLn(Size); WriteLn(info); WriteLn(rezerw); WriteLn(obraz_offset, ' ', SizeOf(TBMPCaption)); WriteLn(LPO); WriteLn(kompresja); WriteLn(Colors); WriteLn(UColors); END; END; BEGIN DefaultRect:=EkranRect; END. |
Programy ON-LINE!