3DOMS012.INC
Assembly source for MS-DOS 3D engine, 2790 lines. Raw file
; LKS 3-Dimensional Object Management System (3DOMS) version 0.103
; 3DOMS.INC - <c> 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).