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