**LISTING 52.9 L52-9.ASM** ; 386-specific fixed point multiply and divide. ; ; C near-callable as: Fixedpoint FixedMul(Fixedpoint M1, Fixedpoint M2); ; Fixedpoint FixedDiv(Fixedpoint Dividend, Fixedpoint Divisor); ; ; Tested with TASM ; .model small .386 .code public _FixedMul,_FixedDiv ; Multiplies two fixed-point values together. FMparms struc dw 2 dup(?) ;return address & pushed BP M1 dd ? M2 dd ? FMparms ends align 2 _FixedMul proc near push bp mov bp,sp mov eax,[bp+M1] imul dword ptr [bp+M2] ;multiply add eax,8000h ;round by adding 2^(-16) adc edx,0 ;whole part of result is in DX shr eax,16 ;put the fractional part in AX pop bp ret _FixedMul endp ; Divides one fixed-point value by another. FDparms struc dw 2 dup(?) ;return address & pushed BP Dividend dd ? Divisor dd ? FDparms ends align 2 _FixedDiv proc near push bp mov bp,sp sub cx,cx ;assume positive result mov eax,[bp+Dividend] and eax,eax ;positive dividend? jns FDP1 ;yes inc cx ;mark it's a negative dividend neg eax ;make the dividend positive FDP1: sub edx,edx ;make it a 64-bit dividend, then shift ; left 16 bits so that result will be in EAX rol eax,16 ;put fractional part of dividend in ; high word of EAX mov dx,ax ;put whole part of dividend in DX sub ax,ax ;clear low word of EAX mov ebx,dword ptr [bp+Divisor] and ebx,ebx ;positive divisor? jns FDP2 ;yes dec cx ;mark it's a negative divisor neg ebx ;make divisor positive FDP2: div ebx ;divide shr ebx,1 ;divisor/2, minus 1 if the divisor is adc ebx,0 ; even dec ebx cmp ebx,edx ;set Carry if remainder is at least adc eax,0 ; half as large as the divisor, then ; use that to round up if necessary and cx,cx ;should the result be made negative? jz FDP3 ;no neg eax ;yes, negate it FDP3: mov edx,eax ;return result in DX:AX; fractional ; part is already in AX shr edx,16 ;whole part of result in DX pop bp ret _FixedDiv endp end **LISTING 52.10 POLYGON.H** /* POLYGON.H: Header file for polygon-filling code, also includes a number of useful items for 3-D animation. */ #define MAX_OBJECTS 100 /* max simultaneous # objects supported */ #define MAX_POLY_LENGTH 4 /* four vertices is the max per poly */ #define SCREEN_WIDTH 320 #define SCREEN_HEIGHT 240 #define PAGE0_START_OFFSET 0 #define PAGE1_START_OFFSET (((long)SCREEN_HEIGHT*SCREEN_WIDTH)/4) #define NUM_CUBE_VERTS 8 /* # of vertices per cube */ #define NUM_CUBE_FACES 6 /* # of faces per cube */ /* Ratio: distance from viewpoint to projection plane / width of projection plane. Defines the width of the field of view. Lower absolute values = wider fields of view; higher values = narrower */ #define PROJECTION_RATIO -2.0 /* negative because visible Z coordinates are negative */ /* Draws the polygon described by the point list PointList in color Color with all vertices offset by (X,Y) */ #define DRAW_POLYGON(PointList,NumPoints,Color,X,Y) \ Polygon.Length = NumPoints; Polygon.PointPtr = PointList; \ FillConvexPolygon(&Polygon, Color, X, Y); #define INT_TO_FIXED(x) (((long)(int)x) << 16) #define DOUBLE_TO_FIXED(x) ((long) (x * 65536.0 + 0.5)) typedef long Fixedpoint; typedef Fixedpoint Xform[3][4]; /* Describes a single 2D point */ typedef struct { int X; int Y; } Point; /* Describes a single 3D point in homogeneous coordinates; the W coordinate isn't present, though; assumed to be 1 and implied */ typedef struct { Fixedpoint X, Y, Z; } Point3; typedef struct { int X; int Y; int Z; } IntPoint3; /* Describes a series of points (used to store a list of vertices that describe a polygon; each vertex is assumed to connect to the two adjacent vertices; last vertex is assumed to connect to first) */ typedef struct { int Length; Point * PointPtr; } PointListHeader; /* Describes the beginning and ending X coordinates of a single horizontal line */ typedef struct { int XStart; int XEnd; } HLine; /* Describes a Length-long series of horizontal lines, all assumed to be on contiguous scan lines starting at YStart and proceeding downward (used to describe a scan-converted polygon to the low-level hardware-dependent drawing code). */ typedef struct { int Length; int YStart; HLine * HLinePtr;} HLineList; typedef struct { int Left, Top, Right, Bottom; } Rect; /* structure describing one face of an object (one polygon) */ typedef struct { int * VertNums; int NumVerts; int Color; } Face; typedef struct { double RotateX, RotateY, RotateZ; } RotateControl; typedef struct { Fixedpoint MoveX, MoveY, MoveZ, MinX, MinY, MinZ, MaxX, MaxY, MaxZ; } MoveControl; /* fields common to every object */ #define BASE_OBJECT \ void (*DrawFunc)(); /* draws object */ \ void (*RecalcFunc)(); /* prepares object for drawing */ \ void (*MoveFunc)(); /* moves object */ \ int RecalcXform; /* 1 to indicate need to recalc */ \ Rect EraseRect[2]; /* rectangle to erase in each page */ /* basic object */ typedef struct { BASE_OBJECT } Object; /* structure describing a polygon-based object */ typedef struct { BASE_OBJECT int RDelayCount, RDelayCountBase; /* controls rotation speed */ int MDelayCount, MDelayCountBase; /* controls movement speed */ Xform XformToWorld; /* transform from object->world space */ Xform XformToView; /* transform from object->view space */ RotateControl Rotate; /* controls rotation change over time */ MoveControl Move; /* controls object movement over time */ int NumVerts; /* # vertices in VertexList */ Point3 * VertexList; /* untransformed vertices */ Point3 * XformedVertexList; /* transformed into view space */ Point3 * ProjectedVertexList; /* projected into screen space */ Point * ScreenVertexList; /* converted to screen coordinates */ int NumFaces; /* # of faces in object */ Face * FaceList; /* pointer to face info */ } PObject; extern void XformVec(Xform, Fixedpoint *, Fixedpoint *); extern void ConcatXforms(Xform, Xform, Xform); extern int FillConvexPolygon(PointListHeader *, int, int, int); extern void Set320x240Mode(void); extern void ShowPage(unsigned int); extern void FillRectangleX(int, int, int, int, unsigned int, int); extern void XformAndProjectPObject(PObject *); extern void DrawPObject(PObject *); extern void AppendRotationX(Xform, double); extern void AppendRotationY(Xform, double); extern void AppendRotationZ(Xform, double); extern near Fixedpoint FixedMul(Fixedpoint, Fixedpoint); extern near Fixedpoint FixedDiv(Fixedpoint, Fixedpoint); extern void InitializeFixedPoint(void); extern void RotateAndMovePObject(PObject *); extern void InitializeCubes(void); extern int DisplayedPage, NonDisplayedPage, RecalcAllXforms; extern int NumObjects; extern Xform WorldViewXform; extern Object *ObjectList[]; extern Point3 CubeVerts[];