Created
December 31, 2013 12:08
-
-
Save codemonkey-uk/8195836 to your computer and use it in GitHub Desktop.
Landcap is a Fractal Landscape Generator for DOS/VGA PC's, that I wrote when I was in college, circa 1993. It was originally released as shareware, and got 1 (one) £10 registration for my efforts. It was reviewed in PC-Format magazine in the same issue as Alta-Vista, which was/is a much better commercial application that does the same thing. At …
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Program MakeTrue3DFract; | |
uses dos,crt; | |
const | |
ver : string = '1'; | |
update : string = '1'; | |
Ysize : WORD = 512; | |
Xsize : WORD = 512; | |
ColourSet : Char = 'G'; | |
Type colorvalue = record rvalue,gvalue,bvalue : byte; end; | |
paltype = array [0..255] of colorvalue; | |
Scape = array[1..512] of byte; | |
River = array[0..64] of byte; | |
Zline = array[0..319] of Integer; | |
var | |
Zbuf : Array[0..199] of ^Zline; | |
Land : array[1..512] of ^Scape; | |
Bed : array[1..512] of ^River; | |
seed : longint; | |
Filename : String[8]; | |
Mode : Byte; | |
Jitter, | |
Water : Byte; | |
h_jitter, | |
SunY, | |
SunX, | |
SunZ : ShortInt; | |
eyeX, | |
eyeZ, | |
eyeY : Integer; | |
gourad, | |
Polyview, | |
City, | |
Interactive, | |
falloff : Boolean; | |
f : Real; | |
Angle, | |
HowmanyStars : Word; | |
Function ISVGA : boolean; | |
var | |
r : registers; | |
begin | |
R.AX:=$1a00; | |
Intr($10,r); | |
ISVGA:=(r.al=$1a); | |
end; | |
{$I-} | |
Function Exist(name : String) : boolean; | |
var | |
f : File; | |
begin | |
assign(f,name+'.raw'); | |
reset(f); | |
if IOresult=0 then exist:=TRUE | |
else exist:=FALSE; | |
end; | |
{$I+} | |
Procedure Defalts; | |
begin | |
randomize; | |
seed:=Random(65535); | |
f:=(Random*3)+0.5; | |
PolyView:=FALSE; | |
Gourad:=FALSE; | |
Filename:='LANDCAP'; | |
SunY:=1; | |
sunX:=1; | |
SunZ:=-1; | |
eyeZ:=20; | |
eyeY:=50; | |
eyeX:=256; | |
Water:=90; | |
Jitter:=2; | |
h_jitter:=jitter div 2; | |
Mode:=2; | |
City:=False; | |
Falloff:=False; | |
Interactive:=False; | |
If Falloff then | |
begin | |
Suny:=2; | |
SunX:=0; | |
SunZ:=1; | |
end; | |
HowmanyStars:=350; | |
angle:=0; | |
end; | |
{$I-} | |
Procedure save; | |
var | |
f : File; | |
key : Char; | |
result : word; | |
begin | |
assign(f,Filename+'.RAW'); | |
Repeat | |
Repeat | |
result:=2; | |
rewrite(f,1); | |
if IOresult<>0 then | |
begin | |
Sound(500); | |
Delay(500); | |
nosound; | |
key:=readkey; | |
result:=0; | |
end; | |
until result<>0; | |
blockwrite(f,mem[$A000:0],$FA00,result); | |
if (IOresult<>0) or (result<>$FA00) then | |
begin | |
Sound(500); | |
Delay(500); | |
nosound; | |
key:=readkey; | |
result:=0; | |
end; | |
until result<>0; | |
close(f); | |
end; | |
{$I+} | |
Procedure FindMem; | |
var | |
count : Integer; | |
kK : Integer; | |
begin | |
for count:=1 to Ysize do | |
begin | |
if maxavail<XSIZE then | |
begin | |
Writeln('You will need more base memory to use Landcap'); | |
Halt; | |
end; | |
New(Land[count]); | |
for kk:=1 to xsize do | |
Land[count]^[kk]:=0; | |
end; | |
for count:=1 to Ysize do | |
begin | |
if maxavail<XSIZE div 8 then | |
begin | |
Writeln('You will need more base memory to use Landcap'); | |
Halt; | |
end; | |
New(bed[count]); | |
for kk:=0 to xsize div 8 do | |
bed[count]^[kk]:=0; | |
end; | |
for count:=0 to 199 do | |
begin | |
if maxavail<640 then | |
begin | |
Writeln('You will need more base memory to use Landcap'); | |
Halt; | |
end; | |
new(Zbuf[count]); | |
end; | |
end; | |
Procedure ClearMem; | |
var | |
count : Integer; | |
Begin | |
for count:=1 to Ysize do | |
Dispose(Land[count]); | |
for count:=1 to Ysize do | |
Dispose(Bed[count]); | |
for count:=0 to 199 do | |
Dispose(Zbuf[count]); | |
end; | |
Procedure DrawScreen; | |
var | |
X,Y : Word; | |
num : Byte; | |
pal : Paltype; | |
regs: Registers; | |
begin | |
Inline($B8/$13/0/$CD/$10); | |
pal[0].rvalue:=0; | |
pal[0].gvalue:=0; | |
pal[0].bvalue:=0; | |
pal[1].rvalue:=0; | |
pal[1].gvalue:=0; | |
pal[1].bvalue:=45; | |
for num:=2 to 63 do | |
With pal[num] do | |
begin | |
Rvalue:=0; | |
Bvalue:=0; | |
Gvalue:=16; | |
end; | |
for num:=64 to 128 do | |
With pal[num] do | |
begin | |
Rvalue:=0; | |
Bvalue:=0; | |
Gvalue:=32; | |
end; | |
for num:=129 to 192 do | |
With pal[num] do | |
begin | |
Rvalue:=0; | |
Bvalue:=0; | |
Gvalue:=48; | |
end; | |
for num:=192 to 255 do | |
With pal[num] do | |
begin | |
Rvalue:=0; | |
Bvalue:=0; | |
Gvalue:=63; | |
end; | |
with regs do | |
begin | |
AX:=$1012; | |
BX:=0; | |
CX:=256; | |
ES:=seg(pal); | |
DX:=ofs(pal); | |
end; | |
intr($10,regs); | |
for x:= 8 to 111 do | |
begin | |
Mem[$A000:320*8+x]:=254; | |
Mem[$A000:320*111+x]:=254; | |
end; | |
for y:= 8 to 111 do | |
begin | |
Mem[$A000:320*y+8]:=254; | |
Mem[$A000:320*y+111]:=254; | |
end; | |
for y:=115 to 125 do | |
for x:=10 to 20 do | |
mem[$a000:320*y+x]:=1; | |
for y:=115 to 125 do | |
for x:=25 to 35 do | |
mem[$a000:320*y+x]:=63; | |
for y:=115 to 125 do | |
for x:=40 to 50 do | |
mem[$a000:320*y+x]:=128; | |
for y:=115 to 125 do | |
for x:=55 to 65 do | |
mem[$a000:320*y+x]:=192; | |
for y:=115 to 125 do | |
for x:=70 to 80 do | |
mem[$a000:320*y+x]:=255; | |
directvideo:=false; | |
gotoxy(2,17); | |
Write('1 6 1 1 2'); | |
gotoxy(2,18); | |
Write(' 4 2 9 5'); | |
gotoxy(2,19); | |
Write(' 9 2 5'); | |
directvideo:=false; | |
gotoXY(18,2); | |
Write('Seed Value :',seed:8); | |
gotoXY(18,3); | |
if not Interactive then | |
Write('Grain :',f:8:3) | |
else | |
Write('Interactive Method'); | |
gotoXY(18,4); | |
Write('Water Level :',water:8); | |
gotoXY(18,5); | |
if Gourad=True | |
then | |
Write('Full detail mode.') | |
else | |
if PolyView then | |
Write('Polygon mode. ') | |
else | |
Write('Quick view mode. '); | |
gotoxy(18,6); | |
Write('Eye Level :',eyey+Water:8); | |
gotoXY(18,7); | |
Write('Jitter :',Jitter:8); | |
gotoXY(18,8); | |
If Falloff then | |
Write('Night Time') | |
else | |
Write('Day Time'); | |
gotoXY(18,9); | |
Write('Light vectors'); | |
gotoXY(20,10); | |
Write('X :',SunX:8); | |
gotoXY(20,11); | |
Write('Y :',SunZ:8); | |
gotoXY(20,12); | |
Write('Elivation :',SunY:8); | |
gotoXY(18,13); | |
Write('Filename :',FileName); | |
gotoXY(18,14); | |
Write('Eye Pos X :',eyeX:8); | |
gotoXY(18,15); | |
Write('Eye Pos Y :',eyeZ:8); | |
gotoXY(18,16); | |
Write('Angle :',Angle:8); | |
gotoXY(18,17); | |
Write('Create Map'); | |
gotoXY(18,18); | |
Write('Render LandScape'); | |
gotoXY(18,19); | |
Write('Save Setup'); | |
gotoXY(18,20); | |
Write('Quit'); | |
gotoXY(2,22); | |
Write('L : Load Picture'); | |
gotoXY(2,23); | |
Write('P : Prepare data'); | |
end; | |
Procedure CreatePal; | |
var | |
pal : Paltype; | |
x : Byte; | |
regs : Registers; | |
begin | |
pal[0].rvalue:=0; | |
pal[0].gvalue:=0; | |
pal[0].bvalue:=0; | |
case upcase(ColourSet) of | |
'G' : Begin { Grass Landscape Pal } | |
for x:=1 to 32 do { Water ... } | |
with pal[x] do | |
begin | |
Rvalue:=0; | |
bvalue:=8+x; | |
Gvalue:=x div 2; | |
end; | |
for x:=33 to 42 do { smooth Blue to green } | |
with pal[x] do | |
begin | |
Rvalue:=(x-33) div 2; | |
Bvalue:=(42-x)*4; | |
Gvalue:=10+((42-x) div 2); | |
end; | |
for x:=43 to 105 do { Grass } | |
with pal[x] do | |
begin | |
Rvalue:=5; | |
bvalue:=0; | |
Gvalue:=(x-20) div 2; | |
end; | |
for x:=106 to 110 do { Smooth grass to greys } | |
with pal[x] do | |
begin | |
Rvalue:=5-(x-106); | |
bvalue:=0; | |
gvalue:=39-((x-106)*8); | |
end; | |
for x:=111 to 166 do { Greys } | |
with pal[x] do | |
begin | |
Gvalue:=x-100; | |
Bvalue:=x-100; | |
Rvalue:=x-100; | |
end; | |
for x:=167 to 255 do { Red filler } | |
with pal[x] do | |
begin | |
gvalue:=0; | |
rvalue:=60; | |
bvalue:=0; | |
end; | |
end; | |
end; | |
with regs do | |
begin | |
AX:=$1012; | |
BX:=0; | |
CX:=256; | |
ES:=seg(pal); | |
DX:=ofs(pal); | |
end; | |
intr($10,regs); | |
end; | |
Procedure DrawMap; | |
var | |
Rx,Ry : Word; | |
X,y : Word; | |
begin | |
for x:=1 to 100 do | |
for y:=1 to 100 do | |
begin | |
Rx:=x+9; | |
Ry:=y+9; | |
mem[$a000:WORD(320*ry+rx)]:=land[y*5]^[x*5]; | |
end; | |
rx:=WORD(EyeX); | |
ry:=WORD(EyeZ); | |
x:=WORD(10+((100*rx) div Xsize)); | |
y:=WORD(10+((100*ry) div Ysize)); | |
mem[$a000:WORD(320*y+x)]:=eyeY+Water; | |
end; | |
Procedure MakeScape; | |
var | |
num : Integer; | |
x, | |
y, | |
c : Integer; | |
Procedure adjust(xa,ya,x,y,xb,yb: Word); | |
var | |
d : integer; | |
v : real; | |
begin | |
if (not city) and (Land[y]^[x]<>0) then exit; | |
d:=Abs(xa-xb)+Abs(ya-yb); | |
if interactive then f:=(Land[ya]^[xa]+Land[yb]^[xb]) div 50; | |
v:=(Land[ya]^[xa]+Land[yb]^[xb])/2+(random-0.5)*d*F; | |
if v<1 then v:=1; | |
if v>=250 then v:=249-(v-250); | |
Land[y]^[x]:=Trunc(v); | |
end; | |
Procedure subDivide(x1,y1,x2,y2: Word); | |
var | |
x,y : Word; | |
v : integer; | |
rx,ry : Word; | |
begin | |
if KeyPressed then exit; | |
if (x2-x1<2) and (y2-y1<2) then exit; | |
x:=(x1+x2) div 2; | |
y:=(y1+y2) div 2; | |
adjust(x1,y1,x,y1,x2,y1); | |
adjust(x2,y1,x2,y,x2,y2); | |
adjust(x1,y2,x,y2,x2,y2); | |
adjust(x1,y1,x1,y,x1,y2); | |
if Land[y]^[x]=0 then | |
begin | |
v:=(Land[y1]^[x1]+Land[y1]^[x2]+Land[y2]^[x2]+Land[y2]^[x1]) div 4; | |
Land[y]^[x]:=v; | |
end; | |
subDivide(x1,y1,x,y); | |
subDivide(x,y,x2,y2); | |
subDivide(x1,y,x,y2); | |
subDivide(x,y1,x2,y); | |
Rx:=WORD(10+((100*x) div Xsize)); | |
Ry:=WORD(10+((100*y) div Ysize)); | |
mem[$a000:WORD(320*ry+rx)]:=land[y]^[x]; | |
end; | |
Begin | |
for num:=1 to Ysize do | |
for c:=1 to xsize do | |
Land[num]^[c]:=0; | |
Randseed:=seed; | |
Land[1]^[1]:=1+Random(230); | |
Land[Ysize]^[1]:=1+Random(230); | |
Land[Ysize]^[Xsize]:=1+Random(230); | |
Land[1]^[Xsize]:=1+Random(230); | |
subDivide(1,1,Xsize,Ysize); | |
end; | |
Procedure PrepData; | |
var | |
x,y : Word; | |
c : Integer; | |
begin | |
for x:=1 to Xsize do | |
for y:=1 to Ysize do | |
begin | |
c:=Land[y]^[x]; | |
dec(c,water); | |
if c<1 then Land[y]^[x]:=1 | |
else Land[y]^[x]:=c; | |
end; | |
end; | |
Procedure DoStars; | |
var | |
kount : Word; | |
begin | |
for kount:=0 to HowManyStars do | |
mem[$A000:random(35000)+3000]:=random(56)+110; | |
end; | |
Function FindPolyColor(x,z : Integer) : Byte; | |
var | |
Water : Boolean; | |
Xpos, Ypos ,Zpos : integer; | |
temp : Integer; | |
shaddow : Byte; | |
depth : LongInt; | |
D_on_X, | |
D_on_Z : Integer; | |
begin | |
water:=(land[z]^[x]=1); | |
water:=Water or odd((bed[z]^[(X-1) div 8] shr ((X-1) mod 8))); | |
Xpos:=x; | |
Ypos:=Land[z]^[x]; | |
zPos:=z; | |
If NOT Falloff Then | |
Begin | |
shaddow:=16; | |
repeat | |
Dec(Xpos,SunX); | |
dec(Zpos,SunZ); | |
inc(Ypos,SunY); | |
if (YPos<Land[Zpos]^[Xpos]) then dec(shaddow); | |
until (Xpos<2) or (Zpos<2) or (Xpos>Xsize-2) or (Zpos>Ysize-2) or (shaddow=2); | |
end | |
else | |
begin | |
if water | |
then shaddow:=15 | |
else shaddow:=4; | |
depth:=abs(z-eyeZ); | |
depth:=(depth*depth)+(abs(x-EyeX)*abs(x-EyeX)); | |
if depth<1 then depth:=1; | |
depth:=Trunc(sqrt(depth)); | |
if depth<100 then depth:=100; | |
end; | |
if Water then | |
begin | |
if Falloff then temp:=100*shaddow div depth | |
else temp:=Shaddow; | |
if (temp<1) then temp:=8 | |
else temp:=8+((temp*3) div 4); | |
if temp>32 then temp:=32; | |
findpolycolor:=temp; | |
end | |
else | |
begin | |
d_on_X:=land[z]^[x]-land[z]^[x+1]; | |
d_on_X:=d_on_X+land[z-1]^[x]-land[z-1]^[x+1]; | |
d_on_Z:=land[z]^[x]-land[z-1]^[x]; | |
d_on_Z:=d_on_Z+land[z]^[x+1]-land[z-1]^[x+1]; | |
d_on_X:=d_on_X*-sunX; | |
d_on_Z:=d_on_Z*SunZ; | |
temp:=(2*(d_on_X+d_on_Z)) div 3; | |
if temp<-18 then temp:=-18; | |
if temp>18 then temp:=18; | |
if falloff then | |
temp:=17+(100*(23+temp+((Shaddow div 5)*5)+random(jitter)-h_jitter) div depth) | |
else | |
temp:=40+temp+((Shaddow div 5)*5)+random(jitter)-h_jitter; | |
temp:=temp+28; | |
if temp<43 then temp:=43; | |
if temp>105 then temp:=105; | |
findpolycolor:=temp; | |
end; | |
end; | |
Function FindColor(x,z : Integer) : Byte; | |
var | |
Water : Boolean; | |
Xpos, Ypos ,Zpos : integer; | |
temp : Byte; | |
shaddow : Byte; | |
depth : LongInt; | |
begin | |
water:=(land[z]^[x]=1); | |
water:=Water or odd((bed[z]^[(X-1) div 8] shr ((X-1) mod 8))); | |
Xpos:=x; | |
Ypos:=Land[z]^[x]; | |
zPos:=z; | |
shaddow:=16; | |
if not falloff then | |
repeat | |
Dec(Xpos,SunX); | |
dec(Zpos,SunZ); | |
inc(Ypos,SunY); | |
if (YPos<Land[Zpos]^[Xpos]) then dec(shaddow); | |
until (Xpos<2) or (Zpos<2) or (Xpos>Xsize-2) or (Zpos>Ysize-2) or (shaddow=2); | |
if falloff then | |
begin | |
depth:=abs(z-eyeZ); | |
depth:=(depth*depth)+(abs(x-EyeX)*abs(x-EyeX)); | |
if depth<1 then depth:=1; | |
depth:=Trunc(sqrt(depth)); | |
if depth<100 then depth:=100; | |
end; | |
if Water then | |
begin | |
if Falloff then temp:=100*shaddow div depth | |
else temp:=Shaddow; | |
if (temp<4) then findcolor:=4 | |
else findcolor:=4+((temp*2) div 3); | |
end; | |
if Not water then | |
begin | |
Temp:=(land[z]^[x]+((shaddow) div 5)*5)+random(jitter); | |
if Falloff then findcolor:=46+((100*Temp div depth) div 4) | |
else findcolor:=46+(Temp div 4); | |
end; | |
end; | |
Procedure ShowscapePoly; | |
var | |
polyq : array [1..4,0..199] of Word; | |
miny, | |
maxy : word; | |
count, | |
countb : integer; | |
zVal, | |
xVal, | |
x1,x2,x3,x4, | |
y1,y2,y3,y4, | |
X,Y, | |
Z,C : LongInt; | |
col,col2, | |
col3,col4 : Byte; | |
k : Char; | |
Procedure ClearZbuff; | |
var | |
X,Y : Word; | |
begin | |
for x:=0 to 319 do | |
for y:=0 to 199 do | |
Zbuf[y]^[x]:=MaxInt; | |
end; | |
procedure SwapInt( var i1, i2: Longint ); | |
var dummy : integer; | |
begin | |
dummy := i2; | |
i2 := i1; | |
i1 := dummy; | |
end; | |
procedure GPolypoint(x,y : Longint;col : word); | |
begin | |
if x<0 then x:=0; | |
if x>319 then x:=319; | |
if y>199 then y:=199; | |
if y<0 then y:=0; | |
if x>polyq[2,y] then | |
begin | |
polyq[2,y]:=WORD(x); | |
polyq[4,y]:=col; | |
end; | |
if x<polyq[1,y] then | |
begin | |
polyq[1,y]:=WORD(x); | |
polyq[3,y]:=col; | |
end; | |
if y>maxy then maxy:=y; | |
if y<miny then miny:=y; | |
end; | |
procedure GLine( x1, y1, x2, y2 : LongInt;Firstcol,lastcol : LongInt); | |
var | |
biggest, | |
smallest, | |
d, dx, dy, | |
aincr, bincr, | |
xincr, yincr, | |
cincr,col, | |
dd,dc,c_jmp, | |
x, y : integer; | |
begin | |
if ( abs(x2-x1) < abs(y2-y1) ) then { X- or Y-axis overflow? } | |
begin { Check Y-axis } | |
if ( y1 > y2 ) then { y1 > y2? } | |
begin | |
SwapInt( x1, x2 ); { Yes --> Swap X1 with X2 } | |
SwapInt( y1, y2 ); { and Y1 with Y2 } | |
SwapInt( Firstcol,lastcol); | |
end; | |
if ( x2 > x1 ) then xincr := 1 { Set X-axis increment } | |
else xincr := -1; | |
dy := y2 - y1; | |
dx := abs( x2-x1 ); | |
d := 2 * dx - dy; | |
aincr := 2 * (dx - dy); | |
bincr := 2 * dx; | |
x := x1; | |
y := y1; | |
if Firstcol<Lastcol then | |
begin | |
biggest:=Lastcol; | |
smallest:=Firstcol; | |
dc:=abs(Lastcol-Firstcol); | |
cincr:=1 | |
end | |
else | |
begin | |
biggest:=Firstcol; | |
smallest:=Lastcol; | |
dc:=abs(Firstcol-Lastcol); | |
cincr:=-1; | |
end; | |
if dc=0 then dc:=1; | |
dd:=y2-y1; { Also changed as below} | |
if dd=0 then dd:=1; | |
if dd>dc then | |
begin | |
c_jmp:=dd div dc; | |
dc:=cincr; | |
end | |
else | |
begin | |
c_jmp:=1; | |
dc:=(dc div dd)*cincr; | |
end; | |
col:=Firstcol; | |
if firstcol=lastcol then dc:=0; | |
dd:=0; | |
Gpolypoint( x, y ,col); { Set first pixel } | |
for y:=y1+1 to y2 do { Execute line on Y-axes } | |
begin | |
inc(dd); | |
if dd=c_jmp then | |
begin | |
inc(col,dc); | |
if col>biggest then col:=biggest; | |
if col<smallest then col:=smallest; | |
dd:=0; | |
end; | |
if ( d >= 0 ) then | |
begin | |
inc( x, xincr ); | |
inc( d, aincr ); | |
end | |
else | |
inc( d, bincr ); | |
Gpolypoint( x, y,col); | |
end; | |
end | |
else { Check X-axes } | |
begin | |
if ( x1 > x2 ) then { x1 > x2? } | |
begin | |
SwapInt( x1, x2 ); { Yes --> Swap X1 with X2 } | |
SwapInt( y1, y2 ); { and Y1 with Y2 } | |
SwapInt( Firstcol,lastcol); | |
end; | |
if ( y2 > y1 ) then yincr := 1 { Set Y-axis increment } | |
else yincr := -1; | |
dx := x2 - x1; | |
dy := abs( y2-y1 ); | |
d := 2 * dy - dx; | |
aincr := 2 * (dy - dx); | |
bincr := 2 * dy; | |
x := x1; | |
y := y1; | |
if Firstcol<Lastcol then | |
begin | |
biggest:=Lastcol; | |
smallest:=firstcol; | |
dc:=abs(Lastcol-Firstcol); | |
cincr:=1 | |
end | |
else | |
begin | |
biggest:=firstcol; | |
smallest:=lastcol; | |
dc:=abs(Firstcol-Lastcol); | |
cincr:=-1; | |
end; | |
if dc=0 then dc:=1; | |
dd:=x2-x1; { Changed from dd:=x2-(x1+1); } | |
if dd=0 then dd:=1; | |
if dd>dc then | |
begin | |
c_jmp:=dd div dc; | |
dc:=cincr; | |
end | |
else | |
begin | |
c_jmp:=1; | |
dc:=(dc div dd)*cincr; | |
end; | |
if firstcol=lastcol then dc:=0; | |
col:=Firstcol; | |
dd:=0; | |
Gpolypoint( x, y ,col); { Set first pixel } | |
for x:=x1+1 to x2 do { Execute line on X-axes } | |
begin | |
inc(dd); | |
if dd=c_jmp then | |
begin | |
inc(col,dc); | |
if col>biggest then col:=biggest; | |
if col<smallest then col:=smallest; | |
dd:=0; | |
end; | |
if ( d >= 0 ) then | |
begin | |
inc( y, yincr ); | |
inc( d, aincr ); | |
end | |
else | |
inc( d, bincr ); | |
Gpolypoint( x, y,col ); | |
end; | |
end; | |
end; | |
procedure DispGPoly(z : Integer); | |
var | |
biggest, | |
smallest, | |
cx,cy : Integer; | |
col : byte; | |
aincr, | |
cincr, | |
dc,dx : Integer; | |
begin | |
for cy:=miny to maxy do | |
if polyq[1,cy]<>400 then | |
begin | |
if polyq[3,cy]<polyq[4,cy] then | |
begin | |
biggest:=polyq[4,cy]; | |
smallest:=polyq[3,cy]; | |
dc:=1+abs(polyq[4,cy]-polyq[3,cy]); | |
cincr:=1 | |
end | |
else | |
begin | |
biggest:=polyq[3,cy]; | |
smallest:=polyq[4,cy]; | |
dc:=abs(polyq[3,cy]-polyq[4,cy]); | |
cincr:=-1; | |
end; | |
dx:=polyq[2,cy]-(polyq[1,cy]+1); | |
if dx>dc then | |
begin | |
if dc<1 then begin | |
dc:=1; | |
cincr:=0; { <----- I changed this bit } | |
end; | |
aincr:=(dx div dc); | |
dc:=cincr; | |
end | |
else | |
begin | |
if dx=0 then dx:=1; | |
aincr:=1; | |
dc:=(dc div dx)*cincr; | |
end; | |
col:=polyq[3,cy]; | |
dx:=0; | |
if polyq[3,cy]=polyq[4,cy] then dc:=0; | |
for cx:=polyq[1,cy] to polyq[2,cy] do | |
begin | |
if (cx>0) and (cx<319) and (cy>-1) and (cy<199) then | |
if Zbuf[cy]^[cx]>Z then | |
begin | |
Zbuf[cy]^[cx]:=Z; | |
if col<1 then col:=1; | |
if col>166 then col:=1; | |
Mem[$a000:320*cy+cx]:=col; | |
end; | |
inc(dx); | |
if dx=aincr then | |
begin | |
inc(col,dc); | |
dx:=0; | |
if col>biggest then col:=biggest; | |
if col<smallest then col:=smallest; | |
inc(col,dc); | |
dx:=0; | |
end; | |
end; | |
end; | |
end; | |
procedure Polypoint(x,y : Longint); | |
begin | |
if x<0 then x:=0; | |
if x>319 then x:=319; | |
if y>199 then y:=199; | |
if y<0 then y:=0; | |
if x>polyq[2,y] then polyq[2,y]:=WORD(x); | |
if x<polyq[1,y] then polyq[1,y]:=WORD(x); | |
if y>maxy then maxy:=y; | |
if y<miny then miny:=y; | |
end; | |
procedure BLine( x1, y1, x2, y2 : Longint); | |
var d, dx, dy, | |
aincr, bincr, | |
xincr, yincr, | |
x, y : integer; | |
begin | |
if ( abs(x2-x1) < abs(y2-y1) ) then { X- or Y-axis overflow? } | |
begin { Check Y-axis } | |
if ( y1 > y2 ) then { y1 > y2? } | |
begin | |
SwapInt( x1, x2 ); { Yes --> Swap X1 with X2 } | |
SwapInt( y1, y2 ); { and Y1 with Y2 } | |
end; | |
if ( x2 > x1 ) then xincr := 1 { Set X-axis increment } | |
else xincr := -1; | |
dy := y2 - y1; | |
dx := abs( x2-x1 ); | |
d := 2 * dx - dy; | |
aincr := 2 * (dx - dy); | |
bincr := 2 * dx; | |
x := x1; | |
y := y1; | |
polypoint( x, y ); { Set first pixel } | |
for y:=y1+1 to y2 do { Execute line on Y-axes } | |
begin | |
if ( d >= 0 ) then | |
begin | |
inc( x, xincr ); | |
inc( d, aincr ); | |
end | |
else | |
inc( d, bincr ); | |
polypoint( x, y); | |
end; | |
end | |
else { Check X-axes } | |
begin | |
if ( x1 > x2 ) then { x1 > x2? } | |
begin | |
SwapInt( x1, x2 ); { Yes --> Swap X1 with X2 } | |
SwapInt( y1, y2 ); { and Y1 with Y2 } | |
end; | |
if ( y2 > y1 ) then yincr := 1 { Set Y-axis increment } | |
else yincr := -1; | |
dx := x2 - x1; | |
dy := abs( y2-y1 ); | |
d := 2 * dy - dx; | |
aincr := 2 * (dy - dx); | |
bincr := 2 * dy; | |
x := x1; | |
y := y1; | |
polypoint( x, y ); { Set first pixel } | |
for x:=x1+1 to x2 do { Execute line on X-axes } | |
begin | |
if ( d >= 0 ) then | |
begin | |
inc( y, yincr ); | |
inc( d, aincr ); | |
end | |
else | |
inc( d, bincr ); | |
polypoint( x, y ); | |
end; | |
end; | |
end; | |
procedure DispPoly(col : byte;Z : Integer); | |
var | |
cx,cy : Integer; | |
begin | |
for cy:=miny to maxy do | |
if polyq[1,cy]<>400 then | |
for cx:=polyq[1,cy] to polyq[2,cy] do | |
if (cx>0) and (cx<319) and (cy>-1) and (cy<199) then | |
if Zbuf[cy]^[cx]>Z | |
then | |
begin | |
Zbuf[cy]^[cx]:=Z; | |
Mem[$a000:320*cy+cx]:=col; | |
end; | |
end; | |
Procedure ClearPolyQ; | |
var | |
kount : Integer; | |
begin | |
maxy:=0; | |
miny:=400; | |
for kount:=0 to 199 do | |
begin | |
polyq[1,kount]:=400; | |
polyq[2,kount]:=0; | |
end; | |
end; | |
begin | |
ClearZBuff; | |
clearpolyq; | |
Inline($B8/$13/0/$CD/$10); | |
CreatePal; | |
DirectVideo:=False; | |
case sunx of | |
-2 : begin | |
x:=5; | |
y:=20; | |
end; | |
-1 : begin | |
x:=10; | |
y:=20; | |
end; | |
0 : begin | |
x:=15; | |
y:=15; | |
end; | |
1 : begin | |
x:=20; | |
y:=10; | |
end; | |
2 : begin | |
x:=20; | |
y:=5; | |
end; | |
end; | |
x2:=32; | |
y2:=32; | |
if sunz=-1 then | |
begin | |
x2:=x; | |
y2:=y; | |
x:=32; | |
y:=32; | |
end; | |
zval:=(ysize-2)-eyeZ; | |
y3:=100-(80*(0-eyeY) div Zval); | |
if Falloff then DoStars | |
else | |
begin | |
Gline(0,0,319,0,x,y); | |
Gline(319,0,319,y3,y,y2); | |
Gline(319,y3,0,y3,y2,x2); | |
Gline(0,y3,0,0,x2,x); | |
DispGPoly(800); | |
end; | |
for z:=Ysize-2 downto 2 do | |
begin | |
zval:=Z-eyeZ; | |
xval:=(2-eyeX)+1; | |
if zval>2 then | |
begin | |
x2:=160+LONGINT(310*xval div Zval); | |
x3:=160+LONGINT(310*xval div (Zval-1)); | |
y2:=100-(80*(land[z]^[3]-eyeY) div Zval); | |
y3:=100-(80*(land[z-1]^[3]-eyeY) div (Zval-1)); | |
end; | |
for x:=2 to Xsize-2 do | |
begin | |
zval:=Z-eyeZ; | |
xval:=(X-eyeX)+1; | |
If Keypressed then Exit; | |
x1:=x2; | |
y1:=y2; | |
if Zval>4 then | |
begin | |
x2:=160+LONGINT(310*xval div Zval); | |
y2:=100-(80*(land[z]^[x+1]-eyeY) div Zval); | |
x4:=x3; | |
y4:=y3; | |
x3:=160+LONGINT(310*xval div (Zval-1)); | |
y3:=100-(80*(land[z-1]^[x+1]-eyeY) div (Zval-1)); | |
if ((x1>0) and (x1<320)) or | |
((x2>0) and (x2<320)) or | |
((x3>0) and (x3<320)) or | |
((x4>0) and (x4<320)) or | |
((y1>0) and (y1<200)) or | |
((y2>0) and (y2<200)) or | |
((y3>0) and (y3<200)) or | |
((y4>0) and (y4<200)) then | |
begin | |
ClearPolyQ; | |
col:=FindPolyColor(x,z); | |
If NOT GOURAD then | |
begin | |
Bline(x1,y1,x2,y2); | |
Bline(x2,y2,x3,y3); | |
Bline(x3,y3,x4,y4); | |
Bline(x4,y4,x1,y1); | |
DispPoly (col,Integer(Zval)); | |
end | |
else | |
begin | |
col2:=FindPolycolor(x+1,z); | |
col3:=FindPolycolor(x+1,z-1); | |
col4:=FindPolycolor(x,z-1); | |
Gline(x1,y1,x2,y2,col,col2); | |
Gline(x2,y2,x3,y3,col2,col3); | |
Gline(x3,y3,x4,y4,col3,col4); | |
Gline(x4,y4,x1,y1,col4,col); | |
DispGPoly(Integer(Zval)) ; | |
end; | |
if Zval>MaxInt then Zval:=MaxInt; | |
if Zval<-MaxInt then Zval:=-MaxInt; | |
DispPoly (col,Integer(Zval)); | |
end; | |
end; | |
end; | |
end; | |
save; | |
end; | |
Procedure ShowScape; | |
Var | |
mul, | |
count, | |
Lx, | |
Fx, | |
Fy, | |
Ly, | |
Rx, | |
Ry, | |
X,Y, | |
Z,C : LongInt; | |
col : Byte; | |
k : Char; | |
MinScreenx, | |
MaxScreenX : Integer; | |
begin | |
Inline($B8/$13/0/$CD/$10); | |
CreatePal; | |
DirectVideo:=False; | |
GotoXY(1,1); | |
if Falloff then DoStars | |
else | |
for z:=1 to 18 do | |
fillchar(mem[$a000:(z*10)*320],320*10,z+5); | |
mul:=round(320/(Xsize/(Ysize+eyeZ))); | |
MinScreenX:=2; | |
MaxScreenX:=Xsize-2; | |
for z:=Ysize downto EyeZ+2 do | |
begin | |
for x:=MinScreenX to MaxScreenX do | |
begin | |
If Keypressed then Exit; | |
Lx:=INTEGER(160+(Mul*(x-eyeX) div (z-eyeZ))); | |
Fx:=INTEGER(160+(Mul*((x-eyeX)-1) div (z-eyeZ))); | |
Fy:=100-(80*((land[z]^[x] div mode)-eyeY) div (z-eyeZ)); | |
Ly:=100-(80*(land[z]^[x]-eyeY) div (z-eyeZ)); | |
col:=FindColor(x,z); | |
for ry:=Ly to Fy do | |
for Rx:=Fx to Lx do | |
if (rx>-1) and (rx<320) and (ry>-1) and (ry<200) then | |
mem[$a000:320*ry+rx]:=col | |
else | |
begin | |
if (rx<0) and (x>MinscreenX) then minscreenX:=x; | |
if (rx>319) and (x<MaxscreenX) then maxscreenX:=x; | |
end; | |
end; | |
end; | |
save; | |
end; | |
Procedure load; | |
var | |
f : File; | |
key : Char; | |
begin | |
{$I-} | |
assign(f,Filename+'.RAW'); | |
reset(f,1); | |
If IOResult=0 then | |
begin | |
blockread(f,mem[$A000:0],$FA00); | |
close(f); | |
createPal; | |
key:=readkey; | |
end | |
else | |
begin | |
sound(500); | |
delay(500); | |
nosound; | |
end; | |
Drawscreen; | |
DrawMap; | |
end; | |
Procedure Menu; | |
var | |
ex,ey, | |
x,y : Longint; | |
Line : Byte; | |
Quit : Boolean; | |
key : char; | |
golly, | |
Click : Boolean; | |
NegClick : Boolean; | |
Procedure VectorMenu; | |
begin | |
line:=10; | |
Repeat | |
click:=False; | |
NegClick:=False; | |
gotoXY(19,line); | |
Write('�'); | |
if keypressed then | |
begin | |
GotoXY(19,line); | |
Write(' '); | |
key:=readkey; | |
if key=#0 then | |
begin | |
key:=readkey; | |
case key of | |
#72 : Dec(Line); | |
#77 : Click:=True; | |
#75 : NegClick:=True; | |
#80 : Inc(line); | |
end; | |
end | |
else | |
case key of | |
'+' : Click:=True; | |
'-' : NegClick:=True; | |
' ' : NegClick:=True; | |
#13 : Click:=True; | |
end; | |
if Click=True then | |
case Line of | |
10 : inc(sunX); | |
11 : inc(SunZ); | |
12 : inc(SunY); | |
end | |
else | |
if NegClick=True then | |
case Line of | |
10 : dec(sunX); | |
11 : dec(SunZ); | |
12 : dec(SunY); | |
end; | |
if SunX<-2 then SunX:=2; | |
if SunX>2 then SunX:=-2; | |
if SunY<1 then SunY:=3; | |
if SunY>3 then SunY:=1; | |
if SunZ<-2 then SunZ:=2; | |
if SunZ>2 then SunZ:=-2; | |
if Line=9 then line:=12; | |
if Line=13 then line:=10; | |
gotoXY(20,10); | |
Write('X :',SunX:8); | |
gotoXY(20,11); | |
Write('Y :',SunZ:8); | |
gotoXY(20,12); | |
Write('Elivation :',SunY:8); | |
end; | |
Until key=#27 | |
end; | |
begin | |
Golly:=False; | |
Line:=2; | |
Repeat | |
Click:=False; | |
NegClick:=False; | |
key:=#255; | |
gotoXY(17,Line); | |
Write('�'); | |
if keypressed then | |
begin | |
GotoXY(17,line); | |
Write(' '); | |
key:=readkey; | |
if key=#0 then | |
begin | |
key:=readkey; | |
case key of | |
#72 : Dec(Line); | |
#77 : Click:=True; | |
#75 : NegClick:=True; | |
#80 : Inc(line); | |
end; | |
end | |
else | |
Case upcase(key) of | |
'L' : Load; | |
'P' : Begin | |
PrepData; | |
DrawMap; | |
end; | |
#13 : Click:=True; | |
#32 : Click:=True; | |
#27 : If Line<>20 then | |
Line:=20 | |
else | |
Click:=True; | |
end; | |
end; | |
if Line=1 then line:=20; | |
if Line=21 then line:=2; | |
if NegClick then | |
case line of | |
4 : Begin | |
Dec(Water,10); | |
gotoXY(18,4); | |
Write('Water Level :',water:8); | |
end; | |
6 : Begin | |
if eyeY>5 then | |
dec(EyeY); | |
gotoxy(18,6); | |
Write('Eye Level :',eyey+Water:8); | |
end; | |
7 : Begin | |
if jitter>0 then | |
dec(Jitter); | |
gotoXY(18,7); | |
Write('Jitter :',Jitter:8); | |
end; | |
14 : Begin | |
dec(eyeX,5); | |
if EyeX<5 then EyeX:=Xsize-5; | |
drawmap; | |
gotoXY(18,14); | |
Write('Eye Pos X :',eyeX:8); | |
end; | |
15 : Begin | |
dec(eyeZ,5); | |
if EyeZ<5 then EyeZ:=YSize-5; | |
drawmap; | |
gotoXY(18,15); | |
Write('Eye Pos Y :',eyeZ:8); | |
end; | |
end; | |
if Click then | |
case line of | |
2 : begin | |
seed:=Random(65535); | |
gotoXY(18,2); | |
Write('Seed Value :',seed:8); | |
end; | |
3 : Begin | |
f:=(Random*3)+0.5; | |
Interactive:=Not Interactive; | |
gotoXY(18,3); | |
if not Interactive then | |
Write('Grain :',f:8:3) | |
else | |
Write('Interactive Method '); | |
end; | |
4 : begin | |
Inc(Water,10); | |
gotoXY(18,4); | |
Write('Water Level :',water:8); | |
end; | |
5 : Begin | |
if Gourad=True then | |
begin | |
PolyView:=False; | |
Gourad:=False; | |
end | |
else | |
If PolyView=True then | |
Gourad:=True | |
else | |
PolyView:=True; | |
gotoXY(18,5); | |
if Gourad=True | |
then | |
Write('Full detail mode.') | |
else | |
if PolyView then | |
Write('Polygon mode. ') | |
else | |
Write('Quick view mode. '); | |
end; | |
6 : Begin | |
if eyeY<300 then | |
inc(EyeY); | |
gotoxy(18,6); | |
Write('Eye Level :',eyey+Water:8); | |
end; | |
7 : Begin | |
if jitter<15 then | |
inc(Jitter); | |
gotoXY(18,7); | |
Write('Jitter :',Jitter:8); | |
end; | |
8 : Begin | |
Falloff:=NOT Falloff; | |
If Falloff then | |
begin | |
Suny:=2; | |
SunX:=0; | |
SunZ:=1; | |
end; | |
gotoXY(18,8); | |
If Falloff then | |
Write('Night Time') | |
else | |
Write('Day Time '); | |
gotoXY(18,9); | |
Write('Light vectors'); | |
gotoXY(20,10); | |
Write('X :',SunX:8); | |
gotoXY(20,11); | |
Write('Y :',SunZ:8); | |
gotoXY(20,12); | |
Write('Elivation :',SunY:8); | |
end; | |
9,10,11,12 : if not falloff then VectorMenu; | |
13 : Begin | |
gotoXY(18,13); | |
Write(' '); | |
gotoXY(18,13); | |
Write('Filename :'); | |
Readln(Filename); | |
if NOT Exist(Filename) | |
then save | |
else load; | |
end; | |
14 : Begin | |
inc(eyeX,5); | |
if EyeX>(Xsize-5) then EyeX:=5; | |
drawmap; | |
gotoXY(18,14); | |
Write('Eye Pos X :',eyeX:8); | |
end; | |
15 : Begin | |
inc(eyeZ,5); | |
if eyez>500 then eyez:=5; | |
drawmap; | |
gotoXY(18,15); | |
Write('Eye Pos Y :',eyeZ:8); | |
end; | |
17 : Begin | |
MakeScape; | |
DrawMap; | |
Golly:=True; | |
end; | |
18 : If Golly Then | |
begin | |
case PolyView of | |
TRUE : ShowScapePoly; | |
FALSE : ShowScape; | |
end; | |
DrawScreen; | |
DrawMap; | |
While KeyPressed do | |
key:=ReadKey; | |
key:=#255; | |
end; | |
20 : Quit:=True; | |
END; | |
until Quit=True; | |
end; | |
begin | |
Writeln('Landcap v',ver,'.',update,' (c) T.Frogley 1993'); | |
Writeln('Loading...'); | |
If ISVGA then | |
begin | |
FindMem; | |
Defalts; | |
DrawScreen; | |
Menu; | |
ClearMem; | |
Textmode(lastmode); | |
Writeln('Thanks for using LANDCAP v',ver,'.',update,' - Fractal landscape generator.'); | |
Writeln(' T.Frogley (c) 1993'); | |
Writeln('You may freely distribute this program on condition that you do not change it.'); | |
Writeln(#10#13'If you enjoyed using it please consider sending me �10 as it has taken'); | |
Writeln('many months to complete, and is all my own work. '); | |
Writeln(' Thad,'); | |
Writeln(' 38 Bentfield Causeway'); | |
Writeln(' Stansted'); | |
Writeln(' Essex, CM24 8HU'); | |
Writeln(#10#13'In return for sending me �10 I will send you an extended copy of LANDCAP'); | |
Writeln('Which will include:'); | |
Writeln(' Set up save option,'); | |
Writeln(' Animation module,'); | |
Writeln(' Controled GRAIN and SEED adustment,'); | |
Writeln(' PCX File save,'); | |
Writeln(' Cloud backdrops,'); | |
Writeln(' Rock, Ice ,Mars palettes & palette editor'); | |
Writeln(' I also hope to have natural rivers and full rotation working by March ''94'); | |
end | |
else | |
Writeln('Sorry, you will need a VGA compatable card and monitor to run Landcap.'); | |
end. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment