-
Notifications
You must be signed in to change notification settings - Fork 1
/
Engine3D_Roofs.p
1053 lines (919 loc) · 24.1 KB
/
Engine3D_Roofs.p
1
unit Engine3D_Roofs; interfaceuses types, quickdraw, Dream3Display_Tipi, Engine3D_Globals;type LongRect = record top, left, bottom, right : longint; end; ThreePtrs = array [1..3] of ptr; var CurrentMaxY : integer; CurrentLevel : integer; Index : integer;procedure InitRoofs;procedure LoadAllRoofs (Id : integer);procedure RotateRoofs;procedure DisposeAllRoofs;procedure DrawRoof ( TheRoofId : integer; TheX : integer);implementation{$R-}uses memory, resources, qdoffscreen, icons, fixmath, toolutils, events, segload, cilindro, dreamTypes, lowlevel, Dream3Display_Tools, Engine3D_CIconArray, Engine3D_Rotate, Engine3D_DrawFloor; const OutOfFireDistance = 25000; RoofResType = 'Roof'; RoofListResType = 'RofL'; MaxRoofs = 256; type RoofRes = record Id : integer; MapRect : rect; Height0Side : integer; Height0 : integer; Height1 : integer; RoofCIconId : integer; SideCIconId : integer; Level : integer; end; RoofResPtr = ^RoofRes; RoofResHandle = ^RoofResPtr; RoofListRes = record Items : integer; RoofId : array [0..MaxRoofs - 1] of integer; end; RoofListResPtr = ^RoofListRes; RoofListResHandle = ^RoofListResPtr; DoubleRectPoint = array [0..3] of DoublePoint; RoofMStruct = record MiddleZSide : longint; XStart : integer; YStart : integer; XDist : integer; DeltaY : fixed; DeltaY0 : integer; SideType : integer; SideInclin : integer; end; Roof = record RealRect : LongRect; RealRectH : DoubleRectPoint; TheZs : array [0..3] of integer; TheZ4 : integer; SelfZ : array [0..3] of longint; RealRectPH : DoubleRectPoint; RealRectPV : DoubleRectPoint; Height0Side : integer; Height0 : integer; Height1 : integer; CRoofPtr : ThreePtrs; CSidePtr : ThreePtrs; MiddleZ : longint; BaseSideInclin : array [0..3] of integer; MStruct : array [0..3] of RoofMStruct; PX0, PX1 : longint; Level : integer; end; RoofPtr = ^Roof; RoofHandle = ^RoofPtr; RoofListType = array [1..MaxRoofs] of RoofPtr; RoofListPtr = ^RoofListType; ListAiutItem = record SID, RID : integer; end; ListAiut = array [1..MaxRoofs] of ListAiutItem; ListAiutPtr = ^listAiut; var RoofList : RoofListPtr; RoofsN : integer; {$S Engine3D_RoofsUtils}function GetRoofRes ( Id : integer) : RoofResPtr;var Tmp : RoofResPtr; TmpH : handle; begin TmpH := mygetresource (RoofResType, Id, true, true); hlock (TmpH); Tmp := RoofResPtr (newptr (sizeof (RoofRes))); if tmp = nil then deathalert (erroutofmemory, memerror); blockmove (TmpH^, Tmp, sizeof (RoofRes)); releaseresource (TmpH); GetRoofRes := Tmp;end;{$S Engine3D_RoofsUtils}procedure LoadAllRoofs (Id : integer);var Tmp : RoofListResHandle; I : integer; ListAiuto : ListAiutPtr; {$S Engine3D_RoofsUtils}function GetRoof ( Id : integer) : RoofPtr;var Tmp : RoofResPtr; Tmp2 : RoofPtr; DoublePlaceDim : integer; isNew : boolean; begin DoublePlaceDim := Environment.PlaceDim * 2; Tmp2 := RoofPtr (newptr (sizeof (Roof))); if tmp2 = nil then deathalert (erroutofmemory, memerror); Tmp := GetRoofRes (Id); with Tmp2^ do begin Height0 := -Tmp^.Height0; Height1 := -Tmp^.Height1; Height0Side := Tmp^.Height0Side; with RealRect do begin Left := Tmp^.MapRect.left * DoublePlaceDim - DoublePlaceDim; Top := (Environment.MapVer - Tmp^.MapRect.top + 1) * DoublePlaceDim; Right := Tmp^.MapRect.right * DoublePlaceDim - DoublePlaceDim; Bottom := (Environment.MapVer - Tmp^.MapRect.bottom + 1) * DoublePlaceDim; end; with RealRect do begin with RealRectH [0] do begin H := Left; V := Top; end; with RealRectH [1] do begin H := Right; V := Top; end; with RealRectH [2] do begin H := Right; V := Bottom; end; with RealRectH [3] do begin H := Left; V := Bottom; end; end; case Height0Side of 0 : begin TheZs [0] := Height0; TheZs [1] := Height1; TheZs [2] := Height1; TheZs [3] := Height0; BaseSideInclin [0] := 4; BaseSideInclin [1] := 1; BaseSideInclin [2] := 2; BaseSideInclin [3] := 3; end; 1 : begin TheZs [0] := Height0; TheZs [1] := Height0; TheZs [2] := Height1; TheZs [3] := Height1; BaseSideInclin [0] := 3; BaseSideInclin [1] := 4; BaseSideInclin [2] := 1; BaseSideInclin [3] := 2; end; 2 : begin TheZs [0] := Height1; TheZs [1] := Height0; TheZs [2] := Height0; TheZs [3] := Height1; BaseSideInclin [0] := 2; BaseSideInclin [1] := 3; BaseSideInclin [2] := 4; BaseSideInclin [3] := 1; end; 3 : begin TheZs [0] := Height1; TheZs [1] := Height1; TheZs [2] := Height0; TheZs [3] := Height0; TheZ4 := Height0; BaseSideInclin [0] := 1; BaseSideInclin [1] := 2; BaseSideInclin [2] := 3; BaseSideInclin [3] := 4; end; end; TheZ4 := Height0; end; Tmp2^.Level := Tmp^.Level; with tmp2^do begin cRoofPtr [3] := getCIconOnPtr (tmp^.roofCIconId, false, isNew); cRoofPtr [2] := ptr (longint (cRoofPtr [3]) + 4096); if isNew and environment.mipMap then mipMap64 (cRoofPtr [2]); cRoofPtr [1] := ptr (longint (cRoofPtr [3]) + 8192); if isNew and environment.mipMap then mipMap64 (cRoofPtr [1]); cSidePtr [3] := getCIconOnPtr (tmp^.sideCIconId, false, isNew); cSidePtr [2] := ptr (longint (cSidePtr [3]) + 4096); if isNew and environment.mipMap then mipMap64 (cSidePtr [2]); cSidePtr [1] := ptr (longint (cSidePtr [3]) + 8192); if isNew and environment.mipMap then mipMap64 (cSidePtr [1]); end; disposeptr (ptr (Tmp)); GetRoof := Tmp2;end;begin listAiuto := listAiutPtr (newptr (sizeof (listAiut))); if listAiuto = nil then deathalert (erroutofmemory, memerror); RoofsN := 0; Tmp := RoofListResHandle (mygetresource (RoofListResType, Id, false, true)); if Tmp = nil then exit (LoadAllRoofs); hlock (handle (Tmp)); for I := 0 to Tmp^^.Items do begin RoofsN := RoofsN + 1; RoofList^ [RoofsN] := GetRoof (Tmp^^.RoofId [I]); end; releaseresource (handle (Tmp)); disposeptr (ptr (listAiuto));end;{$S Engine3D_RoofsUtils}procedure InitRoofs;begin RoofList := RoofListPtr (newptr (sizeof (RoofListType))); if RoofList = nil then deathalert (erroutofmemory, MemError);end;{$S Engine3D_RoofsUtils}procedure DisposeARoof (TheRoof : RoofPtr);var j : integer; begin j := Environment.DiffuseLight; if environment.mipMap then j := 1; disposePictOnPtr (TheRoof^.CSidePtr [3]); disposePictOnPtr (TheRoof^.CRoofPtr [3]); disposeptr (ptr (TheRoof));end;{$S Engine3D_RoofsUtils}procedure DisposeAllRoofs;var I : integer; begin for I := 1 to RoofsN do DisposeARoof (RoofList^ [I]);end;{$S Engine3D}function RotateARoof ( TheRoof : RoofPtr) : boolean;var I, J : integer; VPointH, VPointV : longint; TheSin, TheCos : integer; Tmp0H, Tmp0V, Tmp1H, Tmp1V : longint; HowManyIn : integer; Tmp : RoofMStruct; MaxZ : longint; begin VPointH := Environment.ViewPoint.h; VPointV := Environment.ViewPoint.v; TheSin := DiscreteSin [Environment.ViewAngle]; TheCos := DiscreteCos [Environment.ViewAngle]; RotateARoof := false; with TheRoof^ do begin for I := 3 downto 0 do begin Tmp0H := RealRectH [I].H - VPointH; Tmp0V := RealRectH [I].V - VPointV; Tmp1V := Tmp0V * TheCos - Tmp0H * TheSin; if Tmp1V < DistanceN40 then exit (RotateARoof); RealRectPH [I].V := Tmp1V; RealRectPH [I].H := Tmp0H * TheCos + Tmp0V * TheSin; end; HowManyIn := 4; for I := 3 downto 0 do begin Tmp1H := bsl (RealRectPH [I].H, 9) div (RealRectPH [I].V + Distance40); if (Tmp1H < -WindowXCenter) or (Tmp1H > WindowXCenter) then HowManyIn := HowManyIn - 1; RealRectPV [I].H := Tmp1H; RealRectPV [I].V := bsl (TheZs [I], 16) div (RealRectPH [I].V + Distance40); if TheZ4 <> TheZs [I] then SelfZ [I] := bsl (TheZs [4], 16) div (RealRectPH [I].V + Distance40) + 1 else SelfZ [I] := RealRectPV [I].V + 1; end; if HowManyIn = 0 then exit (RotateARoof); MStruct [0].MiddleZSide := RealRectPH [0].V + RealRectPH [3].V; MStruct [1].MiddleZSide := RealRectPH [0].V + RealRectPH [1].V; MStruct [2].MiddleZSide := RealRectPH [1].V + RealRectPH [2].V; MStruct [3].MiddleZSide := RealRectPH [2].V + RealRectPH [3].V; MaxZ := RealRectPH [0].V; if RealRectPH [1].V > MaxZ then MaxZ := RealRectPH [1].V; if RealRectPH [2].V > MaxZ then MaxZ := RealRectPH [2].V; if RealRectPH [3].V > MaxZ then MaxZ := RealRectPH [3].V; MiddleZ := bsl (MaxZ, 1) + 1; with MStruct [0] do begin XDist := RealRectPV [0].H - RealRectPV [3].H; if BaseSideInclin [0] = 1 then DeltaY0 := SelfZ [0] - RealRectPV [0].V else if BaseSideInclin [0] = 3 then DeltaY0 := SelfZ [3] - RealRectPV [3].V; SideType := 4; if XDist < 0 then begin XDist := -XDist; SideInclin := -BaseSideInclin [0]; XStart := RealRectPV [0].H; YStart := RealRectPV [0].V; DeltaY := fixdiv (RealRectPV [3].V - RealRectPV [0].V, XDist + 1); end else begin SideInclin := BaseSideInclin [0]; XStart := RealRectPV [3].H; YStart := RealRectPV [3].V; DeltaY := fixdiv (RealRectPV [0].V - RealRectPV [3].V, XDist + 1); end; end; with MStruct [1] do begin XDist := RealRectPV [1].H - RealRectPV [0].H; if BaseSideInclin [1] = 1 then DeltaY0 := SelfZ [1] - RealRectPV [1].V else if BaseSideInclin [1] = 3 then DeltaY0 := SelfZ [0] - RealRectPV [0].V; SideType := 1; if XDist < 0 then begin XDist := -XDist; SideInclin := -BaseSideInclin [1]; XStart := RealRectPV [1].H; YStart := RealRectPV [1].V; DeltaY := fixdiv (RealRectPV [0].V - RealRectPV [1].V, XDist + 1); end else begin SideInclin := BaseSideInclin [1]; XStart := RealRectPV [0].H; YStart := RealRectPV [0].V; DeltaY := fixdiv (RealRectPV [1].V - RealRectPV [0].V, XDist + 1); end; end; with MStruct [2] do begin XDist := RealRectPV [1].H - RealRectPV [2].H; if BaseSideInclin [2] = 1 then DeltaY0 := SelfZ [2] - RealRectPV [2].V else if BaseSideInclin [2] = 3 then DeltaY0 := SelfZ [1] - RealRectPV [1].V; SideType := 2; if XDist < 0 then begin XDist := -XDist; SideInclin := -BaseSideInclin [2]; XStart := RealRectPV [1].H; YStart := RealRectPV [1].V; DeltaY := fixdiv (RealRectPV [2].V - RealRectPV [1].V, XDist + 1); end else begin SideInclin := BaseSideInclin [2]; XStart := RealRectPV [2].H; YStart := RealRectPV [2].V; DeltaY := fixdiv (RealRectPV [1].V - RealRectPV [2].V, XDist + 1); end; end; with MStruct [3] do begin XDist := RealRectPV [2].H - RealRectPV [3].H; if BaseSideInclin [3] = 1 then DeltaY0 := SelfZ [3] - RealRectPV [3].V else if BaseSideInclin [3] = 3 then DeltaY0 := SelfZ [2] - RealRectPV [2].V; SideType := 3; if XDist < 0 then begin XDist := -XDist; SideInclin := -BaseSideInclin [3]; XStart := RealRectPV [2].H; YStart := RealRectPV [2].V; DeltaY := fixdiv (RealRectPV [3].V - RealRectPV [2].V, XDist + 1); end else begin SideInclin := BaseSideInclin [3]; XStart := RealRectPV [3].H; YStart := RealRectPV [3].V; DeltaY := fixdiv (RealRectPV [2].V - RealRectPV [3].V, XDist + 1); end; end; for I := 1 to 3 do for J := 3 downto I do if MStruct [J - 1].MiddleZSide > MStruct [J].MiddleZSide then begin Tmp := MStruct [J - 1]; MStruct [J - 1] := MStruct [J]; MStruct [J] := Tmp; end; PX0 := RealRectPV [3].H; PX1 := PX0; for I := 2 downto 0 do begin Tmp1H := RealRectPV [I].H; if Tmp1H < PX0 then PX0 := Tmp1H else if Tmp1H > PX1 then PX1 := Tmp1H; end; end; RotateARoof := true;end;{$S Engine3D}procedure RotateRoofs;var LocalList : RoofListPtr; LocalRoof : RoofPtr; I : integer; begin LocalList := RoofList; for I := RoofsN downto 1 do begin LocalRoof := LocalList^ [I]; if RotateARoof (LocalRoof) then begin PolyN := PolyN + 1; with Polys^ [PolyN] do begin ProjCorner0.X := LocalRoof^.PX0; ProjCorner1.X := LocalRoof^.PX1; MiddleZ := LocalRoof^.MiddleZ; PoType := RoofPoly; BaseRef := I; Levels := LocalRoof^.Level + 1; if Levels > MaxVWall then MaxVWall := Levels; FullMask := true; end; end; end;end;{$S Engine3D}procedure DrawRoof ( TheRoofId : integer; TheX : integer);var TheXStart, TheXEnd, TheStartSide, TheEndSide, TheYStart, TheYEnd : integer; TheXstension : integer; TheRoof : RoofPtr; TheXBetter : integer; StartByY : integer; StartInclin : integer; {$S Engine3D}procedure GetSides;label 100, 101; var I, J : integer; DeltaX : longint; TheXDist : longint; TmpY : integer; EndInclin : integer; begin I := 0; with TheRoof^ do begin101: DeltaX := TheX - MStruct [I].XStart; TheXDist := MStruct [I].XDist; if (DeltaX >= 0) and (DeltaX <= TheXDist) then begin StartInclin := MStruct [I].SideInclin; TmpY := MStruct [I].YStart; TheYStart := TmpY + bsr (MStruct [I].DeltaY * DeltaX, 16); TheXStart := bsl (DeltaX, 6) div (TheXDist + 1); TheStartSide := MStruct [I].SideType; if StartInclin < 0 then begin StartInclin := -StartInclin; TheXStart := 63 - TheXStart; end; goto 100; end else begin I := I + 1; goto 101; end;100: if StartInclin in [1, 3] then begin TheXstension := MStruct [I].DeltaY0 + 1; case MStruct [I].SideInclin of 1, -3 : StartByY := TheXStart; 3, -1 : StartByY := 63 - TheXStart; end; end; J := I + 1; repeat DeltaX := TheX - MStruct [J].XStart; TheXDist := MStruct [J].XDist; if (DeltaX >= 0) and (DeltaX <= TheXDist) then begin TheYEnd := MStruct [J].YStart + bsr (MStruct [J].DeltaY * DeltaX, 16); TheEndSide := MStruct [J].SideType; EndInclin := MStruct [J].SideInclin; TheXEnd := bsl (DeltaX, 6) div (TheXDist + 1); if EndInclin < 0 then begin TheXEnd := 63 - TheXEnd; end; end; J := J + 1; until J = 4; end;end;{$S Engine3D}procedure DrawTheSide;var I : integer; TheSrcPtr : ptr; TheDstPtr : ptr; LocalDstRow : integer; Dy : fixed; IconY : fixed; begin LocalDstRow := DstRow; if TheXstension > 1023 then Dy := fixdiv (64, TheXStension) else Dy := Div64^ [TheXstension]; if TheYStart < 0 then begin IconY := Dy * (-TheYStart); TheSrcPtr := ptr (longint (TheRoof^.CSidePtr [Index]) + TheXStart + bsl (StartByY, 6) + band (bsr (IconY, 10), $FFFFFFC0)); TheDstPtr := ptr (longint (OffScreenAddr) + TheXBetter); while IconY > $10000 do IconY := IconY - $10000; TheYStart := 0; end else begin TheSrcPtr := ptr (longint (TheRoof^.CSidePtr [Index]) + TheXStart + bsl (StartByY, 6)); TheDstPtr := ptr (longint (OffScreenAddr) + TheXBetter + DstRowTop^ [TheYStart]); IconY := 0; end; I := CurrentMaxY - TheYStart + 1; while I > 0 do begin TheDstPtr^ := TheSrcPtr^; TheDstPtr := ptr (longint (TheDstPtr) + LocalDstRow); IconY := IconY + Dy; while IconY > $10000 do begin TheSrcPtr := ptr (longint (TheSrcPtr) + 64); IconY := IconY - $10000; end; I := I - 1; end;end;{$S Engine3D}procedure DrawTheSide2 (Distance : longint);var I : integer; TheSrcPtr : integerptr; TheDstPtr : integerptr; LocalDstRow : integer; Dy : fixed; IconY : fixed; Tmp : integer; begin LocalDstRow := DstRow; if TheXstension > 1023 then Dy := fixdiv (64, TheXStension) else Dy := Div64^ [TheXstension]; if TheYStart < 0 then begin IconY := Dy * (-TheYStart); TheSrcPtr := integerptr (longint (TheRoof^.CSidePtr [Index]) + TheXStart + bsl (StartByY, 6) + band (bsr (IconY, 10), $FFFFFFC0)); TheDstPtr := integerptr (longint (OffScreenAddr) + TheXBetter); while IconY > $10000 do IconY := IconY - $10000; TheYStart := 0; end else begin TheSrcPtr := integerptr (longint (TheRoof^.CSidePtr [Index]) + TheXStart + bsl (StartByY, 6)); TheDstPtr := integerptr (longint (OffScreenAddr) + TheXBetter + DstRowTop^ [TheYStart]); IconY := 0; end; I := CurrentMaxY - TheYStart + 1; if Distance > OutOfFireDistance then begin if TheXStart = 63 then TheSrcPtr := integerptr (longint (TheSrcPtr) - 1); while I > 0 do begin TheDstPtr^ := TheSrcPtr^; TheDstPtr := integerptr (longint (TheDstPtr) + LocalDstRow); IconY := IconY + Dy; while IconY > $10000 do begin TheSrcPtr := integerptr (longint (TheSrcPtr) + 64); IconY := IconY - $10000; end; I := I - 1; end end else while I > 0 do begin Tmp := TheSrcPtr^; TheDstPtr^ := bor (bsr (Tmp, 8), band (Tmp, $FF00)); TheDstPtr := integerptr (longint (TheDstPtr) + LocalDstRow); IconY := IconY + Dy; while IconY > $10000 do begin TheSrcPtr := integerptr (longint (TheSrcPtr) + 64); IconY := IconY - $10000; end; I := I - 1; end;end;{$S Engine3D}procedure DrawTheSide3;var I : integer; TheSrcPtr : ptr; TheDstPtr : ptr; LocalDstRow : integer; Dy : fixed; IconY : fixed; Tmp : byte; begin LocalDstRow := DstRow - 2; if TheXstension > 1023 then Dy := fixdiv (64, TheXStension) else Dy := Div64^ [TheXstension]; if TheYStart < 0 then begin IconY := Dy * (-TheYStart); TheSrcPtr := ptr (longint (TheRoof^.CSidePtr [Index]) + TheXStart + bsl (StartByY, 6) + band (bsr (IconY, 10), $FFFFFFC0)); TheDstPtr := ptr (longint (OffScreenAddr) + TheXBetter); while IconY > $10000 do IconY := IconY - $10000; TheYStart := 0; end else begin TheSrcPtr := ptr (longint (TheRoof^.CSidePtr [Index]) + TheXStart + bsl (StartByY, 6)); TheDstPtr := ptr (longint (OffScreenAddr) + TheXBetter + DstRowTop^ [TheYStart]); IconY := 0; end; I := CurrentMaxY - TheYStart + 1; while I > 0 do begin Tmp := TheSrcPtr^; TheDstPtr^ := Tmp; TheDstPtr := ptr (longint (TheDstPtr) + 1); TheDstPtr^ := Tmp; TheDstPtr := ptr (longint (TheDstPtr) + 1); TheDstPtr^ := Tmp; TheDstPtr := ptr (longint (TheDstPtr) + LocalDstRow); IconY := IconY + Dy; while IconY > $10000 do begin TheSrcPtr := ptr (longint (TheSrcPtr) + 64); IconY := IconY - $10000; end; I := I - 1; end;end;{$S Engine3D}procedure DrawTheRoof;var DeltaX, DeltaY, IconX, IconY : fixed; TheXstension : integer; TheSrcPtr : ptr; TheDstPtr : ptr; TheDstIPtr : integerptr; I : integer; LocalDstRow : integer; Tmp : integer; begin LocalDstRow := DstRow; TheXstension := TheYStart - TheYEnd + 1; case TheEndSide of 4 : begin IconX := 0; IconY := bsl (63 - TheXEnd, 16); case TheStartSide of 1 : begin DeltaX := bsl (TheXStart, 16) div TheXstension; DeltaY := - bsl (63 - TheXEnd, 16) div TheXstension; end; 2 : begin DeltaX := (63 * $10000) div TheXstension; DeltaY := bsl (TheXEnd - TheXStart, 16) div TheXstension; end; 3 : begin DeltaX := bsl (TheXStart, 16) div TheXstension; DeltaY := bsl (TheXEnd, 16) div TheXstension; end; 4 : begin DeltaX := 0; DeltaY := bsl (TheXEnd - TheXStart, 16) div TheXstension; end; end; end; 1 : begin IconX := bsl (TheXEnd, 16); IconY := 0; case TheStartSide of 1 : begin DeltaX := fixdiv (TheXStart - TheXEnd, TheXstension); DeltaY := 0; end; 2 : begin DeltaX := fixdiv (63 - TheXEnd, TheXstension); DeltaY := fixdiv (63 - TheXStart, TheXstension); end; 3 : begin DeltaX := fixdiv (TheXStart - TheXEnd, TheXstension); DeltaY := fixdiv (63, TheXstension); end; 4 : begin DeltaX := fixdiv (-TheXEnd, TheXstension); DeltaY := fixdiv (63 - TheXStart, TheXstension); end; end; end; 2 : begin IconX := 63 * $10000; IconY := bsl (63 - TheXEnd, 16); case TheStartSide of 1 : begin DeltaX := fixdiv (TheXStart - 63, TheXstension); DeltaY := fixdiv (TheXEnd - 63, TheXstension); end; 2 : begin DeltaX := 0; DeltaY := fixdiv (TheXEnd - TheXStart, TheXstension); end; 3 : begin DeltaX := fixdiv (TheXStart - 63, TheXstension); DeltaY := fixdiv (TheXEnd, TheXstension); end; 4 : begin DeltaX := fixdiv (-63, TheXstension); DeltaY := fixdiv (TheXEnd - TheXStart, TheXstension); end; end; end; 3 : begin IconX := bsl (TheXEnd, 16); IconY := 63 * $10000; case TheStartSide of 1 : begin DeltaX := fixdiv (TheXStart - TheXEnd, TheXstension); DeltaY := fixdiv (-63, TheXstension); end; 2 : begin DeltaX := fixdiv (63 - TheXEnd, TheXstension); DeltaY := fixdiv (63 - TheXStart - 63, TheXstension); end; 3 : begin DeltaX := fixdiv (TheXStart - TheXEnd, TheXstension); DeltaY := 0; end; 4 : begin DeltaX := fixdiv (-TheXEnd, TheXstension); DeltaY := fixdiv (-TheXStart, TheXstension); end; end; end; end; if TheYEnd < 0 then begin TheXstension := TheXstension + TheYEnd; I := -TheYEnd - 1; while I <> 0 do begin I := I - 1; IconX := IconX + DeltaX; IconY := IconY + DeltaY; end; TheDstPtr := ptr (longint (OffScreenAddr) + TheXBetter); end else TheDstPtr := ptr (longint (OffScreenAddr) + TheXBetter + DstRowTop^ [TheYEnd]); if TheYStart > CurrentMaxY then TheXstension := TheXstension + CurrentMaxY - TheYStart; I := TheXstension; if I < 0 then exit (DrawTheRoof); TheSrcPtr := ptr (TheRoof^.CRoofPtr [Index]); case Dettaglio of 1 : begin while I <> 0 do begin I := I - 1; TheDstPtr^:= ptr (longint (TheSrcPtr) + band (bsr (IconY, 10), $FFFFFFC0) + bsr (IconX, 16))^; TheDstPtr := ptr (longint (TheDstPtr) + LocalDstRow); IconX := IconX + DeltaX; IconY := IconY + DeltaY; end; end; 2 : begin TheDstIPtr := integerptr (TheDstPtr); while I <> 0 do begin I := I - 1; Tmp := integerptr (longint (TheSrcPtr) + band (bsr (IconY, 10), $FFFFFFC0) + bsr (IconX, 16))^; TheDstIPtr^ := bor (bsr (Tmp, 8), band (Tmp, $FF00)); TheDstIPtr := integerptr (longint (TheDstIPtr) + LocalDstRow); IconX := IconX + DeltaX; IconY := IconY + DeltaY; end; end; end;end;procedure FillBlack;var I : integer; TheStart, TheEnd : integer; TheDstPtr : ptr; LocalDstRow : integer; begin TheStart := Min (TheYStart, TheYEnd); TheEnd := CurrentMaxY; if TheStart < 0 then begin TheDstPtr := ptr (longint (OffScreenAddr) + TheXBetter); TheStart := 0; end else TheDstPtr := ptr (longint (OffScreenAddr) + TheXBetter + DstRowTop^ [TheStart]); I := TheEnd - TheStart; LocalDstRow := DstRow; case Dettaglio of 1 : while I > 0 do begin TheDstPtr^ := TheKBlack; TheDstPtr := ptr (longint (TheDstPtr) + LocalDstRow); I := I - 1; end; 2 : while I > 0 do begin integerptr (TheDstPtr)^ := TheDKBlack; TheDstPtr := ptr (longint (TheDstPtr) + LocalDstRow); I := I - 1; end;{ 3 : while I > 0 do begin longintptr (TheDstPtr)^ := TheTKBlack; TheDstPtr := ptr (longint (TheDstPtr) + LocalDstRow); I := I - 1; end;} end; CurrentMaxY := Max (TheStart, 0);end;begin TheRoof := RoofList^ [TheRoofId]; GetSides; if (StartInclin = 2) then begin exit (DrawRoof); end; TheYStart := TheYStart + WindowYCenter; TheXBetter := TheX + WindowXCenter; TheYEnd := TheYEnd + WindowYCenter; if Index = 0 then begin FillBlack; if TheYStart < CurrentMaxY then CurrentMaxY := TheYStart; exit (DrawRoof); end; if (StartInclin in [1, 3]) and (TheYStart < CurrentMaxY) then begin case Dettaglio of 1 : DrawTheSide; 2 : DrawTheSide2 (TheRoof^.MiddleZ); otherwise; end; if TheYStart < CurrentMaxY then CurrentMaxY := TheYStart; end; CurrentLevel := TheRoof^.Level; if (TheYEnd >= CurrentMaxY) or (CurrentMaxY = 0) then exit (DrawRoof); if (TheYEnd < TheYStart) then begin DrawTheRoof; if TheYEnd < 0 then TheYEnd := 0; if TheYEnd < CurrentMaxY then CurrentMaxY := TheYEnd; end else if TheYStart < CurrentMaxY then CurrentMaxY := TheYStart;end;end.