; LKS 3-Dimensional Object Management System (3DOMS) version 0.103 ; 3DOMS.INC - LKS Created: 22/Dec/1994 Now: 12/Jan/1995. ; PRINTOUT #3 - The code so far. 12/Jan/1995. Heap functions well tested. ; There were quite a few bugs in the CREATE/DELETE routines. ; An error in LOGOFF meant that the computer rebooted when the interrupt ; vector 3Dh was reset was sorted out (I never found out why it did it, but ; swapping the memory deallocation and vector resetting bits seemed to stop ; it). ; Improvements from printout #2: ; - Any obvious mistakes in comments or code fixed. ; - Triangle routine written and debugged (It took some doing!) ; - Basic rendering completed and working - it's far too slow. ; Aims: ; - Make the blitting routines use the screen width and other variables. ; - Incorporate point structures. ; - Incorporate basic textures. ;----------------------------- Documentation --------------------------------; comment | The logon and logoff routines must be called at the start and end of the host program respectively. ;-------- Structure. (POINT) <- Face <- Shape <- FORM <- Object <- Group <- UNIVERSE TEXTURES When I have perfected the basic rendering, I will work on texturing methods including bitmapping, RGB colours (using dithering and an orthogonal palette), and reflectiveness and surface normal smooth shading (for fast computers only!). Other graphical effects which I hope to include to add realism to scenes are light source shading and distance fading. POINTS To make rendering calculations more efficient, I want to introduce a point structure. Then, a point shared between many faces will have all it's calculations done once per shape, not once per face. Faces will still be created in the same way, and points will be managed behind the scenes. FACES Faces are the most basic pieces of a 3-dimensional thing. To avoid any programming difficulties on my part and to make rendering as fast as possible, all faces are triangular. If higher polygons are required, they must be made from more than one face. SHAPES Shapes are the basic building blocks of complicated objects. A shape must be totally convex otherwise rendering will be inaccurate. If you need to make a convex object, it must consist of more than one shape. For example, if you want to make a plane, you may have each wing as one shape, the body as another and the tail as another. Center co-ordinates are first used in shapes. These are used to tell 3DOMS which order to put shapes on the screen if they overlap. It starts by drawing the one with a center furthest from the viewer and works forward. The programmer has to specify the center co-ordinates themselves - they should be centralised and 'inside' the shape if possible. FORMS Shapes and faces are constants - if you want to have more than one plane flying around, as long as all the planes look the same, they can all use the same shapes and faces. A form is basically a descriptor for a linked list of shapes. When you create a new object, you specify it's form, which will be used when the object is drawn. OBJECTS Collections of shapes of a particular form. All the planes would be objects. GROUPS Collections of objects. These can have moving parts, which will be objects, because each object can be moved or rotated individually. A group may be a plane object and some wheel and flap objects, as the wheels and flaps are not fixed in position on the plane. Groups are the main linked list, so, even if an object exists on it's own, it has to be a member of the group - the only one. I may add a flag which allows you to make groups invisible - the renderer will just miss them out - so that, instead of destroying a group temporarily when it is not needed, it can just be made invisible. UNIVERSE I added a universe structure so that groups could be treated as normal child structures and could use the common create/delete routines. ;-------- Function 00h - Get Version And Run-Time Info Inputs: AH - 00h Returns: AH - Major version number. AL - Minor version number. BX - Segment of heap. CX - Size of heap in 32-byte cells. DX - Number of 32-byte cells free. This function returns information about the status of LKS 3DOMS. ;*------- Function 08h - Move Camera Inputs: AH - 08h DS:SI - Pointer to new camera data: 3 double word co-ordinates, 3 rotation bytes and one rotation order byte - 16 bytes in all. Returns: (null) Moves and rotates the viewpoint. ;*------- Function 09h - Change Camera Inputs: AH - 08h DS:SI - Pointer to new camera data: Double-words screen-to-eye distance and screen-to-origin distance. Returns: (null) Changes the distance from the viewer's eye to the screen and from the screen to the origin. ;*------- Function 0Ah - Change View Area. Inputs: AH - 0Ah BX - Virtual width of buffer. CX - New width of viewing area. DX - New height of viewing area. DI - Start of viewing area in virtual buffer. Returns: (null) This function changes the real and virtual size of the output buffer. If outputting to the screen in a smaller window, for example, the virtual width would still be 320, the virtual offset (in DI) would be the offset of the top left hand pixel of the viewing area, and CX and DX would be the size of the area. ;-------- Function 10h - Create Face Inputs: AH - 10h DS:SI - Pointer to face data: 9 co-ordinate words and a colour byte (19 bytes in all). ES - Segment of parent shape. Returns: Carry clear - Success AX - Segment of created face. Carry set - Error AX - Error code. Creates a new face constant in the shape specified. ;-------- Function 11h - Delete Face Inputs: AH - 11h ES - Segment of parent shape. DS - Segment of face. Returns: Carry clear - Success AX - Number of free cells. Carry set - Error AX - Error code. Deletes the face constant from the shape constant specified and frees the cell which contained it. ;-------- Function 14h - Create Shape Inputs: AH - 14h DS:SI - Pointer to shape data: 3 co-ordinate words for center of shape. ES - Segment of parent form. Returns: Carry clear - Success AX - Segment of created shape. Carry set - Error AX - Error code. Creates a new shape constant in the form specified. ;-------- Function 15h - Delete Shape Inputs: AH - 11h ES - Segment of shape. Returns: Carry clear - Success AX - Number of free cells. Carry set - Error AX - Error code. Deletes the shape constant from the form specified and frees the cell which contained it. ;-------- Function 18h - Create Object Inputs: AH - 18h DS:SI - Pointer to object data: 3 double word co-ordinates, 3 rotation bytes and one rotation order byte - 16 bytes in all. ES - Segment of parent group. Returns: Carry clear - Success AX - Segment of created object. Carry set - Error AX - Error code. Creates a new object in the group specified. ;-------- Function 19h - Delete Object Inputs: AH - 19h ES - Segment of object. Returns: Carry clear - Success AX - Number of free cells. Carry set - Error AX - Error code. Deletes the object from the group specified and frees the cell which contained it. ;-------- Function 1Ah - Move Object Inputs: AH - 1Ah DS:SI - Pointer to object data: 3 double word co-ordinates, 3 rotation bytes and one rotation order byte - 16 bytes in all. ES - Segment of object. Returns: Carry clear - Success Carry set - Error AX - Error code. Changes the co-ordinates and rotation of an object. ;-------- Function 1Bh - Change Object Form Inputs: AH - 1Ah BX - Segment of new form (or 0 to just get current form). ES - Segment of object. Returns: Carry clear - Success AX - Segment of old form. Carry set - Error AX - Error code. Changes the form of an object. ;-------- Function 1Ch - Create Group Inputs: AH - 1Ch DS:SI - Pointer to group data: 3 double word co-ordinates, 3 rotation bytes and one rotation order byte - 16 bytes in all. ES - Segment of parent universe. Returns: Carry clear - Success AX - Segment of created group. Carry set - Error AX - Error code. Creates a new group. ;-------- Function 1Dh - Delete Group Inputs: AH - 1Dh ES - Segment of group. Returns: Carry clear - Success AX - Number of free cells. Carry set - Error AX - Error code. Deletes the group specified and frees the cell which contained it. ;-------- Function 1Eh - Move Group Inputs: AH - 1Eh DS:SI - Pointer to group data: 3 double word co-ordinates, 3 rotation bytes and one rotation order byte - 16 bytes in all. ES - Segment of object. Returns: Carry clear - Success Carry set - Error AX - Error code. Changes the co-ordinates and rotation of a group. ;-------- Function 20h - Create Form Inputs: AH - 20h DS:SI - Pointer to form data: 3 co-ordinate words for center of form. Returns: Carry clear - Success AX - Segment of created form. Carry set - Error AX - Error code. Creates a new form. ;-------- Function 21h - Delete Form Inputs: AH - 21h DS - Segment of form. Returns: Carry clear - Success AX - Number of free cells. Carry set - Error AX - Error code. Deletes the form specified and frees the cell which contained it. It is unwise to delete a form which is still being used by any objects. In v0.1, anything could happen. Later versions will stop this from happening and hopefully have automatic heap verification and defragmentation. ;-------- Function 40h - Find Free cell Inputs: AH - 20h Returns: AX - Segment of first free cell. This function finds the first free cell on the heap. It does not allocate it or change the number of free cells; it merely searches through the heap for the first cell with a magic of 00h (free). ;*------- Function 80h - Render. Inputs: AH - 80h DS - Segment of universe. ES - Segment of display buffer (this may be 0A000h or any other 64k buffer which will be overlayed with a 320x200 bitmap). Returns: (none). Draws the whole scene in a 320x200x256 bitmap. It is usually desirable to draw the scren into a buffer or a hidden screen, then display it so that the user cannot see the polygons being drawn. This function clears the output buffer and then calls Function 88h for each group starting with the one furthest from the viewer. ;*------- Function 88h - Draw Group. Inputs: AH - 88h DS - Segment of group. ES - Output segment. Renders a group. Calls Function 8Ah for each shape in the group, starting from the one the furthest away from the viewer. ;*------- Function 8Ah - Draw Object. Inputs: AH - 8Ah DS - Segment of object. ES - Output segment. Renders a shape. Calls Function 8Ch for each shape in the object. ;*------- Function 8Ch - Draw Shape. Inputs: AH - 8Ch DS - Segment of shape. ES - Output segment. Renders a shape. Calls Function 8Eh for each face in the shape. ;*------- Function 8Eh - Draw Face. Inputs: AH - 8Eh DS - Segment of face. ES - Output segment. Renders a face. Decides whether the face is visible or not then draws the triangle if it is. ;*------- Function 90h - Line. Inputs: AH - 90h AL - Palette index. BX - Offset of start of line. CX - Width of line. DX - Height of line. ES - Segment of output bitmap. Draws a line from ES:[BX] to ES:[BX+CX+320*DX]. It does not do any boundary checking, so the line may wrap around on the screen. ;*------- Function 92h - Horizontal Line. Inputs: AH - 92h AL - Palette index. BX - Offset of start of line. CX - Width of line. ES - Segment of output bitmap. Draws a horizontal line form ES:[BX] to ES:[BX+CX]. ;-------- Function 94h - Triangle. Inputs: AH - 94h AL - Palette index. DS:SI - Pointer to 6 co-ordinate words. ES - Segment of output bitmap. Draws a filled triangle. Nearly always. ;*------- Function 96h - Shaded triangle. Inputs: AH - 96h AL BH BL - Palette indexes. DS:SI - Pointer to 6 co-ordinate words ES - Segment of output bitmap. | ;----------------------------- Constants ------------------------------------; ;-------- Errors. ERROR_HEAPOUT equ -1 ; Out of heap space error. ERROR_BADFACE equ -2 ; BADPARENT error used in place of these in ERROR_BADSHAPE equ -3 ; most circumstances. ERROR_BADFORM equ -4 ERROR_BADOBJECT equ -5 ERROR_BADGROUP equ -6 ERROR_BADUNIVERSE equ -7 ERROR_BADPARENT equ -8 ; The parent specified is not valid. ERROR_BADCHILD equ -9 ; The child structure specified is not valid. ERROR_TOOMANY equ -16 ; Too many child structures in a parent. ERROR_BADLIST equ -32 ; Linked list corrupt. ERROR_BADHEAP equ -33 ; Heap corrupt. ERROR_GPFAULT equ -64 ;-------- Offsets for renderer. INT3D_2D_X1 equ 0000h INT3D_2D_Y1 equ 0002h INT3D_2D_X2 equ 0004h INT3D_2D_Y2 equ 0006h INT3D_2D_X3 equ 0008h INT3D_2D_Y3 equ 000Ah INT3D_3D_X1 equ 0000h INT3D_3D_Y1 equ 0004h INT3D_3D_Z1 equ 0008h INT3D_3D_X2 equ 000Ch INT3D_3D_Y2 equ 0010h INT3D_3D_Z2 equ 0014h INT3D_3D_X3 equ 0018h INT3D_3D_Y3 equ 001Ch INT3D_3D_Z3 equ 0020h ;-------- Rotation Order constants. RORDER_XYZ equ 00000000b RORDER_XZY equ 00000100b RORDER_YXZ equ 00000001b RORDER_YZX equ 00000101b RORDER_ZXY equ 00000010b RORDER_ZYX equ 00000110b ;-------- Magics. MAGIC_FREE equ 00h MAGIC_FACE equ 'F' MAGIC_SHAPE equ 'S' MAGIC_FORM equ 'M' MAGIC_OBJECT equ 'O' MAGIC_GROUP equ 'G' MAGIC_UNIVERSE equ 'U' ;-------- Common offsets. ; Offsets which are common to all structures. These are used by the common ; create/delete routines. _MAGIC equ 0000h ; (B) Magic - indicates type of structure. _PARENT equ 0001h ; (W) Segment of parent structure. _NUM equ 0003h ; (B) Number of child structures. _PTR equ 0004h ; (W) Segment of first child in linked list. _PREV equ 0006h ; (W) Segment of previous structure in list. _NEXT equ 0008h ; (W) Segment of next structure in list. _SSDATA equ 000Ah ; (.) Start of structure-specific data. ; All structures take up 32 bytes (2 paragraphs) - one cell. ; Forms, faces and shapes are constant. They can be common for any objects ; which all have the same appearance. ;-------- Faces. F_MAGIC equ 0000h ; (B) Magic byte. F_PARENT equ 0001h ; (W) Segment of parent shape. F_SPARE00 equ 0003h ; (B) There are no child structures. F_SPARE01 equ 0004h ; (W) There are no child structures. F_PREV equ 0006h ; (W) Segment of previous face, or 0 if none. F_NEXT equ 0008h ; (W) Segment of next face, or 0 if none. F_DATA equ 000Ah ; (.) Start of face description data. F_X1 equ 000Ah ; (W) Co-ordinates of corners of face. F_Y1 equ 000Ch F_Z1 equ 000Eh F_X2 equ 0010h F_Y2 equ 0012h F_Z2 equ 0014h F_X3 equ 0016h F_Y3 equ 0018h F_Z3 equ 001Ah F_COL equ 001Ch ; (B) Colour of face (palette index). ;-------- Shapes. S_MAGIC equ 0000h ; (B) Magic byte. S_PARENT equ 0001h ; (W) Segment of parent form. S_NUM equ 0003h ; (B) Number of faces. S_PTR equ 0004h ; (W) Segment of first face in linked list. S_PREV equ 0006h ; (W) Segment of previous shape, or 0 if none. S_NEXT equ 0008h ; (W) Segment of next shape, or 0 if none. S_DATA equ 000Ah ; (.) Start of data - S_CX. S_CX equ 000Ah ; (W) Co-ordinates of center of shape. S_CY equ 000Ch S_CZ equ 000Eh ;-------- Forms. M_MAGIC equ 0000h ; (B) Magic byte. M_NUMOBJ equ 0001h ; (W) Number of objects which use this form. M_NUM equ 0003h ; (B) Number of shapes in form. M_PTR equ 0004h ; (W) Segment of first shape in linked list. M_PREV equ 0006h ; (W) Segment of previous form in list. M_NEXT equ 0008h ; (W) Segment of next form in linked list. M_SPARE01 equ 000Ah ; (W) M_SPARE02 equ 000Ch ; (W) M_DATA equ 000Eh ; (.) M_CX equ 000Eh ; (W) Co-ordinates center of form. M_CY equ 0010h M_CZ equ 0012h ; Objects and groups have to be created for every 3D object which exists in ; the 3DOMS arena. ;-------- Objects. O_MAGIC equ 0000h ; (B) Magic byte. O_PARENT equ 0001h ; (W) Segment of parent group. O_SPARE00 equ 0003h ; (B) O_PTR equ 0004h ; (W) Segment of form. O_PREV equ 0006h ; (W) Segment of previous object, or 0. O_NEXT equ 0008h ; (W) Segment of next object, or 0 if none. O_DATA equ 000Ah ; (.) O_CX equ 000Ah ; (W) Co-ordinates of center of object. O_CY equ 000Ch O_CZ equ 000Eh O_X equ 0010h ; (D) Transformations. O_Y equ 0014h O_Z equ 0018h O_RX equ 001Ch ; (B) Rotation about the axes. O_RY equ 001Dh O_RZ equ 001Eh O_RORDER equ 001Fh ; (B) Order of rotations. ;-------- Groups. G_MAGIC equ 0000h ; (B) Magic byte. G_PARENT equ 0001h ; (W) Segment of parent universe. G_NUM equ 0003h ; (B) Number of objects. G_PTR equ 0004h ; (W) Segment of first object in linked list. G_PREV equ 0006h ; (W) Segment of previous group, or 0. G_NEXT equ 0008h ; (W) Segment of next group, or 0 if none. G_DATA equ 000Ah ; (.) G_CX equ 000Ah ; (W) Co-ordinates of center of group. G_CY equ 000Ch G_CZ equ 000Eh G_X equ 0010h ; (D) Transformations. G_Y equ 0014h G_Z equ 0018h G_RX equ 001Ch ; (B) Rotation about the axes. G_RY equ 001Dh G_RZ equ 001Eh G_RORDER equ 001Fh ; (B) Order of rotations. ;-------- Universe. ; There is one universe - it is basicly a descriptor for the whole scene. I ; may incorporate the camera transformations and rotations into this ; structure. U_MAGIC equ 0000h ; (B) Magic byte. U_SPARE00 equ 0001h ; (W) U_NUM equ 0003h ; (B) Number of groups. U_PTR equ 0004h ; (W) Segment of first group in linked list. ;-------- Other constants. MAX_FACES equ 07Fh ; Maximum number of faces in a shape. MAX_SHAPES equ 07Fh ; Maximum number of shapes in a form. MAX_FORMS equ 07Fh ; Maximum number of forms. MAX_OBJECTS equ 07Fh ; Maximum number of objects in a group. MAX_GROUPS equ 07Fh ; Maximum number of groups. ;----------------------------- 3DOMS Data Area ------------------------------; ; Storage for old INT 3Dh vector. _3doms_int3Dseg dw 0000h _3doms_int3Doff dw 0000h ; Requested min and max size of heap on call to logon routine. _3doms_minheap dw 0000h _3doms_maxheap dw 0000h ; Heap descriptors. _3doms_heapseg dw 0000h ; Segment of allocated memory. _3doms_heapsize dw 0000h ; Size in 32-byte cells of heap. _3doms_heapfree dw 0000h ; Number of free 32-butes cells. ; Segment of universe. _3doms_universe dw 0000h ; Segment of null group. ; Global thing counters. _3doms_faces dw 0000h ; Total number of faces. _3doms_shapes dw 0000h ; Total number of shapes. _3doms_forms dw 0000h ; Number of forms. _3doms_objects dw 0000h ; Total number of objects. _3doms_groups dw 0000h ; Number of groups. ; Camera descriptors. _3doms_camera_x dd 0 ; Camera location. _3doms_camera_y dd 0 _3doms_camera_z dd 0 _3doms_camera_rx db 00h ; Camera rotations. _3doms_camera_ry db 00h _3doms_camera_rz db 00h _3doms_camera_rorder db 00h ; Camera rotation order. _3doms_camera_scr2eye dd 00008000h ; Screen to eye distance. _3doms_camera_scr2org dd 00008000h ; Screen to origin distance. ; View area descriptors. _3doms_view_xsize dw 320 ; Size of viewing window in buffer. _3doms_view_ysize dw 200 _3doms_view_vwidth dw 320 ; Width of virtual screen. _3doms_view_diff dw 0 ; Virtual width - view width. _3doms_view_offset dw 0000h ; Offset into buffer of view window. ;----------------------------- Lookup Tables --------------------------------; ; Sine and cosine table - 256 double word entries for each, but the tables ; overlap quite substantially. _3doms_sin dd 000000000h, 000000006h, 00000000Ch, 000000012h ; 0ø dd 000000019h, 00000001Fh, 000000025h, 00000002Bh dd 000000032h, 000000038h, 00000003Eh, 000000044h dd 00000004Ah, 000000050h, 000000056h, 00000005Ch dd 000000062h, 000000067h, 00000006Dh, 000000073h dd 000000078h, 00000007Eh, 000000083h, 000000089h dd 00000008Eh, 000000093h, 000000098h, 00000009Dh dd 0000000A2h, 0000000A7h, 0000000ACh, 0000000B0h dd 0000000B5h, 0000000B9h, 0000000BDh, 0000000C2h dd 0000000C6h, 0000000CAh, 0000000CDh, 0000000D1h dd 0000000D5h, 0000000D8h, 0000000DBh, 0000000DFh dd 0000000E2h, 0000000E4h, 0000000E7h, 0000000EAh dd 0000000ECh, 0000000EFh, 0000000F1h, 0000000F3h dd 0000000F5h, 0000000F7h, 0000000F8h, 0000000FAh dd 0000000FBh, 0000000FCh, 0000000FDh, 0000000FEh dd 0000000FFh, 0000000FFh, 0000000FFh, 000000100h _3doms_cos dd 000000100h, 000000100h, 0000000FFh, 0000000FFh ; 90ø dd 0000000FFh, 0000000FEh, 0000000FDh, 0000000FCh dd 0000000FBh, 0000000FAh, 0000000F8h, 0000000F7h dd 0000000F5h, 0000000F3h, 0000000F1h, 0000000EFh dd 0000000ECh, 0000000EAh, 0000000E7h, 0000000E4h dd 0000000E2h, 0000000DFh, 0000000DBh, 0000000D8h dd 0000000D5h, 0000000D1h, 0000000CDh, 0000000CAh dd 0000000C6h, 0000000C2h, 0000000BDh, 0000000B9h dd 0000000B5h, 0000000B0h, 0000000ACh, 0000000A7h dd 0000000A2h, 00000009Dh, 000000098h, 000000093h dd 00000008Eh, 000000089h, 000000083h, 00000007Eh dd 000000078h, 000000073h, 00000006Dh, 000000067h dd 000000062h, 00000005Ch, 000000056h, 000000050h dd 00000004Ah, 000000044h, 00000003Eh, 000000038h dd 000000032h, 00000002Bh, 000000025h, 00000001Fh dd 000000019h, 000000012h, 00000000Ch, 000000006h dd 000000000h, 0FFFFFFFAh, 0FFFFFFF4h, 0FFFFFFEEh ; 180ø dd 0FFFFFFE7h, 0FFFFFFE1h, 0FFFFFFDBh, 0FFFFFFD5h dd 0FFFFFFCEh, 0FFFFFFC8h, 0FFFFFFC2h, 0FFFFFFBCh dd 0FFFFFFB6h, 0FFFFFFB0h, 0FFFFFFAAh, 0FFFFFFA4h dd 0FFFFFF9Eh, 0FFFFFF99h, 0FFFFFF93h, 0FFFFFF8Dh dd 0FFFFFF88h, 0FFFFFF82h, 0FFFFFF7Dh, 0FFFFFF77h dd 0FFFFFF72h, 0FFFFFF6Dh, 0FFFFFF68h, 0FFFFFF63h dd 0FFFFFF5Eh, 0FFFFFF59h, 0FFFFFF54h, 0FFFFFF50h dd 0FFFFFF4Bh, 0FFFFFF47h, 0FFFFFF43h, 0FFFFFF3Eh dd 0FFFFFF3Ah, 0FFFFFF36h, 0FFFFFF33h, 0FFFFFF2Fh dd 0FFFFFF2Bh, 0FFFFFF28h, 0FFFFFF25h, 0FFFFFF21h dd 0FFFFFF1Eh, 0FFFFFF1Ch, 0FFFFFF19h, 0FFFFFF16h dd 0FFFFFF14h, 0FFFFFF11h, 0FFFFFF0Fh, 0FFFFFF0Dh dd 0FFFFFF0Bh, 0FFFFFF09h, 0FFFFFF08h, 0FFFFFF06h dd 0FFFFFF05h, 0FFFFFF04h, 0FFFFFF03h, 0FFFFFF02h dd 0FFFFFF01h, 0FFFFFF01h, 0FFFFFF01h, 0FFFFFF00h dd 0FFFFFF00h, 0FFFFFF00h, 0FFFFFF01h, 0FFFFFF01h ; 270ø dd 0FFFFFF01h, 0FFFFFF02h, 0FFFFFF03h, 0FFFFFF04h dd 0FFFFFF05h, 0FFFFFF06h, 0FFFFFF08h, 0FFFFFF09h dd 0FFFFFF0Bh, 0FFFFFF0Dh, 0FFFFFF0Fh, 0FFFFFF11h dd 0FFFFFF14h, 0FFFFFF16h, 0FFFFFF19h, 0FFFFFF1Ch dd 0FFFFFF1Eh, 0FFFFFF21h, 0FFFFFF25h, 0FFFFFF28h dd 0FFFFFF2Bh, 0FFFFFF2Fh, 0FFFFFF33h, 0FFFFFF36h dd 0FFFFFF3Ah, 0FFFFFF3Eh, 0FFFFFF43h, 0FFFFFF47h dd 0FFFFFF4Bh, 0FFFFFF50h, 0FFFFFF54h, 0FFFFFF59h dd 0FFFFFF5Eh, 0FFFFFF63h, 0FFFFFF68h, 0FFFFFF6Dh dd 0FFFFFF72h, 0FFFFFF77h, 0FFFFFF7Dh, 0FFFFFF82h dd 0FFFFFF88h, 0FFFFFF8Dh, 0FFFFFF93h, 0FFFFFF99h dd 0FFFFFF9Eh, 0FFFFFFA4h, 0FFFFFFAAh, 0FFFFFFB0h dd 0FFFFFFB6h, 0FFFFFFBCh, 0FFFFFFC2h, 0FFFFFFC8h dd 0FFFFFFCEh, 0FFFFFFD5h, 0FFFFFFDBh, 0FFFFFFE1h dd 0FFFFFFE7h, 0FFFFFFEEh, 0FFFFFFF4h, 0FFFFFFFAh dd 000000000h, 000000006h, 00000000Ch, 000000012h ; 360ø dd 000000019h, 00000001Fh, 000000025h, 00000002Bh dd 000000032h, 000000038h, 00000003Eh, 000000044h dd 00000004Ah, 000000050h, 000000056h, 00000005Ch dd 000000062h, 000000067h, 00000006Dh, 000000073h dd 000000078h, 00000007Eh, 000000083h, 000000089h dd 00000008Eh, 000000093h, 000000098h, 00000009Dh dd 0000000A2h, 0000000A7h, 0000000ACh, 0000000B0h dd 0000000B5h, 0000000B9h, 0000000BDh, 0000000C2h dd 0000000C6h, 0000000CAh, 0000000CDh, 0000000D1h dd 0000000D5h, 0000000D8h, 0000000DBh, 0000000DFh dd 0000000E2h, 0000000E4h, 0000000E7h, 0000000EAh dd 0000000ECh, 0000000EFh, 0000000F1h, 0000000F3h dd 0000000F5h, 0000000F7h, 0000000F8h, 0000000FAh dd 0000000FBh, 0000000FCh, 0000000FDh, 0000000FEh dd 0000000FFh, 0000000FFh, 0000000FFh, 000000100h ;----------------------------- Initialisation Code --------------------------; ;-------- Logon_3DOMS ; Sets up interrupt vector and stack and initialises variables. ; Inputs: ; BX - Min cells to allocate. ; DX - Max cells to allocate. ; Returns: ; Carry clear: ; AX - Segment of heap. ; CX - Size of heap in cells. ; Carry set: ; AX - Error code. logon_3doms: push bx push cx push dx push ds push es ; Allocate memory. ; Save parameters. mov _3doms_minheap, bx mov _3doms_maxheap, dx ; First try the maximum size requested. mov ah, 48h mov bx, dx shl bx, 1 int 21h ; Was that allocation successful? jnc logon_3doms_memok ; If not that much memory free, see if the minimum can be allocated. shr bx, 1 cmp bx, _3doms_minheap jl logon_3doms_nomem ; Allocate all that can be allocated. mov ah, 48h shl bx, 1 int 21h jnc logon_3doms_memok logon_3doms_nomem: ; There is not enough memory to satisfy the minimum memory requirements. stc mov ax, ERROR_HEAPOUT pop es pop ds pop dx pop cx mov cx, bx shr cx, 1 pop bx ret logon_3doms_memok: mov _3doms_heapseg, ax shr bx, 1 mov _3doms_heapsize, bx mov _3doms_heapfree, bx ; Change interrupt. ; Get old interrupt vector. mov ax, 353Dh int 21h mov _3doms_int3Dseg, es mov _3doms_int3Doff, bx ; Set interrupt vector. mov ax, 253Dh push cs pop ds mov dx, offset int3D_intvect int 21h ; Set all cells on heap to free. mov ax, _3doms_heapseg mov cx, _3doms_heapsize logon_3doms_freeheap: mov ds, ax mov byte ptr ds: [_MAGIC], MAGIC_FREE add ax, 2 loop logon_3doms_freeheap ; Set up universe structure. mov ah, 40h int 3Dh mov ds, ax dec _3doms_heapfree mov byte ptr ds: [U_MAGIC], MAGIC_UNIVERSE mov byte ptr ds: [U_NUM], 0 mov word ptr ds: [U_PTR], 0000h mov _3doms_universe, ax pop es pop ds pop dx pop cx pop bx mov ax, _3doms_heapseg mov cx, _3doms_heapsize ret ;-------- Logoff_3DOMS ; Restores interrupt vector. logoff_3doms: push ax push dx push ds push es ; Free allocated memory. mov ah, 49h mov es, _3doms_heapseg int 21h ; Reset interrupt vector. mov ax, 253Dh mov dx, _3doms_int3Doff mov ds, _3doms_int3Dseg int 21h pop es pop ds pop dx pop ax ret ;----------------------------- The 3DOMS Interrupt --------------------------; ; 3DOMS Identifier - look for to see if 3DOMS TSR loaded. db '3DOMSv', 00h, 10h ; Bootstrap for the 3DOMS interrupt handler. int3D_intvect: ; Branch to the required function. cmp ah, 00h je int3D_info_ cmp ah, 10h je int3D_newface_ cmp ah, 11h je int3D_delface_ cmp ah, 14h je int3D_newshape_ cmp ah, 15h je int3D_delshape_ cmp ah, 18h je int3D_newobject_ cmp ah, 19h je int3D_delobject_ cmp ah, 1Ah je int3D_moveobject_ cmp ah, 1Bh je int3D_formobject_ cmp ah, 1Ch je int3D_newgroup_ cmp ah, 1Dh je int3D_delgroup_ cmp ah, 1Eh je int3D_movegroup_ cmp ah, 20h je int3D_newform_ cmp ah, 21h je int3D_delform_ cmp ah, 40h je int3D_findfree_ cmp ah, 80h je int3D_render_ cmp ah, 88h je int3D_drawgroup_ cmp ah, 8Ah je int3D_drawobject_ cmp ah, 8Ch je int3D_drawshape_ cmp ah, 8Eh je int3D_drawface_ cmp ah, 94h je int3D_triangle_ ; Set carry flag on stack and IRET. int3D_error: pop word ptr cs: [_int3D_calloff] pop word ptr cs: [_int3D_callseg] pop word ptr cs: [_int3D_callflag] or word ptr cs: [_int3D_callflag], 0001h push word ptr cs: [_int3D_callflag] push word ptr cs: [_int3D_callseg] push word ptr cs: [_int3D_calloff] iret ; Clear carry flag on stack and IRET. int3D_end: pop word ptr cs: [_int3D_calloff] pop word ptr cs: [_int3D_callseg] pop word ptr cs: [_int3D_callflag] and word ptr cs: [_int3D_callflag], 0FFFEh push word ptr cs: [_int3D_callflag] push word ptr cs: [_int3D_callseg] push word ptr cs: [_int3D_calloff] iret _int3D_callseg dw 0000h _int3D_calloff dw 0000h _int3D_callflag dw 0000h ;-------- Function branches. int3D_info_: jmp int3D_info int3D_newface_: jmp int3D_newface int3D_delface_: jmp int3D_delface int3D_newshape_: jmp int3D_newshape int3D_delshape_: jmp int3D_delshape int3D_newobject_: jmp int3D_newobject int3D_delobject_: jmp int3D_delobject int3D_moveobject_: jmp int3D_moveobject int3D_formobject_: jmp int3D_formobject int3D_newgroup_: jmp int3D_newgroup int3D_delgroup_: jmp int3D_delgroup int3D_movegroup_: jmp int3D_movegroup int3D_newform_: jmp int3D_newform int3D_delform_: jmp int3D_delform int3D_findfree_: jmp int3D_findfree int3D_render_: jmp int3D_render int3D_drawgroup_: jmp int3D_drawgroup int3D_drawobject_: jmp int3D_drawobject int3D_drawshape_: jmp int3D_drawshape int3D_drawface_: jmp int3D_drawface int3D_triangle_: jmp int3D_triangle ;----------------------------- The 3DOMS Functions --------------------------; ;-------- Function 00h - Info. ; Inputs: ; AH - 00h ; Returns: ; AH - Major version number. ; AL - Minor version number. ; BX - Segment of heap. ; CX - Size of heap in 32-byte cells. ; DX - Number of free 32-byte cells in heap. int3D_info: mov ax, 0010h ; Version 0.1 (00.10). mov bx, _3doms_heapseg mov cx, _3doms_heapsize mov dx, _3doms_heapfree jmp int3D_end ;----------------------------- Structure Management -------------------------; ;-------- Function 10h - Create Face. ; Inputs: ; AH - 10h ; DS:SI - Face data. ; ES - Parent shape. ; Returns: ; Carry clear: ; AX - Segment of face. ; Carry set: ; AX - Error code. int3D_newface: push bx push cx ; Create face. mov ah, MAGIC_SHAPE mov al, MAGIC_FACE mov bl, MAX_FACES mov cx, 10 call int3D_create pop cx pop bx ; Exit if error. jnc int3D_newface_ok jmp int3D_error int3D_newface_ok: inc _3doms_faces jmp int3D_end ;-------- Function 11h - Delete a face. ; Inputs: ; AH - 11h ; ES - Segment of face. ; Returns: ; Carry clear: ; AX - Segment of parent. ; Carry set: ; AX - Error code. int3D_delface: ; Delete face. mov ah, MAGIC_SHAPE mov al, MAGIC_FACE call int3D_delete ; Exit if error. jnc int3D_delface_ok jmp int3D_error int3D_delface_ok: dec _3doms_faces jmp int3D_end ;-------- Function 14h - Create a shape. ; Inputs: ; AH - 14h ; DS:SI - Shape data. ; ES - Parent form. ; Returns: ; Carry clear: ; AX - Segment of shape. ; Carry set: ; AX - Error code. int3D_newshape: push bx push cx ; Create shape. mov ah, MAGIC_FORM mov al, MAGIC_SHAPE mov bl, MAX_SHAPES mov cx, 3 call int3D_create pop cx pop bx ; Exit if error. jnc int3D_newshape_ok jmp int3D_error int3D_newshape_ok: inc _3doms_shapes jmp int3D_end ;-------- Function 15h - Delete a shape. ; Inputs: ; AH - 15h ; ES - Segment of shape. ; Returns: ; Carry clear: ; AX - Segment of parent form. ; Carry set: ; AX - Error code. int3D_delshape: ; Delete shape. mov ah, MAGIC_FORM mov al, MAGIC_SHAPE call int3D_delete ; Exit if error. jnc int3D_delshape_ok jmp int3D_error int3D_delshape_ok: dec _3doms_shapes jmp int3D_end ;-------- Function 18h - Create an object. ; Inputs: ; AH - 18h ; DS:SI - object data. ; ES - Parent group. ; Returns: ; Carry clear: ; AX - Segment of object. ; Carry set: ; AX - Error code. int3D_newobject: push bx push cx ; Create object. mov ah, MAGIC_GROUP mov al, MAGIC_OBJECT mov bl, MAX_OBJECTS mov cx, 11 call int3D_create pop cx pop bx ; Exit if error. jnc int3D_newobject_ok jmp int3D_error int3D_newobject_ok: inc _3doms_objects jmp int3D_end ;-------- Function 19h - Delete an object. ; Inputs: ; AH - 19h ; ES - Segment of object. ; Returns: ; Carry clear: ; AX - Segment of parent group. ; Carry set: ; AX - Error code. int3D_delobject: ; Delete object. mov ah, MAGIC_GROUP mov al, MAGIC_OBJECT call int3D_delete ; Exit if error. jnc int3D_delobject_ok jmp int3D_error int3D_delobject_ok: dec _3doms_objects jmp int3D_end ;-------- Function 1Ah - Move an object. ; Inputs: ; AH - 1Ah ; DS:SI - Object data. ; ES - Object. ; Returns: ; Carry set: ; AX - Error code. int3D_moveobject: ; Make sure object is valid. cmp byte ptr es: [O_MAGIC], MAGIC_OBJECT je int3D_moveobject_objectok mov ax, ERROR_BADOBJECT jmp int3D_error int3D_moveobject_objectok: push si push di push cx ; Copy object parameters. mov si, bx mov di, O_DATA mov cx, 11 rep movsw pop cx pop di pop si jmp int3D_end ;-------- Function 1Bh - Change the form of an object. ; Inputs: ; AH - 1Bh ; BX - New form (or 0000h to just get old form). ; ES - Object. ; Returns: ; Carry clear: ; AX - Old form. ; Carry set: ; AX - Error code. int3D_formobject: ; Make sure object is valid. cmp byte ptr es: [O_MAGIC], MAGIC_OBJECT je int3D_formobject_objectok mov ax, ERROR_BADOBJECT jmp int3D_error int3D_formobject_objectok: ; Get old form. mov ax, es: [O_PTR] ; Only change form if BX is not 0. cmp bx, 0 je int3D_formobject_end ; Check new form is valid. push ds mov ds, bx cmp byte ptr ds: [M_MAGIC], MAGIC_FORM je int3D_formobject_formok ; Return with error code. pop ds mov ax, ERROR_BADFORM jmp int3D_error int3D_formobject_formok: mov es: [O_PTR], bx pop ds int3D_formobject_end: jmp int3D_end ;-------- Function 1Ch - Create a group. ; Inputs: ; AH - 1Ch ; DS:SI - group data. ; ES - Parent universe. ; Returns: ; Carry clear: ; AX - Segment of group. ; Carry set: ; AX - Error code. int3D_newgroup: push bx push cx ; Create group. mov ah, MAGIC_UNIVERSE mov al, MAGIC_GROUP mov bl, MAX_GROUPS mov cx, 11 call int3D_create pop cx pop bx ; Exit if error. jnc int3D_newgroup_ok jmp int3D_error int3D_newgroup_ok: inc _3doms_groups jmp int3D_end ;-------- Function 1Dh - Delete a group. ; Inputs: ; AH - 1Dh ; ES - Segment of group. ; Returns: ; Carry clear: ; AX - Number of free cells. ; Carry set: ; AX - Error code. int3D_delgroup: ; Delete group. mov ah, MAGIC_UNIVERSE mov al, MAGIC_GROUP call int3D_delete ; Exit if error. jnc int3D_delgroup_ok jmp int3D_error int3D_delgroup_ok: dec _3doms_groups jmp int3D_end ;-------- Function 1Eh - Move a group. ; Inputs: ; AH - 1Eh ; DS:SI - Group data. ; ES - Group. ; Returns: ; Carry set: ; AX - Error code. int3D_movegroup: ; Make sure object is valid. cmp byte ptr es: [G_MAGIC], MAGIC_GROUP je int3D_movegroup_groupok mov ax, ERROR_BADGROUP jmp int3D_error int3D_movegroup_groupok: push si push di push cx ; Copy group parameters. mov si, bx mov di, G_DATA mov cx, 11 rep movsw pop cx pop di pop si jmp int3D_end ;-------- Function 20h - Create a form. ; Inputs: ; AH - 20h ; DS:SI - form data. ; Returns: ; Carry clear: ; AX - Segment of form. ; Carry set: ; AX - Error code. int3D_newform: ; Find first free cell. mov ah, 40h int 3Dh jnc int3D_newform_memok mov ax, ERROR_HEAPOUT jmp int3D_error int3D_newform_memok: ; Create form. push es mov es, ax mov byte ptr es: [M_MAGIC], MAGIC_FORM mov byte ptr es: [M_NUM], 0 ; Copy form parameters. int3D_newform_copy: push si push di mov si, bx mov di, M_DATA push cx mov cx, 3 rep movsw pop cx pop di pop si pop es ; Change counters. inc _3doms_forms dec _3doms_heapfree jmp int3D_end ;-------- Function 21h - Delete a form. ; Inputs: ; AH - 21h ; ES - Segment of form. ; Returns: ; Carry clear: ; AX - Number of free cells. ; Carry set: ; AX - Error code. int3D_delform: ; Check if form is valid. cmp byte ptr ds: [M_MAGIC], MAGIC_FORM je int3D_delform_formok mov ax, ERROR_BADFORM jmp int3D_error int3D_delform_formok: ; Free the cell occupied by the form. mov byte ptr ds: [M_MAGIC], MAGIC_FREE ; Change counters. dec _3doms_forms inc _3doms_heapfree jmp int3D_end ;----------------------------- Structure Routines ---------------------------; ;-------- Routine: Create child structure. ; Inputs: ; AH - Magic of parent. ; AL - Magic of child. ; BL - Max number of child structures for parent. ; CX - Number of words of data pointed to by DS:SI. ; DS:SI - Structure dependant data. ; ES - Parent. ; Returns: ; Carry clear: ; AX - Segment of new structure. ; Carry set: ; AX - Error code. _int3D_create_magics dw 0000h _int3D_create_child dw 0000h int3D_create: mov _int3D_create_magics, ax ; Make sure parent structure is valid. cmp byte ptr es: [_MAGIC], ah je int3D_create_parentok mov ax, ERROR_BADPARENT stc ret int3D_create_parentok: ; Make sure not too many structures in parent. cmp es: [_NUM], bl jl int3D_create_numok mov ax, ERROR_TOOMANY stc ret int3D_create_numok: ; Find first free cell. mov ah, 40h int 3Dh jnc int3D_create_memok mov ax, ERROR_HEAPOUT stc ret int3D_create_memok: mov _int3D_create_child, ax push dx push es ; If there are no child structures in the parent then create a new ; linked list. cmp byte ptr es: [_NUM], 0 jne int3D_create_listok mov es: [_PTR], ax xor dx, dx jmp int3D_create_next ; Otherwise insert child into linked list before the first child and ; change pointer in parent. int3D_create_listok: mov dx, es: [_PTR] mov es: [_PTR], ax mov es, dx mov es: [_PREV], ax int3D_create_next: ; Do bits which are common to first and any other child structures. mov es, ax mov ax, _int3D_create_magics mov es: [_MAGIC], al mov byte ptr es: [_NUM], 00h mov es: [_NEXT], dx mov word ptr es: [_PREV], 0000h pop ax push ax mov es: [_PARENT], ax push cx push si push di ; Copy structure-dependant data. mov di, _SSDATA rep movsw pop di pop si pop cx pop es pop dx ; Change counters. inc byte ptr es: [_NUM] inc _3doms_objects dec _3doms_heapfree mov ax, _int3D_create_child clc ret ;-------- Routine: Delete structure. ; Inputs: ; AH - Magic of parent. ; AL - Magic of child. ; ES - Child structure to delete. ; Returns: ; Carry clear: ; AX - Segment of new structure. ; Carry set: ; AX - Error code. _int3D_delete_magics dw 0000h _int3D_delete_child dw 0000h int3D_delete: mov _int3D_delete_magics, ax ; Make sure child structure is valid. cmp byte ptr es: [_MAGIC], al je int3D_delete_childok mov ax, ERROR_BADCHILD stc ret int3D_delete_childok: push ds ; Check if parent is valid. Note that this only checks that the parent ; pointer points to a parent, not whether it is the correct one - it ; doesn't stop you removing a child from the wrong parent! mov ds, es: [_PARENT] cmp ds: [_MAGIC], ah je int3D_delete_parentok mov ax, ERROR_BADPARENT pop ds clc ret int3D_delete_parentok: push bx push dx ; Get segments of previous and next child structures. mov bx, es: [_PREV] mov dx, es: [_NEXT] ; Check both point to child structures unless they are null. ; Check previous child. cmp bx, 0000h je int3D_delete_prevok mov ds, bx cmp ds: [_MAGIC], al je int3D_delete_prevok ; This is an illegal child, so exit with error code. mov ax, ERROR_BADLIST pop dx pop bx pop ds stc ret int3D_delete_prevok: ; Check next child. cmp dx, 0000h je int3D_delete_nextok mov ds, dx cmp ds: [_MAGIC], al je int3D_delete_nextok ; This is an illegal shape, so exit with error code. mov ax, ERROR_BADLIST pop dx pop bx pop ds stc ret int3D_delete_nextok: ; Remove child from linked list. ; Put segment of next child in previous unless this is the first child. cmp bx, 0000h je int3D_delete_first mov ds, bx mov ds: [_NEXT], dx jmp int3D_delete_notfirst int3D_delete_first: ; This was the first child, so change pointer in parent structure. mov ds, es: [_PARENT] mov ds: [_PTR], dx int3D_delete_notfirst: ; Put segment of previous child in next unless this is the last child. cmp dx, 0000h je int3D_delete_last mov ds, dx mov ds: [_PREV], bx int3D_delete_last: mov ax, es: [_PARENT] ; Free the cell occupied by the child. mov byte ptr es: [_MAGIC], MAGIC_FREE ; Change counters. mov ds, ax dec byte ptr ds: [_NUM] inc _3doms_heapfree pop dx pop bx pop ds clc ret ;----------------------------- Heap Management ------------------------------; ;-------- Function 40h - Find first free cell. ; Inputs: ; AH - 40h ; Returns: ; Carry clear: ; AX - Segment of first free cell. ; Carry set: ; AX - Undefined (first segment after heap). int3D_findfree: push ds push cx mov ds, _3doms_heapseg mov cx, _3doms_heapsize int3D_findfree_loop: ; Is this cell free? cmp byte ptr ds: [0], 00h je int3D_findfirst_found ; If not, move on to next cell mov ax, ds add ax, 2 mov ds, ax loop int3D_findfree_loop ; Return an error if the end of the heap is reached before a free cell ; is found. pop cx pop ds jmp int3D_error ; If a free cell has been found, put it's segment in AX and return. int3D_findfirst_found: mov ax, ds pop cx pop ds ; TEMPORARY - Fill cell with 0FFh's (apart from magic). push es push di push cx push ax cld mov es, ax mov di, 1 mov al, 0FFh mov cx, 31 rep stosb pop ax pop cx pop di pop es jmp int3D_end ;----------------------------- Rendering Functions --------------------------; ;-------- Function 80h - Render. ; Inputs: ; AH - 80h ; DS - Segment of universe. ; ES - Output Segment. ; Returns: ; Carry clear: ; AX - Undefined. ; Carry set: ; AX - Error. ; BX - Segment of erroneous structure. int3D_render: ; Check universe magic. cmp byte ptr ds: [U_MAGIC], MAGIC_UNIVERSE je int3D_render_universeok mov ax, ERROR_BADUNIVERSE jmp int3D_error int3D_render_universeok: push cx push ds ; Go through groups, calling Function 88h for each - don't worry about ; order yet. xor ch, ch mov cl, ds: [U_NUM] mov ds, ds: [U_PTR] jcxz int3D_render_end int3D_render_loop: mov ah, 88h int 3Dh jnc int3D_render_groupok pop bx pop cx jmp int3D_error int3D_render_groupok: mov ds, ds: [G_NEXT] loop int3D_render_loop int3D_render_end: pop ds pop cx jmp int3D_end ;-------- Function 88h - Draw group. ; Inputs: ; AH - 88h ; DS - Segment of group. ; ES - Output Segment. ; Returns: ; Carry clear: ; AX - Undefined. ; Carry set: ; AX - Error. ; BX - Segment of erroneous structure. int3D_drawgroup: ; Check group magic. cmp byte ptr ds: [G_MAGIC], MAGIC_GROUP je int3D_drawgroup_groupok mov ax, ERROR_BADGROUP jmp int3D_error int3D_drawgroup_groupok: push cx push ds ; Go through objects, calling Function 8Ah for each - don't worry about ; order yet. xor ch, ch mov cl, ds: [G_NUM] mov ds, ds: [G_PTR] jcxz int3D_drawgroup_end int3D_drawgroup_loop: mov ah, 8Ah int 3Dh jnc int3D_drawgroup_objectok pop bx pop cx jmp int3D_error int3D_drawgroup_objectok: mov ds, ds: [O_NEXT] loop int3D_drawgroup_loop int3D_drawgroup_end: pop ds pop cx jmp int3D_end ;-------- Function 8Ah - Draw object. ; Inputs: ; AH - 8Ah ; DS - Segment of object. ; ES - Output Segment. ; Returns: ; Carry clear: ; AX - Undefined. ; Carry set: ; AX - Error. ; BX - Segment of erroneous structure. int3D_drawobject: ; Check object magic. cmp byte ptr ds: [O_MAGIC], MAGIC_OBJECT je int3D_drawobject_objectok mov ax, ERROR_BADOBJECT jmp int3D_error int3D_drawobject_objectok: push bx push cx push ds mov bx, ds mov ds, ds: [O_PTR] ; Check form magic. cmp byte ptr ds: [F_MAGIC], MAGIC_FORM je int3D_drawobject_formok pop ds pop cx pop bx mov ax, ERROR_BADFORM jmp int3D_error int3D_drawobject_formok: ; Go through shapes, calling Function 8Ch for each - don't worry about ; order yet. xor ch, ch mov cl, ds: [M_NUM] mov ds, ds: [M_PTR] jcxz int3D_drawobject_end int3D_drawobject_loop: mov ah, 8Ch int 3Dh jnc int3D_drawobject_shapeok pop bx pop cx add sp, 2 jmp int3D_error int3D_drawobject_shapeok: mov ds, ds: [S_NEXT] loop int3D_drawobject_loop int3D_drawobject_end: pop ds pop cx pop bx jmp int3D_end ;-------- Function 8Ch - Draw shape. ; Inputs: ; AH - 8Ch ; BX - Sement of parent object. ; DS - Segment of shape. ; ES - Output Segment. ; Returns: ; Carry clear: ; AX - Undefined. ; Carry set: ; AX - Error. ; BX - Segment of erroneous structure. int3D_drawshape: ; Check shape magic. cmp byte ptr ds: [S_MAGIC], MAGIC_SHAPE je int3D_drawshape_shapeok mov ax, ERROR_BADSHAPE jmp int3D_error int3D_drawshape_shapeok: push cx push ds ; Go through faces, calling Function 8Eh for each. xor ch, ch mov cl, ds: [S_NUM] mov ds, ds: [S_PTR] jcxz int3D_drawshape_end int3D_drawshape_loop: mov ah, 8Eh int 3Dh jnc int3D_drawshape_faceok pop bx pop cx jmp int3D_error int3D_drawshape_faceok: mov ds, ds: [F_NEXT] loop int3D_drawshape_loop int3D_drawshape_end: pop ds pop cx jmp int3D_end ;-------- Function 8Eh - Draw face. ; Inputs: ; AH - 8Eh ; BX - Sement of parent object. ; DS - Segment of face. ; ES - Output Segment. ; Returns: ; Carry clear: ; AX - Undefined. ; Carry set: ; AX - Error. _int3D_drawface_xyz dd 9 dup (0000h) _int3D_drawface_scrxy dw 6 dup (0000h) int3D_drawface: push bx push ecx push edx push si push ds ; Calculate spacial co-ordinates of face after rotations. ; Copy co-ordinates into work area. mov ax, ds: [F_X1] cwde mov _int3D_drawface_xyz[INT3D_3D_X1], eax mov ax, ds: [F_Y1] cwde mov _int3D_drawface_xyz[INT3D_3D_Y1], eax mov ax, ds: [F_Z1] cwde mov _int3D_drawface_xyz[INT3D_3D_Z1], eax mov ax, ds: [F_X2] cwde mov _int3D_drawface_xyz[INT3D_3D_X2], eax mov ax, ds: [F_Y2] cwde mov _int3D_drawface_xyz[INT3D_3D_Y2], eax mov ax, ds: [F_Z2] cwde mov _int3D_drawface_xyz[INT3D_3D_Z2], eax mov ax, ds: [F_X3] cwde mov _int3D_drawface_xyz[INT3D_3D_X3], eax mov ax, ds: [F_Y3] cwde mov _int3D_drawface_xyz[INT3D_3D_Y3], eax mov ax, ds: [F_Z3] cwde mov _int3D_drawface_xyz[INT3D_3D_Z3], eax ; Do object rotation. mov ds, bx mov bx, O_RX mov si, offset _int3D_drawface_xyz call int3D_rotate add si, 12 call int3D_rotate add si, 12 call int3D_rotate ; Do object transformations. mov eax, ds: [O_X] add _int3D_drawface_xyz[INT3D_3D_X1], eax add _int3D_drawface_xyz[INT3D_3D_X2], eax add _int3D_drawface_xyz[INT3D_3D_X3], eax mov eax, ds: [O_Y] add _int3D_drawface_xyz[INT3D_3D_Y1], eax add _int3D_drawface_xyz[INT3D_3D_Y2], eax add _int3D_drawface_xyz[INT3D_3D_Y3], eax mov eax, ds: [O_Z] add _int3D_drawface_xyz[INT3D_3D_Z1], eax add _int3D_drawface_xyz[INT3D_3D_Z2], eax add _int3D_drawface_xyz[INT3D_3D_Z3], eax ; Do group rotation. mov ds, ds: [O_PARENT] mov bx, G_RX mov si, offset _int3D_drawface_xyz call int3D_rotate add si, 12 call int3D_rotate add si, 12 call int3D_rotate ; Do group transformations. mov eax, ds: [G_X] add _int3D_drawface_xyz[INT3D_3D_X1], eax add _int3D_drawface_xyz[INT3D_3D_X2], eax add _int3D_drawface_xyz[INT3D_3D_X3], eax mov eax, ds: [G_Y] add _int3D_drawface_xyz[INT3D_3D_Y1], eax add _int3D_drawface_xyz[INT3D_3D_Y2], eax add _int3D_drawface_xyz[INT3D_3D_Y3], eax mov eax, ds: [G_Z] add _int3D_drawface_xyz[INT3D_3D_Z1], eax add _int3D_drawface_xyz[INT3D_3D_Z2], eax add _int3D_drawface_xyz[INT3D_3D_Z3], eax ; Calculate screen co-ordinates. ; SX1 = (scr2eye*X1) / (scr2eye+scr2org+Z1). mov eax, dword ptr _int3D_drawface_xyz[INT3D_3D_X1] imul dword ptr _3doms_camera_scr2eye mov ecx, _3doms_camera_scr2eye add ecx, _3doms_camera_scr2org add ecx, _int3D_drawface_xyz[INT3D_3D_Z1] idiv ecx shr eax, 8 add ax, 159 mov _int3D_drawface_scrxy[INT3D_2D_X1], ax ; SY1 = (scr2eye*Y1) / (scr2eye+scr2org+Z1). mov eax, dword ptr _int3D_drawface_xyz[INT3D_3D_Y1] imul dword ptr _3doms_camera_scr2eye mov ecx, _3doms_camera_scr2eye add ecx, _3doms_camera_scr2org add ecx, _int3D_drawface_xyz[INT3D_3D_Z1] idiv ecx shr eax, 8 add ax, 99 mov _int3D_drawface_scrxy[INT3D_2D_Y1], ax ; SX2 = (scr2eye*X2) / (scr2eye+scr2org+Z2). mov eax, dword ptr _int3D_drawface_xyz[INT3D_3D_X2] imul dword ptr _3doms_camera_scr2eye mov ecx, _3doms_camera_scr2eye add ecx, _3doms_camera_scr2org add ecx, _int3D_drawface_xyz[INT3D_3D_Z2] idiv ecx shr eax, 8 add ax, 159 mov _int3D_drawface_scrxy[INT3D_2D_X2], ax ; SY2 = (scr2eye*Y2) / (scr2eye+scr2org+Z2). mov eax, dword ptr _int3D_drawface_xyz[INT3D_3D_Y2] imul dword ptr _3doms_camera_scr2eye mov ecx, _3doms_camera_scr2eye add ecx, _3doms_camera_scr2org add ecx, _int3D_drawface_xyz[INT3D_3D_Z2] idiv ecx shr eax, 8 add ax, 99 mov _int3D_drawface_scrxy[INT3D_2D_Y2], ax ; SX3 = (scr2eye*X3) / (scr2eye+scr2org+Z3). mov eax, dword ptr _int3D_drawface_xyz[INT3D_3D_X3] imul dword ptr _3doms_camera_scr2eye mov ecx, _3doms_camera_scr2eye add ecx, _3doms_camera_scr2org add ecx, _int3D_drawface_xyz[INT3D_3D_Z3] idiv ecx shr eax, 8 add ax, 159 mov _int3D_drawface_scrxy[INT3D_2D_X3], ax ; SY3 = (scr2eye*Y3) / (scr2eye+scr2org+Z3). mov eax, dword ptr _int3D_drawface_xyz[INT3D_3D_Y3] imul dword ptr _3doms_camera_scr2eye mov ecx, _3doms_camera_scr2eye add ecx, _3doms_camera_scr2org add ecx, _int3D_drawface_xyz[INT3D_3D_Z3] idiv ecx shr eax, 8 add ax, 99 mov _int3D_drawface_scrxy[INT3D_2D_Y3], ax ; Calculate cross vector product - If this is -ive then the shape is ; facing away - don't draw it. mov cx, _int3D_drawface_scrxy[INT3D_2D_X3] sub cx, _int3D_drawface_scrxy[INT3D_2D_X2] mov ax, _int3D_drawface_scrxy[INT3D_2D_Y2] sub ax, _int3D_drawface_scrxy[INT3D_2D_Y1] imul cx mov bx, ax mov cx, _int3D_drawface_scrxy[INT3D_2D_X2] sub cx, _int3D_drawface_scrxy[INT3D_2D_X1] mov ax, _int3D_drawface_scrxy[INT3D_2D_Y3] sub ax, _int3D_drawface_scrxy[INT3D_2D_Y2] imul cx sub ax, bx jle int3D_drawface_nodraw ; Draw face. pop ds push ds mov ah, 94h mov al, ds: [F_COL] push cs pop ds mov si, offset _int3D_drawface_scrxy int 3Dh int3D_drawface_nodraw: pop ds pop si pop edx pop ecx pop bx jmp int3D_end ;-------- Rotate ; Inputs: ; DS:BX - Angles and rotation order (4 bytes). ; CS:SI - 3 Co-ordinate dwords to be rotated. int3D_rotate: test byte ptr ds: [bx+3], 00000001b jnz int3D_rotate_y__ test byte ptr ds: [bx+3], 00000010b jnz int3D_rotate_z__ int3D_rotate_x__: mov al, ds: [bx] call int3D_rotate_x test byte ptr ds: [bx+3], 00000100b jz int3D_rotate__yz int3D_rotate__zy: mov al, ds: [bx+2] call int3D_rotate_z mov al, ds: [bx+1] call int3D_rotate_y ret int3D_rotate__yz: mov al, ds: [bx+1] call int3D_rotate_y mov al, ds: [bx+2] call int3D_rotate_z ret int3D_rotate_y__: mov al, ds: [bx+1] call int3D_rotate_y test byte ptr ds: [bx+3], 00000100b jz int3D_rotate__xz int3D_rotate__zx: mov al, ds: [bx+2] call int3D_rotate_z mov al, ds: [bx] call int3D_rotate_x ret int3D_rotate__xz: mov al, ds: [bx] call int3D_rotate_x mov al, ds: [bx+2] call int3D_rotate_z ret int3D_rotate_z__: mov al, ds: [bx+2] call int3D_rotate_z test byte ptr ds: [bx+3], 00000100b jz int3D_rotate__xy int3D_rotate__yx: mov al, ds: [bx+1] call int3D_rotate_y mov al, ds: [bx] call int3D_rotate_x ret int3D_rotate__xy: mov al, ds: [bx] call int3D_rotate_x mov al, ds: [bx+1] call int3D_rotate_y ret ;-------- Rotate_x ; Inputs: ; AL - Angle. ; CS:SI - 3 Co-ordinate dwords to be rotated about the X-axis. int3D_rotate_x: push bx ; Calculate offset in sine table. xor bx, bx mov bl, al shl bx, 2 ; NY = Y*cos(AL)-Z*sin(AL) mov ecx, cs: INT3D_3D_Y1[si] mov eax, _3doms_cos[bx] imul ecx mov al, dl ror eax, 8 mov cs: INT3D_3D_Y1[si], eax mov eax, _3doms_sin[bx] imul dword ptr cs: INT3D_3D_Z1[si] mov al, dl ror eax, 8 sub cs: INT3D_3D_Y1[si], eax ; NZ = Y*sin(AL)+Z*cos(AL) mov eax, _3doms_cos[bx] imul dword ptr cs: INT3D_3D_Z1[si] mov al, dl ror eax, 8 mov cs: INT3D_3D_Z1[si], eax mov eax, _3doms_sin[bx] imul ecx mov al, dl ror eax, 8 add cs: INT3D_3D_Z1[si], eax pop bx ret ;-------- Rotate_y ; Inputs: ; AL - Angle. ; CS:SI - 3 Co-ordinate dwords to be rotated about the Y-axis. int3D_rotate_y: push bx ; Calculate offset in sine table. xor bx, bx mov bl, al shl bx, 2 ; NY = Y*cos(AL)-Z*sin(AL) mov ecx, cs: INT3D_3D_X1[si] mov eax, _3doms_cos[bx] imul ecx mov al, dl ror eax, 8 mov cs: INT3D_3D_X1[si], eax mov eax, _3doms_sin[bx] imul dword ptr cs: INT3D_3D_Z1[si] mov al, dl ror eax, 8 sub cs: INT3D_3D_X1[si], eax ; NZ = Y*sin(AL)+Z*cos(AL) mov eax, _3doms_cos[bx] imul dword ptr cs: INT3D_3D_Z1[si] mov al, dl ror eax, 8 mov cs: INT3D_3D_Z1[si], eax mov eax, _3doms_sin[bx] imul ecx mov al, dl ror eax, 8 add cs: INT3D_3D_Z1[si], eax pop bx ret ;-------- Rotate_z ; Inputs: ; AL - Angle. ; CS:SI - 3 Co-ordinate dwords to be rotated about the Z-axis. int3D_rotate_z: push bx ; Calculate offset in sine table. xor bx, bx mov bl, al shl bx, 2 ; NY = Y*cos(AL)-Z*sin(AL) mov ecx, cs: INT3D_3D_X1[si] mov eax, _3doms_cos[bx] imul ecx mov al, dl ror eax, 8 mov cs: INT3D_3D_X1[si], eax mov eax, _3doms_sin[bx] imul dword ptr cs: INT3D_3D_Y1[si] mov al, dl ror eax, 8 sub cs: INT3D_3D_X1[si], eax ; NZ = Y*sin(AL)+Z*cos(AL) mov eax, _3doms_cos[bx] imul dword ptr cs: INT3D_3D_Y1[si] mov al, dl ror eax, 8 mov cs: INT3D_3D_Y1[si], eax mov eax, _3doms_sin[bx] imul ecx mov al, dl ror eax, 8 add cs: INT3D_3D_Y1[si], eax pop bx ret ;----------------------------- Graphics Functions ---------------------------; ;-------- Function 94h - Triangle. ; Inputs: ; AH - 94h ; AL - Colour. ; DS:SI - 6 co-ordinate words. ; ES - Output segment. _int3D_triangle_colour db 00h _int3D_triangle_x1x2 dw 0000h _int3D_triangle_y2y1 dw 0000h _int3D_triangle_x1x3 dw 0000h _int3D_triangle_y3y1 dw 0000h _int3D_triangle_x2x3 dw 0000h _int3D_triangle_y3y2 dw 0000h int3D_triangle: mov _int3D_triangle_colour, al push ax push bx push ecx push dx push esi push edi and esi, 0FFFFh and edi, 0FFFFh ; Sort the co-ordinates into order - lowest y-value first. ; Swap (X1,Y1) and (X2,Y2) if necessary. mov ax, INT3D_2D_Y1[si] cmp ax, INT3D_2D_Y2[si] jl int3D_triangle_y1ok xchg ax, INT3D_2D_Y2[si] xchg ax, INT3D_2D_Y1[si] mov ax, INT3D_2D_X1[si] xchg ax, INT3D_2D_X2[si] xchg ax, INT3D_2D_X1[si] int3D_triangle_y1ok: ; Swap (X2,Y2) and (X3,Y3) if necessary. mov ax, INT3D_2D_Y2[si] cmp ax, INT3D_2D_Y3[si] jl int3D_triangle_y2ok xchg ax, INT3D_2D_Y3[si] xchg ax, INT3D_2D_Y2[si] mov ax, INT3D_2D_X2[si] xchg ax, INT3D_2D_X3[si] xchg ax, INT3D_2D_X2[si] int3D_triangle_y2ok: ; Swap (X1,Y1) and (X2,Y2) again if necessary. mov ax, INT3D_2D_Y1[si] cmp ax, INT3D_2D_Y2[si] jl int3D_triangle_y1ok2 xchg ax, INT3D_2D_Y2[si] xchg ax, INT3D_2D_Y1[si] mov ax, INT3D_2D_X1[si] xchg ax, INT3D_2D_X2[si] xchg ax, INT3D_2D_X1[si] int3D_triangle_y1ok2: mov ax, INT3D_2D_X1[si] sub ax, INT3D_2D_X2[si] mov _int3D_triangle_x1x2, ax mov ax, INT3D_2D_Y2[si] sub ax, INT3D_2D_Y1[si] mov _int3D_triangle_y2y1, ax mov ax, INT3D_2D_X1[si] sub ax, INT3D_2D_X3[si] mov _int3D_triangle_x1x3, ax mov ax, INT3D_2D_Y3[si] sub ax, INT3D_2D_Y1[si] mov _int3D_triangle_y3y1, ax mov ax, INT3D_2D_X2[si] sub ax, INT3D_2D_X3[si] mov _int3D_triangle_x2x3, ax mov ax, INT3D_2D_Y3[si] sub ax, INT3D_2D_Y2[si] mov _int3D_triangle_y3y2, ax mov ax, 320 mul word ptr INT3D_2D_Y1[si] mov bx, ax add bx, INT3D_2D_X2[si] add ax, INT3D_2D_X3[si] mov di, ax mov cx, _int3D_triangle_y3y1 rol ecx, 16 mov cx, _int3D_triangle_y2y1 jcxz int3D_triangle_notop int3D_triangle_y1loop: push di push bx mov ax, _int3D_triangle_x1x2 imul cx idiv _int3D_triangle_y2y1 add bx, ax mov ax, _int3D_triangle_x1x3 ror ecx, 16 imul cx idiv _int3D_triangle_y3y1 add di, ax ; Horiz line. cmp di, bx jb int3D_triangle_y1noswap xchg bx, di int3D_triangle_y1noswap: push ecx xor ecx, ecx mov cx, bx sub cx, di inc cx mov al, _int3D_triangle_colour call int3D_line pop ecx dec cx rol ecx, 16 pop bx pop di add di, 320 add bx, 320 loop int3D_triangle_y1loop jmp int3D_triangle_aftertop int3D_triangle_notop: mov bx, INT3D_2D_X1[si] mov di, INT3D_2D_X2[si] cmp bx, di jb int3D_triangle_notop_noswap xchg bx, di int3D_triangle_notop_noswap: mov cx, di sub cx, bx inc cx mov ax, 320 mul word ptr INT3D_2D_Y1[si] mov di, bx add di, ax mov al, _int3D_triangle_colour call int3D_line int3D_triangle_aftertop: mov ax, 320 mul word ptr INT3D_2D_Y2[si] add ax, INT3D_2D_X3[si] mov bx, ax mov di, ax mov cx, _int3D_triangle_y3y2 jcxz int3D_triangle_nobottom int3D_triangle_y2loop: push di push bx mov ax, _int3D_triangle_x2x3 imul cx idiv _int3D_triangle_y3y2 add bx, ax mov ax, _int3D_triangle_x1x3 imul cx idiv _int3D_triangle_y3y1 add di, ax cmp bx, di jb int3D_triangle_y2noswap xchg bx, di int3D_triangle_y2noswap: push ecx xor ecx, ecx mov cx, di sub cx, bx mov di, bx inc cx mov al, _int3D_triangle_colour call int3D_line pop ecx pop bx pop di add bx, 320 add di, 320 loop int3D_triangle_y2loop jmp int3D_triangle_afterbottom int3D_triangle_nobottom: mov bx, INT3D_2D_X2[si] mov di, INT3D_2D_X3[si] cmp bx, di jb int3D_triangle_nobottom_noswap xchg bx, di int3D_triangle_nobottom_noswap: mov cx, di sub cx, bx inc cx mov ax, 320 mul word ptr INT3D_2D_Y2[si] mov di, bx add di, ax mov al, _int3D_triangle_colour call int3D_line int3D_triangle_afterbottom: pop edi pop esi pop dx pop ecx pop bx pop ax jmp int3D_end int3D_line: jcxz int3D_line_noline ; rep stosb ; Slow but safe while testing rendering functions. ; ret shr cx, 1 jnc int3D_line_nobyte stosb int3D_line_nobyte: jcxz int3D_line_noline mov ah, al shr cx, 1 jnc int3D_line_noword stosw int3D_line_noword: jcxz int3D_line_noline push ax rol eax, 16 pop ax rep stosd int3D_line_noline: ret ;-------- End of code (line 2783).