Pascal Ncolor
Pascal
Download (.zip)
Unit NColor;
{$Define Windowed}
{****************************************************************************} {*******************************} Interface {********************************} {****************************************************************************}
Const AlphaChannel:Byte=0; {$IfDef Windowed} MinX:Word=0; MaxX:Word=319; MinY:Word=0; MaxY:Word=199; {$EndIf}
Const Ascii_Data:Array [32..93] Of Word=(0, { } 08338,00045,24445,32223,21157, {!,",#,$,%} 15018,00018, {&,'} 08778,10530, {(,)} 02728,01488,05120,00448,08192, {*,+,,,-,.} 05268, {/} 11114,18740,29351,31143,18926, {0,1,2,3,4} 31183,31695,04775,10922,31215, {5,6,7,8,9} 01040,05136, {:,;} 17492,03640,05393,08615,29695, {<,=,>,?,@} 23535,15083,29263,15211,29391, {A,B,C,D,E} 04815,31311,23533,09362,11044, {F,G,H,I,J} 23277,29257,23421,24573,11114, {K,L,M,N,O} 05103,15215,22511,31183,09367, {P,Q,R,S,T} 31597,11117,24429,23213,09389, {U,V,W,X,Y} 29351, {Z} 29263,17553,31015); {[,\,]}
{Type PScreen=^TScreen; TScreen=Array [0..63999] Of Byte;
Var VScreen:PScreen;} Var VScreen:Pointer;
Procedure InitGraphMode; {Standard Procs} Procedure InitTextMode; Procedure PutPixel(X,Y:Word; Col:Byte); Function GetPixel(X,Y:Word):Byte; Procedure HLine(X,Y,L:Word; Col:Byte); Procedure VLine(X,Y,L:Word; Col:Byte); Procedure Line(X1,Y1,X2,Y2:Integer; Col:Byte); Procedure Box(X,Y,L,H:Word; Col:Byte); Procedure FBox(X,Y,L,H:Word; Col:Byte); Procedure FillTriAngle(X1,Y1,X2,Y2,X3,Y3:Integer; Col:Byte); Procedure FillPoly(X1,Y1,X2,Y2,X3,Y3,X4,Y4:Integer; Col:Byte); Procedure TexturePoly(X1,Y1,X2,Y2,X3,Y3,X4,Y4:Integer; Texture:Pointer); Procedure DumpScreen; Procedure UnDumpScreen; Procedure WaitRetrace; Procedure WaitShortRetrace; Procedure FillScreen(Col:Byte);
Procedure GetSprite(Var P:Pointer; X,Y,Breite,Hohe:Word); {Sprite Procs} Procedure PutSprite(P:Pointer; X,Y:Word); Procedure PutSpriteTrans(P:Pointer; X,Y:Word); {$IfDef Windowed} Procedure PutWinSprite(P:Pointer; X,Y:Integer); Procedure PutWinSpriteTrans(P:Pointer; X,Y:Integer); {$EndIf} Procedure PutScaleSprite(P:Pointer;X,Y:Integer;XL,YL:Word); Procedure PutScaleSpriteTrans(P:Pointer;X,Y:Integer;XL,YL:Word); Procedure PutSpritePixel(Var P:Pointer; X,Y:Word; Col:Byte); Function GetSpritePixel(P:Pointer; X,Y:Word):Byte; Procedure FreeSprite(Var P:Pointer); Procedure OpenSprite(Var P:Pointer;Hohe,Breite:Word); Procedure SaveSprite(P:Pointer; FileName:String); Procedure LoadSprite(Var P:Pointer; FileName:String); Function SpriteOverLap(P1,P2:Pointer;X1,Y1,X2,Y2:Word):Boolean; Function GetSpriteXL(P:Pointer):Word; Function GetSpriteYL(P:Pointer):Word;
Procedure SetPal(PalNum,R,G,B:Byte); {Palette Procs} Function GetPalR(PalNum:Byte):Byte; Function GetPalG(PalNum:Byte):Byte; Function GetPalB(PalNum:Byte):Byte; Procedure SetBorder(Col:Byte);
Function StrLen(Text:String):Word; {Font Procs} Function Int2Str(I:LongInt):String; Function Str2Int(S:String):LongInt; Procedure OutText(X,Y:Integer; Text:String; Col:Byte);
Procedure Wait(Time:Word); {Misc Procs} Function Key:Boolean; Procedure NoKey; Function ReadPort:Byte; Function ReadKey:Char;
{****************************************************************************} {*****************************} Implementation {*****************************} {****************************************************************************}
Const GraphModeOpen:Boolean=False;
Var SaveProc:Pointer;
{****************************************************************************} {*********************************************************** Standard Procs *} {****************************************************************************}
Procedure InitGraphMode;Assembler;
Asm mov GraphModeOpen,True mov ax,$0013 int 10h End;
Procedure InitTextMode;Assembler;
Asm mov GraphModeOpen,False mov ax,$0003 int 10h End;
Procedure PutPixel;Assembler;
Asm {$IfDef Windowed} mov ax,X cmp ax,MinX jb @skip cmp ax,MaxX ja @skip mov ax,Y cmp ax,MinY jb @skip cmp ax,MaxY ja @skip {$EndIf} les di,VScreen mov di,X mov ax,Y mov bx,ax shl ax,$08 shl bx,$06 add di,ax add di,bx mov al,Col stosb @skip: End;
Function GetPixel;Assembler;
Asm push ds {$IfDef Windowed} mov ax,X cmp ax,MinX jb @skip cmp ax,MaxX ja @skip mov ax,Y cmp ax,MinY jb @skip cmp ax,MaxY ja @skip {$EndIf} lds si,VScreen mov si,X mov ax,Y mov bx,ax shl ax,$08 shl bx,$06 add si,ax add si,bx lodsb @skip: pop ds End;
Procedure HLine;Assembler;
Asm les di,VScreen mov bx,Y mov cx,bx shl bx,$08 shl cx,$06 add bx,cx add bx,X add di,bx mov al,Col mov ah,al mov cx,L shr cx,$01 jnc @nobyte stosb @nobyte: rep stosw End;
Procedure VLine;Assembler;
Asm les di,VScreen mov bx,Y mov cx,bx shl bx,$08 shl cx,$06 add bx,cx add bx,X add di,bx mov cx,L mov al,Col @looper1: stosb add di,319 loop @looper1 End;
Procedure Line;
Function Sign(a:integer):Integer;
Begin If a>0 Then Sign:=+1; If a<0 Then Sign:=-1; If a=0 Then Sign:=0; End;
Var i,s,d1x,d1y,d2x,d2y,u,v,m,n:Integer;
Begin u:=x2-x1; v:=y2-y1; d1x:=Sign(u); d1y:=Sign(v); d2x:=Sign(u); d2y:=0; m:=Abs(u); n:=Abs(v); If Not(M>N) Then Begin d2x:=0; d2y:=Sign(v); m:=Abs(v); n:=Abs(u); End; s:=m ShR 1; For i:=0 To M Do Begin PutPixel(x1,y1,Col); Asm mov ax,n add s,ax {s := s + n;} mov ax,s cmp ax,m jb @elseif {IF not (s<m) THEN BEGIN} mov ax,m sub s,ax {s := s - m;} mov ax,d1x add x1,ax {x1:= x1 + d1x;} mov ax,d1y add y1,ax {y1 := y1 + d1y;} jmp @endif {end} @elseif: {ELSE BEGIN} mov ax,d2x add x1,ax {x1 := x1 + d2x;} mov ax,d2y add y1,ax {y1 := y1 + d2y;} @endif: {END;} End; End; End;
Procedure FBox;Assembler;
Asm {$IfDef Windowed} mov ax,X {ganz draussen rechts} cmp ax,MaxX ja @ende add ax,L {ganz draussen links} cmp ax,MinX jbe @ende cmp ax,MaxX {halb draussen rechts} jbe @weiterx1 mov bx,ax sub bx,MaxX sub L,bx inc L @weiterx1: mov ax,x {halb draussen links} cmp ax,MinX ja @weiterx2 mov bx,MinX sub bx,ax add X,bx sub L,bx @weiterx2: mov ax,Y {ganz draussen unten} cmp ax,MaxY ja @ende add ax,H {ganz draussen oben} cmp ax,MinY jbe @ende cmp ax,MaxY {halb draussen unten} jbe @weitery1 mov bx,ax sub bx,MaxY sub H,bx inc H @weitery1: mov ax,Y {halb draussen oben} cmp ax,MinY ja @weitery2 mov bx,MinY sub bx,ax add Y,bx sub H,bx @weitery2: {$EndIf} les di,VScreen mov bx,Y mov cx,bx shl bx,$08 shl cx,$06 add bx,cx add di,bx add di,X mov bx,H mov al,Col mov ah,al mov si,320 sub si,L mov cx,L push cx @looper1: shr cx,$01 jnc @nobyte stosb @nobyte: rep stosw add di,si pop cx push cx dec bx jnz @looper1 pop cx @ende: End;
Procedure Box;Assembler;
Asm les di,VScreen {Anfangs Adresse berechnen} mov bx,y mov cx,bx shl bx,$08 shl cx,$06 add bx,cx add di,bx add di,X {AA Ende} mov dx,L and dx,$01 mov si,320 sub si,L {Erste Linie berechnen} mov cx,L push cx mov al,Col mov ah,al {Erste Linie Zeichnen} shr cx,$01 jnc @nobyte1 stosb @nobyte1: rep stosw {vertikalen Linien} mov bx,H sub bx,$02 @looper1: add di,si stosb add di,L sub di,$02 stosb dec bx jnz @looper1 {Letzte Linie} add di,si pop cx shr cx,$01 jnc @nobyte2 stosb @nobyte2: rep stosw End;
Procedure FillTriAngle;
Const FracBits=16;
Var YMin,YMax,YCurr:Integer; XMin,XMax:Integer; DX1,DX2,DX3:LongInt; XP1,XP2,XP3:LongInt; Temp,Dont:Integer;
Begin YMin:=Y1; YMax:=Y1; If (Y2<YMin) Then Begin YMin:=X2; X2:=X1; X1:=YMin; YMin:=Y2; Y2:=Y1; Y1:=YMin; End; If (Y2>YMax) Then YMax:=Y2; If (Y3<YMin) Then Begin YMin:=X3; X3:=X1; X1:=YMin; YMin:=Y3; Y3:=Y1; Y1:=YMin; End; If (Y3>YMax) Then YMax:=Y3; If (Y3<Y2) Then Begin Temp:=Y3; Y3:=Y2; Y2:=Temp; Temp:=X3; X3:=X2; X2:=Temp; End;
XP1:=LongInt(X1) Shl FracBits; {Xpos in 9.7 fixed point math } XP2:=LongInt(X1) Shl FracBits; XP3:=LongInt(X2) Shl FracBits; Dont:=0; If Y2=Y1 Then Dont:=1 Else DX1:=(LongInt(X2-X1) Shl FracBits) Div (Y2-Y1); If Y3=Y1 Then Dont:=2 Else DX2:=(LongInt(X3-X1) Shl FracBits) Div (Y3-Y1); If Y3=Y2 Then Dont:=3 Else DX3:=(LongInt(X3-X2) Shl FracBits) Div (Y3-Y2); For YCurr:=YMin To YMax Do Begin XMin:=32000; XMax:=-32000; If (YCurr<=Y2) And (Dont<>1) Then Begin XMin:=XP1 Shr FracBits; XMax:=XMin; Inc(XP1,DX1); End; If (YCurr<=Y3) And (Dont<>2) Then Begin Temp:=XP2 Shr FracBits; If Temp<XMin Then XMin:=Temp; If Temp>XMax Then XMax:=Temp; Inc(XP2,DX2); End; If (YCurr>=Y2) And (Dont<>3) Then Begin Temp:=XP3 Shr FracBits; If Temp<XMin Then XMin:=Temp; If Temp>XMax Then XMax:=Temp; Inc(XP3,DX3); End; If XMin<MinX Then XMin:=MinX; If XMax>MaxX Then XMax:=MaxX; If (XMin<=MaxX) And (XMax>=XMin) And (YCurr>=MinY) And (YCurr<=MaxY) Then HLine(XMin,YCurr,XMax-XMin+1,Col); End; End;
Procedure FillPoly;
Const FracBits=16;
Var YMin,YMax,YCurr:Integer; XMin,XMax:Integer; DX1,DX2,DX3,DX4:LongInt; XP1,XP2,XP3,XP4:LongInt; Temp:Integer;
Begin YMin:=Y1; YMax:=Y1; If (Y2<YMin) Then YMin:=Y2; If (Y2>YMax) Then YMax:=Y2; If (Y3<YMin) Then YMin:=Y3; If (Y3>YMax) Then YMax:=Y3; If (Y4<YMin) Then YMin:=Y4; If (Y4>YMax) Then YMax:=Y4;
{Xpos in 16.16 fixed point math } If Y1<Y2 Then XP1:=LongInt(X1) Shl FracBits Else XP1:=LongInt(X2) Shl FracBits; If Y2<Y3 Then XP2:=LongInt(X2) Shl FracBits Else XP2:=LongInt(X3) Shl FracBits; If Y3<Y4 Then XP3:=LongInt(X3) Shl FracBits Else XP3:=LongInt(X4) Shl FracBits; If Y4<Y1 Then XP4:=LongInt(X4) Shl FracBits Else XP4:=LongInt(X1) Shl FracBits;
If Y1=Y2 Then DX1:=0 Else DX1:=(LongInt(X1-X2) Shl FracBits) Div (Y1-Y2); If Y2=Y3 Then DX2:=0 Else DX2:=(LongInt(X2-X3) Shl FracBits) Div (Y2-Y3); If Y3=Y4 Then DX3:=0 Else DX3:=(LongInt(X3-X4) Shl FracBits) Div (Y3-Y4); If Y4=Y1 Then DX4:=0 Else DX4:=(LongInt(X4-X1) Shl FracBits) Div (Y4-Y1);
For YCurr:=YMin To YMax Do Begin XMin:=32000; XMax:=-32000; If ((YCurr<=Y1) And (YCurr>=Y2)) Or ((YCurr<=Y2) And (YCurr>=Y1)) Then Begin XMin:=XP1 Shr FracBits; XMax:=XMin; Inc(XP1,DX1); End; If ((YCurr<=Y2) And (YCurr>=Y3)) Or ((YCurr<=Y3) And (YCurr>=Y2)) Then Begin Temp:=XP2 Shr FracBits; If Temp<XMin Then XMin:=Temp; If Temp>XMax Then XMax:=Temp; Inc(XP2,DX2); End; If ((YCurr<=Y3) And (YCurr>=Y4)) Or ((YCurr<=Y4) And (YCurr>=Y3)) Then Begin Temp:=XP3 Shr FracBits; If Temp<XMin Then XMin:=Temp; If Temp>XMax Then XMax:=Temp; Inc(XP3,DX3); End; If ((YCurr<=Y4) And (YCurr>=Y1)) Or ((YCurr<=Y1) And (YCurr>=Y4)) Then Begin Temp:=XP4 Shr FracBits; If Temp<XMin Then XMin:=Temp; If Temp>XMax Then XMax:=Temp; Inc(XP4,DX4); End; HLine(XMin,YCurr,XMax-XMin+1,Col); End; End;
Procedure TexturePoly;
Const FracBits=16; { TextureSizeX:Word=64; TextureSizeY:Word=64;{}
Procedure TexLine(XMin,Y,XMax,Tex1X,Tex1Y,Tex2X,Tex2Y:Integer; Texture:Pointer);
Var TexDX,TexDY:LongInt; CTX,CTY:LongInt; XCurr:Integer;
Begin If XMax=XMin Then Begin TexDX:=0; TexDY:=0; End Else Begin TexDX:=(LongInt(Tex2X-Tex1X) Shl FracBits) Div (XMax-XMin); TexDY:=(LongInt(Tex2Y-Tex1Y) Shl FracBits) Div (XMax-XMin); End; CTX:=LongInt(Tex1X) Shl FracBits; CTY:=LongInt(Tex1Y) Shl FracBits; For XCurr:=XMin To XMax Do Begin PutPixel(XCurr,Y, Mem[Seg(Texture^):Ofs(Texture^)+4+ (CTX Shr FracBits)+(CTY Shr FracBits)*64]); Inc(CTX,TexDX); Inc(CTY,TexDY); End; End;{}
Var YMin,YMax,YCurr:Integer; XMin,XMax:Integer; DX1,DX2,DX3,DX4:LongInt; XP1,XP2,XP3,XP4:LongInt; Tex1X,Tex1Y,Tex2X,Tex2Y:Integer; Tex1DX,Tex2DX,Tex3DX,Tex4DX:LongInt; Tex1P,Tex2P,Tex3P,Tex4P:LongInt; Temp:Integer;
Begin YMin:=Y1; YMax:=Y1; { TextureSizeX:=GetSpriteXL(Texture); TextureSizeX:=GetSpriteXL(Texture);{} If (Y2<YMin) Then YMin:=Y2; If (Y2>YMax) Then YMax:=Y2; If (Y3<YMin) Then YMin:=Y3; If (Y3>YMax) Then YMax:=Y3; If (Y4<YMin) Then YMin:=Y4; If (Y4>YMax) Then YMax:=Y4; {Xpos in 16.16 fixed point math } If Y1<Y2 Then Begin XP1:=LongInt(X1) Shl FracBits; Tex1P:=1; End Else Begin XP1:=LongInt(X2) Shl FracBits; Tex1P:=64 Shl FracBits; End; If Y2<Y3 Then Begin XP2:=LongInt(X2) Shl FracBits; Tex2P:=1; End Else Begin XP2:=LongInt(X3) Shl FracBits; Tex2P:=64 Shl FracBits; End; If Y3<Y4 Then Begin XP3:=LongInt(X3) Shl FracBits; Tex3P:=64 Shl FracBits; End Else Begin XP3:=LongInt(X4) Shl FracBits; Tex3P:=1; End; If Y4<Y1 Then Begin XP4:=LongInt(X4) Shl FracBits; Tex4P:=64 Shl FracBits; End Else Begin XP4:=LongInt(X1) Shl FracBits; Tex4P:=1; End;
If Y1=Y2 Then Begin DX1:=0; Tex1DX:=0; End Else Begin DX1:=(LongInt(X1-X2) Shl FracBits) Div (Y1-Y2); Tex1DX:=(LongInt(64) Shl FracBits) Div (Y2-Y1); End; If Y2=Y3 Then Begin DX2:=0; Tex2DX:=0; End Else Begin DX2:=(LongInt(X2-X3) Shl FracBits) Div (Y2-Y3); Tex2DX:=(LongInt(64) Shl FracBits) Div (Y3-Y2); End; If Y3=Y4 Then Begin DX3:=0; Tex3DX:=0; End Else Begin DX3:=(LongInt(X3-X4) Shl FracBits) Div (Y3-Y4); Tex3DX:=(LongInt(64) Shl FracBits) Div (Y3-Y4); End; If Y4=Y1 Then Begin DX4:=0; Tex4DX:=0; End Else Begin DX4:=(LongInt(X4-X1) Shl FracBits) Div (Y4-Y1); Tex4DX:=(LongInt(64) Shl FracBits) Div (Y4-Y1); End;
For YCurr:=YMin To YMax Do Begin XMin:=32000; XMax:=-32000; If ((YCurr<=Y1) And (YCurr>=Y2)) Or ((YCurr<=Y2) And (YCurr>=Y1)) Then Begin XMin:=XP1 Shr FracBits; XMax:=XMin; Tex1X:=Tex1P Shr FracBits;Tex1Y:=0; Tex2X:=Tex1P Shr FracBits;Tex2Y:=0; Inc(XP1,DX1); Inc(Tex1P,Tex1DX); End; If ((YCurr<=Y2) And (YCurr>=Y3)) Or ((YCurr<=Y3) And (YCurr>=Y2)) Then Begin Temp:=XP2 Shr FracBits; If Temp<XMin Then Begin XMin:=Temp; Tex1X:=63;Tex1Y:=Tex2P Shr FracBits; End; If Temp>XMax Then Begin XMax:=Temp; Tex2X:=63;Tex2Y:=Tex2P Shr FracBits; End; Inc(XP2,DX2); Inc(Tex2P,Tex2DX); End; If ((YCurr<=Y3) And (YCurr>=Y4)) Or ((YCurr<=Y4) And (YCurr>=Y3)) Then Begin Temp:=XP3 Shr FracBits; If Temp<XMin Then Begin XMin:=Temp; Tex1X:=Tex3P Shr FracBits;Tex1Y:=63; End; If Temp>XMax Then Begin XMax:=Temp; Tex2X:=Tex3P Shr FracBits;Tex2Y:=63; End; Inc(XP3,DX3); Inc(Tex3P,Tex3DX); End; If ((YCurr<=Y4) And (YCurr>=Y1)) Or ((YCurr<=Y1) And (YCurr>=Y4)) Then Begin Temp:=XP4 Shr FracBits; If Temp<XMin Then Begin XMin:=Temp; Tex1X:=0;Tex1Y:=Tex4P Shr FracBits; End; If Temp>XMax Then Begin XMax:=Temp; Tex2X:=0;Tex2Y:=Tex4P Shr FracBits; End; Inc(XP4,DX4); Inc(Tex4P,Tex4DX); End; TexLine(XMin,YCurr,XMax,Tex1X,Tex1Y,Tex2X,Tex2Y,Texture); End; End;
Procedure DumpScreen;Assembler;
Asm push ds lds si,VScreen xor di,di mov ax,$a000 mov es,ax mov cx,$7d00 rep movsw pop ds End;
Procedure UnDumpScreen;Assembler;
Asm push ds les di,VScreen xor si,si mov ax,$a000 mov ds,ax mov cx,$7d00 rep movsw pop ds End;
Procedure FillScreen;Assembler;
Asm les di,VScreen mov al,Col mov ah,al mov cx,$7d00 rep stosw End;
Procedure WaitRetrace;Assembler;
Asm mov dx,$03da @l1: in al,dx and al,$08 jnz @l1 @l2: in al,dx and al,$08 jz @l2 End;
Procedure WaitShortRetrace;Assembler;
Asm mov dx,$03da @l1: in al,dx and al,$01 jnz @l1 @l2: in al,dx and al,$01 jz @l2 End;
{****************************************************************************} {************************************************************* Sprite Procs *} {****************************************************************************}
Procedure GetSprite;
Begin GetMem(P,Breite*Hohe+4); Asm push ds lds si,P lodsw mov di,ax lodsw mov es,ax pop ds mov ax,Breite stosw mov ax,Hohe stosw mov cx,Breite mov dx,Hohe mov ax,Y mov bx,ax shl ax,$08 shl bx,$06 add ax,bx add ax,X mov bx,320 sub bx,Breite push ds lds si,[VScreen] add si,ax @looper1: push cx shr cx,$01 jnc @nobyte movsb @nobyte: rep movsw pop cx add si,bx dec dx jnz @looper1 pop ds End; End;
Procedure PutSprite;Assembler;
Asm push ds les di,[VScreen] lds si,P lodsw mov cx,ax lodsw mov dx,ax mov ax,Y mov bx,ax shl ax,$08 shl bx,$06 add ax,bx add ax,X mov bx,320 sub bx,cx add di,ax @looper1: push cx shr cx,$01 jnc @nobyte movsb @nobyte: rep movsw pop cx add di,bx dec dx jnz @looper1 pop ds End;
Procedure PutSpriteTrans;Assembler;
Var A:Byte;
Asm mov ah,AlphaChannel mov A,ah push ds les di,[VScreen] lds si,P lodsw mov cx,ax lodsw mov dx,ax mov ax,Y mov bx,ax shl ax,$08 shl bx,$06 add ax,bx add ax,X mov bx,320 sub bx,cx add di,ax @looper1: push cx @looper2: lodsb inc di cmp al,A je @trans dec di stosb @trans: loop @looper2 pop cx add di,bx dec dx jnz @looper1 pop ds End;
{$IfDef Windowed} Procedure PutWinSprite;Assembler;
Var X1,X2,Y1:Word;
Asm xor ax,ax mov X1,ax mov X2,ax mov Y1,ax push ds les di,[VScreen] lds si,P lodsw mov cx,ax lodsw mov dx,ax pop ds mov ax,X {ganz draussen rechts} cmp ax,MaxX jg @ende add ax,cx {ganz draussen links} cmp ax,MinX jle @ende cmp ax,MaxX {halb draussen rechts} jle @weiterx1 mov bx,ax sub bx,MaxX mov X2,bx {X2} dec X2 sub cx,bx inc cx @weiterx1: mov ax,x {halb draussen links} cmp ax,MinX jg @weiterx2 mov bx,MinX sub bx,ax add X,bx mov X1,bx {X1} sub cx,bx @weiterx2: mov ax,Y {ganz draussen unten} cmp ax,MaxY jg @ende add ax,dx {ganz draussen oben} cmp ax,MinY jle @ende cmp ax,MaxY {halb draussen unten} jle @weitery1 mov bx,ax sub bx,MaxY sub dx,bx inc dx @weitery1: mov ax,Y {halb draussen oben} cmp ax,MinY jg @weitery2 mov bx,MinY sub bx,ax add Y,bx mov Y1,bx {Y1} sub dx,bx @weitery2: push ds push dx lds si,P lodsw add si,2 mul Y1 add si,ax pop dx mov ax,Y mov bx,ax shl ax,$08 shl bx,$06 add ax,bx add ax,X mov bx,320 sub bx,cx add di,ax @looper1: add si,X1 push cx shr cx,$01 jnc @nobyte movsb @nobyte: rep movsw pop cx add di,bx add si,X2 dec dx jnz @looper1 pop ds @ende: End;
Procedure PutWinSpriteTrans;Assembler;
Var X1,X2,Y1:Word; A:Byte;
Asm mov ah,AlphaChannel mov A,ah xor ax,ax mov X1,ax mov X2,ax mov Y1,ax push ds les di,[VScreen] lds si,P lodsw mov cx,ax lodsw mov dx,ax pop ds mov ax,X {ganz draussen rechts} cmp ax,MaxX jg @ende add ax,cx {ganz draussen links} cmp ax,MinX jle @ende cmp ax,MaxX {halb draussen rechts} jle @weiterx1 mov bx,ax sub bx,MaxX mov X2,bx {X2} dec X2 sub cx,bx inc cx @weiterx1: mov ax,x {halb draussen links} cmp ax,MinX jg @weiterx2 mov bx,MinX sub bx,ax add X,bx mov X1,bx {X1} sub cx,bx @weiterx2: mov ax,Y {ganz draussen unten} cmp ax,MaxY jg @ende add ax,dx {ganz draussen oben} cmp ax,MinY jle @ende cmp ax,MaxY {halb draussen unten} jle @weitery1 mov bx,ax sub bx,MaxY sub dx,bx inc dx @weitery1: mov ax,Y {halb draussen oben} cmp ax,MinY jg @weitery2 mov bx,MinY sub bx,ax add Y,bx mov Y1,bx {Y1} sub dx,bx @weitery2: push ds push dx lds si,P lodsw add si,2 mul Y1 add si,ax pop dx mov ax,Y mov bx,ax shl ax,$08 shl bx,$06 add ax,bx add ax,X mov bx,320 sub bx,cx add di,ax @looper1: add si,X1 push cx @looper2: lodsb inc di cmp al,A je @trans dec di stosb @trans: loop @looper2 pop cx add di,bx add si,X2 dec dx jnz @looper1 pop ds @ende: End; {$EndIf}
Procedure PutScaleSprite;Assembler;
Var I,II:Integer;
Asm les di,VScreen {Berechne Ort in VScreen} push ds add di,X mov ax,Y mov bx,ax shl ax,8 shl bx,6 add di,ax add di,bx
mov ax,320d {berechne offset zwischen zwei hlines=320-XL} sub ax,XL push ax {speichern an oberster stelle in stack}
xor ax,ax {initialisiere schlaufe II=Y zhler} mov II,ax @for1: xor ax,ax {initialisiere schlaufe I=X zhler} mov I,ax
lds si,P {berechne Y position in sprite bezglich YL} lodsw mov bx,ax {XL in bx speichern...} lodsw mul II div YL mul bx {...um damit ypos zu berechnen} add ax,2 {wegen lodsw bei xpos von unten} mov cx,ax {ypos in cx speichern} mov bx,XL {bx mit XL Laden 2x fr unten}
@for2: lds si,P {Berechne x position in Sprite bezglich XL} lodsw mul I div bx {bx=XL noch von oben initialisiert}
add si,ax {xposition addieren} add si,cx {yposition addieren} movsb {kopieren}
inc I {Schlaufe I=X zhler} cmp I,bx {bx=XL noch von oben initialisiert} jnz @for2
add di,[bp-8] {offset zwischen zeilen=pop ax;add di,ax;push ax}
inc II {Schlaufe II=Y zhler} mov ax,YL cmp II,ax jnz @for1 pop ax pop ds End;
Procedure PutScaleSpriteTrans;Assembler;
Var I,II:Integer; A:Byte; {eine var mehr als oben-> [bp-10]}
Asm mov al,AlphaChannel mov A,al les di,VScreen {Berechne Ort in VScreen} push ds add di,X mov ax,Y mov bx,ax shl ax,8 shl bx,6 add di,ax add di,bx
mov ax,320d {berechne offset zwischen zwei hlines=320-XL} sub ax,XL push ax {speichern an oberster stelle in stack}
xor ax,ax {initialisiere schlaufe II=Y zhler} mov II,ax @for1: xor ax,ax {initialisiere schlaufe I=X zhler} mov I,ax
lds si,P {berechne Y position in sprite bezglich YL} lodsw mov bx,ax {XL in bx speichern...} lodsw mul II div YL mul bx {...um damit ypos zu berechnen} add ax,2 {wegen lodsw bei xpos von unten} mov cx,ax {ypos in cx speichern} mov bx,XL {bx mit XL Laden 2x fr unten}
@for2: lds si,P {Berechne x position in Sprite bezglich XL} lodsw mul I div bx {bx=XL noch von oben initialisiert}
add si,ax {xposition addieren} add si,cx {yposition addieren}
lodsb {kopieren} inc di cmp al,A je @nocopy dec di stosb @nocopy:
inc I {Schlaufe I=X zhler} cmp I,bx {bx=XL noch von oben initialisiert} jnz @for2
add di,[bp-10] {offset zwischen zeilen=pop ax;add di,ax;push ax} {da eine "var a:byte" mehr->10 statt 8}
inc II {Schlaufe II=Y zhler} mov ax,YL cmp II,ax jnz @for1 pop ax pop ds End;
Procedure PutSpritePixel;Assembler;
Asm push ds lds si,P lodsw mov di,ax lodsw mov es,ax mov ds,ax mov si,di lodsw pop ds
mov bx,Y {Berechne pos} dec bx mul bx add di,ax add di,X add di,$03 {2+2 (Hohe+Breite)=4 -1 (X)} mov al,Col stosb End;
Function GetSpritePixel;Assembler;
Asm push ds {Setze lods register} lds si,P lodsw
mov bx,Y {Berechne pos} dec bx mul bx add si,ax add si,X inc si {2+2 (Hohe+Breite)=4 -1 (X)=3 -2 (lodsw Breite)=1 -> inc} lodsb pop ds End;
Procedure FreeSprite;
Var Size:Word;
Begin Asm push ds lds si,P lodsw mov bx,ax lodsw mov ds,ax mov si,bx lodsw mov bx,ax lodsw mul bx add ax,$04 pop ds mov Size,ax End; FreeMem(P,Size); End;
Procedure OpenSprite;
Begin GetMem(P,Breite*Hohe+4); Asm push ds lds si,P lodsw mov di,ax lodsw mov es,ax pop ds mov ax,Hohe stosw mov ax,Breite stosw mov cx,Breite mov ax,Hohe mul cx mov cx,ax xor ax,ax rep stosb End; End;
Procedure SaveSprite;
Var F:File; Breite,Hohe:Word;
Begin Asm push ds lds si,P lodsw mov bx,ax lodsw pop ds mov Breite,bx mov Hohe,ax End; Assign(F,FileName); ReWrite(F,1); BlockWrite(F,P^,Breite*Hohe+4); Close(F); End;
Procedure LoadSprite;
Var F:File; Breite,Hohe:Word;
Begin Assign(F,FileName); ReSet(F,1); BlockRead(F,Breite,2); BlockRead(F,Hohe,2); GetMem(P,Breite*Hohe+4); Seek(F,0); BlockRead(F,P^,Breite*Hohe+4); Close(F); End;
Function SpriteOverLap;
Var O1,S1,O2,S2:Word;
Begin O1:=Ofs(P1^); S1:=Seg(P1^); O2:=Ofs(P2^); S2:=Seg(P2^); Asm mov @result,False push ds mov ds,S1 mov si,O1 lodsw {Breite} mov O1,ax lodsw {Hohe} mov S1,ax mov ds,S2 mov si,O2 lodsw {Breite} mov O2,ax lodsw {Hohe} mov S2,ax pop ds mov ax,X1 add ax,O1 cmp ax,X2 jb @ende mov ax,Y1 add ax,S1 cmp ax,Y2 jb @ende mov ax,X2 add ax,O2 cmp ax,X1 jb @ende mov ax,Y2 add ax,S2 cmp ax,Y1 jb @ende mov @result,True @ende: End; End;
Function GetSpriteXL;
Var Breite,Hohe:Word;
Begin Breite:=Ofs(P^); Hohe:=Seg(P^); Asm push ds mov si,Breite mov ds,Hohe lodsw mov Breite,ax pop ds End; GetSpriteXL:=Breite; End;
Function GetSpriteYL;
Var Breite,Hohe:Word;
Begin Breite:=Ofs(P^); Hohe:=Seg(P^); Asm push ds mov si,Breite mov ds,Hohe add si,$02 {alternativ: lodsw -> speedtest!} lodsw mov Hohe,ax pop ds End; GetSpriteYL:=Hohe; End;
{****************************************************************************} {************************************************************ Palette Procs *} {****************************************************************************}
Procedure SetPal;Assembler;
Asm mov dx,$03c8 mov al,Palnum out dx,al inc dx mov al, R out dx,al mov al,G out dx,al mov al,B out dx,al End;
Function GetPalR;Assembler;
Asm mov dx,$03c7 mov al,PalNum out dx,al add dx,2 in al,dx End;
Function GetPalG;Assembler;
Asm mov dx,$03c7 mov al,PalNum out dx,al add dx,2 in al,dx in al,dx End;
Function GetPalB;Assembler;
Asm mov dx,$03c7 mov al,PalNum out dx,al add dx,2 in al,dx in al,dx in al,dx End;
Procedure SetBorder;Assembler;
Asm mov dx,$3da in al,dx mov dx,$3c0 mov al,$11 or al,$20 out dx,al mov al,Col out dx,al End;
{****************************************************************************} {*************************************************************** Font Procs *} {****************************************************************************}
Function StrLen;Assembler;
Asm push ds lds si,Text lodsb xor ah,ah shl ax,$02 dec ax pop ds End;
Function ConvertChar(Letter:Byte):Byte;
Begin Case Letter Of 32..93:ConvertChar:=Letter-32;
Else ConvertChar:=0; End; End;
Procedure OutWinChar(X,Y:Word; Letter,Col:Byte);Assembler;
Asm push ds mov cx,15 lea si,Ascii_Data mov al,Letter xor ah,ah shl ax,1 add si,ax lodsw mov dx,ax shl dx,1 @looper: {PutPixel(X+((I-1) Mod 3),Y+((I-1) Div 3),Col);} shl dx,1 jnc @nopixel mov ax,cx dec ax mov bx,3 div bl mov bl,ah add bx,x mov di,bx {$IfDef Windowed} cmp bx,MinX jl @nopixel cmp bx,MaxX jg @nopixel {$EndIf} xor bh,bh mov bl,al add bx,y {$IfDef Windowed} cmp bx,MinY jl @nopixel cmp bx,MaxY jg @nopixel {$EndIf} push di les di,VScreen pop di mov ax,bx shl ax,8 shl bx,6 add di,ax add di,bx mov al,Col stosb @nopixel: loop @looper pop ds End;
Procedure OutChar(X,Y:Word; Letter,Col:Byte);Assembler;
Asm push ds mov cx,15 lea si,Ascii_Data mov al,Letter xor ah,ah shl ax,1 add si,ax lodsw mov dx,ax shl dx,1 @looper: {PutPixel(X+((I-1) Mod 3),Y+((I-1) Div 3),Col);} shl dx,1 jnc @nopixel mov ax,cx dec ax mov bx,3 div bl mov bl,ah add bx,x mov di,bx xor bh,bh mov bl,al add bx,y push di les di,VScreen pop di mov ax,bx shl ax,8 shl bx,6 add di,ax add di,bx mov al,Col stosb @nopixel: loop @looper pop ds End;
Function Int2Str;
Var S:String;
Begin Str(I,S); Int2Str:=S; End;
Function Str2Int;
Var I,Code:Integer;
Begin Val(S,I,Code); Str2Int:=I; End;
Procedure OutText;
Var I:Integer;
Begin If Length(Text)>0 Then For I:=1 To Length(Text) Do If (X+(I-1)*4<=MaxX) And (X+(I-1)*4+3>=MinX) And (Y<=MaxY) And (Y+5>=MinY) Then Begin If (X+(I-1)*4<MinX) Or (X+(I-1)*4+3>MaxX) Or (Y>MinY) Or (Y+5<MaxY) Then OutWinChar(X+(I-1)*4,Y,ConvertChar(Ord(UpCase(Text[I]))),Col) Else OutChar(X+(I-1)*4,Y,ConvertChar(Ord(UpCase(Text[I]))),Col) End; End;
{****************************************************************************} {*************************************************************** Misc Procs *} {****************************************************************************}
Procedure Wait;Assembler;
Asm mov ax,$03e8 mul Time mov cx,dx mov dx,ax mov ah,$86 int 15h End;
Function Key;Assembler;
Asm mov ah,$01 int 16h mov ax,$01 jnz @weiter xor ax,ax @weiter: End;
Procedure NoKey;Assembler;
Asm @looper: mov ah,$01 int 16h jz @nokey xor ah,ah int 16h jmp @looper @nokey: End;
Function ReadPort;Assembler;
Asm mov dx,$60 in al,dx End;
Function ReadKey;Assembler;
Asm xor ah,ah int 16h End;
Const Text='Visit http://www.datacomm.ch/asuter';
{$F+} Procedure NewExitProc;
Begin ExitProc:=SaveProc; { Dispose(VScreen);} FreeMem(VScreen,64000); If GraphModeOpen Then InitTextMode; WriteLn('NColor by Peter Suter & Clau Curtins'); WriteLn(Text); End; {$F-}
Begin WriteLn('NColor by Peter Suter & Clau Curtins'); WriteLn(Text); SaveProc:=ExitProc; ExitProc:=@NewExitProc; { New(VScreen);} GetMem(VScreen,64000); End.
|