TESTER.ASM
Assembly source for MS-DOS 3D engine, 381 lines. Raw file
; TESTER.ASM - Tester program for LKS 3DOMS.
; Makes a box form with a fin on one side, puts four boxes which share
; it on a turntable, and turns the turntable until Esc is pressed.
.MODEL small
.STACK 1024
.386
JUMPS
;-------- The 3D system.
.CODE
INCLUDE 3DOMS.INC
;-------- Data.
.DATA
_buffer dw 0000h ; Segment of the 64k buffer rendered into.
_universe dw 0000h ; Segment of the universe.
_turntable dw 0000h ; Segment of the object the boxes are on.
_form dw 0000h ; Segment of the box form.
; A center at the origin, for the turntable, the boxes and the form.
_origin dd 0, 0, 0
; The centers of the body and the fin. The body and the fin touch at
; x = 16, and the centers are 8 either side of it, so whichever is nearer
; the camera is always drawn last.
_bodycentre dd 0800h, 0, 0
_fincentre dd 1800h, 0, 0
; The universe: position, angles and rotation order. It puts the scene
; 144 units in front of the camera.
_view dd 0, 0, 9000h
db 00h, 00h, 00h, RORDER_XYZ
; The turntable: position, angles and rotation order. The angles go up a
; little each frame.
_turn dd 0, 0, 0
_turn_rx db 20h
_turn_ry db 00h
_turn_rz db 00h
db RORDER_ZYX
; The four boxes: position, angles and rotation order.
_boxes dd -2000h, -2000h, -0C00h
db 00h, 00h, 00h, RORDER_XYZ
dd -2000h, 2000h, -0400h
db 00h, 00h, 00h, RORDER_XYZ
dd 2000h, 2000h, 0400h
db 00h, 00h, 00h, RORDER_XYZ
dd 2000h, -2000h, 0C00h
db 00h, 00h, 00h, RORDER_XYZ
; The body: 12 faces, two on each side, each in a different grey from the
; standard palette. Each face is its colour and then its three corners.
_body db 1Fh
dd -1000h, 1000h, -2000h, 1000h, 1000h, -2000h, 1000h, -1000h, -2000h
db 1Eh
dd 1000h, -1000h, -2000h, -1000h, -1000h, -2000h, -1000h, 1000h, -2000h
db 1Dh
dd 1000h, -1000h, 2000h, 1000h, 1000h, 2000h, -1000h, 1000h, 2000h
db 1Ch
dd -1000h, -1000h, 2000h, 1000h, -1000h, 2000h, -1000h, 1000h, 2000h
db 1Bh
dd 1000h, 1000h, 2000h, 1000h, 1000h, -2000h, -1000h, 1000h, -2000h
db 1Ah
dd -1000h, 1000h, 2000h, 1000h, 1000h, 2000h, -1000h, 1000h, -2000h
db 19h
dd 1000h, -1000h, 2000h, -1000h, -1000h, -2000h, 1000h, -1000h, -2000h
db 18h
dd -1000h, -1000h, 2000h, -1000h, -1000h, -2000h, 1000h, -1000h, 2000h
db 17h
dd -1000h, 1000h, -2000h, -1000h, -1000h, -2000h, -1000h, 1000h, 2000h
db 16h
dd -1000h, -1000h, -2000h, -1000h, -1000h, 2000h, -1000h, 1000h, 2000h
db 15h
dd 1000h, 1000h, -2000h, 1000h, 1000h, 2000h, 1000h, -1000h, -2000h
db 14h
dd 1000h, -1000h, 2000h, 1000h, -1000h, -2000h, 1000h, 1000h, 2000h
; The fin: a cube on the side of the body, in reds and yellows. The side
; against the body can never be seen, so it has no faces.
_fin db 28h
dd 1000h, 800h, -800h, 2000h, 800h, -800h, 2000h, -800h, -800h
db 28h
dd 2000h, -800h, -800h, 1000h, -800h, -800h, 1000h, 800h, -800h
db 29h
dd 2000h, -800h, 800h, 2000h, 800h, 800h, 1000h, 800h, 800h
db 29h
dd 1000h, -800h, 800h, 2000h, -800h, 800h, 1000h, 800h, 800h
db 2Ah
dd 2000h, 800h, 800h, 2000h, 800h, -800h, 1000h, 800h, -800h
db 2Ah
dd 1000h, 800h, 800h, 2000h, 800h, 800h, 1000h, 800h, -800h
db 2Bh
dd 2000h, -800h, 800h, 1000h, -800h, -800h, 2000h, -800h, -800h
db 2Bh
dd 1000h, -800h, 800h, 1000h, -800h, -800h, 2000h, -800h, 800h
db 2Ch
dd 2000h, 800h, -800h, 2000h, 800h, 800h, 2000h, -800h, -800h
db 2Ch
dd 2000h, -800h, 800h, 2000h, -800h, -800h, 2000h, 800h, 800h
_msg_nomem db 'Not enough memory.', 13, 10, 0
_msg_error db 'ERROR - 3DOMS returned ', 0
_msg_end db 'h', 13, 10, 0
;-------- Start of code.
.CODE
.STARTUP
call tester
.EXIT
;-------- Tester.
tester:
; Give back the memory the program doesn't use, so there is room for the
; buffer and the heap. ES is still the PSP.
mov bx, sp
add bx, 15
shr bx, 4
mov ax, ss
add bx, ax
mov ax, es
sub bx, ax
mov ah, 4Ah
int 21h
jc tester_nomem
; Allocate the 64k buffer to render into.
mov ah, 48h
mov bx, 1000h
int 21h
jc tester_nomem
mov _buffer, ax
; Log on, asking for a heap of between 8k and 32k. The universe is the
; first cell of the heap.
mov bx, 0100h
mov dx, 0400h
call logon_3doms
jc tester_nomem
mov _universe, ax
; Put the scene in front of the camera.
mov ah, 10h
mov si, offset _view
mov es, _universe
int 3Dh
jc tester_error
; Make the turntable in the universe.
mov ah, 1Bh
mov si, offset _origin
mov es, _universe
int 3Dh
jc tester_error
mov _turntable, ax
; Make the box form, with the body and the fin as its two shapes.
mov ah, 1Ch
mov si, offset _origin
int 3Dh
jc tester_error
mov _form, ax
mov ah, 1Dh
mov si, offset _bodycentre
mov es, _form
int 3Dh
jc tester_error
mov es, ax
mov si, offset _body
mov cx, 12
call tester_faces
jc tester_error
mov ah, 1Dh
mov si, offset _fincentre
mov es, _form
int 3Dh
jc tester_error
mov es, ax
mov si, offset _fin
mov cx, 10
call tester_faces
jc tester_error
; Make the four boxes on the turntable, move each one to its place and
; give it the box form.
mov si, offset _boxes
mov cx, 4
tester_box:
push si
mov ah, 1Bh
mov si, offset _origin
mov es, _turntable
int 3Dh
pop si
jc tester_error
mov es, ax
mov ah, 10h
int 3Dh
jc tester_error
mov ah, 11h
mov bx, _form
int 3Dh
jc tester_error
add si, 16
loop tester_box
; Switch to 320x200 in 256 colours.
mov ax, 0013h
int 10h
tester_loop:
; Clear the buffer to stripes of colours 1 and 0.
mov es, _buffer
xor di, di
mov cx, 16000
mov eax, 00010001h
cld
rep stosd
; Turn the turntable a little more each frame.
add _turn_rx, 1
add _turn_ry, 2
add _turn_rz, 4
mov ah, 10h
mov si, offset _turn
mov es, _turntable
int 3Dh
jc tester_error
; Render the universe into the buffer.
push ds
mov ah, 20h
mov es, _buffer
mov ds, _universe
int 3Dh
pop ds
jc tester_error
; Wait for the vertical retrace, then copy the buffer to the screen.
mov dx, 03DAh
tester_retrace:
in al, dx
test al, 08h
jz tester_retrace
push ds
mov ds, _buffer
xor si, si
mov ax, 0A000h
mov es, ax
xor di, di
mov cx, 16000
rep movsd
pop ds
; Carry on until Esc is let go.
in al, 60h
cmp al, 81h
jne tester_loop
; Back to text mode, and log off.
mov ax, 0003h
int 10h
call logoff_3doms
ret
; 3DOMS returned an error: show it and log off.
tester_error:
push ax
mov ax, 0003h
int 10h
mov si, offset _msg_error
call print
pop ax
call print_hex
mov si, offset _msg_end
call print
call logoff_3doms
ret
tester_nomem:
mov si, offset _msg_nomem
call print
ret
;-------- Tester_faces.
; Adds CX faces from DS:SI to the shape in ES. Each face is a colour byte and
; then 36 bytes of corners. Returns with carry set and the error in AX if
; 3DOMS returns one.
tester_faces:
mov al, [si]
inc si
mov ah, 1Eh
int 3Dh
jc tester_faces_end
add si, 36
loop tester_faces
clc
tester_faces_end:
ret
;-------- Print.
; Prints the zero-terminated string at DS:SI.
print:
push ax
push dx
push si
print_loop:
mov dl, [si]
or dl, dl
jz print_end
mov ah, 02h
int 21h
inc si
jmp print_loop
print_end:
pop si
pop dx
pop ax
ret
;-------- Print_hex.
; Prints AX as four hex digits.
print_hex:
push ax
push bx
push cx
push dx
mov bx, ax
mov cx, 4
print_hex_loop:
rol bx, 4
mov dl, bl
and dl, 0Fh
add dl, '0'
cmp dl, '9'
jbe print_hex_digit
add dl, 7
print_hex_digit:
mov ah, 02h
int 21h
loop print_hex_loop
pop dx
pop cx
pop bx
pop ax
ret
END