From 0af3510705e3a3de0f0232d7fb10d050413d54e9 Mon Sep 17 00:00:00 2001 From: Luther Date: Sat, 29 May 2021 16:57:46 +0100 Subject: [PATCH] Initial commit --- BASIC3D.PAS | 178 ++++ BITMAP16.PAS | 188 ++++ BITMAP25.PAS | 1854 ++++++++++++++++++++++++++++++++ CHARDEF.PAS | 440 ++++++++ CLAYCP.PAS | 1377 ++++++++++++++++++++++++ COLOUR.PAS | 501 +++++++++ CPUTYPE.PAS | 138 +++ CRT2.PAS | 127 +++ DIALOGS.PAS | 1214 +++++++++++++++++++++ DISKOP.PAS | 280 +++++ DMA.PAS | 204 ++++ EMSUNIT.PAS | 302 ++++++ GADGETS.PAS | 89 ++ GBASICS.PAS | 952 +++++++++++++++++ GGRAPH.PAS | 643 +++++++++++ LCD.PAS | 163 +++ MSMOUSE.PAS | 397 +++++++ PCX256.PAS | 263 +++++ PITTIMER.PAS | 95 ++ SINCOS.PAS | 40 + STDPAL.PAS | 13 + SVGA256.PAS | 1832 ++++++++++++++++++++++++++++++++ TDB.PAS | 754 +++++++++++++ TDEDITB.PAS | 2636 ++++++++++++++++++++++++++++++++++++++++++++++ TDWIN.PAS | 1492 ++++++++++++++++++++++++++ TMATHS.PAS | 929 ++++++++++++++++ TMENUST.PAS | 493 +++++++++ TTYPES.PAS | 204 ++++ TWINB.PAS | 2252 +++++++++++++++++++++++++++++++++++++++ TWINDRAW.PAS | 699 ++++++++++++ VECTFONT.PAS | 193 ++++ VESAINFO.PAS | 148 +++ VESATEST.PAS | 23 + VGA16.PAS | 2179 ++++++++++++++++++++++++++++++++++++++ VGA256.PAS | 1854 ++++++++++++++++++++++++++++++++ VIEWS.PAS | 1054 ++++++++++++++++++ XVGA256.PAS | 1659 +++++++++++++++++++++++++++++ bin/FORMAT.TXT | 59 ++ bin/HELP.TXT | 309 ++++++ bin/INFO.TXT | 200 ++++ bin/INSTALL.TXT | 22 + bin/REGISTER.TXT | 31 + bin/SANSF16B.FNT | Bin 0 -> 4097 bytes bin/TRIP.CHR | Bin 0 -> 16677 bytes bin/WARN.PCX | Bin 0 -> 1403 bytes readme.txt | 73 ++ 46 files changed, 28553 insertions(+) create mode 100644 BASIC3D.PAS create mode 100644 BITMAP16.PAS create mode 100644 BITMAP25.PAS create mode 100644 CHARDEF.PAS create mode 100644 CLAYCP.PAS create mode 100644 COLOUR.PAS create mode 100644 CPUTYPE.PAS create mode 100644 CRT2.PAS create mode 100644 DIALOGS.PAS create mode 100644 DISKOP.PAS create mode 100644 DMA.PAS create mode 100644 EMSUNIT.PAS create mode 100644 GADGETS.PAS create mode 100644 GBASICS.PAS create mode 100644 GGRAPH.PAS create mode 100644 LCD.PAS create mode 100644 MSMOUSE.PAS create mode 100644 PCX256.PAS create mode 100644 PITTIMER.PAS create mode 100644 SINCOS.PAS create mode 100644 STDPAL.PAS create mode 100644 SVGA256.PAS create mode 100644 TDB.PAS create mode 100644 TDEDITB.PAS create mode 100644 TDWIN.PAS create mode 100644 TMATHS.PAS create mode 100644 TMENUST.PAS create mode 100644 TTYPES.PAS create mode 100644 TWINB.PAS create mode 100644 TWINDRAW.PAS create mode 100644 VECTFONT.PAS create mode 100644 VESAINFO.PAS create mode 100644 VESATEST.PAS create mode 100644 VGA16.PAS create mode 100644 VGA256.PAS create mode 100644 VIEWS.PAS create mode 100644 XVGA256.PAS create mode 100644 bin/FORMAT.TXT create mode 100644 bin/HELP.TXT create mode 100644 bin/INFO.TXT create mode 100644 bin/INSTALL.TXT create mode 100644 bin/REGISTER.TXT create mode 100644 bin/SANSF16B.FNT create mode 100644 bin/TRIP.CHR create mode 100644 bin/WARN.PCX create mode 100644 readme.txt 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