diff --git a/BASIC3D.PAS b/BASIC3D.PAS new file mode 100644 index 0000000..6963985 --- /dev/null +++ b/BASIC3D.PAS @@ -0,0 +1,178 @@ +unit basic3d; + +INTERFACE +uses colour,twindraw; +var +{size of the colour ranges and the 'specular' size value} +rangesize:word; +specularrangesize:byte; +Const +nodeselectedcolour=yellow; +nodecolour=white; +linecolour=lightblue; +selectedlinecolour=yellow; + +{////GLOBAL EFFECTS AND LIGHTING CONSTANTS/////////////} +maxranges=8; +{red, green, blue, yellow, magenta, cyan, brown, grey} +rangebasecolours:array[0..maxranges-1]of rgbtype= +( (r:31;g:0;b:0),(r:0;g:31;b:0),(r:0;g:0;b:31),(r:31;g:31;b:0),(r:31;g:0;b:31), + (r:0;g:31;b:31),(r:31;g:16;b:0),(r:31;g:25;b:25) ); +{ + rangebasecolours:array[0..maxranges-1]of rgbtype= +( (r:20;g:20;b:20),(r:0;g:4;b:20),(r:10;g:10;b:10),(r:31;g:31;b:0),(r:31;g:0;b:31), + (r:31;g:31;b:31),(r:31;g:16;b:0),(r:25;g:25;b:25) ); + } + +highlight=10; +lightcol:rgbtype=(r:64;g:64;b:64); +ambient:rgbtype=(r:2;g:2;b:4); +fog=35; +spec=1; {precentage representing highlight value} +specoffset=1; +lightshift=16; {16 bits for fractional part of normal vector} + +{////WORLD BOUNDS//////////////////////////////////////} +maxbound=32000; +minbound=-32000; +ClipNearZ=1; +ClipFarZ=32000; + +{////MAXIMUM POINTS WHEN USING ARRAYS//////////////////} +ZaverageBufSize=3000; +Maximumpoints=2300; +Maximumlines=3000; +Maximumpolys=1400; +Maxtextures=100; +Maxstars=1000; +MaximumLights=2; +Maxlights:byte=0; + +{////ORIENTATION CONSTANTS/////////////////////////////} +ZY_view=0; XZ_view=1; XY_view=2; view_3d=3; +Xaxis=0;Yaxis=1;Zaxis=2;Allaxis=3; + +{////SELECT MODES//////////////////////////////////////} +SMall_nodes=0; +SMselected_nodes=1; +SMobjects=2; + +{////WORLD ATTRIBUTES//////////////////////////////////} +WAstars=1; +WAground=2; + +{////LIGHT TYPES///////////////////////////////////////} +LTdirectional=1; +LTpoint=2; +LTconical=3; + +{////OBJECT TYPES//////////////////////////////////////} +OTmesh=1; {all types can become a mesh} +OTsquare=2; +OTcube=3; +OTsphere=4; +OTcylinder=5; +OTcone=6; +OTgrid=7; +OTsinegrid=8; +OTtext=9; + +{////OBJECT ATTRIBUTES/////////////////////////////////} +OAvisible=1; +OAselected=2; +OAMatrixDeformed=4; {object has been deformed but the change can be represented by a matrix} +OAselectable=8; +OAcamerafix=16; {used for fixed starfields,sky's etc} +OAmoving=32; {object's matrix to be updated by movement vector} + + +{////NODE ATTRIBUTES///////////////////////////////////} +NAvisible=1; +NAselected=2; +NAreserved=128; {used internally, do not set directly} + +{////DELETE MODES///////////////////////////////} +DMnodes=1; +DMjoins=2; +DMpolys=4; +DMall=7; + +{////COPY MODES/////////////////////////////////} +CMjoins=1; +CMpolys=2; +CMall=3; + +{////EXTRUDE MODE///////////////////////////////} +XMabsolute=1; {simply extrudes to destination} +XMtopoint=2; {destination is a node} +XMbyref=3; {destination is a reference list} +XMcopy=4; {destination is ignored, a new polygon is created using CTM} +XMbevel=5; {edges are beveled} +XMmodemask=7; {masks for modes} +XMflipnormals=8; {special bit, if set then normals are flipped on creation} + +{////POLYGON CREATION MODES/////////////////////} +PClines=1; +PCpolys=2; +PCall=3;{mask for the above two} +PCchecklines=4; {check lines to see if they exist already} +PCcheckpolys=8; {check polys to see if they exist already} +PCclockWise=16; {Create the polygon in a clockwise order} + +{////POLYGON SETTING VARIABLES/////////////////////////} +PAmodeFALSE=0; +PAmodeTRUE=1; +PAmodeABS=2; + +{////POLYGON ATTRIBUTE FLAGS///////////////////////////} +PAclockwise=64; {phase this out -should be on creation} +PAsetmask3d=not PAclockwise; +PAallselected=512; +PAsomeselected=1024; +PAselected=PAallselected + PAsomeselected; + +PAvisible=128; +PAabsolute=32; +PAconnected=16; +PAoutLined=8; +PAsmooth=2; +PAdoubleSided=1; + + + +{////FILLER MODES//////////////////////////////////////} +CMDdots =130; +CMDlines =131; +CMDhlines =132; +CMDCpolygons =133; +CMDLsource =135; +CMDgouraud =136; +{1 unit = 0.7 degrees} +PersStart=500; +Pers=PersStart; + +{////ASSIGNED GLOBAL VARIABLES/////////////////////////} +WAttrib:byte=0; {global attribute byte} +nodepatt:array[0..4] of byte=(124,68,68,68,124); {pattern for nodes} +Scale:real=0.3; {scaling value} + +type + +Vectorstruct=record + x,y,z:real; +end; + +polygonstruct=record + numsides:byte; + p:array[0..3] of word; + colour:byte; + attrib:byte; +end; + +JoinStruct=record + f,t:word +end; + +IMPLEMENTATION + +end. \ No newline at end of file diff --git a/BITMAP16.PAS b/BITMAP16.PAS new file mode 100644 index 0000000..1b1c528 --- /dev/null +++ b/BITMAP16.PAS @@ -0,0 +1,188 @@ +unit bitmap16; +{routines to write to a plainiar bitmap} +INTERFACE +uses chardef,ttypes,gbasics,tmaths; + +Procedure ClearDevice; +procedure putpixel(x1,y1:integer); +function getpixel(x1,y1:integer):byte; +Procedure Qsetxy(x1,y1:integer); +Procedure Qwrite(count:word); +function Qget:byte; + +IMPLEMENTATION + +procedure putpixel(x1,y1:integer);assembler; + + + + asm + mov cx,x1 ;mov bx,y1 + cmp cx,BC.viewport.x1 ;jl @fin {clipping..} + cmp bx,BC.viewport.y1 ;jl @fin + cmp cx,BC.viewport.x2 ;jg @fin + cmp bx,BC.viewport.y2 ;jg @fin + + {load start offset from table} + shl bx,1 + mov di,word ptr BC.startoffsets+bx + + {x-offset} + mov bl,cl + xor bh,bh + and bl,7 + shr cx,3 + add di,cx + + mov dl,byte ptr singlepixelbitmasks+bx + mov bx,di + + {create masks} + + mov dh,dl + not dh + mov ah,t_col + + + @plane1: + les di,dword ptr BC.scrptrs + mov al,1 + + + test al,ah + jz @nowrite1 + or es:[di+BX],dl + jmp @plane2 + @nowrite1: + and es:[di+BX],dh + @plane2: + + shl al,1 {move bitmask along} + + les di,dword ptr BC.scrptrs+4 + + test al,ah + jz @nowrite2 + or es:[di+BX],dl + jmp @plane3 + @nowrite2: + and es:[di+BX],dh + @plane3: + + shl al,1 {move bitmask along} + + les di,dword ptr BC.scrptrs+8 + + test al,ah + jz @nowrite3 + or es:[di+BX],dl + jmp @plane4 + @nowrite3: + and es:[di+BX],dh + @plane4: + + shl al,1 {move bitmask along} + + les di,dword ptr BC.scrptrs+12 + test al,ah + jz @nowrite4 + or es:[di+BX],dl + jmp @fin + @nowrite4: + and es:[di+BX],dh + @fin: + + + +end; + +function getpixel(x1,y1:integer):byte; +var adrs:byteptr; + readbit,planelop,currbyte:byte; + picoffset:word; +begin + currbyte:=0; + if (X1>=BC.viewport.x1)and(Y1>=BC.viewport.y1)and(X1<=BC.viewport.x2)and(Y1<=BC.viewport.y2) then begin + + readbit:=$80 shr (x1 and 7); + picoffset:=(y1 * BC.offsw)+(x1 shr 3); + for planelop:=0 to BC.bitplanes-1 do begin + adrs:=pointer(BC.scrptrs[planelop]); + inc(adrs,picoffset); + if readbit and adrs^<>0 then + inc(currbyte,1 shl planelop); + end; + end; + getpixel:=currbyte; +end; + +{These are generic routines for writing contingous +block fast to bitmaps. Good for loading in from files} +Procedure QSetXY(x1,y1:integer); +begin + BC.qoffset:=y1*BC.offsw+(x1 shr 3); + BC.qbitoffset:=x1 and 7; + +end; + +function Qget:byte; +var + colour:byte; + var planeloop:byte; + qadrs:byteptr; +begin + + colour:=0; + for planeloop:=0 to BC.bitplanes-1 do begin + qadrs:=pointer(BC.scrptrs[planeloop]); + inc(qadrs,BC.qoffset); + if qadrs^ and BC.qbitoffset <> 0 then + inc(colour,1 shl planeloop); + end; + asm + shr bc.qbitoffset,1 + adc word ptr bc.qoffset,0 + end; + qget:=colour; +end; + +Procedure Qwrite(count:word); +var lop,oldqoff:word; + planelop,oldqmask:byte; + oldxpos:integer; + adrs:^byte; +begin + {oldqoff:=q + oldxpos:=BC.qxpos; + for planelop:=0 to BC.bitplanes-1 do begin + qoff:=oldqoff; + qmask:=oldqmask; + BC.qxpos:=oldxpos; + + adrs:=pointer(pic[planelop]); + inc(adrs,Qoff); + for lop:=1 to count do begin + if t_col and (1 shl planelop)<>0 then + adrs^:=adrs^ or Qmask + else + adrs^:=adrs^ and not Qmask; + begin + qmask:=qmask shr 1; + if Qmask=0 then begin + inc(adrs); + inc(Qoff); + Qmask:=128; + end; + end; + end; + end;} +end; + +Procedure ClearDevice; +var bitlop:byte; +begin + for bitlop:=0 to BC.bitplanes-1 do + fillchar(BC.scrptrs[bitlop]^,BC.pagesize,0); +end; + +end. diff --git a/BITMAP25.PAS b/BITMAP25.PAS new file mode 100644 index 0000000..20f8ba7 --- /dev/null +++ b/BITMAP25.PAS @@ -0,0 +1,1854 @@ +Unit BITMAP25; +{$R-} +INTERFACE +uses chardef,ttypes,gbasics,tmaths; +const +{VGA register locations} +MISC_ADDR=$3C2; MISC_READ_ADDR=$3CC; +ATTR_ADDR=$3c0; ATTR_DATA_ADDR=$3c1; +SEQU_ADDR=$3c4; SEQU_DATA_ADDR=$3c5; +CRTC_ADDR=$3D4; CRTC_DATA_ADDR=$3d5; +GRPH_ADDR=$3CE; GRPH_DATA_ADDR=$3CF; +STATUS_ADDR=$3da; + +function set_mode(mode:byte):boolean; +Procedure bar(x1,y,x2,y2:integer); +Procedure GTriangle(xa,ya,xb,yb,xc,yc,ia,ib,ic:integer); +Procedure Triangle(xa,ya,xb,yb,xc,yc:integer); +Procedure Line(x1,y1,x2,y2:integer); +Procedure Hline(x1,x2,y:Integer); +Procedure Vline(x,y1,y2:Integer); +Procedure putpixel(x1,y1:Integer); +Function getpixel(x1,y1:Integer):byte; +Procedure outtextxy(x1,y1:integer;txt:string); +Procedure outtextxy_length(x1,y1:integer;txt:pchar;length:byte); +Procedure Drawbytes(x1,y1:Integer;pic:bytearray;nbytes:byte); +Procedure Drawbytesxy(x1,y1:Integer;pic:bytearray;xbytes,ybytes:byte); +Procedure Screencopy(x1,y1,x2,y2,xd,yd:integer;page1,page2:byte); +procedure putbitmap(x1,y1:integer;bitmap:bitmaptypeptr); +Procedure putbitmapmask(x1,y1:integer;mask:byte;bitmap:bitmaptypeptr); +Procedure putbitmaptintshade(x1,y1:integer;rangestart,rangesize:byte;bitmap:bitmaptypeptr); +Procedure putbitmaptintshademask(x1,y1:integer;rangestart,rangesize:byte;bitmap:bitmaptypeptr); +Procedure putbitmapshade(x1,y1:integer;rangesize:byte;bitmap:bitmaptypeptr); +procedure scanedge(x1,y1,x2,y2:integer;offset:byte); +function getbitmap(x1,y1,x2,y2:integer):bitmaptypeptr; +procedure drawhlines(ytop,ybottom:integer); +procedure ConvexPolygon(points:pointtypearray;numpoints:integer); +Procedure cleardevice; +procedure savescreenregs; +procedure restorescreenregs; + +{quick generic interface to screen -good for file loading} +Procedure QSetXY(x,y:integer); +Procedure Qwrite(count:word); +function Qget:byte; + +type dword=longint; + +IMPLEMENTATION +procedure savescreenregs; +begin +end; +procedure restorescreenregs; +begin +end; + +function set_mode(mode:byte):boolean; +begin + {set up the video mode} + if mode=$13 then asm + xor ax,ax + mov al,mode {mode} + int 10h {call screen interrupt} + end else asm + mov ax,4F02h + mov bh,64 + mov bl,mode + int 10h + + mov AX,800h + int 31h + end; + set_mode:=true; +end; + + +(*function set_mode(mode:byte):boolean; +var installed:boolean; +begin + installed:=true; + with BC.size do + case mode of + vga320x200x256:begin x:=320;y:=200;end; + else installed:=false; + end; + if installed then begin + {set up the video mode} + asm + mov al,mode; {mode} + mov ah,0; {function 0} + int 10h {call screen interrupt} + end; + ColourDepth:=256; + BC.offsw:=BC.size.x; + end; + set_mode:=installed; +end;*) + +Procedure cleardevice;assembler; +Asm + les di,BC.scrptr + mov al,t_fillcol + mov ah,t_fillcol + mov cx,word ptr BC.Pagesize + shr cx,1 + cld + rep stosw +End; + +const +base:byte=0; + + + +var +HlineList:array[0..319] of hlinetype; +deltax,px:longint; + +procedure scanedge(x1,y1,x2,y2:integer;offset:byte); +var + +chval:integerptr; +const +multby=1 shl 16; +hlinesize=sizeof(hlinetype); +begin + {slow due to 16 bit stuff; needs multiplies, 32bit shift would be good} + px:=x1 * multby; + dec(y2); + if y2<=y1 then exit; + + deltax:=((x2 * multby)-px) div (y2-y1); + + + chval:=@HLineList[y1]; + inc(chval,offset); + asm + {create counter} + mov cx,y2 + sub cx,y1 + + {setup gradient fixed point longword in bx/dx} + mov bx,word ptr deltax + mov dx,word ptr deltax+2 + + {put current fixed point x position in si/ax} + mov si,word ptr px + mov ax,word ptr px+2 + les di,chval {points to current hline value} + mov es:[di],ax {grab the integer bit and shove into memory} + @yloop: + + add di,hlinesize {needs to move along by sizeof hlinetype bytes} + add si,bx {add fixed point gradiant longword } + adc ax,dx + mov es:[di],ax {grab the integer bit and shove into memory} + dec cx {next itteration} + + jnz @yloop + end; + + +end; + +procedure drawhlines(ytop,ybottom:integer); +var +chline:^hlinetype; +ylop:integer; +begin + chline:=@Hlinelist[ytop]; + for ylop:=ytop to ybottom-1 do begin + hline(chline^.x1,chline^.x2,ylop); + inc(chline); + end; + +end; + + +procedure ConvexPolygon(points:pointtypearray;numpoints:integer); + +var top_y,bottom_y,top_idx,l_idx_start,r_idx_start:integer; + i:integer; + dir:shortint; + cpoint,nxtpoint:pointtypeptr; + +ignorefirst:boolean; {if the top left and right values have the same x position, ignore} + +function IDX_FWRD(var index:integer):integer; +begin + IDX_FWRD:=(index+1) mod numpoints; +end; + +function IDX_BAKWRD(var index:integer):integer; +begin + IDX_BAKWRD:=(index-1+numpoints) mod numpoints; +end; + +function IDX_MOVE(var index:integer;dir:byte):integer; +begin + if (dir>0) then + IDX_MOVE:=(index-1+numpoints) mod numpoints + else + IDX_MOVE:=(index-1+numpoints) mod numpoints; +end; + +begin + if numpoints<3 then exit; + top_y:=32767; + bottom_y:=-32767; + cpoint:=pointtypeptr(points); + + + {determine the top and bottom of the list} + for i:=0 to numpoints-1 do begin + if cpoint^.ybottom_y then bottom_y:=cpoint^.y; + inc(cpoint); + end; + if top_y=bottom_y then exit; + {figure out starting positions for left and right sides of the list} + i:=top_idx; + cpoint:=@points^[top_idx]; + + while points^[i].x=cpoint^.x do begin + i:=idx_bakwrd(i); + end; + i:=idx_fwrd(i); + l_idx_start:=i; + + i:=top_idx; + while points^[i].x=cpoint^.x do begin + i:=idx_fwrd(i); + end; + i:=idx_bakwrd(i); + + r_idx_start:=i; + i:=idx_fwrd(i); + if points^[i].xbottom_y) do begin + cpoint:=@pointtypearray(points)^[i]; + i:=idx_fwrd(i); + nxtpoint:=@pointtypearray(points)^[i]; + scanedge(cpoint^.x,cpoint^.y,nxtpoint^.x,nxtpoint^.y,1); + end; + + i:=L_idx_start; + cpoint:=@pointtypearray(points)^[L_idx_start]; + nxtpoint:=cpoint; + while (nxtpoint^.y<>bottom_y) do begin + cpoint:=@pointtypearray(points)^[i]; + i:=idx_bakwrd(i); + nxtpoint:=@pointtypearray(points)^[i]; + scanedge(cpoint^.x,cpoint^.y,nxtpoint^.x,nxtpoint^.y,0); + end; + drawhlines(top_y,bottom_y); + + + + + +end; + + + +Procedure outtextxy_length(x1,y1:integer;txt:pchar;length:byte); +var txtlop:byte; +Begin + if tcharset.attrib<>CTproportional then + for txtlop:=1 to length do begin + drawbytes(x1,y1,@tcharset.typeface[byte(txt^)],fontheight); + inc(x1,8); + inc(txt); + end else + for txtlop:=1 to length do begin + drawbytes(x1,y1,@tcharset.typeface[byte(txt^)],fontheight); + inc(x1,tcharset.widths[byte(txt^)]); + inc(txt); + end; +end; +Procedure outtextxy(x1,y1:integer;txt:string); +Begin + outtextxy_length(x1,y1,@txt[1],byte(txt[0])); +end; +(* +Procedure outtextxy_length(x1,y1:integer;txt:pchar;length:byte); +var txtend,ylop,txtstart,lmask,rmask:byte; + Adrs,decoffs:word; + x2,y2,tmp:integer; +Begin + txtend:=length; + x2:=x1+(txtend shl 3); + y2:=y1+fontmax; + if (x1<=BC.viewport.x2)and(y1<=BC.viewport.y2)and(x2>=BC.viewport.x1) + and(y2>=BC.viewport.y1)and(txtend<>0) then begin + + {**Y-cliping**} + If y2>BC.viewport.y2 then ylop:=(BC.viewport.y2-y1) else ylop:=fontmax; + if y1BC.viewport.x2 then begin + dec(txtend,tmp shr 3); + rmask:=rmask shl (tmp and 7); + end; + if txtstart=txtend+1 then exit; + + + decoffs:=(BC.offsw*(ylop+1)-8); + asm + mov di,adrs {load offset} + + mov dl,t_col + mov bx,BC.offsw {load dx with screen offset} + sub bx,8 + + mov dh,txtstart {dh is the loop counter} + @Textloop: + les si,[bp+6] {point to string} + mov al,dh;xor ah,ah {get txtloop from dh into ax} + add si,ax {Add to offset the offset of the..} + mov al,es:[si] ;xor ah,ah {..current character..} + shl ax,fontshift {..shift to get the byte offset..} + add ax,y1 {..of the graphic and add y to clip} + + mov es,word ptr BC.scrptr+2 {set up screen address segment} + + lea si,tcharset {point to character set} + add si,ax {add character offset} + mov cl,ylop ;inc cl {set up y loop (from y to ylop)} + + @drawloop: + push cx {save @drawloop} + mov cx,8 + mov ah,ds:[si] + + cmp dh,txtstart;jnz @noleft + and ah,lmask {mask with the left?} + @noleft: + cmp dh,txtend; jnz @noright + and ah,rmask {mask with the right?} + @noright: + + @bitloop: + shl ah,1 + jnc @nodraw + mov es:[di],dl + @nodraw: + inc di + loop @bitloop + add di,bx {shift to next line on screen} + inc si {go to next byte in pic} + pop cx + loop @drawloop + + sub di,decoffs {correct the screen position..} + inc dh {next character} + cmp dh,txtend {is it the end?} + jle @Textloop {if not, do it all again} + end; + {for txtlop:=1 to txtlop do begin + currmask:=pointer(@tcharset^[ord(txt[txtlop])][y]); + for lop:=0 to lop do begin + hsub2(adrs,currmask^ shr dxr,currmask^ shl (8-dxr)); + inc(Adrs,offs); + inc(currmask); + end; + dec(Adrs,decoffs); + end;} + end; + +end; + +Procedure outtextxy(x1,y1:integer;txt:string); +var txtend,ylop,txtstart,lmask,rmask:byte; + Adrs,decoffs:word; + x2,y2,tmp:integer; +Begin + txtend:=byte(txt[0]); + x2:=x1+(txtend shl 3); + y2:=y1+fontmax; + if (x1<=BC.viewport.x2)and(y1<=BC.viewport.y2)and(x2>=BC.viewport.x1) + and(y2>=BC.viewport.y1)and(txtend<>0) then begin + + {**Y-cliping**} + If y2>BC.viewport.y2 then ylop:=(BC.viewport.y2-y1) else ylop:=fontmax; + if y1BC.viewport.x2 then begin + dec(txtend,tmp shr 3); + rmask:=rmask shl (tmp and 7); + end; + if txtstart=txtend+1 then exit; + + + decoffs:=(BC.offsw*(ylop+1)-8); + asm + mov di,adrs {load offset} + + mov dl,t_col + mov bx,BC.offsw {load dx with screen offset} + sub bx,8 + + mov dh,txtstart {dh is the loop counter} + @Textloop: + les si,[bp+6] {point to string} + mov al,dh;xor ah,ah {get txtloop from dh into ax} + add si,ax {Add to offset the offset of the..} + mov al,es:[si] ;xor ah,ah {..current character..} + shl ax,fontshift {..shift to get the byte offset..} + add ax,y1 {..of the graphic and add y to clip} + + mov es,word ptr BC.scrptr+2 {set up screen address segment} + + lea si,tcharset {point to character set} + add si,ax {add character offset} + mov cl,ylop ;inc cl {set up y loop (from y to ylop)} + + @drawloop: + push cx {save @drawloop} + mov cx,8 + mov ah,ds:[si] + + cmp dh,txtstart;jnz @noleft + and ah,lmask {mask with the left?} + @noleft: + cmp dh,txtend; jnz @noright + and ah,rmask {mask with the right?} + @noright: + + @bitloop: + shl ah,1 + jnc @nodraw + mov es:[di],dl + @nodraw: + inc di + loop @bitloop + add di,bx {shift to next line on screen} + inc si {go to next byte in pic} + pop cx + loop @drawloop + + sub di,decoffs {correct the screen position..} + inc dh {next character} + cmp dh,txtend {is it the end?} + jle @Textloop {if not, do it all again} + end; + {for txtlop:=1 to txtlop do begin + currmask:=pointer(@tcharset^[ord(txt[txtlop])][y]); + for lop:=0 to lop do begin + hsub2(adrs,currmask^ shr dxr,currmask^ shl (8-dxr)); + inc(Adrs,offs); + inc(currmask); + end; + dec(Adrs,decoffs); + end;} + end; +end; +*) +Procedure Drawbytesxy(x1,y1:Integer;pic:bytearray;xbytes,ybytes:byte); +begin +end; + +Procedure Drawbytes(x1,y1:Integer;pic:bytearray;nbytes:byte); +var lop,mask:byte; Adrs:word; + x2:integer; +Begin + x2:=x1+8; + dec(nbytes); + if (x2>=BC.viewport.x1)and(x1<=BC.viewport.x2)and(y1+nbytes>=BC.viewport.y1)and(y1<=BC.viewport.y2)then begin + Adrs:=(y1*BC.offsw)+x1; + + {**XCliping**} + mask:=$ff; + if x1BC.viewport.x2 then + mask:=mask and ($ff shl (x2-BC.viewport.x2-1)); + + {**YCliping**} + If y1+nbytes>BC.viewport.y2 then lop:=(BC.viewport.y2-y1) else lop:=nbytes; + if y1BC.viewport.y2 then Return:=bellow else + if y1BC.viewport.x2 then inc(Return,right) else + if x1BC.viewport.x2))+ {right =$01} + (byte(yb>BC.viewport.y2)shl 1)+{bellow =$02} + (byte(xbBC.viewport.x2))+ {right =$01} + (byte(ya>BC.viewport.y2)shl 1)+{bellow =$02} + (byte(xa0 then begin + clip:=false;exit;{Trivial reject} + end else begin + if not(code0 or code1<>0)then begin + clip:=true;exit;{Trivial accept} + end else If (code0=0) then begin + fswap(code1,code0,1); + fswap(xb,xa,2); + fswap(yb,ya,2); + end; + if (code0 and bellow)<>0 then begin + inc(xb,(xa-xb)*(BC.viewport.y2-yb)div(ya-yb)); + yb:=BC.viewport.y2; + end else if (code0 and above)<>0 then begin + inc(xb,(xa-xb)*(BC.viewport.y1-yb)div(ya-yb)); + yb:=BC.viewport.y1; + end else if (code0 and right)<>0 then begin + inc(yb,(ya-yb)*(BC.viewport.x2-xb)div(xa-xb)); + xb:=BC.viewport.x2; + end else if (code0 and left)<>0 then begin + inc(yb,(ya-yb)*(BC.viewport.x1-xb)div(xa-xb)); + xb:=BC.viewport.x1; + end; + end; + end; +end; + +{biechmans line drawing algo- bit optimization still needed} +Procedure Line(x1,y1,x2,y2:integer); +Var dfx,dfy,d,d2,incr1,incr2,xinc:integer; +adrs:word; +Begin + if x1=x2 then vline(x1,y1,y2) else begin + if y1=y2 then hline(x1,x2,y1) else + if clip(x1,y1,x2,y2) then Begin + dfx:=abs(x2-x1);dfy:=abs(y2-y1); + asm mov es,word ptr BC.scrptr+2 end; + if dfx>dfy then begin + asm + mov ax,x2 ; cmp x1,ax ; jle @no_swap + Xchg x1,ax ; mov x2,ax + mov ax,y2; Xchg y1,ax;mov y2,ax; + @no_swap: + + mov ax,y1; imul BC.offsw ;add ax,word ptr BC.scrptr; {sort out address:} + mov bx,x1; add ax,bx {adrs:=(y1*BC.offsw)+(x1 shr 3)+word ptr BC.scrptr;} + mov adrs,ax + end; + + incr2:=(dfy-dfx)shl 1; + if(y2>y1) then xinc:=BC.offsw else xinc:=-BC.offsw; + + asm + mov al,t_col + mov dx,xinc {get scanline offset} + mov bx,adrs {get offset} + + mov cx,dfx ;inc cx {load in the length} + mov si,dfy ;shl si,1; {get incr1} + mov di,si ;sub di,dfx; {get 'd'} + push bp {remember stack frame} + mov bp,incr2 + + @Runloop: {start loop} + mov es:[bx],al + inc bx + cmp di,0;jl @noinc {new scan line?} + add di,bp {update di} + add bx,dx {add scanline offset} + jmp @check + @noinc: + add di,si {update fractional part} + @check: + loop @runloop + pop bp {recall stack frame} + end; + end else begin + asm + mov ax,y2 ; cmp y1,ax ; jle @no_swap + Xchg y1,ax ; mov y2,ax + mov ax,x2; Xchg x1,ax;mov x2,ax; + @no_swap: + mov ax,y1; imul BC.offsw ;add ax,word ptr BC.scrptr; {sort out address:} + mov bx,x1; add ax,bx {adrs:=(y1*BC.offsw)+(x1 shr 3)+word ptr BC.scrptr;} + mov adrs,ax + end; + d2:=dfx shl 1; + d:=d2-dfy; + incr1:=d2; + incr2:=(dfx-dfy) shl 1; + asm + inc dfy {add one to difference in y} + mov dx,BC.offsw {screen width} + mov bx,adrs {screen address} + mov al,t_col {Colour} + mov di,d {(diff in X*2)-diff in y} + mov si,incr1 {integer increment} + + mov cx,x1; cmp cx,x2; + jg @left {check if line is doing left or right} + + {do these loads for both directions because of the use of bp} + mov cx,dfy {difference in Y} + push bp + mov bp,incr2 {fractional increment} + @Runloop: + mov es:[bx],al {Write to screen} + add bx,dx {next scan line} + cmp di,0 {if no change} + jl @noinc {then don't do below} + add di,bp {do frac part} + inc bx {go to next byte on screen} + jmp @check + @noinc: + add di,si {add frac part} + @check: + loop @runloop + jmp @end + + @left: + {do these loads for both directions because of the use of bp} + mov cx,dfy {difference in Y} + push bp + mov bp,incr2 {fractional increment} + @Runloopb: + mov es:[bx],al {Write to screen} + add bx,dx {next scan line} + cmp di,0 {if no change} + jl @noincb {then don't do below} + add di,bp {do frac part} + dec bx + jmp @checkb + @noincb: + add di,si {add frac part} + @checkb: + loop @runloopb + @end: + pop bp + end; + end; + end; + end; +end; + +Procedure Hline(x1,x2,y:Integer);assembler; +asm + mov ax,y;mov bx,x1; mov cx,x2 + {swap x1,x1 if x1>x2} + cmp bx,cx ;jle @no_swap ; Xchg bx,cx; @no_swap: + + {is line at all visable?} + cmp bx,BC.viewport.x2 ;jg @fin + cmp cx,BC.viewport.x1 ;jl @fin + cmp ax,BC.viewport.y2 ;jg @fin + cmp ax,BC.viewport.y1 ;jl @fin + + {X axis clipping} + mov dx,BC.viewport.x1 ;cmp bx,dx ; JGE @nochange_x1 + mov bx,dx + @nochange_x1: + mov dx,BC.viewport.x2 ;cmp cx,dx ; JLE @nochange_x2 + mov cx,dx + @nochange_x2: + + {start of mode dependant stuff} {load up screen position} + mov es,word ptr BC.scrptr+2 + inc cx ;imul BC.offsw ;add ax,word ptr BC.scrptr; mov di,ax {load up screen pos} + + {calculate length (in bytes-1) of line} + sub cx,bx {get byte length} + add di,bx {add this to screen memory offset} + + mov al,t_col + mov ah,al + + shr cx,1 {get word count} + REP stosw {store words} + adc cx,cx {extra byte?} + REP stosb {Draw if there} + + @fin: +end; + + +Procedure bar(x1,y,x2,y2:integer); +var adrs:word; +Begin + if x2BC.viewport.y2)or(y2BC.viewport.x2)or(x2BC.viewport.x2 then x2:=BC.viewport.x2;if y2>BC.viewport.y2 then y2:=BC.viewport.y2; + inc(x2);inc(y2); + adrs:=(y*BC.offsw)+x1; + asm + mov es,word ptr BC.scrptr+2 + mov di,adrs {address} + add di,word ptr BC.scrptr + mov ax,BC.offsw + mov si,ax {load offset} + mov al,t_fillcol + mov bx,x2 + sub bx,x1 + mov cx,y2 {load loop count -ycnt} + sub cx,y + mov dx,BC.offsw + sub dx,bx + @runloop: + push cx + mov cx,bx + rep stosb + pop cx + add di,dx + loop @runloop + end; + end; +end; + +Procedure Vline(x,y1,y2:Integer);assembler; +asm + {es -screen seg + di -byte offset + al -byte mask + cx -Y length of line} + {remember that these registers are loaded thus:} + mov ax,y1; mov cx,y2 ;mov bx,x + {swap y2,y1 if y1>y2} + cmp ax,cx ;jle @no_swap ; Xchg ax,cx; @no_swap: + + cmp ax,BC.viewport.y2 ;jg @fin {is line at all visable?} + cmp cx,BC.viewport.y1 ;jl @fin + cmp bx,BC.viewport.x2 ;jg @fin + cmp bx,BC.viewport.x1 ;jl @fin + + {Y axis clipping} + mov dx,BC.viewport.y1 ;cmp ax,dx ; JGE @nochange_y1 + mov ax,dx + @nochange_y1: + mov dx,BC.viewport.y2 ;cmp cx,dx ; JLE @nochange_y2 + mov cx,dx + @nochange_y2: + + inc cx {inc y2} + sub cx,ax {calc length} + + les di,BC.scrptr {load up screen position} + imul BC.offsw; + add di,ax; add di,bx; {add di, y*BC.offsw +xposition} + {result of imul is stored (thank God) in ax-dx, perfect for svga} + + mov bx,BC.offsw {load screen width} + mov al,t_col + + @runloop: + mov es:[di],al {write to screen} + add di,bx {next pixel} + loop @runloop + @fin: +end; + +Procedure putpixel(x1,y1:Integer);assembler; +asm + {if dot visable?} + mov bx,x1 ;mov ax,y1 + cmp bx,BC.viewport.x1 ;jl @fin {clipping..} + cmp ax,BC.viewport.y1 ;jl @fin + cmp bx,BC.viewport.x2 ;jg @fin + cmp ax,BC.viewport.y2 ;jg @fin + + mov es,word ptr BC.scrptr+2 + imul BC.offsw; add ax,word ptr BC.scrptr + add ax,bx; mov di,ax {load up screen pos} + + mov al,t_col + + mov es:[di],al + @fin: +end; + +Function getpixel(x1,y1:Integer):byte; +begin asm + mov es,word ptr BC.scrptr+2 + imul BC.offsw; add ax,word ptr BC.scrptr + add ax,bx; mov di,ax {load up screen pos} + + mov al,es:[di] + mov @result,al + end; +end; + +Procedure Triangle(xa,ya,xb,yb,xc,yc:integer);assembler; +const shiftby=6; +Var +lop,Lx,Rx, +Lxadd,Rxadd,yrdiff,yldiff,xoff,Lxa,Rxa,xdiff,endp:integer; +right:boolean; +scroffset:word; + {sort by Y} + asm + {if ya>yc then swap xc,xa swap yc,ya fswap ic,ia} + mov ax,yc + cmp ya,ax + jl @NoSwapY1 + xchg ya,ax; mov yc,ax + mov ax,xc; xchg xa,ax; mov xc,ax + @NoSwapY1: + {if ya>yb then swap xb,xa swap yb,ya fswap ib,ia} + mov ax,yb + cmp ya,ax + jl @NoSwapY2 + xchg ya,ax; mov yb,ax + mov ax,xb; xchg xa,ax; mov xb,ax + @NoSwapY2: + {if yb>yc then swap xc,xb swap yc,yb fswap ic,ib} + mov ax,yc + cmp yb,ax + jl @NoSwapY3 + xchg yb,ax; mov yc,ax + mov ax,xc; xchg xb,ax; mov xc,ax + @NoSwapY3: + + {is the cross point to the left or right?} + mov di,yc;sub di,ya + mov ax,yb;sub ax,yc + mov cx,xc;sub cx,xa + imul cx + cmp di,0 + jz @nodiv + idiv di + @nodiv: + add ax,xc + cmp xb,ax + mov right,true + jle @isright + mov right,false + @isright: + {get smallest x} + mov bx,xa; + mov ax,xb + cmp bx,ax; jl @nodo1 ;mov bx,ax ;@nodo1: + mov ax,xc + cmp bx,ax; jl @nodo2 ;mov bx,ax ;@nodo2: + mov xoff,bx + {sub by bx and shift left } + sub xa,bx; + sub xb,bx; + sub xc,bx; + + shl xa,shiftby + shl xb,shiftby + shl xc,shiftby + + {get y length} + mov si,yc + cmp si,BC.viewport.y2 + jle @noyclip + mov si,BC.viewport.y2 + inc si + @noyclip: + + mov endp,si {exit routine if ends of tri are outside VP} + mov si,ya + cmp si,BC.viewport.y2 {if ya>BC.viewport then exit} + jg @triend + cmp si,endp {if ya=clipped yc then exit} + jz @triend + + {yldiff:=yb-ya;if yldiff=0 then yldiff:=1; + Lxadd:=(xb-xa) div yldiff;} + mov ax,xb ;sub ax,xa + mov bx,yb ;sub bx,ya + jz @nodiv1 + cwd + idiv bx + jmp @nocorrect1 + @nodiv1: + mov bx,1 + @nocorrect1: + mov yldiff,bx + mov lxadd,ax + {yrdiff:=yc-ya;if yrdiff=0 then yrdiff:=1; + Rxadd:=(xc-xa) div yrdiff;} + mov ax,xc ;sub ax,xa + mov bx,yc ;sub bx,ya + jz @nodiv2 + cwd + idiv bx + jmp @nocorrect2 + @nodiv2: + mov bx,1 + @nocorrect2: + mov yrdiff,bx + mov rxadd,ax + mov ax,xa + mov Lxa,ax + mov Rxa,ax + {test for swap} + test right,1 + jnz @isrightb + mov ax,rxadd + xchg lxadd,ax + mov rxadd,ax + @isrightb: + + mov es,word ptr BC.scrptr+2 {load up screen mem pos} + mov cx,BC.offsw + mov ax,ya ;imul cx ;add ax,word ptr BC.scrptr + mov di,ax + + @Yloop: + cmp si,yb + jnz @Daltend + {yldiff:=yc-yb;if yldiff=0 then yldiff:=1;} + mov bx,yc ;sub bx,yb + jnz @nocorrect; mov bx,1; @nocorrect: + {Lxadd:=(xc-xb) div yldiff;} + mov ax,xc; sub ax,xb + cwd + idiv bx + mov bx,xb + {test see which side these need to go in} + test right,true + jz @isleft + mov lxadd,ax + mov lxa,bx + jmp @Daltend + @isleft: + mov rxadd,ax + mov rxa,bx + @Daltend: + + push di + {inc x1a and x2a with the slope of line and inc offset} + mov ax,Lxadd;add lxa,ax + mov ax,Rxadd;add rxa,ax + {if ylop>BC.viewport.y1 then....} + mov ax,BC.viewport.y1 ;cmp ax,si ;jg @fin + {convert the line to normal pixel-space} + mov cx,rxa ;shr cx,shiftby ;add cx,xoff + mov dx,lxa ;shr dx,shiftby ;add dx,xoff + + {flip- shouldn't have to but there ya go} + cmp dx,cx ;jg @no_swap ; Xchg cx,dx; @no_swap: {if x1>x2 then swap} + {if (x1>BC.viewport.x2)or(x2yc then swap xc,xa swap yc,ya fswap ic,ia} + mov ax,yc + cmp ya,ax + jl @NoSwapY1 + xchg ya,ax; mov yc,ax + mov ax,xc; xchg xa,ax; mov xc,ax + mov ax,ic; xchg ia,ax; mov ic,ax + @NoSwapY1: + {if ya>yb then swap xb,xa swap yb,ya fswap ib,ia} + mov ax,yb + cmp ya,ax + jl @NoSwapY2 + xchg ya,ax; mov yb,ax + mov ax,xb; xchg xa,ax; mov xb,ax + mov ax,ib; xchg ia,ax; mov ib,ax + @NoSwapY2: + {if yb>yc then swap xc,xb swap yc,yb fswap ic,ib} + mov ax,yc + cmp yb,ax + jl @NoSwapY3 + xchg yb,ax; mov yc,ax + mov ax,xc; xchg xb,ax; mov xc,ax + mov ax,ic; xchg ib,ax; mov ic,ax + @NoSwapY3: + {is the cross point to the left or right?} + mov di,yc;sub di,ya + mov ax,yb;sub ax,yc + mov cx,xc;sub cx,xa + imul cx + cmp di,0 + jz @nodiv + idiv di + @nodiv: + add ax,xc + cmp xb,ax + mov right,true + jle @isright + mov right,false + @isright: + {get smallest x} + mov bx,xa; + mov ax,xb + cmp bx,ax; jl @nodo1 ;mov bx,ax ;@nodo1: + mov ax,xc + cmp bx,ax; jl @nodo2 ;mov bx,ax ;@nodo2: + mov xoff,bx + {sub by bx and shift left } + sub xa,bx; + sub xb,bx; + sub xc,bx; + + shl xa,shiftby + shl xb,shiftby + shl xc,shiftby + end; + asm + db 66h;shr word ptr ia,16; + db 66h;shr word ptr ib,16; + db 66h;shr word ptr ic,16; + end; + + ylop:=ya;endp:=yc; + if endp>BC.viewport.y2 then endp:=BC.viewport.y2+1; + + asm + {yldiff:=yb-ya;if yldiff=0 then yldiff:=1; + Lxadd:=(xb-xa) div yldiff;} + mov ax,xb ;sub ax,xa + mov bx,yb ;sub bx,ya + jz @nodiv1 + cwd + idiv bx + jmp @nocorrect1 + @nodiv1: + mov bx,1 + @nocorrect1: + mov yldiff,bx + mov lxadd,ax + {yrdiff:=yc-ya;if yrdiff=0 then yrdiff:=1; + Rxadd:=(xc-xa) div yrdiff;} + mov ax,xc ;sub ax,xa + mov bx,yc ;sub bx,ya + jz @nodiv2 + cwd + idiv bx + jmp @nocorrect2 + @nodiv2: + mov bx,1 + @nocorrect2: + mov yrdiff,bx + mov rxadd,ax + end; + {yrdiff:=yc-ya;if yrdiff=0 then yrdiff:=1; + Rxadd:=(xc-xa) div yrdiff;} + Lxa:=xa;Rxa:=xa; + + li32:=ia32; + ri32:=ia32; + liadd32:=(ib32-ia32)div yldiff; + riadd32:=(ic32-ia32)div yrdiff; + if not right then begin + fswap(rxadd,lxadd,2); + fswap(liadd32,riadd32,4); + end; + asm + mov es,word ptr BC.scrptr+2 {load up screen mem pos} + mov si,BC.offsw + mov ax,ya ;imul si ;add ax,word ptr BC.scrptr + mov scroffset,ax + end; + while ylopBC.viewport.y1 then....} + mov ax,BC.viewport.y1 ;cmp ax,ylop ;jg @fin + {convert the line to normal pixel-space} + {xa is in dx, xb is in cx} + mov cx,rxa ;shr cx,shiftby ;add cx,xoff + mov dx,lxa ;shr dx,shiftby ;add dx,xoff + {Xclipping} + mov di,cx + inc di + sub di,dx + mov ax,BC.viewport.x2 ;cmp cx,ax ; JLE @nochange_x2 + mov cx,ax + @nochange_x2: + mov ax,BC.viewport.x1 ;cmp dx,ax ; JGE @nochange_x1 + mov dx,ax + @nochange_x1: + inc cx + mov lx,dx + sub cx,dx {calculate xdiff} + jle @fin + mov xdiff,cx {save it} + {generate colour interpoltaion addition} + mov si,li {colour intensity start} + mov ax,ri + sub ax,si {load colour} + CWD {put ax into AX:DX, with sign} + idiv di {do it, baby} + mov cadd,ax {load ax into erm... addi?} + mov dx,lx + {re-evaluate start address} + mov di,scroffset + mov cx,dx {get the x value} + add di,cx {add this to total} + + mov cx,xdiff {xdiff is the length (xb-xa)} + + push bp + mov bp,Cadd {colour interpolation value} + + @drawloop: + mov bx,si {load colour} + shr bx,8 {get it into non-fixed range} + mov es:[di],bl {write to screen} + add si,bp {add colour interpolation value} + inc di {increment screen offset} + loop @drawloop + pop bp + @fin: + end; + {ci:=li; + for lop:=Lx to Rx do begin + t_col:=asr(ci); + inc(ci,addi); + putpixel(lop,ylop); + end;} + inc(scroffset,BC.offsw); + inc(ylop); + end; +end; + +Procedure Screencopy(x1,y1,x2,y2,xd,yd:integer;page1,page2:byte); +begin +end; + +Procedure putbitmap(x1,y1:integer;bitmap:bitmaptypeptr); +var ylop,xlop:integer; + adrs,picadrs:byteptr; + x2,y2:integer; +Begin + with bitmap^ do begin + x2:=x1+size.x; + y2:=y1+size.y; + if (y1BC.viewport.x1) and(y2>BC.viewport.y1) then begin + if bitmaptype=BMflat then begin + picadrs:=pointer(flatdata); + if x1BC.viewport.x1) and(y2>BC.viewport.y1) then begin + + picadrs:=pointer(flatdata); + if x1BC.viewport.x1) and(y2>BC.viewport.y1) then begin + + picadrs:=pointer(flatdata); + if x1BC.viewport.x1) and(y2>BC.viewport.y1) then begin + + picadrs:=pointer(flatdata); + if x1BC.viewport.x1) and(y2>BC.viewport.y1) then begin + + picadrs:=pointer(flatdata); + if x1BC.viewport.x1) and(y2>BC.viewport.y1) then begin + + picadrs:=pointer(flatdata); + if x1currlen do begin + inc(lop); + inc(currlen,charset^.widths[byte(txt[lop])]) + end; + getindex:=lop; +end; + +function TStrLen_null(txt:pchar;charset:charsettypeptr):word; +var len:word; +begin + len:=0; + with charset^ do + if attrib=CTproportional then + while byte(txt^)<>0 do begin + inc(len,widths[byte(txt^)]); + inc(txt); + end + else + while byte(txt^)<>0 do begin + inc(len,8); + inc(txt); + end; + TStrLen_null:=len; +end; + + +Procedure Maxline(maxlines:integer); +Begin + port[$3d4]:=9;port[$3d5]:=maxlines; +end; + +Procedure setblock(block:byte);assembler; +asm + mov bl,block + mov ax,$1103 + int $10 +end; + +procedure mapmask(mask:byte);assembler; +asm + mov dx,$3c5 + mov al,2 + out dx,al + mov al,mask + out dx,al +end; + +{Procedure Setcharset(lcharset:charsettype);assembler; +const block=0; +asm + {set mapmask to two} + {mov dx,$3c5 + mov al,2 + out dx,al + mov al,$4 + out dx,al + + {load character set into generator 0)} + {push ds + lds si,lcharset + mov ax,$B800 + mov es,ax + mov di,block + mov cx,256*4 + movsw + + {set block to 0} + { +end;} + +Procedure setcharset(lcharset:charsettype;block:byte);assembler; +asm + mov ah,$11 + mov al,$0 + {mov ax,2816} + mov bh,Fontheight + mov bl,block + mov cx,255 + mov dx,0 + push bp + les bp,lcharset + int $10 + pop bp +end; + + +Procedure savefontlist(filename:string;var ch:charsettype); +Var scans:byte;norecs:word; + f:file; +Begin + norecs:=1; + assign(f,filename); + Rewrite(f,norecs); + scans:=Fontheight; + blockwrite(f,scans,1,norecs); + blockwrite(f,ch.typeface,256*Fontheight,norecs); + close(f); +end; + +Procedure proportionalize(var ch:charsettype); +var +currwidth:byteptr; +fontlop,bytelop,bitlop,currbit:byte; +begin + currwidth:=@ch.widths; + ch.attrib:=ctproportional; + for fontlop:=0 to 255 do begin + currwidth^:=0; + for bytelop:=0 to fontmax do begin + currbit:=0; + for bitlop:=7 downto 0 do begin + if ch.typeface[fontlop][bytelop] and (1 shl bitlop)<>0 then + currbit:=bitlop xor 7; + end; + if currbit>currwidth^ then + currwidth^:=currbit; + end; + inc(currwidth^,2); + inc(currwidth); + end; + ch.widths[32]:=6; +end; + +Procedure loadfontlist(filename:string;var ch:charsettype); +const offset=0; +Var scans:byte;norecs:word; + fontlop,bytelop,bitlop,currbit:byte; + dummy:array[0..offset] of word; + + f:file; +Begin + norecs:=1; + assign(f,filename); + Reset(f,norecs); + blockread(f,scans,1,norecs); + blockread(f,dummy,offset,norecs); + blockread(f,ch.typeface,256*scans,norecs); + proportionalize(ch); + close(f); +end; + +{Procedure loadfontlistb(filename:string;var ch:charsettype); +Var lop,lop2,scans:byte;f:text;temp:char;tempstr:string;code:integer; +Begin + Assign(f,filename); + Reset(f); + readln(f,tempstr); + tempstr:=copy(tempstr,1,9); + val(tempstr,scans,code); + for lop:=0 to 255 do + for lop2:=1 to Fontheight do + begin + read(f,temp);ch^[lop][lop2]:=ord(temp); + end; + close(f); +end; + +{the above is the old byte by byte method +below is the dynamicly sized array saver} + +{Procedure loadfontlistc(filename:string;var ch:charsettype); +Var scans,lop:byte;f:file;norecs:word; +Begin + norecs:=1; + Assign(f,filename); + Reset(f,norecs); + blockread(f,scans,1,norecs); + for lop:=0 to 255 do + blockread(f,ch^[lop],scans,norecs); + close(f); +end;} + +procedure rorblock(block:pointer;count:word;shiftby:byte);assembler; +asm + les di,block + mov cl,shiftby + mov bx,count + + dec bx + add di,bx + + {do first byte, save in dx} + mov dl,es:[di] + xor dh,dh + ror dx,cl + mov es:[di],dl + dec di + cmp bx,0 + jz @lastbyte + + @shiftloop: + mov al,es:[di] + xor ah,ah + ror ax,cl + mov es:[di],al + or es:[di+1],ah + dec di + dec bx + jnz @shiftloop + {do last byte} + @lastbyte: + or es:[di+1],dh +end; + +procedure rolblock(block:pointer;count:word;shiftby:byte);assembler; +asm + les di,block + mov cl,shiftby + mov bx,count + dec bx + {do first byte, save in dx} + mov dh,es:[di] + xor dl,dl + rol dx,cl + mov es:[di],dh + inc di + cmp bx,0 + jz @lastbyte + + @shiftloop: + mov ah,es:[di] + xor al,al + rol ax,cl + mov es:[di],ah + or es:[di-1],al + inc di + dec bx + jnz @shiftloop + {do last byte} + @lastbyte: + or es:[di-1],dl +end; + +procedure rol_font(font:bytearray;fontwidth,fontheight:word); +var lop:byte; +begin + for lop:=0 to fontheight-1 do + rolblock(@font^[lop*(fontwidth shr 3)],fontwidth shr 3,1); +end; + +procedure rou_font(font:bytearray;fontwidth,fontheight:word); +var lop:word; + xbytes:byte; + temp:^byte; + +begin + getmem(temp,xbytes); + xbytes:=fontwidth shr 3; + move(font^[0],temp^,xbytes); + for lop:=0 to fontheight-2 do + move(font^[(lop+1)*xbytes],font^[lop*xbytes],xbytes); + move(temp^,font^[(fontheight-1)*xbytes],xbytes); + +end; + +procedure ror_font(font:bytearray;fontwidth,fontheight:word); +var lop:byte; +begin + for lop:=0 to fontheight-1 do + rorblock(@font^[lop*(fontwidth shr 3)],fontwidth shr 3,1); +end; + +procedure rod_font(font:bytearray;fontwidth,fontheight:word); +var lop:word; + xbytes:byte; + temp:^byte; + +begin + xbytes:=fontwidth shr 3; + getmem(temp,xbytes); + + move(font^[(fontheight-1)*xbytes],temp^,xbytes); + for lop:=fontheight-1 downto 1 do + move(font^[(lop-1)*xbytes],font^[(lop)*xbytes],xbytes); + move(temp^,font^[0],xbytes); + freemem(temp,xbytes); + + +end; +{assembler; +asm + les di,font + + mov cx,Fontheight + dec cx + mov ah,es:[di] + @shiftlop: + mov al,es:[di+1] + mov es:[di],al + inc di + loop @shiftlop + mov es:[di],ah +end;} + +procedure not_font(font:bytearray;fontsize:word);assembler; +asm + les di,font + mov cx,Fontsize + @notlop: + mov al,es:[di] + not al + mov es:[di],al + inc di + loop @notlop +end; + +procedure flipbyte(var c:byte);assembler; +asm + les di,c + mov al,es:[di] + mov cx,8 + @bitlop: + rcr al,1 + adc ah,0 + cmp cl,1 + jz @noshift + shl ah,1 + @noshift: + loop @bitlop + mov es:[di],ah +end; + +procedure flipx_font(font:bytearray;fontwidth,fontheight:word); +var xlop,ylop,xbytes,byte1,byte2:word; +begin + xbytes:=(fontwidth shr 3); + for ylop:=0 to xbytes*fontheight do + flipbyte(font^[ylop]); + if xbytes>1 then + for ylop:=0 to fontheight-1 do + for xlop:=0 to (xbytes-1) shr 1 do + fswap(font^[(ylop*xbytes)+xlop],font^[(ylop*xbytes)+xbytes-1-xlop],1); +end; + +procedure flipy_font(font:bytearray;fontwidth,fontheight:word); +var lop,xbytes:byte; +begin + xbytes:=fontwidth shr 3; + for lop:=0 to (Fontheight-1) shr 1 do + fswap(font^[lop*xbytes],font^[(fontheight-1-lop)*xbytes],xbytes); +end; +End. diff --git a/CLAYCP.PAS b/CLAYCP.PAS new file mode 100644 index 0000000..fc72ae3 --- /dev/null +++ b/CLAYCP.PAS @@ -0,0 +1,1377 @@ +{All files in this project are copyright 2000 (c) Tim Lewis} +{Please feel free to use this code as you see fit but please do not release} +{a new version of clayworks without my consent.} +{If you decide to host the source code on your server, please include all of} +{the files, as they are.} + +program CLAYCP; +uses + ttypes,crt2,dos,tmaths,msmouse,SinCos,chardef,diskop,strings, + gbasics,ggraph,vectfont,colour,stdpal, + Basic3d,tdb,tdeditb, + twinb,twindraw,views,gadgets,dialogs,tdwin,tmenust,pcx256; + +const +VersionStr='2.45'; + +{With debug 'writes' +fixedusage=150928;} +fixedusage=150848; +minmem=200000; + +defaultfont='simp.chr'; + +CMDxrot =1000; +CMDyrot =1001; +CMDzrot =1002; + +CMDexitbox =1004; +CMDnewbox =1005; +CMDloaddialog =1007; + +CMDsaveasdialog =1008; +CMDappend =1009; +CMDprint =1010; +CMDexit =1011; + +CMDrefresh =1012; +CMDinfo =1013; +CMDredrawobject =1014; +CMDgetobjectinfo =1015; + +CMDdeleteselectdialog =1018; + +CMDTogglegridFROMICON =1051; +CMDsetwinbig =1052; +{CMDTilewindows =1025; +CMDCascade =1026;} +CMDcallwindowmenu =1053; +CMDtogglegrid =1054; +CMDsetdefaultpal =1055; + +CMDrotateopts =1056; +CMDzoomin =1057; +CMDzoomout =1058; +CMDselectCircChanger =1061; + +{file ops} +CMDloadfont =1064; +CMDCancel =1065; +CMDsave3dfileornot =1066; +CMDapplytextstring =1067; + +CMDToggleExtrude =1073; +CMDToggleConnect =1074; +CMDtoggleSine =1075; +CMDcallhelp =1076; +CMDtogglecheck =1077; + +CMDtogglenodes =1078; +CMDtoggleDoubleSided =1087; +CMDtoggleSmooth =1088; +CMDtoggleAbsolute =1089; +CMDtoggleOutline =1090; +CMDToggleNodesFROMICON =1094; +CMDcallsurfacedialog =1095; +CMDsavepal =2000; +CMDsavepaldialog =2001; +CMDtoggleflat =2002; +CMDtoggleheightmap =2003; +CMDloadheightmapdialog =2004; +CMDloadheightmap =2005; +CMDstickymouse =2006; + +type + +Lgroup=^Lgroup_; +Lgroup_=object(tgroup_) + name:string[20]; + xoffset:integer; + Constructor create(name_:string); + procedure draw;virtual; +end; + +Coordbox=^Coordbox_; +Coordbox_=object(tview_) + coord:vectorreal; + procedure draw;virtual; +end; + +Clay=^Clay_; +Clay_=object(tgroup_) + Coords:Coordbox; + ModeOptions:Tgroup; + ModeOptionsPtrs:array[0..11]of Lgroup; + iconpanel,subpanel:iconpaneltype; + + + Constructor create(xa,ya,xb,yb:integer); + Procedure handlevent(var event:tevent);virtual; + procedure Draw;virtual; +end; + +RotationControl=^RotationControl_; +RotationControl_=object(tgroup_) + constructor create(xa,ya:integer); + procedure handlevent(var event:tevent);virtual; +end; + +TextEditdialog=^TextEditdialog_; +TextEditdialog_=object(Lgroup_) + TextEditBox:edittexttype; + constructor create; + procedure handlevent(var event:tevent);virtual; +end; + +SelectOptions=^SelectOptions_; +SelectOptions_=object(Lgroup_) + seliconpanel,selmodeiconpanel:iconpaneltype; + constructor create; + procedure handlevent(var event:tevent);virtual; + procedure draw;virtual; +end; + +CircOptions=^CircOptions_; +CircOptions_=object(Lgroup_) + Constructor create(name_:string;data:pointer); + Procedure Handlevent(var event:tevent);virtual; + Procedure draw;virtual; +end; + +SphereOptions=^SphereOptions_; +SphereOptions_=object(Lgroup_) + Constructor create(size:pointtypeptr); + Procedure Handlevent(var event:tevent);virtual; + Procedure draw;virtual; +end; + +RotateOptions=^RotateOptions_; +RotateOptions_=object(lgroup_) + Constructor create(name_:string;data:pointer); + Procedure Handlevent(var event:tevent);virtual; + Procedure draw;virtual; +end; + +GridOptions=^GridOptions_; +GridOptions_=object(Lgroup_) + Xval,Yval:Valuetype; + Constructor create; + Procedure Handlevent(var event:tevent);virtual; + Procedure draw;virtual; +end; + +CopyRightBox=^CopyRightBox_; +CopyRightBox_=object(Tview_) + Constructor create; + Procedure HandlEvent(var event:tevent);virtual; + Procedure Draw;virtual; +end; + +SurfaceDialog=^SurfaceDialog_; +SurfaceDialog_=object(tgroup_) + colourgridptr:colourgridtype; + Constructor create(xa,ya:integer); + Procedure HandlEvent(var event:tevent);virtual; + Procedure Draw;virtual; +end; + + +{****----Predeclared Global Variables----****} +var +flipmenu,FileTypeMenu,PolyFunctions,PolyAttribFunctions, +miscmenu,filemenu,editmenu,selectmenu,textmenu, +Windowmenu,stdwinmenu,winmenu3d,rendermenu:Tpopupmenu_; + +Const +backpattern:fillpatterntype=(226,193,163,119,46,28,58,119); + +Flipinfo:array[0..2] of tmenuitem_=( +(name:'üýX';attrib:moptbutton;keycode:0;command:CMDflipx;submenu:nil), +(name:'üýY';attrib:moptbutton;keycode:0;command:CMDflipY;submenu:nil), +(name:'üýZ';attrib:moptbutton;keycode:0;command:CMDflipZ;submenu:nil)); + +FileTypeinfo:array[0..9] of tmenuitem_=( +(name:'3d'; attrib:moptbutton+Moptcentre;keycode:0;command:CMD3dfile;submenu:nil), +(name:'POV'; attrib:moptbutton+Moptcentre;keycode:0;command:CMDPOVfile;submenu:nil), +(name:'RWX'; attrib:moptbutton+Moptcentre;keycode:0;command:CMDRWfile;submenu:nil), +(name:'OBJ'; attrib:moptbutton+Moptcentre;keycode:0;command:CMDOBJfile;submenu:nil), +(name:'PLG'; attrib:moptbutton+Moptcentre;keycode:0;command:CMDPLGfile;submenu:nil), +(name:'GEO'; attrib:moptbutton+Moptcentre;keycode:0;command:CMDGEOfile;submenu:nil), +(name:'VRML';attrib:moptbutton+Moptcentre;keycode:0;command:CMDVRMLfile;submenu:nil), +(name:'3ds';attrib:moptbutton+Moptcentre;keycode:0;command:CMD3dsfile;submenu:nil), +(name:'GOR';attrib:moptbutton+Moptcentre;keycode:0;command:CMDgorfile;submenu:nil), +(name:'JAVA';attrib:moptbutton+Moptcentre;keycode:0;command:CMDJAVAfile;submenu:nil)); +miscinfo:array[0..3] of tmenuitem_=( +(name:'About';attrib:0;keycode:0;command:CMDinfo;submenu:nil), +(name:'Refresh display';attrib:0;keycode:0;command:CMDrefresh;submenu:nil), +(name:'Object information';attrib:0;keycode:0;command:CMDgetobjectinfo;submenu:nil;extratext:''), +(name:'Help!';attrib:0;keycode:0;command:CMDcallhelp;submenu:nil;extratext:'F1')); + + +Fileinfo:array[0..7] of tmenuitem_=( +(name:'New.. ';attrib:0;keycode:0;command:CMDnewbox;submenu:nil;extratext:'þÿF1'), +(name:'Load.. ';attrib:0;keycode:0;command:CMDloaddialog;submenu:@filetypemenu;extratext:'þÿF2'), +(name:'Save ';attrib:0;keycode:0;command:CMDsave3dfile;submenu:nil;extratext:'þÿF5'), +(name:'Save as.. ';attrib:0;keycode:0;command:CMDsaveasdialog;submenu:@filetypemenu;extratext:'þÿF3'), +(name:'Append.. ';attrib:0;keycode:0;command:CMDappend;submenu:@filetypemenu;extratext:'þÿF6'), +(name:'';attrib:moptseperator;keycode:0;command:0;submenu:nil), +(name:'Print..';attrib:MoptDisabled;keycode:0;command:CMDprint;submenu:nil), +(name:'Exit ';attrib:0;keycode:0;command:CMDexitbox;submenu:nil;extratext:'þÿF4')); + +Editinfo:array[0..13] of tmenuitem_=( +(name:'Undo '; attrib:0;keycode:0; command:CMDundo; submenu:nil;extratext:'üýU'), +(name:''; attrib:moptseperator;keycode:0; command:CMDeditselect; submenu:nil), +(name:'Select '; attrib:0;keycode:0; command:CMDeditselect; submenu:nil;extratext:'üýS'), +(name:'Square '; attrib:0;keycode:0; command:CMDeditsquare; submenu:nil;extratext:'üýQ'), +(name:'Cube '; attrib:0;keycode:0; command:CMDeditcube; submenu:nil;extratext:'üýC'), +(name:'Dot '; attrib:0;keycode:0; command:CMDeditdot; submenu:nil;extratext:'üýD'), +(name:'Liner '; attrib:0;keycode:0; command:CMDeditliner; submenu:nil;extratext:'üýL'), +(name:'Cone '; attrib:0;keycode:0; command:CMDeditcone; submenu:nil;extratext:'üýO'), +(name:'Circle '; attrib:0;keycode:0; command:CMDeditcircle; submenu:nil;extratext:'üýI'), +(name:'Cylinder ';attrib:0;keycode:0; command:CMDeditcylinder;submenu:nil;extratext:'üýR'), +(name:'Sphere '; attrib:0;keycode:0; command:CMDeditsphere; submenu:nil;extratext:'üýP'), +(name:'Rotate '; attrib:0;keycode:0; command:CMDeditrotate; submenu:nil;extratext:'üýF'), +(name:'Text '; attrib:0;keycode:0; command:CMDedittext; submenu:nil;extratext:'üýT'), +(name:'Grid '; attrib:0;keycode:0; command:CMDeditgrid; submenu:nil;extratext:'üýG')); + +textinfo:array[0..0] of tmenuitem_=( +(name:'Load font';attrib:0;keycode:0;command:CMDloadfontdialog;submenu:nil)); + +PolyFunctionsinfo:array[0..6] of tmenuitem_=( +(name:'QuadDivide þÿQ';attrib:0;keycode:0;command:CMDQuadDivide ;submenu:nil), +(name:'Triangulate þÿT';attrib:0;keycode:0;command:CMDtriangulate ;submenu:nil), +(name:'Split þÿD';attrib:0;keycode:0;command:CMDsplit ;submenu:nil), +(name:'Flip normals þÿF';attrib:0;keycode:0;command:CMDflipnorms ;submenu:nil), +(name:'Add þÿY';attrib:0;keycode:0;command:CMDaddpolygon ;submenu:nil), +(name:'Delete BKSPC';attrib:0;keycode:0;command:CMDdeletepolys ;submenu:nil), +(name:'Set Attributes >';attrib:0;keycode:0;command:0 ;submenu:@PolyAttribfunctions)); + +PolyAttribFunctionsinfo:array[0..5] of tmenuitem_=( +(name:'Double sided ';attrib:0;keycode:0;command:CMDmkDoublesided;submenu:nil;extratext:'þÿB'), +(name:'Single sided ';attrib:0;keycode:0;command:CMDmkSinglesided;submenu:nil;extratext:'þÿS'), +(name:'Smooth ';attrib:0;keycode:0;command:CMDmkSmooth ;submenu:nil;extratext:'þÿV'), +(name:'Flat ';attrib:0;keycode:0;command:CMDmkFlat ;submenu:nil;extratext:'þÿO'), +(name:'Outline ';attrib:0;keycode:0;command:CMDmkOutlined ;submenu:nil;extratext:''), +(name:'Solid ';attrib:0;keycode:0;command:CMDmkSolid ;submenu:nil;extratext:'')); + +Selectinfo:array[0..8] of tmenuitem_=( +(name:'Select all ';attrib:0;keycode:0;command:CMDselectall;submenu:nil;extratext:'þÿJ'), +(name:'Show All Nodes ';attrib:mopttoggler;keycode:0;command:CMDtogglenodes;submenu:nil;extratext:'þÿN'; +toggleref:@drawallnodes), +(name:'Sticky mouse ';attrib:mopttoggler;keycode:0;command:CMDstickymouse;submenu:nil;extratext:'þÿN';toggleref:@stickymouse), +(name:'Copy ';attrib:0;keycode:0;command:CMDautocopyselected;submenu:nil;extratext:'þÿC'), +(name:'Clear ';attrib:0;keycode:0;command:CMDselectclear;submenu:nil;extratext:'þÿL'), +(name:'Delete ';attrib:0;keycode:0;command:CMDdeleteselectdialog;submenu:nil;extratext:'del'), +(name:'Merge ';attrib:0;keycode:0;command:CMDmerge;submenu:nil;extratext:'þÿM'), +{(name:'Rotated Form >';attrib:0;keycode:0;command:0;submenu:@rotatemenu),} +(name:'Flip object ';attrib:0;keycode:0;command:0;submenu:@flipmenu;extratext:'>'), +(name:'Polygons ';attrib:0;keycode:0;command:0;submenu:@PolyFunctions;extratext:'>')); + +Windowinfo:array[0..2] of tmenuitem_=( +({name:'Tile';attrib:0;keycode:0;command:CMDtilewindows;submenu:nil), +(name:'Cascade';attrib:0;keycode:0;command:CMDcascade;submenu:nil),} + name:'Grid ';attrib:MoptToggler;keycode:0;command:CMDtogglegrid;submenu:nil;extratext:'þÿG ';toggleref:@grid_on), +(name:'Default pal';attrib:0;keycode:0;command:CMDsetdefaultpal;submenu:nil), +(name:'Save pal...';attrib:0;keycode:0;command:CMDsavepaldialog;submenu:nil)); + +Renderinfo:array[0..5] of tmenuitem_=( +(name:'Dots ';attrib:0;keycode:0;command:CMDDots;submenu:nil;extratext:'[1]'), +(name:'Lines ';attrib:0;keycode:0;command:CMDlines;submenu:nil;extratext:'[2]'), +(name:'Hidden lines ';attrib:0;keycode:0;command:CMDHlines;submenu:nil;extratext:'[3]'), +(name:'Flat shaded ';attrib:0;keycode:0;command:CMDlsource;submenu:nil;extratext:'[4]'), +(name:'Smooth shaded ';attrib:0;keycode:0;command:CMDgouraud;submenu:nil;extratext:'[5]'), +(name:'By Attribute ';attrib:0;keycode:0;command:CMDCpolygons;submenu:nil;extratext:'[6]')); + +StdWindowinfo:array[0..2]of tmenuitem_=( +(name:'Centre [Home]';attrib:0;keycode:0;command:CMDcentrewindow;submenu:nil), +(name:'';attrib:moptseperator;keycode:0;command:0;submenu:nil), +(name:'Save Window';attrib:0;keycode:0;command:CMDsavewin;submenu:nil)); + +windowinfo3d:array[0..3] of tmenuitem_=( +(name:'Centre [Home]';attrib:0;keycode:0;command:CMDcentrewindow;submenu:nil), +(name:'Reset 3d [TAB]';attrib:0;keycode:0;command:CMDreset3dvalues;submenu:nil), +(name:'';attrib:moptseperator;keycode:0;command:0;submenu:nil), +(name:'Render depth >';attrib:0;keycode:0;command:CMDredrawobject3d;submenu:@rendermenu)); + +titleinfo:array[0..5] of tmenuitem_=( +(name:chr(9);attrib:0;keycode:0;command:0;submenu:@miscmenu), +(name:'File';attrib:0;keycode:0;command:0;submenu:@filemenu), +(name:'Draw';attrib:0;keycode:0;command:0;submenu:@editmenu), +(name:'Select';attrib:0;keycode:0;command:0;submenu:@selectmenu), +(name:'Text';attrib:0;keycode:0;command:0;submenu:@textmenu), +(name:'Window';attrib:0;keycode:0;command:0;submenu:@windowmenu)); + +Extentions:array[0..10]of string[5]=('*.3D','*.RWX','*.POV','*.OBJ','*.GEO','*.WRL','*.PLG','*.ASC','*.GOR','*.COB','*.JAV'); + + +icons:array[0..11,0..31]of byte=( +(0,0,8,0,12,0,14,0,15,0,15,128,15,192,15,224,15,240,15,248,15,128,13,192,8,192,0,96,0,96,0,0), +(0,0,0,0,63,252,32,4,32,4,32,4,32,4,32,4,32,4,32,4,32,4,32,4,32,4,32,4,63,252,0,0), +(0,128,3,224,15,248,63,254,127,175,127,93,94,177,107,193,85,129,106,129,85,129,42,129,85,134,10,152,5,224,0,128), +(0,0,0,0,0,0,0,0,0,0,0,0,3,192,2,64,2,64,3,192,0,0,0,0,0,0,0,0,0,0,0,0), +(0,0,0,30,0,18,0,18,0,30,0,32,0,64,0,128,1,0,2,0,4,0,120,0,72,0,72,0,120,0,0,0), +(0,128,1,64,1,192,3,32,2,160,7,16,6,144,15,8,14,136,29,4,30,132,61,2,62,130,63,4,30,152,3,224), +(0,0,0,0,3,192,12,48,16,8,32,4,32,4,64,2,64,2,64,2,32,4,32,4,16,8,12,48,3,192,0,0), +(7,240,24,12,32,2,56,14,63,242,61,2,62,2,61,2,62,2,61,2,62,2,61,2,62,2,61,4,30,24,7,240), +(0,0,7,240,31,184,63,196,127,234,127,194,255,169,255,192,191,169,213,0,170,161,64,0,74,2,32,4,24,8,6,160), +(0,0,1,0,10,0,21,0,26,64,31,96,31,240,31,248,31,252,31,254,31,252,15,248,7,240,0,96,0,64,0,0), +(0,0,0,0,63,254,36,146,36,146,63,254,36,146,36,146,63,254,36,146,36,146,63,254,36,146,36,146,63,254,0,0), +(0,0,0,0,127,254,97,134,65,130,1,128,1,128,1,128,1,128,1,128,1,128,1,128,1,128,1,128,7,224,0,0) +); + +iconsattr:array[0..11] of byte=(oneon+1,oneon,oneon,oneon,oneon,oneon,oneon,oneon,oneon,oneon,oneon,oneon); +iconscommands:array[0..11] of word=( +CMDeditselect,CMDeditsquare,CMDeditcube, +CMDeditDot,CMDeditLiner,CMDeditcone,CMDeditCircle,CMDeditCylinder, +CMDeditSphere,CMDeditRotate,CMDeditgrid,CMDedittext); + +Icons2:array[0..5,0..31] of byte=( +(0,0,7,128,8,64,22,32,20,32,16,32,16,32,8,96,7,240,0,56,12,28,12,14,63,6,63,0,12,0,12,0), +(0,0,7,128,8,64,22,32,20,32,16,32,16,32,8,96,7,240,0,56,0,28,0,14,63,6,63,0,0,0,0,0), +(0,0,169,98,173,85,171,85,73,98,0,0,0,0,6,0,12,0,31,210,63,232,31,210,12,0,6,0,0,0,0,0), +(0,0,3,192,7,224,14,112,12,48,12,48,12,48,31,248,31,0,30,136,31,0,30,136,31,0,30,136,31,240,0,0), +(0,0,3,192,3,192,7,224,0,0,0,0,3,192,2,64,2,64,3,192,0,0,0,0,0,0,3,192,7,224,0,0), +(0,0,96,6,112,14,56,30,28,60,6,112,3,192,1,128,3,192,6,96,12,48,28,24,56,12,112,14,48,6,0,0)); +icons2attr:array[0..5] of byte=(nostick,nostick,nostick,onoff,1+onoff,nostick); +icons2commands:array[0..5] of word=(CMDzoomin,CMDzoomout,CMDundo,CMDtogglegridFROMICON,CMDtoggleNodesFROMICON,CMDnewbox); + + + +altletters:array[0..31]of byte=(0,127,128,146,170,170,170,186,170,171,128,127,0,0,0,0,0, + 252,2,58,18,18,18,18,18,210,2,252,0,0,0,0); +ctrlletters:array[0..31]of byte=(0,127,128,159,162,162,162,162,162,154,128,127,0,0,0,0,0, + 254,1,201,169,169,201,169,169,173,1,254,0,0,0,0); + +fin:boolean=false; +{Loadobject_dialog:file_dialog=nil; +Saveobject_dialog:file_dialog=nil; +appendobject_dialog:file_dialog=nil; +loadfont_dialog:file_dialog=nil;} +loadobjectPID=1; +saveobjectPID=2; +appendobjectPID=3; +loadfontPID=4; +quitPID=5; +destroyPID=6; +infoPID=7; +helpPID=8; +dselectPID=9; +selectsomePID=10; +overwritePID=11; +notyetimpPID=12; +filenotfoundPID=14; +copyrightPID=16; +PerspectivePID=1534; +SurfacePID=1535; +PIDambient=1536; +PIDdiffuse=1537; +PIDspecular=1538; +PIDtransparency=1539; +PIDcolourbar=1640; + +filemode:word=CMD3dfile; + +{****----Global Variables----****} +var + +lgroupoffset:integer; {for the start of the right angle in l groups} +GraphInstalled:boolean; +dorth:delta_orth; +PerspectiveINT:longint; +font_path,clay_dir:string[80]; +textfile,helpfile,registerfile,objectinfo:pchar; +varFontpath,varobjectpath,exepath:string; +lop:word; +draw_object:edit_objtype; +application:Clay; +backview:tview; +status:statusviewb; + +function getobjectinfo:pchar; + +begin + + objectinfo^:=#0; + tstrcat_pascal(objectinfo,'Polygon count:'); + + pitoa(draw_object^.maxpolys,objectinfo); + charcat(objectinfo,#13); + tstrcat_pascal(objectinfo,'vertex count:'); + pitoa(draw_object^.maxpoints,objectinfo); + + charcat(objectinfo,#13); + tstrcat_pascal(objectinfo,'Join count:'); + pitoa(draw_object^.maxjoins,objectinfo); + + charcat(objectinfo,#13); + tstrcat_pascal(objectinfo,'Selected vertex count:'); + pitoa(draw_object^.maxselect,objectinfo); + + + {strcat(objectinfo,pitoa(200,tmp)); + strcat(objectinfo,#13);} + + getobjectinfo:=objectinfo; +end; + +constructor Clay_.create(xa,ya,xb,yb:integer); +var + lop:byte; + xsize,ysize:integer; +begin + inherited create(xa,ya,xb,yb); + + flipmenu.create(0,0,@flipinfo,3,3,menupopup); + {rotatemenu.create(0,0,@rotateinfo,3,3,menupopup);} + FileTypeMenu.create(0,0,@FileTypeinfo,10,3,menupopup); + miscmenu.create(0,0,@miscinfo,4,3,menupopup); + filemenu.create(0,0,@fileinfo,8,3,menupopup); + editmenu.create(0,0,@editinfo,14,3,menupopup); + selectmenu.create(0,0,@selectinfo,9,3,menupopup); + textmenu.create(0,0,@textinfo,1,3,menupopup); + windowmenu.create(0,0,@windowinfo,3,3,menupopup); + + stdwinmenu.create(0,0,@stdwindowinfo,3,3,menupopup); + winmenu3d.create(0,0,@windowinfo3d,4,3,menupopup); + rendermenu.create(0,0,@renderinfo,6,3,menupopup); + PolyFunctions.create(0,0,@PolyFunctionsinfo,7,3,menupopup); + PolyAttribFunctions.create(0,0,@PolyAttribFunctionsInfo,6,3,menupopup); + + for lop:=0 to 2 do + edviews[lop]:=new(delta_orth,make(lop,draw_object)); + edviews[3]:=new(delta_3d,make(draw_object)); + dorth:=pointer(edviews[0]); + + desktop:=new(Desktoptype,create(60,vbord+fontheight+10,x2,y2)); + with desktop^ do begin + options:=options or OfKeyGrab ; + insert(new(background,create(x1,y1,x2,y2,darkblue,15,midgreyfill))); + {insert(new(backpic,create(x1,y1,x2,y2,readpcx('c:\bitmap\pics\pcx\webb.pcx'))));} + backview:=pointer(first); + status:=new(statusviewb,create(80,60,200,160)); + status^.val1:=@scan; + insert(status); + {insert(new(RotationControl,create(100,100)));} + xsize:=halfx-(vpindent shl 1); + ysize:=halfy-(vpindent shl 1); + + insert(new(windowtype,create(x1+vpindent,y1+vpindent,xsize,ysize, 'Front', + edviews[zaxis],@stdwinmenu))); + insert(new(windowtype,create(vpindent+x2-halfx,y1+vpindent,xsize,ysize,'Side', + edviews[xaxis],@stdwinmenu))); + insert(new(windowtype,create(x1+vpindent,y1+(vpindent shl 1)+halfy-3,xsize,ysize,'Plan', + edviews[yaxis],@stdwinmenu))); + insert(new(windowtype,create(vpindent+x2-halfx,y1+(vpindent shl 1)+halfy-3,xsize,ysize,'Perspective', + edviews[view_3d],@winmenu3d))); + {insert(new(surfacedialog,create(60,60)));} + end; + options:=options or (ofnooverlap+ofkeygrab); + insert(desktop); + insert(new(tmenubar,create(0,0,@Titleinfo,6,2,menuxorient))); + lgroupoffset:=first^.width-59; + + ModeOptionsPtrs[0]:=New(SelectOptions,create); + ModeOptionsPtrs[1]:=New(Lgroup,create('Square')); + ModeOptionsPtrs[2]:=New(Lgroup,create('Cube')); + ModeOptionsPtrs[3]:=New(Lgroup,create('Dot')); + ModeOptionsPtrs[4]:=New(Lgroup,create('Line')); + ModeOptionsPtrs[5]:=New(CircOptions,create('Cone',@conesize)); + ModeOptionsPtrs[6]:=New(CircOptions,create('Circle',@circsize)); + ModeOptionsPtrs[7]:=New(CircOptions,create('Cylinder',@cylindersize)); + ModeOptionsPtrs[8]:=New(SphereOptions,create(@spheresize)); + ModeOptionsPtrs[9]:=New(RotateOptions,create('Rotated form',@rotsize)); + ModeOptionsPtrs[10]:=New(GridOptions,create); + ModeOptionsPtrs[11]:=New(TextEditDialog,create); + ModeOptions:=new(Tgroup,create(60,0,x2,vbord+25)); + with ModeOptions^ do begin + Options:=Options or (OfKeyGrab); + for lop:=11 downto 0 do + insert(ModeOptionsPtrs[lop]); + end; + + + insert(ModeOptions); + insert(new(Textbutton,create(x1+5,y1+210,50,20,13,1,BM_releaseaction,1,CMDCallSurfaceDialog,'Poly>'))); + iconpanel:=new(iconpaneltype,Create(0,48,3,4,20,20,@icons,@iconsattr,@iconscommands)); + insert(iconpanel); + subpanel:=new(iconpaneltype,Create(0,140,3,2,20,20,@icons2,@icons2attr,@icons2commands)); + coords:=new(coordbox,create(3,y2-46,55,y2-5)); + coords^.coord:=crs; + insert(coords); + + insert(subpanel); + insert(new(RotationControl,create(3,y2-200))); +end; + +procedure clay_.handlevent(var event:tevent); +var filenotfound:boolean; + send_command:word; + tmprect:trect; + transmatrix:matrix3x4type_; + tx,ty:integer; + Coordval:vectorreal; + +begin + inherited handlevent(event); + with event,draw_object^ do + case what of + EvCommand:begin + filenotfound:=false; + case command of + {**********-----Creation/editing commands-----***********} + CMDautocopyselected:dorth^.DoCommand(command,@autocopymatrix,divisionsize); + RANGEextcomSTART..RANGEextcomEND:Dorth^.DoCommand(command,nil,0); + CMDload3dfile,CMDappend3dfile:with file_dialog(infoptr)^,texteditbox^ do begin + varobjectpath:=Sdir; + if fexist(txt) then + dorth^.docommand(command,@txt,filemode) + else + filenotfound:=true; + end; + CMDsave3dfile:if name<>'' then + dorth^.docommand(command,@name,filemode) + else first^.evcallback(CMDsaveasdialog); + {**********-----desktop commands-----***********} + CMDeditselect..CMDedittext:begin + drawing_mode:=command; + dec(drawing_mode,CMDeditselect); + {set new drawing mode, change dialog bar at top of screen} + if drawing_mode<=11 then begin + with ModeOptionsptrs[drawing_mode]^ do + putinfrontof(owner^.first); + {make sure this doesn't recall this code} + if (command=CMDedittext) and (not vfontin) then + addmessage(0,CMDloadfontdialog,'You must load in a Font before using this tool.',fontmessagePID,desktop); + with IconPanel^ do begin + state:=state or sfmute; + iconpanel^.seticon(drawing_mode); + state:=state xor sfmute; + end; + end; + inc(drawing_mode,CMDeditselect); + end; + CMDcallsurfacedialog: + desktop^.add_and_draw(new(surfacedialog,create(0,0)),VPcentre,surfacePID); + CMDtogglenodesFROMICON:begin + drawallnodes:=drawallnodes xor true; + if drawallnodes=true then + what_to_draw:=draw_orthnodes; + draworth; + what_to_draw:=draw_all; + end; + CMDtogglenodes:begin + {make sure this doesn't recall this code} + with SubPanel^ do begin + state:=state or sfmute; + seticon(4); + state:=state xor sfmute; + end; + drawallnodes:=drawallnodes xor true; + if drawallnodes=true then + what_to_draw:=draw_orthnodes; + draworth; + + what_to_draw:=draw_all; + end; + CMDstickymouse: + stickymouse:=stickymouse xor true; + + CMDdeleteselectdialog: + AddMessage(CMDcancel,CMDdeleteselect,'Are you sure want to delete that selection?',dselectPID,desktop); + + CMDtogglegrid:begin + {make sure this doesn't recall this code} + with SubPanel^ do begin + state:=state or sfmute; + seticon(3); + state:=state xor sfmute; + end; + grid_on:=grid_on xor true; + gridlock:=gridlock xor true; + draworth; + end; + CMDtogglegridFROMICON:begin + grid_on:=grid_on xor true; + gridlock:=gridlock xor true; + draworth; + end; + CMDgetobjectinfo: + desktop^.add_and_draw(new(infodialog,create(0,0,300,300,getobjectinfo,false)),VPcentre,infoPID); + CMDinfo: + desktop^.add_and_draw(new(infodialog,create(0,0,300,300,textfile,false)),VPcentre,infoPID); + CMDcallhelp:begin + helpfile:=loadtext(clay_dir+'help.txt'); + desktop^.add_and_draw(new(infodialog,create(0,0,400,270,helpfile,true)),VPcentre,helpPID); + end; + + CMDnewbox:if maxpoints>0 then + AddMessage(CMDcancel,CMDnew,'Are you sure you want to destroy the Object?',destroyPID,desktop); + CMDfilemode_start..CMDfilemode_end:FileMode:=Command; + CMDsave3dfileornot:begin + varobjectpath:=file_dialog(infoptr)^.Sdir; + name:=file_dialog(infoptr)^.texteditbox^.txt; + if fexist(name) then + Addmessage(CMDcancel,CMDsave3dfile,'Are you sure you want to overwrite the file?',overwritePID,desktop) + else + sendCommand(CMDsave3dfile,@self,nil); + end; + + CMDloadfont:with file_dialog(infoptr)^,texteditbox^ do begin + varfontpath:=Sdir; + if fexist(txt) then begin + vfontin:=vfont.load(txt); + if not vfontin then + AddMessage(0,0,'Error in file.',fileerrorPID,desktop); + end else + filenotfound:=true; + if (vfontin) and (drawing_mode=CMDedittext) then + SendCommand(CMDedittext,@self,nil); + end; + CMDloadheightmap: + with file_dialog(infoptr)^,texteditbox^ do begin + if fexist(txt) then begin + if gridpic<>nil then + destroybitmap(gridpic); + gridpic:=readpcx(txt,PAflat); + end else + filenotfound:=true; + end; + + CMDloadfontDialog: + desktop^.add_and_draw(new(file_dialog,create(0,0,CMDcancel,CMDloadfont, + 'Load font',varfontpath,'*.chr',application)),VPcentre,loadfontPID); + CMDappend: + desktop^.add_and_draw(new(file_dialog,create(0,0,CMDcancel,CMDappend3dfile, + 'Append 3d file',varobjectpath,'*.3d',application)),VPcentre,appendobjectPID); + CMDloaddialog:if (filemode<>CMDPOVfile) and + (filemode<>CMDVRMLfile) and (filemode<>CMDPLGfile) then + desktop^.add_and_draw(new(file_dialog,create(0,0,CMDcancel,CMDload3dfile, + 'Load 3d file',varobjectpath,Extentions[FileMode-CMD3dfile],application)),VPcentre,loadobjectPID) + + else + AddMessage(0,0,'Sorry, Not yet implemented.',notyetimpPID,desktop); + CMDsaveasdialog: + desktop^.add_and_draw(new(file_dialog,create(0,0,CMDcancel,CMDsave3dfileornot, + 'save 3d file',varobjectpath,Extentions[FileMode-CMD3dfile],application)),VPcentre,saveobjectPID); + + + CMDrefresh:begin t_fillcol:=0;cleardevice;drawview;end; + CMDexitbox:AddMessage(CMDcancel,CMDexit,'Are you sure you want to Leave?',quitPID,desktop); + CMDexit:fin:=true; + CMDzoomin: setscale(scale*1.05); + CMDzoomout: setscale(scale/1.05); + CMDsetdefaultpal:setpal(@pal16,0,15); + CMDsavepaldialog:desktop^.add_and_draw(new(file_dialog,create(0,0,CMDcancel,CMDsavepal, + 'Save Colour Palette',gtdir,'*.pal',application)),VPcentre,loadfontPID); + CMDsavepal:with file_dialog(infoptr)^,texteditbox^ do begin + {getpal(claypal); + savepalpas(txt,claypal);} + end; + CMDselectedittext:begin + TextEditdialog(ModeOptionsPtrs[11])^.TextEditBox^.Select; + stoprepeat; + end; + {for the drawn coordinates} + CMDsetcoords:begin + with delta_orth(infoptr)^ do begin + tx:=xm;ty:=ym; + localspace(tx,ty); + conv2d_3d(orientation,tx,ty,@crs,@coords^.coord); + coords^.drawview; + end; + end; + + + + {CMDtilewindows,CMDcascade,CMDprint,CMDsavewin:AddMessage(CurrMessage,0,0,'Not yet implemented.');} + end; + if filenotfound then + AddMessage(0,0,'Sorry, the file was not found.',filenotfoundPID,desktop); + + end; + + evkeydown:begin + case charcode of + '+':SendCommand(CMDzoomin,@self,nil); + '-':SendCommand(CMDzoomout,@self,nil); + #242:Addmessage(0,0,'ClayWorks V2.45, C T.Lewis 1993-1995',copyrightPID,desktop); + #8:SendCommand(CMDdeletepolys,@self,nil); + #127:SendCommand(CMDdeletelines,@self,nil); + end; + if boolean(scan and smLEFTCTRL) then case charcode of + {'s','S':RotationStepSel^.drawview;} + #19:SendCommand(CMDeditselect,@self,nil); + #17:SendCommand(CMDeditsquare,@self,nil); + #3:SendCommand(CMDeditcube,@self,nil); + #4:SendCommand(CMDeditdot,@self,nil); + #12:SendCommand(CMDeditliner,@self,nil); + #15:SendCommand(CMDeditcone,@self,nil); + #9:SendCommand(CMDeditcircle,@self,nil); + #18:SendCommand(CMDeditcylinder,@self,nil); + #16:SendCommand(CMDeditSphere,@self,nil); + {'H','h':SendCommand(CMDeditrotate,@self,nil);} + #7:SendCommand(CMDeditgrid,@self,nil); + #20:SendCommand(CMDedittext,@self,nil); + #21:SendCommand(CMDundo,@self,nil); + #24:SendCommand(CMDFlipX,@self,nil); + #25:SendCommand(CMDFlipY,@self,nil); + #26:SendCommand(CMDFlipZ,@self,nil); + end; + case scancode of + 36:SendCommand(CMDselectall,@self,nil); + 20:SendCommand(CMDTriangulate,@self,nil); + 16:SendCommand(CMDQuadDivide,@self,nil); + 46:SendCommand(CMDautocopyselected,@self,nil); + 38:SendCommand(CMDselectclear,@self,nil); + 49:SendCommand(CMDtogglenodes,@self,nil); + 30:SendCommand(CMDapplyColour,@self,nil); + 21:SendCommand(CMDaddpolygon,@self,nil); + 31:SendCommand(CMDmksinglesided,@self,nil); + 33:SendCommand(CMDflipnorms,@self,nil); + 47:SendCommand(CMDmksmooth,@self,nil); + 24:SendCommand(CMDmkflat,@self,nil); + 48:SendCommand(CMDmkDoublesided,@self,nil); + 59:SendCommand(CMDcallhelp,@self,nil); + 107:SendCommand(CMDexitbox,@self,nil); + 106:SendCommand(CMDsaveasdialog,@self,nil); + 104:SendCommand(CMDnew,@self,nil); + 105:SendCommand(CMDloaddialog,@self,nil); + 108:SendCommand(CMDsave3dfile,@self,nil); + 109:SendCommand(CMDappend,@self,nil); + 34:subpanel^.seticon(3); + 130:subpanel^.seticon(0); + 131:subpanel^.seticon(1); + 83:SendCommand(CMDdeleteselectdialog,@self,nil); + + 50:Sendcommand(CMDMerge,@self,nil); + end; + end; + end; +end; + +procedure clay_.draw; +begin + {insert(new(panelback,create(0,20,59,y2)));} + outbox(x1,y1+vbord+5,x1+59,y1+47); + Outtextxy3d(x1+5,y1+30,'Shapes'); + inbox(x1,y1+127,x1+59,y1+139); + inbox(x1,y1+179,x1+59,y2); + t_col:=darkcol; + vline(x1+59,y1+20,y2); + outtextxy3d(x1+5,y2-64,'Coords'); + inherited draw; +end; + +procedure coordbox_.draw; +begin + textboxfilled(x1,y1,x2,y2); + t_col:=textcol; + outtextxy(x1+2,y1+2,ftoa(coord.x,1,1)); + outtextxy(x1+2,y1+14,ftoa(coord.y,1,1)); + outtextxy(x1+2,y1+26,ftoa(coord.z,1,1)); +end; + +Constructor SurfaceDialog_.create(xa,ya:integer); +begin + inherited create(xa,ya,xa+250,ya+220); + options:=options or (ofnooverlap+ofkeygrab+oftopselect); + inc(y1,vbord); + insert(new(Tbutton,create(x1+5,y1+10,8,8,midcol,1,BM_toggleaction,CMDtoggleAbsolute,0))); + insert(new(Tbutton,create(x1+halfx,y1+10,8,8,midcol,1,BM_toggleaction,CMDtoggleoutline,0))); + insert(new(Tbutton,create(x1+5,y1+30,8,8,midcol,1,BM_toggleaction,CMDtogglesmooth,0))); + insert(new(Tbutton,create(x1+halfx,y1+30,8,8,midcol,1,BM_toggleaction,CMDtoggledoubleSided,0))); + insert(new(Textbutton,create(x2-65,y1+45,60,20,midcol,1,BM_releaseaction,2,CMDApplyAttrib,'Apply'))); + insert(new(Textbutton,create(x2-65,y2-25,60,20,midcol,1,BM_releaseaction,1,CMDdismisview,'Dismis'))); + insert(new(Textbutton,create(x2-66,y2-55,61,20,midcol,1,BM_releaseaction,1,CMDApplyColour,'Apply'))); + insert(new(Textbutton,create(x2-150,y2-25,80,20,midcol,1,BM_releaseaction,4,CMDApplyAttribandColour,'Apply All'))); + + insert(new(colourgridtype,create(x2-65,y2-120,11,15,4,4,@fgtexture,@bktexture,desktop))); + colourgridptr:=colourgridtype(first); + insert(new(bartype,create(x2-21,y2-120,scrollbar_size,61,0,252,0,ybardir))); + tgroup(first)^.last^.PID:=PIDcolourbar; + insert(new(bartype,create(x1+100,y2-120,scrollbar_size,61,0,63,0,ybardir))); + tgroup(first)^.last^.PID:=PIDdiffuse; + insert(new(bartype,create(x1+120,y2-120,scrollbar_size,61,0,63,0,ybardir))); + tgroup(first)^.last^.PID:=PIDambient; + insert(new(bartype,create(x1+140,y2-120,scrollbar_size,61,0,63,0,ybardir))); + tgroup(first)^.last^.PID:=PIDspecular; + insert(new(bartype,create(x1+160,y2-120,scrollbar_size,61,0,63,0,ybardir))); + tgroup(first)^.last^.PID:=PIDtransparency; + dec(y1,vbord); + add_title(@self,'Surface Attributes'); +end; + +Procedure SurfaceDialog_.handlevent(var event:tevent); +begin + inherited handlevent(event); + with event do + case what of + EVcommand: + case command of + CMDdismisview:delete; + CMDmoveparent:dragview(1,owner^,0,0,1000,1000); + CMDtoggleDoubleSided:CurrAttrib:=CurrAttrib xor PaDoubleSided; + CMDtoggleSmooth:CurrAttrib:=CurrAttrib xor PaSmooth; + CMDtoggleOutline:CurrAttrib:=CurrAttrib xor PaOutlined; + CMDtoggleAbsolute:CurrAttrib:=CurrAttrib xor PaAbsolute; + CMDvalchanged:begin + case infotview^.PID of + PIDcolourbar:colourgridptr^.handlevent(event); + PIDtransparency:; + end; + end; + CMDcolourchanged:begin + fgtexture:=colourgridptr^.fgcol^; + bktexture:=colourgridptr^.bgcol^; + end; + CMDapplyattrib,CMDapplycolour,CMDapplyattribandColour: + dorth^.docommand(Command,nil,0); + end; + EVkeydown:; + end; +end; + +procedure SurfaceDialog_.draw; +begin + inc(y1,vbord); + outbox(x1,y1,x2,y2); + t_col:=disabledcol; + outtextxy(x1+17,y1+7,'Abs. Colour'); + outtextxy(x1+17,y1+27,'Smooth Shaded'); + outtextxy(x1+halfx+13,y1+7,'OutLined'); + outtextxy(x1+halfx+12,y1+27,'Double Sided'); + outtextxy(x1+102,y2-55,'D'); + outtextxy(x1+122,y2-55,'A'); + outtextxy(x1+142,y2-55,'S'); + outtextxy(x1+162,y2-55,'O'); + + t_col:=lightcol; + vline(x2-66,y2-120,y2-59); + hline3d(x1+5,x2-5,y1+68); + t_col:=lightcol; + hline3d(x1+5,x2-5,y2-30); + dec(y1,vbord); + inherited draw; +end; + +{destructor Surfacedialog_.done; +begin + +end;} + + + + +constructor RotationControl_.create(xa,ya:integer); +const bsize=3; + ynumsel=28; + +var ytotal,ysize,xsize:integer; +begin + inherited create(xa,ya,xa+54,ya+90); + step:=3; + options:=options or (oftopselect+ofnooverlap); + + insert(new(bordertype,create(x1,y1,x2,y2,bsize))); + inc(x1,bsize);inc(y1,bsize);dec(x2,bsize);dec(y2,bsize); + ysize:=((y2-y1-vbord-ynumsel)div 2)-1; + ytotal:=y1; + xsize:=(x2-x1); + + {insert(new(textbutton,create(x1,ytotal,xsize,vbord, + titlecol,0,BM_periodaction,0,CMDmoveparent,'3d'))); + inc(ytotal,vbord+1);} + insert(new(textbutton,create(x1,ytotal,xsize,ysize, + midcol,0,BM_periodaction,1,CMDxrot,'X Rot'))); + inc(ytotal,ysize+1); + insert(new(textbutton,create(x1,ytotal,xsize,ysize, + midcol,0,BM_periodaction,1,CMDyrot,'Y Rot'))); + inc(ytotal,ysize+1); + insert(new(textbutton,create(x1,ytotal,xsize,ysize, + midcol,0,BM_periodaction,1,CMDzrot,'Z Rot'))); + {inc(ytotal,ysize+1); + insert(new(numsel,create(x1,ytotal,xsize,ysize,11, + 100,1000,@perspectiveINT))); + set the 'numbox' to have that PID + tgroup(first)^.last^.PID:=PerspectivePID;} + inc(ytotal,ysize+1); + insert(new(numsel,create(x1,ytotal,xsize,y2-ytotal,8, + -64,64,@step))); + + dec(x1,bsize);dec(y1,bsize);inc(x2,bsize);inc(y2,bsize); +end; + +procedure RotationControl_.handlevent(var event:tevent); +var +rotateby:vectorreal; +val:real; +begin + inherited handlevent(event); + val:=step; + with event do + case what of + Evcommand: + with draw_object^ do case command of + CMDmoveparent:dragview(1,owner^,0,0,1000,1000); + CMDxrot,CMDyrot,CMDzrot: begin + case command of + CMDxrot:rotateby.moveto(val/180,0,0); + CMDyrot:rotateby.moveto(0,val/180,0); + CMDzrot:rotateby.moveto(0,0,val/180); + end; + SendCommand(CMDrotate,edviews[3],@rotateby); + end; + {CMDvalchanged:if infotgroup^.last^.PID=PerspectivePID then begin + pers:=perspectiveINT; + edviews[3]^.drawview + end;} + end; + end; +end; + +Constructor TextEditDialog_.create; +const W=270;H=Vbord+10+Fontheight+(edit_indentY shl 1); +begin + inherited create('3d Text'); + options:=options or (ofnooverlap+oftopselect); + texteditbox:=new(edittexttype,create(x1+185,y1+5,editstring,255,28)); + insert(texteditbox); +end; + +Procedure TextEditDialog_.handlevent(var event:tevent); +begin + if @self=owner^.first then begin + inherited handlevent(event); + with event do + case what of + EvCommand: + case command of + CMDEditstringaltered: + EditString:=Texteditbox^.txt; + end; + EvKeyDown: + if scancode=20 then texteditbox^.select; + end; + end; +end; + +var +selectmodes:tpopupmenu_; + +Constructor SelectOptions_.create; +const +{selectmodestitleinfo:array[0..0] of tmenuitem_=( +(name:'Manip. Modes '+chr(25); attrib:moptbutton;keycode:0; command:0; submenu:@selectmodes)); +selectmodesinfo:array[0..1] of tmenuitem_=( +(name:'Move/Resize '; attrib:0;keycode:0; command:SMresize_repos; submenu:nil), +(name:'Rotate '; attrib:0;keycode:0; command:SMrotate; submenu:nil) +);} + + +selmodeicons:array[0..1,0..31] of byte=((1,0,1,0,1,0,1,0,1,0,7,192,4,64,4,126,4,64,7,192,8,0,16,0,32,0,64,0,0,0,0,0), +(0,0,24,112,24,136,37,68,37,164,67,20,66,12,131,28,130,168,102,72,26,72,2,72,1,80,0,224,0,64,0,0)); + +selmodeiconsattr:array[0..1] of byte=(oneon+1,oneon); +selmodeiconscommands:array[0..1] of word=(SMnodal,SMobjects); +selicons:array[0..2,0..31] of byte= +((0,0,0,128,1,192,3,224,1,192,1,64,17,68,63,126,120,15,63,126,17,68,1,64,1,192,3,224,1,192,0,128), +(0,0,3,192,15,240,31,248,60,60,56,28,112,14,112,14,112,14,113,14,57,156,63,200,31,224,15,192,1,128,1,0), +(0,0,3,128,7,192,2,128,1,0,7,192,3,128,3,128,3,128,3,128,6,128,12,128,8,128,8,128,24,192,0,0) +); +seliconsattr:array[0..2] of byte=(oneon+1,oneon,oneon); +seliconscommands:array[0..2] of word=(SMresize_repos,SMrotate,SMdeform); + +extrudeicons:array[0..0,0..31] of byte=( +(0,0,0,0,3,254,4,6,8,10,16,18,63,226,32,34,32,34,32,34,32,34,32,36,32,40,32,48,63,224,0,0)); +extrudeiconsattr:array[0..0] of byte=(onoff); +extrudeiconscommands:array[0..0] of word=(CMDToggleExtrude); + +begin + inherited create('Select: Move/Resize'); + options:=options or (ofnooverlap+oftopselect); + + {{files:=new(listwbar,create(x1+10,y2-168,110,117,list,listcount,3,true));} + {selectmodes.create(0,0,@selectmodesinfo,2,2,0); + insert(new(tmenubar,create(x1+183,y1+2,@selectmodestitleinfo,1,2,menuindent+menuxorient))); + insert(new(textbutton,create(x1+308,y1+5,76,20,titlecol,1,BM_toggleaction,1,CMDToggleExtrude,'Extrude'))); + tbutton(first)^.dstate:=byte(Extrude);} + insert(new(iconpaneltype,Create(x1+187,y1+6,3,1,20,20,@selicons,@seliconsattr,@seliconscommands))); + + insert(new(iconpaneltype,Create(x1+287,y1+6,2,1,20,20,@selmodeicons,@selmodeiconsattr,@selmodeiconscommands))); + insert(new(iconpaneltype,Create(x1+256,y1+6,1,1,20,20,@extrudeicons,@extrudeiconsattr,@extrudeiconscommands))); + insert(new(numsel,create(x1+389,y1+6,55,16,8,1,30,@DivisionSize))); +end; + +Procedure SelectOptions_.handlevent(var event:tevent); +begin + inherited handlevent(event); + with event do + case what of + EvCommand: + case command of + CMDToggleExtrude:Extrude:=Extrude xor true; + {CMDToggleConnect:PolyConnect:=PolyConnect xor true;} + SMnodal,SMobjects:selectmodelevel:=command; + + + SMbegin..SMend:begin + if selected_mode<>command then begin + what_to_draw:=draw_boundingboxstuff; + drawobject; + selected_mode:=command; + drawobject; + what_to_draw:=draw_all; + case command of + SMresize_repos:name:='Select: Move/Resize'; + SMrotate:name:='Select: Rotate'; + SMdeform:name:='Select: Deform'; + end; + SC.viewport.rassign(x1+69,y1,x1+160,y2); + drawview; + SC.viewport:=SC.screenport; + end; + end; + end; + end; +end; + +Procedure SelectOptions_.draw; +begin + inherited draw; + t_col:=disabledcol; + outtextxy(x1+392,y1+26,'Copies'); +end; + +Constructor SphereOptions_.create(size:pointtypeptr); +begin + inherited create('Sphere'); + insert(new(numsel,create(x1+193,y1+18,56,16,8,3,60,@size^.x))); + insert(new(numsel,create(x1+252,y1+18,56,16,8,3,60,@size^.y))); +end; + +Procedure SphereOptions_.draw; +begin + inherited draw; + t_col:=disabledcol; + outtextxy(x1+193,y1+2,'Number of Segments'); +end; + +Procedure SphereOptions_.handlevent(var event:tevent); +begin + inherited handlevent(event); + {with event do + case what of + EvCommand: + case command of + end; + end;} +end; + + +Constructor CircOptions_.create(name_:string;data:pointer); +begin + inherited create(name_); + insert(new(numsel,create(x1+193,y1+18,56,16,8,3,60,data))); +end; + +Procedure CircOptions_.draw; +begin + inherited draw; + t_col:=disabledcol; + outtextxy(x1+193,y1+2,'Number of Segments:'); +end; + +Procedure CircOptions_.handlevent(var event:tevent); +begin + inherited handlevent(event); + {with event do + case what of + EvCommand: + case command of + end; + end;} +end; + +Constructor RotateOptions_.create(name_:string;data:pointer); +begin + inherited create(name_); + insert(new(numsel,create(x1+193,y1+18,56,16,8,3,30,data))); + insert(new(textbutton,create(x1+270,y1+18,20,20,midcol,1,BM_releaseaction,1,CMDrotatedformX,'X'))); + insert(new(textbutton,create(x1+292,y1+18,20,20,midcol,1,BM_releaseaction,1,CMDrotatedformY,'Y'))); + insert(new(textbutton,create(x1+314,y1+18,20,20,midcol,1,BM_releaseaction,1,CMDrotatedformZ,'Z'))); +end; + +Procedure RotateOptions_.draw; +begin + inherited draw; + t_col:=disabledcol; + outtextxy(x1+193,y1+2,'Side(s)'); + outtextxy(x1+270,y1+2,'Rotate Around....'); +end; + +Procedure RotateOptions_.handlevent(var event:tevent); +begin + if @self=owner^.first then with event do begin + inherited handlevent(event); + if what=EvCommand then + case command of + CMDrotatedformX,CMDrotatedformY,CMDrotatedformz:dorth^.docommand(command,nil,0); + end; + end; +end; +var +gridmodemenu:Tpopupmenu_; +Constructor GridOptions_.create; + +const +gridmodeinfo:array[0..2] of tmenuitem_=( +(name:'Flat';attrib:0;keycode:0;command:CMDtoggleflat;submenu:nil), +(name:'Sine Wave';attrib:0;keycode:0;command:CMDtogglesine;submenu:nil), +(name:'Heightmap';attrib:0;keycode:0;command:CMDtoggleheightmap;submenu:nil)); +gridtitleinfo:tmenuitem_= +(name:'Flat ';attrib:moptchangename+moptbutton;keycode:0;command:0;submenu:@gridmodemenu); + +begin + inherited create('Grid'); + insert(new(numsel,create(x1+183,y1+2,55,16,8,3,30,@GridX))); + xval:=ValueType(tgroup(first)^.last); + insert(new(numsel,create(x1+240,y1+2,55,16,8,3,30,@GridY))); + yval:=ValueType(tgroup(first)^.last); + + insert(new(textbutton,create(x1+320,y1+2,85,18,titlecol,1,BM_toggleaction,1,CMDToggleCheck,'Checkered'))); + insert(new(textbutton,create(x1+320,y1+22,85,18,titlecol,1,BM_releaseaction,1,CMDloadheightmapdialog,'Load Map'))); + insert(new(tmenubar,create(x1+420,y1+2,@gridtitleinfo,1,2,menuxorient))); + gridmodemenu.create(0,0,@gridmodeinfo,3,2,menupopup); + +end; + +Procedure GridOptions_.draw; +begin + inherited draw; + t_col:=disabledcol; + Outtextxy(x1+209,y1+21,'X'); + Outtextxy(x1+266,y1+21,'Y'); +end; +Procedure GridOptions_.handlevent(var event:tevent); +begin + if @self=owner^.first then begin + inherited handlevent(event); + with event do + case what of + EvCommand: + case command of + CMDToggleSine:begin GridMode:=GMSine;end; + CMDToggleHeightmap:begin GridMode:=GMheightmap;end; + CMDToggleFlat:begin GridMode:=gmflat;end; + CmdToggleCheck:CheckOrNot:=CheckOrNot xor true; + CMDloadHeightmapDialog: + desktop^.add_and_draw(new(file_dialog,create(0,0,CMDcancel,CMDloadHeightmap, + 'Load Heightmap',varfontpath,'*.pcx',application)),VPcentre,loadfontPID); + + end; + end; + end; +end; + +Constructor Lgroup_.create(name_:string); +begin + inherited create(60,0,SC.screenport.x2,vbord+25); + xoffset:=lgroupoffset; + options:=options or (OfKeyGrab+OfNoOverlap); + name:=name_; +end; + +Procedure Lgroup_.draw; +begin + t_fillcol:=midcol; + t_col:=purple; + setfillpattern(midgreyfill,true); + bar(x1+1,y1+vbord+6,x2-1,y2-1); + bar(x1+xoffset+1,y1+1,x2-1,y1+vbord+7); + setsolidfill; + + t_col:=lightcol; + hline(x1+xoffset,x2,y1); + hline(x1,x1+xoffset-1,y1+vbord+5); + vline(x1+xoffset,y1,y1+vbord+5); + vline(x1,y1+vbord+5,y2-1); + + t_col:=mid_darkcol; + hline(x1,x2,y2-1); + + t_col:=darkcol; + hline(x1,x2,y2); + outtextxy3d(x1+5,y2-fontheight-1,name); + inherited draw; +end; + +Constructor CopyRightBox_.create; +begin + inherited create(0,0,330,55); + options:=options or ofkeygrab; +end; + +Procedure CopyRightBox_.handlevent(var event:Tevent); +begin + inherited handlevent(event); + if (event.what=EvKeyDown)and(charcode=#27) then + delete; +end; + +Procedure CopyRightBox_.draw; +begin + Outbox(x1,y1,x2,y2); + T_col:=Textcol; + Outtextxy(x1+4,y1+4,'This software is Copyright 1995, T.Lewis'); + Outtextxy(x1+4,y1+4+fontheight, + 'It''s sale or distribution without the '); + Outtextxy(x1+4,y1+4+(fontheight shl 1),'authors consent is forbidden.'); +end; + +function strippath(pstr:string):string; +var i,lastindx:byte; +retstr:string; +begin + for i:=1 to length(pstr) do begin + if pstr[i]='\' then + lastindx:=i; + end; + retstr:=copy(pstr,0,lastindx); + strippath:=retstr; +end; + +begin + {mem1:=memavail; + writeln(memavail); + writeln(memavail+fixedusage); + } + + PerspectiveINT:=PersStart; + if memavail'' then + clay_dir:=clay_dir+'\' + else + clay_dir:=exepath; + varfontpath:=gtdir; + varobjectpath:=gtdir; + if (font_path='') then begin + font_path:=exepath+'sansf16b.fnt'; + end; + + + + if copy(paramstr(1),1,1)='v' then begin + case atoi(copy(paramstr(1),2,system.length(paramstr(1))-1)) of + 1:GraphInstalled:=initgraph(VGA640x480x16); + 2:GraphInstalled:=initgraph(SVGA800x600x16); + 3:GraphInstalled:=initgraph(SVGA640x480x256); + 4:GraphInstalled:=initgraph(SVGA800x600x256); + 5:GraphInstalled:=initgraph(SVGA1024x768x256); + 6:GraphInstalled:=initgraph(xVGA400x300x256); + end; + if not GraphInstalled then begin + Writecon('I can not use that graphics mode$'+chr(13)); + exit; + end; + end else + GraphInstalled:=initgraph(VGA640x480x16); + + usecolours(0,16); + + if fexist(font_path) then + loadfontlist(font_path, tcharset) + else begin + writeln('Font file not found, please place the file sans16b.fnt in the program file''s directory'); + exit; + end; + move(altletters,mem[seg(tcharset):ofs(tcharset)+(254 shl 4)],32); + move(ctrlletters,mem[seg(tcharset):ofs(tcharset)+(252 shl 4)],32); + tcharset.widths[252]:=8; + tcharset.widths[253]:=9; + tcharset.widths[254]:=8; + tcharset.widths[255]:=9; + + tcharset.attrib:=1; + + new(draw_object,create(4900,4200,4200)); + + if fexist(clay_dir+defaultfont) then begin + Vfontin:=vfont.load(defaultfont); + end else + Vfontin:=false; + + if fexist(clay_dir+'info.txt') then + textfile:=loadtext(clay_dir+'info.txt'); + getmem(objectinfo,512); + gridpic:=nil; + + setpal(@pal16,0,16); + init3d; + + lightvec.setlight(0,0,0,500,50,10,SC.ColourDepth shr 1); + + with SC.screenport do + application:=new(clay,create(0,0,x2,y2)); + InitTWIN(application); + if fexist(clay_dir+'warn.pcx') then + warningsign:=readpcx(clay_dir+'warn.pcx',PAcolcheck) + else + warningsign:=nil; + + + application^.draw; + + mouseon; + root:=application; + + + + registerfile:=loadtext(clay_dir+'register.txt'); + + desktop^.add_and_draw(new(infodialog,create(90,80,590,470,registerfile,true)),VPcentre,PIDundefined); + + while not fin do begin + + eventmpos; + eventkey; + status^.update; + + end; + mouseoff; + if vfontin then + vfont.done; + + draw_object^.done; + close3d; + application^.done; + freemem(textfile,strlen(textfile)); + {freemem(objectinfo,512);} + if warningsign<>nil then + destroybitmap(warningsign); + closegraph; + writecon('That was ClayWorks V'+VersionStr+', (C) T.lewis 1995.$'+chr(13)); +end. diff --git a/COLOUR.PAS b/COLOUR.PAS new file mode 100644 index 0000000..204696e --- /dev/null +++ b/COLOUR.PAS @@ -0,0 +1,501 @@ +unit colour; +{$R-} +INTERFACE +uses PITtimer,ttypes; + +const +maxRGBval=64; +{colour weights } +rwt=12; gwt=26; bwt=14; +type +RGBtype=object + R,G,B:byte; +End; + +RGBwordtype=object + R,G,B:word; +End; + +ColourEntry=object(rgbtype) + Used:word; +end; + +RGBarray=^RGBarray_; +RGBarray_=array[0..0] of RGBtype; + +RGBwordarray=^RGBwordarray_; +RGBwordarray_=array[0..0] of RGBwordtype; + +ColourEntryArray=^ColourEntryArray_; +ColourEntryArray_=array[0..0] of ColourEntry; + +procedure readpal(filename:string;pal:RGBarray); +procedure savepal(filename:string;pal:RGBarray); +procedure savepalpas(filename:string;pal:RGBarray); +Function AllocateRGB(Rc,Gc,Bc:byte):byte; +Procedure FreeColour(colindex:byte); +Procedure FreeAllColours; +Procedure InitColours(NumCols:word); +Procedure DoneColours; +Procedure copycol(col1,col2:byte); +Procedure swapcol(col1,col2:byte); +Procedure grad(col1,col2:byte); +procedure LoadColourMap(pal:ColourEntryArray); +Procedure Gethardwarepal(pal:RGBarray); +Procedure SetHardwarepal(pal:RGBarray;start,length:word); +Procedure setpal(pal:RGBarray;start,length:word); +Procedure getpal(pal:RGBarray); +Procedure Fadepal(pal1,pal2:RGBarray;step:byte;background:boolean); +Procedure getrgb(colno:byte;var r,g,b:byte); +Procedure setrgb(colno:byte;r,g,b:byte); +Procedure sethsv(colno:byte;H,S,V:Real); +Procedure gethsv(colno:byte;var Hi,Si,Vi:byte); +function checkforfade:boolean; +function ColoursAvailable:word; +Procedure usecolours(start,length:word); + +IMPLEMENTATION + +var +MaxColours:integer; +ColoursAvail:integer; +ColourMap:ColourEntryArray; +fading:boolean; + +function checkforfade:boolean; +begin + checkforfade:=fading; +end; + +Function ColoursAvailable:word; +begin + ColoursAvailable:=ColoursAvail; +end; + +Procedure usecolours(start,length:word); +var lop:word; +begin + for lop:=start to start+(length-1) do + inc(colourmap^[lop].used); + dec(coloursavail,length); + if coloursavail<0 then coloursavail:=0; +end; + + +{swaps two variables of arbitary length, inline into the code} +Procedure FSwap(Var s,d; L:Integer); +Begin + Inline($1e /$c5/$b6/s /$c4/$be/d /$8b/$8e/l /$fc /$26/$8a/$05 + /$86/$04 /$46 /$aa /$e2/$f7 /$1f); +End; + +procedure readpal(filename:string;pal:RGBarray); +var f:file; +recsize:word; +lop:byte; +begin + recsize:=1; + assign(f,filename); + reset(f,recsize); + blockread(f,pal^,maxcolours*sizeof(rgbtype),recsize); + close(f); +end; + +procedure savepal(filename:string;pal:RGBarray); +var f:file; +recsize:word; +lop:byte; +begin + assign(f,filename); + rewrite(f,recsize); + blockwrite(f,pal^,sizeof(pal),recsize); + close(f); + {for lop:=0 to 15 do begin + pal[lop].r:=pal[lop].r div 4; + pal[lop].g:=pal[lop].g div 4; + pal[lop].b:=pal[lop].b div 4; + end;} +end; + +procedure savepalpas(filename:string;pal:RGBarray); +var f:text; +lop:byte; +begin + assign(f,filename); + rewrite(f); + write(f,'pal:palltype=('); + for lop:=0 to maxcolours-1 do begin + write(f,'(r:',pal^[lop].r,';'); + write(f,'g:',pal^[lop].g,';'); + write(f,'b:',pal^[lop].b,')'); + if lop=maxcolours-1 then + write(f,')') + else + write(f,','); + if (lop and 3=0) then + writeln(f,''); + end; + close(f); +end; + +procedure freecolour(colindex:byte); +begin + ColourMap^[colindex].used:=0; + inc(ColoursAvail); +end; + +procedure freeallcolours; +var lop:byte; +begin + for lop:=0 to maxcolours-1 do + ColourMap^[lop].used:=0; + ColoursAvail:=MaxColours; +end; + +Procedure InitColours(NumCols:word); +begin + MaxColours:=NumCols; + getmem(Colourmap,MaxColours*sizeof(ColourEntry)); + FreeAllColours; + LoadColourMap(ColourMap); + fading:=false; +end; + +Procedure DoneColours; +begin + freemem(Colourmap,MaxColours*sizeof(ColourEntry)); +end; + + +Function AllocateRGB(Rc,Gc,Bc:byte):byte; +var CurrCol:word;matchindex:byte; + ColFound:boolean; + diff,match:word; +begin + CurrCol:=0; + match:=32000; + ColFound:=false; + + While (not ColFound)and(currcoltrue)and(coloursavail<=0) then begin + diff:=abs(gc-g)*gwt; + if diff0) then begin + AllocateRGB:=CurrCol; + inc(ColourMap^[CurrCol].used); + end else if ColoursAvail>0 then begin + CurrCol:=0; + While (ColourMap^[CurrCol].used<>0)and(CurrColG then max:=R else max:=G; + iF B>max then max:=B; + If R0 then s:=diff/max else S:=0; + if S=0 then + H:=0 + else begin + r_dist:=(max - R)/diff; + g_dist:=(max - G)/diff; + b_dist:=(max - B)/diff; + if R=max then + H:=b_dist-G_dist + else if G=max then + H:=2+r_dist-b_dist + else if B=max then + H:=4+g_dist-R_dist; + H:=H * 64; + if H< 0 then H:=H+384; + end; + Hi:=trunc(H / 6); + Si:=trunc(S * 64); + Vi:=trunc(V * 64); +end; + +Procedure swapcol(col1,col2:byte); +var col1val,col2val:RGBtype; +Begin + getrgb(col1,col1val.r,col1val.g,col1val.b); + getrgb(col2,col2val.r,col2val.g,col2val.b); + setrgb(col2,col1val.r,col1val.g,col1val.b); + setrgb(col1,col2val.r,col2val.g,col2val.b); +end; + +Procedure copycol(col1,col2:byte); +var col1val:RGBtype; +Begin + getrgb(col1,col1val.r,col1val.g,col1val.b); + setrgb(col2,col1val.r,col1val.g,col1val.b); +end; + +Procedure grad(col1,col2:byte); +const shiftby=6; +var Rplus,Bplus,Gplus,rp,gp,bp,step:integer; + pal:rgbarray; +Begin + getmem(pal,maxcolours*sizeof(rgbtype)); + if col20 then + sethardwarepal(F_pal1,0,maxcolours) + else + setpal(F_pal1,0,maxcolours) +end; + +Procedure addincs;interrupt; +begin + if F_counter=0 then begin + fading:=false; + cleanuptimer; + end; + doincs; +end; + +Procedure Fadepal(pal1,pal2:RGBarray;step:byte;background:boolean); +Var lop:byte; +Begin + getmem(F_pal1,maxcolours*sizeof(rgbtype)); + getmem(F_ScaledPal,maxcolours*sizeof(rgbwordtype)); + getmem(F_PalIncs,maxcolours*sizeof(rgbwordtype)); + + For lop:=0 to maxcolours-1 do Begin + with F_ScaledPal^[lop] do begin + r:=pal1^[lop].r shl F_shiftby; + g:=pal1^[lop].g shl F_shiftby; + b:=pal1^[lop].b shl F_shiftby; + end; + with F_palincs^[lop] do begin + r:=((pal2^[lop].r-pal1^[lop].r)shl F_shiftby)div step; + g:=((pal2^[lop].g-pal1^[lop].g)shl F_shiftby)div step; + b:=((pal2^[lop].b-pal1^[lop].b)shl F_shiftby)div step; + end; + end; + F_counter:=step; + if background then begin + fading:=true; + settimer(@addincs,1000) + end else + while F_counter>0 do + doincs; + + Freemem(F_pal1,maxcolours*sizeof(rgbtype)); + Freemem(F_ScaledPal,maxcolours*sizeof(rgbwordtype)); + Freemem(F_PalIncs,maxcolours*sizeof(rgbwordtype)); +end; + +end. diff --git a/CPUTYPE.PAS b/CPUTYPE.PAS new file mode 100644 index 0000000..dd86b7e --- /dev/null +++ b/CPUTYPE.PAS @@ -0,0 +1,138 @@ +Unit CPUTYPE; + +Interface + +const CPU_8088 = 0; + CPU_80186 = 1; + CPU_80286 = 2; + CPU_80386 = 3; + CPU_80486 = 4; + CPU_UNKNOWN = -1; + +{ The cpu variable is initialised to the cpu type } +var cpu : integer; + +{ Isa8088 returns true only if cpu is an 8088 or 8086 } +function Isa8088 : boolean; + +{ Isa80186 returns true if cpu is an 80186 or higher } +function Isa80186 : boolean; + +{ Isa80286 returns true if cpu is an 80286 or higher } +function Isa80286 : boolean; + +{ Isa80386 returns true if cpu is an 80386 or higher } +function Isa80386 : boolean; + +{ Isa80486 returns true if cpu is an 80486 or higher } +function Isa80486 : boolean; + + + + +Implementation + +Uses Dos; + +var OldIntr6Handler : procedure; + valid_op_code : boolean; + +procedure Intr6Handler;interrupt; +begin + valid_op_code := false; + + { Stoopid TP7 won't let me modify IP directly } + asm + add word ptr ss:[bp + 18], 3 + end; +end; + +function Isa8088 : boolean; +var sp1, sp2 : word; +begin + asm + mov sp1, sp + push sp + pop sp2 + end; + if sp1 <> sp2 then + Isa8088 := true + else + Isa8088 := false; +end; + +function Isa80186 : boolean; +begin + if Isa8088 then + Isa80186 := false + else + begin + valid_op_code := true; + GetIntVec(6, @OldIntr6Handler); + SetIntVec(6, Addr(Intr6Handler)); + inline($C1/$E2/$05); { shl dx, 5 } + SetIntVec(6, @OldIntr6Handler); + Isa80186 := valid_op_code; + end; +end; + +function Isa80286 : boolean; +begin + if Isa8088 then + Isa80286 := false + else + begin + valid_op_code := true; + GetIntVec(6, @OldIntr6Handler); + SetIntVec(6, Addr(Intr6Handler)); + inline($0F/$01/$E2); { smsw dx } + SetIntVec(6, @OldIntr6Handler); + Isa80286 := valid_op_code; + end; +end; + +function Isa80386 : boolean; +begin + if Isa8088 then + Isa80386 := false + else + begin + valid_op_code := true; + GetIntVec(6, @OldIntr6Handler); + SetIntVec(6, Addr(Intr6Handler)); + inline($0F/$20/$C2); { mov edx, cr0 } + SetIntVec(6, @OldIntr6Handler); + Isa80386 := valid_op_code; + end; +end; + +function Isa80486 : boolean; +begin + if Isa8088 then + Isa80486 := false + else + begin + valid_op_code := true; + GetIntVec(6, @OldIntr6Handler); + SetIntVec(6, Addr(Intr6Handler)); + inline($0F/$C1/$D2); { xadd dx, dx } + SetIntVec(6, @OldIntr6Handler); + Isa80486 := valid_op_code; + end; +end; + + +begin + if Isa8088 then + cpu := CPU_8088 + else if Isa80486 then + cpu := CPU_80486 + else if Isa80386 then + cpu := CPU_80386 + else if Isa80286 then + cpu := CPU_80286 + else if Isa80186 then + cpu := CPU_80186 + else + cpu := CPU_UNKNOWN; +end. diff --git a/CRT2.PAS b/CRT2.PAS new file mode 100644 index 0000000..78401c6 --- /dev/null +++ b/CRT2.PAS @@ -0,0 +1,127 @@ +UNIT crt2; + + +INTERFACE +procedure gotoxy(x,y:byte); +procedure clrscr; +function readkey:char; +function keypressed:boolean; +procedure delay(time:integer); +procedure nosound; +procedure sound(pitch:integer); +procedure writecon(text:pchar); + +const + smLEFTSHIFT=2; + smLEFTCTRL=4; + smLEFTALT=8; + smRIGHTSHIFT=1; + smSCANMASK=15; + + + + tabkey=#9; + whitespace=' '; + rightkey=77; + rightkeyctrl=116; + leftkey=75; + leftkeyctrl=115; + upkey=72; + downkey=80; + pageupkey=73; + pagedownkey=81; + homekey=71; + delkey=83; + endkey=79; + backspacekey=chr(8); + escapekey=chr(27); + returnkey=chr(13); +var + +textscr:^byte; + + +scan:byte Absolute $40:$17; +timer:word Absolute $40:$6c; + +scancode:byte; +charcode:char; + +IMPLEMENTATION + +procedure clrscr;assembler; +asm + les di,textscr; + mov cx,80*25 + mov ax,0 + rep stosw +end; + +function readkey:char;assembler; +asm + mov ah,0 + int $16 + mov scancode,ah + mov charcode,al + cmp scan,smSCANMASK + jnz @fin + mov charcode,0 + @fin: +end; + +function keypressed:boolean;assembler; +asm + mov ah,1 + int $16 + jnz @setz + mov al,0 + jmp @end + @setz: + mov al,1 + @end: + + +end; + + +procedure sound(pitch:integer); +begin +end; + +procedure nosound; +begin +end; + +procedure delay(time:integer); +begin +end; + +procedure writecon(text:pchar);assembler; +asm + push ds + lds dx,text {reload start of string} + mov ah,9 {DOS print string function} + int 21h {display text} + pop ds +end; + +procedure writeln(text:string);assembler; +asm + push ds + lds dx,text {reload start of string} + mov ah,9 {DOS print string function} + int 21h {display text} + pop ds +end; + +procedure gotoxy(x,y:byte);assembler; +asm + mov ax,$02 + + int $10 + +end; + +begin + textscr:=ptr($b800,000); +END. \ No newline at end of file diff --git a/DIALOGS.PAS b/DIALOGS.PAS new file mode 100644 index 0000000..71ce718 --- /dev/null +++ b/DIALOGS.PAS @@ -0,0 +1,1214 @@ +unit dialogs; + +INTERFACE +uses crt2,gbasics,views,twinb,ggraph,dos,diskop, + twindraw,chardef,msmouse,lcd,tmaths,strings,sincos,ttypes,emsunit,colour; + +CONST +ceditorsid =100; +CMDfileOK =400; +CMDfileCancel =401; +CMDCreatecoledit =402; +CMDcolourchanged =403; +CMDcalleditpal =404; + +type + + +Colourgridtype=^Colourgridtype_; + +Coloureditor=^Coloureditor_; +Coloureditor_=object(tgroup_) + Cgrid:colourgridtype; + Rbar,gbar,bbar:slidertype; + + HSVbutton,RGBbutton:TextButton; + colour,mode:byte; + oldpal:RGBarray; + change:boolean; + Constructor create(xa,ya:integer;colour_:byte;Cgrid_:colourgridtype); + Destructor done;virtual; + Procedure handlevent(var event:tevent);virtual; + Procedure setcolour(colour_:byte); + Procedure Draw;virtual; +end; + +Colourgridtype_=object(tview_) + CEditor:coloureditor; + Desktop:tgroup; + size:bytepointtype; + + fgcol,bgcol:byteptr; + xsize,ysize,offset:integer; + + Constructor create(x,y,xsize_,ysize_:integer;xlen_,ylen_:byte;fgcol_,bgcol_:byteptr;desktop_:tgroup); + procedure draw;virtual; + procedure handlevent(var event:tevent);virtual; +end; + +chartype=record + ch:char; + at:byte; +end; + +screenptr=^screentype; +screentype=array[0..24]of textline; + +textpage=^textpage_; +textpage_=object(delta_) + screen:screenptr; + Constructor make(page:screenptr); + procedure draw;virtual; +end; + +colourwindow=^colourwindow_; +colourwindow_=object(delta_) + procedure draw;virtual; +end; + +bitmapwindow=^bitmapwindow_; +bitmapwindow_=object(delta_) + destroypic:boolean; + pic:bitmaptypeptr; + Constructor make(piccy:bitmaptypeptr;dpic:boolean); + Destructor done;virtual; + procedure draw;virtual; +end; + +InfoDialog=^InfoDialog_; +InfoDialog_=object(tgroup_) + deltext:boolean; + xbar,ybar:bartype; + ActionWindow:Delta; + Constructor create(xa,ya,xb,yb:integer;text:pchar;deltext_:boolean); + procedure handlevent(var event:tevent);virtual; +end; + + + +InfoDialogb=^InfoDialogb_; +InfoDialogb_=object(tgroup_) + xbar,ybar:bartype; + ActionWindow:Delta; + Constructor create(xa,ya,xb,yb:integer;text:pchar); + procedure handlevent(var event:tevent);virtual; +end; + +timetype=record + hour,min,sec,nsec:word; +end; + +clock=^clock_; +clock_=object(tview_) + drawmode,alarmon:boolean; + currtime,oldtime,alarm:timetype; + + procedure update; + + Constructor make; + procedure draw;virtual; +end; + +Analogclock=^Analogclock_; +Analogclock_=object(tview_) + drawmode,alarmon:boolean; + currtime,oldtime,alarm:timetype; + + procedure update; + Constructor create(x1_,y1_,x2_,y2_:integer); + procedure setalarm(switch:boolean;hrs,min:word); + procedure draw;virtual; +end; + +digitwindow=^digitwindow_; +digitwindow_=object(delta_) + procedure draw;virtual; +end; + +background=^background_; +background_=object(tview_) + fgcol,bgcol:byte; + pattern:fillpatterntype; + + constructor create(x1_,y1_,x2_,y2_:integer;fgcol_,bgcol_:byte;pattern_:fillpatterntype); + procedure draw;virtual; +end; + +backpic=^backpic_; +backpic_=object(tview_) + pic:bitmaptypeptr; + + constructor create(x1_,y1_,x2_,y2_:integer;pic_:bitmaptypeptr); + procedure draw;virtual; +end; + +{starback=^starback_; +starback_=object(tview_) + starfall:startype; + procedure update; + constructor create(xa,ya,xb,yb:integer); + procedure draw;virtual; +end;} + + +MoveTitle=^Movetitle_; +MoveTitle_=object(Tgroup_) + Constructor Create(xa,ya,xb,yb:integer;Name:string); + Procedure Handlevent(var Event:Tevent);virtual; +end; + +statusviewb=^statusviewb_; +statusviewb_=object(tview_) + val1:^byte;oldval1:byte; + + + procedure handlevent(var event:tevent);virtual; + procedure draw;virtual; + procedure update; +end; + + +statusview=^statusview_; +statusview_=object(tview_) + oldcharcode:char;oldscancode,oldscan:byte; + MemoryLeft:longint; + oldioresult:word; + procedure handlevent(var event:tevent);virtual; + procedure draw;virtual; + procedure update; +end; + +listWbar=^listWbar_; +listWbar_=object(tgroup_) + list:listtype; + bar:slidertype; + constructor create(x,y,x2_,y2_:integer;info_:stringarray;maxopts_,offset:integer;destroyold_:boolean); + Procedure Handlevent(var Event:Tevent);virtual; + Procedure setlist(info_:stringarray;maxopts_:integer); +end; + +File_dialog=^File_dialog_; +File_dialog_=object(tgroup_) + Ok,cancel:word; + SDir: DirStr;SName: NameStr;SExt: ExtStr; + StdFilter:string[11]; + files,paths:listwbar; + texteditbox:edittexttype; + Handler:tview; + + Procedure load_files; + Procedure load_path; + Constructor create(x,y:integer;Cancel_,Ok_:word;name_,path,filter:string;handler_:tview); + Procedure handlevent(var event:tevent);virtual; + Procedure Draw;virtual; +end; + +desktoptype=^desktoptype_; +desktoptype_=object(tgroup_) + procedure handlevent(var event:tevent);virtual; +end; + +procedure AddMessage(Cancel,Ok:word;message:pchar;pid_:word;group:tgroup); +function loadtext(filename:string):pchar; +function inputdir(path,filter:string;attrfilter:word;var count:integer):stringarray; + +IMPLEMENTATION + +Procedure UpCaseStr(var text:string); +var lop:byte; +begin + for lop:=1 to byte(text[0]) do + text[lop]:=upcase(text[lop]); +end; + + +Procedure Sortarray(data:stringarray;datasize:word;maxelem:integer); +var lop2,lop:byte; + {dataptr1,dataptr2:^stdstring;} + +Begin + {dataptr1:=data; + dataptr2:=data;} + For lop:=1 to maxelem do begin + {inc(dataptr1,datasize);} + For lop2:=lop to maxelem do begin + {inc(dataptr2,datasize); + if dataptr2^directory)) + and(count<255) then begin + if DirInfo.attr=directory then + info^[count+1]:=DirInfo.Name + else + info^[count+1]:=DirInfo.Name; + inc(count); + end; + FindNext(DirInfo); + end; + sortarray(info,stringsize+1,maxopts); + inputdir:=info; +End; + +constructor listWbar_.create(x,y,x2_,y2_:integer;info_:stringarray;maxopts_,offset:integer;destroyold_:boolean); +var temp:integer; +begin + inherited create(x,y,x+x2_+offset+scrollbar_size,y+y2_); + options:=options or ofkeygrab+ofnooverlap+OfTabCycleSelect; + list:=new(listtype,create(x,y,x2_,y2_,info_,maxopts_,destroyold_)); + list^.growmode:=TGgrowx2+TGgrowy2; + with list^ do temp:=maxopts-maxylen; + if temp<0 then temp:=0; + insert(list); + insert(new(bartype,create(x+x2_+offset,y,scrollbar_size,y2_,1,1+temp,1,ybardir))); + bar:=slidertype(tgroup(first)^.last); + bar^.growmode:=TGdragx2+TGgrowally; +end; + +Procedure listWbar_.Handlevent(var Event:Tevent); +begin + inherited handlevent(event); + with event do + if what=EvCommand then case command of + CMDoffsetchanged: + bar^.setval(list^.off); + CMDvalchanged:begin + list^.handlevent(event); + EvCallBack(command); + end else + EvCallBack(command); + end; +end; + +{load up a new list, modify the list isteslf and the bar} +Procedure ListWbar_.setlist(info_:stringarray;maxopts_:integer); +var temp:integer; +begin + list^.setlist(info_,maxopts_); + with list^ do temp:=maxopts-maxylen; + if temp<0 then temp:=0; + bar^.setrange(1,1+temp,1); +end; + +{procedure listWbar_.setlist(list_:stringarray;maxopts:integer); +begin + list^.info:= +end;} +const +PIDfiles=100; +PIDpaths=101; + + +Constructor file_dialog_.create(x,y:integer;Cancel_,Ok_:word;name_,path,filter:string;handler_:tview); +const +W=300; H=220+(fontheight shl 1); +var +list:stringarray; +listcount:integer; + +temp:integer; +begin + inherited create(x,y,x+W,y+H); + Cancel:=Cancel_; + Ok:=Ok_; + Stdfilter:=filter; + Handler:=Handler_; + {chdir(path);} + options:=options or (ofnooverlap+ofkeygrab+oftopselect+OfTabCycleSelect); + + texteditbox:=new(edittexttype,create(x1+10,y1+vbord+fontheight+4,path+filter,100,20)); + texteditbox^.growmode:=TGdragx1+TGdragy1; + insert(texteditbox); + + fsplit(texteditbox^.txt,sdir,sname,sext); + list:=inputdir(Sdir,filter,anyfile,listcount); + + files:=new(listwbar,create(x1+10,y2-168,110,117,list,listcount,3,true)); + files^.growmode:=TGgrowallx+TGgrowally; + files^.pid:=PIDfiles; + insert(files); + + list:=inputdir(Sdir,'*.*',directory,listcount); + + paths:=new(listwbar,create(x1+150,y2-168,110,101,list,listcount,3,true)); + paths^.growmode:=TGgrowallx+TGgrowally; + paths^.pid:=PIDpaths; + insert(paths); + + insert(new(listtype,create(x1+10,y2-15-Fontheight,50,4+Fontheight,list,0,true))); + first^.growmode:=TGdragx1+TGdragy2; + add_title(@self,name_); + {insert(new(dialogback,create(x1,y1+vbord+1,x2,y2)));} + insert(new(textbutton,create(x2-140,y2-30,60,20,midcol,1,BM_releaseaction,1,OK,'Ok'))); + first^.growmode:=TGdragx2+TGdragy2; + insert(new(textbutton,create(x2-70,y2-30,60,20,midcol,1,BM_releaseaction,1,Cancel,'Cancel'))); + first^.growmode:=TGdragx2+TGdragy2; + + growmode:=TGdragx2+TGdragy2; + + +end; + +procedure file_dialog_.load_path; +var temp:integer; + list:stringarray; + listcount:integer; +begin + list:=inputdir(Sdir,'*.*',directory,listcount); + paths^.setlist(list,listcount); +end; + +procedure file_dialog_.load_files; +var temp:integer; + list:stringarray; + listcount:integer; +begin + list:=inputdir(Sdir,Sname+Sext,anyfile,listcount); + files^.setlist(list,listcount); +end; + +procedure file_dialog_.handlevent(var event:tevent); +{Const + files=1;paths=2; +var + currbar:slidertype; + currlist:listtype; + currblock:byte;} + +var +ID:word; + +procedure loadlists; +var ODir: DirStr; +begin + if texteditbox^.txt<>sdir+sname+sext then begin + Odir:=Sdir; + fsplit(texteditbox^.txt,sdir,sname,sext); + if (sname='')and(sext='') then begin + texteditbox^.settext(gtdir+stdfilter); + fsplit(texteditbox^.txt,sdir,sname,sext); + end; + if Odir<>Sdir then begin + load_path; + end; + if (instring(sname,'*'))or(instring(sext,'*')) then begin + load_files; + end else begin + upcasestr(texteditbox^.txt); + SendCommand(Ok,Handler,@self);delete; + end; + end; +end; + +begin + inherited handlevent(event); + with event do + case what of + evcommand:begin + {if (infoptr=filebar)or(infoptr=filelist) then begin + currlist:=filelist;currbar:=filebar; + currblock:=files; + end else if (infoptr=pathbar)or(infoptr=pathlist) then begin + currlist:=pathlist;currbar:=pathbar; + currblock:=paths; + end;} + id:=tview(infoptr)^.pid; + case command of + CMDEditReturnPressed:loadlists; + CMDmoveparent:dragview(1,owner^,150,170,1000,1000); + CMDitemDclicked:if id=PIDfiles then begin + upcasestr(texteditbox^.txt); + SendCommand(Ok,Handler,@self);delete; + end else begin + with paths^.list^ do begin + chdir(sdir); + chdir(info^[sel]){copy(info^[sel],2,length(info^[sel])-2))}; + end; + texteditbox^.settext(gtdir+stdfilter); + loadlists; + end; + CMDselectedchanged:begin + if ID=PIDfiles then + with Files^.list^ do texteditbox^.settext(Sdir+info^[sel]) + end; + else if (command=ok)or (command=cancel)then begin + SendCommand(command,Handler,@self);delete; + end; + end; + end; + EvKeyDown:if scancode<>0 then begin + what:=0; + case scancode of + 49:texteditbox^.select; + 25:paths^.list^.select; + 33:files^.list^.select; + else what:=EvKeyDown; + end; + end; + end; + +end; + +Procedure File_dialog_.draw; +begin + outbox(x1,y1+vbord+1,x2,y2); + t_col:=disabledcol; + with TextEditBox^ do + outtextxyU(x1,y1-fontheight-1,'Name',1); + with Files^ do + outtextxyU(x1,y1-fontheight-1,'Files',1); + with Paths^ do + outtextxyU(x1,y1-fontheight-1,'Paths',1); + inherited draw; +end; + +{----****Colour editing dialog****----} +Constructor colourgridtype_.create(x,y,xsize_,ysize_:integer;xlen_,ylen_:byte;fgcol_,bgcol_:byteptr;desktop_:tgroup); + begin + inherited create(x,y,x+(xsize_*xlen_)-1,y+(ysize_*ylen_)+1); + desktop:=desktop_; + fgcol:=fgcol_; + bgcol:=bgcol_; + Ceditor:=nil; + size.x:=xlen_; + size.y:=ylen_; + xsize:=xsize_; + ysize:=ysize_; + offset:=0; +end; + +procedure colourgridtype_.draw; +var x,y:integer; + xpos,ypos:integer; +begin + t_col:=lightcol; + hline(x1,x2,y1); + colourgrid(x1,y1+1,xsize,ysize,size.x,size.y,offset*size.x); + t_col:=darkcol; + hline(x1,x2,y2); + t_writemode:=xorput; + xpos:=(fgcol^ mod size.x); + ypos:=((fgcol^-xpos) div size.x); + x:=1+x1;y:=1+y1; + outtextxy(x+(xpos*xsize),y-(offset*ysize)+(ypos*ysize),'F'); + xpos:=(bgcol^ mod size.x); + ypos:=((bgcol^-xpos) div size.x); + outtextxy(x+(xpos*xsize),y-(offset*ysize)+(ypos*ysize),'B'); + t_writemode:=0; +end; + +procedure colourgridtype_.handlevent(var event:tevent); +var colour:byte; +begin + inherited handlevent(event); + with event do begin + if what and Evmouse<>0 then begin + if zm<>0 then begin + colour:=(((xm-x1-1)div xsize)+((ym-y1-1)div ysize)*size.x)+(offset*size.x); + if ((colour<>fgcol^)and(zm=1))or((colour<>bgcol^)and(zm=2)) then begin + if zm=1 then + fgcol^:=colour + else + bgcol^:=colour; + if Ceditor<>nil then Ceditor^.setcolour(colour); + drawview; + EvCallBack(CMDcolourchanged); + end; + end; + if (ms_doubleclicked) then with desktop^ do begin + if add_and_draw(new(coloureditor,create(x1+100,y1+100,fgcol^,@self)),VPcentre,ceditorsid)<>nil then + ceditor:=pointer(first); + end; + end; + if (what=evcommand)then case command of + CMDvalchanged:begin + offset:=valuetype(infoptr)^.val^; + drawview; + end; + CMDcalleditpal:with desktop^ do begin + if add_and_draw(new(coloureditor,create(x1+100,y1+100,fgcol^,@self)),VPcentre,ceditorsid)<>nil then + ceditor:=pointer(first); + end; + end; + end; +end; + +const +CMDok=300; +CMDCancel=301; +CMDGrad=302; +CMDCopy=303; +CMDSwap=304; +CMDRGB=305; +CMDHSV=306; + +mdHSV=1; +mdRGB=0; + +Constructor Coloureditor_.create(xa,ya:integer;colour_:byte;Cgrid_:Colourgridtype); +const + w=170;h=230; +var +r,g,b:byte; +begin + inherited create(xa,ya,xa+w,ya+h); + cgrid:=cgrid_; + change:=false; + getmem(oldpal,SC.colourdepth*sizeof(rgbtype)); + getpal(oldpal); + colour:=colour_; + mode:=mdRGB; + getrgb(colour,r,g,b); + options:=options or (ofnooverlap+ofkeygrab+oftopselect+OfTabCycleSelect); + insert(new(bartype,create(x1+5,y1+43,scrollbar_size,147,-63,0,-r,ybardir))); + Rbar:=slidertype(tgroup(first)^.last); + insert(new(bartype,create(x1+25,y1+43,scrollbar_size,147,-63,0,-g,ybardir))); + Gbar:=slidertype(tgroup(first)^.last); + insert(new(bartype,create(x1+45,y1+43,scrollbar_size,147,-63,0,-b,ybardir))); + Bbar:=slidertype(tgroup(first)^.last); + insert(new(Textbutton,create(x2-50,y1+40,40,20,titlecol,1,BM_releaseaction,1,CMDgrad,'Fade'))); + insert(new(Textbutton,create(x2-50,y1+65,40,20,titlecol,1,BM_releaseaction,1,CMDswap,'Swap'))); + insert(new(Textbutton,create(x2-50,y1+90,40,20,titlecol,1,BM_releaseaction,2,CMDcopy,'Copy'))); + RGBbutton:=new(Textbutton,create(x2-50,y1+115,40,20,titlecol,1,BM_ToggleAction,1,CMDrgb,'RGB')); + insert(RGBbutton); + RGBbutton^.dstate:=1; + HSVbutton:=new(Textbutton,create(x2-50,y1+140,40,20,titlecol,1,BM_toggleAction,1,CMDhsv,'HSV')); + insert(HSVbutton); + + insert(new(Textbutton,create(x2-65,y2-55,55,20,midcol,1,BM_ReleaseAction,1,CMDok,'Ok'))); + insert(new(Textbutton,create(x2-65,y2-30,55,20,midcol,1,BM_ReleaseAction,1,CMDCancel,'Cancel'))); + + add_title(@self,'Colour editor'); +end; + +Procedure Coloureditor_.setcolour(colour_:byte); +var r,g,b:byte; +begin + colour:=colour_; + if mode=mdRGB then + getrgb(colour,r,g,b) + else + gethsv(colour,r,g,b); + + change:=true; + rbar^.setval(-r); + gbar^.setval(-g); + bbar^.setval(-b); + drawview; + change:=false; +end; + +Procedure Coloureditor_.handlevent(var event:tevent); +var othercolour:byte; + cliprect,oldvp:trect; +begin + inherited handlevent(event); + with event do begin + if what=Evcommand then begin + oldvp:=SC.viewport; + cliprect.rassign(x1+10,y1+vbord+1,x1+58,y1+42); + case command of + CMDmoveparent:dragview(1,owner^,130,100,1000,1000); + CMDvalchanged:if not change then + if mode=mdRGB then + setrgb(colour,-rbar^.offs,-gbar^.offs,-bbar^.offs) + else + sethsv(colour,-rbar^.offs,-gbar^.offs,-bbar^.offs); + CMDrgb:if mode=mdHSV then begin + mode:=mdRGB; + setcolour(colour); + HSVbutton^.dstate:=0; + HSVbutton^.drawview; + SC.viewport:=cliprect; + drawview; + SC.viewport:=oldvp; + end; + CMDhsv:if mode=mdRGB then begin + mode:=mdHSV; + setcolour(colour); + RGBbutton^.dstate:=0; + RGBbutton^.drawview; + SC.viewport:=cliprect; + drawview; + SC.viewport:=oldvp; + end; + CMDgrad,CMDswap,CMDcopy:if Cgrid<>nil then begin + setmouseshape(8,15,pointto); + while ((not cgrid^.inview(xm,ym)) or (not ms_clicked))and(not keypressed ) do + mpos; + if not keypressed then begin + mouseoff;othercolour:=getpixel(xm,ym);mouseon; + if colour<>othercolour then case command of + CMDgrad:grad(colour,othercolour); + CMDcopy:copycol(colour,othercolour); + CMDswap:swapcol(colour,othercolour); + end; + setcolour(colour); + end; + setmouseshape(0,0,arrow); + end; + CMDok:begin + if Cgrid<>nil then Cgrid^.Ceditor:=nil; + delete; + end; + CMDcancel:begin + if Cgrid<>nil then Cgrid^.Ceditor:=nil; + setpal(oldpal,0,SC.colourdepth); + delete; + end; + end; + end; + if what=evkeydown then case scancode of + 19:Rbar^.owner^.select; + 34:Gbar^.owner^.select; + 48:Bbar^.owner^.select; + end; + end; +end; + +Procedure Coloureditor_.draw; +var precalc:integer; +begin + inc(y1,vbord+1); + if not change then begin + precalc:=y1+3; + outbox(x1,y1,x2,y2); + t_col:=disabledcol; + if mode=mdRGB then begin + outtextxy(x1+10,precalc,'R'); + outtextxy(x1+30,precalc,'G'); + outtextxy(x1+50,precalc,'B'); + end else begin + outtextxy(x1+10,precalc,'H'); + outtextxy(x1+30,precalc,'S'); + outtextxy(x1+50,precalc,'V'); + end; + t_col:=Darkcol; + rectangle(x2-90,y1+18,x2-55,y1+87); + inherited draw; + end; + T_fillcol:=colour; + bar(x2-89,y1+19,x2-56,y1+86); + dec(y1,vbord+1); +end; + +Destructor ColourEditor_.done; +begin + Freemem(oldpal,SC.colourdepth*sizeof(RGBtype)); + Inherited done; +end; + +Procedure textpage_.draw; +var ylop,ypos,stpx,stpy:integer; + currline:textlineptr; +Begin + stpy:=25; + stpx:=80; + ypos:=y1-yoff; + t_col:=15; + currline:=pointer(screen); + For ylop:=0 to stpy do begin + {outtextline(x1-xoff,ypos,stpx,currline);} + inc(ypos,Fontheight); + inc(currline); + end; +End; + +Constructor textpage_.make(page:screenptr); +begin + inherited make(0,0,639,(Fontheight * 25)-1); + screen:=page; +end; + +constructor background_.create(x1_,y1_,x2_,y2_:integer;fgcol_,bgcol_:byte;pattern_:fillpatterntype); +begin + inherited create(x1_,y1_,x2_,y2_); + pattern:=pattern_; + fgcol:=fgcol_; + bgcol:=bgcol_; +end; + +const +colrange=512; +colstart=0; +procedure background_.draw; +begin + {stipcolourgridb(x1,y1,width+1,1+height div colrange,1,colrange,colstart);} + t_col:=fgcol; + setfillpattern(pattern,true); + t_fillcol:=bgcol; + bar(x1,y1,x2,y2); + setsolidfill; +end; + +constructor backpic_.create(x1_,y1_,x2_,y2_:integer;pic_:bitmaptypeptr); +begin + inherited create(x1_,y1_,x2_,y2_); + pic:=pic_; +end; + +procedure backpic_.draw; +var xlop,ylop:integer; +begin + for ylop:=0 to (y2 div pic^.size.y) do + for xlop:=0 to (x2 div pic^.size.x) do + putbitmap(x1+(xlop*pic^.size.x),y1+(ylop*pic^.size.y),pic); +end; + +Constructor bitmapwindow_.make(piccy:bitmaptypeptr;dpic:boolean); +begin + with piccy^ do + inherited make(0,0,size.x-1,size.y-1); + pic:=piccy; + destroypic:=dpic; +end; + +Destructor bitmapwindow_.done; +begin + if destroypic then + DestroyBitmap(pic); + inherited done; +end; + +procedure bitmapwindow_.draw; +begin + t_fillcol:=3; + putbitmap(x1-xoff,y1-yoff,pic); +end; + +procedure digitwindow_.draw; +begin + t_fillcol:=3; + bar(x1,y1,x2,y2); + drawdigit(x1+30,y1+30,digits[1],bigLCD); +end; + +procedure colourwindow_.draw; +begin + colourgrid(x1,y1,(x2-x1)div 10,(y2-y1)div 10,10,10,0); +end; + +constructor clock_.make; +begin + inherited make; + drawmode:=false; +end; + +procedure clock_.draw; +var x:integer; +begin + x:=10; + with currtime do begin + x:=10; + t_fillcol:=0; + if not drawmode then + bar(x1,y1,x2,y2); + if (oldtime.hour<>hour)or(not drawmode) then + lcd_num(x1+x,y1+10,hour mod 12,BigLcd,true); + inc(x,biglcd.size+2*(biglcd.width+20)); + + if (oldtime.min<>min)or(not drawmode) then + lcd_num(x1+x,y1+10,min,BigLcd,false); + inc(x,2*(biglcd.width+10)); + + if (oldtime.sec<>sec)or(not drawmode) then + lcd_num(x1+x,y1+10,sec,SmallLcd,true); + inc(x,smalllcd.size+2*(smalllcd.width+10)); + + if (oldtime.nsec<>nsec)or(not drawmode) then + lcd_num(x1+x,y1+10,nsec,SmallLcd,false); + end; +end; + +Procedure clock_.update; +begin + drawmode:=true; + oldtime:=currtime; + with currtime do + gettime(hour,min,sec,nsec); + drawview; + drawmode:=false; +end; + +{Analog Clock} +constructor Analogclock_.create(x1_,y1_,x2_,y2_:integer); +begin + inherited create(x1_,y1_,x2_,y2_); + DrawMode:=false; + alarmon:=false; +end; + +procedure Analogclock_.draw; +const size=3; + Offset=10; + +Var timelop:byte;AngleCount:word; + hlfx,hlfy:integer;precalc:real; + px,py:integer; + Hourhandsize:integer; + Minutehandsize:integer; + secondshandsize:integer; + +function GetAngle(time,stepsize:integer):real; +begin + GetAngle:=(pi/2)+(time*(2*pi))/stepsize; +end; + +Procedure DrawHand(time,Stepsize:integer;col:byte;size:integer;width:integer); +var precalc,precalcb:real; + p1,p2,p3,p4:pointtype; + +begin + T_col:=col; + T_fillcol:=col; + precalc:=GetAngle(time,stepsize); + p1.x:=round(hlfx+cos(precalc)); + p1.y:=round(hlfy+sin(precalc)); + precalcb:=(precalc+pi); + p2.x:=round(hlfx+cos(precalcb)*size); + p2.y:=round(hlfy+sin(precalcb)*size); + precalcb:=(precalc+offset); + p3.x:=round(hlfx+cos(precalcb)*width); + p3.y:=round(hlfy+sin(precalcb)*width); + precalcb:=(precalc-offset); + p4.x:=round(hlfx+cos(precalcb)*width); + p4.y:=round(hlfy+sin(precalcb)*width); + + {triangle(p1.x,p1.y,p3.x,p3.y,p2.x,p2.y); + triangle(p1.x,p1.y,p4.x,p4.y,p2.x,p2.y);} + line(p1.x,p1.y,p3.x,p3.y); + line(p3.x,p3.y,p2.x,p2.y); + line(p2.x,p2.y,p4.x,p4.y); + line(p4.x,p4.y,p1.x,p1.y); +end; + +begin + hlfx:=halfx+x1; + hlfy:=halfy+y1; + hourhandsize:=(width shr 2) +2; + minutehandsize:=(width shr 1) -12; + secondshandsize:=(width shr 1) -12; + + if not Drawmode then with currtime do begin + outbox(x1,y1,x2,y2); + + for timelop:=1 to 12 do begin + precalc:=GetAngle(timelop,12); + px:=hlfx+round(cos(precalc)*(width shr 1 -6)); + py:=hlfy+round(sin(precalc)*(height shr 1 -6)); + if timelop mod 3=0 then begin + T_fillcol:=12; + outboxcol(px-3,py-3,px+3,py+3); + end else + outbox(px+1,py+1,px-1,py-1); + end; + DrawHand(currtime.hour,720,darkblue,hourhandsize,8); + DrawHand(currtime.min,60,darkblue,minutehandsize,4); + DrawHand(currtime.sec,60,red,secondshandsize,1); + end else with oldtime do begin + if hour<>currtime.hour then + DrawHand(hour,720,midcol,hourhandsize,8); + if min<>currtime.min then + DrawHand(min,60,midcol,minutehandsize,4); + if sec<>currtime.sec then + DrawHand(sec,60,midcol,secondshandsize,1); + + DrawHand(currtime.hour,720,darkblue,hourhandsize,8); + DrawHand(currtime.min,60,darkblue,minutehandsize,4); + DrawHand(currtime.sec,60,red,secondshandsize,1); + end; +end; + +Procedure Analogclock_.update; +begin + oldtime:=currtime; + with currtime do begin + gettime(hour,min,sec,nsec); + hour:=(hour mod 12)* 60 + min; + end; + if oldtime.sec<>currtime.sec then begin + drawmode:=true; + drawview; + drawmode:=false; + end; + if (alarmon) then + if (alarm.hour=currtime.hour)and(alarm.min=currtime.min) then begin + sound(100);delay(10);nosound; + end; +end; + +procedure Analogclock_.setalarm(switch:boolean;hrs,min:word); +begin + alarm.hour:=(hrs mod 12)* 60 + min; + alarm.min:=min; + alarmon:=switch; +end; + +{Constructor starback_.create(xa,ya,xb,yb:integer); +begin + inherited create(xa,ya,xb,yb); + starfall.init; + starfall.move(0); + xoff:=halfx; + yoff:=halfy; +end; + +procedure starback_.draw; +begin + t_fillcol:=0; + bar(x1,y1,x2,y2); + starfall.draw; +end; + +procedure starback_.update; +begin + starfall.move(-5); + drawview; +end;} + + +Constructor infodialog_.create(xa,ya,xb,yb:integer;text:pchar;deltext_:boolean); +var loader:trect; +w,h:integer; +begin + inherited create(xa,ya,xb,yb); + options:=options or OfTopSelect; + w:=xb-xa; + h:=yb-ya; + insert(new(dialogback,create(x1,y1,x2,y2))); + actionwindow:= + new(textobject,make(text,TOintextbox,deltext_)); + insert(actionwindow); + + insert(new(bartype,create(x2-20,y1+9,15,h-38,0,0,0,ybardir))); + actionwindow^.ybar:=slidertype(tgroup(first)^.last); + insert(new(bartype,create(x1+5,y2-44,W-27,15,0,0,0,xbardir))); + actionwindow^.xbar:=slidertype(tgroup(first)^.last); + insert(new(textbutton,create(x2-45,y2-25,40,20,midcol,1,BM_releaseaction, + 1,CMDdismisview,'OK'))); + loader.rassign(x1+5,y1+5,x2-25,y2-49); + actionwindow^.changebounds(loader); +end; + + + +procedure infodialog_.handlevent(var event:tevent); +begin + inherited handlevent(event); + with event do + + if what=EvCommand then begin + case command of + CMDdismisview:begin + if deltext=true then with textobject(actionwindow)^ do + freemem(txt,strlen(txt)); + delete; + end; + CMDvalchanged:begin + with actionwindow^ do + if infoptr=xbar then + setoffsets(xbar^.offs,yoff) + else + setoffsets(xoff,ybar^.offs); + end; + end; + + end; +end; + +Constructor infodialogb_.create(xa,ya,xb,yb:integer;text:pchar); +var loader:trect; +begin + inherited create(xa,ya,xb,yb); + actionwindow:= + new(textobject,make(text,TOintextbox,false)); + insert(actionwindow); + + insert(new(bartype,create(x2-15,y1,15,height-16,0,0,0,ybardir))); + actionwindow^.ybar:=slidertype(tgroup(first)^.last); + insert(new(bartype,create(x1,y2-15,width-16,15,0,0,0,xbardir))); + actionwindow^.xbar:=slidertype(tgroup(first)^.last); + loader.rassign(x1,y1,x2-16,y2-16); + actionwindow^.changebounds(loader); +end; + +procedure infodialogb_.handlevent(var event:tevent); +begin + inherited handlevent(event); + with event do + if what=EvCommand then case command of + CMDdismisview:delete; + CMDvalchanged:begin + with actionwindow^ do + if infoptr=xbar then + setoffsets(xbar^.offs,yoff) + else + setoffsets(xoff,ybar^.offs); + end; + end; +end; + +function loadtext(filename:string):pchar; +var lastchar,textfile:pchar; + recsize:word; + f:file; +begin + recsize:=1; + assign(f,filename); + reset(f,recsize); + getmem(textfile,filesize(f)); + blockread(f,textfile^,filesize(f),recsize); + lastchar:=textfile; + inc(lastchar,filesize(f)); + LastChar^:=chr(0); + close(f); + loadtext:=textfile; + +end; + +Constructor MoveTitle_.Create(xa,ya,xb,yb:integer;Name:string); +begin + inherited create(xa,ya,xb,yb); + options:=options or (OfNoOverlap+Oftopselect); + add_title(@self,name); +end; + +Procedure MoveTitle_.Handlevent(var event:Tevent); +begin + inherited Handlevent(event); + with event do + if what=EvCommand then if Command=CMDmoveparent then + dragview(1,owner^,50,50,1000,1000); +end; + +Procedure Statusview_.handlevent(var event:tevent); +begin + Inherited handlevent(event); + if event.what and EvMouseDown<>0 then + dragview(1,owner^,0,0,1000,1000); +end; + +Procedure statusview_.update; +begin + if memavail<>memoryleft then begin + memoryleft:=memavail; + drawview; + end else + if oldscan<>scan then begin + oldscan:=scan; + drawview; + end else + if oldscancode<>scancode then begin + oldscancode:=scancode; + drawview; + end else + if oldcharcode<>charcode then begin + oldcharcode:=charcode; + drawview; + end; + if oldioresult<>ioresult then begin + oldioresult:=ioresult; + drawview; + end; + +end; + +Procedure statusview_.draw; +begin + draw3dborder(x1,y1,x2,y2,false); + draw3dborder(x1+1,y1+1,x2-1,y2-1,true); + t_fillcol:=midcol; + bar(x1+2,y1+2,x2-2,y2-2); + t_col:=textcol; + outtextxy3d(x1+4,y1+4, 'key :'+charcode); + outtextxy3d(x1+4,y1+4+(fontheight), 'ord :'+itoa(ord(charcode))); + outtextxy3d(x1+4,y1+4+(fontheight*2),'scode:'+itoa(scancode)); + outtextxy3d(x1+4,y1+4+(fontheight*3),'mem :'+itoa(memavail)); + outtextxy3d(x1+4,y1+4+(fontheight*4),'scan :'+itoa(scan)); + outtextxy3d(x1+4,y1+4+(fontheight*5),'io :'+itoa(ioresult)); +end; + +Procedure Statusviewb_.handlevent(var event:tevent); +begin + Inherited handlevent(event); + if event.what and EvMouseDown<>0 then + dragview(1,owner^,0,0,1000,1000); +end; + +Procedure statusviewb_.update; +begin + if val1^<>oldval1 then begin + + oldval1:=val1^; + drawview; + end; + +end; + +Procedure statusviewb_.draw; +begin + draw3dborder(x1,y1,x2,y2,false); + draw3dborder(x1+1,y1+1,x2-1,y2-1,true); + t_fillcol:=midcol; + bar(x1+2,y1+2,x2-2,y2-2); + t_col:=textcol; + outtextxy3d(x1+4,y1+4,'val1 :'+ftoa(val1^,3,3)); + +end; + +procedure AddMessage(Cancel,Ok:word;message:Pchar;pid_:word;group:tgroup); +var p:tview; +begin + with group^ do begin + if (cancel=0) then + p:=new(Messagebox,create(0,0,ok,message)) + else + p:=new(Choicebox,create(0,0,cancel,ok,message)); + tgroup(add_and_draw(p,VPcentre,pid_))^.last^.select; + end; +end; + +Procedure Desktoptype_.handlevent(var event:tevent); +begin + inherited handlevent(event); + with event do begin + if (what=EvCommand) then + if owner<>nil then + owner^.handlevent(event); + end; +end; + + + + +end. diff --git a/DISKOP.PAS b/DISKOP.PAS new file mode 100644 index 0000000..1d0d80c --- /dev/null +++ b/DISKOP.PAS @@ -0,0 +1,280 @@ +Unit diskop; +{$X+}{$a+} + +INTERFACE + +uses dos,tmaths,ttypes; +const +maxbuff=20000; + +type +fragtype=(D,P,N,E); +bufferedblock=object + f:file; + fsize:longint; + blockpos,blocksize,blockmax:word; + buffer,bufferpos:^byte; + eof:boolean; + + function open(filename:string):boolean; + function fpos:longint; + procedure fseek(pos:longint); + procedure fskip(pos:longint); + procedure blockread(buf:byteptr;count:word); + function get:byte; + procedure close; +end; + +Function cd(path:string):string; +Function fragname(path:string;frag:fragtype):string; +Function gtdir:string; +Function numoffiles(path,filter:string;attrfilter:word):integer; +Function NumOfDrives:byte; +Function CurrentDrive:byte; +Function Truncatepath(path:string):string; +Function fexist(path:string):boolean; +Function Pexist(path:string):boolean; +Function instring(name:string;testchar:char):boolean; +{Function readkey:char; +Function keypressed:boolean;} + +IMPLEMENTATION + +Function CurrentDrive:byte;assembler; +asm + mov ah,19h + int 21h +end; + +function NumOfDrives:byte;assembler; +asm + mov ah,19h {get current disk handle} + int 21 + mov dl,ah {load this into next function} + mov ah,0Eh + int 21h {call interrupt} +end; + + +function bufferedblock.open(filename:string):boolean; +var maxavailable:longint; + var recsize:word; +begin + if (not fexist(filename)) then begin open:=false;exit;end; + recsize:=1; + assign(f,filename); + reset(f,recsize); + fsize:=filesize(f); + maxavailable:=maxavail; + {keep within 16bit range} + if maxavailable>maxbuff then maxavailable:=maxbuff; + {if filesize is smaller, fine} + blocksize:=smaller(maxavailable,fsize); + getmem(buffer,blocksize); + bufferpos:=buffer; + blockmax:=blocksize; + blockpos:=blockmax; + eof:=false; + open:=true; +end; + +function bufferedblock.get; +var recsize:word; +begin + recsize:=1; + {if end of block and not end of file....} + if (fsize>1)and(not eof) then begin + if blockpos=blockmax then begin + blockmax:=smaller(fsize,blocksize); + system.blockread(f,buffer^,blockmax,recsize); + blockpos:=1; + bufferpos:=buffer; + end else begin + inc(blockpos); + inc(bufferpos); + end; + dec(fsize); + get:=bufferpos^; + end else begin + {end of file, set flag and exit} + get:=0; + eof:=true; + end; + {writeln(eof);} +end; + +procedure bufferedblock.close; +begin + freemem(buffer,blocksize); + system.close(f); +end; + +function bufferedblock.fpos:longint; +begin + fpos:=filepos(f)+blockpos-blockmax-1; +end; + +procedure bufferedblock.blockread(buf:byteptr;count:word); +var lop:word; +begin + for lop:=1 to count do begin + buf^:=get; + inc(buf) + end; +end; + +procedure bufferedblock.fseek(pos:longint); +var lop:longint; + recsize:word; +begin + recsize:=1; + Seek(f,pos); + fsize:=filesize(f)-pos; + blockmax:=smaller(fsize,blocksize); + blockpos:=blockmax; + bufferpos:=buffer; + eof:=false; +end; + +procedure bufferedblock.fskip(pos:longint); +begin + fseek(filepos(f)+blockpos-blockmax-1+pos); +end; + +{Function readkey:char; +var out:char; +Begin + asm + mov ah,0 + int 16h + mov out,al + cmp al,0 + jnz @end + mov out,ah + @end: + end; + readkey:=out; +end; + +Function keypressed:boolean; +Begin + keypressed:=port[$60]<>0; +end;} + +Function fexist(path:string):boolean; +var f:file; +Begin + + (*{$I-} + Assign(f,path); + reset(f); + + close(f); + + {$I+} + FExist := (IOResult = 0);*) + Fexist:=(fsearch(path,'')<>''); +end; + +Function Pexist(path:string):boolean; +var dirinfo:searchrec; +Begin + {$I-} + FindFirst(path+'*.*', anyfile, DirInfo); + {$I+} + PExist := (IOResult = 0) and (path <> ''); +end; + +Function cd(path:string):string; +Begin + if (copy(path,length(path),1)='\') and (length(path)<>3) then + path:=copy(path,1,length(path)-1); + {$I-}; + chdir(path); + {$I+}; + if ioresult=0 then path:=gtdir + else path:='nil'; + cd:=path; +end; + +Function gtdir:string; +var temp:string; +Begin + getdir(0,temp); + if temp[length(temp)]<>'\' then + temp:=temp+'\'; + gtdir:=temp; +end; + +Function Truncatepath(path:string):string; +Var lop:byte; +Temp:string; +Begin + lop:=Length(path); + + Path:=copy(path,1,length(path)-1); + While (path[lop]<>'\') and (lop>0) do + dec(lop); + truncatepath:=copy(path,1,lop); +End; + +Function fragname(path:string;frag:fragtype):string; +Var Dir: DirStr;Name: NameStr;Ext: ExtStr; +Begin + fsplit(path,dir,name,ext); + case frag of + d:fragname:=copy(dir,1,3); + p:fragname:=dir; + n:fragname:=name; + e:fragname:=ext + end; +end; + +Function instring(name:string;testchar:char):boolean; +var lop:byte;out:boolean; +Begin + out:=false;lop:=1; + while (lop<=length(name))and(out=false) do begin + out:=name[lop]=testchar; + inc(lop); + end; + instring:=out; +end; + +Function numoffiles(path,filter:string;attrfilter:word):integer; +var count:word;dirinfo:searchrec; +Begin + count:=0; + FindFirst(path+filter, attrfilter, DirInfo); + while DosError=0 do + begin + if (dirinfo.attr=attrfilter)or((attrfilter=anyfile)and(dirinfo.attr + <>directory){and(DirInfo.Name<>'.')and(DirInfo.Name<>'..')}) then + inc(count); + FindNext(DirInfo); + end; + numoffiles:=count; +end; + +{Procedure inputdrives(var disks:menutype); +Var lop,count:byte; +Begin + count:=0; + For lop:=0 to 25 do + if disksize(lop)<>-1 then inc(count); + with disks do + Begin + maxopts:=count;maxylen:=4; + getmem(attrib,1+maxopts);getmem(info,(1+maxopts)*21); + count:=0; + For lop:=0 to 25 do + if disksize(lop)<>-1 then + Begin + disks.info^[count]:='Drive '+chr(65+count); + disks.attrib^[count]:=0; + inc(count); + end; +end; +end;} +End. + diff --git a/DMA.PAS b/DMA.PAS new file mode 100644 index 0000000..4650e8d --- /dev/null +++ b/DMA.PAS @@ -0,0 +1,204 @@ +Unit DMA; + +INTERFACE +const +DMA_Channel=0; +DMAbaseAdd=0; +DmaPageReg=0; + + +Type +DMAinfo=record + Page:byte; + Offset:word; + Length:word; +end; + +IMPLEMENTATION + +{ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + ; IN: DX:AX = segment/offset address of memory area + ; + ;OUT: DH = Page (0-F) (DL is destroyed) + ; AX = Offset + ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ} + +Procedure MakePage;assembler; +asm + mov bl,dh {save lower byte of segment} + shr bl,4 {isolate upper 4 bits of segment} + shl dx,4 {make segment into ABS address} + add ax,dx {add the offset and put it in AX} + adc bl,0 {complete the addition} + mov dh,bl {put the PAGE where it goes} + {DH:AX is now the PAGE:OFFSET address} +end; + +Procedure MakePageVars(inp:pointer;var outpage:byte;var outoffs:word);assembler; +asm + mov bl,byte ptr inp+3 {save lower byte of segment} + mov ax,word ptr inp + + shr bl,4 {isolate upper 4 bits of segment} + shl dx,4 {make segment into ABS address} + add ax,dx {add the offset and put it in AX} + adc bl,0 {complete the addition} + + les di,outoffs + mov es:[di],ax + les di,outpage + mov es:[di],bl +end; + +{ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + ; This routine programs the DMAC for channels 0-7 + ; + ; IN: [DMA_Channel], [DMAbaseAdd], [DMApageReg] must be setup + ; [DAMBaseAdd] = Memory Address port + ; + ; dh = mode + ; ax = address + ; cx = length + ; dl = page + ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ} + +Procedure Prog_DMA47;assembler; +asm + push bx + mov bx,ax + + mov al,[DMA_Channel] + out 0D4h,al { mask reg bit} + + sub al,al + out 0D8h,al { clr byte ptr} + + mov al,[DMA_Channel] + sub al,4 + add al,dh + out 0D6h,al { set mode reg} + + push dx + + mov dx,[DMAbaseAdd] + mov al,bl + out dx,al ;{set base address low} + mov al,bh + out dx,al { set base address high} + + add dl,2 {point to length} + mov al,cl + out dx,al { set length low} + mov al,ch + out dx,al { set length high} + + pop dx + + mov al,dl + mov dx,[DmaPageReg] + out dx,al { set DMA page reg} + + mov al,[DMA_Channel] + and al,00000011b + out 0D4h,al { unmask (activate) dma channel} + pop bx + ret +END; + +{ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; This routine programs the DMAC for channels 0-7 +; +; IN: [DMA_Channel], [DMAbaseAdd], [DMApageReg] must be setup +; [DAMBaseAdd] = Memory Address port +; +; dh = mode +; ax = address +; cx = length +; dl = page +ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ} + +procedure Prog_DMA;assembler; +asm + push bx + mov bx,ax + + cmp byte ptr [DMA_Channel],4 + jb @@DoDMA03 + + mov al,[DMA_Channel] + out 0D4h,al { mask reg bit} + + sub al,al + out 0D8h,al { clr byte ptr } + + mov al,[DMA_Channel] + sub al,4 + add al,dh + out 0D6h,al { set mode reg} + + push dx + + mov dx,[DMAbaseAdd] + mov al,bl + out dx,al { set base address low} + mov al,bh + out dx,al { set base address high} + + add dl,2 {point to length} + mov al,cl + out dx,al { set length low} + mov al,ch + out dx,al { set length high} + + pop dx + + mov al,dl + mov dx,[DmaPageReg] + out dx,al { set DMA page reg} + + mov al,[DMA_Channel] + and al,00000011b + out 0D4h,al { unmask (activate) dma channel} + pop bx + ret + +@@DoDMA03: + mov al,4 + add al,[DMA_Channel] + out 0Ah,al { mask reg bit} + + sub al,al + out 0Ch,al { clr byte ptr} + + mov al,dh + add al,[DMA_Channel] + out 0Bh,al { set mode reg} + + push dx + + mov dx,[DMAbaseAdd] + mov al,bl + out dx,al { set base address low} + mov al,bh + out dx,al { set base address high} + + inc dx {point to length} + mov al,cl + out dx,al { set length low} + mov al,ch + out dx,al { set length high} + + pop dx + + mov al,dl + mov dx,[DmaPageReg] + out dx,al { set DMA page reg} + + mov al,[DMA_Channel] + out 0Ah,al { unmask (activate) dma channel} + pop bx + ret + +end; + +end. \ No newline at end of file diff --git a/EMSUNIT.PAS b/EMSUNIT.PAS new file mode 100644 index 0000000..8a71120 --- /dev/null +++ b/EMSUNIT.PAS @@ -0,0 +1,302 @@ +Unit emsunit; +INTERFACE +uses dos; + + +Type + ST3 = string[3]; + ST80 = string[80]; + ST5 = string[5]; + +Const + EMS_INT = $67; + DOS_Int = $21; + GET_PAGE_FRAME = $41; + GET_UNALLOCATED_PAGE_COUNT = $42; + ALLOCATE_PAGES = $43; + MAP_PAGES = $44; + MAP_MULTIPLE_PAGES = $50; + DEALLOCATE_PAGES = $45; + GET_VERSION = $46; + STATUS_OK = 0; + EMS_current_handle:word=64000; + + {important global varibales!} + var + + EMS_Base_Address:word; {base segment of ems page frame} + EMS_Total_Pages:word; + EMS_Pages_Available:word; + EMS_version:st3; {3 character string containing version number} + + {misc functions} + Function Hex_String (Number: Integer): ST5; + {init & status functions} + Function EMS_Installed: Boolean; + Procedure Error (Error_Message: ST80; Error_Number: Integer); + + {allocation, mapping and deallocation functions} + Function EMS_Allocate(Var Handle: word;Pages_Needed: word): byte; + Function EMS_Map(Handle, Logical_Page:word;physical_page:byte): byte; + Function EMS_Deallocate(Handle: word): byte; + Function EMS_MapMultiple(Handle,count:word; mappingdata:pointer;func:byte): byte; + + IMPLEMENTATION + + + {------------------------------------------------------------} + { The function Hex_String converts an integer into a four } + { character hexadecimal number (string) with leading zeros. } + {------------------------------------------------------------} + Function Hex_String (Number: Integer): ST5; + Function Hex_Char (Number: Integer): Char; + Begin + If Number < 10 then + Hex_Char := Char (Number + 48) + else + Hex_Char := Char (Number + 55); + end; { Function Hex_char } + + Var + S: ST5; + + Begin + S := ''; + S := Hex_Char ((Number shr 1) shr 11); + Number := (((Number shr 1) mod 2048) shl 1) + (Number and 1); + S := S + Hex_Char (Number shr 8); + Number := Number mod 256; + S := S + Hex_Char (Number shr 4); + Number := Number mod 16; + S := S + Hex_Char (Number); + Hex_String := S + 'h'; + + + end; { Function Hex_String } + + + {------------------------------------------------------------} + { The function EMS_Installed checks to see if the } + { EMS is loaded in memory. It does this by looking } + { for the string 'EMSXXXX0', which should be located } + { at 10 bytes from the beginning of the code segment the } + { EMS interrupt, 67h, points to. } + { Also gets system information } + {------------------------------------------------------------} + Function EMS_Installed: Boolean; + Var + EMS_Device_Name : string[8]; + Int_67_Device_Name: string[8]; + Position : integer; + Regs : registers; + + Begin + Int_67_Device_Name := ''; + EMS_Device_Name := 'EMMXXXX0'; + with Regs do + Begin + {----------------------------------------------------} + { Get the code segment interrupt 67h points to } + { the EMS interrupt by using DOS function 35h. } + { (get interrupt vector) } + {----------------------------------------------------} + AH := $35; + AL := EMS_INT; + Intr (DOS_Int, Regs); + {----------------------------------------------------} + { The ES pseudo-register contains the segment } + { address pointed to by interrupt 67h. Create an } + { eight character string from the eight successive } + { bytes at address ES:$000A (10 bytes from ES) } + {----------------------------------------------------} + For Position := 0 to 7 do + Int_67_Device_Name := + Int_67_Device_Name + Chr (mem[ES:Position + $0A]); + EMS_Installed := True; + {----------------------------------------------------} + { If the string is the EMS manager signature, } + { 'EMSXXXX0', then EMS is installed and ready for } + { use. If not, then EMS is not present. } + {----------------------------------------------------} + If Int_67_Device_Name <> EMS_Device_Name + then EMS_Installed := False; + end; { with Regs do } + + asm + mov ah,GET_UNALLOCATED_PAGE_COUNT + int EMS_INT + {----------------------------------------------------} + { Unload the pseudo-registers after invoking EMS. } + { BX = currently unallocated pages } + { DX = total pages in the system } + { AH = status } + {----------------------------------------------------} + mov EMS_Pages_Available,bx + mov EMS_Total_pages,dx + + {----------------------------------------------------} + { AH = get page frame segment function } + {----------------------------------------------------} + mov ah,GET_PAGE_FRAME + int EMS_INT + {----------------------------------------------------} + { Unload the pseudo-registers after invoking EMS. } + { BX = page frame segment address } + { AH = status } + {----------------------------------------------------} + mov EMS_BASE_Address,BX + + {----------------------------------------------------} + { + { AH = get EMS version function } + + mov ah,GET_VERSION + int EMS_INT + {----------------------------------------------------} + { If the version number returned was OK, then } + { convert it to a three-character string. } + {----------------------------------------------------} + cmp ah,status_ok + jnz @error + {------------------------------------------------} + { The upper four bits of AH are the integer } + { portion of the version number, the lower four } + { bits are the fractional portion. Convert the } + { integer value to ASCII by adding 48. } + {------------------------------------------------} + lea di,EMS_Version + mov dh,3 + mov ds:[di],dh + + {Integer_Part := Char (AL shr 4 + 48);} + mov dh,al + shr dh,4 + add dh,48 + {mov Integer_Part,dh} + mov ds:[di+1],dh + mov dh,'.' + mov ds:[di+2],dh + {Fractional_Part := Char (AL and $F + 48);} + mov dh,al + and dh,$f + add dh,48 + {mov fractional_Part,dh} + mov ds:[di+3],dh + @error: + end; + end; { Function EMS_Installed } + + {------------------------------------------------------------} + { This function requests the specified number of pages } + { from the EMS. } + {------------------------------------------------------------} + Function EMS_Allocate(Var Handle: word;Pages_Needed: word): byte;assembler; + asm + {----------------------------------------------------} + { Allocate the specified number of pages from EMS. } + { Load pseudo-registers prior to invoking EMS. } + { AH = allocate pages function. } + { BX = number of pages to allocate. } + {----------------------------------------------------} + mov AH, ALLOCATE_PAGES; + mov BX, Pages_Needed; + int EMS_int + {----------------------------------------------------} + { Unload the pseudo-registers after invoking EMS. } + { DX = EMS handle } + { AH = status } + {----------------------------------------------------} + les di,Handle + mov es:[di],dx + {move into result variable} + mov al,ah + end; + + {------------------------------------------------------------} + { This function maps a logical page allocated by the } + { Allocate_Expanded_Memory_Pages function into one of the } + { four physical pages. } + {------------------------------------------------------------} + Function EMS_MapMultiple(Handle,count:word; mappingdata:pointer;func:byte): byte;assembler; + asm + {----------------------------------------------------} + { Map a logical page at a physical page. } + { Load pseudo-registers prior to invoking EMS. } + { AH = map page function } + { DX = handle } + { CX = Count } + { AL = SUB FUNCTION } + { DS:SI = POINTER TO DATA } + {----------------------------------------------------} + mov bx,ds + + mov ah,MAP_MULTIPLE_PAGES + mov al,func + mov DX,Handle + mov cx,count + + lds si,mappingdata + + int EMS_INT + {move into result register} + mov al,ah; + mov ds,bx + end; { Function Map_Expanded_Memory_Pages } + + Function EMS_Map(Handle, Logical_Page:word; Physical_Page: byte): byte;assembler; + asm + {----------------------------------------------------} + { Map a logical page at a physical page. } + { Load pseudo-registers prior to invoking EMS. } + { AH = map page function } + { DX = handle } + { BX = logical page number } + { AL = physical page number } + {----------------------------------------------------} + mov ah,MAP_PAGES + mov DX,Handle + mov EMS_current_handle,DX; + {0-3} + mov BX,Logical_Page + mov AL,Physical_Page + int EMS_INT + {move into result register} + mov al,ah; + end; { Function Map_Expanded_Memory_Pages } + + {------------------------------------------------------------} + { This function releases the EMS memory pages allocated to } + { us, back to the EMS memory pool. } + {------------------------------------------------------------} + Function EMS_Deallocate(Handle: word): byte;assembler; + asm + {----------------------------------------------------} + { Deallocate the pages allocated to an EMS handle. } + { Load pseudo-registers prior to invoking EMS. } + { AH = deallocate pages function } + { DX = EMS handle } + {----------------------------------------------------} + mov ah,DEALLOCATE_PAGES + mov dx,Handle + int EMS_INT + {----------------------------------------------------} + { AH = status } + {----------------------------------------------------} + mov al,ah + end; { Function Deallocate_Expanded_Memory_Pages } + + {------------------------------------------------------------} + { This procedure prints an error message passed by the } + { caller, prints the error code passed by the caller in hex, } + { and then terminates the program with an error level of 1. } + {------------------------------------------------------------} + Procedure Error (Error_Message: ST80; Error_Number: Integer); + Begin + Writeln (Error_Message); + Writeln (' Error_Number = ', Hex_String (Error_Number)); + Writeln ('EMS test program aborting.'); + Halt (1); + end; { Procedure Error } + +end. + diff --git a/GADGETS.PAS b/GADGETS.PAS new file mode 100644 index 0000000..4b86f3b --- /dev/null +++ b/GADGETS.PAS @@ -0,0 +1,89 @@ +Unit gadgets; +{$X+}{$g+}{$a+} + +INTERFACE + +uses Gbasics,views,ggraph,twindraw,twinb,msmouse,tmaths,SinCos; +type + +angle_box=object(tview_) + currangle,xoffs,yoffs,halfheight,halfwidth:integer; + constructor create(x1_,y1_,x2_,y2_:integer); + + procedure Tchangebounds(var bounds:trect);virtual; + procedure draw;virtual; + private + procedure calcoffs; + procedure drawline; +end; + + +IMPLEMENTATION + +constructor angle_box.create(x1_,y1_,x2_,y2_:integer); +begin + currangle:=0; + inherited create(x1_,y1_,x2_,y2_); + calcoffs; +end; + +procedure angle_box.calcoffs; +begin + xoffs:=x1+halfx; + yoffs:=y1+halfy; +end; + +procedure angle_box.Tchangebounds(var bounds:trect); +begin + setbounds(bounds); + calcoffs; +end; + +procedure angle_box.drawline; +const +inner_range=6; +begin + line(xoffs,yoffs, + xoffs+trunc((cos(currangle)*(halfwidth-inner_range))), + yoffs+trunc((sin(currangle)*(halfheight-inner_range)))); +end; + +procedure angle_box.draw; +const +stp=16; +marker_length=2; +extra_marker=maxangle div 8; +var lop:integer; +Ccos,Csin:real; +begin + outbox(x2,y2,x1,y1); + for lop:=0 to stp do begin + Ccos:=cos((lop*2*pi)/ stp); + Csin:=sin((lop*2*pi)/ stp); + line(xoffs+trunc(Ccos*(halfwidth-1)), + yoffs+trunc(Csin*(halfheight-1)), + xoffs+trunc(Ccos*(halfwidth-marker_length-1)), + yoffs+trunc(Csin*(halfheight-marker_length-1))); + end; + drawline; +end; + +{procedure angle_box.handle; +const +quater=maxangle div 4; +begin + while chkicon>0 do begin + mpos; + if ms_moved then begin + mouseoff; + t_col:=midcol;drawline; + dec(currangle,oldxm-xm); + currangle:=currangle and maxangle_mask; + t_col:=darkcol;drawline; + ;mouseon; + end; + end; +end;} + + +end. \ No newline at end of file diff --git a/GBASICS.PAS b/GBASICS.PAS new file mode 100644 index 0000000..5f945a2 --- /dev/null +++ b/GBASICS.PAS @@ -0,0 +1,952 @@ +unit Gbasics; + + +{Graphics Basics} +{$X+}{$a+} +INTERFACE + +uses ttypes,chardef,tmaths; + +type + +hlinetypeptr=^hlinetype; +hlinetype=record + x1,x2:integer; +end; + + +bytepointtypeptr=^bytepointtype; +bytepointtype=object + x,y:byte; + procedure moveto(x_,y_:byte); +end; + + +pointtypeptr=^pointtype; +pointtype=object + x,y:integer; + procedure moveto(x_,y_:integer); +end; + +pointtypearray=^pointtypearray_; + pointtypearray_=array[0..0] of pointtype; + +{used to initialize a graphics mode} + +screenidtype=record + Driver:byte; {screen mode describes the general graphics driver} + graphmode:byte; {Graph mode is the exact mode that the above driver understands} + colourdepth:word; {the amount of colours available with this mode} + size:pointtype; {resolution of the screen} + bitplanes:byte; {Number of bits per pixel} +end; + + +const +{these are used in 16 colour or plainiar modes. They are included in here +instead of inside those specific Libraries as the 16 colour bitmap routines +are always included and will need these constants} +singlepixelbitmasks:array[0..7] of byte= +(128,64,32,16,8,4,2,1); +left_pixelbitmasks:array[0..7] of byte= +(255,127,63,31,15,7,3,1); +right_pixelbitmasks:array[0..7] of byte= +(0,128,192,224,240,248,252,254); + +{dirty rectangle constants} + +RSlist=2; +RSobscured=1; +RSnooverlap=0; + + +{Logical modes} +xorput=24; +andput=$10; +orput=$20; + +{graphic driver identifiers} +STnull=0; +STvga_plainiar=1; +STbitmap_plainiar=2; +STvga_flat=3; +STbitmap_flat=4; +STsvga_flat=5; +STxvga_plainiar=6; + +{Video modes} +{16 colour plainiar 64k} +VGA320x200x16:ScreenIdType=(Driver:STvga_plainiar;GraphMode:$d;ColourDepth:16;size:(x:320;y:200);bitplanes:4); +VGA640x200x16:ScreenIdType=(Driver:STvga_plainiar;GraphMode:$e;ColourDepth:16;size:(x:640;y:200);bitplanes:4); +VGA640x350x16:ScreenIdType=(Driver:STvga_plainiar;GraphMode:$10;ColourDepth:16;size:(x:640;y:350);bitplanes:4); +VGA640x480x16:ScreenIdType=(Driver:STvga_plainiar;GraphMode:$12;ColourDepth:16;size:(x:640;y:480);bitplanes:4); +SVGA800x600x16:ScreenIdType=(Driver:STvga_plainiar;GraphMode:102;ColourDepth:16;size:(x:800;y:600);bitplanes:4); +SVGA1024x768x16:ScreenIdType=(Driver:STvga_plainiar;GraphMode:104;ColourDepth:16;size:(x:1024;y:768);bitplanes:4); +SVGA1280x1024x16:ScreenIdType=(Driver:STvga_plainiar;GraphMode:106;ColourDepth:16;size:(x:1280;y:1024);bitplanes:4); + +{256 colour flat 64k} +VGA320x200x256:ScreenIdType=(Driver:STvga_flat;GraphMode:$13;ColourDepth:256;size:(x:320;y:200);bitplanes:1); + +{256 colour flat >64k} +SVGA640x400x256:ScreenIdType=(Driver:STsvga_flat;GraphMode:5;ColourDepth:256;size:(x:640;y:400);bitplanes:1); +SVGA640x480x256:ScreenIdType=(Driver:STsvga_flat;GraphMode:1;ColourDepth:256;size:(x:640;y:480);bitplanes:1); +SVGA800x600x256:ScreenIdType=(Driver:STsvga_flat;GraphMode:3;ColourDepth:256;size:(x:800;y:600);bitplanes:1); +SVGA1024x768x256:ScreenIdType=(Driver:STsvga_flat;GraphMode:5;ColourDepth:256;size:(x:1024;y:768);bitplanes:1); + +{16 million colour flat >64k} +SVGA640x480x16m:ScreenIdType=(Driver:STsvga_flat;GraphMode:$12;ColourDepth:256;size:(x:640;y:480);bitplanes:1); + + +{256 colour, unchained 64k} + +XVGA320x200x256:ScreenIdType=(Driver:STxvga_plainiar;GraphMode:$14;ColourDepth:256;size:(x:320;y:200);bitplanes:6); +XVGA320x240x256:ScreenIdType=(Driver:STxvga_plainiar;GraphMode:$15;ColourDepth:256;size:(x:320;y:240);bitplanes:6); +XVGA400x300x256:ScreenIdType=(Driver:STxvga_plainiar;GraphMode:$16;ColourDepth:256;size:(x:400;y:300);bitplanes:6); +XVGA640x400x256:ScreenIdType=(Driver:STxvga_plainiar;GraphMode:$18;ColourDepth:256;size:(x:640;y:400);bitplanes:6); +XVGA400x600x256:ScreenIdType=(Driver:STxvga_plainiar;GraphMode:$17;ColourDepth:256;size:(x:400;y:600);bitplanes:6); + +BMnull=0; +BMplanes=1; +BMflat=2; + +{ +clip area constants + ÚÄÄÄÂÄÄÄÂÄÄÄÂÄÄÄmiddle = $0F +ÉÍÍÍÑÍÍÍÑÍÍÍÑÍÍÍÑÍÏÍÑÍÏÍÑÍÏÍÑÍÏÍ» +ºmsb³ ³ ³ ³ ³ ³ ³lsbº +ÈÍÑÍÏÍÍÍÏÍÑÍÏÍÑÍÏÍÑÍÏÍÑÍÏÍÑÍÏÍÑͼ + ÀÄÄÄÂÄÄÄÙ ³ ³ ³ ³ ÀÄÄÄRight = $01 + ³ ³ ³ ³ ÀÄÄÄÄÄÄÄBellow = $02 + Undefined ³ ³ ÀÄÄÄÄÄÄÄÄÄÄÄLeft = $04 + ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄabove = $08 + ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄrelative = $10} + +right =$01; +bellow =$02; +left =$04; +above =$08; + +above_right=above+right; +bellow_right=bellow+right; +above_left=above+left; +bellow_left=bellow+left; +middle=above+bellow+right+left; +type +dword=longint; + +prect=^trect; +prectlist=^rectlist; +Trect=object + x1,y1,x2,y2:integer; + + procedure Rpos(xp,yp:integer); + procedure Rmove(xa,ya:integer); + procedure Rgrow(xg,yg:integer); + procedure Rassign(x1_,y1_,x2_,y2_:integer); + function contains(x,y:integer):boolean; + + function Clipin(var xa,ya,xb,yb:integer):boolean; + function Clipout(var xa,ya,xb,yb:integer):boolean; + procedure union(const r:trect); + function intersect(const r:trect):boolean; + function overlap(const r:trect):boolean; + function empty:boolean; + function inside(const r:trect):boolean; + function equals(const r:trect):boolean; + function concatable(const r:trect):boolean; + + function cutfrom(r:trect):prectlist; + function halfx:integer; + function halfy:integer; + function height:integer; + function width:integer; +end; + +rectlist=object(trect) + next:prectlist; +end; + +ScreenDataType=record + Driver:byte; {screen mode describes the general graphics driver} + graphmode:byte; {Graph mode is the exact mode that the above driver understands} + colourdepth:word; {the amount of colours available with this mode} + size:pointtype; {resolution of the screen} + bitplanes:byte; {Number of bitplanes} + + nopages:byte; {number of pages available in memory} + bitsperpixel:byte; {how many bits per pixel} + + scrptr:bytearray; + scrptrs:array[0..3] of bytearray; + startoffsets:array[0..800]of word; {wordarray; {Used for quick access into the screen, an LUT for the addresses of scanlines} + + + + pagesize:dword; {size in bytes of the screen} + + {quick access stuff} + + Qoffset:dword; {address position of the currentpixel as an address} + Qbitoffset:byte; {byte mask for current pixel} + ScreenPort,Viewport:trect; + case byte of + 0:(offsb:byte); + 1:(offsw:word); + 1:(offsd:dword); {width of the screen in bytes} + +end; + +BitmapTypeptr=^BitmapType; +Bitmaptype=record + bitmaptype:byte; + size:pointtype; + planesize:dword; + BitsPerPixel:byte; + bitplanes:byte; + xoff:word; + Qbitoffset:byte; {used in plainiar colour modes for fast drawing} + memallocated:boolean; + case byte of + 0:(flatdata:bytearray); + 1:(planedata:array[0..3]of bytearray); +end; + +textlineptr=^textline; +textline=array[0..79] of word; +fillpatterntype=array[0..7] of byte; +fillptr=^fillpatterntype; + +var +SC:ScreenDataType; {screen context} +BC:ScreenDataType; {bitmap context} + +{Current Colours & writemode } +T_fillcol,T_col,T_writemode:byte; +tcharset:charsettype; +{for fill patterns} + +maskword:word; +maskbyte:byte absolute maskword; +fillpattern:fillpatterntype; +maskbackground:boolean; +nullpattern:boolean; + +{global rectangle information} +lastrect:prectlist; +Rectlist_status:byte; +Rect_count:byte; + +procedure destroyplist(p:prectlist); +function CreateBitmap(xlen_,ylen_:word;bitplanes_,mode:byte):BitmapTypeptr; +function CreateBitmapFromSource(newpic:bitmaptypeptr;xlen_,ylen_:word;bitplanes_,mode:byte;src:bytearray):BitmapTypeptr; +procedure DestroyBitmap(Bitmap:BitmapTypeptr); +procedure ResizeBitmap(xlen_,ylen_:word;Bitmap:BitmapTypeptr); +function insiderect(x1,y1,x2,y2,x,y:integer):boolean; + + +IMPLEMENTATION + +function insiderect(x1,y1,x2,y2,x,y:integer):boolean; +begin + insiderect:=(x>=x1)and(y>=y1)and(x<=x2)and(y<=y2); +end; + +function CreateBitmap(xlen_,ylen_:word;bitplanes_,mode:byte):BitmapTypeptr; +var + bitlop:byte; + newpic:BitmapTypeptr; +begin + newpic:=new(BitmapTypeptr); + with newpic^ do begin + size.x:=xlen_; + size.y:=ylen_; + bitmaptype:=mode; + Qbitoffset:=0; + + case mode of + BMflat:begin + BitsPerPixel:=8; + bitplanes:=1; + xoff:=size.x; + planesize:=xoff*size.y; + getmem(pointer(flatdata),planesize); + end; + BMplanes:begin + xoff:=(size.x shr 3)+1; + bitplanes:=bitplanes_; + planesize:=xoff*size.y; + for bitlop:=0 to 3 do begin + getmem(pointer(planedata[bitlop]),planesize); + end; + + end; + end; + memallocated:=true; + end; + CreateBitmap:=newpic; +end; + +function CreateBitmapFromSource(newpic:bitmaptypeptr;xlen_,ylen_:word;bitplanes_,mode:byte;src:bytearray):BitmapTypeptr; +var + bitlop:byte; + +begin + if (newpic=nil) then + newpic:=new(BitmapTypeptr); + with newpic^ do begin + size.x:=xlen_; + size.y:=ylen_; + bitmaptype:=mode; + Qbitoffset:=0; + + case mode of + BMflat:begin + BitsPerPixel:=8; + bitplanes:=1; + xoff:=size.x; + planesize:=xoff*size.y; + flatdata:=src; + end; + BMplanes:begin + xoff:=(size.x shr 3); + bitplanes:=bitplanes_; + planesize:=xoff*size.y; + for bitlop:=0 to 3 do begin + planedata[bitlop]:=src; + inc(src,planesize); + end; + + end; + end; + memallocated:=false; + end; + CreateBitmapFromSource:=newpic; +end; + + +procedure ResizeBitmap(xlen_,ylen_:word;bitmap:BitmapTypeptr); +begin + with bitmap^ do begin + size.x:=xlen_; + size.y:=ylen_; + + case bitmaptype of + BMplanes:begin + xoff:=(size.x shr 3); + planesize:=xoff*size.y; + end; + BMflat: + planesize:=size.x*size.y; + end; + end; +end; + +procedure DestroyBitmap(Bitmap:BitmapTypeptr); +var i:byte; +begin + with Bitmap^ do + case bitmaptype of + BMplanes:freemem(pointer(flatdata),planesize*bitplanes); + BMflat:freemem(pointer(flatdata),planesize); + end; + Dispose(Bitmap); +end; + + +function Trect.Clipin(var xa,ya,xb,yb:integer):boolean; +Function outcode(xa,ya:integer):byte; +Begin + outcode:=(byte(xax1)shl 2)+{left =$04} + (byte(ya>y1)shl 3) {above =$08}; +end; +{clip a line against 'viewport'} +var code0,code1:byte; +Begin + While 0=0 do begin + code1:=outcode(xa,ya);code0:=outcode(xb,yb); + if (code0 and code1)=code1 then begin + clipin:=false;exit{Trivial accept} + end else begin + if not(code0 or code1)=code1 then begin + clipin:=true;exit;{Trivial reject} + end else If (code0=0) then begin + fswap(code1,code0,1); + fswap(xa,xb,2); + fswap(ya,yb,2); + end; + if (code0 and bellow)<>0 then begin + inc(xa,-(xa-xb)*(y2-yb)div(ya-yb)); + ya:=y2; + end else if (code0 and above)<>0 then begin + inc(xa,-(xa-xb)*(y1-yb)div(ya-yb)); + ya:=y1; + end else if (code0 and right)<>0 then begin + dec(ya,-(ya-yb)*(x2-xb)div(xa-xb)); + xa:=x2; + end else if (code0 and left)<>0 then begin + inc(ya,-(ya-yb)*(x1-xb)div(xa-xb)); + xa:=x1; + end; + end; + end; +end; + + +function Trect.Clipout(var xa,ya,xb,yb:integer):boolean; +Function outcode(xa,ya:integer):byte; +Begin + outcode:=(byte(xa>x2))+ {right =$01} + (byte(ya>y2)shl 1)+{bellow =$02} + (byte(xa0 then begin + inc(xa,(xa-xb)*(y2-yb)div(ya-yb)); + ya:=y2; + end else if (code0 and above)<>0 then begin + inc(xa,(xa-xb)*(y1-yb)div(ya-yb)); + ya:=y1; + end else if (code0 and right)<>0 then begin + dec(ya,(ya-yb)*(x2-xb)div(xa-xb)); + xa:=x2; + end else if (code0 and left)<>0 then begin + inc(ya,(ya-yb)*(x1-xb)div(xa-xb)); + xa:=x1; + end; + end; + end; +end; + +procedure bytepointtype.moveto(x_,y_:byte); +begin + x:=x_; + y:=y_; +end; + + +procedure pointtype.moveto(x_,y_:integer); +begin + x:=x_; + y:=y_; +end; + +procedure Trect.Rmove(xa,ya:integer); +{begin + inc(x1,xa); + inc(x2,xa); + inc(y1,ya); + inc(y2,ya); +end;} +assembler; +asm + les di,self + mov ax,xa ;mov bx,ya + add es:[di],ax + add es:[di+2],bx + add es:[di+4],ax + add es:[di+6],bx +end; + +procedure Trect.Rgrow(xg,yg:integer); +{begin + dec(x1,xg); + dec(y1,yg); + inc(x2,xg); + inc(y2,yg); +end;} +assembler; +asm + les di,self + mov ax,xg; sub es:[di],ax + mov ax,yg; sub es:[di+2],ax + mov ax,xg; add es:[di+4],ax + mov ax,yg; add es:[di+6],ax +end; + +procedure Trect.Rpos(xp,yp:integer); +{var w,h:integer; +begin + w:=x2-x1; + h:=y2-y1; + x1:=xp; y1:=yp; + x2:=xp+w; y2:=yp+h; +end;} + +assembler; +asm + les di,self + mov ax,es:[di+offset x2] {load x2} + mov bx,es:[di+offset y2] {load y2} + + sub ax,es:[di+offset x1] {get width} + sub bx,es:[di+offset y1] {get height} + + mov cx,xp + mov dx,yp + mov es:[di+offset x1],cx {calc x1} + mov es:[di+offset y1],dx {calc y1} + + add ax,cx + add bx,dx + mov es:[di+offset x2],ax {calc x2} + mov es:[di+offset y2],bx {calc y2} +end; + +procedure Trect.Rassign(x1_,y1_,x2_,y2_:integer);assembler; +asm + + les di,self + mov ax,x1_; mov es:[di+offset x1],ax + mov ax,y1_; mov es:[di+offset y1],ax + mov ax,x2_; mov es:[di+offset x2],ax + mov ax,y2_; mov es:[di+offset y2],ax +end; +{ +begin + x1:=x1_; + y1:=y1_; + x2:=x2_; + y2:=y2_; +end;} + + +function Trect.overlap(const r:trect):boolean; +{begin + overlap:=(r.x2>=x1)and (r.x1<=x2)and(r.y2>=y1)and (r.y1<=y2); +end;} +assembler; +asm + les di,self {point to rectangles} + push ds + lds si,r + mov al,false + mov bx,ds:[si+offset x1]; cmp bx,es:[di+offset x2]; jg @end + mov bx,ds:[si+offset y1]; cmp bx,es:[di+offset y2]; jg @end + mov bx,ds:[si+offset x2]; cmp bx,es:[di+offset x1]; jl @end + mov bx,ds:[si+offset y2]; cmp bx,es:[di+offset y1]; jl @end + mov al,true + @end: + pop ds + end; + + +function Trect.empty:boolean; +{begin + empty:=(x1=x2)and(y1=y2); +end;} +assembler; +asm + les di,self + mov al,false + mov bx,es:[di+offset x1] ;cmp bx,es:[di+offset x2] + jnz @end + mov bx,es:[di+offset y1] ;cmp bx,es:[di+offset y2] + jnz @end + mov al,true + @end: +end; + +procedure Trect.union(const r:trect);assembler; +{ +begin + if (r.x2>x2) then x2:=r.x2; + if (r.y2>y2) then y2:=r.y2; + if (r.x1=x1)and (r.x1<=x2)and(r.y2>=y1)and (r.y1<=y2) then begin + if (r.x1>=x1)and(r.x1<=x2) then x1:=r.x1; + if (r.y1>=y1)and(r.y1<=y2) then y1:=r.y1; + if (r.x2>=x1)and(r.x2<=x2) then x2:=r.x2; + if (r.y2>=y1)and(r.y2<=y2) then y2:=r.y2; + intersect:=true; + end else begin + fillchar(x1,8,0); + intersect:=false; + end; +end;} + +assembler; +asm + les di,self {point to rectangles} + push ds + lds si,r + mov ax,ds:[si+offset x1]; cmp ax,es:[di+offset x2]; jg @end + mov bx,ds:[si+offset y1]; cmp bx,es:[di+offset y2]; jg @end + mov cx,ds:[si+offset x2]; cmp cx,es:[di+offset x1]; jl @end + mov dx,ds:[si+offset y2]; cmp dx,es:[di+offset y1]; jl @end + + {if (r.x1>=x1)and(r.x1<=x2) then x1:=r.x1;} + cmp ax,es:[di+offset x2]; jg @endx1 + cmp ax,es:[di+offset x1]; jl @endx1 + mov es:[di+offset x1],ax; + @endx1: + {if (r.y1>=y1)and(r.y1<=y2) then y1:=r.y1;} + cmp bx,es:[di+offset y2]; jg @endy1 + cmp bx,es:[di+offset y1]; jl @endy1 + mov es:[di+offset y1],bx + @endy1: + {if (r.x2>=x1)and(r.x2<=x2) then x2:=r.x2;} + cmp cx,es:[di+offset x1]; jl @endx2 + cmp cx,es:[di+offset x2]; jg @endx2 + mov es:[di+offset x2],cx + @endx2: + {if (r.y2>=y1)and(r.y2<=y2) then y2:=r.y2;} + cmp dx,es:[di+offset y1]; jl @endy2 + cmp dx,es:[di+offset y2]; jg @endy2 + mov es:[di+offset y2],dx + @endy2: + mov al,true {intersection was made, return true} + jmp @noclear + @end: + xor ax,ax {fill rectangle with 0's and return with false} + mov cx,4 + rep stosw + @noclear: + pop ds +end; + + + +function trect.inside(const r:trect):boolean;assembler; +{begin + inside:=(x1>=r.x1)and(x2<=r.x2)and(y1>=r.y1)and(y2<=r.y2); +end; +} + +asm + les di,self + push ds + lds si,r + mov al,0 {set to zero -not inside} + mov bx,[si+offset x1] ;cmp bx,es:[di+offset x1] + jg @end + mov bx,[si+offset y1] ;cmp bx,es:[di+offset y1] + jg @end + mov bx,[si+offset x2] ;cmp bx,es:[di+offset x2] + jl @end + mov bx,[si+offset y2] ;cmp bx,es:[di+offset y2] + jl @end + mov al,1 {if you get to here then it is inside} + + @end: + pop ds +end; + +function Trect.contains(x,y:integer):boolean; +begin + contains:=(x>=x1)and(y>=y1)and(x<=x2)and(y<=y2); +end; +(*assembler;asm + les di,self + mov bx,x {load up x..} + mov cx,y {..and y} + + mov al,0 {set to zero -not inside} + cmp bx,es:[di+offset x1] + jl @end + cmp cx,es:[di+offset y1] + jl @end + cmp bx,es:[di+offset x2] + jg @end + cmp cx,es:[di+offset y2] + jg @end + + mov al,1 {if you get to here then it is inside} + @end: +end;*) + +Function Trect.equals(const r:trect):boolean; +begin + equals:=(x1=r.x1)and(y1=r.y1)and(x2=r.x2)and(y2=r.y2); +end; +(*assembler;asm + les di,self + push ds + lds si,r + mov al,0 {set to zero -not equal} + mov bx,ds:[si+offset x1] ;cmp bx,es:[di+offset x1] + jnz @end + mov bx,ds:[si+offset y1] ;cmp bx,es:[di+offset y1] + jnz @end + mov bx,ds:[si+offset x2] ;cmp bx,es:[di+offset x2] + jnz @end + mov bx,ds:[si+offset y2] ;cmp bx,es:[di+offset y2] + jnz @end + mov al,1 {if you get to here then it is equal} + + @end: + pop ds +end;*) + + +function Trect.concatable(const r:trect):boolean; +begin + concatable:=((r.x2>=x1-1)and(r.x1<=x2+1)and(r.y1=y1)and(r.y2=y2)) + or ((r.x1=x1)and(r.x2=x2)and(r.y2>=y1-1)and(r.y1<=y2+1)); +end; +(*assembler;asm + les di,self + push ds + lds si,r + mov ax,es:[di+offset x1] + mov bx,es:[di+offset y1] + mov cx,es:[di+offset x2] + mov dx,es:[di+offset y2] + mov di,ax + mov al,false {preset to false} + + dec di; inc cx {dec and inc for compare} + {(r.x2>=x1-1)and(r.x1<=x2+1)and(r.y1=y1)and(r.y2=y2)} + cmp ds:[si + offset x2],di; jl @half + cmp ds:[si + offset x1],cx; jg @half + cmp ds:[si + offset y1],bx; jne @half + cmp ds:[si + offset y2],dx; jne @half + mov al,true + jmp @end + @half: + inc di; dec cx {get these back to original size} + dec bx; inc dx {dec and inc for compare} + cmp ds:[si + offset x1],di; jne @end + cmp ds:[si + offset x2],cx; jne @end + cmp ds:[si + offset y2],bx; jl @end + cmp ds:[si + offset y1],dx; jg @end + mov al,true + @end: + pop ds {restore data segment} +end;*) + +(* +function Trect.cutfrom(r:trect):prectlist; + +var newlist,nextrect,firstrect:prectlist; + ovrlap:boolean; + +begin + Rect_count:=0; + ovrlap:=r.intersect(self); + if (not equals(r)) then begin + if not ovrlap then begin + new(nextrect); + nextrect^.rassign(x1,y1,x2,y2); + newlist:=nextrect; + rectlist_status:=RSnooverlap; + end else begin + new(firstrect); + nextrect:=firstrect; + if y1<>r.y1 then begin + new(nextrect^.next); nextrect:=nextrect^.next; + inc(rect_count); newlist:=nextrect; + nextrect^.rassign(x1,y1,x2,r.y1-1); + if nextrect^.y1r.x1 then begin + new(nextrect^.next); nextrect:=nextrect^.next; + if rect_count=0 then newlist:=nextrect; + inc(rect_count); + + nextrect^.rassign(x1,r.y1,r.x1-1,r.y2); + if nextrect^.x1r.x2 then begin + new(nextrect^.next); nextrect:=nextrect^.next; + if rect_count=0 then newlist:=nextrect; + inc(rect_count); + + nextrect^.rassign(r.x2+1,r.y1,x2,r.y2); + if nextrect^.x2>x2 then nextrect^.x2:=x2; + end; + if y2<>r.y2 then begin + new(nextrect^.next); nextrect:=nextrect^.next; + if rect_count=0 then newlist:=nextrect; + inc(rect_count); + + nextrect^.rassign(x1,r.y2+1,x2,y2); + if nextrect^.y1>y2 then nextrect^.y1:=y2; + end; + rectlist_status:=RSlist; + dispose(firstrect); + end; + lastrect:=nextrect; + cutfrom:=newlist; + nextrect^.next:=nil; + end else begin + cutfrom:=nil; + rectlist_status:=RSobscured + end; +end; + +procedure destroyplist(p:prectlist); +var curr_p,next_p:prectlist; +begin + curr_p:=p; + while curr_p<>nil do begin + next_p:=curr_p^.next; + dispose(curr_p); + curr_p:=next_p; + end; +end; +*) + +function Trect.cutfrom(r:trect):prectlist; + +var newlist,nextrect,firstrect:prectlist; + ovrlap:boolean; + +begin + Rect_count:=0; + ovrlap:=r.intersect(self); + if (not equals(r)) then begin + if not ovrlap then begin + new(nextrect); + nextrect^.rassign(x1,y1,x2,y2); + newlist:=nextrect; + rectlist_status:=RSnooverlap; + end else begin + new(firstrect); + nextrect:=firstrect; + if y1<>r.y1 then begin + new(nextrect^.next); nextrect:=nextrect^.next; + inc(rect_count); newlist:=nextrect; + nextrect^.rassign(x1,y1,x2,r.y1-1); + if nextrect^.y1r.x1 then begin + new(nextrect^.next); nextrect:=nextrect^.next; + if rect_count=0 then newlist:=nextrect; + inc(rect_count); + + nextrect^.rassign(x1,r.y1,r.x1-1,r.y2); + if nextrect^.x1r.x2 then begin + new(nextrect^.next); nextrect:=nextrect^.next; + if rect_count=0 then newlist:=nextrect; + inc(rect_count); + + nextrect^.rassign(r.x2+1,r.y1,x2,r.y2); + if nextrect^.x2>x2 then nextrect^.x2:=x2; + end; + if y2<>r.y2 then begin + new(nextrect^.next); nextrect:=nextrect^.next; + if rect_count=0 then newlist:=nextrect; + inc(rect_count); + + nextrect^.rassign(x1,r.y2+1,x2,y2); + if nextrect^.y1>y2 then nextrect^.y1:=y2; + end; + rectlist_status:=RSlist; + dispose(firstrect); + end; + lastrect:=nextrect; + cutfrom:=newlist; + nextrect^.next:=nil; + end else begin + cutfrom:=nil; + rectlist_status:=RSobscured + end; +end; + + +procedure destroyplist(p:prectlist); +var curr_p,next_p:prectlist; +begin + curr_p:=p; + while curr_p<>nil do begin + next_p:=curr_p^.next; + dispose(curr_p); + curr_p:=next_p; + end; +end; + + + + + +Function Trect.width:integer; +begin + width:=x2-x1; +end; + +Function Trect.height:integer; +begin + height:=y2-y1; +end; + +Function Trect.halfx:integer; +begin + halfx:=(x2-x1) shr 1; +end; + +{assembler; +asm + les di,self + mov ax,es:[di+offset x2] + sub ax,es:[di+offset x1] + shr ax,1 +end;} + +Function Trect.halfy:integer; +begin + halfy:=(y2-y1) shr 1; +end; +{ + +assembler; +asm + les di,self + mov ax,es:[di+offset y2] + sub ax,es:[di+offset y1] + shr ax,1 +end;} +end. diff --git a/GGRAPH.PAS b/GGRAPH.PAS new file mode 100644 index 0000000..2185434 --- /dev/null +++ b/GGRAPH.PAS @@ -0,0 +1,643 @@ +Unit Ggraph; +{Generic Graphics unit} + +{$DEFINE VGA256} +{$DEFINE XVGA256} +{$DEFINE SVGA256} +{$DEFINE VGA16} +{$DEFINE BITMAP16} +{$DEFINE BITMAP25} + +INTERFACE +{stuff to be preserved for mouse inter: + GRPH_ADDR + 3,logicmode + 0,colour + 5,WriteMode (Normaly 3) + 4,ReadMask +} + +uses {$IFDEF XVGA256}xvga256,{$ENDIF} + {$IFDEF VGA256}vga256,{$ENDIF} + {$IFDEF SVGA256}svga256,{$ENDIF} + {$IFDEF VGA16}vga16,{$ENDIF} + {$IFDEF BITMAP16}bitmap16,{$ENDIF} + {$IFDEF bitmap25}bitmap25,{$ENDIF} +gbasics,chardef,ttypes,dos,colour,tmaths; + + + +Const + +{active and visual page indicies} +active:byte=0; +visual:byte=1; + +ctext=$3; +bwtext=$2; +allplanes=3841; + +{****-mouse draw modes-*****} +MSdrawold=1; +MSdrawpointer=2; +MSdrawboth=3; + +Type +Piclist=^piclist_; +piclist_=array[0..0] of bitmaptypeptr; + +const +Normal=0; +pingpong=1; +type +Animtype=object + numframes,mode,curframe:byte; + frames:piclist; + direction:shortint; + + constructor create(mode_,numframes_,start:byte); + Procedure Play(x,y:integer); + destructor done; +end; + +set_modeproc=function (mode:byte):boolean; +GetBitmapProc=function(x1,y1,x2,y2:integer):Bitmaptypeptr; +PutBitmapProc=procedure(x,y:integer;bitmap:bitmaptypeptr); +QuadProc=procedure(x1,y1,x2,y2:integer); +TriProc=procedure(a,b,c:integer); +GTriAngleProc=procedure(xa,ya,xb,yb,xc,yc,ia,ib,ic:integer); +TriAngleProc=procedure(xa,ya,xb,yb,xc,yc:integer); +NoParamProc=procedure; +PutPixelProc=procedure(x1,y1:integer); +GetPixelProc=function(x1,y1:integer):byte; +OutTextxyProc=procedure(x1,y1:integer;txt:string); +OutTextxylengthProc=procedure(x1,y1:integer;txt:pchar;length:byte); +DrawBytesProc=procedure(x1,y:Integer;pic:bytearray;nbytes:byte); +DrawBytesxyProc=procedure(x1,y1:Integer;pic:bytearray;xbytes,ybytes:byte); +ScreenCopyProc=procedure(x1,y1,x2,y2,xd,yd:integer;page1,page2:byte); +QwriteProc=procedure(count:word); +QgetProc=function:byte; +PolygonProc=procedure(points:pointtypeptr;numpoints:byte); + + +Procedure Qpop; +Procedure Qpush; +Procedure Qnextline; + +Procedure BMQpop; +Procedure BMQpush; +Procedure BMQnextline; + +Procedure thickrectangle(x1,y1,x2,y2,thickness:integer); +Procedure rectangle(x1,y1,x2,y2:integer); + +function initgraph(var screen:screenidtype):boolean; +procedure closegraph; + +Procedure Setbase(scrnbase:word); +Procedure waitvbl; +procedure pageswap; +Procedure Setvisualpage(pageno:byte); +Procedure Setactivepage(pageno:byte); +Procedure setoffset(offst:byte); + +procedure setlinepattern(pattern:byte;background:boolean); +procedure setfillpattern(const pattern:fillpatterntype;background:boolean); +procedure setsolidfill; + +Procedure SetBitmapContext(data:bitmaptypeptr); +{Procedure SetGraphicsContext(scrtype:byte;data:dword);} + +var +set_mode:set_modeProc; +bar,BMbar:QuadProc; +GTriangle,BMGTriangle:GTriAngleProc; +Triangle,BMTriangle:TriangleProc; +polygon,BMpolygon:PolygonProc; +line,BMline:QuadProc; +Hline,BMHline:TriProc; +Vline,BMVline:TriProc; +ClearDevice,BMClearDevice:NoParamProc; +putpixel,BMputpixel:putpixelproc; +getpixel,BMgetpixel:getpixelproc; +outtextxy,BMouttextxy:outtextxyproc; +outtextxy_length,BMouttextxy_length:outtextxylengthproc; +DrawBytes,BMDrawBytes:DrawBytesProc; +DrawBytesxy,BMDrawBytesxy:DrawBytesxyProc; +ScreenCopy,BMScreenCopy:ScreencopyProc; +PutBitmap,BMPutBitmap:PutBitmapProc; +GetBitmap,BMGetBitmap:GetBitmapProc; +Qsetxy,BMQsetxy:putpixelproc; +Qwrite,BMQwrite:QwriteProc; +Qget,BMQget:Qgetproc; +savescreenregs:procedure; +restorescreenregs:procedure; + +mousepicadrs:^word; + +const +maxgreyfills=31; +greyfills:array[0..31]of fillpatterntype=((0,0,0,0,0,0,0,0),(0,0,0,0,16,0,0,0), +(0,0,8,0,0,64,2,0),(0,64,0,2,0,32,4,0),(0,32,4,128,0,16,130,0), +(0,68,0,17,0,68,0,17),(0,132,32,1,0,84,0,17),(0,34,0,73,0,34,0,73), +(0,162,0,73,0,170,0,73),(16,170,1,170,16,170,68,9), +(16,170,65,170,20,170,84,9),(17,170,69,170,17,170,84,9), +(81,170,69,170,17,170,85,138),(81,170,85,170,17,170,85,170), +(85,170,81,170,21,170,85,170),(85,170,85,170,85,170,85,170),(85,170,85,170,93,170,85,170), +(85,170,87,170,117,170,85,170),(87,170,85,170,119,170,85,170), +(87,170,93,170,119,170,85,186),(119,170,93,170,119,170,213,123), +(247,170,95,170,245,170,213,123),(247,170,127,170,247,170,221,123), +(255,174,255,91,255,170,255,91),(255,187,255,214,255,187,255,214), +(255,111,251,223,255,117,255,221),(255,238,255,187,255,238,255,187), +(255,239,253,191,255,247,190,255),(255,223,255,254,255,239,253,255), +(255,255,251,255,255,223,254,255),(255,255,255,255,247,255,255,255), +(255,255,255,255,255,255,255,255)); + +solidfill:fillpatterntype=(255,255,255,255,255,255,255,255); +emptyfill:fillpatterntype=(0,0,0,0,0,0,0,0); +midgreyfill:fillpatterntype=(170,85,170,85,170,85,170,85); + +var +{oldscreen:array[0..3999] of byte;} +oldcrsx,oldcrsy:byte; + +IMPLEMENTATION + +procedure setlinepattern(pattern:byte;background:boolean);assembler; +asm + mov al,pattern + mov ah,al + mov maskword,ax + mov al,background + mov maskbackground,al +end; + +procedure setfillpattern(const pattern:fillpatterntype;background:boolean); +var i:byte; +begin + fillpattern:=pattern; + nullpattern:=true; + i:=0; + while (nullpattern=true)and(i<8) do begin + nullpattern:=solidfill[i]=pattern[i]; + inc(i); + end; + maskbackground:=background; +end; + +procedure setsolidfill; +begin + maskbackground:=false; + nullpattern:=true; + maskword:=$ffff; +end; + + +Procedure pageswap;begin + visual:=visual xor 1;active:=active xor 1; + setactivepage(active);setvisualpage(visual); +end; + +Procedure setoffset(offst:byte);assembler; +asm + mov dx,CRTC_ADDR {load dx with CRT controller address} + mov al,$1 {function $1} + mov ah,offst {screen offset} + out dx,ax {write to port} + + mov al,$13 {funtion $13} + out dx,ax {write to port} + + mov al,0 {function 0} + shl ah,1 {half offset} + out dx,ax {write to port} + + mov byte ptr SC.offsd,ah {set my offset value} +end; + +procedure mapmask(mask:byte);assembler; +asm + mov dx,SEQU_ADDR; {load Sequencer} + mov al,2; mov ah,mask {function 2, mask} + out dx,ax {write to port} +end; + +procedure readmask(plane:byte);assembler; +asm + mov dx,GRPH_ADDR {Load graphics address} + mov al,4 {function 4-set readmask} + mov ah,plane {Planes to mask} + out dx,ax {write to port} +end; + +Procedure Setvisualpage(pageno:byte); {set page that is displayed} +begin + setbase(pageno*SC.pagesize); +end; + +Procedure Setactivepage(pageno:byte); +begin + SC.scrptr:=ptr($a000,pageno*SC.pagesize); +end; + +Procedure memorymode(mask:byte);assembler; +asm + mov dx,SEQU_ADDR {write to sequencer} + mov al,4 {function 4-memory modes} + mov ah,mask {set up mask} + out dx,ax {write to port} +end; + +{address mode control the way in which data is written to the screen. +3=No bitmask needed. +1=use bitmask. +0=32 bit screen to screen transfer. +} +Procedure adrsmode(mask:byte);assembler; +asm + mov dx,GRPH_ADDR {Graphics address} + mov al,5; {function 5, address mode} + mov ah,mask; {load mode} + out dx,ax {write to port} +end; + +Procedure Setbase(scrnbase:word);assembler; +asm + mov dx,CRTC_ADDR {CRT controller} + mov bx,scrnbase {base of screen} + mov al,$C ;mov ah,bh {load up low bits} + out dx,ax {write to port} + inc al ;mov ah,bl {load up high bits} + out dx,ax {write to port} +end; + + +{wait for vertiacal blank} +Procedure waitvbl;assembler; +Asm + mov dx,STATUS_ADDR {load status address} + @runloop: + in al,dx {get status} + test al,08h {is it equal to al?} + jz @runloop {if not then loop} +end; + +procedure setcurs(x,y:byte);assembler; + asm + mov ah,02h + mov bh,0 + mov dh,x + mov dl,y + int 10h + end; + +procedure getcurs(var x,y:byte);assembler; +asm + mov ah,03h + mov bh,0 + int 10h + les di,x + mov es:[di],dh + les di,y + mov es:[di],dl +end; + +{data is either a pointtype or a bitmap} +Procedure SetGraphicsContext(scrtype:byte{;data:dword}); +var i:byte; +begin + {set up screen address -$a000 for screens, supplied address for bitmaps} +end; + + +Procedure SetBitmapContext(data:bitmaptypeptr); +var +i:byte; +coffset:integer; +begin + BC.bitplanes:=data^.bitplanes; + BC.offsd:=data^.xoff; + BC.size:=data^.size; + BC.screenport.rassign(0,0,BC.size.x-1,BC.size.y-1); + BC.viewport:=BC.screenport; + BC.pagesize:=data^.planesize; + BC.qbitoffset:=128; + BC.scrptr:=data^.flatdata; + BC.qoffset:=0; + coffset:=0; + for i:=0 to BC.size.y do begin + BC.startoffsets[i]:=coffset; + inc(coffset,BC.offsd); + end; + + {if BC.Driver<>data^.bitmaptype then }begin + BC.Driver:=data^.bitmaptype; + case BC.driver of + 255:; + {$IFDEF Bitmap25} + BMflat:begin + BMbar:=bitmap25.bar; + BMGTriangle:=bitmap25.GTriangle; + BMTriangle:=bitmap25.Triangle; + BMline:=bitmap25.line; + BMHline:=bitmap25.hline; + BMVline:=bitmap25.vline; + BMClearDevice:=bitmap25.ClearDevice; + BMPutPixel:=bitmap25.putpixel; + BMGetPixel:=bitmap25.getpixel; + BMOuttextxy:=bitmap25.Outtextxy; + BMDrawBytes:=bitmap25.drawbytes; + BMPutBitmap:=bitmap25.putbitmap; + BMGetBitmap:=bitmap25.getbitmap; + BMQsetxy:=bitmap25.Qsetxy; + BMQget:=bitmap25.Qget; + BMQwrite:=bitmap25.Qwrite; + end; + {$ENDIF} + {$IFDEF BITMAP16} + BMplanes:begin + + for i:=0 to data^.bitplanes-1 do + BC.scrptrs[i]:=data^.planedata[i]; + BMputpixel:=bitmap16.putpixel; + BMgetpixel:=bitmap16.getpixel; + BMcleardevice:=bitmap16.cleardevice; + BMqsetxy:=bitmap16.qsetxy; + BMqwrite:=bitmap16.qwrite; + BMqget:=bitmap16.qget; + end; + {$ENDIF} + end; + end; +end; + +{set graphics mode and setup varilbes} +function initgraph(var screen:screenidtype):boolean; +var + installed:boolean; + i,tempoffset:word; +Begin + + SC.Driver:=Screen.Driver; + SC.graphmode:=Screen.Graphmode; + + case SC.driver of + {$IFDEF vga256} + STvga_flat:begin + set_mode:=vga256.set_mode; + bar:=vga256.bar; + GTriangle:=vga256.GTriangle; + Triangle:=vga256.Triangle; + line:=vga256.line; + Hline:=vga256.hline; + Vline:=vga256.vline; + ClearDevice:=vga256.ClearDevice; + PutPixel:=vga256.putpixel; + GetPixel:=vga256.getpixel; + Outtextxy:=vga256.Outtextxy; + Outtextxy_length:=vga256.outtextxy_length; + DrawBytes:=vga256.drawbytes; + DrawBytesxy:=vga256.drawbytesxy; + ScreenCopy:=vga256.screencopy; + PutBitmap:=vga256.putbitmap; + GetBitmap:=vga256.getbitmap; + Qsetxy:=vga256.Qsetxy; + Qget:=vga256.Qget; + Qwrite:=vga256.Qwrite; + savescreenregs:=vga256.savescreenregs; + restorescreenregs:=vga256.restorescreenregs; + {Polygon:=vga256.polygon;} + end; + {$endif} + {$ifdef SVGA256} + STsvga_flat:begin + set_mode:=svga256.set_mode; + bar:=svga256.bar; + GTriangle:=svga256.GTriangle; + Triangle:=svga256.Triangle; + line:=svga256.line; + Hline:=svga256.hline; + Vline:=svga256.vline; + ClearDevice:=svga256.ClearDevice; + PutPixel:=svga256.putpixel; + GetPixel:=svga256.getpixel; + Outtextxy:=svga256.Outtextxy; + Outtextxy_length:=svga256.outtextxy_length; + DrawBytes:=svga256.drawbytes; + DrawBytesxy:=svga256.drawbytesxy; + ScreenCopy:=svga256.screencopy; + PutBitmap:=svga256.putbitmap; + GetBitmap:=svga256.getbitmap; + Qsetxy:=svga256.Qsetxy; + Qget:=svga256.Qget; + Qwrite:=svga256.Qwrite; + savescreenregs:=svga256.savescreenregs; + restorescreenregs:=svga256.restorescreenregs; + end; + {$endif} + {$IFDEF VGA16} + STvga_plainiar:begin + set_mode:=vga16.set_mode; + bar:=vga16.bar; + GTriangle:=vga16.GTriangle; + Triangle:=vga16.Triangle; + line:=vga16.line; + Hline:=vga16.hline; + Vline:=vga16.vline; + ClearDevice:=vga16.ClearDevice; + PutPixel:=vga16.putpixel; + GetPixel:=vga16.getpixel; + Outtextxy:=vga16.Outtextxy; + Outtextxy_length:=vga16.outtextxy_length; + DrawBytes:=vga16.drawbytes; + DrawBytesxy:=vga16.drawbytesxy; + ScreenCopy:=vga16.screencopy; + PutBitmap:=vga16.putbitmap; + GetBitmap:=vga16.getbitmap; + Qsetxy:=vga16.Qsetxy; + Qget:=vga16.Qget; + Qwrite:=vga16.Qwrite; + savescreenregs:=vga16.savescreenregs; + restorescreenregs:=vga16.restorescreenregs; + end; + {$endif} + end; + + + SC.colourdepth:=Screen.Colourdepth; + SC.size:=Screen.Size; + SC.bitplanes:=Screen.Bitplanes; + SC.scrptr:=ptr($a000,00); + SC.bitsperpixel:=SC.colourdepth shr SC.bitplanes; + SC.offsd:=SC.size.x; + if SC.driver=STvga_plainiar then + SC.offsd:=SC.offsd shr 3; + SC.screenport.rassign(0,0,SC.size.x-1,SC.size.y-1); + + SC.viewport:=SC.screenport; + SC.pagesize:=SC.size.y*SC.offsd; + + + SC.Qbitoffset:=128; + SC.Qoffset:=0;{SC.Scrptr;} + SC.nopages:=4; + installed:=set_mode(SC.graphmode); + initcolours(SC.colourdepth); + {getmem(SC.startoffsets,SC.Size.y shl 1);} + tempoffset:=0; + for i:=0 to SC.Size.y do begin + + SC.startoffsets[i]:=tempoffset; + inc(tempoffset,SC.offsw); + end; + + + t_fillcol:=0; + t_col:=SC.ColourDepth-1; + t_writemode:=0; + maskbyte:=255; + setsolidfill; + cleardevice; + initgraph:=true; +end; + +Procedure CloseGraph; +begin + {while CheckForFade do;} + DoneColours; + {freemem(SC.startoffsets,SC.Size.y shl 1);} + asm + + mov al,ctext; + mov ah,0; + int 10h end; + {setcurs(oldcrsx,oldcrsy);} +end; + +Procedure thickrectangle(x1,y1,x2,y2,thickness:integer); +Begin + for thickness:=1 to thickness do begin + rectangle(x1,y1,x2,y2); + inc(x1); inc(y1); + dec(x2); dec(y2); + end; +end; + +Procedure rectangle(x1,y1,x2,y2:integer); +Begin + if x1>x2 then asm mov ax,x2;xchg x1,ax;mov x2,ax;end; + if y1>y2 then asm mov ax,y2;xchg y1,ax;mov y2,ax;end; + if y1<>y2 then begin + hline(x1,x2,y1); + vLine(x2,y1+1,y2-1); + vLine(x1,y1+1,y2-1); + end; + hLine(x1,x2,y2); +end; + + + +{these Qwrite procedures are the same for all Graphics Devices} +var +BMoldoffset:Dword; +SMoldoffset:Dword; + +Procedure Qpush;assembler; +asm + mov ax,word ptr SC.qoffset + mov word ptr SMoldoffset,ax +end; + +Procedure Qpop;assembler; +asm + mov ax,word ptr SMoldoffset + mov word ptr SC.qoffset,ax +end; + +Procedure Qnextline; +begin + inc(SC.qoffset,SC.offsd); +end; + + +Procedure BMQpush;assembler; +asm + mov ax,word ptr BC.qoffset + mov word ptr BMoldoffset,ax +end; + +Procedure BMQpop;assembler; +asm + + mov ax,word ptr BMoldoffset + mov word ptr BC.qoffset,ax +end; + +Procedure BMQnextline; +begin + inc(BC.qoffset,BC.offsd); +end; + +{------------------****Animation stuff****---------------------} + +Constructor Animtype.create(mode_,numframes_,start:byte); +begin + direction:=1; + curframe:=start mod numframes_; + mode:=mode_; + numframes:=numframes_; + getmem(frames,sizeof(bitmaptypeptr)*numframes); +end; + +Procedure Animtype.play(x,y:integer); +begin + putbitmap(x,y,frames^[curframe]); + if mode=pingpong then begin + if ((curframe=0)and(direction<0))or + ((curframe=numframes-1)and(direction>0)) then + direction:=-direction + end else + if curframe=numframes-1 then curframe:=255; + inc(curframe,direction); +end; + +Destructor Animtype.done; +var i:byte; +begin + for i:=0 to numframes-1 do + DestroyBitmap(frames^[i]); +end; + +begin +{load in default font} + fillchar(tcharset,255*fontheight,0); + asm + (* + {get address of 8 pixel high font} + mov ah,$35 + mov al,fontintr + int $21 + {correct vector, subtract a k} + sub bx,1024 + + {get tcharset pointer} + lea si,tcharset + + {inititiate a loop} + mov cx,256 + @copyloop: + push cx + mov cx,8 + @byteloop: + mov al,es:[bx] + mov ds:[si+(fontheight shr 1)-4],al + inc bx + inc si + loop @byteloop + add si,fontheight shr 1 + pop cx + loop @copyloop*) + end; +End. + + diff --git a/LCD.PAS b/LCD.PAS new file mode 100644 index 0000000..d6d49a0 --- /dev/null +++ b/LCD.PAS @@ -0,0 +1,163 @@ +Unit LCD; + +INTERFACE +uses ggraph,tmaths,msmouse,gbasics; + + +type +lcdsize=record + height,width,size,gap:integer; +end; + +const +BigLcd:lcdsize=(height:150;width:75;size:15;gap:12); +SmallLcd:lcdsize=(height:40;width:20;size:6;gap:5); + +LCD_dark=4; +LCD_light=12; + +LCD_dot=128; {h} +LCD_mid=64; {g} +LCD_TopLeft=32; {f} +LCD_BottomLeft=16;{e} +LCD_Bottom=8; {d} +LCD_BottomRight=4;{c} +LCD_TopRight=2; {b} +LCD_Top=1; {a} + +digits:array[0..9] of byte=(63,6,91,79,102,109,125,7,127,111); +chars:array[0..29] of byte=(119,124,88,94,123,113,111,116,4,14, + 120,56,56,84,92,115,103,80,109, + 112,28,28,28,118,110,91,0,99,64,8); + +Procedure drawdigit(x,y:integer;dig:byte;size:LCDsize); +Function getlight(x,y:integer;size:LCDsize):byte; +Procedure lcd_num(x,y,num:integer;size:lcdsize;dotornot:boolean); +Procedure Lcd_string(x,y:integer;text:string;size:lcdsize); + +IMPLEMENTATION + +Procedure HorizDiamond(x1,y1,x2,y2:integer); +var depth,yp:integer; +begin + if x1>x2 then fswap(x1,x2,sizeof(integer)); + if y1>y2 then fswap(y1,y2,sizeof(integer)); + depth:=(y2-y1) shr 1; + + yp:=1+y1+(y2-y1) shr 1; + bar(x1+depth,y1,x2-depth,y2); + inc(y2); + triangle(x1,yp,x1+depth,y1,x1+depth,y2); + triangle(x2,yp,x2-depth,y1,x2-depth,y2); +end; + +Procedure VertDiamond(x1,y1,x2,y2:integer); +var depth,px:integer; +begin + if x1>x2 then fswap(x1,x2,sizeof(integer)); + if y1>y2 then fswap(y1,y2,sizeof(integer)); + depth:=(x2-x1) shr 1; + px:=x1+(x2-x1) shr 1; + + bar(x1,y1+depth,x2,y2-depth); + triangle(px,y1,x1,y1+depth,x2,y1+depth); + inc(y2); + triangle(px,y2,x1,y2-depth,x2,y2-depth); +end; + +Function getlight(x,y:integer;size:LCDsize):byte; +var halfheight:integer; +begin + with size do begin + halfheight:=height shr 1; + getlight:=0; + if chkicon(x+size,y,width-size,size)<>-1 then getlight:=LCD_top; + if chkicon(x,y+size,size,halfheight)<>-1 then getlight:=LCD_topleft; + if chkicon(x+width-size,y+size,size,halfheight)<>-1 then getlight:=LCD_topright; + + inc(y,halfheight-size); + if chkicon(x+size,y,width-size,size)<>-1 then getlight:=LCD_mid; + if chkicon(x,y+size,size,halfheight)<>-1 then getlight:=LCD_bottomleft; + if chkicon(x+width-size,y+size,size,halfheight)<>-1 then getlight:=LCD_bottomright; + + inc(y,halfheight-size); + if chkicon(x+size,y,width-size,size)<>-1 then getlight:=LCD_bottom; + end; +end; + +Procedure drawdigit(x,y:integer;dig:byte;size:LCDsize); + +procedure setbright(bright:byte); +begin + if bright<>0 then + T_fillcol:=LCD_light else T_fillcol:=LCD_dark; +end; + +var +halfheight:integer; + +begin + with size do begin + halfheight:=height shr 1; + setbright(dig and LCD_top); + horizDiamond(x+gap,y,x+width-gap,y+size); + + setbright(dig and LCD_topleft); + vertdiamond(x,y+gap,x+size,y+halfheight-gap); + + setbright(dig and LCD_topright); + vertdiamond(x+width-size,y+gap,x+width,y+halfheight-gap); + + inc(y,halfheight-size); + + setbright(dig and LCD_mid); + horizDiamond(x+gap,y,x+width-gap,y+size); + + setbright(dig and LCD_bottomleft); + vertdiamond(x,y+gap,x+size,y+halfheight-gap); + + setbright(dig and LCD_bottomright); + vertdiamond(x+width-size,y+gap,x+width,y+halfheight-gap); + + inc(y,halfheight-size); + + setbright(dig and LCD_bottom); + horizDiamond(x+gap,y,x+width-gap,y+size); + + inc(x,width+gap); + setbright(dig and LCD_dot); + if t_fillcol=LCD_light then + bar(x,y,x+size,y+size); + end; +end; + + + + + +Procedure lcd_num(x,y,num:integer;size:lcdsize;dotornot:boolean); +var lop,numlen,numcount,dot:byte; + precalc,powered:integer; +begin + dot:=0; + numlen:=1{numlength(num)-1}; + numcount:=numlen; + for lop:=0 to numlen do begin + if (lop=numlen)and(dotornot) then dot:=LCD_dot; + powered:=power(10,numcount); + precalc:=num div powered; + drawdigit(x+lop*(size.width+10),y,digits[precalc]+dot,size); + dec(num,precalc * powered); + dec(numcount); + end; +end; + +Procedure Lcd_string(x,y:integer;text:string;size:lcdsize); +var lop:byte; +begin + for lop:=1 to length(text) do + drawdigit(x+lop*(size.width+10),y,chars[ord(text[lop])-ord('a')],size); +end; + + +end. \ No newline at end of file diff --git a/MSMOUSE.PAS b/MSMOUSE.PAS new file mode 100644 index 0000000..74d6414 --- /dev/null +++ b/MSMOUSE.PAS @@ -0,0 +1,397 @@ +Unit msmouse; +{DEFINE NonStandardVideo} +INTERFACE +uses gbasics,crt2; + +const +arrow:array[0..31]of word=(16383,8191,4095,2047,1023,511,255,127,63,127,511,4351,45311,63615,63615,64767, +0,16384,24576,28672,30720,31744,32256,32512,32640,31744,27648,17920,1536,768,768,0); +Hourglass:array[0..31]of word= +(49155,49155,49155,49155,57351,61455,63519,64575,64575,63519,61455,61455,57351,49155,49155,49155, +0,8184,8088,0,3088,1568,832,384,0,832,1568,3616,3088,8184,7832,0); +PointTo:array[0..31]of word=(33155,1,0,32784,49680,49680,49664,49664,49921,58371,64575,61455,61455,63519,64575,65151, +32380,32510,6342,6342,6342,6342,6398,6268,0,384,384,2016,960,384,0,0); + +mouserect:trect=(x1:-1;y1:-1;x2:13;y2:17); +mousevisible:boolean=false; +oldvis:boolean=false; + +clickwait=3; +Dclickwait=6; + +Dclick_Xthreshold=2; +Dclick_Ythreshold=2; +linger_for=400; + +Xgrid_Corner:integer=0; +Ygrid_Corner:integer=0; +Xgrid_size:integer=1; +Ygrid_size:integer=1; + +RightShiftKey=1; +LeftShiftKey=2; +CtrlKey=4; +AltKey=8; +ScrollKey=16; +NumLockKey=32; +CapsKey=64; +InsertKey=128; + +var +xm,ym,gridxm,gridym,oldgridxm,oldgridym,zm,oldxm,oldym,oldzm,ms_xdiff,ms_ydiff:integer; + +ms_attrib:byte; + +ms_pressed,ms_released,ms_clicked,ms_doubleclicked,ms_moved,ms_lingering,ms_gridmoved:boolean; + +function chkouticon(x1,y1,x2,y2:integer):shortint; +function chkicon(x1,y1,x2,y2:integer):shortint; +Procedure stoprepeat; +Procedure stoprepeatwait(wait:word); +Function resetmouse:boolean; +Procedure getstuff;far; +Procedure mouseon; +Procedure mouseoff; +procedure mouseoffrect(var rect:trect); +procedure setuserproc(p:pointer;callmask:word); +Procedure mpos; +Procedure mbutton; +Procedure setmouserect(x1,y1,x2,y2:integer); +Procedure Setmousepos(x,y:integer); +Procedure setmouseshape(x,y:integer;var mask); +Procedure setmickeys(x,y:integer); +procedure setsence(x,y,dspeed:integer); +Procedure xyfilter; +Procedure ymisxm; + +IMPLEMENTATION +var counter,Dcounter,Lcounter:word; +{Procedure gettime(var hours,minutes,seconds,centi:byte);assembler; +asm + pushf + MOV AH, 2CH + INT 21H + LES DI,hours + MOV ES:[di],ch + MOV ES:[di+1],cl + MOV ES:[di+2],dh + MOV ES:[di+3],dl + popf +end;} + +Procedure Mouse(var m1,m2,m3,m4:integer);assembler; +asm + push es + les di,m1 + mov ax,es:[di] + les di,m2 + mov bx,es:[di] + les di,m3 + mov cx,es:[di] + les di,m4 + mov dx,es:[di] + pop es + int $33 + les di,m1 + mov es:[di],ax + les di,m2 + mov es:[di],bx + les di,m3 + mov es:[di],cx + les di,m4 + mov es:[di],dx +end; + +Procedure setuserproc(p:pointer;callmask:word);assembler; +asm + mov ax,000Ch + mov cx,callmask + les dx,p + int $33 +end; + +Procedure Setmousepos(x,y:integer); +Var m1,m:integer; +Begin + m1:=4; + mouse(m1,m,x,y); +end; + +Function resetmouse:boolean; +Var m1,m2,m:integer; +Begin + M1:=0; + Mouse(m1,m2,m,m); + resetmouse:=m1<>0; + {MousePicAdrs:=@arrow;} +end; + +{$IFDEF NonStandardVideo} +Procedure Mouseon; +var oldrect:trect; +begin + oldrect:=viewport; + viewport:=screenport; + if not mousevisible then + drawmouse(xm,ym,0,0,MSdrawpointer); + viewport:=oldrect; + oldvis:=mousevisible; + mousevisible:=true; +end; + +Procedure Mouseoff; +var oldrect:trect; +begin + oldrect:=viewport; + viewport:=screenport; + if mousevisible then + drawmouse(0,0,xm,ym,MSdrawold); + viewport:=oldrect; + oldvis:=mousevisible; + mousevisible:=false; +end; + +Procedure setmouseshape(x,y:integer;var mask); +var oldrect:trect; +begin + mousepicadrs:=pointer(@mask); + drawmouse(xm,ym,oldxm,oldym,MSdrawboth); +end; + +procedure mouseoffrect(var rect:trect); +begin + if rect.overlap(mouserect) then + mouseoff; +end; +{$ELSE} + +Procedure Mouseon;assembler; +asm + mov ax,1 + int $33 +End; + +Procedure Mouseoff;assembler; +asm + mov ax,2 + int $33 +End; + +Procedure setmouseshape(x,y:integer;var mask); +Var M1,M2,M3,M4:integer; +Begin + M1:=9;m2:=x;m3:=y; + m4:=ofs(mask); + asm + les di,mask + end; + Mouse(m1,m2,m3,m4); + setmousepos(xm+1,ym); + setmousepos(xm,ym); +End; + +procedure mouseoffrect(var rect:trect);assembler; + {if mousevisible then begin + if rect.overlap(mouserect) then + mouseoff; + end;} + asm + mov ax,$10 + les di,rect + mov cx,es:[di] + mov dx,es:[di+2] + mov si,es:[di+4] + mov di,es:[di+6] + int $33 +end; + +{$ENDIF} + +Procedure getdirection(var hor,ver:integer); +Var m1,m2,m3,m4:integer; +Begin + m1:=11; + mouse(m1,m2,hor,ver); +End; + +function getxmove:integer; +Var m1,m2,m3,m4,ver,hor:integer; +Begin + m1:=11; + mouse(m1,m2,hor,ver); + getxmove:=hor; +End; + +function getymove:integer; +Var m1,m2,m3,m4,ver,hor:integer; +Begin + m1:=11; + mouse(m1,m2,hor,ver); + getymove:=ver; +End; + +Procedure setmouserect(x1,y1,x2,y2:integer); +Var M1,M2,M3,M4:integer; +Begin + M1:=7;M3:=X1;M4:=X2; + Mouse(M1,M2,M3,M4); + M1:=8;M3:=Y1;M4:=Y2; + Mouse(M1,M2,M3,M4); +End; + + + +Procedure setmickeys(x,y:integer);assembler; +asm + mov ax,0fh + mov cx,x + mov dx,y + int 33h +end; + +Procedure setsence(x,y,dspeed:integer);assembler; +asm + mov ax,1Ah + mov bx,x + mov cx,y + mov dx,dspeed + int 33h +end; + +var oldmouserect:trect; + +Procedure mbutton; + + +begin + + asm + push gridxm + push gridym + push oldgridxm + push oldgridym + push xm + push ym + push oldxm + push oldym + end; + mpos; + asm + pop oldym + pop oldxm + pop ym + pop xm + pop oldgridym + pop oldgridxm + pop gridym + pop gridxm + end; + +end; + +Procedure mpos; +var M1:integer; +oldwritemode,oldcol:byte; +oldrect:trect; +Begin + M1:=3; + oldxm:=xm;oldym:=ym;oldzm:=zm; + oldgridxm:=gridxm;oldgridym:=gridym; + Mouse(m1,zm,xm,ym); + mouserect.rpos(xm,ym); + + if Xgrid_size>1 then + GridXm:=(((Xm-Xgrid_corner) div Xgrid_size)*Xgrid_size)+Xgrid_corner + else + gridXm:=Xm; + if Ygrid_size>1 then + GridYm:=(((Ym-Ygrid_corner) div Ygrid_size)*Ygrid_size)+Ygrid_corner + else + GridYm:=Ym; + + ms_xdiff:=xm-oldxm;ms_ydiff:=ym-oldym; + ms_moved:=(oldxm<>xm)or(oldym<>ym); + ms_gridmoved:=(oldgridxm<>gridxm)or(oldgridym<>gridym); + ms_released:=(oldzm<>0)and(zm=0); + + ms_pressed:=(oldzm<>zm)and(zm<>0); + + if ms_pressed then counter:=timer+clickwait; + ms_clicked:=(ms_released)and(timerlinger_for; + end else begin + Lcounter:=0; + ms_lingering:=false; + end; + + {$IFDEF NonStandardVideo} + if (ms_moved)and(mousevisible) then begin + drawmouse(xm,ym,oldxm,oldym,msdrawboth); + end; + {$Endif} +end; + +Procedure xyfilter; +begin + if scan and 2<>0 then xm:=oldxm else + if scan and 4<>0 then ym:=oldym; +end; + +Procedure ymisxm;Begin + if scan and 4<>0 then begin ym:=xm;oldym:=oldxm;end; +end; + +Procedure stoprepeat; +Begin +While zm<>0 do mpos; +end; + +function chkicon(x1,y1,x2,y2:integer):shortint; +Begin + if (xm>=x1) and (ym>=y1) and (xm<=x1+x2) and (ym<=y1+y2) then + chkicon:=zm + else chkicon:=-1; +end; + +function chkouticon(x1,y1,x2,y2:integer):shortint; +Begin + if (xmx1+x2) or (ym>y1+y2) then + chkouticon:=zm + else chkouticon:=-1; +end; + +Procedure stoprepeatwait(wait:word); +Var start,count:word; +Begin + start:=timer; + count:=0; + While (zm<>0) and (count0; +end; + +Begin + counter:=clickwait; + Dcounter:=Dclickwait; + Lcounter:=linger_for; + {setuserproc(@getstuff,255);} +end. diff --git a/PCX256.PAS b/PCX256.PAS new file mode 100644 index 0000000..4f24f7d --- /dev/null +++ b/PCX256.PAS @@ -0,0 +1,263 @@ +Unit PCX256; +INTERFACE +uses ggraph,gbasics,tmaths,ttypes,diskop,colour; + +const +{////PICTURE ATTRIBUTES////} +PAflat=BMflat; +PAPlanes=BMPlanes; +PACheckVidMode=0; {DDB} +PAtypemask=BMflat+BMPlanes; + +PAcolcheck=4; + +type +pcx_header=record + header:byte; + version:byte; {5 for extra colours at end of file} + encoding:byte; {1 for runlength} + bits_per_pixel:byte; + window:trect; + resolution:pointtype; + cmap:array[0..15]of RGBtype; + reserved:byte; + numplanes:byte; + offset:integer; {screen width in bytes} + PaletteInfo:integer; {1 =colour/bw, 2=greyscale} + screensize:pointtype; + filler:array[0..53]of byte; +end; + +var +LCmap:bytearray; +header:pcx_header; + +const + no_bytes_back=769; + Check_256Val=12; + chkbits=$C0; + maskbits=255-chkbits; + +Function readPCX(filename:string;Pattrib:byte):pointer; +Procedure writePCX(pic:bitmaptypeptr;filename:string); +IMPLEMENTATION + +Procedure writePCX(pic:bitmaptypeptr;filename:string); +var + writecol:rgbtype; + lop:byte; + xlop,ylop,runsize,subtotal:integer; + writeheader:pcx_header; + f:file; + recsize,bufsize:word; + linebuf,currbyte:^byte; + temp,oldbyte,runcolour:byte; + +procedure endrun; +begin + currbyte^:=chkbits or runsize; + inc(currbyte); + inc(bufsize); + currbyte^:=runcolour; + runsize:=0; + {on off subtotal count -there was a 'run flag' byte} +end; + +begin + recsize:=1; + assign(f,filename); + rewrite(f,recsize); + + with writeheader,pic^ do begin + header:=$0a; + version:=5; + encoding:=1; + bits_per_pixel:=8; + window.rassign(0,0,size.x,size.y-1); + resolution.x:=1+sc.screenport.x2-sc.screenport.x1; + resolution.y:=1+sc.screenport.y2-sc.screenport.y1; + for lop:=0 to 15 do with cmap[lop] do + getrgb(lop,r,g,b); + reserved:=0; + numplanes:=1; + offset:=size.x; + if offset mod 2<>0 then inc(offset); + PaletteInfo:=1; + screensize:=resolution; + fillchar(filler,54,0); + blockwrite(f,writeheader,sizeof(writeheader),recsize); + {reset internal picture coords} + Qsetxy(0,0); + getmem(linebuf,size.x); + {blockwrite(f,pic^,planesize,recsize);} + for ylop:=1 to size.y do begin + currbyte:=linebuf; + bufsize:=0; + oldbyte:=currbyte^+1; + runsize:=0; + subtotal:=0; + while (subtotaltemp then begin + {end an ongoing run?} + if runsize>0 then + endrun; + {no run} + inc(currbyte); + inc(bufsize); + if temp and chkbits<>0 then dec(temp); + oldbyte:=temp; + {inc(subtotal); + {reset runsize} + end else if runsize<=64 then begin + {run in progress...} + if runsize=0 then runcolour:=temp; + inc(runsize); + {inc(subtotal);} + end else + endrun; + end; + {end run if currently in one} + if runsize>0 then endrun; + blockwrite(f,linebuf^,bufsize,recsize); + end; + freemem(linebuf,size.x); + t_col:=check_256val; + + blockwrite(f,t_col,1,recsize); + for lop:=0 to 255 do with writecol do begin + getrgb(lop,r,g,b); + blockwrite(f,writecol,3,recsize); + end; + end; + close(f); +end; + +Function readPCX(filename:string;pattrib:byte):pointer; +var + buf:bufferedblock; + xln,yln,xpos,ypos:integer; + tmpRGB:RGBtype; + tmpcolref:byte; + bmtype:byte; + + lop,chk,loadbyte:byte; + subtotal,scanlop,xlop,palsize:word; + oldfilepos:word; + tmp:byteptr; + + pic:bitmaptypeptr; + +begin + buf.open(filename); + buf.blockread(@header,sizeof(pcx_header)); + with header do begin + xln:=1+(window.x2-window.x1); + yln:=1+(window.y2-window.y1); + if memavail<(((xln shr 3)*yln) *4) then begin + buf.close; + readpcx:=nil; + end; + + {PCX files xoffset needs to be even} + if xln mod 2<>0 then inc(xln); + bmtype:=Pattrib and PAtypemask; + case bmtype of + PAcheckvidmode: + if SC.colourdepth>16 then + pic:=createBitmap(xln,yln,8,BMflat) + else + pic:=createBitmap(xln,yln,4,BMplanes); + PAflat: + pic:=createBitmap(xln,yln,8,BMflat); + PAPlanes: + pic:=createBitmap(xln,yln,4,BMplanes); + end; + SetBitmapContext(pic); + + palsize:=0; + if (bits_per_pixel<=4) then begin + palsize:=16; + Getmem(LCmap,palsize); + for lop:=0 to 15 do begin + with Cmap[lop] do + LCmap^[lop]:=AllocateRGB(r shr 2,g shr 2,b shr 2); + end + end else begin + oldfilepos:=buf.fpos; + buf.fseek(filesize(buf.f)-no_bytes_back); + chk:=buf.get; + if (chk=check_256val) then begin + palsize:=256; + Getmem(LCmap,palsize); + for lop:=0 to 255 do begin + buf.blockread(@TmpRGB,3); + with TmpRGB do + LCmap^[lop]:=AllocateRGB(r shr 2,g shr 2,b shr 2); + end; + end; + buf.fseek(oldfilepos+1); + end; + {begin image decode} + xpos:=0; + ypos:=0; + if bits_per_pixel=8 then begin + for scanlop:=0 to pic^.size.y-1 do begin + subtotal:=0; + while subtotal0) then + t_col:=LCmap^[buf.get] + else + t_Col:=buf.get; + for xpos:=xpos to xpos+chk do + BMputpixel(xpos,ypos); + inc(subtotal,chk); + end else begin + if (pattrib and PAcolcheck <>0) then + t_col:=LCmap^[chk] + else + t_col:=chk; + BMputpixel(xpos,ypos); + inc(xpos); + inc(subtotal); + end; + end; + inc(ypos); + xpos:=0; + end; + end else begin + {begin image decode} + {getmem(buf,offset*bitplanes); + for scanlop:=0 to size.y-1 do begin + for currplane:=0 to bitplanes-1 do begin + subtotal:=0; + while subtotal0 then + freemem(LCmap,palsize); + end; + buf.close; + readPCX:=pic; +end; +end. diff --git a/PITTIMER.PAS b/PITTIMER.PAS new file mode 100644 index 0000000..875f546 --- /dev/null +++ b/PITTIMER.PAS @@ -0,0 +1,95 @@ +UNIT PITtimer; + + +INTERFACE +Uses Dos; + +{$F+} { Force far mode, a good idea when mucking around with interrupts } + +const TIMERINTR = 8; + PIT_FREQ = $1234DD; + +procedure SetTimer(TimerHandler : pointer; frequency : word); +procedure CleanupTimer; + +IMPLEMENTATION +var BIOSTimerHandler : procedure; + clock_ticks, counter : longint; + PHandle:procedure; + +{Ok, here's our actual handler. This particular handler just writes an +asterix (*) to the screen. Then it does the checks to see if the BIOS +handler should be called. If so it calls it, if not it acknowledges the +interrupt itself.} + +procedure Handler; Interrupt; +begin + + Phandle; + { Adjust the count of clock ticks } + inc(clock_ticks,counter); + + { Is it time for the BIOS handler to do it's thang? } + if clock_ticks >= $10000 then begin + { Yep! So adjust the count and call the BIOS handler } + clock_ticks := 0; + + asm pushf end; + BIOSTimerHandler; + end + + { If not then just acknowledge the interrupt } + else + Port[$20] := $20; +end; + +{ +The clock_ticks variable will keep track of how many cycles the PIT has +had, it'll be intialised to 0. The counter variable will hold the new +channel 0 counter value. We'll also be adding this number to clock_ticks +every time our handler is called. + +Next we need to do some initialization:} + +procedure SetTimer(TimerHandler : pointer; frequency : word); +begin + + { Do some initialization } + clock_ticks := 0; + counter := $1234DD div frequency; + + { Store the current BIOS handler and set up our own } + GetIntVec(TIMERINTR, @BIOSTimerHandler); + SetIntVec(TIMERINTR, @Handler); + @Phandle:=timerHandler; + + { Set the PIT channel 0 frequency } + Port[$43] := $34; + Port[$40] := counter mod 256; + Port[$40] := counter div 256; +end; +{ +Pretty straightforward stuff. We save the address of the BIOS handler, +install our own, set up the variables we'll use and program PIT channel 0 +for the divide-by-N mode at the frequency we need. + +This next bit is what we need to do once our program is finished. It just +resets everything back to normal.} + +procedure CleanUpTimer; +begin + { Restore the normal clock frequency } + Port[$43] := $34; + Port[$40] := 0; + Port[$40] := 0; + + { Restore the normal ticker handler } + SetIntVec(TIMERINTR, @BIOSTimerHandler); +end; +{ +And finally our calling program. What follows is just an example program +which sets everything up, waits for us to press a key and then cleans up +after itself. +} + +end. \ No newline at end of file diff --git a/SINCOS.PAS b/SINCOS.PAS new file mode 100644 index 0000000..62fdb10 --- /dev/null +++ b/SINCOS.PAS @@ -0,0 +1,40 @@ +Unit Sincos; + +INTERFACE +const +{set these up so you don'y have to use tmaths directly} +maxangle=256; +maxangle_mask=maxangle-1; + +shiftsize=10; +shiftmult=1 shl shiftsize; + + +var +Sin_real,Cos_real:array[0..maxangle+1] of real; +Sin_int,Cos_int:array[0..maxangle+1] of longint; +procedure init_sin_cos_int; +procedure init_sin_cos_real; +IMPLEMENTATION + + + +procedure init_sin_cos_real; +var lop:word; +begin + For lop:=0 to maxangle+1 do Begin + Sin_real[lop]:=sin(lop*pi/(maxangle shr 1)); + Cos_real[lop]:=cos(lop*pi/(maxangle shr 1)); + end; +end; + + +procedure init_sin_cos_int; +var lop:word; +begin + For lop:=0 to maxangle+1 do Begin + Sin_int[lop]:=ROUND(sin(PI/(maxangle shr 1)*lop)*shiftmult); + Cos_int[lop]:=ROUND(cos(PI/(maxangle shr 1)*lop)*shiftmult); + end; +end; +end. \ No newline at end of file diff --git a/STDPAL.PAS b/STDPAL.PAS new file mode 100644 index 0000000..7b2de63 --- /dev/null +++ b/STDPAL.PAS @@ -0,0 +1,13 @@ +unit stdpal; + +INTERFACE +uses colour; + +const +pal16:array[0..15]of rgbtype=((r:0;g:0;b:0), +(r:6;g:6;b:8),(r:16;g:17;b:22),(r:22;g:22;b:26),(r:29;g:29;b:32), +(r:36;g:38;b:42),(r:48;g:50;b:52),(r:63;g:63;b:63),(r:9;g:7;b:19), +(r:23;g:31;b:45),(r:30;g:49;b:63),(r:9;g:47;b:0),(r:63;g:54;b:0), +(r:54;g:38;b:2),(r:46;g:0;b:0),(r:52;g:52;b:41)); +IMPLEMENTATION +end. diff --git a/SVGA256.PAS b/SVGA256.PAS new file mode 100644 index 0000000..2ef3a45 --- /dev/null +++ b/SVGA256.PAS @@ -0,0 +1,1832 @@ +Unit SVGA256; +INTERFACE +{Super VGA driver C. 1996 T.Lewis} + +uses chardef,ttypes,gbasics,tmaths,vesainfo; +const +{VGA register locations} +MISC_ADDR=$3C2; MISC_READ_ADDR=$3CC; +ATTR_ADDR=$3c0; ATTR_DATA_ADDR=$3c1; +SEQU_ADDR=$3c4; SEQU_DATA_ADDR=$3c5; +CRTC_ADDR=$3D4; CRTC_DATA_ADDR=$3d5; +GRPH_ADDR=$3CE; GRPH_DATA_ADDR=$3CF; +STATUS_ADDR=$3da; + +function set_mode(mode:byte):boolean; +Procedure bar(x1,y,x2,y2:integer); +Procedure GTriangle(xa,ya,xb,yb,xc,yc,ia,ib,ic:integer); +Procedure Triangle(xa,ya,xb,yb,xc,yc:integer); +Procedure Line(x1,y1,x2,y2:integer); +Procedure Hline(x1,x2,y:Integer); +Procedure Vline(x,y1,y2:Integer); +Procedure putpixel(x1,y1:Integer); +Function getpixel(x1,y1:Integer):byte; +Procedure outtextxy(x1,y1:integer;txt:string); +Procedure outtextxy_length(x1,y1:integer;txt:pchar;length:byte); +Procedure Drawbytes(x1,y1:Integer;pic:bytearray;nbytes:byte); +Procedure Drawbytesxy(x1,y1:Integer;pic:bytearray;xbytes,ybytes:byte); +Procedure Screencopy(x1,y1,x2,y2,xd,yd:integer;page1,page2:byte); +procedure putbitmap(x1,y1:integer;bitmap:bitmaptypeptr); +function getbitmap(x1,y1,x2,y2:integer):bitmaptypeptr; +Procedure cleardevice; +procedure savescreenregs; +procedure restorescreenregs; + +Procedure GetAreaUnderMouse(x,y:integer;buf:byteptr); +Procedure PutMouse(x,y:integer;buf:byteptr); +Procedure PutAreaUnderMouse(x,y:integer;buf:byteptr); + +{quick generic interface to screen -good for file loading} +Procedure QSetXY(x,y:integer); +Procedure Qwrite(count:word); +function Qget:byte; + +var + +oldscreenwindow:word; +setpagefunc:procedure; + +Granularity:longint; +NumberOfSegments,currwin:word; + +IMPLEMENTATION + +procedure savescreenregs;assembler; +asm + mov ax,4f05h + mov bh,1 + xor bl,bl + int 10h + mov oldscreenwindow,dx +end; + +procedure restorescreenregs;assembler; +asm + mov dx,oldscreenwindow + mov ax,4f05h;xor bx,bx;int 10h +end; + +Procedure GetAreaUnderMouse(x,y:integer;buf:byteptr); +begin +end; +Procedure PutMouse(x,y:integer;buf:byteptr); +begin +end; +Procedure PutAreaUnderMouse(x,y:integer;buf:byteptr); +begin +end; + + +procedure setSVGA_window(win:word);assembler; +asm + mov dx,win + Cmp currwin,dx + jz @nochange + mov ax,4f05h + xor bx,bx + int 10h + @nochange: +end; + +function set_mode(mode:byte):boolean; + +begin + if getvesaheaderinfo(@SVGAheader)<>SVGAok then begin + set_mode:=false; + exit; + end; + if getvesainfo(@SVGAinfo,255+mode)=SVGAok then begin; + setpagefunc:=SVGAinfo.WinFuncPtr; + end; + + +{set up the video mode} + asm + + mov ax,4F02h; + mov bh,01h; + mov bl,mode; + int 10h + + + + mov dx,0 + mov currwin,dx + xor bx,bx; + call setpagefunc + end; + NumberOfSegments:=longint((SC.pagesize)div $ffff); + + set_mode:=TRUE; +end; + +procedure FillWord(var Dest; Count: Word; Data: Word); +begin + inline( + $C4/$7E/=SC.viewport.x1)and(x1<=SC.viewport.x2)and(y1+nbytes>=SC.viewport.y1)and(y1<=SC.viewport.y2)then begin + {**XCliping**} + mask:=$ff; + if x1SC.viewport.x2 then + mask:=mask and ($ff shl (x2-SC.viewport.x2-1)); + + {**YCliping**} + If y1+nbytes>SC.viewport.y2 then lop:=(SC.viewport.y2-y1) else lop:=nbytes; + if y1SC.viewport.x2))+ {right =$01} + (byte(yb>SC.viewport.y2)shl 1)+{bellow =$02} + (byte(xbSC.viewport.x2))+ {right =$01} + (byte(ya>SC.viewport.y2)shl 1)+{bellow =$02} + (byte(xa0 then begin + clip:=false;exit;{Trivial reject} + end else begin + if not(code0 or code1<>0)then begin + clip:=true;exit;{Trivial accept} + end else If (code0=0) then begin + fswap(code1,code0,1); + fswap(xb,xa,2); + fswap(yb,ya,2); + end; + if (code0 and bellow)<>0 then begin + inc(xb,(xa-xb)*(SC.viewport.y2-yb)div(ya-yb)); + yb:=SC.viewport.y2; + end else if (code0 and above)<>0 then begin + inc(xb,(xa-xb)*(SC.viewport.y1-yb)div(ya-yb)); + yb:=SC.viewport.y1; + end else if (code0 and right)<>0 then begin + inc(yb,(ya-yb)*(SC.viewport.x2-xb)div(xa-xb)); + xb:=SC.viewport.x2; + end else if (code0 and left)<>0 then begin + inc(yb,(ya-yb)*(SC.viewport.x1-xb)div(xa-xb)); + xb:=SC.viewport.x1; + end; + end; + end; +end; + +{biechmans line drawing algo- bit optimization still needed} +Procedure Line(x1,y1,x2,y2:integer); +Var dfx,dfy,d,d2,incr1,incr2,xinc:integer; +adrs:longint; +currentwindow:word; +Begin + + if x1=x2 then vline(x1,y1,y2) else begin + if y1=y2 then hline(x1,x2,y1) else + if clip(x1,y1,x2,y2) then Begin + currentwindow:=currwin; + dfx:=abs(x2-x1);dfy:=abs(y2-y1); + + if T_writemode<>xorput then begin + + if dfx>dfy then begin + asm + mov ax,x2 ; cmp x1,ax ; jle @no_swap + Xchg x1,ax ; mov x2,ax + mov ax,y2; Xchg y1,ax;mov y2,ax; + @no_swap: + end; + adrs:=(y1*SC.offsw) +x1; + asm + mov dx,word ptr adrs+2 + mov currentwindow,dx + xor bx,bx;call setpagefunc + end; + incr2:=(dfy-dfx)shl 1; + + {shallow lines} + if y2>y1 then asm + mov al,t_col + mov dx,SC.offsw {get scanline offset} + les bx,SC.Scrptr + add bx,word ptr adrs + + mov cx,dfx ;inc cx {load in the length} + mov si,dfy ;shl si,1; {get incr1} + + mov di,si ;sub di,dfx; {get 'd'} + + @Runloop: {start loop} + mov es:[bx],al + inc bx + {set svga window} + jnz @nooverflow + {bx should already be 0} + inc currentwindow;mov dx,currentwindow + call setpagefunc; + mov dx,SC.offsw;mov al,t_col + @nooverflow: + + cmp di,0;jl @noinc {new scan line?} + add di,incr2 {update di} + add bx,dx {add scanline offset} + {set svga window} + ja @nooverflow1 + push bx + inc currentwindow;mov dx,currentwindow + xor bx,bx; call setpagefunc + mov dx,SC.offsw;mov al,t_col + pop bx + @nooverflow1: + jmp @check + @noinc: + add di,si {update fractional part} + @check: + loop @runloop + end else asm + + mov al,t_col + mov dx,SC.offsw {get scanline offset} + les bx,SC.Scrptr + add bx,word ptr adrs + + mov cx,dfx ;inc cx {load in the length} + mov si,dfy ;shl si,1; {get incr1} + mov di,si ;sub di,dfx; {get 'd'} + + @Runloop: {start loop} + mov es:[bx],al + inc bx + {set svga window} + jnz @nooverflow + {bx should already be 0} + inc currentwindow;mov dx,currentwindow + xor bx,bx;call setpagefunc + mov dx,SC.offsw;mov al,t_col + @nooverflow: + + cmp di,0;jl @noinc {new scan line?} + add di,incr2 {update di} + + sub bx,dx {sub scanline offset} + {set svga window} + jnc @nooverflow1 + push bx + dec currentwindow;mov dx,currentwindow + xor bx,bx; call setpagefunc + mov dx,SC.offsw;mov al,t_col + pop bx + @nooverflow1: + + jmp @check + @noinc: + add di,si {update fractional part} + @check: + loop @runloop + end + + end else begin + {steep lines} + asm + mov ax,y2 ; cmp y1,ax ; jle @no_swap + Xchg y1,ax ; mov y2,ax + mov ax,x2; Xchg x1,ax;mov x2,ax; + @no_swap: + end; + adrs:=(y1*SC.offsw) +x1; + d2:=dfx shl 1; + d:=d2-dfy; + incr1:=d2; + incr2:=(dfx-dfy) shl 1; + asm + {set svga window} + mov dx,word ptr adrs+2 + Cmp currentwindow,dx + jz @nochange + mov currentwindow,dx + xor bx,bx;call setpagefunc + @nochange: + + inc dfy {add one to difference in y} + mov dx,SC.offsw {screen width} + les bx,SC.Scrptr {point to screen} + add bx,word ptr adrs + + mov al,t_col {Colour} + mov di,d {(diff in X*2)-diff in y} + mov si,incr1 {integer increment} + + mov cx,x1; cmp cx,x2; + jg @left {check if line is doing left or right} + + {do these loads for both directions because of the use of bp} + mov cx,dfy {difference in Y} + @Runloop: + mov es:[bx],al {Write to screen} + add bx,dx {next scan line} + {set svga window} + ja @nooverflow2 + push bx + inc currentwindow;mov dx,currentwindow + xor bx,bx; call setpagefunc + mov dx,SC.offsw;mov al,t_col + pop bx + @nooverflow2: + cmp di,0 {if no change} + jl @noinc {then don't do below} + add di,incr2 {do frac part} + inc bx {go to next byte on screen} + {set svga window} + jnz @nooverflow3 + {bx should already be 0} + inc currentwindow;mov dx,currentwindow + xor bx,bx; call setpagefunc + mov dx,SC.offsw;mov al,t_col + @nooverflow3: + jmp @check + @noinc: + add di,si {add frac part} + @check: + loop @runloop + jmp @end + + @left: + + {do these loads for both directions because of the use of bp} + mov cx,dfy {difference in Y} + @Runloopb: + mov es:[bx],al {Write to screen} + add bx,dx {next scan line} + {set svga window} + ja @nooverflow4 + inc currentwindow;mov dx,currentwindow + push bx + + xor bx,bx; call setpagefunc; + mov dx,SC.offsw;mov al,t_col + pop bx + @nooverflow4: + cmp di,0 {if no change} + jl @noincb {then don't do below} + add di,incr2 {do frac part} + cmp bx,0 {are we on zero?} + {set svga window} + jnz @nooverflow5 + {if so, do bank switch} + dec currentwindow;mov dx,currentwindow + {push bx} + xor bx,bx;call setpagefunc; + mov dx,SC.offsw;mov al,t_col + {pop bx} + mov bx,65535 + jmp @checkb + @nooverflow5: + dec bx {otherwise, jump as normal} + jmp @checkb + @noincb: + add di,si {add frac part} + @checkb: + loop @runloopb + @end: + end; + + end; + currwin:=currentwindow; + end else begin + if dfx>dfy then begin + asm + mov ax,x2 ; cmp x1,ax ; jle @no_swap + Xchg x1,ax ; mov x2,ax + mov ax,y2; Xchg y1,ax;mov y2,ax; + @no_swap: + end; + adrs:=(y1*SC.offsw) +x1; + asm + mov dx,word ptr adrs+2 + mov currentwindow,dx + xor bx,bx;call setpagefunc; + end; + incr2:=(dfy-dfx)shl 1; + + {shallow lines} + if y2>y1 then asm + mov al,t_col + mov dx,SC.offsw {get scanline offset} + les bx,SC.Scrptr + add bx,word ptr adrs + + mov cx,dfx ;inc cx {load in the length} + mov si,dfy ;shl si,1; {get incr1} + + mov di,si ;sub di,dfx; {get 'd'} + + @Runloop: {start loop} + xor es:[bx],al + inc bx + {set svga window} + jnz @nooverflow + {bx should already be 0} + inc currentwindow;mov dx,currentwindow + call setpagefunc; + mov dx,SC.offsw;mov al,t_col + @nooverflow: + + cmp di,0;jl @noinc {new scan line?} + add di,incr2 {update di} + add bx,dx {add scanline offset} + {set svga window} + ja @nooverflow1 + push bx + inc currentwindow;mov dx,currentwindow + xor bx,bx; call setpagefunc; + mov dx,SC.offsw;mov al,t_col + pop bx + @nooverflow1: + jmp @check + @noinc: + add di,si {update fractional part} + @check: + loop @runloop + end else asm + + mov al,t_col + mov dx,SC.offsw {get scanline offset} + les bx,SC.Scrptr + add bx,word ptr adrs + + mov cx,dfx ;inc cx {load in the length} + mov si,dfy ;shl si,1; {get incr1} + mov di,si ;sub di,dfx; {get 'd'} + + @Runloop: {start loop} + xor es:[bx],al + inc bx + {set svga window} + jnz @nooverflow + {bx should already be 0} + inc currentwindow;mov dx,currentwindow + xor bx,bx;call setpagefunc; + mov dx,SC.offsw;mov al,t_col + @nooverflow: + + cmp di,0;jl @noinc {new scan line?} + add di,incr2 {update di} + + sub bx,dx {sub scanline offset} + {set svga window} + jnc @nooverflow1 + push bx + dec currentwindow;mov dx,currentwindow + xor bx,bx; call setpagefunc; + mov dx,SC.offsw;mov al,t_col + pop bx + @nooverflow1: + + jmp @check + @noinc: + add di,si {update fractional part} + @check: + loop @runloop + end + + end else begin + {steep lines} + asm + mov ax,y2 ; cmp y1,ax ; jle @no_swap + Xchg y1,ax ; mov y2,ax + mov ax,x2; Xchg x1,ax;mov x2,ax; + @no_swap: + end; + adrs:=(y1*SC.offsw) +x1; + d2:=dfx shl 1; + d:=d2-dfy; + incr1:=d2; + incr2:=(dfx-dfy) shl 1; + asm + {set svga window} + mov dx,word ptr adrs+2 + Cmp currentwindow,dx + jz @nochange + mov currentwindow,dx + xor bx,bx;call setpagefunc; + @nochange: + + inc dfy {add one to difference in y} + mov dx,SC.offsw {screen width} + les bx,SC.Scrptr {point to screen} + add bx,word ptr adrs + + mov al,t_col {Colour} + mov di,d {(diff in X*2)-diff in y} + mov si,incr1 {integer increment} + + mov cx,x1; cmp cx,x2; + jg @left {check if line is doing left or right} + + {do these loads for both directions because of the use of bp} + mov cx,dfy {difference in Y} + @Runloop: + xor es:[bx],al {Write to screen} + add bx,dx {next scan line} + {set svga window} + ja @nooverflow2 + push bx + inc currentwindow;mov dx,currentwindow + xor bx,bx; call setpagefunc; + mov dx,SC.offsw;mov al,t_col + pop bx + @nooverflow2: + cmp di,0 {if no change} + jl @noinc {then don't do below} + add di,incr2 {do frac part} + inc bx {go to next byte on screen} + {set svga window} + jnz @nooverflow3 + {bx should already be 0} + inc currentwindow;mov dx,currentwindow + xor bx,bx;call setpagefunc; + mov dx,SC.offsw;mov al,t_col + @nooverflow3: + jmp @check + @noinc: + add di,si {add frac part} + @check: + loop @runloop + jmp @end + + @left: + + {do these loads for both directions because of the use of bp} + mov cx,dfy {difference in Y} + @Runloopb: + xor es:[bx],al {Write to screen} + add bx,dx {next scan line} + {set svga window} + ja @nooverflow4 + inc currentwindow;mov dx,currentwindow + push bx + + xor bx,bx; call setpagefunc; + mov dx,SC.offsw;mov al,t_col + pop bx + @nooverflow4: + cmp di,0 {if no change} + jl @noincb {then don't do below} + add di,incr2 {do frac part} + cmp bx,0 {are we on zero?} + {set svga window} + jnz @nooverflow5 + {if so, do bank switch} + dec currentwindow;mov dx,currentwindow + {push bx} + xor bx,bx; call setpagefunc; + mov dx,SC.offsw;mov al,t_col + {pop bx} + mov bx,65535 + jmp @checkb + @nooverflow5: + dec bx {otherwise, jump as normal} + jmp @checkb + @noincb: + add di,si {add frac part} + @checkb: + loop @runloopb + @end: + end; + + end; + currwin:=currentwindow; + end; + end; + end; +end; + +Procedure Hline(x1,x2,y:Integer);assembler; +asm + mov ax,y;mov bx,x1; mov cx,x2 + {swap x1,x1 if x1>x2} + cmp bx,cx ;jle @no_swap ; Xchg bx,cx; @no_swap: + + {is line at all visable?} + cmp bx,SC.viewport.x2 ;jg @fin + cmp cx,SC.viewport.x1 ;jl @fin + cmp ax,SC.viewport.y2 ;jg @fin + cmp ax,SC.viewport.y1 ;jl @fin + + {X axis clipping} + mov dx,SC.viewport.x1 ;cmp bx,dx ; JGE @nochange_x1 + mov bx,dx + @nochange_x1: + mov dx,SC.viewport.x2 ;cmp cx,dx ; JLE @nochange_x2 + mov cx,dx + @nochange_x2: + + {calculate length (in bytes) of line} + sub cx,bx + inc cx + mov x2,cx + + {start of mode dependant stuff} {load up screen position} + + les di,SC.Scrptr {calculate screen pos} + + imul SC.offsw + add di,ax;add di,bx; adc dx,0 {add carray to dx (current SVGA window)} + + {set start svga window} + Cmp currwin,dx + jz @nochange + xor bx,bx;call setpagefunc; + @nochange: + + mov al,t_col;mov ah,al + + cmp t_writemode,xorput + jnz @normalput + add di,cx + ja @nooverflow + sub di,cx + mov bx,$FFFF {biggest word size minus segment offset} + sub bx,di + inc bx + mov cx,bx + {draw first segment of line} + @byteloop: + xor es:[di],al + inc di + loop @byteloop + + {get length of rest of line into cx} + mov cx,x2 + sub cx,bx + + {set svga window} + inc dx + xor bx,bx;call setpagefunc; + {restore al} + mov al,t_col;mov ah,al + mov di,0 {begining of segment} + + {draw second segment of line} + @byteloop2: + xor es:[di],al + inc di + loop @byteloop2 + + {set window counter} + mov currwin,dx + + jmp @fin + @nooverflow: + sub di,cx + @byteloop3: + xor es:[di],al + inc di + loop @byteloop3 + + {set window counter} + mov currwin,dx + jmp @fin + {does it cross a window boundry?} + @normalput: + add di,cx + ja @nooverflowb + sub di,cx + mov bx,$FFFF {biggest word size minus segment offset} + sub bx,di + inc bx + mov cx,bx + {draw first segment of line} + shr cx,1 {get word count} + REP stosw {store words} + adc cx,cx {extra byte?} + REP stosb {Draw if there} + {get length of rest of line into cx} + mov cx,x2 + sub cx,bx + + {set svga window} + inc dx + xor bx,bx;call setpagefunc; + {restore al} + mov al,t_col;mov ah,al + mov di,0 {begining of segment} + + {draw second segment of line} + shr cx,1 {get word count} + REP stosw {store words} + adc cx,cx {extra byte?} + REP stosb {Draw if there} + + {set window counter} + mov currwin,dx + + jmp @fin + @nooverflowb: + sub di,cx + shr cx,1 {get word count} + REP stosw {store words} + adc cx,cx {extra byte?} + REP stosb {Draw if there} + + {set window counter} + mov currwin,dx + + @fin: +end; + +Procedure Vline(x,y1,y2:Integer);assembler; +asm + mov ax,y1; mov cx,y2 ;mov bx,x + {swap y2,y1 if y1>y2} + cmp ax,cx ;jle @no_swap ; Xchg ax,cx; @no_swap: + + cmp ax,SC.viewport.y2 ;jg @fin {is line at all visable?} + cmp cx,SC.viewport.y1 ;jl @fin + cmp bx,SC.viewport.x2 ;jg @fin + cmp bx,SC.viewport.x1 ;jl @fin + + {Y axis clipping} + mov dx,SC.viewport.y1 ;cmp ax,dx ; JGE @nochange_y1 + mov ax,dx + @nochange_y1: + mov dx,SC.viewport.y2 ;cmp cx,dx ; JLE @nochange_y2 + mov cx,dx + @nochange_y2: + + inc cx {inc y2} + sub cx,ax {calc length} + + les di,SC.Scrptr {calculate screen pos} + + imul SC.offsw + add di,ax;add di,bx; adc dx,0 {add carray to dx (current SVGA window)} + + {change window?} + xor bx,bx; + cmp currwin,dx + jz @nochange + call setpagefunc; + @nochange: + + mov si,SC.offsw {load screen width} + mov al,t_col + + cmp t_writemode,xorput + jnz @runloop + + @runloopb: + xor es:[di],al {write to screen} + add di,si {next pixel} + ja @nooverflowb + + inc dx + call setpagefunc + mov al,t_col + + @nooverflowb: + loop @runloopb + mov currwin,dx + jmp @fin + + @runloop: + mov es:[di],al {write to screen} + add di,si {next pixel} + ja @nooverflow + {set svga window} + inc dx + call setpagefunc + mov al,t_col + @nooverflow: + loop @runloop + mov currwin,dx + @fin: +end; + + +Procedure bar(x1,y,x2,y2:integer); +Begin + if x2SC.viewport.y2)or(y2SC.viewport.x2)or(x2SC.viewport.x2 then x2:=SC.viewport.x2;if y2>SC.viewport.y2 then y2:=SC.viewport.y2; + asm + les di,SC.Scrptr {calculate screen pos} + mov ax,y + imul SC.offsw + add di,ax;add di,x1; adc dx,0 {add carray to dx (current SVGA window)} + + Cmp currwin,dx + jz @nochange + xor bx,bx;call setpagefunc; + @nochange: + + mov al,t_fillcol + mov ah,al + mov bx,x1 + sub x2,bx {get length of single line} + inc x2 + + mov si,SC.offsw + sub si,x2 + + mov bx,y {load loop count -ycnt} + sub y2,bx + inc y2 + + @runloop: + mov cx,x2 + add di,cx + ja @nooverflow + sub di,cx + mov bx,$FFFF {biggest word size minus segment offset} + sub bx,di + inc bx {correct length} + mov cx,bx + {draw first segment of line} + shr cx,1 {get word count} + REP stosw {store words} + adc cx,cx {extra byte?} + REP stosb {Draw if there} + {get length of rest of line into cx} + mov cx,x2 + sub cx,bx + + {set svga window} + inc dx + xor bx,bx;call setpagefunc; + {restore al} + mov al,t_fillcol;mov ah,al + xor di,di {begining of segment} + + {draw second segment of line} + shr cx,1 {get word count} + REP stosw {store words} + adc cx,cx {extra byte?} + REP stosb {Draw if there} + + jmp @overflowed + @nooverflow: + sub di,cx + shr cx,1 + rep stosw + adc cx,cx + rep stosb + @overflowed: + add di,si + ja @nooverflow2 + inc dx + xor bx,bx;call setpagefunc; + {restore al} + mov al,t_fillcol;mov ah,al + @nooverflow2: + + dec y2 + jnz @runloop + mov currwin,dx + + end; + end; +end; + +Procedure putpixel(x1,y1:Integer);assembler; +asm + {if dot visable?} + mov bx,x1 ;mov ax,y1 + cmp bx,SC.viewport.x1 ;jl @fin {clipping..} + cmp ax,SC.viewport.y1 ;jl @fin + cmp bx,SC.viewport.x2 ;jg @fin + cmp ax,SC.viewport.y2 ;jg @fin + + les di,SC.Scrptr {calculate screen pos} + imul SC.offsw + add di,bx; add di,ax;adc dx,0 {add carray to dx (current SVGA window)} + + {set svga window} + Cmp currwin,dx + jz @nochange + mov currwin,dx;xor bx,bx;call setpagefunc; + @nochange: + + {mov ax,4f05h;xor bx,bx;int 10h} + + mov al,t_col + mov es:[di],al + + @fin: +end; + +Function getpixel(x1,y1:Integer):byte; +begin +(* asm + les di,SC.Scrptr {calculate screen pos} + imul SC.offsw + add di,bx;; add di,ax; adc dx,0 {add carray to dx (current SVGA window)} + + {set svga window} + Cmp currwin,dx + jz @nochange + mov currwin,dx;mov ax,4f05h;xor bx,bx;int 10h + @nochange: + + mov al,es:[di] + mov @result,al + end;*) +end; + +Procedure Triangle(xa,ya,xb,yb,xc,yc:integer);assembler; +const shiftby=6; +Var +lop,Lx,Rx, +Lxadd,Rxadd,yrdiff,yldiff,xoff,Lxa,Rxa,xdiff,endp:integer; +right:boolean; +scroffset:word; + {sort by Y} + asm + {if ya>yc then swap xc,xa swap yc,ya fswap ic,ia} + mov ax,yc + cmp ya,ax + jl @NoSwapY1 + xchg ya,ax; mov yc,ax + mov ax,xc; xchg xa,ax; mov xc,ax + @NoSwapY1: + {if ya>yb then swap xb,xa swap yb,ya fswap ib,ia} + mov ax,yb + cmp ya,ax + jl @NoSwapY2 + xchg ya,ax; mov yb,ax + mov ax,xb; xchg xa,ax; mov xb,ax + @NoSwapY2: + {if yb>yc then swap xc,xb swap yc,yb fswap ic,ib} + mov ax,yc + cmp yb,ax + jl @NoSwapY3 + xchg yb,ax; mov yc,ax + mov ax,xc; xchg xb,ax; mov xc,ax + @NoSwapY3: + + {is the cross point to the left or right?} + mov di,yc;sub di,ya + mov ax,yb;sub ax,yc + mov cx,xc;sub cx,xa + imul cx + cmp di,0 + jz @nodiv + idiv di + @nodiv: + add ax,xc + cmp xb,ax + mov right,true + jle @isright + mov right,false + @isright: + {get smallest x} + mov bx,xa; + mov ax,xb + cmp bx,ax; jl @nodo1 ;mov bx,ax ;@nodo1: + mov ax,xc + cmp bx,ax; jl @nodo2 ;mov bx,ax ;@nodo2: + mov xoff,bx + {sub by bx and shift left } + sub xa,bx; + sub xb,bx; + sub xc,bx; + + shl xa,shiftby + shl xb,shiftby + shl xc,shiftby + + {get y length} + mov si,yc + cmp si,SC.viewport.y2 + jle @noyclip + mov si,SC.viewport.y2 + inc si + @noyclip: + + mov endp,si {exit routine if ends of tri are outside VP} + mov si,ya + cmp si,SC.viewport.y2 {if ya>SC.viewport then exit} + jg @triend + cmp si,endp {if ya=clipped yc then exit} + jz @triend + + {yldiff:=yb-ya;if yldiff=0 then yldiff:=1; + Lxadd:=(xb-xa) div yldiff;} + mov ax,xb ;sub ax,xa + mov bx,yb ;sub bx,ya + jz @nodiv1 + cwd + idiv bx + jmp @nocorrect1 + @nodiv1: + mov bx,1 + @nocorrect1: + mov yldiff,bx + mov lxadd,ax + {yrdiff:=yc-ya;if yrdiff=0 then yrdiff:=1; + Rxadd:=(xc-xa) div yrdiff;} + mov ax,xc ;sub ax,xa + mov bx,yc ;sub bx,ya + jz @nodiv2 + cwd + idiv bx + jmp @nocorrect2 + @nodiv2: + mov bx,1 + @nocorrect2: + mov yrdiff,bx + mov rxadd,ax + mov ax,xa + mov Lxa,ax + mov Rxa,ax + {test for swap} + test right,1 + jnz @isrightb + mov ax,rxadd + xchg lxadd,ax + mov rxadd,ax + @isrightb: + + mov es,word ptr SC.Scrptr+2 {load up screen mem pos} + mov cx,SC.offsw + mov ax,ya ;imul cx ;add ax,word ptr SC.Scrptr + mov di,ax + + @Yloop: + cmp si,yb + jnz @Daltend + {yldiff:=yc-yb;if yldiff=0 then yldiff:=1;} + mov bx,yc ;sub bx,yb + jnz @nocorrect; mov bx,1; @nocorrect: + {Lxadd:=(xc-xb) div yldiff;} + mov ax,xc; sub ax,xb + cwd + idiv bx + mov bx,xb + {test see which side these need to go in} + test right,true + jz @isleft + mov lxadd,ax + mov lxa,bx + jmp @Daltend + @isleft: + mov rxadd,ax + mov rxa,bx + @Daltend: + + push di + {inc x1a and x2a with the slope of line and inc offset} + mov ax,Lxadd;add lxa,ax + mov ax,Rxadd;add rxa,ax + {if ylop>SC.viewport.y1 then....} + mov ax,SC.viewport.y1 ;cmp ax,si ;jg @fin + {convert the line to normal pixel-space} + mov cx,rxa ;shr cx,shiftby ;add cx,xoff + mov dx,lxa ;shr dx,shiftby ;add dx,xoff + + {flip- shouldn't have to but there ya go} + cmp dx,cx ;jg @no_swap ; Xchg cx,dx; @no_swap: {if x1>x2 then swap} + {if (x1>SC.viewport.x2)or(x2yc then swap xc,xa swap yc,ya fswap ic,ia} + mov ax,yc + cmp ya,ax + jl @NoSwapY1 + xchg ya,ax; mov yc,ax + mov ax,xc; xchg xa,ax; mov xc,ax + mov ax,ic; xchg ia,ax; mov ic,ax + @NoSwapY1: + {if ya>yb then swap xb,xa swap yb,ya fswap ib,ia} + mov ax,yb + cmp ya,ax + jl @NoSwapY2 + xchg ya,ax; mov yb,ax + mov ax,xb; xchg xa,ax; mov xb,ax + mov ax,ib; xchg ia,ax; mov ib,ax + @NoSwapY2: + {if yb>yc then swap xc,xb swap yc,yb fswap ic,ib} + mov ax,yc + cmp yb,ax + jl @NoSwapY3 + xchg yb,ax; mov yc,ax + mov ax,xc; xchg xb,ax; mov xc,ax + mov ax,ic; xchg ib,ax; mov ic,ax + @NoSwapY3: + {is the cross point to the left or right?} + mov di,yc;sub di,ya + mov ax,yb;sub ax,yc + mov cx,xc;sub cx,xa + imul cx + cmp di,0 + jz @nodiv + idiv di + @nodiv: + add ax,xc + cmp xb,ax + mov right,true + jle @isright + mov right,false + @isright: + {get smallest x} + mov bx,xa; + mov ax,xb + cmp bx,ax; jl @nodo1 ;mov bx,ax ;@nodo1: + mov ax,xc + cmp bx,ax; jl @nodo2 ;mov bx,ax ;@nodo2: + mov xoff,bx + {sub by bx and shift left } + sub xa,bx; + sub xb,bx; + sub xc,bx; + + shl xa,shiftby + shl xb,shiftby + shl xc,shiftby + end; + asm + db 66h;shr word ptr ia,16; + db 66h;shr word ptr ib,16; + db 66h;shr word ptr ic,16; + end; + + ylop:=ya;endp:=yc; + if endp>SC.viewport.y2 then endp:=SC.viewport.y2+1; + + asm + {yldiff:=yb-ya;if yldiff=0 then yldiff:=1; + Lxadd:=(xb-xa) div yldiff;} + mov ax,xb ;sub ax,xa + mov bx,yb ;sub bx,ya + jz @nodiv1 + cwd + idiv bx + jmp @nocorrect1 + @nodiv1: + mov bx,1 + @nocorrect1: + mov yldiff,bx + mov lxadd,ax + {yrdiff:=yc-ya;if yrdiff=0 then yrdiff:=1; + Rxadd:=(xc-xa) div yrdiff;} + mov ax,xc ;sub ax,xa + mov bx,yc ;sub bx,ya + jz @nodiv2 + cwd + idiv bx + jmp @nocorrect2 + @nodiv2: + mov bx,1 + @nocorrect2: + mov yrdiff,bx + mov rxadd,ax + end; + {yrdiff:=yc-ya;if yrdiff=0 then yrdiff:=1; + Rxadd:=(xc-xa) div yrdiff;} + Lxa:=xa;Rxa:=xa; + + li32:=ia32; + ri32:=ia32; + liadd32:=(ib32-ia32)div yldiff; + riadd32:=(ic32-ia32)div yrdiff; + if not right then begin + fswap(rxadd,lxadd,2); + fswap(liadd32,riadd32,4); + end; + asm + mov es,word ptr SC.Scrptr+2 {load up screen mem pos} + mov si,SC.offsw + mov ax,ya ;imul si ;add ax,word ptr SC.Scrptr + mov scroffset,ax + end; + while ylopSC.viewport.y1 then....} + mov ax,SC.viewport.y1 ;cmp ax,ylop ;jg @fin + {convert the line to normal pixel-space} + {xa is in dx, xb is in cx} + mov cx,rxa ;shr cx,shiftby ;add cx,xoff + mov dx,lxa ;shr dx,shiftby ;add dx,xoff + {Xclipping} + mov di,cx + inc di + sub di,dx + mov ax,SC.viewport.x2 ;cmp cx,ax ; JLE @nochange_x2 + mov cx,ax + @nochange_x2: + mov ax,SC.viewport.x1 ;cmp dx,ax ; JGE @nochange_x1 + mov dx,ax + @nochange_x1: + inc cx + mov lx,dx + sub cx,dx {calculate xdiff} + jle @fin + mov xdiff,cx {save it} + {generate colour interpoltaion addition} + mov si,li {colour intensity start} + mov ax,ri + sub ax,si {load colour} + CWD {put ax into AX:DX, with sign} + idiv di {do it, baby} + mov cadd,ax {load ax into erm... addi?} + mov dx,lx + {re-evaluate start address} + mov di,scroffset + mov cx,dx {get the x value} + add di,cx {add this to total} + + mov cx,xdiff {xdiff is the length (xb-xa)} + + push bp + mov bp,Cadd {colour interpolation value} + + @drawloop: + mov bx,si {load colour} + shr bx,8 {get it into non-fixed range} + mov es:[di],bl {write to screen} + add si,bp {add colour interpolation value} + inc di {increment screen offset} + loop @drawloop + pop bp + @fin: + end; + {ci:=li; + for lop:=Lx to Rx do begin + t_col:=asr(ci); + inc(ci,addi); + putpixel(lop,ylop); + end;} + inc(scroffset,SC.offsw); + inc(ylop); + end; +end; + +Procedure putbitmap(x1,y1:integer;bitmap:bitmaptypeptr); +var ylop,xlop:integer; +adrs,picadrs:byteptr; +x2,y2:integer; +cwindow:word; +Begin + with bitmap^ do begin + x2:=x1+size.x; + y2:=y1+size.y; + if (y1<=SC.viewport.y2) and(x1<=SC.viewport.x2)and(x2>SC.viewport.x1) and(y2>SC.viewport.y1) then begin + if bitmaptype=BMflat then begin + Cwindow:=Currwin; + picadrs:=pointer(flatdata); + if x1SC.viewport.x1) and(y2>SC.viewport.y1) then begin + + picadrs:=pointer(flatdata); + if x13) then begin + setpolyvertex:=PVnotset; + exit; + end; + for i:=0 to numsides-1 do begin + if (p[i]=vertref) then begin + move(p[pvertref+1],p[pvertref],(3-pvertref) shl 1); + dec(numsides); + setpolyvertex:=PVdeleted; + exit; + end; + end; + p[pvertref]:=vertref; + setpolyvertex:=PVsetok; + +end; + +Procedure Polygontype.setattrib(attrib_: word; mode: Byte); +var oldselect:word; +begin + oldselect:=pattrib and PAselected; + case mode of + PAmodeFALSE:pattrib:=pattrib and not word(attrib_ or PAselected); + PAmodeTRUE:pattrib:=pattrib or word(attrib_); + PAmodeABS:pattrib:=attrib_; + end; + pattrib:=pattrib or oldselect; +end; + +procedure polygontype.reverse; +var pcpy:array[0..3] of word; + lop:byte; +begin + move(p,pcpy,numsides shl 1); + for lop:=0 to numsides-1 do + p[lop]:=pcpy[numsides-lop-1]; +end; +function polygontype.anyequal(testpoly:polygonptr):boolean; +var lop,lop2:byte; +begin + anyequal:=false; + for lop:=0 to numsides-1 do + for lop2:=0 to testpoly^.numsides-1 do + if p[lop]=testpoly^.p[lop2] then begin + anyequal:=true; + exit; + end; +end; + +function polygontype.equals(testpoly:polygonptr):boolean; +var t1,t2:longint;lop:byte; +begin + if numsides=testpoly^.numsides then begin + t1:=0;t2:=0; + for lop:=0 to numsides-1 do begin + inc(t1,p[lop]); + inc(t2,testpoly^.p[lop]); + end; + equals:=t1=t2; + end else + equals:=false; +end; + +function polygontype.anyselected(thred:nodearray):boolean; +{var lop:byte;} +begin + anyselected:=Pattrib and PAsomeselected<>0; + {for lop:=0 to numsides-1 do + if (thred^[p[lop]].nattrib and NAselected)<>0 then begin + anyselected:=true; + exit; + end; + anyselected:=false;} +end; + +function polygontype.countselected(thred:nodearray):byte; +var lop:byte;count:byte; +begin + if Pattrib and PAsomeselected=0 then begin + countselected:=0;exit; + end; + count:=0; + + for lop:=0 to numsides-1 do + if (thred^[p[lop]].nattrib and NAselected)<>0 then + inc(count); + countselected:=count; +end; + +function polygontype.getfirstselected(thred:nodearray):byte; +var lop:byte; +begin + + + for lop:=0 to numsides-1 do + if (thred^[p[lop]].nattrib and NAselected)<>0 then begin + getfirstselected:=lop; + exit; + end; + getfirstselected:=255; +end; + + + +function polygontype.allselected(thred:nodearray):boolean; +{var lop:byte;} +begin + allselected:=Pattrib and PAallselected<>0; + {for lop:=0 to numsides-1 do + if thred^[p[lop]].nattrib and NaSelected=0 then begin + allselected:=false; + exit; + end; + allselected:=true;} +end; + +{////JOIN TYPE////////////////////////////} +procedure jointype.reverse; +begin + fswap(f,t,sizeof(word)); +end; + +function jointype.insidepoly(const poly:polygontype):boolean; +begin + with poly do + insidepoly:=((f=p[0])and(t=p[1]))or((t=p[0])and(f=p[1]))or + ((f=p[1])and(t=p[2]))or((t=p[1])and(f=p[2]))or + ((f=p[2])and(t=p[3]))or((t=p[2])and(f=p[3]))or + ((f=p[3])and(t=p[0]))or((t=p[3])and(f=p[0])); +end; + +function jointype.equals(const join:jointype):boolean; +begin + equals:=((join.f=f)and(join.t=t))or((join.f=t)and(join.t=f)); +end; + +function jointype.allselected(thred:nodearray):boolean; +begin + allselected:=((thred^[f].nattrib and NaSelected)=NaSelected) and ((thred^[t].nattrib and Naselected)=NaSelected); +end; + +function jointype.anyselected(thred:nodearray):boolean; +begin + anyselected:=((thred^[f].nattrib and NaSelected)=NaSelected) or ((thred^[t].nattrib and NaSelected)=NaSelected); +end; + +function jointype.clockwise(thred:nodearray):boolean; +begin + +end; + +{////LIGHT VECTOR/////////////////////////////} + +Procedure lightvectype.setlight(fx,fy,fz,tx,ty,tz:real;range:integer); +begin + f.moveto(fx,fy,fz); + t.moveto(tx,ty,tz); + + uvec.moveto(f.x-t.x,f.y-t.y,f.z-t.z); + uvec.unitvec(range); +end; + +{////OBJTYPE////////////////////////////////////////} + + +function objtype_.intensity(Poly:polygonptr):integer; +Var u:VectorReal; +Begin + with poly^ do + CalcSurfNormal(thred^[p[1]],thred^[p[0]],thred^[p[2]],U); + intensity:=((SC.colourdepth-1) shr 1)+round(dot(u,lightvec.uvec)); +end; + +procedure FSwap(Var s,d; L:Integer); +Begin + Inline($1e /$c5/$b6/s /$c4/$be/d /$8b/$8e/l /$fc /$26/$8a/$05 + /$86/$04 /$46 /$aa /$e2/$f7 /$1f); +end; + +{clear the reserved field in the nodes} +Procedure objtype_.ResetNodeReservedAttrib; +var +i:word; +begin + for i:=0 to maxpoints-1 do with thred^[i] do + nattrib:=nattrib and not (NAreserved); + +end; + +constructor objtype_.Create(mpnts,mjoins,mpolys:word); +Begin + name:=''; + LmUnit(@ObMat); + + pointsize:=mpnts;joinsize:=mjoins;polysize:=mpolys; + maxpoints:=0;maxjoins:=0;maxpolys:=0; + oldmaxpoints:=0;oldmaxjoins:=0;oldmaxpolys:=0; + maxselect:=0; + minselect:=0; + draw_points_offset:=0; + draw_lines_offset:=0; + draw_polys_offset:=0; + + + getmem(tmpz,pointsize*sizeof(Real)); + {getmem(Normals,pointsize*sizeof(NormalType));} + getmem(thred,pointsize*sizeof(NodeType)); + getmem(select,pointsize*sizeof(word)); + + getmem(jointo,joinsize*sizeof(jointype)); + getmem(polys,polysize*sizeof(polygontype)); + getmem(twod,pointsize*sizeof(pointtype)); + getmem(zav,polysize*sizeof(real)); + max.moveto(0,0,0); + min:=max; +end; + +Destructor objtype_.Done; +Begin + freemem(tmpz,pointsize*sizeof(Real)); + {freemem(Normals,pointsize*sizeof(NormalType));} + freemem(select,pointsize*sizeof(word)); + freemem(thred,pointsize*sizeof(NodeType)); + freemem(jointo,joinsize*sizeof(jointype)); + freemem(polys,polysize*sizeof(polygontype)); + freemem(twod,pointsize*sizeof(pointtype)); + freemem(zav,polysize*sizeof(real)); +end; + +procedure objtype_.multmatrix(mat:matrix3x4type); +var lop:word; +begin + if maxselect>0 then begin + for lop:=0 to maxselect-1 do + Thred^[select^[lop]].multmatrix(mat); + getmaxmin; + end; +end; + +procedure objtype_.do3d; +var lop:word; + {domat:matrix3x4type_;} +Begin + with obmat do begin + obmat.p.sub(obspos.x,obspos.y,obspos.z); + Currtmp:=pointer(tmpz); + inc(currtmp,draw_points_offset); + CurrNode:=pointer(thred); + inc(CurrNode,draw_points_offset); + currtwod:=pointer(twod); + inc(currtwod,draw_points_offset); + + For lop:=0 to maxpoints-1-draw_points_offset do begin + with CurrNode^ do begin + currtmp^:=(m02*x + m12*y + m22*z + p.z); + if currtmp^<=0 then currtmp^:=1; + {there is an error here} + currtwod^.x:=trunc((m00*x + m10*y + m20*z + p.x) /currtmp^ *pers)+xoffs; + currtwod^.y:=trunc((m01*x + m11*y + m21*z + p.y) /currtmp^ *pers)+yoffs; + end; + inc(CurrNode); + inc(currtmp); + inc(currtwod); + end; + obmat.p.add(obspos.x,obspos.y,obspos.z); + end; +end; + +Procedure objtype_.coloursort; +Procedure sort(l,r:integer); +var lop1,lop2:integer;lop3:integer; +Begin + lop1:=l; lop2:=r; lop3:=polys^[(l+r) shr 1].textureref; + repeat + while polys^[lop1].texturereflop2; + if llop2; + if l0 then begin + for lopb:=0 to numsides-1 do + zav^[lop]:=zav^[lop]+tmpz^[p[lopb]]; + zav^[lop]:=-(zav^[lop] / numsides); + end; + end; + sort(0,maxpolys-1); +end; + +procedure objtype_.filler(mode:byte); +Var +lop2,oldcol,testattrib,shademode,amask:byte;facetowards:boolean; +dx1,dy1,dx2,dy2:integer; +lop:word; +i:array[0..3]of byte; +pn:array[0..3] of pointtype; +Begin + if (maxpolys>0)then begin + depthsort; + oldcol:=t_fillcol; + currpoly:=pointer(polys); + case mode of + CMDLsource:begin amask:=byte(not PAsmooth);shademode:=0;end; + CMDgouraud:begin amask:=byte(not PAsmooth);shademode:=PAsmooth;end; + CMDhlines:begin amask:=255;shademode:=PAoutlined+PAconnected;end; + else begin amask:=255;shademode:=0;end; + end; + For lop:=0 to maxpolys-1 do with currpoly^,texturebank[textureref] do begin + for lop2:=0 to 3 do begin + pn[lop2].x:=twod^[p[lop2]].x; + pn[lop2].y:=twod^[p[lop2]].y; + end; + dx1:=pn[1].x-pn[0].x; + dy1:=pn[1].y-pn[0].y; + dx2:=pn[2].x-pn[0].x; + dy2:=pn[2].y-pn[0].y; + facetowards:=(pattrib and PaDoubleSided<>0) or((dx1 * dy2) > (dx2 * dy1)); + if (facetowards) then begin + testattrib:=(Pattrib and amask)or Shademode; + if numsides=2 then begin + t_col:=palref; + line(pn[0].x,pn[0].y,pn[1].x,pn[1].y); + end else if (testattrib and PaOutlined<>0) then begin + t_col:=palref; + {if not facetowards then setlinepattern(136,false);} + for lop2:=0 to numsides-2 do + line(pn[lop2].x,pn[lop2].y,pn[lop2+1].x,pn[lop2+1].y); + if testattrib and PaConnected<>0 then + line(pn[numsides-1].x,pn[numsides-1].y,pn[0].x,pn[0].y); + {setlinepattern(255,false);} + end else if testattrib and PaAbsolute<>0 then begin + t_fillcol:=palref; + triangle(pn[0].x,pn[0].y,pn[1].x,pn[1].y,pn[2].x,pn[2].y); + if numsides>3 then triangle(pn[0].x,pn[0].y,pn[3].x,pn[3].y,pn[2].x,pn[2].y); + end else if Testattrib and PaSmooth<>0 then begin + for lop2:=0 to numsides-1 do begin + i[lop2]:=palref+lop2{intensity(n,addval,colour,Pattrib)}; + end; + Gtriangle(pn[0].x,pn[0].y,pn[1].x,pn[1].y,pn[2].x,pn[2].y,i[0],i[1],i[2]); + if numsides>3 then Gtriangle(pn[0].x,pn[0].y,pn[3].x,pn[3].y,pn[2].x,pn[2].y,i[0],i[3],i[2]); + end else begin + t_fillcol:=palref; + triangle(pn[0].x,pn[0].y,pn[1].x,pn[1].y,pn[2].x,pn[2].y); + if numsides>3 then triangle(pn[0].x,pn[0].y,pn[3].x,pn[3].y,pn[2].x,pn[2].y); + end; + end; + inc(currpoly) + end; + t_fillcol:=oldcol; + end; +end; + +procedure objtype_.doorth(orientation:byte;xoff,yoff:integer;scale:real); +var lop,maxlimit:word; +begin + maxlimit:=maxpoints-1-draw_points_offset; + currtwod:=pointer(twod); + inc(currtwod,draw_points_offset); + CurrNode:=pointer(thred); + inc(CurrNode,draw_points_offset); + case orientation of + XY_view:For lop:=0 to maxlimit do with currtwod^ do begin + x:=round(CurrNode^.x*scale)+xoff; + y:=round(CurrNode^.y*scale)+yoff; + inc(currtwod); + inc(CurrNode); + end; + ZY_view:For lop:=0 to maxlimit do with currtwod^ do begin + x:=round(CurrNode^.z*scale)+xoff; + y:=round(CurrNode^.y*scale)+yoff; + inc(currtwod); + inc(CurrNode); + end; + XZ_view:For lop:=0 to maxlimit do with currtwod^ do begin + x:=round(CurrNode^.x*scale)+xoff; + y:=round(CurrNode^.z*scale)+yoff; + inc(currtwod); + inc(CurrNode); + end; + end; +end; + +procedure objtype_.liner; +var lop:word; +Begin + if draw_lines_offset0 then + For lop:=0 to maxselect-1 do begin + with twod^[select^[lop]] do drawbytes(x-3,y-2,@nodepatt,5); + end; +end; + +Procedure objtype_.Getmaxmin; +var lop:word; + tmpmat:matrix3x4type; + oldmin,oldmax:VectorReal; +const + big=6400000; + +Begin + if maxselect>0 then Begin + oldmin:=min; oldmax:=max; + min.moveto(big,big,big); + max.moveto(-big,-big,-big); + For lop:=0 to maxselect-1 do Begin + if thred^[select^[lop]].x>max.x then max.x:=thred^[select^[lop]].x; + if thred^[select^[lop]].y>max.y then max.y:=thred^[select^[lop]].y; + if thred^[select^[lop]].z>max.z then max.z:=thred^[select^[lop]].z; + if thred^[select^[lop]].xnode) and (sublopERRnone then exit; + + for lop:=0 to maxselect-1 do + copypoint(select^[lop]); + oldmax:=maxjoins; + if (copymode and CMjoins<>0)and(maxjoins>0) then + for lop:=0 to oldmax-1 do with jointo^[lop] do + if (thred^[f].Nattrib and Naselected<>0) and (thred^[t].Nattrib and Naselected<>0) then begin + {fgtexture:=colour;} + addjoin(getspos(f),getspos(t)); + end; + if errorlevel>ERRnone then exit; + oldmax:=maxpolys; + if (copymode and CMpolys<>0)and(maxpolys>0) then begin + oldtexture:=fgtexture; + for lop:=0 to oldmax-1 do with polys^[lop] do + if allselected(thred) then begin + fgtexture:=textureref; + case numsides of + 2:addline(getspos(p[1]),getspos(p[0]),pattrib and PAsetmask3d); + 3:addtriangle(getspos(p[2]),getspos(p[1]),getspos(p[0]),pattrib and PAsetmask3d); + 4:addquad(getspos(p[3]),getspos(p[2]),getspos(p[1]),getspos(p[0]),pattrib and PAsetmask3d); + end; + end; + fgtexture:=oldtexture; + end; + {select new points} + if reselect then + for lop:=0 to maxselect-1 do begin + with thred^[select^[lop]] do Nattrib:=Nattrib and not NaSelected; + select^[lop]:=oldmaxp+lop; + with thred^[oldmaxp+lop] do Nattrib:=Nattrib or NaSelected; + end; + calcselectedpolys; + end; +end; + +{splits a lines and any related faces} +Procedure edit_objtype_.splitline(line:word); +var + +newvec:vectorreal; +count:integer; +lop:byte; +join:joinptr; +begin + join:=@jointo^[line]; + newvec:=thred^[join^.f]; + with thred^[join^.t] do + newvec.add(x,y,z); + newvec.divide(2); + + addvector(newvec.x,newvec.y,newvec.z); + addjoin(join^.f,maxpoints-1); + addjoin(maxpoints-1,join^.t); + count:=maxpolys-1; + while (count>=0) do begin + if jointo^[line].insidepoly(polys^[count]) then with polys^[count] do begin + lop:=0; + while (p[lop]<>join^.f)or(p[lop]<>join^.t) do + inc(lop); + {split up faces here! do it tomorrow} + count:=maxpolys; + end; + dec(count); + end; + + +end; + + +Procedure edit_objtype_.quaddivideselected; +Var lop,lop2,sublop:word; + pointlop:byte; + new:vectorreal; + oldtexture:byte; +begin + if (maxpolys>0) then begin + CTM:=@unitmatrix; + for lop:=0 to maxpolys-1 do with polys^[lop] do + if (allselected(thred))and(numsides>2) then begin + oldtexture:=fgtexture; + fgtexture:=textureref; + if (numsides=4) then begin + lop2:=0; + while (lop2=0) do begin {delete affected lines} + if jointo^[lop2].insidepoly(polys^[lop]) then + deletejoin(lop2) + else + inc(lop2); + end; + new.moveto(0,0,0); + for pointlop:=0 to 3 do with thred^[p[pointlop]] do + new.add(x,y,z); + new.divide(4); + with new do begin + {sub(x,y,z);} + addvector(x,y,z); + end; + + for pointlop:=0 to 2 do begin + new:=thred^[p[pointlop]]; + with thred^[p[pointlop+1]] do + new.add(x,y,z); + new.divide(2); + with new do + addvector(x,y,z); + end; + new:=thred^[p[3]]; + with thred^[p[0]] do + new.add(x,y,z); + new.divide(2); + with new do + addvector(x,y,z); + addjoincheck(maxpoints-1,maxpoints-5); + addjoincheck(maxpoints-5,maxpoints-3); + addjoincheck(maxpoints-4,maxpoints-5); + addjoincheck(maxpoints-5,maxpoints-2); + + + addjoincheck(p[0],maxpoints-4); + addjoincheck(maxpoints-4,p[1]); + addjoincheck(p[1],maxpoints-3); + addjoincheck(maxpoints-3,p[2]); + addjoincheck(p[2],maxpoints-2); + addjoincheck(maxpoints-2,p[3]); + addjoincheck(p[3],maxpoints-1); + addjoincheck(maxpoints-1,p[0]); + + addquad(maxpoints-4,p[1],maxpoints-3,maxpoints-5,pattrib or PaClockWise); + addquad(maxpoints-5,maxpoints-3,p[2],maxpoints-2,pattrib or PaClockWise); + addquad(maxpoints-1,maxpoints-5,maxpoints-2,p[3],pattrib or PaClockWise); + p[1]:=maxpoints-4; + p[2]:=maxpoints-5; + p[3]:=maxpoints-1; + end; + fgtexture:=oldtexture; + end; + end + else ErrorLevel:=ERRnotselected; +end; + +procedure edit_objtype_.TriangulatePoly(polyref:word;from_p:byte); +var oldtexture:byte; + to_p:byte; +begin + with polys^[polyref] do begin + oldtexture:=fgtexture; + fgtexture:=textureref; + if (numsides>3) then begin + to_p:=(from_p +2) mod numsides; + from_p:=from_p mod numsides; + addjoincheck(p[from_p],p[to_p]); + addtriangle(p[from_p],p[(from_p+1)mod numsides],p[to_p],pattrib or PaClockWise or Paallselected); + + numsides:=3; + p[0]:=from_p; + p[1]:=to_p; + p[2]:=(to_p +1 ) and 3; + + + fgtexture:=oldtexture; + end; + end; +end; + +procedure edit_objtype_.splitpolygons; +var lop:word; + selected:byte; +begin + if (maxpolys>0)and(maxselect>0)and(maxselect<3) then begin + for lop:=0 to maxpolys do with polys^[lop] do if numsides=4 then begin + + selected:=GetFirstSelected(thred); + if selected<>255 then begin + {if thred^[p[selected+2]].nattrib and NAselected<>0 then begin} + triangulatepoly(lop,selected); + {end;} + end else begin + {sound(100);delay(10);nosound;} + end; + + end; + + end else + ErrorLevel:=ERRnotselected; +end; + +Procedure edit_objtype_.Triangulateselected; +Var lop:word; + oldtexture:byte; +begin + if maxpolys>0 then begin + CTM:=@unitmatrix; + for lop:=0 to maxpolys-1 do with polys^[lop] do + if (allselected(thred))and(numsides=4) then begin + oldtexture:=fgtexture; + fgtexture:=textureref; + addjoincheck(p[1],p[3]); + addtriangle(p[1],p[2],p[3],pattrib or PaClockWise or Paallselected); + + numsides:=3; + p[2]:=p[3]; + p[3]:=0; + fgtexture:=oldtexture; + end; + end else + ErrorLevel:=ERRnotselected; +end; + +Procedure edit_objtype_.connectbyref(p1:word;list:wordarray;count:word;attrib:byte); +Var lop:word; + pf,pt:word; + +function getspos(node:word;var pos:word):boolean; +var + found:boolean; +begin + pos:=0; + found:=false; + while (not found) and (posx-border) and (xpsy-border) and + (((getselected) and (thred^[lop].Nattrib and NaSelected<>0))or not getselected) then ans:=lop; + inc(lop); +End; +getnode:=ans; +End;{of function} + +Procedure edit_objtype_.addvector(xa,ya,za:real); +begin + if maxpointsyb then begin fswap(ya,yb,2);fswap(xa,xb,2);end; + intersect:=(y>=ya)and(y<=yb)and((x>=xa)or(x>=xb)); +end; + + + + +begin + if mode and PClines<>0 then begin + for lop:=0 to count-2 do + if mode and PCchecklines<>0 then + addjoincheck(startp+lop,startp+lop+1) + else + addjoin(startp+lop,startp+lop+1); + if attrib_ and PaConnected<>0 then + if mode and PCchecklines<>0 then + addjoincheck(startp+count-1,startp) + else + addjoin(startp+count-1,startp); + end; + if mode and PCpolys<>0 then + if count=2 then + addline(startp,startp+1,attrib_) + else begin + if count>3 then begin + for lop:=0 to (count shr 1)-2 do + addquad(startp+lop,startp+lop+1,startp+count-lop-2,startp+count-lop-1,attrib_); + inc(lop); + end else + lop:=0; + inc(lop,startp); + if (count mod 2)=1 then + addtriangle(lop,lop+1,lop+2,attrib_); + end; +end; + +procedure edit_objtype_.AddPolygonByRef(startp:wordarray;count:word;attrib_:byte;mode:word); +var lop:word; +begin + if mode and PClines<>0 then begin + for lop:=0 to count-2 do + if mode and PCchecklines<>0 then + addjoincheck(startp^[lop],startp^[lop+1]) + else + addjoin(startp^[lop],startp^[lop+1]); + + if attrib_ and PaConnected<>0 then + if mode and PCchecklines<>0 then + addjoincheck(startp^[count-1],startp^[0]) + else + addjoin(startp^[count-1],startp^[0]) + end; + if mode and PCpolys<>0 then begin + if count=2 then + addline(startp^[count-1],startp^[count-2],attrib_) + else begin + if count>3 then begin + for lop:=0 to (count shr 1)-2 do begin + addquad(startp^[lop],startp^[1+lop],startp^[count-lop-2],startp^[count-lop-1],attrib_); + {with polys^[maxpolys-1] do + if allselected(@thred) then pattrib:=pattrib or PAallselected; } + end; + inc(lop); + end else + lop:=0; + if (count mod 2)=1 then begin + addtriangle(startp^[lop],startp^[lop+1],startp^[lop+2],attrib_); + {with polys^[maxpolys-1] do + if allselected(@thred) then pattrib:=pattrib or PAallselected;} + end; + end; + calcselectedpolys; + + end; +end; + + + +Procedure edit_objtype_.addquad(p1,p2,p3,p4:word;attrib_:word); +Begin + if maxpolys0) then begin + p[0]:=p1;p[1]:=p2; + p[2]:=p3;p[3]:=p4; + end else begin + p[3]:=p1;p[2]:=p2; + p[1]:=p3;p[0]:=p4; + end; + if not anyduplicates then + inc(maxpolys); + End + Else + ErrorLevel:=ERRnopolys; +End; + + +Procedure edit_objtype_.addtriangle(p1,p2,p3:word;attrib_:word); +Begin + if maxpolys0)) then begin + p[0]:=p1;p[1]:=p2;p[2]:=p3; + end else begin + p[0]:=p3;p[1]:=p2;p[2]:=p1; + end; + if not anyduplicates then + inc(maxpolys); + End + Else + ErrorLevel:=ERRnopolys; +End; + +Procedure edit_objtype_.addline(p1,p2:word;attrib_:word); +Begin + if maxpolys0 then begin + for lop:=0 to maxpolys-1 do with polys^[lop] do begin + nselected:=numsides; + for nlop:=0 to numsides-1 do begin + if thred^[p[nlop]].nattrib and NAselected<>0 then + dec(nselected); + end; + pattrib:=pattrib and (not PAallselected+PAsomeselected); + if nselected=0 then + pattrib:=pattrib or PAallselected + else if nselectednil do begin + selectpoly(elem^.data); + elem:=elem^.next; + end; + elem:=list^.first; + while elem<>nil do begin + GetNextPoly(@polys^[elem^.data]); + elem:=elem^.next; + end; + dispose(list,done); +end; + +var lop,nlop:word; + polyref:integer; +begin + polyref:=-1; + lop:=0; + while (polyref=-1)and (lop-1 then begin + GetNextPoly(@polys^[polyref]); + end; +end; + +Function edit_objtype_.getselectlistconnected(id:byte;R:trect):boolean; +var +lop:word; +noderef:integer; +chkpoint:pointtype; +Begin + if maxpoints>0 then with R do begin + lop:=0; + clearselection; + while (lop=x1) and (x<=x2) and (y>=y1) and (y<=y2) then + selectconnected(lop); + end; + inc(lop); + end; + getmaxmin; + end; +End;{of procedure} + +function close_to(x,y,xm,ym,howclose:integer):boolean; +begin + close_to:=(xm>=x-howclose)and(ym>=y-howclose)and + (xm<=x+howclose)and(ym<=y+howclose); +end; + + + + +Function edit_objtype_.getselectlist(id:byte;R:trect;selmode:byte):boolean; +var lop,cnt:word; +chkpoint:pointtype; + +Begin + if maxpoints>0 then with R do begin + {freemem(select,maxselect);} + + with chkpoint do + case selmode of + SMintersect:if (maxselect>0) then + for lop:=0 to maxpoints-1 do begin + conv3d_2d(id,@thred^[lop],x,y); + if not(r.contains(x,y)) then + with thred^[lop] do Nattrib:=Nattrib and not NaSelected; + end; + SMcutfromlist:if (maxselect>0) then + for lop:=0 to maxpoints-1 do begin + conv3d_2d(id,@thred^[lop],x,y); + if (r.contains(x,y)) then + with thred^[lop] do Nattrib:=Nattrib and not NaSelected; + + end; + SMnewlist: + for lop:=0 to maxpoints-1 do begin + conv3d_2d(id,@thred^[lop],x,y); + if (r.contains(x,y)) then + with thred^[lop] do Nattrib:=Nattrib or NaSelected + else + with thred^[lop] do Nattrib:=Nattrib and not NaSelected; + end; + + SMaddtolist: + for lop:=0 to maxpoints-1 do begin + conv3d_2d(id,@thred^[lop],x,y); + if (r.contains(x,y)) then + with thred^[lop] do Nattrib:=Nattrib or NaSelected; + end; + end; + {find out how many are selected} + maxselect:=0; + for lop:=0 to maxpoints-1 do begin + with thred^[lop] do + if Nattrib and NAselected<>0 then inc(maxselect); + end; + {GetMem(select,maxselect);} + cnt:=0; + for lop:=0 to maxpoints-1 do begin + with thred^[lop] do + if Nattrib and NAselected<>0 then begin + select^[cnt]:=lop; + inc(cnt); + end; + end; + getmaxmin; + + calcselectedpolys; + end; + +End;{of procedure} + +procedure edit_objtype_.selectpoly(polyref:word); +var lop:byte; +begin + + with polys^[polyref] do begin + for lop:=0 to numsides-1 do + selectnode(p[lop]); + Pattrib:=Pattrib or PAallselected; + end; +end; + +procedure edit_objtype_.selectnode(noderef:word); +begin + if thred^[noderef].nattrib and NAselected=0 then begin + thred^[noderef].Nattrib:=thred^[noderef].Nattrib or NAselected; + select^[maxselect]:=noderef; + inc(maxselect); + end; +end; + +procedure edit_objtype_.clearselection; +var lop:word; +begin + if maxselect>0 then begin + for lop:=0 to maxselect-1 do + with thred^[Select^[lop]] do Nattrib:=Nattrib and not NaSelected; + maxselect:=0; + for lop:=0 to maxpolys do with polys^[lop] do begin + Pattrib:=Pattrib and (not PAselected); + end; + end; +end; + +Procedure edit_objtype_.FlipSelectedNormals; +var lop:word; +begin + if maxselect>0 then begin + if maxjoins>0 then + for lop:=0 to maxjoins-1 do with jointo^[lop] do + if allselected(thred) then reverse; + if maxpolys>0 then + for lop:=0 to maxpolys-1 do with polys^[lop] do + if allselected(thred) then reverse; + end else + ErrorLevel:=ERRnotselected; +end; + +Procedure edit_objtype_.SetSelectedTexture(textureref_:byte); +var lop:word; +begin + if maxselect>0 then begin + if maxpolys>0 then + for lop:=0 to maxpolys-1 do with polys^[lop] do + if allselected(thred) then + textureref:=textureref_; + end else + ErrorLevel:=ERRnotselected; + {if maxjoins>0 then + for lop:=0 to maxjoins-1 do with jointo^[lop] do + if (thred^[f].selected) and (thred^[t].selected) then colour:=col;} +end; + +Procedure edit_objtype_.SetSelectedAttrib(attrib_: word; mode: byte); +var lop:word; +begin + if maxselect>0 then begin + if maxpolys>0 then + for lop:=0 to maxpolys-1 do with polys^[lop] do + if allselected(thred) then SetAttrib(attrib_,mode); + end else + ErrorLevel:=ERRnotselected; +end; + +procedure edit_objtype_.selectall; +var lop:word; +begin + if maxpoints>0 then begin + maxselect:=maxpoints; + for lop:=0 to maxselect-1 do begin + select^[lop]:=lop; + with thred^[lop] do Nattrib:=Nattrib or Naselected; + end; + getmaxmin; + calcselectedpolys; + end; +end; + +Procedure edit_objtype_.flip(direction:byte); +var lop:word; +begin + if maxselect>0 then begin + for lop:=0 to maxselect-1 do with thred^[select^[lop]] do + case direction of + Xaxis:x:=(max.x+min.x)-x; + Yaxis:y:=(max.y+min.y)-y; + Zaxis:z:=(max.z+min.z)-z; + end; + FlipSelectedNormals; + end else + ErrorLevel:=ERRnotselected; +End; + +{procedure edit_objtype_.deleteduplicatereferences(var i:word); +var i,ib,numdups:byte; +var p:^polygontype; +begin + p=&polys[i]; + numdups:=0; + if (p^.numsides<3) then begin deletepoly(i);exit;end; + for i:=0 to p.numsides-1 do + for ib:=i+1 to p.numsides-1 do + if (p.p[ib]=p.p[i]) then inc(numdups); + if (numdups>1) deletepoly(i);exit;end; + +end;} + +function edit_objtype_.counttriangles:integer; +var i,count:word; +begin + count:=0; + if (maxpolys>0) then + for i:=0 to maxpolys-1 do with polys^[i] do begin + if (numsides=4) then + inc(count,2) + else + inc(count); + end; + counttriangles:=count; +end; + +procedure edit_objtype_.merge; +function joinexists(j1,j2:word):boolean; +var lop:word; +begin + joinexists:=false; + if j1<>j2 then + for lop:=0 to maxjoins-1 do with jointo^[lop] do + if (j1+j2)=(f+t) then begin + joinexists:=true; + exit; + end; +end; + +var lop,mergeto:word;lopb:byte; + +begin + if maxselect>1 then begin + with thred^[select^[0]] do Nattrib:=Nattrib and not NaSelected; + mergeto:=select^[0]; + if maxjoins>0 then + for lop:=0 to maxjoins-1 do with jointo^[lop] do begin + {if not joinexists(f,mergeto) then} + if thred^[f].Nattrib and NaSelected<>0 then f:=mergeto; + {if not joinexists(t,mergeto) then} + if thred^[t].Nattrib and NaSelected<>0 then t:=mergeto; + end; + if maxpolys>0 then + + for lop:=0 to maxpolys-1 do with polys^[lop] do begin + + for lopb:=0 to numsides-1 do begin + if thred^[p[lopb]].Nattrib and NaSelected<>0 then begin + if (setpolyvertex(lopb,mergeto)=PVdeleted) then break; + end; + end; + if (numsides<3) then + deletepoly(lop); + end; + + + dec(maxselect); + for lop:=0 to maxselect-1 do + select^[lop]:=select^[lop+1]; + calcselectedpolys; + delete_select(DMall); + maxselect:=0; + getmaxmin; + calcselectedpolys; + end else + ErrorLevel:=ERRoneselected; +end; + +procedure edit_objtype_.delete_select(whattodel:byte); +var lop,selectlop,sublop,joinlop,index:integer; + oldsel:integer; + delpoly,DelNode:boolean; + +begin + if maxselect>0 then begin + + DelNode:=WhatToDel and DMnodes<>0; + if whatToDel and DMjoins<>0 then begin + index:=0; + lop:=maxjoins; + while (lop>0) do begin + if ((delnode) and (jointo^[index].anyselected(thred))) + or((Not DelNode) and (jointo^[index].allselected(thred))) then begin + deletejoin(index); + end else + inc(index); + dec(lop); + end; + end; + + if whatToDel and DMpolys<>0 then begin + index:=0; + lop:=maxpolys; + while (lop>0) do begin + if ((delnode) and (polys^[index].anyselected(thred))) + or((Not DelNode) and (polys^[index].allselected(thred))) then begin + deletepoly(index); + end else + inc(index); + dec(lop); + end; + end; + + lop:=0; + if DelNode then + while (lop0) do begin + if thred^[lop].Nattrib and NaSelected<>0 then begin + for joinlop:=0 to maxjoins do begin + if jointo^[joinlop].t>lop then dec(jointo^[joinlop].t); + if jointo^[joinlop].f>lop then dec(jointo^[joinlop].f); + end; + for joinlop:=0 to maxpolys do + for sublop:=0 to 3 do + if polys^[joinlop].p[sublop]>lop then dec(polys^[joinlop].p[sublop]); + for sublop:=lop to maxpoints-2 do begin + thred^[sublop]:=thred^[sublop+1]; + end; + dec(maxpoints); + end else + inc(lop); + end; + if delnode then maxselect:=0; + end else + ErrorLevel:=ERRnotselected; +end; + +procedure edit_objtype_.deletejoin(lineno:word); +begin + if (lineno=0) then begin + move(jointo^[lineno+1],jointo^[lineno],(maxjoins-lineno-1)*sizeof(jointype)); + dec(maxjoins); + end; +end; + +procedure edit_objtype_.deletepoly(polyno:word); +begin + if polyno0)and(lopz1 then + polydir:=0 + else + polydir:=PaClockWise; + mksquare(x1,y1,x2,y2,z1,attrib_ xor polydir); + polydir:=polydir xor PaClockWise; + mksquare(x1,y1,x2,y2,z2,attrib_ xor polydir); + connect(maxpoints-8,maxpoints-4,4,attrib_ xor PolyDir,true); + +end; + +procedure edit_objtype_.mkcylinder(cx,cy,rx1,ry1,rx2,ry2,z1,z2:real;stp:word;startangle:real;attrib_:byte); +var polydir:byte; +begin + attrib_:=attrib_ and PAsetmask3d; + {get the right orientation for the surfaces} + if z2>z1 then + polydir:=0 + else + polydir:=PaClockwise; + mkcircle(cx,cy,rx1,ry1,z1,stp,startangle,PCall,attrib_ xor polydir); + polydir:=polydir xor PaClockWise; + mkcircle(cx,cy,rx2,ry2,z2,stp,startangle,PCall,attrib_ xor polydir); + connect(maxpoints-(stp shl 1),maxpoints-stp,stp,attrib_ xor polydir,true); +end; + +Procedure edit_objtype_.rotateobj(axis:byte;stp,attrib:byte); +Var sellop,lop,oldmax:word; + rotby:real; + tmpmat:matrix3x4type_; +Begin + if maxselect>0 then begin + CTM:=@tmpmat; + rotby:=0; + oldmax:=maxpoints; + for lop:=0 to stp-1 do begin + rotby:=(lop*maxrotate)/stp; + Case axis of + Xaxis:LmRotate(@tmpmat,rotby,0,0); + Yaxis:LmRotate(@tmpmat,0,rotby,0); + Zaxis:LmRotate(@tmpmat,0,0,rotby); + end; + addpolygon(maxpoints,maxselect,attrib,PClines); + if (lop0)and(path^.maxjoins>0) then begin + with path^ do + connectup:=true{jointo^[maxjoins-1].t=0}; + middle:=max; + middle.sub(min.x,min.y,min.z); + middle.divide(2); + middle.add(min.x,min.y,min.z); + with middle do + LMtrans(@tmpmat,-x,-y,-z); + multmatrix(@tmpmat); + oldmaxpnts:=maxpoints; + CTM:=@tmpmat; + for lop:=0 to path^.maxpoints-1 do begin + with path^.thred^[lop] do + LMtrans(@tmpmat,x,y,z); + + rotby:=(lop*maxrotate) / (path^.maxpoints); + + {to be replaced by an angle finding routine} + Case edit_orientation of + Xaxis:LmRotate(@tmpmatb,-rotby,0,0); + Yaxis:LmRotate(@tmpmatb,0,-rotby,0); + Zaxis:LmRotate(@tmpmatb,0,0,-rotby); + end; + tmpmat.multiply(@tmpmatb,mtpostconcat); + + if extrude then begin + copyobj(CMjoins,false,false); + if lop0) then + fgtexture:=fgtexture xor Xorby; + end; + currjoin:=maxpoints; + For ylop:=0 to ystp do begin + For xlop:=0 to xstp do begin + if xlop0 then begin + for lop:=0 to maxp-1 do with tmpvec do begin + system.read(f,x); + system.read(f,y); + system.readln(f,z); + addvector(x,y,-z); + end; + maxjoins:=0; + readln(f,maxp); + if maxp>0 then begin + for lop:=0 to maxp-1 do begin + system.read(f,fgtexture); + system.read(f,nsides); + for lopb:=0 to nsides-1 do begin + system.read(f,pref[lopb]); + dec(pref[lopb]); + end; + addpolygonByRef(@pref,nsides,0,PCall); + end; + end; + end; + close(f); +end; + +procedure gettoken(var buf:bufferedblock;data:pointer;datatype:byte); +const + records:word=1; +var + token:tokenstring; + tptr:char; +begin + token:=''; + tptr:=char(buf.bufferpos^); + while(not buf.eof)and((tptr=whitespace)or(tptr=#13)or(tptr=#10)or(tptr=#9)) do + tptr:=char(buf.get); + {strip comments} + if tptr='#' then begin + while (not buf.eof)and(tptr<>#13) do + tptr:=char(buf.get); + gettoken(buf,data,datatype); + end else begin + while (not buf.eof)and(tptr<>whitespace)and(tptr<>#13)and(tptr<>#10)and(tptr<>#9) do begin + token:=token+upcase(tptr); + tptr:=char(buf.get); + end; + case datatype of + DTstring:stringptr(data)^:=token; + DTint:integerptr(data)^:=atoi(token); + DTreal:realptr(data)^:=atof(token); + end; + end; +end; + +procedure edit_objtype_.writeOBJ(filename:string); +var f:text; + lop:word; + lopb:byte; +begin + assign(f,filename); + rewrite(f); + writeln(f,filename); + writeln(f,maxpoints); + if maxpoints>0 then begin + for lop:=0 to maxpoints-1 do with thred^[lop] do begin + system.write(f,x:3:5,' '); + system.write(f,y:3:5,' '); + system.write(f,-z:3:5); + writeln(f,''); + end; + writeln(f,maxpolys); + if maxpolys>0 then begin + for lop:=0 to maxpolys-1 do with polys^[lop] do begin + system.write(f,'1 '); + system.write(f,numsides); + for lopb:=numsides-1 downto 0 do begin + system.write(f,' ',p[lopb]+1); + end; + writeln(f,''); + end; + end; + end; + close(f); +end; + +procedure edit_objtype_.readGEO(filename:string); +var f:text; + lop,val:word; + lopb:byte; + dummy:string; + tmpvec:VectorReal; + maxn,maxp:word; + pref:array[0..30] of word; + nsides:byte; +begin + Assign(F, filename); + name:=filename; + + Reset(F); + read(f,maxn); + t_col:=15; + if maxn>0 then begin + readln(f,maxp); + maxpoints:=0; + maxjoins:=0; + maxpolys:=0; + for lop:=0 to maxn-1 do with tmpvec do begin + system.read(f,x); + system.read(f,y); + system.readln(f,z); + addvector(x{*50},y{*50},-z{*50}); + end; + if maxp>0 then begin + for lop:=0 to maxp-1 do begin + system.read(f,nsides); + for lopb:=0 to nsides-1 do begin + system.read(f,pref[lopb]); + dec(pref[lopb]); + end; + addpolygonByRef(@pref,nsides,0,PCall); + end; + end; + end; + close(f); +end; + +procedure edit_objtype_.writeGEO(filename:string); +var f:text; + lop:word; + lopb:byte; +begin + assign(f,filename); + rewrite(f); + writeln(f,maxpoints,' ',maxpolys); + if maxpoints>0 then begin + for lop:=0 to maxpoints-1 do with thred^[lop] do begin + write(f,x:3:5,' '); + write(f,y:3:5,' '); + writeln(f,-z:3:5); + end; + if maxpolys>0 then begin + for lop:=0 to maxpolys-1 do with polys^[lop] do begin + system.write(f,numsides); + for lopb:=numsides-1 downto 0 do + system.write(f,' ',p[lopb]+1); + writeln(f,''); + end; + end; + end; + close(f); +end; + +procedure edit_objtype_.readVTek(filename:string); +var lop,recsize:word; + f:file; +begin + assign(f,filename); + name:=filename; + recsize:=1; + maxpoints:=filesize(f) div sizeof(vectorint); + maxjoins:=0; + maxpolys:=0; + for lop:=0 to maxpoints-1 do begin + blockread(f,thred^[lop],sizeof(vectorint),recsize); + end; + close(f); +end; + +procedure edit_objtype_.writegor(filename:string); +var +f:text; +i:word; +pi:byte; +p:polygonptr; +v:vectorrealptr; +begin + assign(f,filename); + rewrite(f); + writeln(f,maxpolys); + for i:=0 to maxpolys-1 do begin + p:=@polys^[i]; + writeln(f,''); + writeln(f,p^.textureref*16); + for pi:=0 to p^.numsides-1 do begin + v:=@thred^[p^.p[pi]]; + + writeln(f,round(v^.x*scale),' ',round(-v^.y*scale),' ',round(v^.z*scale)); + end; + if (p^.numsides=3) then + writeln(f,round(v^.x*scale),' ',round(-v^.y*scale),' ',round(v^.z*scale)); + + end; + close(f); + +end; + +procedure edit_objtype_.readgor(filename:string;append:boolean); +var +f:text; +numquads:word; +i:word; +pi:byte; +xp,yp,zp:integer; +begin + name:=filename; + assign(f,filename); + + Reset(f); + + if (not append) then begin + maxpoints:=0; + maxjoins:=0; + maxpolys:=0; + end; + readln(f,numquads); + t_col:=15; + for i:=1 to numquads do begin + readln(f,fgtexture); + fgtexture :=fgtexture div 16;{and 15;} + AddQuad(maxpoints,maxpoints+1,maxpoints+2,maxpoints+3,PAclockwise+PAdoublesided); + AddJoin(maxpoints,maxpoints+1); + AddJoin(maxpoints+1,maxpoints+2); + AddJoin(maxpoints+2,maxpoints+3); + AddJoin(maxpoints+3,maxpoints); + + for pi:=0 to 3 do begin + read(f,xp);read(f,yp);readln(f,zp); + AddVector(xp/scale,-yp/scale,zp/scale); + end; + + end; + close(f); + +end; + +function mottointel_int16(val:integer):integer; +begin +end; + +function mottointel_int32(val:longint):longint; +begin +end; +{ +procedure edit_objtype_.readlw(filename:string;append:boolean); +var f:file; +recsize:integer; +begin + recsize:=1; + name:=filename; + assign(f,filename); + Reset(f,recsize); + + +end; + } +procedure edit_objtype_.read3d(filename:string;append:boolean); +Var maxs:array[0..2] of word; + tmppoly:PolygonStruct; + tmpjoin:joinstruct; + tmpvector:VectorStruct; + recsize,addpnts:word; + lop:word; + ypos:integer; + f:file; +Begin + recsize:=1; + name:=filename; + assign(f,filename); + Reset(f,recsize); + + blockread(f,maxs,sizeof(maxs),recsize); + if append then begin + addpnts:=maxpoints; + end else begin + addpnts:=0; + reset3d; + end; + + if objectsize(maxs[0],maxs[1],maxs[2])<>filesize(f) then begin + maxpoints:=0;maxjoins:=0;maxpolys:=0; + ErrorLevel:=ERRfileerror; + close(f); + exit; + end; + + t_col:=15; + if maxs[0]>0 then + for lop:=0 to maxs[0]-1 do with tmpvector do begin + blockread(f,tmpvector,sizeof(VectorStruct)); + addvector(x,y,z); + thred^[maxpoints-1].divide(loadscale); + end; + + + fgtexture:=11; + if maxs[1]>0 then + for lop:=0 to maxs[1]-1 do begin + blockread(f,tmpjoin,sizeof(joinstruct),recsize); + addjoin(tmpjoin.f+addpnts,tmpjoin.t+addpnts); + end; + + if maxs[2]>0 then + for lop:=0 to Maxs[2]-1 do begin + blockread(f,TmpPoly,sizeof(polygonstruct),recsize); + with TmpPoly do begin + fgtexture:=colour; + case numsides of + 2:Addline(p[0]+addpnts,p[1]+addpnts,attrib or PaClockwise); + 3:AddTriangle(p[0]+addpnts,p[1]+addpnts,p[2]+addpnts,attrib or PaClockwise); + 4:AddQuad(p[0]+addpnts,p[1]+addpnts,p[2]+addpnts,p[3]+addpnts,attrib or PAclockwise); + end; + end; + end; + close(f); +end; + +procedure edit_objtype_.write3d(filename:string); +Var maxs:array[0..2] of word;recsize:word; + tmppoly:polygonstruct; + lop:word; + tmpvec:VectorStruct; + f:file; +Begin + recsize:=1; + assign(f,filename); + Rewrite(f,1); + maxs[0]:=maxpoints;maxs[1]:=maxjoins;maxs[2]:=maxpolys; + blockwrite(f,maxs,sizeof(maxs)); + if maxpoints>0 then begin + CurrNode:=pointer(thred); + for lop:=0 to maxpoints-1 do with tmpvec do begin + x:=CurrNode^.x;y:=CurrNode^.y;z:=CurrNode^.z; + {thred^[maxpoints-1].multiply(loadscale);} + blockwrite(f,tmpvec,sizeof(VectorStruct),recsize); + inc(CurrNode); + end; + if maxjoins>0 then + for lop:=0 to maxjoins-1 do + blockwrite(f,jointo^[lop],4); + if maxpolys>0 then begin + Currpoly:=pointer(polys); + for lop:=0 to maxpolys-1 do with tmppoly do begin + numsides:=currpoly^.numsides; + attrib:=currpoly^.pattrib; + colour:=currpoly^.textureref; + move(currpoly^.p,p,8); + blockwrite(f,TmpPoly,sizeof(polygonstruct),recsize); + inc(currpoly); + end; + end; + end; + close(f); +end; + +procedure edit_objtype_.writeSG(filename:string); +Var dummy:string;tmp_lop,lop2:word;f:text; +Begin + Assign(f,filename); + Rewrite(f); + writeln(f,maxpoints-1); + writeln(f,maxpolys-1); + writeln(f,filename); + For tmp_lop:= 0 to maxpoints-1 do Begin + writeln(f,thred^[tmp_lop].x :1:4); + writeln(f,thred^[tmp_lop].y :1:4); + writeln(f,thred^[tmp_lop].z :1:4); + end; + if maxpolys>0 then begin + For tmp_lop:= 0 to maxpolys-1 do Begin + Writeln(f,4); + writeln(f,polys^[tmp_lop].textureref); + For lop2:=0 to 3 do + Writeln(f,polys^[tmp_lop].p[lop2]); + end; + close(f); + end; +end; +{writes some java code for use in my java3d engine} + +procedure edit_objtype_.writejava(filename:string); +const +loadscale=20; + + +Var i:integer; +pal:array[0..255]of realrgb; + oldcol:byte; + c:rgbtype; + f:text; +Begin + coloursort; + Assign(f,filename); + Rewrite(f); + oldcol:=0; + + for i:=0 to 255 do begin + getrgb(i,c.r,c.g,c.b); + pal[i].r:=c.r /64.0; + pal[i].g:=c.g /64.0; + pal[i].b:=c.b /64.0; + end; + + + writeln(f,'super(',maxpoints,',',counttriangles,');'); + if (maxpoints<0) then exit; + for i:=0 to maxpoints-1 do with thred^[i] do + writeln(f,'addvertex(',x:2:4,'f,',y:2:4,'f,',z:2:4,'f);'); + for i:=0 to maxpolys-1 do with polys^[i] do begin + if (textureref<>oldcol) then + writeln(f,'cred=',pal[textureref].r:2:4,'f;cgreen=', + pal[textureref].g:2:4,'f;cblue=', + pal[textureref].b:2:4,'f;'); + + if (numsides=4) then + writeln(f,'addquad(',Pattrib and PAdoublesided,',points[',p[0],'],points[',p[1],'],points[',p[2],'],points[',p[3],']);') + else + writeln(f,'addtriangle(',Pattrib and PAdoublesided,',points[',p[0],'],points[',p[1],'],points[',p[2],']);'); + oldcol:=textureref; + end; + close(f); +end; + + +procedure edit_objtype_.writeVRML(filename:string); +const +loadscale=20; +Var lop,lop2:word;f:text; + r1,g1,b1,oldtexture:byte; + pal:array[0..255]of realrgb; + c:rgbtype; + +Begin + Assign(f,filename); + Rewrite(f); + writeln(f,'#VRML V1.0 ascii'); + + writeln(f,'Separator{'); + writeln(f,'MaterialBinding{'); + writeln(f,' value PER_FACE_INDEXED'); + writeln(f,'}'); + + writeln(f,'Material {'); + writeln(f,'ambientColor 0.0 0.0 0.3'); + writeln(f,'specularColor 1.0 1.0 1.0'); + + + writeln(f,'diffuseColor['); + for lop:=0 to 255 do begin + getrgb(lop,c.r,c.g,c.b); + writeln(f,' ',c.r /64:2:4,' ',c.g /64:2:4,' ',c.b /64:2:4,','); + + end; + writeln(f,']'); + writeln(f,'} #material'); + + writeln(f,' Coordinate3 {'); + writeln(f,' point['); + if maxpoints>0 then + For lop:= 0 to maxpoints-1 do Begin + with thred^[lop] do + writeln(f,' ',x/loadscale :1:4,' ',y/loadscale :1:4,' ',z/loadscale :1:4,','); + end; + writeln(f,' ]'); + writeln(f,' }'); + if maxpolys>0 then begin + writeln(f, ' ','IndexedFaceSet{'); + writeln(f,' ','coordIndex['); + + For lop:= 0 to maxpolys-1 do with polys^[lop] do Begin + {if lop=maxpolys-1 then comma:=' ';} + Write(f,' '); + For lop2:=numsides-1 downto 0 do + write(f,p[lop2],','); + Writeln(f,'-1,'); + end; + writeln(f, ' ',']'); + writeln(f, ' ','materialIndex['); + For lop:= 0 to maxpolys-1 do with polys^[lop] do Begin + Write(f,' '); + writeln(f,textureref,','); + end; + + writeln(f,' ]'); + writeln(f, '}'); + end; + writeln(f, '}'); + close(f); +end; + +procedure edit_objtype_.readVRML(filename:string); +const +loadscale=20; +var +buf:bufferedblock; +token:string; +vstring:string[10]; +parsed:boolean; + +Begin + parsed:=false; + buf.open(filename); + gettoken(buf,@token,DTstring); + if token='#VRML' then begin + gettoken(buf,@vstring,DTstring); + gettoken(buf,@token,DTstring); + while not buf.eof do begin + gettoken(buf,@token,DTstring); + end; + end; + buf.close; +end; + +procedure edit_objtype_.writePLG(filename:string); +Var dummy:string;tmp_lop,lop2:word;f:text; +Begin + Assign(f,filename); + Rewrite(f); + + writeln(f,'##MULTI'); + writeln(f,'SAVED ',maxpoints,' ',maxpolys); + For tmp_lop:= 0 to maxpoints-1 do Begin + write(f,round(thred^[tmp_lop].x*makebig),' '); + write(f,round(-thred^[tmp_lop].y*makebig),' '); + writeln(f,round(thred^[tmp_lop].z*makebig)); + end; + if maxpolys>0 then begin + For tmp_lop:= 0 to maxpolys-1 do with polys^[tmp_lop] do Begin + Write(f,'0x1955 ',numsides,' '); + For lop2:=numsides-1 downto 0 do + Write(f,p[lop2],' '); + writeln(f); + end; + close(f); + end; +end; + +procedure edit_objtype_.writePOV(filename:string); +Var lop,lop2:word;f:text; + r1,g1,b1:byte; + + procedure WriteVector(vec:word); + begin + write(f,' <',thred^[vec].x:3:5,','); + write(f,-thred^[vec].y:3:5,','); + write(f,thred^[vec].z:3:5,'>'); + end; + + procedure WriteTriangle(p1,p2,p3:byte); + begin + with currpoly^ do begin + writeln(f,' triangle {'); + WriteVector(p[p1]); + writeln(f,','); + WriteVector(p[p2]); + writeln(f,','); + WriteVector(p[p3]); + writeln(f,' '); + + writeln(f,' texture { Col',textureref,' }');; + writeln(f,' }'); + end; + end; + +Begin + assign(f,filename); + Rewrite(f); + + writeln(f,'camera {'); + writeln(f,' location <0, 0, -200>'); + writeln(f,' look_at <0, 0, 0>'); + writeln(f,'}'); + + for lop:=0 to SC.ColourDepth-1 do begin + getrgb(lop,r1,g1,b1); + writeln(f,'#declare Col',lop,' = texture {'); + writeln(f,' pigment { color red ',r1/64:3:5,' green ',g1/64:3:5,' blue ', b1/64:3:5,' }' ); + writeln(f,' finish {phong 2}'); + writeln(f,'}'); + end; + + writeln(f,'light_source {<15, 5, -140> color red 0.5 green 0.7 blue 0.9}'); + writeln(f,'light_source {<124, 125, -140> color red 1.0 green 1.0 blue 0.9}'); + writeln(f,'light_source {<5, 45, -120> color red 0.9 green 0.7 blue 0.3}'); + + currpoly:=pointer(polys); + if maxpolys>0 then begin + For lop:= 0 to maxpolys-1 do with currpoly^ do Begin + case numsides of + 3:WriteTriangle(0,1,2); + 4:begin + WriteTriangle(0,1,3); + WriteTriangle(1,2,3); + end; + end; + inc(currpoly); + end; + end; + close(f); +end; + + +function fileend(var f:file):boolean; +begin + fileend:=filesize(f)-filepos(f)>0; +end; + +procedure edit_objtype_.readRW(filename:string); +var + buf:bufferedblock; + tokenstack,matrixstack,protolist:linkedlist; + parsed:boolean; + token:tokenstring; + rotmat,usemat,tmpmat,origmat:matrix3x4type_; + poffset:integer; + currattrib:byte; + {uses to create and destroy the protolist} + protoref:prototype; + oldfileposlist:linkedlist; + lop:byte; + nsides:byte; + i:array[0..11] of word; + id:wordarray; + readvec:vectorreal; + angle:real; + currtokenref:tokentype; + geom:boolean; + const + records:word=1; +begin + reset3d; + parsed:=false; + poffset:=0; + name:=filename; + + {RenderWare draws along a different axis to me, this matrix will compensate} + lmrotate(@rotmat,-maxrotate / 4,0,0); + {default matrix scales by 100,100,100 and rotates around X 180 degrees} + Lmscale(@origmat,100,100,100); + lmrotate(@tmpmat,maxrotate / 2,0,0); + origmat.multiply(@tmpmat,mtpostconcat); + usemat:=origmat; + CTM:=@usemat; + + buf.open(filename); + + tokenstack.create(sizeof(tokentype_)); + matrixstack.create(sizeof(matrixelem_)); + protolist.create(sizeof(prototype_)); + oldfileposlist.create(sizeof(longintlist_)); + currattrib:=PAconnected; + while ((not parsed)and(Errorlevel<=ERRparseerror)) do begin + gettoken(buf,@token,DTstring); + parsed:=buf.eof; + begin + if token='MODELBEGIN' then + tokenstack.add(createtoken(token)) + else if token='CLUMPBEGIN' then begin + tokenstack.add(createtoken(token)); + poffset:=maxpoints; + end else if token='CLUMPEND' then begin + poffset:=maxpoints; + if tokentype(tokenstack.last)^.token='CLUMPBEGIN' then + tokenstack.delete(tokenstack.last) + else + Errorlevel:=ERRparseerror; + end else if token='MODELEND' then begin + if tokentype(tokenstack.last)^.token='MODELBEGIN' then + tokenstack.delete(tokenstack.last) + else + Errorlevel:=ERRparseerror; + end else if token='TRANSFORMBEGIN' then with readvec do begin + tokenstack.add(createtoken(token)); + matrixstack.add(creatematrix(@usemat)); + end else if token='MATERIALBEGIN' then with readvec do begin + end else if token='MATERIALEND' then with readvec do begin + end else if token='TRANSFORMEND' then begin + if tokentype(tokenstack.last)^.token='TRANSFORMBEGIN' then begin + tokenstack.delete(tokenstack.last); + usemat:=matrixelem(matrixstack.last)^.mat; + matrixstack.delete(matrixstack.last); + end else + Errorlevel:=ERRparseerror; + end else if token='TRANSFORM' then with readvec,tmpmat do begin + gettoken(buf,@m00,DTreal);gettoken(buf,@m01,DTreal);gettoken(buf,@m02,DTreal);gettoken(buf,@x,DTreal); + gettoken(buf,@m10,DTreal);gettoken(buf,@m11,DTreal);gettoken(buf,@m12,DTreal);gettoken(buf,@x,DTreal); + gettoken(buf,@m20,DTreal);gettoken(buf,@m21,DTreal);gettoken(buf,@m22,DTreal);gettoken(buf,@x,DTreal); + gettoken(buf,@p.x,DTreal);gettoken(buf,@p.y,DTreal);gettoken(buf,@p.z,DTreal);gettoken(buf,@x,DTreal); + CTM^:=origmat; + CTM^.multiply(@tmpmat,mtpostconcat); + end else if token='PROTOBEGIN' then begin + gettoken(buf,@token,DTstring); + protolist.add(createprototype(token,buf.fpos)); + while token<>'PROTOEND' do + gettoken(buf,@token,DTstring); + end else if token='PROTOEND' then begin + if oldfileposlist.count<>0 then begin + poffset:=maxpoints; + buf.fseek(longintlist(oldfileposlist.last)^.data); + oldfileposlist.delete(oldfileposlist.last) + end; + end else if (token='PROTOINSTANCE')or(token='PROTOINSTANCEGEOMETRY') then begin + + geom:=token='PROTOINSTANCEGEOMETRY'; + gettoken(buf,@token,DTstring); + {search protolist to see if the name is there} + protoref:=protolist.first; + while (protoref<>nil)and(protoref^.name<>token) do + protoref:=protoref^.next; + if protoref<>nil then begin + if geom then + poffset:=maxpoints; + oldfileposlist.add(createlongint(buf.fpos)); + buf.fseek(protoref^.bufpos); + end else + Errorlevel:=ERRparseerror; + end else if token='SCALE' then with readvec do begin + tmpmat:=CTM^; + gettoken(buf,@x,DTreal); + gettoken(buf,@y,DTreal); + gettoken(buf,@z,DTreal); + LmScale(CTM,x,y,z); + tmpmat.multiply(CTM,mtpostconcat); + CTM^:=tmpmat; + end else if token='TRANSLATE' then with readvec do begin + tmpmat:=CTM^; + gettoken(buf,@x,DTreal); + gettoken(buf,@y,DTreal); + gettoken(buf,@z,DTreal); + LmTrans(CTM,x,y,z); + tmpmat.multiply(CTM,mtpostconcat); + CTM^:=tmpmat; + end else if token='ROTATE' then with readvec do begin + tmpmat:=CTM^; + gettoken(buf,@x,DTreal); + gettoken(buf,@y,DTreal); + gettoken(buf,@z,DTreal); + gettoken(buf,@angle,DTreal); + angle:=(angle * maxrotate) /360; + LmRotate(CTM,round(x*angle),round(y*angle),round(z*angle)); + tmpmat.multiply(CTM,mtpostconcat); + CTM^:=tmpmat; + end else if token='IDENTITY' then with readvec do begin + lmunit(CTM); + end else if (token='VERTEX')or(token='VERTEXEXT') then with readvec do begin + gettoken(buf,@x,DTreal); + gettoken(buf,@y,DTreal); + gettoken(buf,@z,DTreal); + addvector(x,y,z); + end else if (token='QUAD')or(token='QUADEXT') then begin + for lop:=0 to 3 do begin + gettoken(buf,@i[lop],DTint); + inc(i[lop],poffset-1); + end; + addpolygonByRef(@i,4,currattrib,PCall+PCchecklines); + end else if (token='TRIANGLE')or(token='TRIANGLEEXT') then begin + for lop:=0 to 2 do begin + gettoken(buf,@i[lop],DTint); + inc(i[lop],poffset-1); + end; + addpolygonByRef(@i,3,currattrib,PCall+PCchecklines); + end else if (token='POLYGON')or(token='POLYGONEXT') then begin + gettoken(buf,@nsides,DTint); + getmem(id,nsides*sizeof(word)); + for lop:=0 to nsides-1 do begin + gettoken(buf,@id^[lop],DTint); + inc(id^[lop],poffset-1); + end; + addpolygonByRef(id,nsides,currattrib or PAconnected,PCall+PCchecklines); + freemem(id,nsides*sizeof(word)); + end else if token='DISC' then with readvec do begin + tmpmat:=CTM^; + CTM^.multiply(@rotmat,mtpostconcat); + gettoken(buf,@x,DTreal); + gettoken(buf,@y,DTreal); + gettoken(buf,@nsides,DTint); + mkcircle(0,0,y,y,-x,nsides,PCall,0,currattrib or PAconnected); + CTM^:=tmpmat; + end else if token='BLOCK' then with readvec do begin + gettoken(buf,@x,DTreal); + gettoken(buf,@y,DTreal); + gettoken(buf,@Z,DTreal); + divide(2); + mkcube(-x,-y,-z,x,y,z,currattrib or PAconnected); + end else if token='CONE' then with readvec do begin + tmpmat:=CTM^; + CTM^.multiply(@rotmat,mtpostconcat); + gettoken(buf,@x,DTreal); + gettoken(buf,@y,DTreal); + gettoken(buf,@nsides,DTint); + mkcone(0,0,-y,-y,0,-x,nsides,0,currattrib or PAconnected); + CTM^:=tmpmat; + end else if token='CYLINDER' then with readvec do begin + tmpmat:=CTM^; + CTM^.multiply(@rotmat,mtpostconcat); + gettoken(buf,@x,DTreal); + gettoken(buf,@y,DTreal); + gettoken(buf,@z,DTreal); + gettoken(buf,@nsides,DTint); + mkcylinder(0,0,-y,-y,-z,-z,0,-x,nsides,0,currattrib or PAconnected); + CTM^:=tmpmat; + end else if token='SPHERE' then with readvec do begin + tmpmat:=CTM^; + CTM^.multiply(@rotmat,mtpostconcat); + gettoken(buf,@y,DTreal); + gettoken(buf,@nsides,DTint); + mksphere(0,0,0,-y,-y,-y,nsides * 2,nsides,0,currattrib or PAconnected); + CTM^:=tmpmat; + end else if token='LIGHTSAMPLING' then begin + gettoken(buf,@token,DTstring); + if token='VERTEX' then + Currattrib:=Currattrib or PAsmooth + else if token='FACET' then + Currattrib:=Currattrib and not PAsmooth + end else if token='GEOMETRYSAMPLING' then with readvec do begin + gettoken(buf,@token,DTstring); + if token='SOLID' then + Currattrib:=Currattrib and not PAoutlined + else if token='WIREFRAME' then + Currattrib:=Currattrib or PAoutlined + end else if token='COLOR' then with readvec do begin + gettoken(buf,@x,DTreal); + gettoken(buf,@y,DTreal); + gettoken(buf,@z,DTreal); + fgtexture:=allocateRGB(round(x*64),round(y*64),round(z*64)); + end; + end; + end; + CTM:=@unitmatrix; + tokenstack.done; + matrixstack.done; + protolist.done; + oldfileposlist.done; + buf.close; +end; + + + +procedure edit_objtype_.writeRW(filename:string); +Var lop,lop2:word;f:text; + r1,g1,b1:byte; + pal:array[0..255]of realrgb; + oldtexture:byte; + oldattrib:byte; +Begin + for lop:=0 to SC.ColourDepth-1 do begin + getrgb(lop,r1,g1,b1); + pal[lop].r:=r1/64;pal[lop].g:=g1/64;pal[lop].b:=b1/64; + end; + assign(f,filename); + Rewrite(f); + writeln(f,'ModelBegin '); + writeln(f,' ClumpBegin '); + writeln(f,' Surface 0.200000 0.900000 0.400000 '); + writeln(f,' GeometrySampling Solid '); + writeln(f,' Texture NULL '); + if maxpoints>0 then + for lop:=0 to maxpoints-1 do with thred^[lop] do + writeln(f,' Vertex ',x/100:3:5,' ',-y/100:3:5,' ',-z/100:3:5,' '); + oldtexture:=polys^[lop].textureref+1; + oldattrib:=polys^[lop].pattrib+1; + if maxpolys>0 then begin + For lop:= 0 to maxpolys-1 do with polys^[lop] do begin + if textureref<>oldtexture then + with texturebank[textureref] do begin + with colour do writeln(f,' color ',r/64:3:5,' ',g/64:3:5,' ',b/64:3:5,' '); + writeln(f,' Surface ',ambient/256:3:5,' ',diffuse/256:3:5,' ',specular/256:3:5); + end; + if (oldattrib and PaSmooth)<>(pattrib and PaSmooth)then begin + if pattrib and PAsmooth<>0 then + writeln(f,' LightSampling Vertex ') + else + writeln(f,' LightSampling Facet '); + end; + if (oldattrib and PaOutlined)<>(pattrib and PaOutlined)then begin + if pattrib and Paoutlined<>0 then + writeln(f,' GeometrySampling Wireframe ') + else + writeln(f,' GeometrySampling Solid '); + end; + case numsides of + {2:writeln(f, ' triangle ',p[1]+1,' ',p[1]+1,' ',p[0]+1);} + 3:writeln(f, ' triangle ',p[2]+1,' ',p[1]+1,' ',p[0]+1,' '); + 4:writeln(f, ' Quad ',p[3]+1,' ',p[2]+1,' ',p[1]+1,' ',p[0]+1,' '); + end; + {if Attrib and PaDoubleSided <> 0 then + writeln(f,' Quad ',p[3]+1,' ',p[2]+1,' ',p[1]+1,' ',p[0]+1);} + oldtexture:=textureref; + oldattrib:=pattrib; + end; + end; + writeln(f,' ClumpEnd '); + writeln(f,'ModelEnd '); + close(f); +end; + +procedure edit_objtype_.write3dsasc(filename:string); +var f:text; +lop:word; +maxtriangles:word; +r1,g1,b1:byte; +begin + assign(f,filename); + rewrite(f); + + maxtriangles:=0; + for lop:=0 to maxpolys-1 do with polys^[lop] do + if numsides=3 then + inc(maxtriangles) + else + inc(maxtriangles,2); + + writeln(f,'Ambient light color: Red=0.1 Green=0.1 Blue=0.3'); + writeln(f,'Named object: "',filename,'"'); + writeln(f,'Tri-mesh, Vertices: ',maxpoints,' Faces: ',maxtriangles); + writeln(f,'Vertex list:'); + for lop:=0 to maxpoints-1 do with thred^[lop] do + writeln(f,'Vertex ',lop,': X:',x/100:3:5,' Y:',-y/100:3:5,' Z:',z/100:3:5,' '); + writeln(f,'Face list:'); + maxtriangles:=0; + for lop:=0 to maxpolys-1 do with polys^[lop] do begin + writeln(f,'Face ',maxtriangles,': A:',p[0],' B:',p[1],' C:',p[2],' AB:',1,' BC:',1,' CA:',1); + {with texturebank[textureref].colour do + writeln(f,'Material:"r',r shl 2,'g',g shl 2,'b',b shl 2,'a0"');} + write(f,'Material:"color'); + if textureref<10 then write(f,'0'); + writeln(f,textureref,'"'); + writeln(f,'Smoothing:',1{byte(pattrib and PaSmooth <>0)}); + inc(maxtriangles); + if numsides>3 then begin + writeln(f,'Face ',maxtriangles,': A:',p[0],' B:',p[2],' C:',p[3],' AB:',1,' BC:',1,' CA:',1); + {with texturebank[textureref].colour do + writeln(f,'Material:"r',r shl 2,'g',g shl 2,'b',b shl 2,'a0"');} + write(f,'Material:"color'); + if textureref<10 then write(f,'0'); + writeln(f,textureref,'"'); + + writeln(f,'Smoothing:',1{byte(pattrib and PaSmooth <>0)}); + inc(maxtriangles); + end; + end; + close(f); +end; + + +procedure edit_objtype_.writeCOBasc(filename:string); +var f:text; +lop,objid:word; +lopb:byte; +r1,g1,b1:byte; +begin + assign(f,filename); + rewrite(f); + objid:=10000; + + writeln(f,'Caligari V00.01ALH'); + writeln(f,'PolH V1.00 Id ',objid,'Parent 0 Size ',0); + writeln(f,'Name',filename,'"'); + {PolH V0.02 Id 2440108 Parent 0 Size 00067914} + writeln(f,'center 0.0 0.0 0.0'); + writeln(f,'Transform'); + Writeln(f,obmat.m00:3:4,' ',obmat.m01:3:4,' ',obmat.m02:3:4,' 0.0'); + Writeln(f,obmat.m10:3:4,' ',obmat.m11:3:4,' ',obmat.m12:3:4,' 0.0'); + Writeln(f,obmat.m20:3:4,' ',obmat.m21:3:4,' ',obmat.m22:3:4,' 0.0'); + Writeln(f,obmat.p.x:3:4,' ',obmat.p.y:3:4,' ',obmat.p.z:3:4,' 1.0'); + writeln(f,'World Vertices ',maxpoints); + for lop:=0 to maxpoints-1 do with thred^[lop] do + writeln(f,'Vertex ',x/100:3:5,' ',-y/100:3:5,' ',z/100:3:5); + + writeln(f,'Texture Vertices 1'); + writeln(f,'0.000000 0.000000'); + writeln(f,'Faces ',maxpolys); + for lop:=0 to maxpolys-1 do with polys^[lop] do begin + + writeln(f,'Face verts ',numsides,' flags 0 mat ',textureref); + for lopb:=0 to numsides-1 do + write(f,'<',p[lopb],',0> '); + writeln(f); + end; + {alpha 1 ka 0.29 ks 0.94 exp 0.1 ior 1} + for lop:=0 to 15 do with texturebank[lop] do begin + writeln(f,'mat# ',lop); + writeln(f,'shader: phong facet: smooth'); + {if attrib and PaSmooth<>0 then + writeln(f,'smooth') + else + writeln(f,'faceted')} + + with colour do + writeln(f,'rgb ',r / 64:3:4,',',g / 64:3:4,',',b / 64:3:4); + end; + writeln(f,'END V1.00 Id 0 Parent 0 Size 0'); + + close(f); + +end; + +procedure edit_objtype_.write3ds(filename:string); +const +{chunks are *mostly* in any order but some chunks expect others +after them} +HeaderChunk=$4D4D; +ObjectChunk=$3D3D; {Start of object mesh data.} + BackgroundColourBlock=$1200; + AmbientColourBlock=$2100; + ObjectDescriptionChunk=$4000; + {insert name here -assciz} + ShadowChunk=$4012; {shadow?} + TriangleObjectChunk=$4100; {Triangular Polygon Object} + VertexListChunk=$4110; {Vertex List} + TrianglelistChunk=$4120; {Points List} + MatrixChunk=$4160; {Translation Matrix} + LightChunk=$4600; {Light} + CameraChunk=$4700; {Camera} +KeyFrameChunk=$B000; {Start of keyframer data.} + + +Var lop,lop2,tricount:word; + f:file; + recsize:word; + NumTriPos,EndTriListPos:longint; + r1,g1,b1:byte; + pal:array[0..255]of realrgb; + objectname:array[0..255] of byte; + oldcolour:byte; + oldsmooth:byte; + wword,trilistsize,vertlistsize,meshsize, + objdiscriptionsize,objectdatasize,totalobjectsize:word; + +Begin + recsize:=1; + for lop:=0 to SC.ColourDepth-1 do begin + getrgb(lop,r1,g1,b1); + pal[lop].r:=r1/64;pal[lop].g:=g1/64;pal[lop].b:=b1/64; + end; + tricount:=0; + for lop:=0 to maxpolys-1 do with polys^[lop] do begin + inc(tricount); + if numsides=4 then + inc(tricount); + end; + + trilistsize:=4+(6*tricount); + vertlistsize:=4+(16*maxpoints); + meshsize:=4+trilistsize+vertlistsize; + objdiscriptionsize:=4+meshsize+sizeof(name)+1; + objectdatasize:=4+objdiscriptionsize; + totalobjectsize:=4+objectdatasize; + + + + {make a null-terminated string and write it} + if length(name)>0 then + for lop2:=1 to length(name) do + objectname[lop-1]:=byte(name[lop]); + objectname[length(name)]:=0; + + assign(f,filename); + rewrite(f,recsize); + {////////////HEADER////////////} + wword:=HeaderChunk; + blockwrite(f,wword,2,recsize); + wword:=totalobjectsize; + blockwrite(f,wword,2,recsize); + {POST OPTIONS: OBJECT(S), KEYFRAMING} + {////////////OBJECT DATA////////////} + {OPTIONS: + BACKGROUND COLOUR,AMBIENT COLOUR} + wword:=ObjectChunk; + blockwrite(f,wword,2,recsize); + wword:=objectdatasize; + blockwrite(f,wword,2,recsize); + {////////////OBJECT TYPE/DESCRIPTION HEADER////////////} + {OPTIONS: + SHADOW,LIGHT,CAMERA} + wword:=ObjectDescriptionChunk; + blockwrite(f,wword,2,recsize); + wword:=objdiscriptionsize; + blockwrite(f,wword,2,recsize); + blockwrite(f,objectname,sizeof(name)+1); + {////////////TRIANGLE MESH////////////} + wword:=TriangleObjectChunk; + blockwrite(f,wword,2,recsize); + wword:=meshsize; + blockwrite(f,wword,2,recsize); + {POST OPTIONS: + VERTEX LIST, TRIANGLE LIST, MATRIX} + {////////////VERTEX LIST////////////} + wword:=VertexListChunk; + blockwrite(f,wword,2,recsize); + wword:=vertlistsize; + blockwrite(f,wword,2,recsize); + {num points} + blockwrite(f,maxpoints,2,recsize); + {actual vertex data in IEEE format} + for lop:=0 to maxpoints-1 do + blockwrite(f,thred^[lop],4,recsize); + {end of vertex list chunk} + + {////////////TRIANGLE LIST////////////} + wword:=TrianglelistChunk; + blockwrite(f,wword,2,recsize); + wword:=trilistsize; + blockwrite(f,wword,2,recsize); + blockwrite(f,tricount,2,recsize); + {actual triangle data} + for lop:=0 to maxpolys-1 do with polys^[lop] do begin + for lop2:=0 to 2 do begin + wword:=p[lop2]+1; + blockwrite(f,wword,2,recsize); + end; + if numsides=4 then begin + wword:=p[1]+1; + blockwrite(f,wword,2,recsize); + wword:=p[3]+1; + blockwrite(f,wword,2,recsize); + wword:=p[2]+1; + blockwrite(f,wword,2,recsize); + end; + end; + + close(f); +end; + +procedure edit_objtype_.ReadEAfile(filename:string); +Var dummy:string; + tmp_lop,lop2,maxlines,curline,oldline:word;code:integer; + f:text; +Begin + assign(f,filename); + name:=filename; + Rewrite(f); + {Readln(f,dummy);} + readln(f,maxpoints); + For tmp_lop:=0 to maxpoints-1 do Begin + system.read(f,thred^[tmp_lop].x);system.read(f,thred^[tmp_lop].y);system.read(f,thred^[tmp_lop].z); + readln(f); + end; + readln(f,maxlines); + maxjoins:=0; + For tmp_lop:=1 to maxlines do begin + oldline:=curline; + system.read(f,curline); + system.read(f,code); + if code<>0 then begin + jointo^[maxjoins].f:=oldline-1; + jointo^[maxjoins].t:=curline-1; + inc(maxjoins); + end; + readln(f); + end; + + close(f); +end; + +begin + CTM:=@unitmatrix; +end. \ No newline at end of file diff --git a/TDWIN.PAS b/TDWIN.PAS new file mode 100644 index 0000000..bb06353 --- /dev/null +++ b/TDWIN.PAS @@ -0,0 +1,1492 @@ +Unit Tdwin; + +INTERFACE + +uses + ttypes,crt2,tmaths,msmouse,SinCos, + gbasics,ggraph,vectfont, + twinb,twindraw,views,gadgets,dialogs, + Basic3d,tdb,tdeditb; + +const +ZOOMKEYS=smLEFTSHIFT or smLEFTCTRL; + +{Rotation sensitivity} +sensi=100; +{Grid modes} +GMflat=1; +GMsine=2; +GMheightmap=3; +{ID numbers} +memmessagePID=423; +fontmessagePID=424; +notyetimpPID=12; +selectmessagePID=425; +fileerrorPID=15; + +CMDredrawobject3d =328; + +{Drawing modes} +CMDeditselect =6140; +CMDeditsquare =6141; +CMDeditcube =6142; +CMDeditDot =6143; +CMDeditLiner =6144; +CMDeditcone =6145; +CMDeditCircle =6146; +CMDeditCylinder =6147; +CMDeditSphere =6148; +CMDeditRotate =6149; +CMDeditgrid =6150; +CMDedittext =6151; +{extended internal drawingmodes} + +RANGEextcomSTART =7152; +RANGEextcomEND =7310; + +{these make changes to the existing database +(deletion or transformation)} + +RANGEchangecomSTART =7152; +RANGEchangecomEND =7165; + +CMDundo =7152; +CMDtransformselection =7153; +CMDmovenode =7154; +CMDselectclear =7155; +CMDmerge =7156; +CMDdeleteselect =7157; +CMDflipx =7158; +CMDflipy =7159; +CMDflipz =7160; +CMDQuadDivide =7161; +CMDTriangulate =7162; +CMDSplit =7163; +CMDnew =7164; +CMDdeletelines =7165; + +RANGEchangeselectSTART =7200; +RANGEchangeselectEND =7201; +CMDselectall =7200; +CMDnewselection =7201; + +{these add to the existing database, making no changes} +RANGEaddcomSTART =7250; +RANGEaddcomEND =7255; + +CMDautocopyselected =7250; +CMDcopyselection =7251; +CMDaddpolygon =7252; +CMDrotatedformX =7253; +CMDrotatedformY =7254; +CMDrotatedformZ =7255; + +{these change polygon attributes} +RANGEpolychangeSTART =7300; +RANGEpolychangeEND =7310; + +CMDmkDoublesided =7300; +CMDmkSinglesided =7301; +CMDmksmooth =7302; +CMDmkFlat =7303; +CMDmkSolid =7304; +CMDmkOutlined =7305; +CMDflipnorms =7306; +CMDApplycolour =7307; +CMDApplyAttrib =7308; +CMDapplyAttribandColour=7309; +CMDdeletepolys =7310; + + +{load and save commands} +CMDsave3dfile =400; +CMDload3dfile =401; +CMDappend3dfile =402; + +{file modes} +CMDfilemode_start=1279; +CMDfilemode_end=1289; + +CMD3dfile =1279; +CMDRWfile =1280; +CMDPOVfile =1281; +CMDOBJfile =1282; +CMDGEOfile =1283; +CMDVRMLfile =1284; +CMDPLGfile =1285; +CMD3dsfile =1286; +CMDgorfile =1287; +CMDTrueSpaceFile =1288; +CMDJavaFile =1289; + + +{window commands} +CMDrotate =202; +CMDreset3dvalues =200; +CMDsavewin =201; +CMDsetcoords =1086; + +CMDloadfontdialog =1059; + +CMDselectedittext =2004; + +worldsize=1000; {extent of scroller bars} + +draw_back=32; {draw back rectangle} +draw_orthnodes=16; {draw the edit window nodes} +draw_orthlines=8; {draw the edit window lines} +draw_orth=draw_orthnodes+draw_orthlines; +draw_Perspective=4; {draw the 3d display window} +draw_3dstuff=draw_orth+Draw_perspective; {draw the object} +draw_boundingboxstuff=2; {draw the bounding box} +draw_cursorstuff=64; {draw 3d cursor} +draw_all=255; + +what_to_draw:byte=draw_all; +last_twodwindow:byte=4; + +{is extruding on or off?} +extrude:boolean=false; +currattrib:byte=PaConnected; + + +drawallnodes:boolean=true; +drawing_mode:word=CMDeditselect; +conesize:integer=10; +circsize:integer=10; +cylindersize:integer=10; +spheresize:pointtype=(x:10;y:10); +RotSize:integer=10; +DivisionSize:integer=1; {global permitations between two extruded surfaces} +GridX:integer=10; +GridY:integer=10; +gridmode:byte=GMflat; +Checkornot:boolean=false; +divsizez:byte=10; +grid_on:boolean=false; +gridlock:boolean=false; +gridsize:pointtype=(x:10;y:10); +SMbegin=160; +SMend=162; +SMresize_repos=160; +SMrotate=161; +SMdeform=162; +SMnodal=163; +SMobjects=164; +Selected_mode:word=SMresize_repos; +selectmodelevel:byte=SMnodal; +stickymouse:boolean=FALSE; + + +xorRed=red xor backcol;xorgreen=linecolour xor backcol; + +type + +Creationstruct = record + v1,v2:vectorreal; + angle:real; + segments:word +end; + +CoordArray=array[0..29] of vectorreal; + +Tcube=^Tcube_; +Tcube_=record + a,b:vectorreal; +end; + +delta_orth=^delta_orth_; +delta_orth_=object(delta_) + orientation:byte; + transmat:matrix3x4type_; + editobject:edit_objtype; + + constructor make(orient:byte;obj:edit_objtype); + procedure draw;virtual; + Procedure LocalSpace(var x,y:integer); + Procedure GlobalSpace(var x,y:integer); + {procedure draw_precalc;virtual;} + procedure draw_boundingbox(xp,yp:integer); + procedure handlevent(var event:tevent);virtual; + procedure docommand(command:word;params:pointer;divsize:integer); + + Procedure do2d_3d(xp,yp:integer;filter:VectorReal;var dot:VectorReal); + Procedure do3d_2d(dot:VectorReal;var x,y:integer); +end; + +delta_3d=^delta_3d_; +delta_3d_=object(delta_) + {obspos,obsrot:vectorint; + drawmode:byte;} + CurrentRotation:vectorreal; + editobject:edit_objtype; + boundcube:edit_objtype; + cursor:edit_objtype; + constructor make(obj:edit_objtype); + destructor done;virtual; + procedure draw;virtual; + Procedure handlevent(var event:tevent); virtual; + procedure setoffsets(xoff_,yoff_:integer);virtual; + {procedure draw_precalc;virtual;} +end; + +var +gridpic:bitmaptypeptr; +{****-----Desktop Needs to be set to send messages to---****} +desktop:desktoptype; + +{check to see if font is loaded, value altered by main prog} +vfontin:boolean; +autocopymatrix:matrix3x4type_; +step:integer; +Vfont:font_type; +EditString:string; +Edviews:array[0..3]of delta; + +procedure Drawobject; +procedure Draworth; +procedure setscale(scaleval:real); + +IMPLEMENTATION + +procedure Drawobject; +var lop:byte; +begin + for lop:=0 to 3 do + edviews[lop]^.drawview; +end; + +procedure Draworth; +var lop:byte; +begin + for lop:=0 to 2 do + edviews[lop]^.drawview; +end; + +{---------------------****Windowing stuff****-----------------------} + +constructor delta_3d_.make(obj:edit_objtype); +const +cs=7; +begin + inherited make(-worldsize,-worldsize,worldsize,worldsize); + editobject:=obj; + xoff:=0;yoff:=0; + currentrotation.moveto(0,0,0); + fgtexture:=xorred; + new(boundcube,create(8,12,6)); + boundcube^.mkcube(0,0,0,1,1,1,PaOutLined+PaConnected); + new(cursor,create(6,3,0)); + with cursor^ do begin + addvector(-cs,0,0); addvector(cs,0,0); + addvector(0,-cs,0); addvector(0,cs,0); + addvector(0,0,-cs); addvector(0,0,cs); + + addjoin(0,1); + addjoin(2,3); + addjoin(4,5); + end; + {drawmode:=CMDlines;} + fgtexture:=5; +end; + +destructor delta_3d_.done; +begin + dispose(boundcube,done); + dispose(cursor,done); + inherited done; +end; + +Procedure delta_3d_.draw; +const + bs=3; + base:byte=0; +var + lop:byte; +begin + + with editobject^ do begin + if what_to_draw and Draw_perspective<>0 then + if maxpoints>0 then begin + if state and sfdrawnonce=0 then begin + do3d(x1+halfx,y1+halfy); + {sound(200);delay(50);nosound;} + waitvbl; + end; + end; + if what_to_draw and draw_back<>0 then begin + t_fillcol:=backcol; + bar(x1,y1,x2,y2); + end; + if what_to_draw and draw_perspective<>0 then if maxpoints>0 then begin + T_col:=linecolour; + case render_mode of + CMDlines:if maxjoins>0 then liner; + CMDdots:dotter; + CMDhlines..CMDgouraud:if maxpolys>0 then filler(render_mode); + End; + + end; + if what_to_draw and draw_boundingboxstuff<>0 then + If (maxselect>0)and(maxpoints>0) then with editobject^ do Begin + t_writemode:=(xorput);t_col:=(xorRed); + if state and sfdrawnonce=0 then begin + + boundcube^.thred^[0].moveto(min.x-bs,min.y-bs,min.z-bs); + boundcube^.thred^[base+1].moveto(max.x+bs,min.y-bs,min.z-bs); + boundcube^.thred^[base+2].moveto(max.x+bs,max.y+bs,min.z-bs); + boundcube^.thred^[base+3].moveto(min.x-bs,max.y+bs,min.z-bs); + + boundcube^.thred^[base+4].moveto(min.x-bs,min.y-bs,max.z+bs); + boundcube^.thred^[base+5].moveto(max.x+bs,min.y-bs,max.z+bs); + boundcube^.thred^[base+6].moveto(max.x+bs,max.y+bs,max.z+bs); + boundcube^.thred^[base+7].moveto(min.x-bs,max.y+bs,max.z+bs); + + boundcube^.do3d(x1+halfx,y1+halfy); + end; + boundcube^.liner; + t_writemode:=(0); + End; + End; + if (what_to_draw and draw_cursorstuff<>0) + then with cursor^ do begin + t_writemode:=(xorput);t_col:=(xorRed); + if state and sfdrawnonce=0 then begin + for lop:=0 to 5 do + thred^[lop].add(crs.x,crs.y,crs.z); + do3d(x1+halfx,y1+halfy); + for lop:=0 to 5 do + thred^[lop].sub(crs.x,crs.y,crs.z); + end; + liner; + t_writemode:=(0); + end; + t_col:=15; + outtextxy(x1+2,y1+2,'Rotation:'+ftoa(currentrotation.x,1,1)+','+ + ftoa(currentrotation.z,1,1)+','+ftoa(currentrotation.z,1,1)); + + +End; + +procedure delta_3d_.setoffsets(xoff_,yoff_:integer); +begin + obspos.x:=xoff_; + obspos.y:=yoff_; + inherited setoffsets(xoff_,yoff_); +end; + +procedure delta_3d_.handlevent(var event:tevent); + + +var px,py:integer; + dontdraw:boolean; +begin + inherited handlevent(event); + dontdraw:=true; + with event,editobject^ do begin + if what and EvMousePressed<>0 then begin + SC.viewport.intersect(self); + SC.viewport.intersect(SC.screenport); + SC.viewport.intersect(owner^.owner^); + px:=xm;py:=ym; + mouseoff; + While zm<>0 do begin + Case zm of + 2:obmat.p.z:=obmat.p.z+(py-ym); + 1:begin + obmat.p.x:=obmat.p.x+xm-px; + obmat.p.y:=obmat.p.y+ym-py; + End; + 3:with CurrentRotation do begin + x:=x+((py shr 1)-(ym shr 1))/sensi; + y:=y+((px shr 1)-(xm shr 1))/sensi; + LmRotTrans(@obmat,x,y,z,obmat.p.x,obmat.p.y,obmat.p.z); + End; + End;{of case} + boundcube^.obmat:=obmat; + cursor^.obmat:=obmat; + if (px<>xm) or(py<>ym) then + draw; + mpos; + if (px<>xm) or(py<>ym) then setmousepos(px,py); + End;{of while} + mouseon; + SC.viewport:=SC.screenport; + end; + if what=EvKeyDown then with editobject^ do begin + dontdraw:=false; + case charcode of + #9:Begin + LmUnit(@obmat); + BoundCube^.obmat:=obmat; + Cursor^.obmat:=obmat; + CurrentRotation.moveto(0,0,0); + end; + '1':Render_mode:=CMDdots; + '2':Render_mode:=CMDlines; + '3':Render_mode:=CMDHlines; + '4':Render_mode:=CMDLsource; + '5':Render_mode:=CMDGouraud; + '6':Render_mode:=CMDCpolygons; + ',','.','a','z','x','c','s','S':with CurrentRotation do begin + case charcode of + ',':y:=y+step; + '.':y:=y-step; + 'a':x:=x+step; + 'z':x:=x-step; + 'x':z:=z+step; + 'c':z:=z-step; + end; + LmRotTrans(@obmat,x,y,z,obmat.p.x,obmat.p.y,obmat.p.z); + BoundCube^.obmat:=obmat; + Cursor^.obmat:=obmat; + end; + 's':inc(step,1); + 'S':dec(step,1); + else dontdraw:=true; + end; + + end; + if what=EvCommand then begin + dontdraw:=false; + case command of + CMDrotate:begin + with VectorRealPtr(infoptr)^ do + CurrentRotation.add(x,y,z); + with CurrentRotation do + LmRotTrans(@obmat,x,y,z,obmat.p.x,obmat.p.y,obmat.p.z); + BoundCube^.obmat:=obmat; + Cursor^.obmat:=obmat; + end; + CMDredrawobject3d:drawview; + CMDdots..CMDgouraud:render_mode:=command; + CMDreset3dvalues:begin + LmUnit(@obmat); + BoundCube^.obmat:=obmat; + Cursor^.obmat:=obmat; + CurrentRotation.moveto(0,0,0); + end; + else dontdraw:=true; + end; + end; + if not dontdraw then drawview; + end; +end; + +Procedure drawcircle(x,y:integer;w,h:integer;stp:integer;start_angle:real); +Var lop:integer; + Ccos,Csin,oldsin,oldcos:integer; + cindex,cadd:real; +begin + + cindex:=0; + cadd:=(2*pi) / stp; + For lop:=0 to stp do begin + oldsin:=Csin; + oldcos:=Ccos; + Csin:=x+round(sin(start_angle+cindex)*w); + Ccos:=y+round(cos(start_angle+cindex)*h); + if lop>0 then + line(Csin,Ccos,oldsin,oldcos); + cindex:=cindex+cadd; + End; +End; + +function CheckClicked(altmethod:boolean;zm:byte):boolean; +begin + altmethod:=altmethod and stickymouse; + checkclicked:=((zm=1) and not(altmethod))or((altmethod) and (zm=0)); +end; + + +Function resizebounds(var x1,y1,x2,y2:integer;numcopies:word):shortint; +const +innerborder=border-halfgadget; +Var a:shortint;xa,ya,xb,yb,offx,offy:integer; +oldvp:trect; +r:trect; +altmethod:boolean; +oldxm,oldym:integer; + +Begin + oldxm:=gridxm; + oldym:=gridym; + r.rassign(x1,y1,x2,y2); + a:=0; + xa:=x1-maxborder;ya:=y1-maxborder;xb:=x2+innerborder;yb:=y2+innerborder; + offx:=((x2-x1) shr 1)-halfgadget; + offy:=((y2-y1) shr 1)-halfgadget; + + if chkicon(xb,yb,gadgetsize,gadgetsize)>0 then a:=bellow_right else + if chkicon(xa,yb,gadgetsize,gadgetsize)>0 then a:=bellow_left else + if chkicon(xa,ya,gadgetsize,gadgetsize)>0 then a:=above_left else + if chkicon(xb,ya,gadgetsize,gadgetsize)>0 then a:=above_right else + + if chkicon(offx + x1,yb, gadgetsize,gadgetsize)>0 then a:=bellow else {_} + if chkicon(xb,offy + y1, gadgetsize,gadgetsize)>0 then a:=right else {>} + if chkicon(offx + x1,ya, gadgetsize,gadgetsize)>0 then a:=above else {~} + if chkicon(xa,offy + y1, gadgetsize,gadgetsize)>0 then a:=left else {<} + if chkicon(x1-border,y1-border,(border shl 1)+(x2-x1),(border shl 1)+ + (y2-y1))>0 then a:=middle;{move} + + if a<>0 then begin + oldvp:=SC.viewport; + SC.viewport:=SC.screenport; + what_to_draw:=draw_boundingboxstuff; + drawobject; + what_to_draw:=draw_all; + SC.viewport:=oldvp; + t_writemode:=(xorput);t_col:=(xorRed); + altmethod:=false; + + While checkclicked(altmethod,zm) do Begin + mpos; + mouseoff;Drawboundmulti(r.x1,r.y1,r.x2,r.y2,x1,y1,x2,y2,numcopies,true);mouseon; + while (not ms_gridmoved) and (zm=byte(altmethod)xor 1) do mbutton; + + Mouseoff;Drawboundmulti(r.x1,r.y1,r.x2,r.y2,x1,y1,x2,y2,numcopies,true);mouseon; + ms_xdiff:=gridxm-oldgridxm; + ms_ydiff:=gridym-oldgridym; + + if (zm=0)and(oldxm=gridxm)and(oldym=gridym) then altmethod:=stickymouse; + + if a and left <> 0 then begin + inc(x1,ms_xdiff); + if scan and smLEFTSHIFT<>0 then dec(x2,ms_xdiff); + end; + if a and above <> 0 then begin + inc(y1,ms_ydiff); + if scan and smLEFTSHIFT<>0 then dec(y2,ms_ydiff); + end; + if a and right <> 0 then begin + inc(x2,ms_xdiff); + if scan and smLEFTSHIFT<>0 then dec(x1,ms_xdiff); + end; + if a and bellow <> 0 then begin + inc(y2,ms_ydiff); + if scan and smLEFTSHIFT<>0 then dec(y1,ms_ydiff); + end; + + End; + {if (oldx=xm)and(oldy=ym) then a:=-1;} + End; + resizebounds:=a; + {inc(x1,border);inc(y1,border);dec(x2,border);dec(y2,border);} +End;{of function} + +function rotatesquare(x1,y1,x2,y2,cx,cy:integer;var angle:real;numcopies:word):shortint; +var oldx:integer; + oldvp:trect; + oldangle:real; +begin + + oldx:=xm; + if chkicon(x1-border,y1-border,(border shl 1)+x2-x1,(border shl 1)+y2-y1)>0 then begin + oldvp:=SC.viewport; + oldangle:=0; + SC.viewport:=SC.screenport; + what_to_draw:=draw_boundingboxstuff; + drawobject; + what_to_draw:=draw_all; + SC.viewport:=oldvp; + t_writemode:=(xorput);t_col:=(xorRed); + rotatesquare:=1; + angle:=0; + + while zm=1 do begin + mpos; + angle:=((xm-oldx)/ sensi); + mouseoff;rectangle_rotatedmulti(x1,y1,x2,y2,cx,cy,angle,oldangle,numcopies,true);mouseon; + while not (ms_moved)and(zm=1) do mpos; + mouseoff;rectangle_rotatedmulti(x1,y1,x2,y2,cx,cy,angle,oldangle,numcopies,true);mouseon; + end; + + end else rotatesquare:=-1; +end; + + +Procedure getsquare(R:prect;win:delta_orth); +var currcol:byte; + altmethod:boolean; +Begin + currcol:=t_col; + with R^ do begin + x1:=Gridxm;y1:=Gridym; + + altmethod:=false; + while checkclicked(altmethod,zm) do Begin + mpos; + t_writemode:=0; + if scan and smLEFTSHIFT <>0 then setmousepos(gridxm,y1+(gridxm-x1)); + win^.sendCommand(CMDsetcoords,root,win); + t_writemode:=(xorput); + t_col:=currcol; + mouseoff;rectangle(x1,y1,oldgridxm,oldgridym);mouseon; + while (not ms_gridmoved ) and (zm=byte(altmethod)xor 1) do + mbutton; + mouseoff;rectangle(x1,y1,oldgridxm,oldgridym);mouseon; + + if (zm=0)and(gridxm=x1)and(gridym=y1) then altmethod:=stickymouse; + + End; + x2:=Gridxm;y2:=Gridym; + {make sure that 0 size squares are not possible} + if x2=x1 then inc(x2,1); + if y2=y1 then inc(y2,1); + if x1>x2 then fswap(x1,x2,2);if y1>y2 then fswap(y1,y2,2); + end; + t_writemode:=(0); +End; + +{this routine is crap (hehe) and always behaves like 'sticky mouse'} +function getline(points:pointtypearray;maxpoints:word;win:delta_orth):integer; +var currcol:byte; + linecount:byte; + x1,y1:integer; + altmethod,endsame:boolean; + firstrect:trect; +Begin + currcol:=t_col; + x1:=Gridxm;y1:=Gridym; + linecount:=0; + points^[0].x:=x1; + points^[0].y:=y1; + firstrect.rassign(x1-3,y1-3,x1+3,y1+3); + altmethod:=false; + endsame:=false; + mpos; + while (not ms_doubleclicked)and(linecount0 then setmousepos(xm,y1+(Gridxm-x1)); + win^.sendCommand(CMDsetcoords,root,win); + t_writemode:=(xorput); + t_col:=currcol; + mouseoff;line(x1,y1,oldgridxm,oldgridym);mouseon; + while (not ms_gridmoved) and (zm=byte(altmethod)xor 1) do + mpos; + mouseoff;line(x1,y1,oldgridxm,oldgridym);mouseon; + if (zm=0)and(Gridxm=x1)and(Gridym=y1) then altmethod:=true; + end; + endsame:=firstrect.contains(gridxm,gridym); + if not endsame then begin + inc(linecount); + points^[linecount].x:=Gridxm; + points^[linecount].y:=Gridym; + if not (ms_doubleclicked)and(not keypressed) then begin + mouseoff; + t_writemode:=0; + t_col:=t_col xor backcol; + line(x1,y1,Gridxm,Gridym); + t_writemode:=xorput; + t_col:=t_col xor backcol; + mouseon; + x1:=Gridxm; + y1:=Gridym; + end; + stoprepeat; + altmethod:=true; + end; + end; + t_writemode:=(0); + getline:=linecount+1+(byte(endsame) shl 8); +End; + +Procedure getcircle(R:prect;stp:integer;var angle:real;win:delta_orth); + +var + + currcol:byte; + altmethod:boolean; + ydiff,xdiff:real; + + +Begin + currcol:=t_col; + angle:=0; + t_writemode:=(xorput); + with R^ do begin + x1:=gridxm;y1:=gridym; + x2:=1;y2:=1; + altmethod:=false; + while checkclicked(altmethod,zm) do Begin + mpos; + t_writemode:=0; + + + win^.sendCommand(CMDsetcoords,root,win); + t_writemode:=(xorput); + t_col:=currcol; + + if scan and smLEFTCTRL<>0 then + angle:=angle+(ms_xdiff / sensi) + else if scan and smLEFTSHIFT <>0 then begin + inc(x2,ms_xdiff); + inc(y2,ms_xdiff); + end else begin + inc(x2,ms_xdiff); + inc(y2,ms_ydiff); + end; + mouseoff;drawcircle(x1,y1,x2,y2,stp,angle);mouseon; + + while (not ms_gridmoved) and (zm=byte(altmethod)xor 1) do + mbutton; + mouseoff;drawcircle(x1,y1,x2,y2,stp,angle);mouseon; + + if (zm=0)and(gridxm=x1)and(gridym=y1) then altmethod:=stickymouse; + + End; + x1:=abs(x1); + x2:=abs(x2); + {make sure that 0 size squares are not possible} + if gridxm=x1 then inc(x2,2); + if gridym=y1 then inc(y2,2); + end; + t_writemode:=(0); +End; + +constructor delta_orth_.make(orient:byte;obj:edit_objtype); +begin + inherited make(-worldsize,-worldsize,worldsize,worldsize); + case orient of + {spin around -90ø's in the Yaxis to get into position} + Xaxis:LmAxisRotate(@transmat,0,1,0,pi/2); + {YRotate(@transmat,pi/2);} + {spin around 90ø's in the Xaxis to get into position} + Yaxis:LmXrotate(@transmat,-pi/2); + Zaxis:LmUnit(@transmat); + end; + editobject:=obj; + orientation:=orient; + xoff:=0;yoff:=0; +end; + +procedure delta_orth_.localspace(var x,y:integer); +begin + dec(x,x1+halfx-xoff); + dec(y,y1+halfy-yoff); +end; + +procedure delta_orth_.Globalspace(var x,y:integer); +begin + inc(x,x1+halfx-xoff); + inc(y,y1+halfy-yoff); +end; + +Procedure delta_orth_.do2d_3d(xp,yp:integer;filter:VectorReal;var dot:VectorReal);begin + localspace(xp,yp); + conv2d_3d(orientation,xp,yp,@filter,@dot); +end; + +Procedure delta_orth_.do3d_2d(dot:VectorReal;var x,y:integer);begin + conv3d_2d(orientation,@dot,x,y); + globalspace(x,y); +end; + +procedure delta_orth_.draw_boundingbox(xp,yp:integer); +var minx,miny,maxx,maxy:integer; +Begin + with editobject^ do begin + conv3d_2d(orientation,@min,minx,miny); + conv3d_2d(orientation,@max,maxx,maxy); + end; + case selected_mode of + SMresize_repos:drawbound(xp+minx,yp+miny,xp+maxx,yp+maxy); + SMrotate:rectangle_rotated(xp+minx,yp+miny,xp+maxx,yp+maxy,xp,yp,0); + SMdeform:begin end; + end; +end; + +{Procedure delta_orth_.draw_precalc; +begin + with editobject^ do begin + if maxpoints>0 then + load_orthview(orientation,x1+halfx+xoff,y1+halfy+yoff,scale); + end; +end;} + +Procedure delta_orth_.draw; +var lop:integer;xp,yp:integer; + gx,gy:integer; +begin + xp:=x1+halfx-xoff;yp:=y1+halfy-yoff; + with editobject^ do begin + if what_to_draw and draw_back<>0 then begin + t_fillcol:=backcol; + bar(x1,y1,x2,y2); + if (grid_on)and(scale>0.4) then begin + t_col:=15;{(gridcol);} + {hline(x1,x2,y1+halfy);} + gx:=round(gridsize.x*scale); + if (gx=0) then gx:=1; + gy:=round(gridsize.y*scale); + if (gy=0) then gy:=1; + dotgrid(x1+((halfx-xoff) mod gx), + y1+((halfy-yoff) mod gy), + gx,gy,1+(x2-x1) div gx,1+(y2-y1)div gy); + End; + t_col:=(red); + Drawx(xp,yp); + end; + + if (maxpoints>0) and (what_to_draw and draw_orth <>0 )then begin + if state and sfdrawnonce=0 then + doorth(orientation,xp,yp,scale); + if (what_to_draw and draw_orthlines<>0) then begin + t_col:=linecolour; + liner; + end; + if (what_to_draw and draw_orthnodes<>0) then begin + noder(drawallnodes); + end; + end; + if what_to_draw and draw_boundingboxstuff<>0 then + If (maxselect>0)and(maxpoints>0) then Begin + t_writemode:=(xorput);t_col:=(xorRed); + draw_boundingbox(xp,yp); + t_writemode:=(0); + End; + + if what_to_draw and draw_cursorstuff<>0 then begin + t_writemode:=(xorput);t_col:=(xorRed); + conv3d_2d(orientation,@crs,gx,gy); + drawcursor(xp+gx,yp+gy); + t_writemode:=(0); + end; + End; +end; + +procedure setscale(scaleval:real); +begin + if scaleval<>0 then + scale:=scaleval; + draworth; +end; + +var + angle:real; + +Procedure delta_orth_.docommand(command:word;params:pointer;divsize:integer); +const + LastMatrixOp:matrix3x4type_=(m00:1;m01:0;m02:0; + m10:0;m11:1;m12:0; + m20:0;m21:0;m22:1; + p:(x:0;y:0;z:0)); +var lop:word; + tmpobj:edit_objtype; + Snormal:VectorReal; + selectmode:byte; + +begin + with editobject^ do begin + if command<>CMDundo then begin + oldmaxpoints:=maxpoints; + oldmaxjoins:=maxjoins; + oldmaxpolys:=maxpolys; + end; + setmouseshape(1,1,hourglass); + {execute the command} + case command of + RANGEchangeselectSTART..RANGEchangeselectEND,CMDautocopyselected: + if (drawallnodes)and(maxselect>0) then begin + what_to_draw:=draw_boundingboxstuff; + drawobject; + what_to_draw:=draw_all; + end; + end; + case Command of + CMDcopyselection,CMDautocopyselected:if maxselect>0 then begin + lop:=0; + while (lop1 then begin + if boolean(hi(divsize))then + addpolygon(maxpoints,lo(divsize),PaDoubleSided+PAconnected,PCall) + else + addpolygon(maxpoints,lo(divsize),PaDoubleSided+PaOutlined,PCall); + for lop:=0 to lo(divsize)-1 do with vectorrealarray(params)^[lop] do + addvector(x,y,z); + end; + CMDeditsquare:mksquare(a.x,a.y,b.x,b.y,a.z,Currattrib or (PaDoubleSided+PaClockWise)); + CMDeditcube:mkcube(a.x,a.y,a.z,b.x,b.y,b.z,currattrib); + CMDeditDot:addvector(a.x,a.y,a.z); + CMDeditCircle:mkcircle(a.x,a.y,b.x,b.y,a.z,divsize,angle,PCall,Currattrib or (PaDoubleSided+PaClockWise)); + CMDeditcone:mkcone(a.x,a.y,b.x,b.y,a.z,b.z,divsize,angle,currattrib); + CMDeditCylinder:mkcylinder(a.x,a.y,b.x,b.y,b.x,b.y,a.z,b.z,divsize,angle,currattrib); + CMDeditSphere:mksphere(a.x,a.y,a.z,b.x,b.y,b.z,divsize,divsizez,angle,CurrAttrib); + CMDeditgrid: + case gridmode of + GMheightmap:if gridpic<>nil then + mkgridfrompic(a.x,a.y,b.x,b.y,a.z,gridpic,checkornot,currattrib or PaDoubleSided); + {else + gridmode:=GMflat;} + GMflat:mkgrid(a.x,a.y,b.x,b.y,a.z,GridX,GridY,false,checkornot,currattrib or PaDoubleSided); + GMsine:mkgrid(a.x,a.y,b.x,b.y,a.z,GridX,GridY,true,checkornot,currattrib or PaDoubleSided); + end; + + CMDeditrotate:begin + tmpobj:=new(edit_objtype,create(30,30,30)); + tmpobj^.mkcircle(a.x,a.y,b.x,b.y,a.z,divsize,angle,PCall,0); + extrudepath(tmpobj,CurrAttrib,Extrude); + dispose(tmpobj,done); + end; + CMDRotatedformX:rotateobj(Xaxis,rotsize,CurrAttrib); + CMDRotatedformY:rotateobj(Yaxis,rotsize,CurrAttrib); + CMDRotatedformZ:rotateobj(Zaxis,rotsize,CurrAttrib); + CMDselectclear:if maxselect>0 then begin + what_to_draw:=draw_boundingboxstuff; + drawobject; + clearselection; + + end else + ErrorLevel:=ERRnotselected; + CMDnew:begin + reset3d; + crs.moveto(0,0,0); + setscale(1); + end; + CMDmerge:merge; + CMDflipx:flip(Xaxis); + CMDflipy:flip(Yaxis); + CMDflipz:flip(Zaxis); + CMDselectall:selectall; + CMDnewselection:begin + if selectmodelevel=SMnodal then begin + + + if scan and smLEFTCTRL<>0 then + selectmode:=SMintersect + else if scan and smLEFTALT<>0 then + selectmode:=SMaddtolist + else + selectmode:=SMnewlist; + + + getselectlist(orientation,prect(params)^,selectmode) + end + else + getselectlistconnected(orientation,prect(params)^); + end; + + CMDdeleteselect:delete_select(DMall); + CMDdeletepolys:delete_select(DMpolys); + CMDdeletelines:delete_select(DMjoins); + + CMDaddpolygon:addpolygonbyref(select,maxselect,currattrib or PaDoubleSided+PaClockWise, + PCall or PCchecklines or PCcheckpolys); + CMDflipnorms:FlipSelectedNormals; + + CMDmkDoublesided:SetSelectedattrib(PaDoublesided,PAmodeTRUE); + CMDmkSinglesided:SetSelectedattrib(PaDoublesided,PAmodeFALSE); + CMDmkSmooth:SetSelectedattrib(PaSmooth,PAmodeTRUE); + CMDmkFlat:SetSelectedattrib(PaSmooth,PAmodeFALSE); + CMDmkOutlined:SetSelectedattrib(PaOutlined,PAmodeTRUE); + CMDmkSolid:SetSelectedattrib(PaOutlined,PAmodeFALSE); + CMDapplyColour:SetSelectedTexture(fgtexture); + CMDapplyattrib:SetSelectedattrib(CurrAttrib,PAmodeABS); + CMDapplyattribandcolour:begin + SetSelectedTexture(fgtexture); + SetSelectedattrib(CurrAttrib,PAmodeABS); + end; + CMDundo:begin + maxselect:=0; + fswap(maxpoints,oldmaxpoints,2); + fswap(maxjoins,oldmaxjoins,2); + fswap(maxpolys,oldmaxpolys,2); + end; + end; + end; + end; {end of command list} + {if there was an error then do this} + case ErrorLevel of + {if no errors were detected, draw the changes} + ERRnone:begin + {how to draw the changes} + case command of + {redraw whole object} + RANGEchangeselectSTART..RANGEchangeselectEND:begin + if (drawallnodes) then + what_to_draw:=draw_boundingboxstuff; + drawobject; + LmUnit(@LastMatrixOp); + + end; + RANGEchangecomSTART..RANGEchangecomEND,CMDload3dfile:drawobject; + {only redraw the 3d window and even then under conditions} + RANGEpolychangeSTART..RANGEpolychangeEND: + if render_mode>=CMDhlines then edviews[3]^.drawview; + else if (oldmaxpoints<>maxpoints)or(oldmaxjoins<>maxjoins)or(oldmaxpolys<>maxpolys) then begin + {draw each view, remove and replace 'xor' stuff} + if ((command=CMDautocopyselected)or(command=CMDcopyselection))and(not drawallnodes) then + drawobject + else begin + if (command<>CMDaddpolygon)and((command<>CMDcopyselection)and not(extrude)) then + draw_points_offset:=oldmaxpoints; + draw_lines_offset:=oldmaxjoins; + draw_polys_offset:=oldmaxpolys; + + for lop:=0 to 3 do begin + if (Command<>CMDcopyselection)and(Command<>CMDautocopyselected) then + what_to_draw:=draw_cursorstuff+draw_boundingboxstuff + else + what_to_draw:=draw_cursorstuff; + + edviews[lop]^.drawview; + what_to_draw:=draw_3dstuff; + edviews[lop]^.drawview; + what_to_draw:=draw_cursorstuff+draw_boundingboxstuff; + edviews[lop]^.drawview; + end; + end; + end; + end; + end; + ERRnovectors..ERRnopolys:begin + {out of memory undo} + maxpoints:=oldmaxpoints; + maxjoins:=oldmaxjoins; + maxpolys:=oldmaxpolys; + addmessage(0,0,'Sorry, object too large: out of memory.',memmessagePID,desktop); + end; + ERRnotselected:begin + addmessage(0,0,'Select some points using the select tool (the arrow).',selectmessagePID,desktop); + + end; + ERRoneselected:begin + addmessage(0,0,'You must select two or more points.',selectmessagePID,desktop); + end; + ERRparseerror:begin + addmessage(0,0,'Parse Error in 3d file.',selectmessagePID,desktop); + end; + ERRfileerror:begin AddMessage(0,0,'The file format is not understood.',fileerrorPID,desktop); + end; + end; + ErrorLevel:=Errnone; + {CMDDeleteJoins,CMDdeleteSelect,CMDmerge,CMDquaddivide,CMDtriangulate:begin + oldmaxpoints:=maxpoints; + oldmaxjoins:=maxjoins; + oldmaxpolys:=maxpolys; + end;} + + draw_points_offset:=0; + draw_lines_offset:=0; + draw_polys_offset:=0; + what_to_draw:=draw_all; + setmouseshape(1,1,arrow); + CTM:=@unitmatrix; + end; +end; + + +var +oldx,oldy:integer; + +Procedure Delta_orth_.handlevent(var event:tevent); +var pointslist:array[0..29] of pointtype; + points:trect absolute pointslist; + oldvp:trect; + oldcrs:VectorReal; + boundcode:shortint; + newmin,newmax:VectorReal; + CoordsList:CoordArray; + CoordsCube:Tcube_ absolute CoordsList; + tmpz:real; + temp:word; + ccirc:integer; + lop:byte; + Transmatrix:matrix3x4type_; + olddrawing_mode:word; + dot:integer; + px,py:integer; + + g:pointtype; + +{***************************************************************} +{loads up values that will later be used in transformations & does +selection code (calls the correct redraws in that section)} +procedure handle_repos; +var x,y,maxotherdot:integer;rotation:real; + lop:integer; + otherdot:array[0..30] of word; + tmpmatb:matrix3x4type_; + oldbounds:trect; + + {when moving a single node} + procedure drawotherdots(x,y:integer); + var lop:integer; + xb,yb:integer; + begin + mouseoff; + {if editobject^.thred^[dot].Nattrib and NAselected<>0 then + t_col:=nodeselectedcolour xor backcol + else} + t_col:=nodecolour xor backcol; + + drawbytes(x-3,y-2,@nodepatt,5); + t_col:=(xorGreen); + if maxotherdot>0 then + For lop:=0 to maxotherdot-1 do Begin + do3d_2d(editobject^.thred^[otherdot[lop]],xb,yb); + line(x,y,xb,yb); + end; + mouseon; + end; + +begin + with editobject^,points do begin + x1:=xm;y1:=ym; + localSpace(x1,y1); + dot:=getnode(orientation,x1,y1,not drawallnodes); + + {if you are moving a node then do this....} + if dot>-1 then begin + maxotherdot:=0; + lop:=0; + if maxjoins>0 then + while (lop0 do begin + mpos; + drawotherdots(oldgridxm+x,oldgridym+y); + while (not (ms_gridmoved))and(zm<>0) do mpos; + drawotherdots(oldgridxm+x,oldgridym+y); + end; + {load up 'points.x1' and 'points.x2' with new xy position} + x1:=gridxm+x; + y1:=gridym+y; + + t_writemode:=0; + drawing_mode:=CMDmovenode; + end else begin + {do selected group stuff} + do3d_2d(min,x1,y1); + do3d_2d(max,x2,y2); + + {do you resize/move or rotate? load up 'transmat in this block'} + if (scan and smLEFTCTRL=0)and(scan and smLEFTALT=0) then + case selected_mode of + SMresize_repos:begin + oldbounds:=points; + if maxselect>0 then + boundcode:=resizebounds(x1,y1,x2,y2,divisionsize) + else + boundcode:=0; + if (boundcode>0) then begin + do2d_3d(x1,y1,min,newmin); + do2d_3d(x2,y2,max,newmax); + {if just moving, not resizin or rotaing} + if boundcode=middle then with min do begin + newmin.sub(x,y,z); + with newmin do LmTrans(@transmatrix,x,y,z); + end else + {else here, load matrix to stretch} + LmStretch(@transmatrix,min,max,newmin,newmax); + if zm=3 then begin + LmUnit(@tmpmatb); + transmatrix.sub(@tmpmatb); + transmatrix.divide(divisionsize); + transmatrix.add(@tmpmatb); + end; + end; + end; + SMrotate:begin + {rotateSquare will return 0 if there is no rotation} + if maxselect>0 then begin + do3d_2d(crs,g.x,g.y); + + boundcode:=rotatesquare(x1,y1,x2,y2,g.x,g.y, + rotation,divisionsize); + end else boundcode:=0; + if (boundcode>0) then begin + if zm=3 then + rotation:=rotation / divisionsize; + case orientation of + Xaxis:LmRotateAround(@transmatrix,rotation,0,0,crs); + Yaxis:LmRotateAround(@transmatrix,0,rotation,0,crs); + Zaxis:LmRotateAround(@transmatrix,0,0,-rotation,crs); + end; + end; + end; + SMdeform:begin + LmUnit(@TransMatrix); + end; + end; + {'transmatix' now loaded with relevant information} + {user select with mouse} + {if no moving of single node or click in bounding box then...} + if (boundcode<=0)or(scan and smLEFTCTRL<>0)or(scan and smLEFTALT<>0) then begin + t_col:=backcol xor red;T_writemode:=xorput; + getsquare(@points,@self); + t_writemode:=0; + if zm<>3 then begin + SC.viewport:=oldvp; + localSpace(points.x1,points.y1); + localSpace(points.x2,points.y2); + docommand(CMDnewselection,@points,0); + end; + stoprepeat; + end else begin + {set up move mode} + if zm=3 then + drawing_mode:=CMDcopyselection + else + drawing_mode:=CMDtransformselection; + t_writemode:=0; + end; + end; + end; +end; + +{***************************************************************} + +var mousepoint:vectorreal; +newscale:real; + +begin + inherited handlevent(event); + edit_orientation:=orientation; + olddrawing_mode:=drawing_mode; + with event do begin + if what and EvMousepressed<>0 then begin + if what and Evmousemove<>0 then + sendCommand(CMDsetcoords,root,@self); + {this defines the direction in which polygon points are defined} + if gridlock then Begin + Xgrid_size:=round(gridsize.x*scale);Ygrid_size:=round(gridsize.y*scale); + if (ygrid_size=0) then ygrid_size:=1; + if (xgrid_size=0) then xgrid_size:=1; + Xgrid_corner:=x1+((xoff+halfx) mod Xgrid_size); + Ygrid_corner:=y1+((yoff+halfy) mod Ygrid_size); + mpos; + End; + with points do case zm of + 1,3:begin + {clip to SC.viewport} + oldvp:=SC.viewport; + SC.viewport.intersect(self); + SC.viewport.intersect(owner^.owner^); + t_col:={fgcol xor backcol}xorgreen; + {get 2d input from user} + case drawing_mode of + CMDeditsquare,CMDeditcube,CMDeditgrid,CMDedittext:begin + getsquare(@points,@self); + localspace(x1,y1); + localspace(x2,y2); + end; + CMDeditselect:with editobject^ do begin + {selection/copying is a special case.} + {all these handles are the same for drawn objects} + handle_repos; + end; + CMDeditliner:begin + ccirc:=getline(@pointslist,29,@self); + for lop:=0 to lo(ccirc)-1 do with pointslist[lop] do + localspace(x,y); + end; + CMDeditdot:begin + x1:=xm;y1:=ym; + localspace(x1,y1); + end; + CMDeditcone,CMDeditcircle,CMDeditcylinder,CMDeditsphere,CMDeditrotate:begin + case drawing_mode of + CMDeditcone:ccirc:=conesize; + CMDeditcircle:ccirc:=circsize; + CMDeditcylinder:ccirc:=cylindersize; + CMDeditsphere:begin ccirc:=spheresize.x;divsizez:=spheresize.y;end; + CMDeditrotate:ccirc:=rotsize; + end; + getcircle(@points,ccirc,angle,@self); + + + localspace(x1,y1); + end; + end; + {un clip} + SC.viewport:=oldvp; + if (drawing_mode<>CMDeditselect) then + if ((zm<>3) or (drawing_mode=CMDcopyselection)) then begin + with CoordsCube do begin + {covert to 3d object space {scaling, cursor positioning} + case orientation of + Xaxis:tmpz:=-crs.x; + Yaxis:tmpz:=-crs.y; + Zaxis:tmpz:=crs.z; + end; + if drawing_mode=CMDeditliner then begin + for lop:=0 to lo(ccirc)-1 do with pointslist[lop] do + coordslist[lop].moveto(x/scale,y/scale,tmpz); + end else begin + a.moveto(x1/scale,y1/scale,tmpz); + b.moveto(x2/scale,y2/scale,tmpz); + {setup parameters for 'docommand'} + case drawing_mode of + CMDmovenode:begin + ccirc:=dot; + do2d_3d(points.x1,points.y1,editobject^.thred^[dot],a); + end; + {set z position for corners} + CMDeditcube:begin + tmpz:=((a.x-b.x)+(a.y-b.y))/4; + a.z:=a.z-tmpz; + b.z:=b.z+tmpz; + end; + {set radius of sphere} + CMDeditsphere:b.z:=(b.x+b.y)/2; + {set z start and end positions} + CMDeditcone,CMDeditcylinder:begin + tmpz:=(b.x+b.y)/2; + a.z:=a.z-tmpz; + b.z:=b.z+tmpz; + end; + end; + end; + end;{with coords cube} + {--All changes to the 3d database occur in this section--} + + {case statement for different paramaters} + case drawing_mode of + CMDcopyselection,CMDtransformselection:docommand(drawing_mode,@transmatrix,divisionsize); + else begin + docommand(drawing_mode,@CoordsCube,ccirc); + end; + end; + end;{if zm<>3} + stoprepeat; + end; + 2:if (oldx<>xm)or(oldy<>ym) then begin + oldx:=xm; + oldy:=ym; + what_to_draw:=draw_cursorstuff; + drawobject; + with points do begin + x1:=gridxm;y1:=gridym; + do2d_3d(x1,y1,crs,crs); + end; + drawobject; + end; + end; + end else + if what and Evmousemove<>0 then begin + px:=xm;py:=ym; + + if (scan and ZOOMKEYS<>0) and (scan and ZOOMKEYS<>smLEFTCTRL)then begin + mouseoff; + while scan and ZOOMKEYS<>0 do begin + mpos; + if (px<>xm) or(py<>ym) then begin + if scan and ZOOMKEYS=ZOOMKEYS then + begin + newscale:=(ms_ydiff*scale)/100; + state:=state and not sfvisible; + + setoffsets(xoff,yoff); + state:=state or sfvisible; + setscale(scale+newscale); + end + else if scan and ZOOMKEYS=smLEFTSHIFT then + setoffsets(xoff-ms_xdiff,yoff-ms_ydiff); + if (px<>xm) or(py<>ym) then setmousepos(px,py); + end; + end; + mouseon; + end; + end; + what_to_draw:=draw_all; + if gridlock then Begin + Xgrid_size:=0;Ygrid_size:=0; + End; + drawing_mode:=olddrawing_mode; + + end; +end; + + + + +end. diff --git a/TMATHS.PAS b/TMATHS.PAS new file mode 100644 index 0000000..704aa60 --- /dev/null +++ b/TMATHS.PAS @@ -0,0 +1,929 @@ +Unit Tmaths; + +INTERFACE +uses sincos,strings; +const +MTpreconcat=1; +MTpostconcat=2; +MTreplace=3; + +type +BasicUnit=real{single}; +matrix3x4type=^matrix3x4type_; +vectorintptr=^vectorint; + +pointreal=object + x,y:real; + function length:real; + procedure normalize; + procedure moveto(x_,y_:real); + procedure sub(var p:pointreal); + procedure add(var p:pointreal); + procedure mul(var p:real); + procedure divi(var p:real); +end; + +vectorint=object + x,y,z:longint; + + function equals(Vector:Vectorint):boolean; + procedure moveto(x_,y_,z_:longint); + procedure add(xa,ya,za:longint); + procedure sub(xs,ys,zs:longint); + procedure divide(divby:longint); + procedure multiply(multby:longint); + procedure multmatrix(mat:matrix3x4type); + Procedure unitvec(range:longint); +end; + +vectorintsmallptr=^vectorintsmall; + +vectorintsmall=object + x,y,z:integer; + function equals(Vector:VectorIntSmall):boolean; + procedure moveto(x_,y_,z_:Integer); + procedure add(xa,ya,za:Integer); + procedure sub(xs,ys,zs:Integer); + procedure divide(divby:Integer); + procedure multiply(multby:Integer); + procedure multmatrix(mat:matrix3x4type); + Procedure unitvec(range:integer); +end; + +VectorReal=object + x,y,z:basicunit; + function equals(const VectorReal:VectorReal):boolean; + procedure add(tx,ty,tz:BasicUnit); + procedure sub(tx,ty,tz:BasicUnit); + Procedure Divide(d:BasicUnit); + Procedure multiply(m:BasicUnit); + Procedure multmatrixinto(mat:matrix3x4type;multby:VectorReal); + procedure multmatrixinto_notrans(mat:matrix3x4type;multby:VectorReal); + Procedure multmatrix(mat:matrix3x4type); + Procedure unitvec(range:basicunit); + procedure moveto(tx,ty,tz:basicunit); +End; + +vectorrealptr=^vectorreal; + +usemattype=^usemattype_; +usemattype_=array[0..3,0..3] of basicunit; + +matrix3x4type_=object + m00,m01,m02, + m10,m11,m12, + m20,m21,m22:basicunit; {rotation fields} + p:VectorReal; + + + procedure sub(mat:matrix3x4type); + procedure add(mat:matrix3x4type); + procedure divide(divby:basicunit); + procedure multiply(mat:matrix3x4type;mode:byte); + procedure multiplyinto(B,A:matrix3x4type); + procedure invert; + procedure invertnotrans; + procedure transpose; +end; + +procedure gettricentre(xa,ya,xb,yb,xc,yc:integer; var retx,rety:integer); +procedure getlinecentre(xa,ya,xb,yb:integer;var retx,rety:integer); +function lineintersect(x1a,y1a,x2a,y2a,x1b,y1b,x2b,y2b:integer):boolean; +function linelength(x1,y1,x2,y2:integer):integer; +function linelengthrl(x1,y1,x2,y2:real):real; +function linelength3d(x1,y1,z1,x2,y2,z2:longint):longint; +function linelength3drl(x1,y1,z1,x2,y2,z2:real):real; +function LongDiv(X: Longint; Y: Integer): Integer; +function longmul(X, Y: integer): Longint; +Function itoa(num:longint):string; +Function pitoa(num:longint;instr:pchar):pchar; +function tstrcat(dst,src:pchar):pchar; +function tstrcat_pascal(dst:pchar;src:string):pchar; +function tstrend(src:pchar):pchar; +function charcat(dst:pchar;ch:char):pchar; + + +Function atoi(numstr:string):longint; +Function ftoa(num:real;i,j:byte):string; +function atof(numstr:string):real; +Function isqrt(a:longint):longint; +function bound(val,r1,r2:longint):longint; +Function smaller(n1,n2:longint):longint; +Function bigger(n1,n2:longint):longint; +Function Power(num:longint;raise:integer):longint; +Function numlength(num:longint):byte; +Function Random32(range:longint):longint; + +Procedure CalcSurfNormal(p1,p2,p3:VectorReal;var pn:VectorReal); +Function Dot(var p1,p2:VectorReal):basicunit; +Procedure LMAxisRotate(mat:matrix3x4type;x,y,z,theta:real); +Procedure LmTrans(mat:matrix3x4type;xt,yt,zt:BasicUnit); +Procedure LmRotTrans(mat:matrix3x4type;rx,ry,rz:real;xt,yt,zt:basicunit); +Procedure LmUnit(mat:matrix3x4type); +Procedure LmRotUnit(mat:matrix3x4type); +Procedure LmFlip(mat:matrix3x4type); +Procedure LmRotateAround(mat:matrix3x4type;rx,ry,rz:real;vec:VectorReal); +Procedure LmStretch(mat:matrix3x4type;oldmin,oldmax,newmin,newmax:VectorReal); +Procedure LmScale(mat:matrix3x4type;x,y,z:basicunit); +Procedure LmRotate(mat:matrix3x4type;rx,ry,rz:real); +Procedure LmXrotate(mat:matrix3x4type;r:real); +Procedure LmYrotate(mat:matrix3x4type;r:real); +Procedure LmZrotate(mat:matrix3x4type;r:real); +Procedure FSwap(Var s,d; L:byte); + +var +UnitMatrix:matrix3x4type_; +const +maxangle=sincos.maxangle; +maxangle_mask=maxangle-1; +{UnitMatrix:matrix3x4type_=(m00:1;m01:0;m02:0; + m10:0;m11:1;m12:0; + m20:0;m21:0;m22:1; + p:(x:0;y:0;z:0));} + + +IMPLEMENTATION +{assemblerize this routine} +var +swaptemp:longint; +{swaps two variables of arbitary length, inline into the code} +Procedure FSwap(Var s,d; L:byte); +begin + move(s,swaptemp,l); + move(d,s,l); + move(swaptemp,d,l); +end; + + +{////VectorReal PROCEDURES///////////////////////////////////} + +Function VectorReal.equals(const VectorReal:VectorReal):boolean; +begin + equals:=(VectorReal.x=x)and(VectorReal.y=y)and(VectorReal.z=z); +end; + +procedure VectorReal.multmatrixinto(mat:matrix3x4type;multby:VectorReal); +begin + with multby,mat^ do begin + self.x:=(m00*x +m01*y +m02*z)+p.x; + self.y:=(m10*x +m11*y +m12*z)+p.y; + self.z:=(m20*x +m21*y +m22*z)+p.z; + end; +end; + +procedure VectorReal.multmatrixinto_notrans(mat:matrix3x4type;multby:VectorReal); +begin + with multby,mat^ do begin + self.x:=(m00*x +m01*y +m02*z); + self.y:=(m10*x +m11*y +m12*z); + self.z:=(m20*x +m21*y +m22*z); + + end; +end; + +procedure VectorReal.multmatrix(mat:matrix3x4type); +var multby:VectorReal; +begin + multby:=self; + with multby,mat^ do begin + self.x:=(m00*x +m01*y +m02*z)+p.x; + self.y:=(m10*x +m11*y +m12*z)+p.y; + self.z:=(m20*x +m21*y +m22*z)+p.z; + end; +end; + +procedure VectorReal.add(tx,ty,tz:BasicUnit); +Begin + x:=x+tx;y:=y+ty;z:=z+tz; +end; + +procedure VectorReal.sub(tx,ty,tz:BasicUnit); +Begin + x:=x-tx;y:=y-ty;z:=z-tz; +end; + +{normalize to a range} +Procedure VectorReal.unitvec(range:basicunit); +var uli:BasicUnit; +begin + Uli:=sqrt(abs( (x*x)+ (y*y)+ (z*z))); + if uli=0 then uli:=1; + x:=(x *range)/ uli; + y:=(y *range)/ uli; + z:=(z *range)/ uli; +end; + +Procedure VectorReal.Divide(D:BasicUnit); +begin + if D<>0 then begin + X:=X / D; + Y:=Y / D; + Z:=Z / D; + end; +end; + +Procedure VectorReal.multiply(m:BasicUnit); +begin + X:=X * M; + Y:=Y * M; + Z:=Z * M; +end; + +Procedure VectorReal.moveto(tx,ty,tz:basicunit); +begin + x:=tx;y:=ty;z:=tz; +end; + +procedure pointreal.moveto(x_,y_:real); +begin + x:=x_; + y:=y_; +end; + +function pointreal.length:real; +begin + length:=sqrt((x*x)+(y*y)); +end; + +procedure pointreal.normalize; +var uli:real; +begin + uli:=length; + x:=x/uli; + y:=y/uli; +end; + +procedure pointreal.sub(var p:pointreal); +begin + x:=x-p.x; + y:=y-p.y; +end; + +procedure pointreal.add(var p:pointreal); +begin + x:=x+p.x; + y:=y+p.y; +end; + +procedure pointreal.divi(var p:real); +begin + x:=x / p; + y:=y / p; +end; + +procedure pointreal.mul(var p:real); +begin + x:=x * p; + y:=y * p; +end; + + +{////VECTOR INT///////////////////////////////////////////} + +procedure VectorInt.multmatrix(mat:matrix3x4type); +var new:VectorInt; +begin + {if selected then begin} + new:=self; + with new,mat^ do begin + self.x:=round(m00*x + m10*y + m20*z +p.x); + self.y:=round(m01*x + m11*y + m21*z +p.y); + self.z:=round(m02*x + m12*y + m22*z +p.z); + end; + {end;} +end; + +Procedure VectorInt.unitvec(range:longint); +var uli:longint; +begin + Uli:=(isqrt(abs( (x*x)+ (y*y)+ (z*z) ))); + if range<>1 then + multiply(range); + if uli<>0 then + divide(uli); +end; + +Procedure VectorInt.moveto(x_,y_,z_:longint); +begin + x:=x_;y:=y_;z:=z_; +end; + +Procedure VectorInt.divide(divby:longint); +begin + x:=x div divby;y:=y div divby;z:=z div divby; +end; + +Procedure VectorInt.multiply(multby:longint); +begin + x:=x*multby;y:=y*multby;z:=z*multby; +end; + +procedure VectorInt.add(xa,ya,za:longint); +begin + inc(x,xa);inc(y,ya);inc(z,za); +end; + +procedure VectorInt.sub(xs,ys,zs:longint); +begin + dec(x,xs);dec(y,ys);dec(z,zs); +end; + +Function vectorint.equals(vector:vectorint):boolean; +begin + equals:=(vector.x=x)and(vector.y=y)and(vector.z=z); +end; +{////VECTOR INT Small///////////////////////////////////////////} + +procedure VectorIntSmall.multmatrix(mat:matrix3x4type); +var new:VectorIntSmall; +begin + {if selected then begin} + new:=self; + with new,mat^ do begin + self.x:=round(m00*x + m10*y + m20*z +p.x); + self.y:=round(m01*x + m11*y + m21*z +p.y); + self.z:=round(m02*x + m12*y + m22*z +p.z); + end; + {end;} +end; + +Procedure VectorIntSmall.unitvec(range:integer); +var uli:integer; +begin + Uli:=(isqrt(abs( (x*x)+ (y*y)+ (z*z) ))); + if range<>1 then + multiply(range); + if uli<>0 then + divide(uli); +end; + +Procedure VectorIntSmall.moveto(x_,y_,z_:integer); +begin + x:=x_;y:=y_;z:=z_; +end; + +Procedure VectorIntSmall.divide(divby:integer); +begin + x:=x div divby;y:=y div divby;z:=z div divby; +end; + +Procedure VectorIntSmall.multiply(multby:integer); +begin + x:=x*multby;y:=y*multby;z:=z*multby; +end; + +procedure VectorIntSmall.add(xa,ya,za:integer); +begin + inc(x,xa);inc(y,ya);inc(z,za); +end; + +procedure VectorIntSmall.sub(xs,ys,zs:integer); +begin + dec(x,xs);dec(y,ys);dec(z,zs); +end; + +Function VectorIntSmall.equals(vector:VectorIntSmall):boolean; +begin + equals:=(vector.x=x)and(vector.y=y)and(vector.z=z); +end; + + +{////MATRIX PROCEDURES///////////////////////////////////} + +Procedure LMAxisRotate(mat:matrix3x4type;x,y,z,theta:real); +var +c,s,t,txy,txz,tyz,sx,sy,sz:real; +begin + c:=cos(theta);s:=sin(theta);t:=1-c; + txy:=t*x*y;txz:=t*x*z;tyz:=t*y*z; + sx:=s*x;sy:=s*y;sz:=s*z; + with mat^ do begin + m00:=t*x*x+c; m01:=txy*sz; m02:=txz-sy; + m10:=txy-sz; m11:=t*y*y+c; m12:=tyz+sx; + m20:=txz+sy; m21:=tyz-sx; m22:=t*z*z+c; + p.moveto(0,0,0); + end; +end; + +Procedure LmRotTrans(mat:matrix3x4type;rx,ry,rz:real;xt,yt,zt:basicunit); +var precalc:basicunit; + tmpmat:matrix3x4type_; +begin + with mat^ do begin + LmXrotate(mat,rx); + LmYrotate(@tmpmat,ry); + multiply(@tmpmat,MTpostconcat); + LmZrotate(@tmpmat,rz); + multiply(@tmpmat,MTpostconcat); + + {m00:=cos(rz]*cos(ry]; + precalc:=cos(rz]* -sin(ry]; + m01:=precalc *-sin(rx] +sin(rz]*cos(rx]; + m02:=precalc * cos(rx] + sin(rz]*sin(rx]; + + m10:=-sin(rz] * cos(ry]; + precalc:=-sin(rz] * -sin(ry]; + m11:=precalc * -sin(rx] + cos(rz] * cos(rx]; + m12:=precalc * -sin(ry] * cos(rx] + cos(rz] * sin(rx]; + + m20:=sin(ry] ; + m21:=cos(ry]* -sin(rx] ; + m22:=cos(ry]* cos(rx];} + + + p.moveto(xt,yt,zt); + end; +end; + +Procedure LmXrotate(mat:matrix3x4type;r:real); +begin + + with mat^ do begin + m00:=1; m01:=0; m02:=0; + m10:=0; m11:=cos(r); m12:=sin(r); + m20:=0; m21:=-sin(r); m22:=cos(r); + p.moveto(0,0,0); + end; +end; +Procedure LmYrotate(mat:matrix3x4type;r:real); +begin + + with mat^ do begin + m00:=cos(r); m01:=0; m02:=-sin(r); + m10:=0; m11:=1; m12:=0; + m20:=sin(r); m21:=0; m22:=cos(r); + p.moveto(0,0,0); + end; +end; + +Procedure LmZrotate(mat:matrix3x4type;r:real); +begin + + + with mat^ do begin + m00:=cos(r); m01:=sin(r); m02:=0; + m10:=-sin(r); m11:=cos(r); m12:=0; + m20:=0; m21:=0 ; m22:=1; + p.moveto(0,0,0); + end; +end; + +Procedure LmRotate(mat:matrix3x4type;rx,ry,rz:real); +begin + LmRotTrans(mat,rx,ry,rz,0,0,0); +end; + +Procedure LmRotateAround(mat:matrix3x4type;rx,ry,rz:real;vec:VectorReal); +var tmpmat:matrix3x4type_; +begin + LmTrans(mat,-vec.x,-vec.y,-vec.z); + LmRottrans(@tmpmat,rx,ry,rz,0,0,0); + mat^.multiply(@tmpmat,MTpostconcat); + LmTrans(@tmpmat,vec.x,vec.y,vec.z); + mat^.multiply(@tmpmat,MTpostconcat) +end; + +Procedure LmStretch(mat:matrix3x4type;oldmin,oldmax,newmin,newmax:VectorReal); +var multby:VectorReal; + tmpmat:matrix3x4type_; +begin + multby:=oldmax; + multby.sub(oldmin.x,oldmin.y,oldmin.z); + with multby do begin + if x=0 then x:=1;x:=(newmax.x-newmin.x)/x; + if y=0 then y:=1;y:=(newmax.y-newmin.y)/y; + if z=0 then z:=1;z:=(newmax.z-newmin.z)/z; + end; + with mat^ do begin + m00:=multby.x; m01:=0; m02:=0; + m10:=0; m11:=multby.y; m12:=0; + m20:=0; m21:=0; m22:=multby.z; + p.x:=(-oldmin.x)*multby.x+newmin.x; + p.y:=(-oldmin.y)*multby.y+newmin.y; + p.z:=(-oldmin.z)*multby.z+newmin.z; + end; +end; + +Procedure LmTrans(mat:matrix3x4type;xt,yt,zt:basicunit); +begin + with mat^ do begin + m00:=1;m01:=0;m02:=0; + m10:=0;m11:=1;m12:=0; + m20:=0;m21:=0;m22:=1; + p.x:=xt;p.y:=yt;p.z:=zt; + end; +end; + +Procedure LmRotUnit(mat:matrix3x4type); +begin + with mat^ do begin + m00:=1; m01:=0; m02:=0; + m10:=0; m11:=1; m12:=0; + m20:=0; m21:=0; m22:=1; + end; +end; + + +Procedure LmUnit(mat:matrix3x4type); +begin + with mat^ do begin + m00:=1; m01:=0; m02:=0; + m10:=0; m11:=1; m12:=0; + m20:=0; m21:=0; m22:=1; + p.x:=0; p.y:=0; p.z:=0; + end; +end; +Procedure LmFlip(mat:matrix3x4type); +begin + with mat^ do begin + m00:=0; m01:=0; m02:=1; + m10:=0; m11:=1; m12:=0; + m20:=1; m21:=0; m22:=0; + p.x:=0; p.y:=0; p.z:=0; + end; +end; + +Procedure LmScale(mat:matrix3x4type;x,y,z:basicunit); +begin + with mat^ do begin + m00:=x; m01:=0; m02:=0; + m10:=0; m11:=y; m12:=0; + m20:=0; m21:=0; m22:=z; + p.x:=0; p.y:=0; p.z:=0; + end; +end; + +procedure matrix3x4type_.add(mat:matrix3x4type); +begin + m00:=m00+mat^.m00; m01:=m01+mat^.m01; m02:=m02+mat^.m02; + m10:=m10+mat^.m10; m11:=m11+mat^.m11; m12:=m12+mat^.m12; + m20:=m20+mat^.m20; m21:=m21+mat^.m21; m22:=m22+mat^.m22; + p.add(mat^.p.x,mat^.p.y,mat^.p.z); +end; + +procedure matrix3x4type_.sub(mat:matrix3x4type); +begin + m00:=m00-mat^.m00; m01:=m01-mat^.m01; m02:=m02-mat^.m02; + m10:=m10-mat^.m10; m11:=m11-mat^.m11; m12:=m12-mat^.m12; + m20:=m20-mat^.m20; m21:=m21-mat^.m21; m22:=m22-mat^.m22; + p.sub(mat^.p.x,mat^.p.y,mat^.p.z); +end; + +procedure matrix3x4type_.divide(divby:basicunit); +begin + if divby<>0 then begin + m00:=m00/divby; m01:=m01/divby; m02:=m02/divby; + m10:=m10/divby; m11:=m11/divby; m12:=m12/divby; + m20:=m20/divby; m21:=m21/divby; m22:=m22/divby; + p.divide(divby); + end; +end; + +procedure matrix3x4type_.invert; +var tmppx,tmppy:basicunit; + +begin + transpose; + tmppx:=p.x;tmppy:=p.y; + p.x:=(-m00*tmppx)+(-m01*tmppy)+(-m02*p.z); + p.y:=(-m10*tmppx)+(-m11*tmppy)+(-m12*p.z); + p.z:=(-m20*tmppx)+(-m21*tmppy)+(-m22*p.z); +end; + +procedure matrix3x4type_.invertnotrans; +begin + transpose; + p.moveto(0,0,0); +end; + +procedure matrix3x4type_.transpose; +var tmpmat:matrix3x4type_; +begin + tmpmat:=self; + self.m01:=tmpmat.m10; + self.m02:=tmpmat.m20; + self.m10:=tmpmat.m01; + self.m12:=tmpmat.m21; + self.m20:=tmpmat.m02; + self.m21:=tmpmat.m12; +end; + +procedure matrix3x4type_.multiply(mat:matrix3x4type;mode:byte); +var A:matrix3x4type_; +Begin + + A:=self; + {multiplyinto(@a,@unitmatrix);} + + case mode of + MTpostconcat:begin + multiplyinto(@a,mat); + end; + MTpreconcat:begin + multiplyinto(mat,@a); + end; + MTreplace:Self:=mat^; + end; +end; + +procedure matrix3x4type_.multiplyinto(B,A:matrix3x4type); +var +i,j,k:byte; +Begin + with B^ do begin + self.m00:=(A^.m00*m00 + A^.m01*m10 + A^.m02*m20); + self.m10:=(A^.m10*m00 + A^.m11*m10 + A^.m12*m20); + self.m20:=(A^.m20*m00 + A^.m21*m10 + A^.m22*m20); + + self.m01:=(A^.m00*m01 + A^.m01*m11 + A^.m02*m21); + self.m11:=(A^.m10*m01 + A^.m11*m11 + A^.m12*m21); + self.m21:=(A^.m20*m01 + A^.m21*m11 + A^.m22*m21); + + self.m02:=(A^.m00*m02 + A^.m01*m12 + A^.m02*m22); + self.m12:=(A^.m10*m02 + A^.m11*m12 + A^.m12*m22); + self.m22:=(A^.m20*m02 + A^.m21*m12 + A^.m22*m22); + + + self.p.x:=(A^.m00*p.x + A^.m01*p.y + A^.m02*p.z)+A^.p.x; + self.p.y:=(A^.m10*p.x + A^.m11*p.y + A^.m12*p.z)+A^.p.y; + self.p.z:=(A^.m20*p.x + A^.m21*p.y + A^.m22*p.z)+A^.p.z; + end; +end; + +{returns the dot product between two vectors} +Function Dot(var p1,p2:VectorReal):basicunit; +Begin + dot:=((P1.X*P2.X + P1.Y*P2.Y + P1.Z*P2.Z)); +end; + +Procedure CalcSurfNormal(p1,p2,p3:VectorReal;var pn:VectorReal); +Begin + {make magnitude Nodes, P2 being the base} + {make magnitude Nodes, P2 being the base} + P3.sub(P2.X,P2.Y,P2.Z); + P1.sub(P2.X,P2.Y,P2.Z); + pn.x:=(p1.y*p3.z) - (p1.z*p3.y); + pn.y:=(p1.z*p3.x) - (p1.x*p3.z); + pn.z:=(p1.x*p3.y) - (p1.y*p3.x); + pn.unitvec(1); +end; + +{returns number of digits in a number} + +Function numlength(num:longint):byte; +var count:byte; +begin + if num=0 then numlength:=1 else begin + count:=0; + while num<>0 do begin + num:=num div 10; + inc(count); + end; + numlength:=count; + end; +end; + +Function Power(num:longint;raise:integer):longint; +var tmp:longint; +begin + tmp:=num; + if raise>0 then begin + for raise:=1 to raise-1 do + num:=num*tmp; + Power:=num; + end else power:=1; +end; + +function bound(val,r1,r2:longint):longint; +begin + if val>r2 then val:=r2; + if valn2 then Bigger:=n1 + else + Bigger:=n2; +end; + +function LongDiv(X: Longint; Y: Integer): Integer; +begin +inline($59/$58/$5A/$F7/$F9); +end; + +Function atoi(numstr:string):longint; +var lop:byte; + multby,numcount:longint; +begin + multby:=1; + numcount:=0; + for lop:=length(numstr) downto 1 do begin + inc(numcount,(ord(numstr[lop])-ord('0'))*multby); + multby:=multby*10; + end; + atoi:=numcount; +end; + +Function itoa(num:longint):string; +var lop,numlen,numcount,dot,powerlop:byte; + precalc,powered:longint; + tmp:string; +begin + {str(num,tmp);} + tmp:=''; + dot:=0; + numlen:=numlength(num)-1; + numcount:=numlen; + if num<0 then begin tmp:=tmp+'-'; num:=-num; end; + for lop:=0 to numlen do begin + powered:=power(10,numcount); + precalc:=num div powered; + tmp:=tmp+char(precalc+byte('0')); + dec(num,precalc * powered); + dec(numcount); + end; + itoa:=tmp; +end; + +function tstrend(src:pchar):pchar; +begin + while (src^<>#0) do + inc(src); + + tstrend:=src; +end; + +function tstrcat_pascal(dst:pchar;src:string):pchar; +var i:integer; +begin + tstrcat_pascal:=dst; + while (dst^<>#0) do + inc(dst); + for i:=1 to byte(src[0]) do begin + dst^:=src[i]; + inc(dst); + end; + dst^:=#0; +end; + + +function tstrcat(dst,src:pchar):pchar; +begin + tstrcat:=dst; + while (dst^<>#0) do + inc(dst); + while (src^<>#0) do begin + + dst^:=src^; + inc(dst); + inc(src); + end; + dst^:=#0; +end; + +function charcat(dst:pchar;ch:char):pchar; +var last:array [0..1] of char; +begin + charcat:=dst; + while (dst^<>#0) do + inc(dst); + dst^:=ch; + inc(dst); + dst^:=#0; +end; + +Function pitoa(num:longint;instr:pchar):pchar; +var lop,numlen,numcount,dot,powerlop:byte; + precalc,powered:longint; + tmp:pchar; +begin + tmp:=instr; + dot:=0; + numlen:=numlength(num)-1; + numcount:=numlen; + {if num<0 then begin tmp^:='-'; num:=-num; inc(tmp);end;} + if num<0 then begin charcat(tmp,'-'); num:=-num; end; + for lop:=0 to numlen do begin + powered:=power(10,numcount); + precalc:=num div powered; + {tmp^:=char(precalc+byte('0')); + inc(tmp);} + charcat(tmp,char(precalc+byte('0'))); + dec(num,precalc * powered); + dec(numcount); + end; + {tmp^:=#0;} + pitoa:=instr; +end; + +Function ftoa(num:real;i,j:byte):string; +var temp:string; +Begin + str(num:i:j,temp);ftoa:=temp; +end; + +function atof(numstr:string):real; +var lop:byte; + numcount,multby:real; +begin + multby:=1; + numcount:=0; + + for lop:=length(numstr) downto 1 do begin + case(numstr[lop]) of + '0'..'9':begin + numcount:=numcount+(ord(numstr[lop])-ord('0'))*multby; + multby:=multby*10; + end; + '.':begin + numcount:=numcount/multby; + multby:=1; + end; + end; + end; + if numstr[1]='-' then + atof:=-numcount + else + atof:=numcount; +end; + +function longmul(X, Y: integer): Longint; +begin + inline($5A/$58/$f7/$EA); +end; + +Function isqrt(a:longint):longint; +var x,y,z:longint; +begin + x:=0;y:=1;z:=1; + while y<=a do begin + inc(x); + inc(z,2); + inc(y,z); + end; + isqrt:=x; +end; + +procedure gettricentre(xa,ya,xb,yb,xc,yc:integer; var retx,rety:integer); +begin + retx:=(xa+xb+xc) div 3; + rety:=(ya+yb+yc) div 3; +end; + +procedure getlinecentre(xa,ya,xb,yb:integer;var retx,rety:integer); +begin + retx:=(xa+xb) shr 1; + rety:=(ya+yb) shr 1; +end; + +function lineintersect(x1a,y1a,x2a,y2a,x1b,y1b,x2b,y2b:integer):boolean; +begin + if (x2a>=x1b)and (x1a<=x2b)and(y2a>=y1b)and (y1a<=y2b) then begin + + end else + lineintersect:=false; +end; + +function linelength(x1,y1,x2,y2:integer):integer; +Begin + x1:=abs(x2-x1);y1:=abs(y2-y1); + linelength:=isqrt((x1*x1)+(y1*y1)); +end; + +function linelengthRl(x1,y1,x2,y2:real):real; +Begin + x1:=abs(x2-x1);y1:=abs(y2-y1); + linelengthrl:=sqrt((x1*x1)+(y1*y1)); +end; + +function linelength3d(x1,y1,z1,x2,y2,z2:longint):longint; +Begin + x1:=abs(x2-x1);y1:=abs(y2-y1);z1:=abs(z2-z1); + linelength3d:=isqrt((x1*x1)+(y1*y1)+(z1*z1)); +end; + +function linelength3drl(x1,y1,z1,x2,y2,z2:real):real; +Begin + x1:=abs(x2-x1);y1:=abs(y2-y1);z1:=abs(z2-z1); + linelength3drl:=sqrt((x1*x1)+(y1*y1)+(z1*z1)); +end; + +function random32(range:longint):longint; +var nums:array[0..1] of word; +begin + nums[0]:=random (range and 65535); + nums[1]:=random (range shr 16); + random32:=longint(nums); +end; + +begin + LmUnit(@unitmatrix); +end. diff --git a/TMENUST.PAS b/TMENUST.PAS new file mode 100644 index 0000000..b044615 --- /dev/null +++ b/TMENUST.PAS @@ -0,0 +1,493 @@ +Unit Tmenust; +{$X+}{$g+}{$a+} +{Only 'Tpopupmenu's can be submenus. All menus can be 'rootmenu's +however. 'Tpopupmenu's save the area beneath them as a bitmap and +replace it *before* the 'commandlist' is exectuted (the command list +is allways exectuted by the 'rootmenu') so as to avoid screen corruption +if the area saved is graphically changed by the menu command} + +INTERFACE +uses views,twindraw,gbasics,ggraph,chardef,msmouse,ttypes,tmaths; + +const +{vertical size for horizontal menus} +vbord=fontheight+2; + +popupindent=2; +optyoffs=(12 shr 1)-(Fontheight shr 1); + +yseperatorsize=8; +ygapsize=5; +textindent = 4; + +menuxorient = $0001; +menuPopup = $0002; +menuSubMenu = $0004; +menuindent =$0008; + + +{menu item options} +moptButton = $0001; {if set then the menu item will appear in bas relief} +moptCentre = $0002; {if set, text will centre justify} +moptDisabled = $0004; {if set then text will appear in disabled colour and option will not highlight} +moptTitle = $0008+moptcentre+moptButton; {An unselectable title box} +moptseperator = $0010; +mopttoggler = $0020; +moptUnselectable =$0008+moptDisabled+moptseperator; +moptchangename =$0100; +MenuDrawAll=1; +MenuDrawchange=2; +MenuDrawFinish=3; + +type +{Itempalette=^Itempalette_; +Itempalette_=record + backCol,foreCol, + backselCol,foreselCol, + titlebackCol,titleforeCol, + disabledCol:byte; +end;} + +CommandElementptr=^CommandElement; +CommandElement=object(belem) + command:word; +end; + + +Tmenuview=^Tmenuview_; +Tmenuitem=^Tmenuitem_; +Tpopupmenu=^Tpopupmenu_; + + +Tmenuitem_=object + name:string[20]; + attrib:word; + keycode,command:word; + submenu:tpopupmenu; + extratext:string[10]; + + {internal} + toggleref:^boolean; + offset:integer; + name_length:byte; + optgap:byte{=vbord-2}; + +end; + +tmenuarray=^tmenuarray_; +tmenuarray_=array[0..0] of tmenuitem; + + + +Tmenuview_=object(tview_) + maxopts,Mattrib,drawmode,indent:byte; + private + + maxnamelength,maxoffset:integer; + commandlist:linkedlist; + noevent:boolean; + parent,rootmenu:Tmenuview; + menu:Tmenuitem; + oldsel,current:Tmenuitem; + public + constructor create(x,y:integer;menulist:tmenuitem;maxopts_,indent_,attrib_:byte); + procedure calcsize(x,y:integer); + + procedure handlevent(var event:tevent);virtual; + procedure draw;virtual; + procedure additem(item:tmenuitem); + + private + procedure getItemrect(item:Tmenuitem;var bounds:trect); + function insideitem(item:Tmenuitem):boolean; + procedure drawitem(item:Tmenuitem;selecting:boolean); + Function getoptselect{(x,y:integer)}:tmenuitem; +end; + +Tpopupmenu_=object(Tmenuview_) + backpic:bitmaptypeptr; + {Constructor create(x,y:integer;menulist:tmenuitem;maxopts_,indent_,attrib_:byte); + destructor done;virtual;} + procedure makesubmenuof(ParentMenu:TmenuView); + procedure doevent(x,y:integer;var event:tevent;rootmenu_:Tmenuview;owner_:tgroup); +end; + +Tmenubar=^tmenubar_; +Tmenubar_=object(Tmenuview_) + procedure handlevent(var event:tevent);virtual; +end; + +{var +pallete:Itempalette;} + +IMPLEMENTATION +Function tmenuview_.insideitem(item:tmenuitem):boolean; +var tmp_rect:trect; +begin + getitemrect(item,tmp_rect); + if mattrib and menuxorient<>0 then begin + dec(tmp_rect.y1,textindent);inc(tmp_rect.y2,textindent); + end else begin + dec(tmp_rect.x1,textindent);inc(tmp_rect.x2,textindent); + end; + insideitem:=tmp_rect.contains(xm,ym); +end; + +{creates a menu} + +procedure tmenuview_.calcsize(x,y:integer); +var offset:integer; + indented:integer; + +begin + indented:=indent shl 1; + + if mattrib and menuxorient<>0 then + rassign(x,y,x+maxoffset+indented,y+vbord+indented) + else + rassign(x,y,x+maxnamelength+indented,y+maxoffset+indented); + +end; + +procedure tmenuview_.additem(item:tmenuitem); + +var +optgap:integer; + +begin + with item^ do begin + if submenu<>nil then + submenu^.makesubmenuof(@self); + offset:=maxoffset; + if attrib and moptseperator<>0 then + optgap:=yseperatorsize + else + optgap:=fontheight+ygapsize; + + name_length:=(textindent shl 1)+TStrlen(name,@tcharset)+Tstrlen(extratext,@tcharset); + if name_length>maxnamelength then maxnamelength:=name_length; + if mattrib and menuxorient<>0 then begin + inc(maxoffset,name_length); + end else + inc(maxoffset,optgap); + + end; + + + inc(maxopts); + {sort out size and shape depending on orientation} + +end; +constructor tmenuview_.create(x,y:integer;menulist:tmenuitem;maxopts_,indent_,attrib_:byte); +var + optloop:tmenuitem; + lop:byte; + tmp_loader:trect; +begin + + menu:=menulist; + maxopts:=0; + indent:=indent_; + mattrib:=attrib_; + + CommandList.Create(sizeof(CommandElement)); + parent:=nil; current:=nil; oldsel:=nil; + drawmode:=MenuDrawall; + + maxnamelength:=0; + maxoffset:=0; + + rootmenu:=@self; + inherited make; + + {for easy positioning} + optloop:=menu; + For lop:=1 to maxopts_ do begin + {initialize for submenu} + additem(optloop); + + inc(optloop); + end; + + calcsize(x,y); + {set up grow behaviour} + + growmode:=TGgrowx1+TGgrowy1+TGdragonx+TGdragony; + +end; + +{this function returns the box that contains x and y} +Function tmenuview_.getoptselect{(x,y:integer)}:tmenuitem; +var optlop:tmenuitem; + lop:byte; +begin + optlop:=menu; + getoptselect:=nil; + for lop:=1 to maxopts do begin + if (insideitem(optlop))then begin + if(optlop^.attrib and moptunselectable=0) then + getoptselect:=optlop; + exit; + end; + inc(optlop); + end; +End; + +function CheckClicked(altmethod:boolean;zm:byte):boolean; +begin + + checkclicked:=((zm=1) and not(altmethod))or((altmethod) and (zm=0)); +end; +var +altmethod:boolean; +procedure Tmenuview_.handlevent(var event:tevent); +var currsub:tpopupmenu; + +begin + inherited handlevent(event); + with event do + if what and EvMouseDown<>0 then begin + oldsel:=nil; + currsub:=nil; + noevent:=false; + if rootmenu=@self then + altmethod:=false; + while checkclicked(altmethod,zm) do begin + mpos; + if rootmenu=@self then + if ((zm=0)and(not ms_moved)) then altmethod:=true; + oldsel:=current; + if (parent<>nil)then with parent^ do + if (contains(xm,ym)) and not(insideitem(current)) then begin + self.noevent:=true; + exit; + end; + current:=getoptselect; + if oldsel<>current then begin + drawmode:=MenuDrawChange; + mouseoff; + draw; + mouseon; + Drawmode:=MenuDrawall; + if current<>nil then with current^ do begin + if (submenu<>nil) then + currsub:=pointer(submenu) + else + currsub:=nil; + if (currsub<>nil ) then with currsub^ do begin + parent:=@self; + if self.mattrib and menuxorient<>0 then + doevent(self.x1+offset+self.indent,self.y2+1,event,self.rootmenu,self.owner) + else + doevent(self.x2+1,self.y1+offset+self.indent,event,self.rootmenu,self.owner); + end; + end; + end; + end; + what:=0; + Drawmode:=MenuDrawFinish; + drawview; + Drawmode:=MenuDrawall; + end else noevent:=true; +end; + +procedure Tmenuview_.getItemrect(item:Tmenuitem;var bounds:trect); +var temp:byte; +begin + {the '-1's are there to prevent overwrite by the next box} + temp:=0; + with item^ do begin + if attrib and mopttitle <> mopttitle then temp:=indent; + if mattrib and menuxorient<>0 then + bounds.rassign(x1+offset+temp,y1+temp, + x1+offset+temp+name_length-1,y2-temp) + else + bounds.rassign(x1+temp,y1+offset+temp, + x2-temp,y1+offset+temp+optgap-1); + end; +end; + +procedure Tmenuview_.drawitem(item:Tmenuitem;selecting:boolean); +var drawbox,oldvp:trect; + textoffs:integer; + inabit:byte; + button,selected:boolean; + olddrawmode:byte; +begin + if item<>nil then + with item^ do begin + getitemrect(item,drawbox); + with drawbox do begin + if attrib and moptseperator <>0 then begin + t_col:=lightcol; + hline3d(self.x1,self.x2-2,y1+(y2-y1) shr 1) + end else begin + button:=(attrib and moptbutton<>0); + selected:=current=item; + inabit:=0; + + textoffs:=inabit+textindent; + + if attrib and moptcentre<>0 then + inc(textoffs,1+((x2-x1)shr 1)-((name_length)shr 1)); + {different colours} + if attrib and mopttitle = mopttitle then + T_fillcol:=titlecol + else if (selected)and(not button) then begin + T_fillcol:=menuselcolback; + T_col:=menuselcolfore; + end else begin + T_col:=textcol; + t_fillcol:=midcol; + end; + if button then begin + if (selected)and(selecting) then begin + inboxcol(x1,y1,x2,y2); + inabit:=2; + end else + outboxcol(x1,y1,x2,y2) + + end else if (selected) or (not selecting) then begin + if (selected) then + buttonbardown(x1,y1,x2-1,y2) + else + buttonbar(x1,y1,x2-1,y2); + + end; + + if attrib and moptdisabled <>0 then begin + T_col:=lightcol; + + outtextxy(x1+textoffs+inabit,y1+2+inabit+((y2-y1) shr 1)-(Fontsizey shr 1),name); + outtextxy(x2-textoffs-inabit-Tstrlen(extratext,@tcharset),y1+inabit+((y2-y1) shr 1)-(Fontsizey shr 1),extratext); + T_col:=Disabledcol; + end; + outtextxy(x1+textoffs+inabit-1,y1+1+inabit+((y2-y1) shr 1)-(Fontsizey shr 1),name); + outtextxy(x2-textoffs-inabit-Tstrlen(extratext,@tcharset),y1+inabit+((y2-y1) shr 1)-(Fontsizey shr 1),extratext); + if attrib and mopttoggler<>0 then begin + if toggleref^ then + t_fillcol:=biege + else + t_fillcol:=midcol; + inboxcolb(x2-7,y1+((y2-y1) shr 1)-3,x2-2,y1+((y2-y1) shr 1)+3); + end; + end; + end; + end; +end; + +procedure Tmenuview_.draw; +var optloop:tmenuitem;lop:byte; +begin + case drawmode of + MenuDrawAll:begin + if mattrib and menuindent=0 then + outbox(x1,y1,x2,y2) + else + outbox(x2-1,y2-1,x1,y1); + optloop:=menu; + for lop:=1 to maxopts do begin + drawitem(optloop,true); + inc(optloop); + end; + end; + MenuDrawchange:if oldsel<>current then begin + drawitem(oldsel,false); + drawitem(current,true); + end; + MenuDrawFinish: + drawitem(current,false); + end; +end; + +{******************* Pop up *********************} +{Constructor Tpopupmenu_.create(x,y:integer;menulist:tmenuitem;maxopts_,indent_,attrib_:byte); +begin + backpic.create((x2-x1)+16,(y2-y1)+1); + inherited create(x,y,menulist,maxopts_,indent_,attrib_); +end; + +destructor Tpopupmenu_.done; +begin + inherited done; + backpic.done; +end;} + +procedure Tpopupmenu_.doevent(x,y:integer;var event:tevent;rootmenu_:tmenuview;owner_:tgroup); +var newcommand:CommandElementptr; +begin + {set up owners and rootmenu} + rootmenu:=rootmenu_; + owner:=owner_; + if x+(x2-x1)>SC.screenport.x2 then dec(x,x+(x2-x1)-SC.screenport.x2); + if y+(y2-y1)>SC.screenport.y2 then dec(y,y+(y2-y1)-SC.screenport.y2); + rpos(x,y); + mouseoff; + {Backpic:=getbitmap(x1,y1,width+1,height+1);} + draw; + mouseon; + handlevent(event); + SC.viewport:=self; + root^.drawview; + SC.viewport:=SC.screenport; + {mouseoff; + putbitmap(x1,y1,backpic); + mouseon; + DestroyBitmap(backpic);} + + if not noevent then begin + {add command to rootmenu's command list} + new(newcommand); + newcommand^.command:=current^.command; + rootmenu^.commandlist.add(newcommand); + if current^.attrib and moptchangename<>0 then begin + rootmenu^.current^.name:='got here' {current^.name}; + rootmenu^.drawview; + end; + if mattrib and MenuSubmenu=0 then begin + {if this is a root menu, execute command list} + newcommand:=commandlist.first; + while newcommand<>nil do begin + Evcallback(newcommand^.command); + newcommand:=newcommand^.next; + end; + commandlist.done; + end; + end; + current:=nil; +end; + +{******************* Menu bar *********************} + +Procedure tpopupmenu_.MakeSubmenuOf(ParentMenu:TmenuView); +begin + parent:=ParentMenu; + mattrib:=mattrib or MenuSubMenu; + {rootmenu:=ParentMenu^.rootmenu;} +end; + +procedure Tmenubar_.handlevent(var event:tevent); +var currcommand:CommandElementptr; + oldcurrent:tmenuitem; +begin + inherited handlevent(event); + if not noevent then begin + {this is a root menu, execute command list} + currcommand:=commandlist.first; + while currcommand<>nil do begin + Evcallback(currcommand^.command); + currcommand:=currcommand^.next; + end; + commandlist.done; + {exectute the top level instruction} + Evcallback(current^.command); + oldcurrent:=current; + current:=nil; + mouseoff; + drawitem(oldcurrent,false); + mouseon; + end; + current:=nil; +end; + +end. diff --git a/TTYPES.PAS b/TTYPES.PAS new file mode 100644 index 0000000..d32ca2b --- /dev/null +++ b/TTYPES.PAS @@ -0,0 +1,204 @@ +Unit Ttypes; + INTERFACE + const + stringsize=20; + + type + stdstring=string[stringsize]; + + stringptr=^string; + realptr=^real; + integerptr=^integer; + wordptr=^word; + byteptr=^byte; + + Stringarray=^Stringarray_; + Stringarray_=array[0..0] of stdstring; + + bytearray=^bytearray_; + bytearray_=array[0..0] of byte; + + CharArray=^CharArray_; + CharArray_=array[0..0] of Char; + + ShortArray=^ShortArray_; + ShortArray_=array[0..0] of ShortInt; + + Integerarray=^Integerarray_; + Integerarray_=array[0..0] of Integer; + + Wordarray=^Wordarray_; + Wordarray_=array[0..0] of word; + + Longintarray=^Longintarray_; + Longintarray_=array[0..0] of longint; + + realarray=^realarray_; + realarray_=array[0..0] of real; + + PointerArray=^PointerArray_; + PointerArray_=array[0..0] of pointer; + + BytePointerArray=^BytePointerArray_; + BytePointerArray_=array[0..0] of BytePtr; + + BElemPtr=^BElem; + + BElem=object + {Prev,}Next:Pointer; + end; + + LinkedList=Object + Count,size:word; + + first,Last:pointer; + + Function Prev(Elem:BElemPtr):Pointer; + Procedure Add(Elem:BelemPtr); + Procedure Insert(By,Elem:BElemPtr); + Procedure Delete(Elem:BelemPtr); + function GetByIndex(index:word):Pointer; + Constructor Create(Size_:word); + Destructor Done;virtual; + end; + + linkedlistptr=^linkedlist; + + wordlistelem=object(belem) + data:word; + end; + wordlistelemptr=^wordlistelem; + + integerlistelem=object(belem) + data:integer; + end; + integerlistelemptr=^integerlistelem; + longintlistelem=object(belem) + data:longint; + end; + longintlistelemptr=^longintlistelem; + reallistelem=object(belem) + data:real; + end; + reallistelemptr=^reallistelem; + + Function CountFrom(elem:belemptr;count:word):Pointer; + function createwordelem(data:word):belemptr; + function createintegerelem(data:integer):belemptr; + IMPLEMENTATION + function createwordelem(data:word):belemptr; + var new:belemptr; + begin + getmem(new,sizeof(wordlistelem)); + wordlistelemptr(new)^.data:=data; + createwordelem:=new; + end; + + function createintegerelem(data:integer):belemptr; + var new:belemptr; + begin + getmem(new,sizeof(integerlistelem)); + integerlistelemptr(new)^.data:=data; + createintegerelem:=new; + end; + + + + + Function CountFrom(elem:belemptr;count:word):Pointer; + var lop:word; + begin + For lop:=1 to count-1 do + elem:=elem^.next; + CountFrom:=elem; + end; + + Function LinkedList.Prev(Elem:BelemPtr):Pointer; + var E:BelemPtr; + begin + E:=First; + While (E<>nil)and(E^.next<>Elem) do + E:=E^.next; + Prev:=E; + end; + + Constructor LinkedList.Create(Size_:word); + begin + Count:=0; + first:=nil; + Last:=nil; + Size:=Size_; + end; + + Destructor LinkedList.Done; + var next:BelemPtr; + begin + while first<>nil do begin + next:=BelemPtr(first)^.next; + Freemem(BelemPtr(first),size); + first:=next; + end; + Count:=0; + last:=nil; + first:=nil; + end; + + {assumes Elem^.next = nil} + Procedure LinkedList.add(Elem:BelemPtr); + begin + BelemPtr(Elem)^.next:=nil; + if First=nil then + First:=Elem + else + BelemPtr(last)^.next:=Elem; + last:=Elem; + inc(count); + end; + + Procedure LinkedList.delete(Elem:BelemPtr); + var Previous:BelemPtr; + begin + if Elem=first then begin + first:=Elem^.next; + Previous:=nil; + end else begin + Previous:=Prev(elem); + Previous^.next:=Elem^.next; + end; + if elem=last then last:=Previous; + Freemem(Elem,Size); + dec(count); + end; + + Procedure LinkedList.insert(by,elem:BelemPtr); + var previous:BelemPtr; + begin + if by=first then begin + elem^.next:=by; + first:=elem; + end else begin + Previous:=Prev(by); + Elem^.next:=Previous^.next; + Previous^.next:=Elem; + end; + inc(count); + end; + + function LinkedList.GetByIndex(index:word):Pointer; + var lop:word; + CurrElem:BelemPtr; + begin + if index>count then + GetByIndex:=Last + else begin + Currelem:=First; + for lop:=1 to index do + Currelem:=Currelem^.next; + GetByIndex:=CurrElem; + end; + end; + + +begin + asm cwd;end; +end. \ No newline at end of file diff --git a/TWINB.PAS b/TWINB.PAS new file mode 100644 index 0000000..b971563 --- /dev/null +++ b/TWINB.PAS @@ -0,0 +1,2252 @@ +Unit twinb; +{$X+}{$a+}{$R-} +INTERFACE +{This is my standard widget set -including the basic window frame +and delta view, which needs the window or something similar. +If you aren't me and you want to shive 'deltas' in your own views +then look carefully how I initialize them -the two 'bartypes' must be +given pointers but these aren't parameters because only the delta's +imeditate owner needs to set them} + +uses crt2,msmouse,gbasics,ggraph, + twindraw,diskop,dos,ttypes, + chardef,views,Tmenust,tmaths,strings; + +{some handy keyboard constants -stop you forgeting all the time} +var +warningsign:bitmaptypeptr; +const + +tabtoplefthighlight:array[0..7] of byte=(7,24,32,64,64,128,128,128); +tabtopleftbody:array[0..7] of byte=(0,7,31,63,63,127,127,127); + +tabtoprightbody:array[0..7] of byte=(192,224,240,248,248,248,252,252); +tabtoprightshadow1:array[0..7] of byte=(32,16,8,0,4,4,0,0); +tabtoprightshadow2:array[0..7] of byte=(16,8,4,4,2,2,2,2); + + + + +CMDzoomwindow =1; +CMDwindowmenu =2; +CMDmoveparent =3; +CMDresizeparent =4; +CMDdecval =5; +CMDincval =6; +CMDselectedchanged =7; +CMDoffsetchanged =8; +{used in listtype} +CMDitemdclicked =9; +CMDvalchanged =10; +{these are used in valuetype objects} +CMDsetval =11; +CMDdismisview =12; +{used for delta} +CMDcentredelta =13; +{used in edittexttype} +CMDEditReturnPressed =14; +CMDEditstringaltered =15; +CMDcentrewindow =16; + +{for windows} +hbord=15; {title border -horizontal size} +vbord=20; {title border -vertical size} +scrollbar_size=15; {size of the scrolling bars that line windows, optional} +xbord=3; {multi-directional resize gadget size} +Wdeltax=1+scrollbar_size+(xbord*2); {Wdeltax -size of a delta window in x} +Wdeltay=2+scrollbar_size+vbord+(xbord*2); {Wdeltax -size of a delta window in x} + +edit_indentX =14; +edit_indentY =3; +edit_textindentY=edit_indenty-1; + +{icon panel constants} +icon_offsetout=1; +icon_offsetin=3; + +{Icon types -shift the attrib^[n] byte 4 to the right to get these} +statemask=1; +oneon= 2; +nostick=4; +onoff=8; + +TOjustifyMask=2; +TObordermask=24; +TOleftjustify=1; +TOrightjustify=2; +TOcentre=3; +TOwordwrap=4; +TOinborder=8; +TOinTextBox=16; +TOinbox=24; + +ToBold=1; +ToItalic=2; +ToUnderlined=4; + +DaNoscale=0; +DaScale=1; +DaNoDraw=2; + +sliderblob:array[0..3] of byte=(48,120,120,48); +leftarrowb:array[0..7] of byte=(8,24,56,120,56,24,8,0); +rightarrowb:array[0..7] of byte=(32,48,56,60,56,48,32,0); + +arrow:array[1..16]of word=(16383,8191,4095,2047,1023,511,255,127,63,127,511,4351,45311,63615,63615,64767); +arrowshape:array[1..16]of word= +(0,16384,24576,28672,30720,31744,32256,32512,32640,31744,27648,17920,1536,768,768,0); +PointTo:array[1..16]of word=(33155,1,0,32784,49680,49680,49664,49664,49921,58371,64575,61455,61455,63519,64575,65151); +PointToshape:array[1..16]of word=(0,32380,32510,6342,6342,6342,6342,6398,6268,0,384,384,2016,960,384,0); +Hourglass:array[1..16]of word= +(49155,49155,49155,49155,57351,61455,63519,64575,64575,63519,61455,61455,57351,49155,49155,49155); +Hourglassshape:array[1..16]of word=(0,8184,8088,0,3088,1568,832,384,0,832,1568,3616,3088,8184,7832,0); + +Scancodes:array['0'..'Z']of byte=(129,120,121,122,123,124,125,126,127,128, +0,0,0,0,0,0,0, +30,48,46,32,18,33,34,35,23,36,37, +38,50,49,24,25,16,19,31,20,22,47,17,45,21,44); + +{0- option}{1- remark}{2- tick}{3- Title} +type +fillpatternarray=^fillpatternarray_; +fillpatternarray_=array[0..0]of array[0..7] of byte; + +const +{button modes} +BM_ClickAction=1; +BM_ReleaseAction=2; +BM_PeriodAction=3; +BM_toggleAction=4; + +TextcentreY=1; +TextcentreX=2; +Textcentreall=3; +type + +Namebox=^Namebox_; +Namebox_=object(tview_) + align,ylines:byte; + name:pchar; + Constructor create(xa,ya,xb,yb:integer;align_:byte;name_:pchar); + procedure draw;virtual; +end; + +const +{internal} +BAdrawonlyborder=2; +BAstatechange=2; +{setable} +BAdown=1; +BAhighlightedborder=2; + +type + +bigfillarray=^bigfillarray_; +bigfillarray_=array[0..0]of array[0..31] of byte; + +Tbutton=^tbutton_; +Tbutton_=object(tview_) + bkcol,borderstate,action,dstate:byte; + Docommand:word; + Hotkeycode:byte; + constructor create(_x1,_y1,w,h:integer;_bkcol,_borderstate,action_:byte;command_:word;hotkey:byte); + destructor done;virtual; + procedure handlevent(var event:tevent);virtual; + Procedure Draw;virtual; + procedure SetState(Astate:word;Enable:boolean);virtual; + +end; + +Textbutton=^Textbutton_; +Textbutton_=object(Tbutton_) + hotkey:byte; + name:string[20]; + constructor create(_x1,_y1,w,h:integer;_bkcol,_borderstate,mode_:byte;_hotkey:byte;command_:word;_name:string); + Procedure Draw;virtual; +end; + +Tpicbutton=^Tpicbutton_; +Tpicbutton_=object(Tbutton_) + Pic:byteptr; + Procedure Draw;virtual; + constructor create(_x1,_y1,w,h:integer;_bkcol,_borderstate,mode_:byte;command_:word;hotkey:byte;_pic:byteptr); +end; + +Tbitmapbutton=^Tbitmapbutton_; +Tbitmapbutton_=object(Tbutton_) + inpic,outpic:bitmaptypeptr; + Procedure Draw;virtual; + constructor create(_x1,_y1:integer;borderstate_,mode_:byte;command_:word;hotkey:byte; + inpic_,outpic_:bitmaptypeptr); +end; + +Iconpaneltype=^Iconpaneltype_; +Iconpaneltype_=object(Tview_) + maxx,maxy:byte; + icons:bigfillarray; + attrib:bytearray; + Commands:wordarray; + xsize,ysize:byte; + curicon:byte; + dicon:integer; + + Constructor Create(x,y:integer;maxx_,maxy_,xsize_,ysize_:byte; + icons_:bigfillarray;attrib_:bytearray; + commands_:wordarray); + Procedure draw;virtual; + Procedure seticonstate(icon:byte;on:boolean); + Procedure seticon(icon:byte); + Procedure handlevent(var event:tevent);virtual; + Procedure Drawicon(X,Y:byte); +end; + +listtype=^listtype_; +listtype_=object(tview_) + maxopts,maxylen,oldsel,sel,off:integer; + drawmode:byte; + destroyold,changed:boolean; + info:stringarray; + + Constructor create(x,y,x2_,y2_:integer;info_:stringarray;maxopts_:integer;destroyold_:boolean); + destructor done;virtual; + procedure makelist(nopts:integer;list:stringarray); + Procedure setlist(info_:stringarray;maxopts_:integer); + procedure killist; + procedure setval(val_:integer); + Procedure drawitem(itemno:integer); + procedure SetState(AState: Word; Enable: Boolean); virtual; + Procedure draw;virtual; + Procedure handlevent(var event:tevent);virtual; +End; + +Edittexttype=^Edittexttype_; +Edittexttype_=object(tview_) + {private} + public + changed:boolean; + curspos,curslen:integer; + off,maxcpos,xlen:byte; + txt:string; + constructor create(x,y:integer;txt_:string;maxcpos_,xlen_:byte); + procedure draw;virtual; + procedure handlevent(var event:tevent);virtual; + procedure setstate(Astate:word;Enable:boolean);virtual; + procedure setcurs(pos:integer;followtail:boolean); + procedure settext(txt_:string); + {procedure update;} +end; + +const +barminsize=15; +xbardir=true; +ybardir=false; + +type +valuetype=^valuetype_; +valuetype_=object(tview_) + minval,maxval:integer; + val:^integer; + + constructor make(min,max:integer;val_:pointer); + procedure setval(val_:integer); + procedure initvals(min,max,val_:integer); + procedure setrange(min,max,val_:integer);virtual; +end; + +slidertype=^slidertype_; +slidertype_=object(valuetype_) + s1,s2,offs:integer; + xorient:boolean; + + Constructor create(x,y,w,h:integer;minval_,maxval_,val_:integer;orient:boolean); + Procedure draw;virtual; + procedure handlevent(var event:tevent);virtual; + procedure changebounds(var bounds:trect);virtual; + Procedure setrange(min,max,val_:integer);virtual; + {private} + procedure getsrect(var srect:trect); + procedure calcslidepos; +End; + +numbox=^numbox_; +numbox_=object(valuetype_) + constructor create(x1_,y1_,x2_,y2_:integer;min_,max_:integer;val_:pointer); + + procedure setrange(min,max,val_:integer);virtual; + destructor done;virtual; + procedure draw;virtual; +end; + +numsel=^numsel_; +numsel_=object(tgroup_) + Constructor create(x1_,y1_,W,H,bwidth,min,max:integer;val:pointer); + procedure handlevent(var event:tevent);virtual; +end; + +bartype=^bartype_; +bartype_=object(tgroup_) + Constructor create(x,y,w,h:integer;minval_,maxval_,val_:integer;orient:boolean); + procedure handlevent(var event:tevent);virtual; +end; + +bordertype=^bordertype_; +bordertype_=object(tview_) + size:byte; + Constructor create(xa,ya,xb,yb:integer;size_:byte); + Procedure draw;virtual; +end; + +Dialogback=^Dialogback_; +Dialogback_=object(tgroup_) + {Constructor create(xa,ya,xb,yb:integer);} + Procedure draw;virtual; +end; + + +type + +Delta=^Delta_; +Delta_=object(Tview_) + xbar,ybar:slidertype; + xoff,yoff:integer; + world:trect; + constructor make(x1b,y1b,x2b,y2b:integer); + + procedure changeworld(var bounds:trect);virtual; + procedure changebounds(var bounds:trect);virtual; + procedure setoffsets(xoff_,yoff_:integer);virtual; + procedure handlevent(var event:tevent);virtual; + procedure draw;virtual; +end; + +Windowtype=^Windowtype_; +Windowtype_=object(tgroup_) + menu:tpopupmenu; + oldbounds:pointtype; + maximized:boolean; + maximizegadget:tpicbutton; + deltaview:delta; + Constructor create(x,y,W,H:integer;tname:string;action_window:delta;menu_:tpopupmenu); + procedure handlevent(var event:tevent);virtual; + function changeworld(var bounds:trect):boolean; + procedure changebounds(var bounds:trect);virtual; + {procedure SetState(AState: Word; Enable: Boolean); virtual;} +End; + +Messagebox=^Messagebox_; +Messagebox_=object(tgroup_) + OkC:word; + Constructor create(x,y:integer;Ok:word;txt:pchar); + procedure handlevent(var event:tevent);virtual; + procedure draw;virtual; +end; + +Choicebox=^choicebox_; +Choicebox_=object(tgroup_) + CancelC,OkC:word; + Constructor create(x,y:integer;Cancel,Ok:word;txt:pchar); + procedure handlevent(var event:tevent);virtual; + procedure draw;virtual; +end; + +TextColourList=^TextColourList_; +TextColourList_=record + colour:byte; + maxnames:word; + text:stringarray; + next:TextColourList; +end; + +TextObject=^TextObject_; +TextObject_=object(delta_) + deltext:boolean; + TOoptions:byte; + Txt,txtstart:pchar; + maxxlen,maxylen:word; + {namelist:TextColourList;} + + private + ystart:integer; + startcol:byte; + startattrib:byte; + public + Constructor make(txt_:pchar;TOoptions_:byte;deltext_:boolean); + Destructor done;virtual; + Procedure handlevent(var event:tevent);virtual; + Procedure Draw;virtual; + procedure changebounds(var bounds:trect);virtual; + procedure getpcharxy(var maxwidth,maxheight:word); + procedure setoffsets(xoff_,yoff_:integer);virtual; + procedure settext(txt_:pchar); +end; + +tabpage=^tabpage_; +tabgroup=^tabgroup_; +tabgroup_=object(tgroup_) + lastx:integer; + tabheight:integer; + drawpagetab:tabpage; + + Constructor Create(x1_,y1_,x2_,y2_,tabheight_:integer); + + procedure addtabpage(page:tabpage); + Procedure handlevent(var event:tevent);virtual; + Procedure Draw;virtual; + + +end; + + +tabpage_=object(tgroup_) + pos:hlinetype; + name:string[20]; + icon:bitmaptypeptr; + + constructor make(name_:string;icon_:bitmaptypeptr); + procedure draw;virtual; +end; + + +procedure add_title(group:tgroup;tname:string); +{const + +pic:array[0..3,0..159]of byte=((0,0,0,0,115,0,3,128,0,6,0,6,0,0,71,0,4,0,0,0,0, +13,128,0,114,0,9,144,0,126,0,19,232,0,60,0,19,216,0,6,0, +39,252,0,126,0,5,232,0,6,0,15,252,0,11,0,13,180,0,126,0, +31,254,0,0,0,29,187,0,126,0,63,255,128,26,0,63,253,128,1,0, +127,255,128,22,0,127,254,192,118,0,255,254,192,126,0,253,189,96,91,1, +253,186,224,0,1,255,212,48,9,3,253,170,176,62,3,235,216,24,52,5, +84,42,24,11,2,131,192,12,70,5,83,192,12,139,0,131,192,6,254,32, +0,0,6,1,85,255,255,255,0,255,255,255,255,0,1,127,181,0,255), +(0,2,0,0,6,0,7,192,0,48,0,6,160,0,126,0,12,96,0,70,0, +13,176,0,0,0,25,176,0,3,0,19,248,0,60,0,59,248,0,22,0, +62,124,0,126,0,86,60,0,0,0,60,62,0,0,0,172,62,0,0,0, +126,127,0,114,1,94,126,0,127,0,252,63,0,0,0,188,63,0,11,3, +252,63,192,119,3,124,63,128,9,7,254,126,224,8,6,252,61,192,6,15, +254,122,240,58,13,254,116,96,3,31,252,42,184,70,27,235,216,48,70,61, +84,42,28,10,58,128,0,24,100,117,80,0,14,0,112,128,0,12,86,248, +0,0,7,139,255,255,255,254,242,255,255,255,254,0,126,128,74,254,70), +(255,255,255,255,141,255,255,255,255,215,255,255,255,255,150,255,255,255,255,128,255, +255,255,255,253,255,255,239,255,246,255,255,215,255,176,255,255,231,255,208,255, +254,99,255,128,255,254,115,255,128,255,254,113,255,150,255,254,121,255,154,255, +252,56,255,139,255,252,60,255,248,255,252,60,127,222,255,252,62,127,128,255, +252,62,63,153,255,252,63,63,253,255,252,63,31,134,255,254,127,159,233,255, +254,127,143,242,255,254,127,207,254,255,254,127,199,255,255,254,127,231,128,255, +255,255,227,128,255,254,127,243,255,255,252,63,241,12,255,254,127,249,70,223, +255,255,248,138,170,0,0,0,80,0,0,0,0,22,128,0,0,1,154), +(0,3,128,0,13,0,4,64,0,87,0,1,224,0,87,0,11,224,0,0,0, +2,112,0,74,0,22,112,0,1,0,12,56,0,67,0,44,56,0,62,0, +24,28,0,6,0,120,24,0,109,0,112,12,0,71,0,240,12,0,0,0, +224,6,0,0,1,224,6,0,126,1,192,3,0,114,1,192,3,0,6,3, +128,1,128,71,3,128,1,128,0,7,0,1,192,60,7,0,2,192,83,14, +0,5,96,126,14,0,11,224,121,28,2,85,112,126,28,20,39,240,10,58, +171,213,248,48,61,124,63,248,119,122,172,63,252,254,127,124,63,252,138,255, +255,255,254,228,255,255,255,254,154,255,255,255,254,139,0,0,0,0,182) +); + + +warningsign:bitmaptype=(size.x:32;ylen:32;planesize:160;bitmaptype:BMplanes;memallocated:false;xoff:5;bitplanes:4; +Planedata:(@pic[0],@pic[1],@pic[2],@pic[3]);bitoffset:0);} + + +IMPLEMENTATION +function strequals(str1,str2:string):boolean; +var lop:byte; +begin + for lop:=1 to byte(str1[0]) do + str1[lop]:=upcase(str1[lop]); + strequals:=(str1=str2); +end; + +{*===================================*} +{* -*Text Object*- *} +{*===================================*} + +Constructor textobject_.make(txt_:pchar;TOoptions_:byte;deltext_:boolean); +begin + inherited make(0,0,0,0); + {namelist:=namelist_;} + deltext:=deltext_; + TOoptions:=TOoptions_; + txt:=txt_; + txtstart:=txt; + getpcharxy(maxxlen,maxylen); + world.rassign(0,0,(maxxlen shl 3)-1,(maxylen*Fontheight)-1); + ystart:=y1; + startcol:=textcol; +end; + +Destructor textobject_.done; +begin + if (deltext) and (txt<>nil) then + {freemem(txt,strlen(txt));} + inherited done; +end; + +procedure textobject_.getpcharxy(var maxwidth,maxheight:word); +var textwidth:word; + txtlop:pchar; + txtpos:word; +begin + textwidth:=0; + maxwidth:=0; + maxheight:=2; + txtlop:=txt; + txtpos:=0; + while txtlop^<>chr(0) do begin + if{((TOoptions and TOwordwrap =0) and }(txtlop^=returnkey) {or + ((TOoptions and TOwordwrap<>0) and ((textwidth * 8)>(x2-x1)))} then begin + if textwidth>maxwidth then maxwidth:=textwidth; + textwidth:=0; + inc(maxheight); + end else if txtlop^<>'^' then + inc(textwidth) + else + dec(textwidth); + inc(txtlop); + inc(txtpos); + end; + if textwidth>maxwidth then maxwidth:=textwidth; + inc(maxwidth); + inc(maxheight); +end; + +procedure textobject_.settext(txt_:pchar); +var wbounds:trect; +begin + txt:=txt_; + getpcharxy(maxxlen,maxylen); + wbounds.rassign(0,0,(maxxlen shl 3)-1,(maxylen*Fontheight)-1); + state:=state and not sfvisible; + changeworld(wbounds); + state:=state or sfvisible; + drawview; +end; + +procedure textobject_.draw; +var x,y:integer; + Lx,Wx:integer; + CurrAttrib,lastcurrwidth,currwidth:byte; + txtlop:pchar; + currchar:char; + oldvp:trect; + temp:byte; + currnamelist:TextColourList; +begin + + case TOoptions and TObordermask of + TOinTextBox:begin + t_fillcol:=textboxcol; + bar(x1+2,y1+2,x2-2,y2-2); + textbox(x1,y1,x2,y2); + end; + TOinBox:inbox(x1,y1,x2,y2); + end; + + oldvp:=SC.viewport; + SC.viewport:=self; + SC.viewport.intersect(SC.screenport); + SC.viewport.rgrow(-2,-2); + SC.viewport.intersect(oldvp); + + txtlop:=txtstart; + x:=x1-xoff; + Wx:=x; + y:=ystart; + + CurrAttrib:=0; + t_col:=startcol; + + lastcurrwidth:=0; + while (y0 then begin + hline(lx+4,x+4,y+fontheight); + lx:=x; + end; + inc(y,Fontheight); + end; + end; + else begin + drawbytes(x+4,y+4,@Tcharset.typeface[ord(currchar)],fontheight); + if Currattrib and ToBold<>0 then drawbytes(x+5,y+4,@Tcharset.typeface[ord(currchar)],fontheight); + end; + end; + if txtlop^=chr(0) then exit; + inc(x,currwidth); + lastcurrwidth:=currwidth; + inc(txtlop); + end; + SC.viewport:=oldvp; +end; + +procedure textobject_.handlevent(var event:tevent); +begin + inherited handlevent(event); +end; + +procedure textobject_.changebounds(var bounds:trect); +begin + {if not equals(bounds) then begin + getpcharxy(maxxlen,maxylen); + world.rassign(0,0,(maxxlen shl 3)-1,(maxylen*Fontheight)-1); + end;} + inherited changebounds(bounds); +end; + +procedure textobject_.setoffsets(xoff_,yoff_:integer); +begin + ystart:=y1-yoff_; + txtstart:=txt; + startcol:=textcol; + while ystart<(y1-Fontheight) do begin + case txtstart^ of + chr(13):inc(ystart,Fontheight); + {'^':begin + inc(txtstart); + case txtstart^ of + 'C','c':begin + inc(Txtstart); + startcol:=ord(txtstart^); + end; + end; + inc(txtstart); + end;} + end; + inc(txtstart); + end; + inherited setoffsets(xoff_,yoff_); +end; + + + +function getline(var txt:pchar;maxlinewidth:byte):byte; +var length,lastwordpos:byte; + lastwordchar:pchar; +begin + length:=0; + lastwordpos:=0; + while (txt^<>#0)and (length<=maxlinewidth) do begin + if txt^=' ' then begin + lastwordpos:=length; + lastwordchar:=txt; + end; + inc(length); + inc(txt) + end; + if (txt^=' ') or (txt^=#0) then + getline:=length + else begin + txt:=lastwordchar; + getline:=lastwordpos; + end; +end; + +{*===================================*} +{* -*NameBox*- *} +{*===================================*} + +function GetHeight(text:pchar;width:integer):integer; +var ylines:integer; +begin + + ylines:=0; + while text^<>#0 do begin + getline(text,(width shr 3)-1); + inc(ylines,fontheight); + end; + GetHeight:=ylines; +end; + +Constructor Namebox_.Create(xa,ya,xb,yb:integer;align_:byte;name_:pchar); +begin + inherited create(xa,ya,xb,yb); + align:=align_; + name:=name_; + ylines:=0; + while name_^<>#0 do begin + getline(name_,(width shr 3)-1); + inc(ylines); + end; +end; + +Procedure Namebox_.draw; +const +offset=3; +var xindent,yindent:integer; + strlength:byte; + oldchar,currchar:pchar; + +begin + t_col:=textcol; + currchar:=name; + if align and TextCentreY<>0 then + Yindent:=y1+1+(halfy-((Fontheight*ylines) shr 1)) + else + Yindent:=y1+offset; + while currchar^<>#0 do begin + oldchar:=currchar; + strlength:=getline(currchar,(width shr 3)-1); + if align and TextCentreX<>0 then + Xindent:=x1+1+halfx-(strlength shl 3)shr 1 + else + Xindent:=x1+offset; + outtextxy_length(Xindent,Yindent,oldchar,strlength); + inc(Yindent,fontheight); + end; +end; + +{*===================================*} +{* -*Tbutton*- *} +{*===================================*} + +constructor Tbutton_.create(_x1,_y1,w,h:integer;_bkcol,_borderstate,action_:byte;command_:word;hotkey:byte); +begin + inherited create(_x1,_y1,_x1+w,_y1+h); + options:=options or ofkeygrab+ofautoraise+oftabcycleselect; + hotkeycode:=hotkey; + bkcol:=_bkcol; + docommand:=command_; + action:=action_; + borderstate:=_borderstate; + dstate:=0; {not depressed} +end; + +destructor Tbutton_.done; +Begin +end; + +Procedure tbutton_.handlevent(var event:tevent); +var Mcount:word; +const + threshold=2; +begin +inherited handlevent(event); + with event do + if what and evmousepressed<>0 then begin + dstate:=dstate xor BAdown; + drawview; + case action of + BM_toggleaction:begin Evcallback(doCommand);whilemousein;end; + BM_ClickAction:Evcallback(doCommand); + BM_ReleaseAction:while (inview(xm,ym))and(not ms_released) do + mpos; + BM_PeriodAction:begin + Evcallback(doCommand); + mcount:=timer; + while (inview(xm,ym))and(not ms_released) do begin + mpos; + if (timer-mcount)>threshold then + evcallback(doCommand); + delay(6); + end; + end; + end; + if action<>BM_toggleaction then begin + dstate:=dstate xor BAdown; + drawview; + end; + if (action=BM_ReleaseAction)and(inview(xm,ym))and(ms_released) then + evcallback(doCommand); + what:=0; + end; + with event do + if what=EvKeyDown then begin + if (scancode=hotkeycode)and(scancode<>0)or((state and sfselected<>0)and + (charcode=#13)) then begin + if action=BM_toggleaction then begin + dstate:=dstate xor BAdown; + drawview; + end; + Evcallback(doCommand); + what:=0; + end; + end; +end; + +Procedure Tbutton_.draw; +Begin + if borderstate>0 then begin + if State and sfselected <> 0 then + t_col:=red + else + t_col:=grey2; + thickrectangle(x1,y1,x2,y2,borderstate); + end; + if dstate and BAdrawonlyborder=0 then begin + t_fillcol:=bkcol; + if dstate=0 then + outboxcol(x1+borderstate,y1+borderstate,x2-borderstate,y2-borderstate) + else + inboxcol(x1+borderstate,y1+borderstate,x2-borderstate,y2-borderstate); + end; +end; + +procedure Tbutton_.setstate(Astate:word;Enable:boolean); +begin + + inherited setstate(Astate,Enable); + if (astate and sfselected)<>0 then begin + dstate:=dstate or Badrawonlyborder; + drawview; + dstate:=dstate xor BAdrawonlyborder; + end; +end; + +{*===================================*} +{* -*TextButton*- *} +{*===================================*} + +constructor Textbutton_.create(_x1,_y1,w,h:integer;_bkcol,_borderstate,mode_:byte;_hotkey:byte;command_:word;_name:string); +begin + name:=_name; + hotkey:=_hotkey; + inherited create(_x1,_y1,w,h,_bkcol,_borderstate,mode_,command_, + scancodes[upcase(name[hotkey])]); +end; + +Procedure Textbutton_.draw; +var dofs:byte; +xoffs,yoffs:integer; +begin + inherited draw; + if dstate and BAdrawonlyborder=0 then begin + if dState and Badown<>0 then dofs:=2 else dofs:=0; + t_col:=(textcol); + xoffs:=dofs+x1+halfx-((TStrlen(name,@tcharset))shr 1); + yoffs:=dofs+y1+halfy; + OuttextxyU(xoffs,yoffs-(Fontsizey shr 1),name,hotkey); + end; +end; + +{*===================================*} +{* -*Pic Button*- *} +{*===================================*} + +constructor Tpicbutton_.create(_x1,_y1,w,h:integer;_bkcol,_borderstate,mode_:byte;command_:word;hotkey:byte;_pic:byteptr); +begin + inherited create(_x1,_y1,w,h,_bkcol,_borderstate,mode_,command_,hotkey); + pic:=_pic; +end; + +Procedure Tpicbutton_.draw; +var dofs:byte; +begin + inherited draw; + if dstate and BAdrawonlyborder=0 then begin + if dState and BAdown<>0 then dofs:=3 else dofs:=1; + t_col:=(grey5); + drawbytes(dofs+x1+halfx-3,dofs+y1+halfy-3,pointer(pic),8); + {if dState and BAdown<>0 then t_col:=biege else }t_col:=(grey1); + drawbytes(dofs+x1+halfx-4,dofs+y1+halfy-4,pointer(pic),8); + end; +end; + +Procedure Tbitmapbutton_.Draw; +begin + if borderstate>0 then begin + if State and sfselected <> 0 then + t_col:=red + else + t_col:=grey2; + thickrectangle(x1,y1,x2,y2,borderstate); + end; + if dstate and BAdrawonlyborder=0 then + if dstate=0 then + putbitmap(x1,y1,outpic) + else + putbitmap(x1,y1,inpic) +end; + +constructor Tbitmapbutton_.create(_x1,_y1:integer;borderstate_,mode_:byte;command_:word;hotkey:byte; + inpic_,outpic_:bitmaptypeptr); +begin + with outpic_^ do + inherited create(_x1,_y1,size.x-1,size.y-1,0,borderstate_,mode_,command_,hotkey); + inpic:=inpic_; + outpic:=outpic_; +end; + +{*===================================*} +{* -*Icon Panel*- *} +{*===================================*} + +Constructor Iconpaneltype_.Create(x,y:integer;maxx_,maxy_,xsize_,ysize_:byte; + icons_:bigfillarray;attrib_:bytearray; + commands_:wordarray); +Begin + icons:=icons_; attrib:=attrib_; + commands:=commands_; + maxx:=maxx_; maxy:=maxy_; + xsize:=xsize_; ysize:=ysize_; + inherited create(x,y,x+(maxx*xsize)-1,y+(maxy*ysize)-1); + curicon:=0; + dicon:=-1; +end; + +{draws the icon given at the x,y position on the grid in its current state} +Procedure Iconpaneltype_.drawicon(X,Y:byte); +var xoffs,yoffs:integer; +begin + xoffs:=x*xsize+x1; + yoffs:=y*ysize+y1; + if attrib^[x+(y*maxx)]and statemask<>0 then begin + inbox(xoffs,yoffs,xoffs+xsize-2,yoffs+ysize-2); + t_col:=grey5; + drawbytesxy(xoffs+icon_offsetin,yoffs+icon_offsetin,pointer(@icons^[(y*maxx)+x]),2,16); + t_col:=darkcol; + hline(xoffs,xoffs+xsize-1,yoffs+ysize-1); + vline(xoffs+xsize-1,yoffs,yoffs+ysize-1); + end else begin + outbox(xoffs,yoffs,xoffs+xsize-1,yoffs+ysize-1); + t_col:=grey6;drawbytesxy(xoffs+icon_offsetout,yoffs+icon_offsetout,pointer(@icons^[(y*maxx)+x]),2,16); + end; +end; + +Procedure Iconpaneltype_.draw; +var xlop,ylop:byte; +Begin + if dicon=-1 then begin + For ylop:=0 to maxy-1 do + For xlop:=0 to maxx-1 do + drawicon(xlop,ylop); + end else begin + xlop:=dicon mod maxx; + ylop:=(dicon-xlop) div maxx; + drawicon(xlop,ylop); + end; +end; + +Procedure Iconpaneltype_.seticonstate(icon:byte;on:boolean); +var + attr:byte; +begin + dicon:=icon; + + attr:=attrib^[icon]; + if on then begin + case attrib^[icon] and not statemask of + nostick:begin + attrib^[icon]:=attrib^[icon] or statemask; + drawview; + evcallback(commands^[icon]); + whilemousein; + attrib^[icon]:=attrib^[icon] xor statemask; + drawview; + end; + onoff:attr:=attr xor statemask; + oneon:attr:=attr or statemask; + end; + end else if (attr and not statemask=oneon)and(icon<>curicon) then + attr:=attr and not statemask; + if attr<>attrib^[icon] then begin + attrib^[icon]:=attr; + drawview; + if on then + evcallback(commands^[icon]); + if attrib^[icon] and onoff<>0 then whilemousein; + end; + dicon:=-1; +end; + +{The attrib array is in bytes. The last 4 bits are used to donate the +mode of the icon (onoff -a toggler, oneon -switches off when another mode +is selected and nostick -icon dosent stay depressed} + +Procedure Iconpaneltype_.seticon(icon:byte); +var oldicon:byte; +begin + oldicon:=curicon; + curicon:=icon; + seticonstate(curicon,true); + if attrib^[oldicon] and oneon<>0 then + seticonstate(oldicon,false); +end; + +Procedure Iconpaneltype_.handlevent(var event:tevent); +begin + inherited handlevent(event); + if event.what and Evmousepressed<>0 then begin + seticon(((xm-x1-1)div xsize)+((ym-y1-1)div ysize)*maxx); + end; +end; + +{*===================================*} +{* -*Value Type*- *} +{*===================================*} + +constructor valuetype_.make(min,max:integer;val_:pointer); +begin + {call the root setrange -No event calling here} + inherited make; + val:=val_; + valuetype_.initvals(min,max,val^); +end; + +Procedure valuetype_.setval(val_:integer); +begin + setrange(minval,maxval,val_); +end; + +Procedure valuetype_.initvals(min,max,val_:integer); +var tmp:longint; +begin + maxval:=max; + minval:=min; + if val_>maxval then val_:=maxval else + if val_ 0) then begin + if scan and (leftshiftkey+rightshiftkey)<>0 then + moveby:=10 + else + moveby:=1; + case command of + CMDincval:setval(val^+moveby); + CMDdecval:setval(val^-moveby); + CMDsetval:setval(infoint); + end; + end; + if (what=EvKeyDown) and (scancode<>0) then begin + what:=0; + if xorient then + case scancode of + rightkeyctrl,endkey:setval(maxval); + leftkeyctrl:setval(minval); + {stop key event here..} + rightkey,leftkey:; + else what:=EvKeyDown; + end else + case scancode of + PageUpKey:setval(minval); + PageDownKey:setval(maxval); + {stop key event here..} + upkey,downkey:; + else what:=EvKeyDown; + end; + end; + end; +end; + +{*===================================*} +{* -*SliderType*- *} +{*===================================*} + +Constructor slidertype_.create(x,y,w,h:integer;minval_,maxval_,val_:integer;orient:boolean); +begin + offs:=val_; + valuetype_.make(minval_,maxval_,@offs); + xorient:=orient; + rassign(x,y,x+w,y+h); + calcslidepos; +end; + +Procedure slidertype_.handlevent(var event:tevent); +var diff,range,offset:integer; + incby:longint; + srect:trect; +Begin + inherited handlevent(event); + with event do + if what and EvMousePressed+Evmousemove<>0 then begin + getsrect(srect); + if (srect.contains(xm,ym))and(zm>0) then begin + if xorient then offset:=xm-srect.x1 else offset:=ym-srect.y1; + if xorient then begin + setmouserect(x1+offset,ym,x2-(s2-s1-offset),ym); + diff:=x2-x1; + end else begin + setmouserect(xm,y1+offset,xm,y2-(s2-s1-offset)); + diff:=y2-y1; + end; + dec(diff,barminsize); + if diff=0 then diff:=1; + range:=maxval-minval; + + while not ms_released do begin + mpos; + if ms_moved then begin + if xorient then incby:=xm-x1 else incby:=ym-y1; + dec(incby,offset); + if range>=diff then + incby:=(incby * range) div diff; + inc(incby,minval); + setval(incby); + end; + end; + with SC.screenport do setmouserect(x1,y1,x2,y2); + end; + what:=0; + end; {else if what=EvKeyDown then + owner^.handlevent(Event);} +end; + +Procedure slidertype_.setrange(min,max,val_:integer); +var oldvp,tmp:trect; + oldval:integer; + changed:boolean; +begin + oldval:=offs; + if (max-min)<0 then begin + min:=0;max:=0; + end; + changed:=(min<>minval)or(max<>maxval); + initvals(min,max,val_); + if (offs<>oldval)or changed then begin + if state and sfvisible<>0 then begin + oldvp:=SC.viewport; + getsrect(SC.viewport); + calcslidepos; + getsrect(tmp); + SC.viewport.union(tmp); + SC.viewport.intersect(oldvp); + drawview; + SC.viewport:=oldvp; + end else + calcslidepos; + {send out message to parent} + sendcommand(CMDvalchanged,owner^.owner,@self); + end; +end; + +Procedure slidertype_.draw; +Begin + T_fillcol:=scrollcol; + if xorient then begin + bar(x1,y1+1,x2,y2-1); + t_col:=lightcol; hline(x1,x2,y1); + t_col:=scrollhighlight; hline(x1+1,x2-1,y1+1+halfy); + T_col:=mid_darkcol; hline(x1,x2,y2-1); + t_col:=darkcol; hline(x1,x2,y1+halfy); + hline(x1,x2,y2); + outbox(x1+s1,y1+2,x1+s2,y2-2); + t_col:=lightcol; + drawbytes(x1+s1+((s2-s1) shr 1)-2,(y1+(y2-y1) shr 1)-1,@sliderblob,4); + t_col:=mid_darkcol; + drawbytes(x1+s1+((s2-s1) shr 1)-3,(y1+(y2-y1) shr 1)-2,@sliderblob,4); + end else begin + bar(x1+1,y1,x2-1,y2); + t_col:=lightcol; vline(x1,y1,y2); + t_col:=scrollhighlight; vline(x1+1+halfx,y1+1,y2-1); + T_col:=mid_darkcol; vline(x2-1,y1,y2); + t_col:=darkcol; vline(x1+halfx,y1,y2); + vline(x2,y1,y2); + outbox(x1+2,y1+s1,x2-2,y1+s2); + t_col:=lightcol; + drawbytes((x1+(x2-x1) shr 1)-2,y1+s1+((s2-s1) shr 1)-1,@sliderblob,4); + t_col:=mid_darkcol; + drawbytes((x1+(x2-x1) shr 1)-3,y1+s1+((s2-s1) shr 1)-2,@sliderblob,4); + end; +end; + +procedure slidertype_.calcslidepos; +var diff,valdiff:integer; +docalc:longint; +size:integer; +begin + if xorient then + diff:=x2-x1 + else + diff:=y2-y1; + valdiff:=maxval-minval; + if valdiff<(diff-barminsize) then + size:=diff-valdiff + else + size:=barminsize; + if valdiff<>0 then begin + docalc:=offs-minval; + s1:=(docalc*(diff-size)) div valdiff; + end else begin + s1:=0; + size:=diff; + end; + s2:=s1+size; +end; + +procedure slidertype_.changebounds(var bounds:trect); +begin + inherited changebounds(bounds); + calcslidepos; +end; + +procedure slidertype_.getsrect(var srect:trect); +begin + if xorient then + srect.rassign(x1+s1,y1+2,x1+s2,y2-2) + else + srect.rassign(x1+2,y1+s1,x2-2,y1+s2); +end; + +{*===================================*} +{* -*Edit text type*- *} +{*===================================*} +constructor Edittexttype_.create(x,y:integer;txt_:string;maxcpos_,xlen_:byte); +begin + changed:=false; + txt:=txt_; + xlen:=xlen_; + maxcpos:=maxcpos_; + curspos:=1; + curslen:=1; + off:=1; + inherited create(x,y, + x+((edit_indentX shl 1)+xlen shl 3)-1, + y+Fontheight+(edit_indentY shl 1)); + options:=options or OfAutoRaise+OfTabCycleSelect; +end; + +procedure Edittexttype_.settext(txt_:string); +begin + if txt_<>txt then begin + txt:=txt_; + if curspos>byte(txt[0]) then curspos:=byte(txt[0]); + curslen:=curspos; + drawview; + end; +end; + +procedure Edittexttype_.setcurs(pos:integer;followtail:boolean); +var oldoff:integer; +begin + if pos<1 then pos:=1; + if pos>byte(txt[0])+1 then pos:=byte(txt[0])+1; + if (pos<>curspos) then begin + oldoff:=off; + curspos:=pos; + if curspos>off+xlen then + off:=curspos-xlen; + if curspos<=off then + off:=curspos; + if followtail then + Curslen:=Curspos; + if oldoff<>off then begin + drawview; + end else begin + drawview; + end; + end; +end; +{ +Procedure edittextype_.update; +const lasttime:word=0; + onoff:boolean=false; +var + oldmode:byte; +begin + if timmer-lasttime>100 then begin + onoff:=onoff xor true; + oldmode:=drawmode; + drawmode:= + + end; +end;} + +Procedure Edittexttype_.draw; +var poff,cp1,cp2:integer; + c1,c2:byte; + oldvp,usevp:trect; +Begin + oldvp:=SC.viewport; + SC.viewport:=self; + SC.viewport.rgrow(-edit_indentX,-2); + usevp:=SC.viewport; + SC.viewport.intersect(oldvp); + c1:=curspos; + c2:=curslen; + poff:=TStrlen(copy(txt,1,off-1),@tcharset); + if c1>c2 then fswap(c1,c2,1); + cp1:=TStrLen_at(txt,c1,@tcharset)-poff; + cp2:=TStrLen_at(txt,c2,@tcharset)-poff; + with usevp do begin + t_fillcol:=textboxcol; + t_col:=textcol; + bar(x1-poff,y1,x1+cp1,y2); + bar(x1+cp2,y1,x2,y2); + if c1<>c2 then begin + if state and sfselected<>0 then + t_fillcol:=menuselcolback; + bar(x1+cp1,y1,x1+cp2,y2); + outtextxy(x1-poff,y1+edit_textindenty,copy(txt,1,c1-1)); + outtextxy(x1+cp2,y1+edit_textindenty,copy(txt,c2,1+byte(txt[0])-c2)); + t_col:=menuselcolfore; + outtextxy(x1+cp1,y1+edit_textindenty,copy(txt,c1,c2-c1)); + t_fillcol:=lightcol; + end else + outtextxy(x1-TStrLen_at(txt,off,@tcharset),y1+edit_textindenty,txt); + end; + SC.viewport:=oldvp; + bar(x1+2,y1+2,x1+13,y2-2); + bar(x2-2,y1+2,x2-13,y2-2); + if state and sfselected<>0 then begin + t_col:=textcol; + textcurs(x1+edit_indentX+TStrlen_at(txt,1+curspos-off,@tcharset),y1+3,y2-y1-5); + end; + t_col:=menuselcolfore; + if (byte(txt[0])-off)>xlen then + drawbytes(x2-10,y1+(halfy-4),pointer(@rightarrow),8); + if off>1 then + drawbytes(x1+2,y1+(halfy-4),pointer(@leftarrow),8); + textbox(x1,y1,x2,y2); +end; + +Procedure Edittexttype_.handlevent(var event:tevent); +var followtail:boolean; + c1,c2:byte; +Begin + inherited handlevent(event); + with event do + if what and EvMousePressed<>0 then begin + setcurs(off+getindex(txt,xm-edit_indentX-x1,@tcharset),true); + while not ms_released do begin + mpos; + setcurs(off+getindex(txt,xm-edit_indentX-x1,@tcharset),false) + end; + what:=0; + end; + with event do begin + if what=EvKeyDown then begin + what:=0; + case charcode of + backspacekey:if curspos>1 then begin + if curspos=2 then + txt:=copy(txt,2,byte(txt[0])) + else if curspos=byte(txt[0])+1 then + txt:=copy(txt,1,byte(txt[0])-1) + else + txt:=copy(txt,1,curspos-2)+copy(txt,curspos,byte(txt[0])); + setcurs(curspos-1,true); + end; + escapekey:; + returnkey:EvCallBack(CMDEditReturnPressed); + chr(32)..chr(126):begin + if scan and insertkey<>0 then + txt:=copy(txt,0,curspos-1)+charcode+(copy(txt,curspos,byte(txt[0]))) + else if curspos>byte(txt[0]) then + txt:=txt+charcode + else + txt[curspos]:=charcode; + setcurs(curspos+1,true); + end; + else what:=EvKeyDown; + end; + followtail:=scan and (LeftShiftKey+RightShiftKey)=0; + if charcode=chr(0) then begin + what:=0; + case scancode of + homekey,leftkeyctrl:setcurs(1,followtail); + endkey,rightkeyctrl:setcurs(byte(txt[0])+1,followtail); + rightkey:setcurs(curspos+1,followtail); + leftkey:setcurs(curspos-1,followtail); + delkey:if (curspos<=byte(txt[0]))or(curspos<>curslen) then begin + c1:=curspos;c2:=curslen; + if c1>c2 then fswap(c1,c2,1); + if (c2=curslen)and(curspos<>curslen) then dec(c2); + txt:=copy(txt,1,c1-1)+copy(txt,c2+1,byte(txt[0])); + if curspos=c1 then begin + curslen:=curspos; + drawview; + end else + setcurs(c1,true); + end; + else what:=evkeydown; + end; + end; + if what=0 then Evcallback(CMDEditstringaltered); + end; + end; +end; + +procedure EditTextType_.setstate(Astate:word;Enable:boolean); +begin + inherited setstate(Astate,Enable); + if Astate and sfselected <> 0 then + drawview; +end; + +{*===================================*} +{* -*Number box type*- *} +{*===================================*} + +constructor numbox_.create(x1_,y1_,x2_,y2_:integer;min_,max_:integer;val_:pointer); +begin + inherited make(min_,max_,val_); + rassign(x1_,y1_,x2_,y2_); +end; + +destructor numbox_.done; +Begin +end; + +Procedure numbox_.draw; +var numstr:string; +Begin + {Outbox(x1,y1,x2,y2)} + {Outbox(x2-5,y2-5,x1+5,y1+5);} + textboxfilled(x1,y1,x2,y2); + t_col:=(textcol); + numstr:=itoa(val^); + Outtextxy(x1+halfx-(TStrLen(numstr,@tcharset))shr 1,y1+1+(halfy-(Fontsizey shr 1)),numstr); +end; + +procedure numbox_.setrange(min,max,val_:integer); +var oldvp:trect; + oldval:integer; +begin + oldval:=val^; + inherited initvals(min,max,val_); + if (val^<>oldval) then begin + drawview; + sendcommand(CMDvalchanged,owner^.owner,@self); + end; +end; + +{*===================================*} +{* -*Number select type*- *} +{*===================================*} + +Constructor numsel_.create(x1_,y1_,W,H,bwidth,min,max:integer;val:pointer); +begin + inherited create(x1_,y1_,x1_+W,y1_+H); + options:=options or Ofnooverlap+OfKeyGrab+Ofautoraise; + insert(new(numbox,create(x1+bwidth+1,y1,x2-bwidth-1,y2,min,max,val))); + first^.growmode:=TGgrowx2+TGgrowally; + insert(new(tpicbutton,create(x2-bwidth,y1,bwidth,y2-y1,midcol,0,BM_PeriodAction,CMDincval,rightkey,@rightarrowb))); + first^.growmode:=TGgrowy1+TGdragx1; + insert(new(tpicbutton,create(x1,y1,bwidth,y2-y1,midcol,0,BM_PeriodAction,CMDdecval,leftkey,@leftarrowb))); + first^.growmode:=TGgrowy2+TGdragx1; +end; + +procedure numsel_.handlevent(var event:tevent); +begin + inherited handlevent(event); + with slidertype(last)^,event do begin + if event.what=EVcommand then + case event.command of + CMDincval:setval(val^+1); + CMDdecval:setval(val^-1); + end; + if (what=EvKeyDown)and(scancode<>0)then begin + what:=0; + case scancode of + PageUpKey:setval(maxval); + PageDownKey:setval(minval); + {stop key event here..} + upkey,downkey:; + else what:=EvKeyDown; + end; + end; + end; +end; + +{*===================================*} +{* -*List type*- *} +{*===================================*} +const +listdrawall=1; +listdrawchange=2; +listdrawselected=3; + +constructor listtype_.create(x,y,x2_,y2_:integer;info_:stringarray;maxopts_:integer;destroyold_:boolean); +begin + inherited create(x,y,x+x2_,y+y2_); + options:=options or ofautoraise+OfTabCycleSelect; + drawmode:=listdrawall; + destroyold:={(info_=nil) or }(destroyold_); + makelist(maxopts_,info_); + + maxylen:=(y2-y1)div Fontheight; + info^[0]:=''; +end; + +{set a list to a new list and redraw} +Procedure listtype_.setlist(info_:stringarray;maxopts_:integer); +begin + state:=state and not sfvisible; + killist; + state:=state or sfvisible; + makelist(maxopts_,info_); + drawview; +end; + +procedure listtype_.makelist(nopts:integer;list:stringarray); +begin + maxopts:=nopts; + if list<>nil then + info:=list + else + getmem(info,(1+maxopts)*21); + changed:=false; + sel:=1;off:=1;oldsel:=1; +end; + +procedure listtype_.killist; +Begin + if (maxopts>0)and(destroyold) then + freemem(info,(1+maxopts)*21); + maxopts:=0; +end; + +destructor listtype_.done; +begin + killist; + inherited done; +end; + +Procedure listtype_.drawitem(itemno:integer); +var yoff:integer; +Begin + if (itemno>=off)and(itemno<=maxopts)then begin + yoff:=4+y1+(itemno-off)*Fontheight; + t_fillcol:=textboxcol; + if itemno=sel then begin + if state and sfselected<>0 then + t_fillcol:=menuselcolback; + t_col:=menuselcolfore; + end else begin + t_col:=textcol; + end; + if (itemno=oldsel) or (itemno=sel) then + bar(x1+4,yoff,x2-4,yoff+Fontmax); + outtextxy(4+x1,yoff+1,info^[itemno]); + end; +End; + +Procedure listtype_.draw; +var lop:integer; +begin + case drawmode of + listdrawall:begin + t_fillcol:=textboxcol; + bar(x1+2,y1+2,x2-2,y2-2); + Textbox(x1,y1,x2,y2); + maxylen:=(y2-y1)div Fontheight; + if maxopts=0 then begin + t_col:=textcol; + outtextxy(x1+4,y1+4,info^[0]) + end else For lop:=off to off+maxylen do + drawitem(lop); + end; + listdrawchange:begin + Drawitem(oldsel);Drawitem(sel); + end; + listdrawselected:Drawitem(sel); + end; + Textbox(x1,y1,x2,y2); +end; + +procedure listtype_.setval(val_:integer); +var oldoff:integer; +begin + if val_<1 then val_:=1; + if val_>maxopts then val_:=maxopts; + if (sel<>val_)or(not changed) then begin + changed:=true; + maxylen:=(y2-y1)div Fontheight; + + oldoff:=off; + oldsel:=sel; + sel:=val_; + if sel>=off+maxylen then + off:=1+sel-maxylen; + if sel<=off then + off:=sel; + if oldoff<>off then begin + drawview; + evcallback(CMDoffsetchanged); + end else begin + drawmode:=listdrawchange; + drawview; + drawmode:=listdrawall; + end; + + evcallback(CMDselectedchanged); + end; +end; + +Procedure listtype_.handlevent(var event:tevent); +Var oldoff,listlop:byte; +Begin + inherited handlevent(event); + if maxopts>0 then + with event do begin + if what and evmousepressed<>0 then begin + while zm<>0 do begin + mpos; + setval(off+(ym-y1-4) div Fontheight); + end; + if (ms_doubleclicked) then begin + evcallback(CMDitemDclicked); + end; + what:=0; + end; + if what = EvKeyDown then begin + case scancode of + upkey,downkey,pageupkey,pagedownkey:what:=0; + end; + case scancode of + upkey:setval(sel-1); + downkey:setval(sel+1); + pageupkey:setval(0); + pagedownkey:setval(maxopts); + end; + case charcode of + #13:begin + evcallback(CMDitemDclicked); + what:=0; + end; + 'A'..'z':begin + listlop:=0; + while ((listlop<=maxopts)and(info^[listlop][1]<>charcode))do + inc(listlop); + if (listlopoff then + drawview; + end; + end; + end; +End; + +procedure listtype_.SetState(AState: Word; Enable: Boolean); +begin + inherited setstate(Astate,enable); + if (Astate and sfselected<>0) then begin + drawmode:=listdrawselected; + drawview; + drawmode:=listdrawall; + end; +end; + +Procedure Sortarray(menu:listtype); +var lop2,lop:byte; +Begin +with menu^ do +For lop:=1 to maxopts do + For lop2:=lop to maxopts do begin + if info^[lop2]xoff_) or (yoff<>yoff_) then begin + with xbar^ do state:=state or sfmute; + with ybar^ do state:=state or sfmute; + xoff:=xoff_; + yoff:=yoff_; + xbar^.setval(xoff); + ybar^.setval(yoff); + with xbar^ do state:=state xor sfmute; + with ybar^ do state:=state xor sfmute; + drawview; + end; +end; + +procedure delta_.changeworld(var bounds:trect); +var add,sub:integer; + loader:trect; + resize:boolean; +begin + world:=bounds; + if world.x1=0 then begin + add:=0;sub:=x2-x1; + end else begin + add:=halfx;sub:=add; + end; + {disable out events from the bars to prevent 'setoffsets' being + called too many times} + with xbar^ do state:=state or sfmute; + with ybar^ do state:=state or sfmute; + xbar^.setrange(world.x1+add,world.x2-sub,xbar^.offs); + if world.y1=0 then begin + add:=0;sub:=y2-y1; + end else begin + add:=halfy;sub:=add; + end; + ybar^.setrange(world.y1+add,world.y2-sub,ybar^.offs); + with xbar^ do state:=state xor sfmute; + with ybar^ do state:=state xor sfmute; + {now you call setoffsets} + setoffsets(xbar^.offs,ybar^.offs); +end; + +procedure delta_.changebounds(var bounds:trect); +begin + inherited changebounds(bounds); + if (xbar<>nil)and(ybar<>nil)then begin + with xbar^ do state:=state and not sfvisible; + with ybar^ do state:=state and not sfvisible; + state:=state xor sfvisible; + changeworld(world); + with xbar^ do state:=state or sfvisible; + with ybar^ do state:=state or sfvisible; + state:=state or sfvisible; + end; +end; + +procedure delta_.handlevent(var event:tevent); +var oldx,oldy:integer; +begin + inherited handlevent(event); + with event do + if ((what=EvCommand)and(command=CMDcentrewindow)) + or ((what=EvKeyDown)and(ScanCode=Homekey)) then begin + what:=0; + oldx:=xbar^.offs;oldy:=ybar^.offs; + state:=state and not sfvisible; + xbar^.setval(0); + ybar^.setval(0); + state:=state or sfvisible; + if (xbar^.offs<>oldx)or(ybar^.offs<>oldy) then + drawview; + end; +end; + +{*===================================*} +{* -*Border type*- *} +{*===================================*} + +Constructor bordertype_.create(xa,ya,xb,yb:integer;size_:byte); +begin + inherited create(xa,ya,xb,yb); + size:=size_-1; +end; + +procedure bordertype_.draw; +begin + draw3dborder(x1,y1,x2,y2,false); + t_col:=midcol; + Thickrectangle(x1+1,y1+1,x2-1,y2-1,size-1); + draw3dborder(x1+size,y1+size,x2-size,y2-size,true) +end; + +{*===================================*} +{* -*Dialog Back*- *} +{*===================================*} + +procedure Dialogback_.draw; +begin + outbox(x1,y1,x2,y2); + inherited draw; +end; + +{*===================================*} +{* -*Add title procedure*- *} +{*===================================*} + +procedure add_title(group:tgroup;tname:string); +var w,h:integer; +begin + with group^ do begin + w:=x2-x1; + h:=y2-y1; + insert(new(Textbutton, + create(x1+hbord+1,y1,w-(hbord shl 1)-2,vbord,titlecol,0,BM_clickaction,0,CMDmoveparent,tname))); + first^.growmode:=TGgrowallx+TGdragy1; + first^.options:=first^.options and not oftabcycleselect; + insert(new(Tpicbutton,create(x1,y1,hbord,vbord,midcol,0,BM_clickAction,CMDwindowmenu,200,@closegadget))); + first^.growmode:=TGdragx1+TGdragy1; + first^.options:=first^.options and not oftabcycleselect; + insert(new(Tpicbutton,create(x2-hbord,y1,hbord,vbord,midcol,0,BM_ReleaseAction,CMDzoomwindow,0,@updownarrow))); + first^.growmode:=TGdragx2+TGdragy1; + first^.options:=first^.options and not oftabcycleselect; + end; +end; + +{*===================================*} +{* -*Window type*- *} +{*===================================*} + +Constructor windowtype_.create(x,y,W,H:integer;tname:string;action_window:delta;menu_:tpopupmenu); +const +barsegs=300; +var +loader:trect; +min,max:integer; +begin + inc(x,xbord);inc(y,xbord);dec(W,xbord);dec(H,xbord); + inherited create(x,y,x+W,y+H); + growmode:=0; + options:=options or (ofnooverlap + oftopselect); + loader.rassign(x1,y1+vbord+1,x2-scrollbar_size-1,y2-scrollbar_size-1); + deltaview:=action_window; + + insert(deltaview); + add_title(@self,tname); + maximizegadget:=pointer(first); + + insert(new(bartype,create(x2-scrollbar_size,y1+vbord+1,scrollbar_size, + H-scrollbar_size-vbord-2,0,0,0,ybardir))); + action_window^.ybar:=slidertype(tgroup(first)^.last); + insert(new(bartype,create(x1,y2-scrollbar_size,w-scrollbar_size-1, + scrollbar_size,0,0,0,xbardir))); + action_window^.xbar:=slidertype(tgroup(first)^.last); + + insert(new(tpicbutton,create(x2-scrollbar_size,y2-scrollbar_size,scrollbar_size,scrollbar_size, + midcol,0,BM_ClickAction,CMDresizeparent,0,@resizegadget))); + first^.growmode:=TGdragx2+TGdragy2; + {reform action window -it is safe to do so now} + with deltaview^ do begin + changebounds(loader); + if ((world.x2-world.x1)<(x2-x1))or + ((world.y2-world.y1)<(y2-y1)) then with world do begin + loader.rassign(x+x1,y+y1,x+x2+scrollbar_size+1,y+y2+vbord+scrollbar_size+2); + self.changebounds(loader); + end; + end; + + dec(x1,xbord);dec(y1,xbord);inc(x2,xbord);inc(y2,xbord); + insert(new(bordertype,create(x1,y1,x2,y2,xbord))); + menu:=menu_; + oldbounds.x:=x2-x1; + oldbounds.y:=y2-y1; + maximized:=false; +end; + +procedure windowtype_.handlevent(var event:tevent); +var loader:trect; +begin + inherited handlevent(event); + with event do + if what=Evcommand then + case command of + CMDmoveparent: + dragview(1,owner^,-32000,-32000,32000,32000); + CMDresizeparent:with deltaview^ do + self.dragview(0,SC.screenport,130,170, + wdeltax+(world.x2-world.x1),wdeltay+(world.y2-world.y1)); + CMDvalchanged:begin + with deltaview^ do + if infoptr=xbar then + setoffsets(xbar^.offs,yoff) + else + setoffsets(xoff,ybar^.offs); + end; + CMDzoomwindow:begin + if maximized then begin + loader.rassign(x1,y1,x1+oldbounds.x,y1+oldbounds.y); + reposview(loader); + end else begin + oldbounds.x:=x2-x1; + oldbounds.y:=y2-y1; + with deltaview^ do + loader.rassign(self.x1,self.y1,self.x1+wdeltax+(world.x2-world.x1),self.y1+wdeltay+(world.y2-world.y1)); + if ((owner^.x2-owner^.x1)<(loader.x2-loader.x1)) then begin + loader.x1:=owner^.x1;loader.x2:=owner^.x2; + end; + if ((owner^.y2-owner^.y1)<(loader.y2-loader.y1)) then begin + loader.y1:=owner^.y1;loader.y2:=owner^.y2; + end; + reposview(loader); + end; + maximized:=maximized xor true; + end; + CMDwindowmenu:if menu<>nil then begin + event.what:=evmousepressed; + menu^.doevent(x1+xbord,y1+vbord+xbord+1,event,menu,@self); + end; + else last^.handlevent(event); + end; +end; + +function Windowtype_.changeworld(var bounds:trect):boolean; +var tmprect:trect; + winwidth,winheight:integer; +const xdiff=(xbord shl 1)+scrollbar_size+1; + ydiff=(xbord shl 1)+vbord+scrollbar_size+2; +begin + with bounds do if ((x2-x1)>=(126-xdiff))and((y2-y1)>=(170-ydiff)) then begin + changeworld:=true; + with DeltaView^ do begin + state:=state and not SfVisible; + + ChangeWorld(bounds); + state:=state or SfVisible; + if ((bounds.x2-bounds.x1)<(x2-x1)) then + winwidth:=self.x1+(bounds.width)+xdiff + else + winwidth:=x2; + if ((bounds.height)<(y2-y1)) then + winheight:=self.y1+(bounds.height)+ydiff + else + winheight:=y2; + if (winheight<>y2)or(winwidth<>x2) then + with bounds do begin + tmprect.rassign(self.x1,self.y1,winwidth,winheight); + owner^.reposview(tmprect); + end else begin + Drawview; + end; + end; + end else changeworld:=false; +end; + +procedure Windowtype_.changebounds(var bounds:trect); +var diff:pointtype; +begin + with deltaview^.world do begin + diff.x:=(x2-x1)+Wdeltax; + diff.y:=(y2-y1)+Wdeltay; + end; + if (bounds.x2-bounds.x1)>diff.x then bounds.x2:=bounds.x1+diff.x; + if (bounds.y2-bounds.y1)>diff.y then bounds.y2:=bounds.y1+diff.y; + inherited changebounds(bounds); +end; + +{procedure windowtype_.SetState(AState: Word; Enable: Boolean); +var title:tbutton; +begin + if (astate and sfselected<>0) then begin + title:=tbutton(last^.prev); + if Enable then begin + title^.bkcol:=1; + end else begin + title^.bkcol:=titlecol; + end; + title^.drawview; + end; + inherited SetState(Astate,Enable); +end;} + +{*===================================*} +{* -*Choice Box*- *} +{*===================================*} +{these are used for making decisions -'cancel' and 'ok' are command events +sent to the owner} +Constructor choicebox_.create(x,y:integer;cancel,ok:word;txt:pchar); +const +W=200; +begin + inherited create(x,y,x+W,y+GetHeight(txt,w)+90); + CancelC:=cancel; + Okc:=Ok; + options:=options or (ofnooverlap+ofkeygrab+oftopselect+oftabcycleselect); + insert(new(textbutton,create(x1+30,y2-30,60,20,midcol,1,BM_releaseaction,1,okC,'Ok'))); + first^.growmode:=TGdragx2+TGdragy2; + insert(new(textbutton,create(x2-90,y2-30,60,20,midcol,1,BM_releaseaction,1,cancelC,'Cancel'))); + first^.growmode:=TGdragx1+TGdragy2; + insert(new(namebox,create(x1+40,y1+vbord+1,x2-8,y2-30,3,txt))); + growmode:=TGdragx2+TGdragy2; + add_title(@self,'System message'); +end; + +Procedure choicebox_.handlevent(var event:tevent); +begin + inherited handlevent(event); + with event do case what of + evcommand:case command of + CMDmoveparent:dragview(1,owner^,0,0,32000,32000); + else + if (command=OkC)or(command=CancelC) then begin + EvCallback(command); + delete; + end; + end; + {evkeydown:if charcode=#9 then selected^.next^.select;} + end; +end; + +procedure choicebox_.draw; +begin + outbox(x1,y1+vbord+1,x2,y2); + if warningsign<>nil then + putbitmap(x1+8,vbord+y1+20,warningsign); + inherited draw; +end; + +{*===================================*} +{* -*Message Box*- *} +{*===================================*} + + +{Simple message -'ok' can send an event if you want it to (set it to zero +as always, if you do not} +Constructor messagebox_.create(x,y:integer;ok:word;txt:pchar); +const +W=200; +begin + inherited create(x,y,x+W,y+GetHeight(txt,w)+90); + Okc:=Ok; + options:=options or (ofnooverlap+ofkeygrab+oftopselect); + insert(new(textbutton,create(x1+halfx-30,y2-30,60,20,midcol,1,BM_releaseaction,1,okC,'Ok'))); + first^.growmode:=TGdragx2+TGdragy2; + insert(new(namebox,create(x1+40,y1+vbord+1,x2-8,y2-30,3,txt))); + growmode:=TGdragx2+TGdragy2; + add_title(@self,'System message'); +end; + +Procedure messagebox_.handlevent(var event:tevent); +begin + inherited handlevent(event); + with event do case what of + evcommand:case command of + CMDmoveparent:dragview(1,owner^,0,0,32000,32000); + else if command=OkC then begin + EvCallback(command); + delete; + end; + end; + {evkeydown:if charcode=#13 then begin + EvCallback(Okc); + delete; + end;} + end; +end; + +procedure messagebox_.draw; +begin + outbox(x1,y1+vbord+1,x2,y2); + if warningsign<>nil then + putbitmap(x1+8,vbord+y1+20,warningsign); + inherited draw; +end; + +{tabgroup=^_tabgroup; +_tabgroup=object(tgroup_) + tabheight:integer; + drawmode:byte;} +Constructor tabgroup_.Create(x1_,y1_,x2_,y2_,tabheight_:integer); +begin + inherited create(x1_,y1_,x2_,y2_); + tabheight:=tabheight_; + lastx:=0; + drawpagetab:=nil; + +end; + + +procedure drawtab(x1,y1,x2,y2:integer;coffs:byte); +begin + t_col:=lightcol-coffs; + drawbytes(x1,y1,@tabtoplefthighlight,8); + hline(x1+8,x2-8,y1); + vline(x1,y1+8,y2); + t_col:=midcol-coffs; + t_fillcol:=t_col; + drawbytes(x1,y1,@tabtopleftbody,8); + drawbytes(x2-8,y1,@tabtoprightbody,8); + bar(x1+8,y1+1,x2-9,y2); + bar(x1+1,y1+8,x1+8,y2); + bar(x2-8,y1+8,x2-3,y2); + dec(t_col,1+coffs); + + drawbytes(x2-8,y1,@tabtoprightshadow1,8); + vline(x2-2,y1+8,y2); + + t_col:=mid_darkcol; + drawbytes(x2-8,y1,@tabtoprightshadow2,8); +end; + + +procedure tabgroup_.addtabpage(page:tabpage); +var +cpage:tabpage; + + +begin + insert(page); + cpage:=tabpage(first); + + + page^.pos.x1:=lastx; + + page^.pos.x2:=lastx+tstrlen(page^.name,@tcharset)+8; + lastx:=page^.pos.x2+1; + + page^.rassign(x1,y1+tabheight,x2,y2); +end; + +Procedure tabgroup_.handlevent(var event:tevent); +var +cpage:tabpage; +begin + inherited handlevent(event); + with event do begin + if what and evmousepressed<>0 then begin + cpage:=tabpage(first); + + while cpage<>nil do begin + if insiderect(x1+cpage^.pos.x1,y1,x1+cpage^.pos.x2,y1+tabheight,xm,ym) then + if cpage<>tabpage(selected) then begin + drawpagetab:=tabpage(selected); + cpage^.select; + selected:=cpage; + if drawpagetab<>nil then + drawview; + drawpagetab:=cpage; + drawview; + drawpagetab:=nil; + end; + cpage:=tabpage(cpage^.next); + end; + end; + end; +end; + +Procedure tabgroup_.Draw; +var cpage:tabpage; +begin + if drawpagetab<>nil then begin + cpage:=drawpagetab; + if cpage=tabpage(selected) then + drawtab(x1+cpage^.pos.x1,y1,x1+cpage^.pos.x2,y1+tabheight,0) + else + drawtab(x1+cpage^.pos.x1,y1,x1+cpage^.pos.x2,y1+tabheight,1); + t_col:=textcol; + outtextxy(x1+4+cpage^.pos.x1,y1+2,cpage^.name); + {drawtab(} + end else begin + t_fillcol:=grey2; + bar(x1,y1,x2,y2); + + + + cpage:=tabpage(first); + while(cpage<>nil) do begin + if cpage=tabpage(selected) then + drawtab(x1+cpage^.pos.x1,y1,x1+cpage^.pos.x2,y1+tabheight,0) + else + drawtab(x1+cpage^.pos.x1,y1,x1+cpage^.pos.x2,y1+tabheight,1); + + t_col:=textcol; + outtextxy(x1+4+cpage^.pos.x1,y1+2,cpage^.name); + cpage:=tabpage(cpage^.next); + end; + end; + + inherited draw; +end; + +constructor tabpage_.make(name_:string;icon_:bitmaptypeptr); +begin + name:=name_; + icon_:=icon; + inherited make; + options:=options or oftopselect; +end; +procedure tabpage_.draw; +begin + outbox(x1,y1,x2,y2); + if (owner^.selected=tview(@self)) then begin + t_col:=midcol; + hline(pos.x1,pos.x2,y1); + + end; + + inherited draw; + +end; + + +end. + diff --git a/TWINDRAW.PAS b/TWINDRAW.PAS new file mode 100644 index 0000000..28d673f --- /dev/null +++ b/TWINDRAW.PAS @@ -0,0 +1,699 @@ +Unit Twindraw; +{$X+}{$g+}{$a+} +INTERFACE + +uses ggraph,gbasics,chardef,SinCos,Tmaths; +{define backtex} + + +Const +circlepic:array[0..7] of byte=(0,24,60,126,126,60,24,0); +Tickpic:array[0..7] of byte=(0,1,3,6,140,216,112,32); +closegadget:array[0..7] of byte=(00,00,126,126,0,00,00,00); +uparrow:array[0..7] of byte=(24,60,126,255,60,60,60,60); +downarrow:array[0..7] of byte=(60,60,60,60,255,126,60,24); +resizegadget:array[0..7] of byte=(253,253,253,253,253,253,1,255); +leftarrow:array[0..7] of byte=(16,48,127,255,255,127,48,16); +rightarrow:array[0..7] of byte=(8,12,254,255,255,254,12,8); +updownarrow:array[0..7] of byte=(24,60,126,0,126,60,24,0); +{Diricon:array[0..7] of byte=(252,132,159,161,161,194,252,0); +Fileicon:array[0..7] of byte=(127,145,161,193,129,129,255,0); +flopdrivel:array[0..7] of byte=(255,128,143,129,128,128,255,255); +flopdriver:array[0..7] of byte=(255,1,241,129,49,1,255,255); +Harddrivel:array[0..7] of byte=(255,144,160,192,128,128,128,255); +Harddriver:array[0..7] of byte=(255,1,1,1,1,13,1,255);} + +gadgetsize=6; +border=8; +halfgadget=gadgetsize div 2; +maxborder=border+halfgadget; + +nodesize=2; +nodesizedec1=nodesize-1; + +{$ifdef backtex} + +black=0; {A} +grey1=4; {B} +grey2=6; {C} +grey3=8; {D} +grey4=9; {E} +grey5=12; {F} +grey6=13; {G} +white=15; {H} +darkblue=8;{I} +yellow=12; {J} +lightgreen=11;{K} +red=14; {L} +biege=12; {M} +{darkgreen=11; {N} +purple=9; {N} +blue=9; +orange=15; {O} +lightblue=10; {P} + +textboxcol=grey5; +Highlight=white; {for icons e.t.c.} +textcol=grey1; {text colour} +titletextcol=grey1; {for window titles} +scrollcol=grey2; {scroller background} +scrollhighlight=grey3; +lightcol=grey5; {highlight colour} +midcol=grey4; {button colour} +mid_darkcol=grey2; {shadow colour 1} +darkcol=grey1; {shadow colour 2} +backcol=darkblue; {background colour} +gridcol=blue; {grid colour} +selectcol=black; {selection colour} +titlecol=blue; {titlebar colour} +disabledcol=grey3; + +menuselcolback=grey2; + +menuselcolfore=white; +{$else} + + +black=0; {A} +grey1=1; {B} +grey2=2; {C} +grey3=3; {D} +grey4=4; {E} +grey5=5; {F} +grey6=6; {G} +white=7; {H} +darkblue=8;{I} +yellow=12; {J} +lightgreen=11;{K} +red=14; {L} +biege=12; {M} +{darkgreen=11; {N} +purple=9; {N} +blue=9; +orange=15; {O} +lightblue=10; {P} + +textboxcol=grey5; +Highlight=white; {for icons e.t.c.} +textcol=grey1; {text colour} +titletextcol=grey1; {for window titles} +scrollcol=grey2; {scroller background} +scrollhighlight=grey3; +lightcol=grey5; {highlight colour} +midcol=grey4; {button colour} +mid_darkcol=grey2; {shadow colour 1} +darkcol=grey1; {shadow colour 2} +backcol=darkblue; {background colour} +gridcol=blue; {grid colour} +selectcol=black; {selection colour} +titlecol=blue; {titlebar colour} +disabledcol=grey3; + +menuselcolback=grey2; + +menuselcolfore=grey4; +{$endif} + + +var +backtex:bitmaptypeptr; +backdark:bitmaptypeptr; +{type +barprocedure=procedure(x1,y1,x2,y2:integer);} + +Procedure Outtextxy3d(x,y:integer;txt:string); +Procedure OuttextxyU(x,y:integer;txt:string;underchar:byte); +Procedure OuttextxyU3d(x,y:integer;txt:string;underchar:byte); +Procedure Drawx(x,y:integer); +Procedure drawcursor(x,y:integer); +Procedure grid(x,y,gxsize,gysize,stpx,stpy:integer); +Procedure dotgrid(x,y,gxsize,gysize,stpx,stpy:integer); +Procedure boxgrid(x,y:integer;gxsize,gysize,stpx,stpy:integer); +Procedure colourgrid(x,y:integer;gxsize,gysize,stpx,stpy:integer;scol:byte); +Procedure stipcolourgrid(x,y:integer;gxsize,gysize,stpx,stpy,scol:integer); +Procedure stipcolourgridb(x,y:integer;gxsize,gysize,stpx,stpy,scol:integer); +Procedure solidrect(x1,y1,x2,y2:integer); + +Procedure ButtonBar(x1,y1,x2,y2:integer); +Procedure ButtonBarDown(x1,y1,x2,y2:integer); +Procedure outbox(x1,y1,x2,y2:integer); +Procedure outboxcol(x1,y1,x2,y2:integer); +Procedure inbox(x1,y1,x2,y2:integer); +Procedure inboxcol(x1,y1,x2,y2:integer); +Procedure inboxcolb(x1,y1,x2,y2:integer); +Procedure Insetborder(x1,y1,x2,y2:integer;txt:string); +Procedure textcurs(x,y,y2:integer); +Procedure textsel(x,y,x2:integer); +Procedure textbox(x1,y1,x2,y2:integer); +Procedure textboxfilled(x1,y1,x2,y2:integer); +Procedure hline3d(x1,x2,y1:integer); +procedure draw3dborder(x1,y1,x2,y2:integer;inv:boolean); +procedure rectangle_rotated(x1,y1,x2,y2,cx,cy:integer;angle:real); +Procedure drawbound(x1,y1,x2,y2:integer); +procedure rotate_point(var x,y:integer;cx,cy:integer;angle:real); +procedure DrawArrow(x1,y1,x2,y2:integer); +Function lineangle(x1,y1,x2,y2:integer):integer; +procedure drawboundmulti(x1,y1,x2,y2,x3,y3,x4,y4:longint;count:integer;drawfirst:boolean); +procedure rectangle_rotatedmulti(x1,y1,x2,y2,cx,cy:integer;angle,oldangle:real;num:integer;drawfirst:boolean); + +IMPLEMENTATION + +procedure tilebitmap; +var xlop,ylop:byte; +begin + + for ylop:=0 to SC.size.y shr 6 do + for xlop:=0 to SC.size.x shr 6 do + putbitmap(xlop shl 6,ylop shl 6,backtex); + +end; + + +procedure tilebitmapb; +var xlop,ylop:byte; +begin + + for ylop:=0 to SC.size.y shr 6 do + for xlop:=0 to SC.size.x shr 6 do + putbitmap(xlop shl 6,ylop shl 6,backdark); + +end; + +procedure ButtonBar(x1,y1,x2,y2:integer); +var oldvp,temp:trect; + +begin + {$ifdef backtex} + oldvp:=SC.viewport; + temp.rassign(x1,y1,x2,y2); + SC.viewport.intersect(temp); + + tilebitmap; + SC.viewport:=oldvp; + {$else} + + bar(x1,y1,x2,y2); + {$endif} +end; + +procedure ButtonBarDown(x1,y1,x2,y2:integer); +var oldvp,temp:trect; + +begin + {$ifdef backtex} + oldvp:=SC.viewport; + temp.rassign(x1,y1,x2,y2); + SC.viewport.intersect(temp); + + tilebitmapb; + SC.viewport:=oldvp; + {$else} + + bar(x1,y1,x2,y2); + {$endif} + + +end; + + +Procedure outboxcol(x1,y1,x2,y2:integer); +var oldvp,temp:trect; +Begin + {$ifdef backtex} + oldvp:=SC.viewport; + temp.rassign(x1+1,y1+1,x2-2,y2-2); + SC.viewport.intersect(temp); + + tilebitmap; + SC.viewport:=oldvp; + {$else} + bar(x1+1,y1+1,x2-2,y2-2); + {$endif} + + + t_col:=lightcol;vline(x1,y1,y2-1); hline(x1,x2-1,y1); + t_col:=highlight;putpixel(x1,y1); + t_col:=grey3;vline(x2-1,y1+1,y2-1);hline(x1+1,x2-1,y2-1); + t_col:=darkcol;vline(x2,y1,y2); hline(x1,x2,y2); +end; + +Procedure outbox(x1,y1,x2,y2:integer); +var +oldvp,temp:trect; + +Begin + {$ifdef backtex} + oldvp:=SC.viewport; + temp.rassign(x1+1,y1+1,x2-2,y2-2); + SC.viewport.intersect(temp); + + tilebitmap; + SC.viewport:=oldvp; + {$else} + t_fillcol:=midcol;bar(x1+1,y1+1,x2-2,y2-2); + {$endif} + + + + t_col:=lightcol;vline(x1,y1,y2-1); hline(x1,x2-1,y1); + t_col:=highlight;putpixel(x1,y1); + t_col:=grey3;vline(x2-1,y1+1,y2-1);hline(x1+1,x2-1,y2-1); + t_col:=darkcol;vline(x2,y1,y2); hline(x1,x2,y2); +end; + +Procedure inbox(x1,y1,x2,y2:integer); + +var +oldvp,temp:trect; + +Begin + {$ifdef backtex} + oldvp:=SC.viewport; + temp.rassign(x1+1,y1+1,x2,y2); + SC.viewport.intersect(temp); + tilebitmapb; + SC.viewport:=oldvp; + {$else} + + t_fillcol:=midcol;bar(x1+2,y1+2,x2,y2); + {$endif} + t_col:=mid_darkcol;vline (x1+1,y1+1,y2);hline (x1+1,x2,y1+1); + t_col:=darkcol;vline (x1,y1,y2);hline (x1,x2,y1); +end; + +Procedure inboxcol(x1,y1,x2,y2:integer); +var +oldvp,temp:trect; + +Begin + {$ifdef backtex} + oldvp:=SC.viewport; + temp.rassign(x1+1,y1+1,x2,y2); + SC.viewport.intersect(temp); + tilebitmapb; + SC.viewport:=oldvp; + {$else} + bar(x1+2,y1+2,x2,y2); + {$endif} + t_col:=mid_darkcol;vline (x1+1,y1+1,y2);hline (x1+1,x2,y1+1); + t_col:=darkcol;vline (x1,y1,y2);hline (x1,x2,y1); +end; + +Procedure inboxcolb(x1,y1,x2,y2:integer); +Begin + bar(x1+1,y1+1,x2-1,y2-1); + t_col:=darkcol;vline (x1,y1,y2);hline (x1,x2,y1); + t_col:=lightcol;vline (x2,y1+1,y2-1);hline (x1+1,x2-1,y2); + t_col:=15;putpixel(x2,y2); +end; + +Procedure Insetborder(x1,y1,x2,y2:integer;txt:string); +Begin + t_col:=(darkcol); + outtextxy(x1+8,y1-2,txt); + vline(x1,y1+1,y2-1);vline(x2,y1+1,y2-1); + t_col:=(15); + vline(x1+1,y1+1,y2-1);vline(x2+1,y1+1,y2); + hline3d(x1+1,x1+4,y1+1);hline3d(x1+10+TStrlen(txt,@tcharset),x2-1,y1+1); + hline3d(x1+1,x2+1,y2+1); +end; + +Procedure Hline3d(x1,x2,y1:integer); +begin + hline(x1,x2,y1+1); + t_col:=darkcol; + hline(x1,x2,y1); +end; + +Procedure grid(x,y,gxsize,gysize,stpx,stpy:integer); +var lop,x2,y2:integer; +Begin + x2:=gxsize*stpx; + y2:=gysize*stpy; + For lop:=1 to stpx do + vline(x+(lop*gxsize),y-1,y2+y-1); + For lop:=1 to stpy do + hline(x+1,x2+x+1,y+(lop*gysize)); +End; + +Procedure dotgrid(x,y,gxsize,gysize,stpx,stpy:integer); +var xlop,ylop,ycount:integer; +Begin + For xlop:=1 to stpx do begin + ycount:=y; + For ylop:=1 to stpy do begin + {hline(x,x,ycount);} + putpixel(x,ycount); + inc(ycount,gysize); + {ycount:=ycount+gysize;} + end; + inc(x,gxsize); + {x:=x+gxsize;} + end; +End; + +Procedure boxgrid(x,y:integer;gxsize,gysize,stpx,stpy:integer); +var xlop,ylop:byte; +Begin + For ylop:=0 to stpy-1 do + For xlop:=0 to stpx-1 do + outbox(x+(xlop*gxsize),y+(ylop*gysize), + x+(xlop*gxsize)+gxsize-1,y+(ylop*gysize)+gysize-1); +End; + +Procedure colourgrid(x,y:integer;gxsize,gysize,stpx,stpy:integer;scol:byte); +var xlop,ylop:byte; +Begin + t_fillcol:=scol; + For ylop:=0 to stpy-1 do + For xlop:=0 to stpx-1 do + Begin + bar(x+(xlop*gxsize),y+(ylop*gysize), + x+(xlop*gxsize)+gxsize-1,y+(ylop*gysize)+gysize-1); + inc(t_fillcol); + end; +End; + +Procedure stipcolourgrid(x,y:integer;gxsize,gysize,stpx,stpy,scol:integer); +var xlop,ylop,stipval:byte; + blackrun:boolean; +Begin + t_col:=scol div 64; + blackrun:=(scol and 63)<=31; + if blackrun then + t_fillcol:=black + else + t_fillcol:=white; + stipval:=scol mod 32; + For ylop:=0 to stpy-1 do + For xlop:=0 to stpx-1 do + Begin + setfillpattern(greyfills[stipval xor (byte(blackrun) * 31)],true); + bar(x+(xlop*gxsize),y+(ylop*gysize), + x+(xlop*gxsize)+gxsize-1,y+(ylop*gysize)+gysize-1); + if stipval=maxgreyfills then begin + if blackrun then begin + t_fillcol:=white; + blackrun:=blackrun xor true; + end else begin + t_col:=t_col+1; + t_fillcol:=black; + blackrun:=blackrun xor true; + end; + stipval:=0; + end else inc(stipval); + end; + setsolidfill; +End; + +Procedure stipcolourgridb(x,y:integer;gxsize,gysize,stpx,stpy,scol:integer); +var xlop,ylop,stipval:byte; +Begin + t_col:=scol div 32; + t_fillcol:=t_col+1; + stipval:=scol mod 32; + For ylop:=0 to stpy-1 do + For xlop:=0 to stpx-1 do + Begin + setfillpattern(greyfills[stipval],true); + bar(x+(xlop*gxsize),y+(ylop*gysize),x+(xlop*gxsize)+gxsize-1,y+(ylop*gysize)+gysize-1); + if stipval=maxgreyfills then begin + inc(t_col); + inc(t_fillcol); + stipval:=0; + end else inc(stipval); + end; + setsolidfill; +End; + +Procedure textbox(x1,y1,x2,y2:integer); +Begin + T_col:=grey4;hline(x1+1,x2-2,y1+1); + vline(x1+1,y1+1,y2-2); + T_col:=grey6;hline(x1+1,x2-1,y2-1); + vline(x2-1,y1+1,y2-1); + t_col:=darkcol;rectangle(x1,y1,x2,y2); +end; + +Procedure textboxfilled(x1,y1,x2,y2:integer); +Begin + T_col:=grey4;hline(x1+1,x2-2,y1+1); + vline(x1+1,y1+1,y2-2); + T_col:=grey6;hline(x1+1,x2-1,y2-1); + vline(x2-1,y1+1,y2-1); + t_col:=darkcol;rectangle(x1,y1,x2,y2); + T_fillcol:=textboxcol; + bar(x1+2,y1+2,x2-2,y2-2); +end; + +Procedure textsel(x,y,x2:integer); +Begin +if x>x2 then asm mov ax,x;Xchg x2,ax;mov x,ax;end; +if x<>x2 then Begin dec(x2);solidrect(x,y,x2,y+8);end; +end; + +Procedure textcurs(x,y,y2:integer); +begin + Hline(x-2,x+2,y-1); + Hline(x-2,x+2,y+y2); + Vline(x,y,y+y2-1); +end; + +Procedure solidrect(x1,y1,x2,y2:integer); +Var lop:word; +Begin +For lop:=y1 to y2 do + HLine(x1,x2,lop); +End; + +Procedure drawcursor(x,y:integer); +Begin + hLine(x-7,x+7,y); + hLine(x-7,x+7,y+1); + vLine(x+1,y-7,y+7); + vLine(x,y-7,y+7); +End; + +Procedure Drawx(x,y:integer); +Begin + Line(x-5,y-5,x+5,y+5); + Line(x-5,y+5,x+5,y-5); +End; + +procedure rotate_point(var x,y:integer;cx,cy:integer;angle:real); +var tmp:integer; +begin + + if angle<>0 then begin + dec(x,cx);dec(y,cy); + tmp:=trunc((x*cos(angle)) - (y* sin(angle)) ); + y:=trunc( (x* sin(angle)) + (y*cos(angle)) ); + x:=tmp; + inc(x,cx);inc(y,cy); + end; +end; + +procedure draw3dborder(x1,y1,x2,y2:integer;inv:boolean); +begin + if inv then t_col:=darkcol else t_col:=lightcol; + hline(x1,x2,y1); + vline(x1,y1,y2-1); + if inv then t_col:=lightcol else t_col:=darkcol; + hline(x1,x2-1,y2); + vline(x2,y1,y2); + t_col:=highlight; + if inv then + putpixel(x2,y2) + else + putpixel(x1,y1); +end; + +{the first drawn rectangle often stays still so you have the option to draw it or not to avoid flicker} +procedure rectangle_rotatedmulti(x1,y1,x2,y2,cx,cy:integer;angle,oldangle:real;num:integer;drawfirst:boolean); +var +addstep,cangle:real; +lop:word; +begin + + if (num>0) and(angle<>oldangle) then begin + + cangle:=0; + addstep:=(angle-oldangle) /num; + SetLinePattern(170,false); + for lop:=0 to num-1 do begin + if (lop<>0)or(drawfirst) then + rectangle_rotated(x1,y1,x2,y2,cx,cy,cangle); + cangle:=cangle+addstep; + end; + SetLinePattern(255,false); + end; + rectangle_rotated(x1,y1,x2,y2,cx,cy,angle); +end; + +procedure rectangle_rotated(x1,y1,x2,y2,cx,cy:integer;angle:real); +var p:array[0..7] of pointtype; + lop:byte; + dist:real; + tmp:integer; +begin + dec(x1,border);dec(y1,border); + inc(x2,border);inc(y2,border); + p[0].x:=x1;p[0].y:=y1; + p[1].x:=x2;p[1].y:=y1; + + p[2].x:=x2;p[2].y:=y1+1; + p[3].x:=x2;p[3].y:=y2-1; + + p[4].x:=x1;p[4].y:=y2; + p[5].x:=x2;p[5].y:=y2; + + p[6].x:=x1;p[6].y:=y1+1; + p[7].x:=x1;p[7].y:=y2-1; + + + + if angle<>0 then + for lop:=0 to 7 do with p[lop] do begin + rotate_point(x,y,cx,cy,angle); + end; + + + + + + line(p[0].x,p[0].y,p[1].x,p[1].y); + line(p[2].x,p[2].y,p[3].x,p[3].y); + line(p[4].x,p[4].y,p[5].x,p[5].y); + line(p[6].x,p[6].y,p[7].x,p[7].y); +end; + +procedure drawboundmulti(x1,y1,x2,y2,x3,y3,x4,y4:longint;count:integer;drawfirst:boolean); +var addx1,addy1,addx2,addy2, + px1,py1,px2,py2:longint; + lop:word; +const + s=halfgadget; + shiftby=16; + +begin + + if (count>0)and((x1<>x3)or(x2<>x4)or(y1<>y3)or(y2<>y4)) then begin + + x1:=x1 shl shiftby; + y1:=y1 shl shiftby; + x2:=x2 shl shiftby; + y2:=y2 shl shiftby; + addx1:=((x3 shl shiftby)-x1)div count; + addy1:=((y3 shl shiftby)-y1)div count; + addx2:=((x4 shl shiftby)-x2)div count; + addy2:=((y4 shl shiftby)-y2)div count; + + SetLinePattern(170,false); + for lop:=1 to count do begin + if (lop<>1)or(drawfirst) then + rectangle((x1 shr shiftby)-s,(y1 shr shiftby)-s, + (x2 shr shiftby)+s,(y2 shr shiftby)+s); + inc(x1,addx1); + inc(y1,addy1); + inc(x2,addx2); + inc(y2,addy2); + end; + SetLinePattern(255,false); + end; + drawbound(x3,y3,x4,y4); +end; + + + + +Procedure drawbound(x1,y1,x2,y2:integer); +const s=halfgadget; +var halfx,halfy:integer; +Begin + dec(x1,border);dec(y1,border);inc(x2,border);inc(y2,border); + Rectangle(x1,y1,x2,y2); + Rectangle(x2-s,y2-s,x2+s,y2+s); + Rectangle(x1-s,y2-s,x1+s,y2+s); + Rectangle(x1-s,y1-s,x1+s,y1+s); + Rectangle(x2-s,y1-s,x2+s,y1+s); + halfx:=(x2-x1) shr 1; + halfy:=(y2-y1) shr 1; + Rectangle(halfx+x1-s,y2-s,halfx+x1+s,y2+s); + Rectangle(x2-s,halfy+y1-s,x2+s,halfy+y1+s); + Rectangle(halfx+x1-s,y1-s,halfx+x1+s,y1+s); + Rectangle(x1-s,halfy+y1-s,x1+s,halfy+y1+s); +end; + +Function lineangle(x1,y1,x2,y2:integer):integer; +var hyp,opp,adj:integer; + tmp:real; +begin + opp:=abs(x2-x1); + adj:=abs(y2-y1); + Hyp:=isqrt((opp*opp)+(adj*adj)); + if hyp=0 then hyp:=1; + lineangle:=round(sin(sin(90)*opp )/hyp); +end; + +procedure DrawArrow(x1,y1,x2,y2:integer); +{var p1,p2:pointtype; + angle:integer;} + +begin + line(x1,y1,x2,y2); + drawbytes(x2-4,y2-4,@circlepic,8); + {p1.x:=x2-6;p1.y:=x2+6; + p2.x:=x2+6;p2.y:=x2+6; + angle:=lineangle(x1,y1,x2,y2); + rotate_point(p1.x,p1.y,x2,y2,angle); + rotate_point(p2.x,p2.y,x2,y2,angle); + line(x2-1,y2-1,p1.x,p1.y); + line(x2+1,y2+1,p2.x,p2.y);} +end; + +Procedure Outtextxy3d(x,y:integer;txt:string); +begin + t_col:=lightcol; + Outtextxy(x+1,y+1,txt); + t_col:=textcol; + Outtextxy(x,y,txt); +end; + +Procedure OuttextxyU(x,y:integer;txt:string;underchar:byte); +var lop:byte; + xpos:integer; +begin + outtextxy(x,y,txt); + if underchar>0 then begin + lop:=fontmax; + while (lop>=0) and (Tcharset.typeface[ord(txt[underchar]),lop]=0) do + dec(lop); + xpos:=x+(TStrlen_at(txt,underchar,@tcharset)); + hline(xpos,xpos+tcharset.widths[ord(txt[underchar])]-2,y+2+lop); + end; +end; + +Procedure OuttextxyU3d(x,y:integer;txt:string;underchar:byte); +begin + t_col:=lightcol; + OuttextxyU(x+1,y+1,txt,underchar); + t_col:=textcol; + OuttextxyU(x,y,txt,underchar); +end; + +end. +Highlight=15; {for icons e.t.c.} +textcol=3; {text colour} +titletextcol=3; {for window titles} +scrollcol=14; {scroller background} +lightcol=6; {highlight colour} +midcol=5; {middle colour} +mid_darkcol=4; {shadow colour} +darkcol=3; {shadow colour} +backcol=2; {background colour} +gridcol=1; {grid colour} +selectcol=15; {selection colour} +titlecol=13; {titlebar colour} +disabledcol=4; +menuselcolback=10; +menuselcolfore=12; \ No newline at end of file diff --git a/VECTFONT.PAS b/VECTFONT.PAS new file mode 100644 index 0000000..e8645dc --- /dev/null +++ b/VECTFONT.PAS @@ -0,0 +1,193 @@ +Unit vectfont; +INTERFACE +uses ggraph,ttypes; + +const +Prefix_Size=$80; +Major_Version=1; +Minor_Version=0; +SIGNATURE='+'; + +type +op_codes=(end_of_char,do_scan,moveit,drawit); + +Fheader=record + header_size :word; { Version 2.0 Header Format } + font_name :string[4]; { Font Internal Name } + font_size :integer; { Size in byte of file } + font_major, font_minor:byte; { Driver Version Information } + min_major, min_minor :byte; { BGI Revision Information } +end; + +Header_type=record + sig :char; { SIGNATURE byte } + nchrs :integer; { number of characters in file } + mystery :byte; { Currently Undefined } + first :byte; { first character in file } + cdefs :integer; { offset to char definitions } + scan_flag :boolean; { True if set is scanable } + org_to_cap :shortint; { Height from origin to top of capitol } + org_to_base:shortint; { Height from origin to baseline } + org_to_dec :shortint; { Height from origin to bot of decender} + fntname :string[3]; { Four character name of font } + unused :byte; { Currently undefined } +end; + +stroke_type=record + opcode:op_codes; { Stroke opcode byte } + x,y:shortint; +end; + +strokearray=^strokearray_; +strokearray_=array[0..0] of stroke_type; + +stroke_char=record + num_ops:integer; + S:strokearray; +end; + +font_type=object + first,nchars:byte; + org_to_cap,org_to_base,org_to_dec :shortint; + Strokes:array[0..255]of stroke_char; + Widths:array[0..255] of byte; + Procedure drawbm(xoff,yoff,zoom:integer;text:string); + Procedure draw(xoff,yoff,zoom:integer;text:string); + function load(filename:string):boolean; + Procedure done; +end; + +IMPLEMENTATION + +function font_type.load(filename:string):boolean; +var +len,base:longint; +recsize,i:word; +ffile:file; + +Font:bytearray; {Dynamic array of font storage} +header:header_type; +Prefix:array[0..Prefix_size-1] of byte; +Offset:array[0..255] of word; + +{unpacking variables} +pb:^word; lop:integer; dummy:shortint; opc:op_codes; + +{decode a word} +Function decode(iptr:word;var x,y:shortint):byte; +type +decoder=record x,y:byte; end; +var cword:decoder; +tmp:byte; +begin + cword:=decoder(iptr); + x:=(cword.x and 127); + tmp:=(cword.y and 127); + {if top bit of singed thingy is set then copy over} + if boolean(tmp and 64) then tmp:=tmp+128; + y:=(org_to_cap)-tmp; + cword.x:=(cword.x and 128) shr 7; + cword.y:=(cword.y and 128) shr 7; + decode:=(cword.x shl 1)+cword.y; +end; + +begin + recsize:=1; + assign(ffile,filename); + reset(ffile,recsize); + + blockread(ffile,prefix,prefix_size,recsize); + blockread(ffile,header,sizeof(header),recsize); + if header.sig<>signature then begin + load:=false; + close(ffile); + exit; + end; + first:=header.first; + nchars:=header.nchrs; + org_to_cap:=header.org_to_cap; + org_to_dec:=header.org_to_dec; + org_to_base:=header.org_to_base; + blockread(ffile,offset[first],nchars shl 1,recsize); + blockread(ffile,widths[first],nchars,recsize); + + len:=filesize(ffile)-filepos(ffile); + + {allocate space for and load in font raw data} + getmem(font,len); + if font=nil then begin load:=false;exit end; + blockread(ffile,font^,len,recsize); + for i:=first to first+nchars-1 do begin + {pointer position in font list} + pb:=@font^[offset[i]]; + strokes[i].num_ops:=0; + opc:=moveit; + + While opc<>end_of_char do begin + opc:=op_codes(decode(pb^,dummy,dummy)); + inc(pb); + inc(strokes[i].num_ops); + end; + {dec(strokes[i].num_ops,2);} + + getmem(strokes[i].s,strokes[i].num_ops*sizeof(stroke_type)); + if strokes[i].s<>nil then begin + pb:=@font^[offset[i]]; + for lop:=0 to strokes[i].num_ops-1 do begin + with strokes[i].s^[lop] do + opcode:=op_codes(decode(pb^,x,y)); + inc(pb); + end; + end else begin load:=false;exit;end; + end; + freemem(font,len); + close(ffile); + load:=true; +end; +Procedure font_type.drawbm(xoff,yoff,zoom:integer;text:string); +var lop,tmp:byte; +lop1,mx,my:integer; +stroke:^stroke_type; +begin + for lop:=1 to ord(text[0]) do begin + tmp:=ord(text[lop]); + stroke:=pointer(strokes[tmp].s); + for lop1:=0 to strokes[tmp].num_ops-3 do + with stroke^ do begin + if opcode=drawit then + bmline(zoom*mx+xoff,zoom*my+yoff,zoom*x+xoff,zoom*y+yoff); + mx:=x;my:=y; + inc(stroke); + end; + inc(xoff,widths[tmp]*zoom); + end; +end; + + +Procedure font_type.draw(xoff,yoff,zoom:integer;text:string); +var lop,tmp:byte; +lop1,mx,my:integer; +stroke:^stroke_type; +begin + for lop:=1 to ord(text[0]) do begin + tmp:=ord(text[lop]); + stroke:=pointer(strokes[tmp].s); + for lop1:=0 to strokes[tmp].num_ops-3 do + with stroke^ do begin + if opcode=drawit then + line(zoom*mx+xoff,zoom*my+yoff,zoom*x+xoff,zoom*y+yoff); + mx:=x;my:=y; + inc(stroke); + end; + inc(xoff,widths[tmp]*zoom); + end; +end; + +Procedure font_type.done; +var i:word; +begin + for i:=first to first+nchars-1 do + freemem(strokes[i].s,strokes[i].num_ops*sizeof(stroke_type)); +end; + +end. \ No newline at end of file diff --git a/VESAINFO.PAS b/VESAINFO.PAS new file mode 100644 index 0000000..490ab53 --- /dev/null +++ b/VESAINFO.PAS @@ -0,0 +1,148 @@ +UNIT vesainfo; +INTERFACE +uses ttypes; + + +const +SVGAok= $004F;{ Function is supported} +SVGAErr2 = $4F00;{ Function is not supported} +SVGAErr3 = $0000;{ Function call successful} +SVGAErr4 = $0100;{ Function call failed} +SVGAErr5 = $0200;{ Software supports this function, but the hardware does not} +SVGAErr6 = $0300;{ Function call invalid in current video mode} + +{Errstrings:array[0..5] of string=('Function is supported'} +TEST_SVGA640x400x256=5; +TEST_SVGA640x480x256=1; +TEST_SVGA800x600x256=3; +TEST_SVGA1024x768x256=5; + +type + +headerblockptr= ^headerblock; +headerblock=record + VESAsig:array[0..3] of char; + VESAversion:word; + OEMStringPtr:byteptr; + Capabilities:byte; + Modelist:wordptr; + totalmemory:word; + emSoftwareRev:word; + OemVendorNamePtr:Pchar; + OemProductNamePtr:Pchar; + OemProductRevPtr:Pchar; + reserved:array[0..237] of byte; +end; + + + + +infoblockptr=^infoblocktype; +infoblocktype=record + ModeAttributes :word ;{ mode attributes} + WinAAttributes :byte ;{ window A attributes} + WinBAttributes :byte ;{ window B attributes } + WinGranularity :word ;{ window granularity} + WinSize :word ;{ window size} + WinASegment :word ;{ window A start segment} + WinBSegment :word ;{ window B start segment} + WinFuncPtr :procedure;{ pointer to window function} + BytesPerScanLine :word ;{ bytes per scan line} + + { Mandatory information for VBE 1.2 and above} + XResolution :word ;{ horizontal resolution in pixels or chars} + YResolution :word ;{ vertical resolution in pixels or chars} + XCharSize :byte ;{ character cell width in pixels} + YCharSize :byte ;{ character cell height in pixels} + NumberOfPlanes :byte ;{ number of memory planes} + BitsPerPixel :byte ;{ bits per pixel} + NumberOfBanks :byte ;{ number of banks} + MemoryModel :byte ;{ memory model type} + BankSize :byte ;{ bank size in KB} + NumberOfImagePages :byte ;{ number of images} + Reserved :byte ;{ reserved for page function} + + { Direct Color fields (required for direct/6 and YUV/7 memory models)} + RedMaskSize :byte ;{ size of direct color red mask in bits} + RedFieldPosition :byte ;{ bit position of lsb of red mask} + GreenMaskSize :byte ;{ size of direct color green mask in bits} + GreenFieldPosition :byte ;{ bit position of lsb of green mask} + BlueMaskSize :byte ;{ size of direct color blue mask in bits} + BlueFieldPosition :byte ;{ bit position of lsb of blue mask} + RsvdMaskSize :byte ;{ size of direct color reserved mask in bits} + RsvdFieldPosition :byte ;{ bit position of lsb of reserved mask} + DirectColorModeInfo :byte ;{ direct color mode attributes} + + { Mandatory information for VBE 2.0 and above} + PhysBasePtr :longint ;{ physical address for flat frame buffer} + OffScreenMemOffset :pointer ;{ pointer to start of off screen memory} + OffScreenMemSize :word ;{ amount of off screen memory in 1k units} + Filler :array[0..206] of byte ;{ remainder of ModeInfoBlock} + + +end; + + +var +SVGAheader:headerblock; +SVGAinfo:infoblocktype; + + +function getvesaheaderinfo(infobloc:headerblockptr):word; +function getvesainfo(infobloc:infoblockptr;mode:word):word; + + +{Input: A Real-Mode pointer; +Output: The equivilant Protected-Mode pointer +Usage: PM_Pointer:=ConvertPtr(RM_Pointer); +Alternate: MyPointer:=ConvertPtr(MyPointer); +Restrictions: Must be in Protected Mode; Must have a DPMI host. +} + + +IMPLEMENTATION +function ConvertPtr(RMPointer:Pointer):pointer; assembler; +asm + mov ax,0002h + mov bx,word ptr RMPointer+2 {Convert the RM segment to PM selector} + int 31h {Call DPMI} + mov dx,ax {Return pointer in DX:AX} + mov ax,word ptr RMPointer {Offset is the same} +end; + + +function getvesaheaderinfo(infobloc:headerblockptr):word; +var retword:word; +begin + asm + + mov ah,4fh + mov al,00 + + {mov cx,mode} + les DI,infobloc + int $10 + mov retword,ax; + end; + infobloc^.modelist:=ConvertPtr(infobloc^.modelist); + getvesaheaderinfo:=retword; +end; + + +function getvesainfo(infobloc:infoblockptr;mode:word):word; +var retword:word; +begin + asm + + mov ah,4fh + mov al,01 + + mov cx,mode + les DI,infobloc + int $10 + mov retword,ax; + end; + + getvesainfo:=retword; +end; +end. \ No newline at end of file diff --git a/VESATEST.PAS b/VESATEST.PAS new file mode 100644 index 0000000..686311d --- /dev/null +++ b/VESATEST.PAS @@ -0,0 +1,23 @@ +program vesatest; + +uses vesainfo,ttypes,crt; +var +infoblock:headerblock; +modeinfoblock:infoblocktype; +modelist:wordptr; +ch:char; +begin +getvesaheaderinfo(@infoblock); +modelist:=infoblock.modelist; +while (modelist^<>-1) and (ch<>#27) do +begin + + getvesainfo(@modeinfoblock,modelist^); + writeln('Mode no:',modelist^); + + writeln('xres:',modeinfoblock.xresolution,' yres:',modeinfoblock.yresolution); + writeln('bpp:',modeinfoblock.bitsperpixel); + inc(modelist); + ch:=readkey; +end; +end. \ No newline at end of file diff --git a/VGA16.PAS b/VGA16.PAS new file mode 100644 index 0000000..5270cc5 --- /dev/null +++ b/VGA16.PAS @@ -0,0 +1,2179 @@ +Unit vga16; +{16 colour VGA driver (C) T.Lewis 1996} +{$X+}{$a+} +INTERFACE +{stuff to be preserved for mouse inter: + GRPH_ADDR + 3,logicmode + 0,colour + 5,WriteMode (Normaly 3) + 4,ReadMask +} + +uses gbasics,chardef,ttypes,tmaths; + +Const + + + +{VGA register locations} +MISC_ADDR=$3C2; MISC_READ_ADDR=$3CC; +ATTR_ADDR=$3c0; ATTR_DATA_ADDR=$3c1; +SEQU_ADDR=$3c4; SEQU_DATA_ADDR=$3c5; +CRTC_ADDR=$3D4; CRTC_DATA_ADDR=$3d5; +GRPH_ADDR=$3CE; GRPH_DATA_ADDR=$3CF; +STATUS_ADDR=$3da; + +noclear=128; +allplanes=3841; + +{Register masks} +data_rotate=$3; +chainfour=$8; +oddeven=$4; +exetendedmem=$2; +alphaon=$1; + +function set_mode(mode:byte):boolean; +Procedure bar(x1,y,x2,y2:integer); +Procedure GTriangle(xa,ya,xb,yb,xc,yc,ia,ib,ic:integer); +Procedure Triangle(xa,ya,xb,yb,xc,yc:integer); +Procedure Line(x1,y1,x2,y2:integer); +Procedure Hline(x1,x2,y:Integer); +Procedure Vline(x,y1,y2:Integer); +Procedure putpixel(x1,y1:Integer); +Function getpixel(x1,y1:Integer):byte; +Procedure outtextxy(x1,y1:integer;txt:string); +Procedure outtextxy_length(x1,y1:integer;txt:pchar;length:byte); +Procedure Drawbytes(x1,y:Integer;pic:bytearray;nbytes:byte); +Procedure Drawbytesxy(x1,y1:Integer;pic:bytearray;xbytes,ybytes:byte); +Procedure Screencopy(x1,y1,x2,y2,xd,yd:integer;page1,page2:byte); +procedure putbitmap(x1,y1:integer;bitmap:bitmaptypeptr); +function getbitmap(x1,y1,x2,y2:integer):bitmaptypeptr; +Procedure cleardevice; +procedure savescreenregs; +procedure restorescreenregs; + +{quick generic interface to screen -good for file loading} +Procedure QSetXY(x,y:integer); +Procedure Qwrite(count:word); +function Qget:byte; + +IMPLEMENTATION +{swaps two variables of arbitary length, inline into the code} +{stuff to be preserved for mouse inter: + GRPH_ADDR + 3,logicmode + 0,colour + 5,WriteMode (Normaly 3) + 4,ReadMask +} +var +oldlogicmode,oldcolour,oldwritemode,oldreadmask:byte; + +procedure savescreenregs; +begin +end; +procedure restorescreenregs; +begin +end; + +function set_mode(mode:byte):boolean; +var installed:boolean; +begin + if mode>100 then + asm mov ax,4F02h;mov bh,01h;mov bl,mode;sub bl,100;int 10h end + else + asm mov al,mode;mov ah,0;int 10h end; + asm + {Natural state for the video mode} + mov dx,GRPH_ADDR + mov al,data_rotate;mov ah,t_writemode; out dx,ax; {Logical mode} + xor ax,ax; out dx,ax; {colour} + mov ax,0B05h; out dx,ax; {writemode -3} + mov ax,0007h; out dx,ax; {set colour don't care} + mov ax,0ff08h; out dx,ax; {bitmask,255 func:8} + {correct oddering of the palette} + mov cx,15 + @runloop: + mov dx,STATUS_ADDR + in al,dx + mov dx,ATTR_ADDR + mov al,cl + out dx,al + out dx,al + loop @runloop + mov dx,STATUS_ADDR + in al,dx + mov dx,ATTR_ADDR + mov al,32; + out dx,al + end; + + set_mode:=TRUE; + {PatternMask:=$A0000+65535;} + {PatternAdrs:=PatternMask-8;} + + +end; + + + +Procedure cleardevice;assembler; +Asm + mov dx,GRPH_ADDR + mov al,3; mov ah,t_writemode; out dx,ax; {writemode} + xor al,al; mov ah,t_fillcol; out dx,ax; {colour} + mov ax,0B05h; out dx,ax; {writemode -3} + mov ax,0007h; out dx,ax; {set colour don't care} + mov ax,0FF08h; out dx,ax; {bitmask,255 func:8} + + les di,SC.scrptr + mov ax,$ffff {set fill mask} + mov cx,word ptr SC.pagesize {byte count} + shr cx,1 {half that...} + CLD {clear stuff} + REP STOSW {write to screen} +End; + +{clip a line against 'SC.viewport'} +function clip(var xas,yas,xbs,ybs:integer):boolean; +var code0,code1:byte; +var xa,ya,xb,yb:longint; +Begin + xa:=xas;ya:=yas;xb:=xbs;yb:=ybs; + + While 0=0 do begin + + code0:=(byte(xb>SC.viewport.x2))+ {right =$01} + (byte(yb>SC.viewport.y2)shl 1)+{bellow =$02} + (byte(xbSC.viewport.x2))+ {right =$01} + (byte(ya>SC.viewport.y2)shl 1)+{bellow =$02} + (byte(xadfy then....} + mov ax,x2 ; cmp x1,ax ; jle @no_swap + Xchg x1,ax ; mov x2,ax + mov ax,y2 ; Xchg y1,ax ; mov y2,ax; + @no_swap: + + {get address} + mov si,y1 + shl si,1 + mov bx,x1; shr bx,3 + add bx,word ptr Sc.startoffsets+si + {offset now in bx} + + mov ax,dfy {difference in y} + sub ax,dfx {subtract difference in x} + shl ax,1 {times by two and you've got incr2} + mov incr2,ax {save it in here- goes into bp latter} + + mov dx,SC.offsw {load up scanline increment} + mov ax,y1 {is y2 less than y1?} + cmp ax,y2 + jle @notneg; neg dx; @notneg: {then make it not negative} + + mov cx,x1 ;and cl,7 {get mask} + mov al,128 ;shr al,cl {get mask} + + mov cx,dfx ;inc cx {load in the length} + mov si,dfy ;shl si,1; {get incr1} + mov di,si ;sub di,dfx {get fractional counter} + {mov ah,al {remember last drawpos} + push bp {remember stack frame} + mov bp,incr2 + + {is the line stippled?} + test maskbyte,255 + jnz @stiplinea + + @Runloopa: {start loop} + and es:[bx],al {write to screen} + ror al,1 {move index bit along 1} + adc bx,0 {increment draw offset if overflow} + cmp di,0;jl @noinca {new scan line?} + add di,bp {update di,go to next scan line} + add bx,dx {add scanline offset} + jmp @checka + @noinca: + add di,si {update fractional part} + @checka: + dec cx;jnz @runloopa + pop bp {recall stack frame} + jmp @end_of_proc + + @stiplinea: + {do stippled near horizontal line} + @Runloopb: {start loop} + test maskbyte,al + jz @nodrawa + and es:[bx],al {write to screen} + @nodrawa: + ror al,1 {move index bit along 1} + adc bx,0 {increment draw offset if overflow} + cmp di,0;jl @noincb {new scan line?} + add di,bp {update di,go to next scan line} + add bx,dx {add scanline offset} + jmp @checkb + @noincb: + add di,si {update fractional part} + @checkb: + dec cx;jnz @runloopb + pop bp {recall stack frame} + jmp @end_of_proc + + @near_vertical: + + mov ax,y2 ; cmp y1,ax ; jle @no_swapb + Xchg y1,ax ; mov y2,ax + mov ax,x2 ; Xchg x1,ax ; mov x2,ax; + @no_swapb: + + {get address} + mov si,y1 + shl si,1 + mov bx,x1; shr bx,3 + add bx,word ptr Sc.startoffsets+si + {offset now in bx} + + + mov ax,dfx {difference in x} + sub ax,dfy {subtract difference in y} + shl ax,1 {times by two and you've got incr2} + mov incr2,ax + + inc dfy {add one to difference in y} + mov dx,SC.offsw {screen width} + mov cx,x1 ;and cl,7 {get mask} + mov al,$80 ;shr al,cl {get mask} + mov si,dfx; shl si,1 {integer increment} + mov di,si {copy diff in x*2} + sub di,dfy {(diff in X*2)-diff in y} + mov ah,1 {stipple mask} + + mov cx,x1; cmp cx,x2; {check if line is going..} + jg @left {..left or right} + + {do these loads for both directions because of the use of bp} + mov cx,dfy {difference in Y} + push bp + mov bp,incr2 {fractional increment} + + {is the line stippled?} + test maskbyte,255 + jnz @stiplineb + + @Runloopc: + and es:[bx],al {Write to screen} + add bx,dx {next scan line} + cmp di,0 {if no change} + jl @noincc {then don't do below} + add di,bp {do frac part} + ror al,1 {rotate mask right} + adc bx,0 {go to next byte on screen} + jmp @checkc {don't add di,si} + @noincc: + add di,si {add frac part} + @checkc: + dec cx;jnz @runloopc + jmp @end + + {stippled left near vertical} + @stiplineb: + @Runloope: + test maskbyte,ah + jz @nodrawb + and es:[bx],al {write to screen} + @nodrawb: + rol ah,1 {rotate stipple check mask} + add bx,dx {next scan line} + cmp di,0 {if no change} + jl @noince {then don't do below} + add di,bp {do frac part} + ror al,1 {rotate mask right} + adc bx,0 {go to next byte on screen} + jmp @checke {don't add di,si} + @noince: + add di,si {add frac part} + @checke: + dec cx;jnz @runloope + jmp @end + + @left: + {do these loads for both directions because of the use of bp} + mov cx,dfy {difference in Y} + push bp + mov bp,incr2 {fractional increment} + {is the line stippled?} + test maskbyte,255 + jnz @stiplinec + + @Runloopd: + and es:[bx],al {Write to screen} + add bx,dx {next scan line} + cmp di,0 {if no change} + jl @noincd {then don't do below} + add di,bp {do frac part} + rol al,1 {rotate mask left} + sbb bx,0 {go to previous byte on screen} + jmp @checkd {don't add di,si} + @noincd: + add di,si {add frac part} + @checkd: + dec cx;jnz @runloopd + jmp @end + + {stippled right near vertical} + @stiplinec: + @Runloopf: + test maskbyte,ah + jz @nodrawc + and es:[bx],al {write to screen} + @nodrawc: + rol ah,1 {rotate stipple check mask} + add bx,dx {next scan line} + cmp di,0 {if no change} + jl @noincf {then don't do below} + add di,bp {do frac part} + rol al,1 {rotate mask left} + sbb bx,0 {go to previous byte on screen} + jmp @checkf {don't add di,si} + @noincf: + add di,si {add frac part} + @checkf: + dec cx;jnz @runloopf + + @end: + pop bp + @end_of_proc: + end; + end; + end; +end; + + +{write a graphical text output to the screen. + clipped to words and then to pixel bits} + + (* +Procedure outtextxy_length(x1,y1:integer;txt:pchar;length:byte); +var txtend,ylop,txtstart,lmask,rmask,cmask:byte; + Adrs,decoffs:word; + x2,y2,tmp:integer; +Begin + asm + mov al,length {get length (first byte)} + mov txtend,al + xor ah,ah {clear top byte} + mov al,txtend {x2:=x1+(txtend shl 3);} + shl ax,3 + add ax,x1 + mov x2,ax + + mov ax,y1 {y2:=y1+Fontmax;} + add ax,Fontmax + mov y2,ax + end; + + if (x1<=SC.viewport.x2)and(y1<=SC.viewport.y2)and(x2>=SC.viewport.x1) + and(y2>=SC.viewport.y1)and(txtend<>0) then begin + asm + mov ax,y1 ;imul SC.offsw + mov di,x1 ;sar di,3 + add di,word ptr SC.scrptr + add di,ax + mov adrs,di + end; + + {**X - Clipping**} + lmask:=$ff; rmask:=$ff; + txtstart:=1; + tmp:=(SC.viewport.x1-x1); + if x1SC.viewport.x2 then begin + dec(txtend,tmp shr 3); + rmask:=rmask shl (tmp and 7); + end; + if txtstart=txtend+1 then exit; + + {**Y-cliping**} + If y2>SC.viewport.y2 then ylop:=(SC.viewport.y2-y1) else ylop:=Fontmax; + if y1CTproportional then + for txtlop:=1 to length do begin + drawbytes(x1,y1,@tcharset.typeface[byte(txt^)],fontheight); + inc(x1,8); + inc(txt); + end else + for txtlop:=1 to length do begin + drawbytes(x1,y1,@tcharset.typeface[byte(txt^)],fontheight); + inc(x1,tcharset.widths[byte(txt^)]); + inc(txt); + end; +end; + +Procedure outtextxy(x1,y1:integer;txt:string); +Begin + outtextxy_length(x1,y1,@txt[1],byte(txt[0])); +end; + +{in the C version, replace this with a macro} + +Procedure Drawbytes(x1,y:Integer;pic:bytearray;nbytes:byte); +var lop,mask:byte; Adrs:word; + x2:integer; +Begin + x2:=x1+8; + dec(nbytes); + if (x2>=SC.viewport.x1)and(x1<=SC.viewport.x2)and(y+nbytes>=SC.viewport.y1)and(y<=SC.viewport.y2)then begin + + {**XCliping**} + mask:=$ff; + if x1SC.viewport.x2 then + mask:=mask and ($ff shl (x2-SC.viewport.x2-1)); + asm + mov si,y + shl si,1 + mov bx,x1 ;sar bx,3 + add bx,word ptr SC.scrptr + add bx,word ptr SC.startoffsets+si + mov adrs,bx + end; + + {**YCliping**} + If y+nbytes>SC.viewport.y2 then lop:=(SC.viewport.y2-y) else lop:=nbytes; + if y=SC.viewport.x1) + and(y2>=SC.viewport.y1)and(xbytes<>0) then begin + asm + mov ax,y1 ;imul SC.offsw + mov di,x1 ;sar di,3 + add di,word ptr SC.scrptr + add di,ax + mov adrs,di + end; + {**X - Clipping**} + lmask:=$ff;rmask:=$ff; + xlenclipped:=xbytes; + incpicoffs:=0; + + tmp:=(SC.viewport.x1-x1); + if x1SC.viewport.x2 then begin + rmask:=rmask shl (tmp and 7); + tmp:=tmp shr 3; + dec(xlenclipped,tmp); + inc(incpicoffs,tmp); + end; + + {**Y-cliping**} + If y2>SC.viewport.y2 then + ylop:=(SC.viewport.y2-y1)+1 + else + ylop:=ybytes; + + if y1x2} + cmp bx,cx ;jle @no_swap ; Xchg bx,cx; @no_swap: + + {is line at all visable?} + cmp bx,SC.viewport.x2 ;jg @fin + cmp cx,SC.viewport.x1 ;jl @fin + cmp ax,SC.viewport.y2 ;jg @fin + cmp ax,SC.viewport.y1 ;jl @fin + + {X axis clipping} + mov dx,SC.viewport.x1 ;cmp bx,dx ; JGE @nochange_x1 + mov bx,dx + @nochange_x1: + mov dx,SC.viewport.x2 ;cmp cx,dx ; JLE @nochange_x2 + mov cx,dx + @nochange_x2: + + {Get starting byte to work on} + + mov si,ax + shl si,1 + mov di,word ptr SC.startoffsets+si + add di,word ptr SC.scrptr + mov es,word ptr SC.scrptr+2 + inc cx + + mov dl,cl {save cl} + mov ax,$ffff {2nd mask } + and cl,7 ; shr ah,cl ;not ah {x2 already loaded into cx} + mov cl,bl; and cl,7 ;shr al,cl {1st mask ,load x1 (in bx) into cx} + + {and ax,maskword} + mov cl,dl {restore cl} + + {calculate length (in bytes-1) of line} + shr cx,3 {x2 in byte range} + shr bx,3 {x1 in byte range} + sub cx,bx {get byte length} + {shr cx,3} + add di,bx {add this to screen memory offset} + mov bx,ax {get masks from ax} + + {///////2 COLOUR BACKGROUND FILLED PATTERN/////////////////////////} + + test maskbackground,true + jz @normalfill + cmp cl,0; jnz @more1 {if there is only one byte then do only this} + and bh,bl + @More1: + + mov dx,GRPH_ADDR + mov ah,$ff;mov al,8; out dx,ax; {bitmask,$ff func:8} + + {/////////////EDGES OF SOLID PATTERN FILL////////////////} + mov al,maskbyte + and es:[64427],al {copy to top of screen memory} + push bx + and bl,al + and bh,al + cmp cx,0 + jz @lastbyteb {if only one byte then goto @lastbyte} + and es:[di],bl {write to screen} + add di,cx {next byte} + @lastbyteb: + and es:[di],bh {write to screen} + pop bx + + sub di,cx {restore di to original value} + + xor al,al; mov ah,t_fillcol; out dx,ax; {setup inverse colour} + + mov al,maskbyte + not al + and es:[64427],al {copy to top of screen memory} + and bl,al + and bh,al + + cmp cx,0 + jz @lastbytec {if only one byte then goto @lastbyte} + and es:[di],bl {write to screen} + add di,cx {next byte} + @lastbytec: + and es:[di],bh {write to screen} + + sub di,cx {restore di to original value} + + cmp cl,0 + jle @fin + + {/////////////BODY OF SOLID PATTERN FILL////////////////} + dec cl + inc di + + mov ax,00008h;out dx,ax {set bitmask to 0} + and al,es:[64427] + shr cl,1 {word length} + REP STOSw {write words} + adc cl,cl {extra byte?} + REP STOSb {write byte if there} + + jmp @fin + {///////NORMAL FILL PATTERN/////////////////////////} + + @normalfill: + + cmp cl,0; jnz @more {if there is only one byte then do only this} + and bh,bl + jmp @lastbyte + @More: + + and es:[di],bl {first byte} + inc di {inc byte offset} + + dec cl {one less for count} + jcxz @lastbyte {if no '$ff' body then go to the last byte} + mov ax,$ffff {load up for body of line} + test maskbyte,255 + jnz @runloop + test T_writemode,0; + {mov ax,maskword} + Jnz @runloop {if T_writmode<>0 then goto runloop} + shr cl,1 {get word count} + REP stosw {store words} + adc cl,cl {extra byte?} + REP stosb {Draw if there} + jmp @lastbyte + + @runloop: {Do this for checking bytes -xor putting} + and es:[di],al + inc di + dec cx;jnz @runloop + + @lastbyte: + and es:[di],bh {write to screen} + @fin: + {reset bitmask + mov dx,GRPH_ADDR + mov ax,0FF08h; out dx,ax; {bitmask,255 func:8} +end; + + +Procedure putpixel(x1,y1:Integer); +begin +asm + {if dot visable?} + + mov cx,x1 ;mov bx,y1 + cmp cx,SC.viewport.x1 ;jl @fin {clipping..} + cmp bx,SC.viewport.y1 ;jl @fin + cmp cx,SC.viewport.x2 ;jg @fin + cmp bx,SC.viewport.y2 ;jg @fin + + mov dx,GRPH_ADDR + mov al,data_rotate;mov ah,t_writemode; out dx,ax; {Logical mode} + xor al,al; mov ah,t_col; out dx,ax; {colour} + mov ax,0B05h; out dx,ax; {writemode -3} + mov ax,0007h; out dx,ax; {set colour don't care} + mov ax,0FF08h; out dx,ax; {bitmask,255 func:8} + + shl bx,1 + mov di,word ptr SC.startoffsets+bx + add di,word ptr SC.scrptr + mov es,word ptr SC.scrptr+2 + {x-offset} + mov bl,cl + xor bh,bh + and bl,7 + shr cx,3 + add di,cx + + mov al,byte ptr singlepixelbitmasks+bx + + and es:[di],al + @fin: +end; +end; + +Function getpixel(x1,y1:Integer):byte;assembler; +asm + mov dx,GRPH_ADDR;mov ax,5; out dx,ax + + mov ah,$0d + xor bh,bh + mov dx,y1 + mov cx,x1 + int $10 {value should be returned to al} + + mov bl,al + + mov dx,GRPH_ADDR; + mov ax,0B05h; out dx,ax; + mov ax,0FF08h; out dx,ax; {bitmask} + mov al,bl +end; + +Procedure Vline(x,y1,y2:Integer);assembler; +var +height:word; +asm + + + mov dx,GRPH_ADDR + mov al,data_rotate;mov ah,t_writemode; out dx,ax; {Logical mode} + xor al,al; mov ah,t_col; out dx,ax; {colour} + mov ax,0B05h; out dx,ax; {writemode -3} + mov ax,0007h; out dx,ax; {set colour don't care} + mov ax,0ff08h; out dx,ax; {bitmask,255 func:8} + + {remember that these registers are loaded thus:} + mov ax,y1; mov bx,y2 ;mov cx,x + {swap y2,y1 if y1>y2} + cmp ax,bx ;jle @no_swap ; Xchg ax,bx; @no_swap: + + cmp ax,SC.viewport.y2 ;jg @fin {is line at all visable?} + cmp bx,SC.viewport.y1 ;jl @fin + cmp cx,SC.viewport.x2 ;jg @fin + cmp cx,SC.viewport.x1 ;jl @fin + + {Y axis clipping} + mov dx,SC.viewport.y1 ;cmp ax,dx ; JGE @nochange_y1 + mov ax,dx + @nochange_y1: + mov dx,SC.viewport.y2 ;cmp bx,dx ; JLE @nochange_y2 + mov bx,dx + @nochange_y2: + + + inc bx {inc y2} + sub bx,ax {calc length} + mov height,bx + + {could use a lookup table for start memory addresses as well, cut out the multiply} + + mov es,word ptr SC.scrptr+2 {load up screen position} + + mov si,ax + shl si,1 + + mov di,word ptr SC.startoffsets+si + add di,word ptr SC.scrptr; {(ax*SC.offsw)+word ptr SC.scrptr (calculate)} + + {get bitmask} + mov si,cx + and si,7 + mov al,byte ptr [singlepixelbitmasks+si] + {add xoffset} + shr cx,3 + add di,cx + + mov cx,SC.offsw {load screen width} + + + test maskbyte,255 + jz @runloop + {////MASKED LINE//////} + push di {save screen offset} + mov ah,maskbyte {copy mask in to ah} + mov dl,1 + @runloopmask: + test ah,dl {draw the pixel if ah and dl<>0} + jz @nodraw + and es:[di],al {write to screen} + @nodraw: + rol dl,1 {shift mask} + add di,cx {next pixel} + dec bx + jnz @runloopmask + pop di {restore screen offset} + mov bx,height + test maskbackground,true + jz @fin + {////MASKED LINE WITH BACKGROUND//////} + push ax + mov dx,GRPH_ADDR + xor al,al; mov ah,t_fillcol; out dx,ax; {colour} + pop ax + not ah + mov dl,1 + @runloopmaskbackground: + test ah,dl {draw the pixel if ah and dl<>0} + jz @nodrawbackground + and es:[di],al {write to screen} + @nodrawbackground: + rol dl,1 {shift mask} + add di,cx {next pixel} + dec bx; + jnz @runloopmaskbackground + jmp @fin + + {////NO PATTERN//////} + @runloop: + and es:[di],al {write to screen} + add di,cx {next pixel} + dec bx + jnz @runloop + + @fin: + +end; + +Procedure bar(x1,y,x2,y2:integer);assembler; +var +scroffs:word; +xlop:word; +mask:byte; + +asm + mov ax,x2 ;cmp x1,ax ;jle @no_swapx ; Xchg x1,ax; mov x2,ax ; @no_swapx: + mov ax,y2 ;cmp y,ax ;jle @no_swapy ; Xchg y,ax; mov y2,ax ; @no_swapy: + {is bar at all visable?} + mov ax,x1 ;cmp ax,SC.viewport.x2 ;jg @end + mov ax,x2 ;cmp ax,SC.viewport.x1 ;jl @end + mov ax,y ;cmp ax,SC.viewport.y2 ;jg @end + mov ax,y2 ;cmp ax,SC.viewport.y1 ;jl @end + + mov dx,GRPH_ADDR + mov al,3; mov ah,t_writemode; out dx,ax; {writemode} + xor al,al; mov ah,t_fillcol; out dx,ax; {colour} + mov ax,0B05h; out dx,ax; {writemode -3} + mov ax,0007h; out dx,ax; {set colour don't care} + mov ax,0FF08h; out dx,ax; {bitmask,255 func:8} + + {x axis clipping} + mov ax,SC.viewport.x1 ;cmp x1,ax ; JGE @nochange_x1 + mov x1,ax + @nochange_x1: + mov ax,SC.viewport.x2 ;cmp x2,ax ; JLE @nochange_x2 + mov x2,ax + @nochange_x2: + {Y axis clipping} + mov ax,SC.viewport.y1 ;cmp y,ax ; JGE @nochange_y1 + mov y,ax + @nochange_y1: + mov ax,SC.viewport.y2 ;cmp y2,ax ; JLE @nochange_y2 + mov y2,ax + @nochange_y2: + inc y2;inc x2 + + mov di,x1 + + mov es,word ptr SC.scrptr+2 {calculate address} + mov si,y + shl si,1 + mov di,x1; shr di,3 + add di,word ptr Sc.startoffsets+si + + + mov ax,$ffff {solid middle mask} + + mov si,x1 + and si,7 + mov bl,byte ptr left_pixelbitmasks+si + + mov si,x2 + and si,7 + mov bh,byte ptr right_pixelbitmasks+si + + + + shr x1,3 + shr x2,3 + mov dx,x2 {calculate length (in bytes-1) of line} + sub dx,x1 {and shove in dx} + + mov cx,y2 {calculate height} + sub cx,y + + mov si,dx {copy no of bytes} + sub si,SC.offsw {calculate add offset} + + cmp dl,0; jnz @noand + and bh,bl; {make one mask} + @noand: + + dec dl {correct dl} + + test nullpattern,1 + jz @patternfill + {/////////////////////// SOLID FILL -NO PATTERN ///////////////////////} + push bp {save stack frame} + + @runloop: + mov bp,cx {save cx} + mov cl,dl; xor ch,ch {load up length} + cmp cl,255; jz @lastbyte {if only one byte then goto @lastbyte} + and es:[di],bl {write to screen} + inc di {next byte} + + shr cl,1 {word length} + REP STOSw {write words} + adc cl,cl {extra byte?} + REP STOSb {write byte if there} + + @lastbyte: + and es:[di],bh {write to screen} + sub di,si + mov cx,bp {restore cx} + dec cx;jnz @runloop + pop bp {restore stack frame} + jmp @end + + @patternfill: + mov scroffs,si {si is used, use variable for screenoffset} + + mov si,y {calculate byte offset into bitpattern} + and si,7 + + test maskbackground,1 + jz @runloopc {jump if not background} + {else do the code for two colour patterns} + {the two colour pattern is first loaded into high video memory + and a dummy read (to load the vga latches) is initialized enabling + fast writes to the vga using a pattern. for future reference, the + pattern could be a combination of any 16 colours} + + xor dh,dh + mov xlop,dx {dx is used, must use variable to remember xlop} + mov dx,GRPH_ADDR {set dx for graphics registers} + + + {/////////////EDGES OF SOLID PATTERN FILL////////////////} + inc xlop {for speed, is deced at the end of this block} + + push cx {save ylop} + push di {save screen offset} + @edgeloop: + push bx {save masks} + mov al,byte ptr fillpattern+si + and bl,al + and bh,al + + cmp byte ptr xlop,0 + jz @lastbyteb {if only one byte then goto @lastbyte} + + and es:[di],bl {write to screen} + add di,xlop {next byte} + + @lastbyteb: + and es:[di],bh {write to screen} + + sub di,scroffs + pop bx + inc si + and si,7 + dec cx;jnz @edgeloop + pop di {restore screen offset} + pop cx {restore ylop} + + xor al,al; mov ah,t_col; out dx,ax; {setup inverse colour} + + mov si,y {calculate byte offset into bitpattern} + and si,7 + + push cx {save ylop} + push di {save screen offset} + @edgeloop2: + push bx {save masks} + mov al,byte ptr fillpattern+si + not al + and bl,al + and bh,al + + cmp byte ptr xlop,0 + jz @lastbytec {if only one byte then goto @lastbyte} + + and es:[di],bl {write to screen} + add di,xlop {next byte} + + @lastbytec: + and es:[di],bh {write to screen} + + sub di,scroffs + pop bx + inc si + and si,7 + dec cx;jnz @edgeloop2 + pop di {restore screen offset} + pop cx {restore ylop} + + dec xlop {restore xlop to orig value} + + cmp byte ptr xlop,0 + jle @end + + {/////////////BODY OF SOLID PATTERN FILL////////////////} + + xor al,al; mov ah,t_fillcol; out dx,ax; {setup inverse colour} + {set up 2 colour 8*8 bitpattern in hight video memory} + xor si,si {use si as count register, set to 0} + @firstcolloop: + mov al,byte ptr fillpattern+si {copy byte pattern} + and es:[64427+si],al {copy to top of screen memory} + inc si + cmp si,8 {end of loop?} + jnz @firstcolloop {loop it} + xor al,al; mov ah,t_col; out dx,ax; {setup inverse colour} + xor si,si {use si as count register, set to 0} + @secondcolloop: + mov al,byte ptr fillpattern+si {copy byte pattern} + not al {inverse byte pattern} + and es:[64427+si],al {copy to top of screen memory} + inc si + cmp si,8 {end of loop?} + jnz @secondcolloop {loop it} + xor si,si + xor al,al; mov ah,t_fillcol; out dx,ax; {setup inverse colour} + + mov si,y {calculate byte offset into bitpattern} + and si,7 + + dec scroffs {fiddle these for speed} + inc di + mov ax,00008h;out dx,ax {set bitmask to 0} + @runloopb: + push cx + mov cx,xlop {load up length} + and al,es:[64427+si] + shr cl,1 {word length} + REP STOSw {write words} + adc cl,cl {extra byte?} + REP STOSb {write byte if there} + sub di,scroffs + pop cx + inc si + and si,7 + dec cx;jnz @runloopb + jmp @end + + + {////////////////TRANSPARENT PATTERN FILL////////////////} + @runloopc: + push bx {save masks} + mov al,byte ptr fillpattern+si + + and bh,al + and bl,al + push cx + mov cl,dl + xor ch,ch {load up length} + cmp cl,255 + jz @lastbyted {if only one byte then goto @lastbyte} + and es:[di],bl {write to screen} + inc di {next byte} + + cmp cl,0 + jz @lastbyted + + @drawlopx: + and es:[di],al {write to screen} + inc di {next byte} + dec cx;jnz @drawlopx + + @lastbyted: + and es:[di],bh {write to screen} + sub di,scroffs + pop cx + pop bx + inc si + and si,7 + dec cx;jnz @runloopc + @end: +end; + +{l shifts.obj +Function asr(num:Longint;shiftby:byte):Longint; near; external; +Function asl(num:Longint;shiftby:byte):Longint; near; external;} + +Procedure GTriangle(xa,ya,xb,yb,xc,yc,ia,ib,ic:integer); +const shiftby=7; +Var +lop,Lx{,Rx}, +endp,ylop,Lxadd,Rxadd,yrdiff,yldiff,xoff,Lxa,Rxa,li,ri,xdiff,cadd:integer; +Ri32,li32,Riadd32,liadd32,ia32,ib32,ic32:longint; +right:boolean; +scroffset:word; + +Begin + + {sort by Y} + asm + {if ya>yc then swap xc,xa swap yc,ya fswap ic,ia} + mov ax,yc + cmp ya,ax + jl @NoSwapY1 + xchg ya,ax; mov yc,ax + mov ax,xc; xchg xa,ax; mov xc,ax + mov ax,ic; xchg ia,ax; mov ic,ax + @NoSwapY1: + {if ya>yb then swap xb,xa swap yb,ya fswap ib,ia} + mov ax,yb + cmp ya,ax + jl @NoSwapY2 + xchg ya,ax; mov yb,ax + mov ax,xb; xchg xa,ax; mov xb,ax + mov ax,ib; xchg ia,ax; mov ib,ax + @NoSwapY2: + {if yb>yc then swap xc,xb swap yc,yb fswap ic,ib} + mov ax,yc + cmp yb,ax + jl @NoSwapY3 + xchg yb,ax; mov yc,ax + mov ax,xc; xchg xb,ax; mov xc,ax + mov ax,ic; xchg ib,ax; mov ic,ax + @NoSwapY3: + {is the cross point to the left or right?} + mov di,yc;sub di,ya + mov ax,yb;sub ax,yc + mov cx,xc;sub cx,xa + imul cx + cmp di,0 + jz @nodiv + idiv di + @nodiv: + add ax,xc + cmp xb,ax + mov right,1 + jle @isright + mov right,false + @isright: + + {get largest x + mov bx,xa; + mov ax,xb + cmp bx,ax; jg @nodo1 ;mov bx,ax ;@nodo1: + mov ax,xc + cmp bx,ax; jg @nodo2 ;mov bx,ax ;@nodo2: + {if largest off screen then exit + cmp bx,SC.viewport.x1;jl @triend + + {get smallest x} + mov bx,xa; + mov ax,xb + cmp bx,ax; jl @nodo3 ;mov bx,ax ;@nodo3: + mov ax,xc + cmp bx,ax; jl @nodo4 ;mov bx,ax ;@nodo4: + {if smallest off screen then exit + cmp bx,SC.viewport.x2;jg @triend} + + mov xoff,bx + {sub by bx and shift left } + sub xa,bx; + sub xb,bx; + sub xc,bx; + + sal xa,shiftby + sal xb,shiftby + sal xc,shiftby + end; + ia32:=ia * 65536 {asl(ia,16)}; + ib32:=ib * 65536 {asl(ib,16)}; + ic32:=ic * 65536 {asl(ic,16)}; + + ylop:=ya;endp:=yc; + if endp>SC.viewport.y2 then endp:=SC.viewport.y2+1; + + asm + {yldiff:=yb-ya;if yldiff=0 then yldiff:=1; + Lxadd:=(xb-xa) div yldiff;} + mov ax,xb ;sub ax,xa + mov bx,yb ;sub bx,ya + jz @nodiv1 + cwd + idiv bx + jmp @nocorrect1 + @nodiv1: + mov bx,1 + @nocorrect1: + mov yldiff,bx + mov lxadd,ax + {yrdiff:=yc-ya;if yrdiff=0 then yrdiff:=1; + Rxadd:=(xc-xa) div yrdiff;} + mov ax,xc ;sub ax,xa + mov bx,yc ;sub bx,ya + jz @nodiv2 + cwd + idiv bx + jmp @nocorrect2 + @nodiv2: + mov bx,1 + @nocorrect2: + mov yrdiff,bx + mov rxadd,ax + end; + {yrdiff:=yc-ya;if yrdiff=0 then yrdiff:=1; + Rxadd:=(xc-xa) div yrdiff;} + Lxa:=xa;Rxa:=xa; + + li32:=ia32; + ri32:=ia32; + liadd32:=(ib32-ia32)div yldiff; + riadd32:=(ic32-ia32)div yrdiff; + if not right then begin + fswap(rxadd,lxadd,2); + fswap(liadd32,riadd32,4); + end; + asm + mov dx,GRPH_ADDR + mov ax,0B05h; out dx,ax; {writemode -3} + mov ax,0ff08h; out dx,ax; {bitmask,255 func:8} + mov al,3; mov ah,t_writemode; out dx,ax; {writemode} + mov ax,0007h; out dx,ax; {set colour don't care} + xor al,al; out dx,al; {setup for colours} + + + mov es,word ptr SC.scrptr+2 {load up screen mem pos} + mov si,SC.offsw + mov ax,ya ;imul si ;add ax,word ptr SC.scrptr + mov scroffset,ax + end; + while ylopSC.viewport.y1 then....} + mov ax,SC.viewport.y1 ;cmp ax,ylop ;jg @fin + {convert the line to normal pixel-space} + {xa is in dx, xb is in cx} + mov cx,rxa ;shr cx,shiftby ;add cx,xoff + mov dx,lxa ;shr dx,shiftby ;add dx,xoff + + mov di,cx + inc di + sub di,dx {holds non clipped xdiff} + {Xclipping} + mov ax,SC.viewport.x2 ;cmp cx,ax ; JLE @nochange_x2 + mov cx,ax + @nochange_x2: + mov ax,SC.viewport.x1 ;cmp dx,ax ; JGE @nochange_x1 + mov dx,ax + @nochange_x1: + inc cx {correct x2} + + mov lx,dx + sub cx,dx {calculate xdiff} + jle @fin + mov xdiff,cx {save it} + + {generate colour interpoltaion addition} + mov si,li {colour intensity start} + mov ax,ri + sub ax,si {load colour} + CWD {put ax into AX:DX, with sign} + idiv di {do it, baby} + mov cadd,ax {load ax into erm... addi?} + mov dx,lx + {re-evaluate start address} + mov di,scroffset + mov cx,dx {get the x value} + shr cx,3 {into byte range} + add di,cx {add this to total} + {generate start X mask} + mov cx,dx {load up x value} + and cl,7 {get mask} + mov ah,128 {Start mask} + shr ah,cl {shift in place} + + mov cx,xdiff {xdiff is the length (xb-xa)} + mov dx,grph_data_addr + + push bp + mov bp,Cadd {colour interpolation value} + + @drawloop: + + mov bx,si {load colour} + shr bx,8 {get it into non-fixed range} + mov al,bl + out dx,al {Send colour} + + and es:[di],ah {write to screen} + add si,bp {add colour interpolation value} + + ror ah,1 {shift pixel along} + adc di,0 + dec cx;jnz @drawloop + pop bp + @fin: + end; + {ci:=li; + for lop:=Lx to Rx do begin + t_col:=asr(ci); + inc(ci,addi); + putpixel(lop,ylop); + end;} + inc(scroffset,SC.offsw); + inc(ylop); + end; +end; + +{Procedure GTriangle(xa,ya,xb,yb,xc,yc,ia,ib,ic:integer);external;} + +Procedure Triangle(xa,ya,xb,yb,xc,yc:integer);assembler; +const shiftby=6; +Var +lop,Lx,Rx, +Lxadd,Rxadd,yrdiff,yldiff,xoff,Lxa,Rxa,xdiff,endp:integer; +right:boolean; +scroffset:word; + {sort by Y} + asm + {if ya>yc then swap xc,xa swap yc,ya fswap ic,ia} + mov ax,yc + cmp ya,ax + jl @NoSwapY1 + xchg ya,ax; mov yc,ax + mov ax,xc; xchg xa,ax; mov xc,ax + @NoSwapY1: + {if ya>yb then swap xb,xa swap yb,ya fswap ib,ia} + mov ax,yb + cmp ya,ax + jl @NoSwapY2 + xchg ya,ax; mov yb,ax + mov ax,xb; xchg xa,ax; mov xb,ax + @NoSwapY2: + {if yb>yc then swap xc,xb swap yc,yb fswap ic,ib} + mov ax,yc + cmp yb,ax + jl @NoSwapY3 + xchg yb,ax; mov yc,ax + mov ax,xc; xchg xb,ax; mov xc,ax + @NoSwapY3: + {is the cross point to the left or right?} + mov di,yc;sub di,ya + mov ax,yb;sub ax,yc + mov cx,xc;sub cx,xa + imul cx + cmp di,0 + jz @nodiv {seems to be a div by zero error here} + idiv di + @nodiv: + add ax,xc + cmp xb,ax + mov right,true + jle @isright + mov right,false + @isright: + {get largest x} + mov bx,xa; + mov ax,xb + cmp bx,ax; jg @nodo1 ;mov bx,ax ;@nodo1: + mov ax,xc + cmp bx,ax; jg @nodo2 ;mov bx,ax ;@nodo2: + {if largest off screen then exit} + cmp bx,SC.viewport.x1;jl @triend + + {get smallest x} + mov bx,xa; + mov ax,xb + cmp bx,ax; jl @nodo3 ;mov bx,ax ;@nodo3: + mov ax,xc + cmp bx,ax; jl @nodo4 ;mov bx,ax ;@nodo4: + {if smallest off screen then exit} + cmp bx,SC.viewport.x2;jg @triend + mov xoff,bx + {sub by bx and shift left } + sub xa,bx; + sub xb,bx; + sub xc,bx; + + shl xa,shiftby + shl xb,shiftby + shl xc,shiftby + + {get y length} + mov si,yc + cmp si,SC.viewport.y2 + jle @noyclip + mov si,SC.viewport.y2 + inc si + @noyclip: + + mov endp,si + mov si,ya + cmp si,SC.viewport.y2 + jg @triend + cmp si,endp + jz @triend + + {yldiff:=yb-ya;if yldiff=0 then yldiff:=1; + Lxadd:=(xb-xa) div yldiff;} + mov ax,xb ;sub ax,xa + mov bx,yb ;sub bx,ya + jz @nodiv1 + cwd + idiv bx + jmp @nocorrect1 + @nodiv1: + mov bx,1 + @nocorrect1: + mov yldiff,bx + mov lxadd,ax + {yrdiff:=yc-ya;if yrdiff=0 then yrdiff:=1; + Rxadd:=(xc-xa) div yrdiff;} + mov ax,xc ;sub ax,xa + mov bx,yc ;sub bx,ya + jz @nodiv2 + cwd + idiv bx + jmp @nocorrect2 + @nodiv2: + mov bx,1 + @nocorrect2: + mov yrdiff,bx + mov rxadd,ax + mov ax,xa + mov Lxa,ax + mov Rxa,ax + {test for swap} + test right,1 + jnz @isrightb + mov ax,rxadd + xchg lxadd,ax + mov rxadd,ax + @isrightb: + + mov dx,GRPH_ADDR + mov al,3; mov ah,t_writemode; out dx,ax; {writemode} + xor al,al; mov ah,t_fillcol; out dx,ax; {colour} + mov ax,0B05h; out dx,ax; {writemode -3} + mov ax,0007h; out dx,ax; {set colour don't care} + mov ax,0FF08h; out dx,ax; {bitmask,255 func:8} + + mov es,word ptr SC.scrptr+2 {load up screen mem pos} + mov cx,SC.offsw + mov ax,ya ;imul cx ;add ax,word ptr SC.scrptr + mov di,ax + + @Yloop: + cmp si,yb + jnz @Daltend + {yldiff:=yc-yb;if yldiff=0 then yldiff:=1;} + mov bx,yc ;sub bx,yb + jnz @nocorrect; mov bx,1; @nocorrect: + {Lxadd:=(xc-xb) div yldiff;} + mov ax,xc; sub ax,xb + cwd + idiv bx + mov bx,xb + {test see which side these need to go in} + test right,true + jz @isleft + mov lxadd,ax + mov lxa,bx + jmp @Daltend + @isleft: + mov rxadd,ax + mov rxa,bx + @Daltend: + + push di + {inc x1a and x2a with the slope of line and inc offset} + mov ax,Lxadd;add lxa,ax + mov ax,Rxadd;add rxa,ax + {if ylop>SC.viewport.y1 then....} + mov ax,SC.viewport.y1 ;cmp ax,si ;jg @fin + {convert the line to normal pixel-space} + mov cx,rxa ;shr cx,shiftby ;add cx,xoff + mov dx,lxa ;shr dx,shiftby ;add dx,xoff + {flip- shouldn't have to but there ya go} + cmp dx,cx ;jg @no_swap ; Xchg cx,dx; @no_swap: {if x1>x2 then swap} + {if (x1>SC.viewport.x2)or(x2SC.viewport.x2-x2 then x2:=SC.viewport.x2-xd; + if yd>SC.viewport.y2-y2 then y2:=SC.viewport.y2-yd; + if y2<1 then y2:=1; + asm + mov dx,GRPH_ADDR + mov ax,261; out dx,ax {adrsmode=1} + mov ax,513; out dx,ax {esetres=2} + xor ax,ax; out dx,ax {colour=0} + mov ax,$ff08; out dx,ax {bitmask=255} + end; + Scrncpysub(SC.offsw-x2 shr 3, + (page1*SC.pagesize)+(y1*SC.offsw)+x1 shr 3, + (page2*SC.pagesize)+(yd*SC.offsw)+xd shr 3,x2 shr 3,y2); + {adrsmode(3);} +end; + +Procedure putbitmap(x1,y1:integer;bitmap:bitmaptypeptr); +var picadrs,scradrs:^byte; + bitoffs,lmask,rmask:byte; + picofs,planeofs,tmp,addpicoffs,addscroffs:word; + x2,y2,xlop,ylop:integer; + bitlop:word; +begin + with bitmap^ do begin + x2:=x1+size.x; + y2:=y1+size.y; + if (x1<=SC.viewport.x2)and(y1<=SC.viewport.y2)and(x2>=SC.viewport.x1)and(y2>=SC.viewport.y1+1) then begin + if bitmaptype=BMplanes then begin + bitoffs:=(x1 and 7); + lmask:=$ff shr bitoffs; + rmask:=(not lmask); + if bitoffs>qbitoffset then begin + bitoffs:=bitoffs-qbitoffset; + for bitlop:=0 to bitplanes-1 do begin + picadrs:=@planedata[bitlop]^; + rorblock(picadrs,xoff,size.y,bitoffs); + end; + + end else if bitoffsSC.viewport.x2 then begin + tmp:=(x2-SC.viewport.x2)+(qbitoffset xor 7){-(size.x -(size.x shr 3 shl 3))}; + rmask:=$ff shl (tmp and 7); + dec(xlop,tmp shr 3); + end; + + {y1 clipping} + if y1SC.viewport.y2 then begin + tmp:=(y2-SC.viewport.y2)-1; + dec(ylop,tmp); + end; + addscroffs:=SC.offsw-xlop; + addpicoffs:=xoff-xlop; + {update masks as well?} + if xlop=1 then begin + dec(addscroffs,1); + dec(addpicoffs,1); + lmask:=rmask and lmask; + rmask:=0; + end; + Asm + mov dx,GRPH_ADDR + mov al,3; mov ah,t_writemode; out dx,ax; {Logical mode} + mov ax,05h; out dx,ax; {writemode -0} + mov ax,0007h; out dx,ax; {set colour don't care} + mov cx,4 + mov planeofs,12 + {dec planeofs { 1 less} + {shl planeofs,2 {list of 32 pointers so times by 4 (shl 2)} + + @planeloop: + push cx {save cx} + push ds {save ds} + {get address of bitplane} + les di,bitmap {load up object pointer} + add di,planeofs {add bitplane offset} + lds si,es:[di+offset planedata] {load up segment} + add si,picofs + + mov dx,SEQU_ADDR {load Sequencer} + mov al,2 {function 2} + mov ah,1;dec cl {generate..} + shl ah,cl {..pix mask} + out dx,ax {write to port} + + mov bx,ylop {get height} + mov cx,xlop {get byte width} + + les di,scradrs + + {ready bitmask} + mov dx,GRPH_ADDR + mov al,08h; out dx,al {bitmask,255 func:8} + inc dx + + @runloop: {start vertical loop} + mov cx,xlop {save screen height} + + mov al,lmask + out dx,al + mov ah,es:[di] + movsb + sub cx,2 + js @lastbyte + + mov al,$ff + out dx,al + + shr cx,1 {get word count} + REP movsw {store words} + adc cx,cx {extra byte?} + REP movsb {Draw if there} + + @lastbyte: + mov al,rmask + out dx,al + mov ah,es:[di] + movsb + + add di,addscroffs {screen update} + add si,addpicoffs + + dec bx + jnz @runloop + pop ds + pop cx + sub planeofs,4 + dec cx;jnz @planeloop + + mov dx,SEQU_ADDR {load Sequencer} + mov ax,3842 {function 2} + out dx,ax {write to port} + end; + end else begin + picadrs:=pointer(flatdata); + if x10) then + IDX_MOVE:=(index-1+numpoints) mod numpoints + else + IDX_MOVE:=(index-1+numpoints) mod numpoints; +end; + +begin + if numpoints<3 then exit; + top_y:=32767; + bottom_y:=-32767; + cpoint:=pointtypeptr(points); + + + {determine the top and bottom of the list} + for i:=0 to numpoints-1 do begin + if cpoint^.ybottom_y then bottom_y:=cpoint^.y; + inc(cpoint); + end; + if top_y=bottom_y then exit; + {figure out starting positions for left and right sides of the list} + i:=top_idx; + cpoint:=@points^[top_idx]; + + while points^[i].x=cpoint^.x do begin + i:=idx_bakwrd(i); + end; + i:=idx_fwrd(i); + l_idx_start:=i; + + i:=top_idx; + while points^[i].x=cpoint^.x do begin + i:=idx_fwrd(i); + end; + i:=idx_bakwrd(i); + + r_idx_start:=i; + i:=idx_fwrd(i); + if points^[i].xbottom_y) do begin + cpoint:=@pointtypearray(points)^[i]; + i:=idx_fwrd(i); + nxtpoint:=@pointtypearray(points)^[i]; + scanedge(cpoint^.x,cpoint^.y,nxtpoint^.x,nxtpoint^.y,1); + end; + + i:=L_idx_start; + cpoint:=@pointtypearray(points)^[L_idx_start]; + nxtpoint:=cpoint; + while (nxtpoint^.y<>bottom_y) do begin + cpoint:=@pointtypearray(points)^[i]; + i:=idx_bakwrd(i); + nxtpoint:=@pointtypearray(points)^[i]; + scanedge(cpoint^.x,cpoint^.y,nxtpoint^.x,nxtpoint^.y,0); + end; + drawhlines(top_y,bottom_y); + + + + + +end; + + + +Procedure outtextxy_length(x1,y1:integer;txt:pchar;length:byte); +var txtlop:byte; +Begin + if tcharset.attrib<>CTproportional then + for txtlop:=1 to length do begin + drawbytes(x1,y1,@tcharset.typeface[byte(txt^)],fontheight); + inc(x1,8); + inc(txt); + end else + for txtlop:=1 to length do begin + drawbytes(x1,y1,@tcharset.typeface[byte(txt^)],fontheight); + inc(x1,tcharset.widths[byte(txt^)]); + inc(txt); + end; +end; +Procedure outtextxy(x1,y1:integer;txt:string); +Begin + outtextxy_length(x1,y1,@txt[1],byte(txt[0])); +end; +(* +Procedure outtextxy_length(x1,y1:integer;txt:pchar;length:byte); +var txtend,ylop,txtstart,lmask,rmask:byte; + Adrs,decoffs:word; + x2,y2,tmp:integer; +Begin + txtend:=length; + x2:=x1+(txtend shl 3); + y2:=y1+fontmax; + if (x1<=SC.viewport.x2)and(y1<=SC.viewport.y2)and(x2>=SC.viewport.x1) + and(y2>=SC.viewport.y1)and(txtend<>0) then begin + + {**Y-cliping**} + If y2>SC.viewport.y2 then ylop:=(SC.viewport.y2-y1) else ylop:=fontmax; + if y1SC.viewport.x2 then begin + dec(txtend,tmp shr 3); + rmask:=rmask shl (tmp and 7); + end; + if txtstart=txtend+1 then exit; + + + decoffs:=(SC.offsw*(ylop+1)-8); + asm + mov di,adrs {load offset} + + mov dl,t_col + mov bx,SC.offsw {load dx with screen offset} + sub bx,8 + + mov dh,txtstart {dh is the loop counter} + @Textloop: + les si,[bp+6] {point to string} + mov al,dh;xor ah,ah {get txtloop from dh into ax} + add si,ax {Add to offset the offset of the..} + mov al,es:[si] ;xor ah,ah {..current character..} + shl ax,fontshift {..shift to get the byte offset..} + add ax,y1 {..of the graphic and add y to clip} + + mov es,word ptr SC.scrptr+2 {set up screen address segment} + + lea si,tcharset {point to character set} + add si,ax {add character offset} + mov cl,ylop ;inc cl {set up y loop (from y to ylop)} + + @drawloop: + push cx {save @drawloop} + mov cx,8 + mov ah,ds:[si] + + cmp dh,txtstart;jnz @noleft + and ah,lmask {mask with the left?} + @noleft: + cmp dh,txtend; jnz @noright + and ah,rmask {mask with the right?} + @noright: + + @bitloop: + shl ah,1 + jnc @nodraw + mov es:[di],dl + @nodraw: + inc di + loop @bitloop + add di,bx {shift to next line on screen} + inc si {go to next byte in pic} + pop cx + loop @drawloop + + sub di,decoffs {correct the screen position..} + inc dh {next character} + cmp dh,txtend {is it the end?} + jle @Textloop {if not, do it all again} + end; + {for txtlop:=1 to txtlop do begin + currmask:=pointer(@tcharset^[ord(txt[txtlop])][y]); + for lop:=0 to lop do begin + hsub2(adrs,currmask^ shr dxr,currmask^ shl (8-dxr)); + inc(Adrs,offs); + inc(currmask); + end; + dec(Adrs,decoffs); + end;} + end; + +end; + +Procedure outtextxy(x1,y1:integer;txt:string); +var txtend,ylop,txtstart,lmask,rmask:byte; + Adrs,decoffs:word; + x2,y2,tmp:integer; +Begin + txtend:=byte(txt[0]); + x2:=x1+(txtend shl 3); + y2:=y1+fontmax; + if (x1<=SC.viewport.x2)and(y1<=SC.viewport.y2)and(x2>=SC.viewport.x1) + and(y2>=SC.viewport.y1)and(txtend<>0) then begin + + {**Y-cliping**} + If y2>SC.viewport.y2 then ylop:=(SC.viewport.y2-y1) else ylop:=fontmax; + if y1SC.viewport.x2 then begin + dec(txtend,tmp shr 3); + rmask:=rmask shl (tmp and 7); + end; + if txtstart=txtend+1 then exit; + + + decoffs:=(SC.offsw*(ylop+1)-8); + asm + mov di,adrs {load offset} + + mov dl,t_col + mov bx,SC.offsw {load dx with screen offset} + sub bx,8 + + mov dh,txtstart {dh is the loop counter} + @Textloop: + les si,[bp+6] {point to string} + mov al,dh;xor ah,ah {get txtloop from dh into ax} + add si,ax {Add to offset the offset of the..} + mov al,es:[si] ;xor ah,ah {..current character..} + shl ax,fontshift {..shift to get the byte offset..} + add ax,y1 {..of the graphic and add y to clip} + + mov es,word ptr SC.scrptr+2 {set up screen address segment} + + lea si,tcharset {point to character set} + add si,ax {add character offset} + mov cl,ylop ;inc cl {set up y loop (from y to ylop)} + + @drawloop: + push cx {save @drawloop} + mov cx,8 + mov ah,ds:[si] + + cmp dh,txtstart;jnz @noleft + and ah,lmask {mask with the left?} + @noleft: + cmp dh,txtend; jnz @noright + and ah,rmask {mask with the right?} + @noright: + + @bitloop: + shl ah,1 + jnc @nodraw + mov es:[di],dl + @nodraw: + inc di + loop @bitloop + add di,bx {shift to next line on screen} + inc si {go to next byte in pic} + pop cx + loop @drawloop + + sub di,decoffs {correct the screen position..} + inc dh {next character} + cmp dh,txtend {is it the end?} + jle @Textloop {if not, do it all again} + end; + {for txtlop:=1 to txtlop do begin + currmask:=pointer(@tcharset^[ord(txt[txtlop])][y]); + for lop:=0 to lop do begin + hsub2(adrs,currmask^ shr dxr,currmask^ shl (8-dxr)); + inc(Adrs,offs); + inc(currmask); + end; + dec(Adrs,decoffs); + end;} + end; +end; +*) +Procedure Drawbytesxy(x1,y1:Integer;pic:bytearray;xbytes,ybytes:byte); +begin +end; + +Procedure Drawbytes(x1,y1:Integer;pic:bytearray;nbytes:byte); +var lop,mask:byte; Adrs:word; + x2:integer; +Begin + x2:=x1+8; + dec(nbytes); + if (x2>=sc.viewport.x1)and(x1<=SC.viewport.x2)and(y1+nbytes>=SC.viewport.y1)and(y1SC.viewport.x2 then + mask:=mask and ($ff shl (x2-SC.viewport.x2-1)); + + {**YCliping**} + If y1+nbytes>SC.viewport.y2 then lop:=(SC.viewport.y2-y1) else lop:=nbytes; + if y1SC.viewport.y2 then Return:=bellow else + if y1SC.viewport.x2 then inc(Return,right) else + if x1SC.viewport.x2))+ {right =$01} + (byte(yb>SC.viewport.y2)shl 1)+{bellow =$02} + (byte(xbSC.viewport.x2))+ {right =$01} + (byte(ya>SC.viewport.y2)shl 1)+{bellow =$02} + (byte(xa0 then begin + clip:=false;exit;{Trivial reject} + end else begin + if not(code0 or code1<>0)then begin + clip:=true;exit;{Trivial accept} + end else If (code0=0) then begin + fswap(code1,code0,1); + fswap(xb,xa,2); + fswap(yb,ya,2); + end; + if (code0 and bellow)<>0 then begin + inc(xb,(xa-xb)*(SC.viewport.y2-yb)div(ya-yb)); + yb:=SC.viewport.y2; + end else if (code0 and above)<>0 then begin + inc(xb,(xa-xb)*(SC.viewport.y1-yb)div(ya-yb)); + yb:=SC.viewport.y1; + end else if (code0 and right)<>0 then begin + inc(yb,(ya-yb)*(SC.viewport.x2-xb)div(xa-xb)); + xb:=SC.viewport.x2; + end else if (code0 and left)<>0 then begin + inc(yb,(ya-yb)*(SC.viewport.x1-xb)div(xa-xb)); + xb:=SC.viewport.x1; + end; + end; + end; +end; + +{biechmans line drawing algo- bit optimization still needed} +Procedure Line(x1,y1,x2,y2:integer); +Var dfx,dfy,d,d2,incr1,incr2,xinc:integer; +adrs:word; +Begin + if x1=x2 then vline(x1,y1,y2) else begin + if y1=y2 then hline(x1,x2,y1) else + if clip(x1,y1,x2,y2) then Begin + dfx:=abs(x2-x1);dfy:=abs(y2-y1); + asm mov es,word ptr SC.scrptr+2 end; + if dfx>dfy then begin + asm + mov ax,x2 ; cmp x1,ax ; jle @no_swap + Xchg x1,ax ; mov x2,ax + mov ax,y2; Xchg y1,ax;mov y2,ax; + @no_swap: + + mov ax,y1; imul SC.offsw ;add ax,word ptr SC.scrptr; {sort out address:} + mov bx,x1; add ax,bx {adrs:=(y1*SC.offsw)+(x1 shr 3)+word ptr SC.scrptr;} + mov adrs,ax + end; + + incr2:=(dfy-dfx)shl 1; + if(y2>y1) then xinc:=SC.offsw else xinc:=-SC.offsw; + + asm + mov al,t_col + mov dx,xinc {get scanline offset} + mov bx,adrs {get offset} + + mov cx,dfx ;inc cx {load in the length} + mov si,dfy ;shl si,1; {get incr1} + mov di,si ;sub di,dfx; {get 'd'} + push bp {remember stack frame} + mov bp,incr2 + + @Runloop: {start loop} + mov es:[bx],al + inc bx + cmp di,0;jl @noinc {new scan line?} + add di,bp {update di} + add bx,dx {add scanline offset} + jmp @check + @noinc: + add di,si {update fractional part} + @check: + loop @runloop + pop bp {recall stack frame} + end; + end else begin + asm + mov ax,y2 ; cmp y1,ax ; jle @no_swap + Xchg y1,ax ; mov y2,ax + mov ax,x2; Xchg x1,ax;mov x2,ax; + @no_swap: + mov ax,y1; imul SC.offsw ;add ax,word ptr SC.scrptr; {sort out address:} + mov bx,x1; add ax,bx {adrs:=(y1*SC.offsw)+(x1 shr 3)+word ptr SC.scrptr;} + mov adrs,ax + end; + d2:=dfx shl 1; + d:=d2-dfy; + incr1:=d2; + incr2:=(dfx-dfy) shl 1; + asm + inc dfy {add one to difference in y} + mov dx,SC.offsw {screen width} + mov bx,adrs {screen address} + mov al,t_col {Colour} + mov di,d {(diff in X*2)-diff in y} + mov si,incr1 {integer increment} + + mov cx,x1; cmp cx,x2; + jg @left {check if line is doing left or right} + + {do these loads for both directions because of the use of bp} + mov cx,dfy {difference in Y} + push bp + mov bp,incr2 {fractional increment} + @Runloop: + mov es:[bx],al {Write to screen} + add bx,dx {next scan line} + cmp di,0 {if no change} + jl @noinc {then don't do below} + add di,bp {do frac part} + inc bx {go to next byte on screen} + jmp @check + @noinc: + add di,si {add frac part} + @check: + loop @runloop + jmp @end + + @left: + {do these loads for both directions because of the use of bp} + mov cx,dfy {difference in Y} + push bp + mov bp,incr2 {fractional increment} + @Runloopb: + mov es:[bx],al {Write to screen} + add bx,dx {next scan line} + cmp di,0 {if no change} + jl @noincb {then don't do below} + add di,bp {do frac part} + dec bx + jmp @checkb + @noincb: + add di,si {add frac part} + @checkb: + loop @runloopb + @end: + pop bp + end; + end; + end; + end; +end; + +Procedure Hline(x1,x2,y:Integer);assembler; +asm + mov ax,y;mov bx,x1; mov cx,x2 + {swap x1,x1 if x1>x2} + cmp bx,cx ;jle @no_swap ; Xchg bx,cx; @no_swap: + + {is line at all visable?} + cmp bx,SC.viewport.x2 ;jg @fin + cmp cx,SC.viewport.x1 ;jl @fin + cmp ax,SC.viewport.y2 ;jg @fin + cmp ax,SC.viewport.y1 ;jl @fin + + {X axis clipping} + mov dx,SC.viewport.x1 ;cmp bx,dx ; JGE @nochange_x1 + mov bx,dx + @nochange_x1: + mov dx,SC.viewport.x2 ;cmp cx,dx ; JLE @nochange_x2 + mov cx,dx + @nochange_x2: + + {start of mode dependant stuff} {load up screen position} + mov es,word ptr SC.scrptr+2 + inc cx ;imul SC.offsw ;add ax,word ptr SC.scrptr; mov di,ax {load up screen pos} + + {calculate length (in bytes-1) of line} + sub cx,bx {get byte length} + add di,bx {add this to screen memory offset} + + mov al,t_col + mov ah,al + + shr cx,1 {get word count} + REP stosw {store words} + adc cx,cx {extra byte?} + REP stosb {Draw if there} + + @fin: +end; + + +Procedure bar(x1,y,x2,y2:integer); +var adrs:word; +Begin + if x2SC.viewport.y2)or(y2SC.viewport.x2)or(x2SC.viewport.x2 then x2:=SC.viewport.x2;if y2>SC.viewport.y2 then y2:=SC.viewport.y2; + inc(x2);inc(y2); + adrs:=(y*SC.offsw)+x1; + asm + mov es,word ptr SC.scrptr+2 + mov di,adrs {address} + add di,word ptr SC.scrptr + mov ax,SC.offsw + mov si,ax {load offset} + mov al,t_fillcol + mov bx,x2 + sub bx,x1 + mov cx,y2 {load loop count -ycnt} + sub cx,y + mov dx,SC.offsw + sub dx,bx + @runloop: + push cx + mov cx,bx + rep stosb + pop cx + add di,dx + loop @runloop + end; + end; +end; + +Procedure Vline(x,y1,y2:Integer);assembler; +asm + {es -screen seg + di -byte offset + al -byte mask + cx -Y length of line} + {remember that these registers are loaded thus:} + mov ax,y1; mov cx,y2 ;mov bx,x + {swap y2,y1 if y1>y2} + cmp ax,cx ;jle @no_swap ; Xchg ax,cx; @no_swap: + + cmp ax,SC.viewport.y2 ;jg @fin {is line at all visable?} + cmp cx,SC.viewport.y1 ;jl @fin + cmp bx,SC.viewport.x2 ;jg @fin + cmp bx,SC.viewport.x1 ;jl @fin + + {Y axis clipping} + mov dx,SC.viewport.y1 ;cmp ax,dx ; JGE @nochange_y1 + mov ax,dx + @nochange_y1: + mov dx,SC.viewport.y2 ;cmp cx,dx ; JLE @nochange_y2 + mov cx,dx + @nochange_y2: + + inc cx {inc y2} + sub cx,ax {calc length} + + les di,SC.scrptr {load up screen position} + imul SC.offsw; + add di,ax; add di,bx; {add di, y*SC.offsw +xposition} + {result of imul is stored (thank God) in ax-dx, perfect for svga} + + mov bx,SC.offsw {load screen width} + mov al,t_col + + @runloop: + mov es:[di],al {write to screen} + add di,bx {next pixel} + loop @runloop + @fin: +end; + +Procedure putpixel(x1,y1:Integer);assembler; +asm + {if dot visable?} + mov bx,x1 ;mov ax,y1 + cmp bx,SC.viewport.x1 ;jl @fin {clipping..} + cmp ax,SC.viewport.y1 ;jl @fin + cmp bx,SC.viewport.x2 ;jg @fin + cmp ax,SC.viewport.y2 ;jg @fin + + mov es,word ptr SC.scrptr+2 + imul SC.offsw; add ax,word ptr SC.scrptr + add ax,bx; mov di,ax {load up screen pos} + + mov al,t_col + + mov es:[di],al + @fin: +end; + +Function getpixel(x1,y1:Integer):byte; +begin asm + mov es,word ptr SC.scrptr+2 + imul SC.offsw; add ax,word ptr SC.scrptr + add ax,bx; mov di,ax {load up screen pos} + + mov al,es:[di] + mov @result,al + end; +end; + +Procedure Triangle(xa,ya,xb,yb,xc,yc:integer);assembler; +const shiftby=6; +Var +lop,Lx,Rx, +Lxadd,Rxadd,yrdiff,yldiff,xoff,Lxa,Rxa,xdiff,endp:integer; +right:boolean; +scroffset:word; + {sort by Y} + asm + {if ya>yc then swap xc,xa swap yc,ya fswap ic,ia} + mov ax,yc + cmp ya,ax + jl @NoSwapY1 + xchg ya,ax; mov yc,ax + mov ax,xc; xchg xa,ax; mov xc,ax + @NoSwapY1: + {if ya>yb then swap xb,xa swap yb,ya fswap ib,ia} + mov ax,yb + cmp ya,ax + jl @NoSwapY2 + xchg ya,ax; mov yb,ax + mov ax,xb; xchg xa,ax; mov xb,ax + @NoSwapY2: + {if yb>yc then swap xc,xb swap yc,yb fswap ic,ib} + mov ax,yc + cmp yb,ax + jl @NoSwapY3 + xchg yb,ax; mov yc,ax + mov ax,xc; xchg xb,ax; mov xc,ax + @NoSwapY3: + + {is the cross point to the left or right?} + mov di,yc;sub di,ya + mov ax,yb;sub ax,yc + mov cx,xc;sub cx,xa + imul cx + cmp di,0 + jz @nodiv + idiv di + @nodiv: + add ax,xc + cmp xb,ax + mov right,true + jle @isright + mov right,false + @isright: + {get smallest x} + mov bx,xa; + mov ax,xb + cmp bx,ax; jl @nodo1 ;mov bx,ax ;@nodo1: + mov ax,xc + cmp bx,ax; jl @nodo2 ;mov bx,ax ;@nodo2: + mov xoff,bx + {sub by bx and shift left } + sub xa,bx; + sub xb,bx; + sub xc,bx; + + shl xa,shiftby + shl xb,shiftby + shl xc,shiftby + + {get y length} + mov si,yc + cmp si,SC.viewport.y2 + jle @noyclip + mov si,SC.viewport.y2 + inc si + @noyclip: + + mov endp,si {exit routine if ends of tri are outside VP} + mov si,ya + cmp si,SC.viewport.y2 {if ya>SC.viewport then exit} + jg @triend + cmp si,endp {if ya=clipped yc then exit} + jz @triend + + {yldiff:=yb-ya;if yldiff=0 then yldiff:=1; + Lxadd:=(xb-xa) div yldiff;} + mov ax,xb ;sub ax,xa + mov bx,yb ;sub bx,ya + jz @nodiv1 + cwd + idiv bx + jmp @nocorrect1 + @nodiv1: + mov bx,1 + @nocorrect1: + mov yldiff,bx + mov lxadd,ax + {yrdiff:=yc-ya;if yrdiff=0 then yrdiff:=1; + Rxadd:=(xc-xa) div yrdiff;} + mov ax,xc ;sub ax,xa + mov bx,yc ;sub bx,ya + jz @nodiv2 + cwd + idiv bx + jmp @nocorrect2 + @nodiv2: + mov bx,1 + @nocorrect2: + mov yrdiff,bx + mov rxadd,ax + mov ax,xa + mov Lxa,ax + mov Rxa,ax + {test for swap} + test right,1 + jnz @isrightb + mov ax,rxadd + xchg lxadd,ax + mov rxadd,ax + @isrightb: + + mov es,word ptr SC.scrptr+2 {load up screen mem pos} + mov cx,SC.offsw + mov ax,ya ;imul cx ;add ax,word ptr SC.scrptr + mov di,ax + + @Yloop: + cmp si,yb + jnz @Daltend + {yldiff:=yc-yb;if yldiff=0 then yldiff:=1;} + mov bx,yc ;sub bx,yb + jnz @nocorrect; mov bx,1; @nocorrect: + {Lxadd:=(xc-xb) div yldiff;} + mov ax,xc; sub ax,xb + cwd + idiv bx + mov bx,xb + {test see which side these need to go in} + test right,true + jz @isleft + mov lxadd,ax + mov lxa,bx + jmp @Daltend + @isleft: + mov rxadd,ax + mov rxa,bx + @Daltend: + + push di + {inc x1a and x2a with the slope of line and inc offset} + mov ax,Lxadd;add lxa,ax + mov ax,Rxadd;add rxa,ax + {if ylop>SC.viewport.y1 then....} + mov ax,SC.viewport.y1 ;cmp ax,si ;jg @fin + {convert the line to normal pixel-space} + mov cx,rxa ;shr cx,shiftby ;add cx,xoff + mov dx,lxa ;shr dx,shiftby ;add dx,xoff + + {flip- shouldn't have to but there ya go} + cmp dx,cx ;jg @no_swap ; Xchg cx,dx; @no_swap: {if x1>x2 then swap} + {if (x1>SC.viewport.x2)or(x2yc then swap xc,xa swap yc,ya fswap ic,ia} + mov ax,yc + cmp ya,ax + jl @NoSwapY1 + xchg ya,ax; mov yc,ax + mov ax,xc; xchg xa,ax; mov xc,ax + mov ax,ic; xchg ia,ax; mov ic,ax + @NoSwapY1: + {if ya>yb then swap xb,xa swap yb,ya fswap ib,ia} + mov ax,yb + cmp ya,ax + jl @NoSwapY2 + xchg ya,ax; mov yb,ax + mov ax,xb; xchg xa,ax; mov xb,ax + mov ax,ib; xchg ia,ax; mov ib,ax + @NoSwapY2: + {if yb>yc then swap xc,xb swap yc,yb fswap ic,ib} + mov ax,yc + cmp yb,ax + jl @NoSwapY3 + xchg yb,ax; mov yc,ax + mov ax,xc; xchg xb,ax; mov xc,ax + mov ax,ic; xchg ib,ax; mov ic,ax + @NoSwapY3: + {is the cross point to the left or right?} + mov di,yc;sub di,ya + mov ax,yb;sub ax,yc + mov cx,xc;sub cx,xa + imul cx + cmp di,0 + jz @nodiv + idiv di + @nodiv: + add ax,xc + cmp xb,ax + mov right,true + jle @isright + mov right,false + @isright: + {get smallest x} + mov bx,xa; + mov ax,xb + cmp bx,ax; jl @nodo1 ;mov bx,ax ;@nodo1: + mov ax,xc + cmp bx,ax; jl @nodo2 ;mov bx,ax ;@nodo2: + mov xoff,bx + {sub by bx and shift left } + sub xa,bx; + sub xb,bx; + sub xc,bx; + + shl xa,shiftby + shl xb,shiftby + shl xc,shiftby + end; + asm + db 66h;shr word ptr ia,16; + db 66h;shr word ptr ib,16; + db 66h;shr word ptr ic,16; + end; + + ylop:=ya;endp:=yc; + if endp>SC.viewport.y2 then endp:=SC.viewport.y2+1; + + asm + {yldiff:=yb-ya;if yldiff=0 then yldiff:=1; + Lxadd:=(xb-xa) div yldiff;} + mov ax,xb ;sub ax,xa + mov bx,yb ;sub bx,ya + jz @nodiv1 + cwd + idiv bx + jmp @nocorrect1 + @nodiv1: + mov bx,1 + @nocorrect1: + mov yldiff,bx + mov lxadd,ax + {yrdiff:=yc-ya;if yrdiff=0 then yrdiff:=1; + Rxadd:=(xc-xa) div yrdiff;} + mov ax,xc ;sub ax,xa + mov bx,yc ;sub bx,ya + jz @nodiv2 + cwd + idiv bx + jmp @nocorrect2 + @nodiv2: + mov bx,1 + @nocorrect2: + mov yrdiff,bx + mov rxadd,ax + end; + {yrdiff:=yc-ya;if yrdiff=0 then yrdiff:=1; + Rxadd:=(xc-xa) div yrdiff;} + Lxa:=xa;Rxa:=xa; + + li32:=ia32; + ri32:=ia32; + liadd32:=(ib32-ia32)div yldiff; + riadd32:=(ic32-ia32)div yrdiff; + if not right then begin + fswap(rxadd,lxadd,2); + fswap(liadd32,riadd32,4); + end; + asm + mov es,word ptr SC.scrptr+2 {load up screen mem pos} + mov si,SC.offsw + mov ax,ya ;imul si ;add ax,word ptr SC.scrptr + mov scroffset,ax + end; + while ylopSC.viewport.y1 then....} + mov ax,SC.viewport.y1 ;cmp ax,ylop ;jg @fin + {convert the line to normal pixel-space} + {xa is in dx, xb is in cx} + mov cx,rxa ;shr cx,shiftby ;add cx,xoff + mov dx,lxa ;shr dx,shiftby ;add dx,xoff + {Xclipping} + mov di,cx + inc di + sub di,dx + mov ax,SC.viewport.x2 ;cmp cx,ax ; JLE @nochange_x2 + mov cx,ax + @nochange_x2: + mov ax,SC.viewport.x1 ;cmp dx,ax ; JGE @nochange_x1 + mov dx,ax + @nochange_x1: + inc cx + mov lx,dx + sub cx,dx {calculate xdiff} + jle @fin + mov xdiff,cx {save it} + {generate colour interpoltaion addition} + mov si,li {colour intensity start} + mov ax,ri + sub ax,si {load colour} + CWD {put ax into AX:DX, with sign} + idiv di {do it, baby} + mov cadd,ax {load ax into erm... addi?} + mov dx,lx + {re-evaluate start address} + mov di,scroffset + mov cx,dx {get the x value} + add di,cx {add this to total} + + mov cx,xdiff {xdiff is the length (xb-xa)} + + push bp + mov bp,Cadd {colour interpolation value} + + @drawloop: + mov bx,si {load colour} + shr bx,8 {get it into non-fixed range} + mov es:[di],bl {write to screen} + add si,bp {add colour interpolation value} + inc di {increment screen offset} + loop @drawloop + pop bp + @fin: + end; + {ci:=li; + for lop:=Lx to Rx do begin + t_col:=asr(ci); + inc(ci,addi); + putpixel(lop,ylop); + end;} + inc(scroffset,SC.offsw); + inc(ylop); + end; +end; + +Procedure Screencopy(x1,y1,x2,y2,xd,yd:integer;page1,page2:byte); +begin +end; + +Procedure putbitmap(x1,y1:integer;bitmap:bitmaptypeptr); +var ylop,xlop:integer; + adrs,picadrs:byteptr; + x2,y2:integer; +Begin + with bitmap^ do begin + x2:=x1+size.x; + y2:=y1+size.y; + if (y1SC.viewport.x1) and(y2>SC.viewport.y1) then begin + if bitmaptype=BMflat then begin + picadrs:=pointer(flatdata); + if x1SC.viewport.x1) and(y2>SC.viewport.y1) then begin + + picadrs:=pointer(flatdata); + if x1SC.viewport.x1) and(y2>SC.viewport.y1) then begin + + picadrs:=pointer(flatdata); + if x1SC.viewport.x1) and(y2>SC.viewport.y1) then begin + + picadrs:=pointer(flatdata); + if x1SC.viewport.x1) and(y2>SC.viewport.y1) then begin + + picadrs:=pointer(flatdata); + if x1SC.viewport.x1) and(y2>SC.viewport.y1) then begin + + picadrs:=pointer(flatdata); + if x1