mirror of
https://github.com/elliotnunn/supermario.git
synced 2024-11-22 04:31:30 +00:00
980 lines
32 KiB
Plaintext
980 lines
32 KiB
Plaintext
;
|
|
; File: Graf3DAsm.a
|
|
;
|
|
; Copyright: © 1984-1992 by Apple Computer, Inc., all rights reserved.
|
|
;
|
|
; Change History (most recent first):
|
|
;
|
|
; <SM2> 10/28/92 SWC Changed INCLUDEs to a LOAD of StandardEqu.d.
|
|
;
|
|
|
|
LOAD 'StandardEqu.d'
|
|
INCLUDE 'FixMath.a'
|
|
|
|
|
|
FixRad EQU 3754936 ;radConst = 57.29578
|
|
FracRad EQU 1073741824
|
|
|
|
;offsets
|
|
|
|
;Point3D and Point2D
|
|
x EQU 0 ;Fixed
|
|
y EQU 4 ;Fixed
|
|
z EQU 8 ;Fixed
|
|
|
|
|
|
;XfMatrix = ARRAY[0..3,0..3] OF fixed
|
|
xf00 EQU 0
|
|
xf01 EQU 4
|
|
xf02 EQU 8
|
|
xf03 EQU 12
|
|
xf10 EQU 16
|
|
xf11 EQU 20
|
|
xf12 EQU 24
|
|
xf13 EQU 28
|
|
xf20 EQU 32
|
|
xf21 EQU 36
|
|
xf22 EQU 40
|
|
xf23 EQU 44
|
|
xf30 EQU 48
|
|
xf31 EQU 52
|
|
xf32 EQU 56
|
|
xf33 EQU 60
|
|
|
|
;Port3D
|
|
GrPort EQU 0 ;GrafPtr
|
|
viewRect EQU 4 ;Rect
|
|
xLeft EQU 12 ;Fixed
|
|
yTop EQU 16 ;Fixed
|
|
xRight EQU 20 ;Fixed
|
|
yBottom EQU 24 ;Fixed
|
|
pen EQU 28 ;Point3D
|
|
penPrime EQU 40 ;Point3D
|
|
eye EQU 52 ;Point3D
|
|
hSize EQU 64 ;Fixed
|
|
vSize EQU 68 ;Fixed
|
|
hCenter EQU 72 ;Fixed
|
|
vCenter EQU 76 ;Fixed
|
|
xCotan EQU 80 ;Fixed
|
|
yCotan EQU 84 ;Fixed
|
|
ident EQU 88 ;BOOLEAN
|
|
xForm EQU 90 ;XfMatrix
|
|
szPort3D EQU 154 ;size of Port3D
|
|
|
|
GRAF3D PROC EXPORT
|
|
|
|
;GRAF3DIMPL translated into assembly, a little at a time
|
|
|
|
EXPORT InitGrf3D
|
|
|
|
InitGrf3D ;PROCEDURE InitGrf3D(globalPtr: Ptr);
|
|
|
|
MOVE.L (SP)+,A0
|
|
MOVE.L (SP)+,4(A5)
|
|
JMP (A0)
|
|
|
|
|
|
EXPORT SetPort3D ;PROCEDURE SetPort3D(port: Port3DPtr);
|
|
EXPORT GetPort3D
|
|
|
|
;change to another Port3D
|
|
|
|
SetPort3D
|
|
|
|
MOVE.L 4(SP),A0 ;port
|
|
MOVE.L 4(A5),A1
|
|
MOVE.L A0,(A1) ;thePort3D := port;
|
|
MOVE.L GrPort(A0),-(SP) ;port^.GPort
|
|
_SetPort ;SetPort(port^.GPort);
|
|
popRet MOVE.L (SP)+,(SP) ;pop param off stack
|
|
RTS ;END;
|
|
|
|
|
|
GetPort3D ;PROCEDURE GetPort3D(VAR port: Port3DPtr);
|
|
|
|
;inquire the current Port3D
|
|
;BEGIN
|
|
MOVE.L 4(A5),A0 ;VAR port
|
|
MOVE.L 4(SP),A1
|
|
MOVE.L (A0),(A1) ;port := thePort3D;
|
|
BRA.S popRet ;pop param off stack
|
|
|
|
;PROCEDURE Open3DPort(port:Port3DPtr);
|
|
|
|
EXPORT Open3DPort
|
|
EXPORT MoveTo2D, MoveTo3D, LineTo2D, LineTo3D
|
|
EXPORT Move2D, Move3D, Line2D, Line3D
|
|
EXPORT ViewAngle, Identity, TransForm, Clip3D
|
|
EXPORT ViewPort, LookAt
|
|
|
|
;initialize all values in port^ to their defaults
|
|
|
|
Open3DPort
|
|
MOVE.L A2,-(SP) ;BEGIN
|
|
MOVE.L 8(SP),A1 ;port
|
|
MOVE.L 4(A5),A0
|
|
MOVE.L A1,(A0) ;thePort3D := port;
|
|
MOVE.L (A5),A0 ;get globals
|
|
MOVE.L (A0),GrPort(A1) ;port^.GPort := thePort;
|
|
MOVE.L (A0),A0 ;thePort^
|
|
LEA portRect(A0),A2 ;WITH thePort^.portRect DO
|
|
MOVE.L A2,-(SP) ;thePort^.portRect
|
|
BSR ViewPort ;ViewPort(thePort^.portRect);
|
|
MOVEQ #7,D0
|
|
@1 CLR.L -(SP)
|
|
DBRA D0,@1 ;clear 8 longs on the stack for later operations
|
|
MOVE (A2)+,12(SP) ;put left, right, top, bottom in high words as fixed #s
|
|
MOVE (A2)+,8(SP)
|
|
MOVE (A2)+,4(SP)
|
|
MOVE (A2),(SP)
|
|
BSR LookAt ;LookAt(FixRatio(left,1), FixRatio(top,1), FixRatio(right,1), FixRatio(bottom,1));
|
|
BSR ViewAngle ;ViewAngle(0)
|
|
BSR Identity ;Identity
|
|
BSR.S MoveTo3D ;MoveTo3D(0, 0, 0)
|
|
MOVE.L (SP)+,A2 ;preserved reg.
|
|
MOVE.L (SP)+,(SP) ;return address
|
|
RTS ;END
|
|
|
|
|
|
MoveTo3D ;PROCEDURE MoveTo3D(x, y, z: fixed);
|
|
|
|
;Move from current position to x,y,z without drawing
|
|
|
|
pt1 EQU -4 ;POINT
|
|
pt2 EQU -8 ;POINT
|
|
oldPrime EQU -20 ;Point3D
|
|
local EQU -24 ;local return address
|
|
|
|
BSR.S CmnTo3D
|
|
BEQ.S dontMove
|
|
MOVE.L pt2(A6),-(SP)
|
|
_MoveTo ;THEN MoveTo(pt2.H, pt2.V);
|
|
dontMove MOVE.L (SP)+,A2
|
|
UNLK A6
|
|
MOVE.L (SP),A0
|
|
ADD #16,SP
|
|
JMP (A0) ;END
|
|
|
|
CmnTo3D MOVE.L (SP)+,D0 ;local return address
|
|
LINK A6,#local ;BEGIN
|
|
MOVE.L D0,local(A6) ;save local return
|
|
MOVE.L A2,-(SP)
|
|
MOVE.L 4(A5),A2 ;WITH thePort3D^ DO
|
|
MOVE.L (A2),A2
|
|
LEA penPrime(A2),A0 ;BEGIN
|
|
LEA oldPrime(A6),A1 ;oldPrime := penPrime
|
|
MOVE.L (A0)+,(A1)+
|
|
MOVE.L (A0)+,(A1)+
|
|
MOVE.L (A0),(A1)
|
|
LEA 20(A6),A0 ;x
|
|
LEA pen+x(A2),A1 ;pen + x
|
|
MOVE.L -(A0),(A1)+ ;pen.x := x;
|
|
MOVE.L -(A0),(A1)+ ;pen.y := y;
|
|
MOVE.L -(A0),(A1) ;pen.z := z;
|
|
PEA pen(A2)
|
|
PEA penPrime(A2) ;
|
|
BSR TransForm ;TransForm(pen, penPrime);
|
|
SUBQ #2,SP ;room for result
|
|
PEA oldPrime(A6)
|
|
PEA penPrime(A2)
|
|
PEA pt1(A6)
|
|
PEA pt2(A6)
|
|
BSR Clip3D ;IF Clip3D(oldPrime, penPrime, pt1, pt2)
|
|
MOVE.B (SP)+,D0
|
|
MOVE.L local(A6),A0 ;retrieve local return
|
|
JMP (A0)
|
|
|
|
|
|
LineTo3D ;PROCEDURE LineTo3D(x, y, z: fixed);
|
|
|
|
;nearly the same as MoveTo3D, just moveTo pt1, LineTo pt2
|
|
|
|
BSR.S CmnTo3D
|
|
BEQ.S dontMove
|
|
_HidePen ;changed to support Polygons
|
|
MOVE.L pt1(A6),-(SP)
|
|
_LineTo ;THEN MoveTo(pt1.h, pt1.v);
|
|
_ShowPen
|
|
MOVE.L pt2(A6),-(SP) ;LineTo(pt2.h, pt2.v);
|
|
_LineTo
|
|
BRA.S dontMove
|
|
|
|
Move3D ;PROCEDURE Move3D(dx, dy, dz: fixed);
|
|
BSR.S Cmn3D
|
|
BRA.S MoveTo3D ;MoveTo3D(pen.x + dx, pen.y + dy, pen.z + dz)
|
|
|
|
Cmn3D MOVE.L (SP)+,D2 ;save ret. address
|
|
MOVE.L 4(A5),A0 ;thePort3D
|
|
MOVE.L (A0),A0
|
|
LEA pen(A0),A0 ;thePort3D^.pen
|
|
LEA 16(SP),A1 ;add 4 for the predecrement
|
|
MOVEQ #2,D1 ;3 times, for x, y and z
|
|
@0 MOVE.L (A0)+,D0
|
|
ADD.L D0,-(A1) ;pen.? + d?
|
|
DBRA D1,@0 ;WITH thePort3D^ DO
|
|
MOVE.L D2,A0 ;get ret. addr.
|
|
JMP (A0)
|
|
|
|
Line3D ;PROCEDURE Line3D(dx, dy, dz: fixed);
|
|
BSR.S Cmn3D
|
|
BRA.S LineTo3D ;LineTo3D(pen.x + dx, pen.y + dy, pen.z + dz)
|
|
|
|
MoveTo2D ;PROCEDURE MoveTo2D(x, y: fixed);
|
|
BSR.S CmnTo2D
|
|
BRA.S MoveTo3D ;MoveTo3D(x, y, thePort3D^.pen.z);
|
|
|
|
CmnTo2D MOVE.L (SP)+,A1 ;save return address
|
|
MOVE.L (SP),-(SP) ;get prior return address
|
|
MOVE.L 4(A5),A0 ;thePort3D
|
|
MOVE.L (A0),A0
|
|
MOVE.L pen+z(A0),4(SP)
|
|
JMP (A1)
|
|
|
|
Move2D ;PROCEDURE Move2D(dx, dy: fixed);
|
|
BSR.S Cmd2D
|
|
BRA.S Move3D ;Move3D(dx, dy, 0);
|
|
|
|
Cmd2D MOVE.L (SP)+,A0 ;save local return address
|
|
MOVE.L (SP),-(SP) ;move Move2D return address
|
|
CLR.L 4(SP) ; to make room for '0'
|
|
JMP (A0)
|
|
|
|
LineTo2D ;PROCEDURE LineTo2D(x, y: fixed);
|
|
BSR.S CmnTo2D
|
|
BRA.S LineTo3D ;LineTo3D(x, y, thePort3D^.pen.z);
|
|
|
|
|
|
Line2D ;PROCEDURE Line2D(dx, dy: fixed);
|
|
BSR.S Cmd2D
|
|
BRA.S Line3D ;Line3D(dx, dy, 0);
|
|
|
|
|
|
ViewLook ;PROCEDURE ViewLook
|
|
|
|
;re-calculate offsets and scales after LookAt or ViewPort
|
|
|
|
MOVE.L 4(A5),A0 ;WITH thePort3D^, viewRect DO
|
|
MOVE.L (A0),A0
|
|
MOVE viewRect+right(A0),D0
|
|
MOVE viewRect+left(A0),D2
|
|
SUB D2,D0
|
|
SWAP D0
|
|
CLR.W D0
|
|
ASR.L #1,D0
|
|
MOVE.L D0,hsize(A0) ;hSize:=(right-left)/2.0
|
|
SWAP D2
|
|
CLR.W D2
|
|
ADD.L D2,D0
|
|
MOVE.L D0,hCenter(A0) ;hCenter:=left + hSize;
|
|
MOVE viewRect+bottom(A0),D0
|
|
MOVE viewRect+top(A0),D2
|
|
SUB D2,D0
|
|
SWAP D0
|
|
CLR.W D0
|
|
ASR.L #1,D0
|
|
NEG.L D0
|
|
MOVE.L D0,vsize(A0) ;vSize:=(bottom-top)/(-2.0)
|
|
SWAP D2
|
|
CLR.W D2
|
|
SUB.L D0,D2
|
|
MOVE.L D2,vCenter(A0) ;vCenter:=top - vSize
|
|
RTS
|
|
|
|
|
|
ViewPort ;PROCEDURE ViewPort(r: Rect);
|
|
|
|
;specify what portion of the folder to map onto
|
|
|
|
MOVE.L 4(A5),A0 ;thePort3D
|
|
MOVE.L (A0),A0
|
|
LEA viewRect(A0),A0
|
|
MOVE.L (SP)+,D0 ;save return address
|
|
MOVE.L (SP)+,A1 ;thePort3D^.viewRect := r;
|
|
MOVE.L (A1)+,(A0)+
|
|
MOVE.L (A1),(A0)
|
|
MOVE.L D0,-(SP) ;restore return address
|
|
BRA.S ViewLook ;ViewLook; { re-calculate scales and offsets }
|
|
|
|
|
|
LookAt ;PROCEDURE LookAt(left, top, right, bottom: fixed);
|
|
|
|
;specify the fixed number coordinates of the portRect
|
|
|
|
MOVE.L 4(A5),A0 ; WITH thePort3D^ DO
|
|
MOVE.L (A0),A0
|
|
MOVEQ #3,D0
|
|
LEA xLeft(A0),A0 ; xLeft:= left;
|
|
LEA 20(SP),A1 ; add 4 for predecrement
|
|
@0 MOVE.L -(A1),(A0)+ ;xRight := right;
|
|
DBRA D0,@0 ;yBottom := bottom;
|
|
;yTop := top;
|
|
MOVE.L 4(A5),A0
|
|
MOVE.L (A0),A0
|
|
MOVE.L 16(SP),D0
|
|
ADD.L 8(SP),D0
|
|
ASR.L #1,D0
|
|
MOVE.L D0,eye+x(A0) ;eye.x:=(left+right)/2.0
|
|
MOVE.L 12(SP),D0
|
|
ADD.L 4(SP),D0
|
|
ASR.L #1,D0
|
|
MOVE.L D0,eye+y(A0) ;eye.y:=(top+bottom)/2.0
|
|
MOVE.L (SP)+,A0 ;save return address
|
|
ADD #16,SP ;pop parameters
|
|
MOVE.L A0,-(SP) ;restore return address
|
|
BRA.S ViewLook ;re-calculate scales and offsets
|
|
|
|
|
|
|
|
ViewAngle ;PROCEDURE ViewAngle(angle: fixed);
|
|
|
|
;specify the horizontal angle subtended by the viewing pyramid }
|
|
|
|
MOVE.L A2,-(SP)
|
|
MOVE.L 8(SP),D0
|
|
MOVE.L #6553,D1
|
|
CMP.L D1,D0 ;IF angle < 0.1 THEN angle:=0.1
|
|
BGE.S @0
|
|
MOVE.L D1,D0
|
|
@0 MOVE.L #117899236,D1
|
|
CMP.L D1,D0
|
|
BLE.S @1
|
|
MOVE.L D1,D0 ;IF angle > 179.9 THEN angle := 179.9
|
|
@1 SUB #36,SP ;room for _FixDiv, _FracCos, _FracSin, (_FracRatio), 2 _FixMul, _FixDiv
|
|
MOVE.L D0,-(SP)
|
|
MOVE.L #7509872,-(SP)
|
|
|
|
_FixDiv ;angle:=angle/(2.0*radConst); } { halve angle & convert to rad }
|
|
MOVE.L (SP),8(SP) ;put a copy on stack for Sin
|
|
|
|
_FracCos
|
|
MOVE.L (SP)+,8(SP) ;save result for FracRatio
|
|
|
|
_FracSin
|
|
_FixDiv
|
|
MOVE.L 4(A5),A2
|
|
MOVE.L (A2),A2
|
|
MOVE.L (SP)+,xCotan(A2) ;xCotan := FracRatio(FracCos(angle), FracSin(angle)); { remember for perspective calc }
|
|
MOVE.L xRight(A2),D0
|
|
SUB.L xLeft(A2),D0
|
|
MOVE.L D0,-(SP) ;one for FixDiv, below
|
|
MOVE.L yTop(A2),D0
|
|
SUB.L yBottom(A2),D0
|
|
MOVE.L D0,-(SP)
|
|
|
|
_FixDiv
|
|
MOVE.L xCotan(A2),-(SP) ;note: must divide first or overflow will occur for small angles
|
|
_FixMul
|
|
MOVE.L (SP)+,yCotan(A2) ;yCotan:=xCotan * (xRight-xLeft)/(yTop-yBottom)
|
|
MOVE.L xRight(A2),D0
|
|
SUB.L xLeft(A2),D0
|
|
ASR.L #1,D0
|
|
MOVE.L D0,-(SP)
|
|
MOVE.L xCotan(A2),-(SP)
|
|
_FixMul
|
|
MOVE.L (SP)+,eye+z(A2) ;eye.z:=xCotan * (xRight-xLeft)/2;
|
|
MOVE.L (SP)+,A2
|
|
MOVE.L (SP)+,(SP)
|
|
RTS
|
|
|
|
|
|
TransForm ;PROCEDURE TransForm(src: Point3D; VAR dst: Point3D);
|
|
|
|
;use the current xForm matrix to transform
|
|
;a 3D source point into a 3D destination point.
|
|
|
|
LINK A6,#-12 ;12 bytes off the stack, thank you
|
|
MOVEM.L D3/D4/A2-A4,-(SP)
|
|
MOVE.L 12(A6),A0
|
|
LEA -12(A6),A1
|
|
MOVE.L (A0)+, (A1)+
|
|
MOVE.L (A0)+, (A1)+
|
|
MOVE.L (A0), (A1)
|
|
MOVE.L 4(A5),A2 ;BEGIN
|
|
MOVE.L (A2),A2
|
|
MOVE.L 8(A6),A3
|
|
LEA -12(A6),A4 ; oops Wargo bugo -- fixed 5/8/86
|
|
TST.B ident(A2) ;IF thePort3D^.ident
|
|
BEQ.S trans1
|
|
MOVE.L (A4)+,(A3)+
|
|
MOVE.L (A4)+,(A3)+
|
|
MOVE.L (A4),(A3) ;THEN dst := src
|
|
BRA.S leave
|
|
trans1 MOVEQ #8,D3 ;do all three evaluations in this loop
|
|
@0 SUB #12,SP ;for 3 _FixMuls
|
|
MOVE.L x(A4),-(SP)
|
|
MOVE.L xForm+xF00(A2,D3),-(SP)
|
|
_FixMul ;dst.x:=src.x * xForm[0,0] +
|
|
MOVE.L (SP)+,D4
|
|
MOVE.L y(A4),-(SP)
|
|
MOVE.L xForm+xF10(A2,D3),-(SP)
|
|
_FixMul ; src.y * xForm[1,0] +
|
|
ADD.L (SP)+,D4
|
|
MOVE.L z(A4),-(SP)
|
|
MOVE.L xForm+xF20(A2,D3),-(SP)
|
|
_FixMul ; src.z * xForm[2,0]
|
|
ADD.L (SP)+,D4
|
|
LEA xForm+xF30(A2),A0 ;changed 'cause xForm+xF30(A2,D3) too big
|
|
ADD.L 0(A0,D3),D4 ; + xForm[3,0];
|
|
MOVE.L D4,x(A3,D3)
|
|
SUBQ #4,D3 ;dst.y := src.x * xForm[0,1] + src.y * xForm[1,1] + src.z * xForm[2,1] + xForm[3,1]
|
|
BPL.S @0 ;dst.z := src.x * xForm[0,2] + src.y * xForm[1,2] + src.z * xForm[2,2] + xForm[3,2]
|
|
leave MOVEM.L (SP)+,D3/D4/A2-A4
|
|
UNLK A6
|
|
MOVE.L (SP)+,A0
|
|
ADDQ #8,SP
|
|
JMP (A0)
|
|
|
|
bTop EQU 0
|
|
bLeft EQU 1
|
|
bBottom EQU 2
|
|
bRight EQU 3
|
|
|
|
Code ;FUNCTION Code(pt3D: Point3D) : OutCode;
|
|
MOVE.L 4(SP),A0 ;pt3D
|
|
MOVEQ #0,D1 ;c := []
|
|
MOVE.L z(A0),D0
|
|
MOVE.L x(A0),D2
|
|
CMP.L D2,D0 ;IF pt3D.x > pt3D.z
|
|
BGE.S @0
|
|
BSET #bRight,D1 ;THEN c := [right]
|
|
BRA.S @1
|
|
@0 NEG.L D0
|
|
CMP.L D2,D0 ;ELSE IF pt3D.x < -pt3D.z
|
|
BLE.S @1
|
|
BSET #bLeft,D1 ;THEN c := [left];
|
|
@1 MOVE.L z(A0),D0
|
|
MOVE.L y(A0),D2
|
|
CMP.L D2,D0 ;ELSE IF pt3D.y > pt3D.z
|
|
BGE.S @2
|
|
BSET #bTop,D1 ;THEN c := c + [top]
|
|
BRA.S @3
|
|
@2 NEG.L D0
|
|
CMP.L D2,D0 ;IF pt3D.y < -pt3D.z
|
|
BLE.S @3
|
|
BSET #bBottom,D1 ;THEN c := c + [bottom]
|
|
@3 MOVE.L (SP)+,A0
|
|
ADDQ.L #6,SP ;remove parameter & function result space
|
|
MOVE.B D1,-(SP) ;return byte sized result
|
|
JMP (A0)
|
|
|
|
convert MOVEQ #4,D3 ;do 'y' first
|
|
@0 MOVE.L x(A2,D3),D0
|
|
SUB.L eye+x(A3,D3),D0
|
|
SUBQ #4,SP
|
|
MOVE.L D0,-(SP)
|
|
MOVE.L xCotan(A3,D3),-(SP)
|
|
_FixMul
|
|
MOVE.L (SP)+,x(A2,D3) ;src1.y := (src1.y - eye.y) * yCotan
|
|
SUBQ #4,D3 ;src1.x := (src1.x - eye.x) * xCotan;
|
|
BPL.S @0
|
|
|
|
MOVE.L eye+z(A3),D0
|
|
SUB.L z(A2),D0
|
|
MOVE.L D0,z(A2) ;src1.z := eye.z - src1.z
|
|
RTS
|
|
|
|
Clip3D ;FUNCTION Clip3D(src1, src2: Point3D; VAR dst1, dst2: POINT) : BOOLEAN;
|
|
|
|
;do full 3D clipping to viewing pyramid and return 2D
|
|
;screen coords in dst. Function value true if visible.
|
|
; D3 = c A2 = src1, scratch across ROM calls
|
|
; D4 = c * [left, right] A3 = thePort3D^
|
|
; D5 = _FixMul, _FFixMul flag A4 = src2, scratch
|
|
; D6 = t*(src2.z-src1.z),etc.
|
|
; D7 = Clip3D result flag
|
|
|
|
dst2 EQU 8
|
|
dst1 EQU 12
|
|
src2 EQU 16
|
|
src1 EQU 20
|
|
|
|
c1 EQU -1 ;SET OF (left,top,right,bottom)
|
|
c2 EQU -2 ;SET OF (left,top,right,bottom)
|
|
pt3D EQU -14 ;Point3D
|
|
src1copy EQU -26
|
|
src2copy EQU -38
|
|
|
|
LINK A6,#src2copy
|
|
MOVEM.L D3-D7/A2-A4,-(SP) ;BEGIN
|
|
MOVE.L src1(A6),A0
|
|
LEA src1copy(A6),A1
|
|
MOVE.L (A0)+,(A1)+
|
|
MOVE.L (A0)+,(A1)+
|
|
MOVE.L (A0),(A1)
|
|
MOVE.L src2(A6),A0
|
|
LEA src2copy(A6),A1
|
|
MOVE.L (A0)+,(A1)+
|
|
MOVE.L (A0)+,(A1)+
|
|
MOVE.L (A0),(A1)
|
|
MOVEQ #0,D7 ;Clip3D:=FALSE
|
|
MOVE.L 4(A5),A3 ;WITH thePort3D^ DO
|
|
MOVE.L (A3),A3
|
|
LEA src1Copy(A6),A2
|
|
BSR.S convert
|
|
SUBQ #4,SP ;reserve room for 2 calls to Code
|
|
MOVE.L A2,-(SP)
|
|
BSR.S Code ;c1 := Code(src1)
|
|
MOVE.B (SP)+,c1(A6)
|
|
|
|
LEA src2Copy(A6),A2 ;src2.x := (src2.x - eye.x) * xCotan
|
|
BSR.S convert ;src2.y := (src2.y - eye.y) * yCotan
|
|
;src2.z := eye.z - src2.z;
|
|
MOVE.L A2,-(SP)
|
|
BSR Code ;c2 := Code(src2)
|
|
MOVE.B (SP)+,c2(A6)
|
|
|
|
while ;WHILE c1 + c2 <> [] DO
|
|
MOVE.B c2(A6),D0
|
|
MOVE.B c1(A6),D3
|
|
MOVE.B D0,D2
|
|
OR.B D3,D2
|
|
BEQ endWhile
|
|
|
|
MOVE.B D0,D2
|
|
AND.B D3,D2 ;IF c1 * c2 <> [] THEN GOTO 0; { both out on same side }
|
|
BNE endItAll
|
|
|
|
TST.B D3
|
|
BNE.S @0
|
|
MOVE.B D0,D3 ;c := c1; IF c = [] THEN c := c2
|
|
@0 LEA src1Copy(A6),A2
|
|
LEA src2Copy(A6),A4
|
|
|
|
MOVE.L z(A2),D0
|
|
BTST #bLeft,D3 ;IF left IN c THEN
|
|
BEQ.S @1
|
|
ADD.L x(A2),D0 ;calc intersect with left edge
|
|
MOVE.L D0,D1 ;num := src1.z + src1.x
|
|
SUB.L x(A4),D1 ;denom := (src1.x-src2.x) - (src2.z-src1.z)
|
|
BRA.S @4
|
|
@1 BTST #bRight,D3 ;ELSE IF right IN c THEN
|
|
BEQ.S @2
|
|
SUB.L x(A2),D0 ;calc intersect with right edge
|
|
MOVE.L D0,D1 ;num := src1.z-src1.x
|
|
ADD.L x(A4),D1 ;denom := (src2.x-src1.x) - (src2.z-src1.z)
|
|
BRA.S @4
|
|
@2 BTST #bBottom,D3 ;ELSE IF bottom IN c THEN
|
|
BEQ.S @3
|
|
ADD.L y(A2),D0 ;calc intersect with bottom edge
|
|
MOVE.L D0,D1 ;num := src1.z + src1.y
|
|
SUB.L y(A4),D1 ;denom := (src1.y-src2.y) - (src2.z-src1.z)
|
|
BRA.S @4
|
|
@3 BTST #bTop,D3 ;ELSE IF top IN c THEN
|
|
BEQ.S @4
|
|
SUB.L y(A2),D0 ;calc intersect with bottom edge
|
|
MOVE.L D0,D1 ;num := src1.z - src1.y
|
|
ADD.L y(A4),D1
|
|
@4 SUB.L z(A4),D1 ;denom := (src2.y-src1.y) - (src2.z-src1.z)
|
|
|
|
SUBQ.L #4,SP
|
|
MOVE.L D0,-(SP) ;num (for FFixRatio later, if needed)
|
|
MOVE.L D1,-(SP) ;denom
|
|
SUBQ.L #4,SP
|
|
MOVE.L D0,-(SP) ;num
|
|
MOVE.L D1,-(SP) ;denom
|
|
|
|
|
|
_FixDiv
|
|
MOVE.L (SP),D0 ;t := FixDiv(num, denom);
|
|
BPL.S @5
|
|
NEG.L D0
|
|
@5 CMP.L #$00020000,D0 ;IF ABS(t) < 131072 { < 2} THEN
|
|
BGE.S @9
|
|
MOVEQ #1,D5 ;set _FFixMul flag
|
|
ADDQ #4,SP ;throw away _FixDiv result
|
|
|
|
_FracDiv
|
|
MOVE.L (SP),-(SP) ;room for 2nd FixMul result, copy t for 2nd FixMul
|
|
SUBQ #8,SP ;room for 1st FixMul result, t for 1st FixMul
|
|
MOVE.L 8(SP),(SP) ;copy t for 1st FixMul
|
|
@55 MOVE.L z(A4),D0
|
|
SUB.L z(A2),D0
|
|
BSR.S @8 ;_FFixMul
|
|
MOVE.L (SP)+,D6 ;num := FFixMul(t, src2.z - src1.z);
|
|
|
|
MOVE.L D3,D4
|
|
AND.B #$A,D4 ;IF c * [left, right] <> []
|
|
BEQ.S @6
|
|
|
|
MOVE.L y(A4),D0
|
|
SUB.L y(A2),D0 ;THEN t := FFixMul(t, src2.y - src1.y)
|
|
BRA.S @7
|
|
@6 MOVE.L x(A4),D0
|
|
SUB.L x(A2),D0 ;ELSE t := FFixMul(t, src2.x - src1.x);
|
|
|
|
@7 BSR.S @8 ;_FFixMul
|
|
BRA.S @10
|
|
|
|
@8 MOVE.L (SP)+,D7 ;save return address
|
|
MOVE.L D0,-(SP)
|
|
TST D5
|
|
BNE.S @85
|
|
_FixMul
|
|
BRA.S @87
|
|
|
|
@85 _FracMul
|
|
|
|
@87 MOVE.L D7,A0
|
|
MOVEQ #0,D7
|
|
JMP (A0)
|
|
|
|
@9 MOVE.L (SP),8(SP) ;put 2nd copy on for 2nd _FixMul
|
|
MOVEQ #0,D5 ;flag for _FixMul
|
|
BRA.S @55
|
|
;ELSE
|
|
;num := FixMul(t, src2.z - src1.z);
|
|
;IF c * [left, right] <> []
|
|
;THEN t := FixMul(t, src2.y - src1.y)
|
|
;ELSE t := FixMul(t, src2.x - src1.x);
|
|
|
|
@10 ADD.L z(A2),D6 ;pt3D.z:=t*(src2.z-src1.z) + src1.z;
|
|
MOVE.L D6,pt3D+z(A6)
|
|
|
|
MOVE.L (SP)+,D0 ;get t*(src2.y-src1.y) from above
|
|
TST.B D4 ;IF c * [left, right] <> []
|
|
BEQ.S @11
|
|
ADD.L y(A2),D0
|
|
MOVE.L D0,pt3D+y(A6) ;pt3D.y:=t*(src2.y-src1.y) + src1.y;
|
|
BRA.S @12
|
|
@11 ADD.L x(A2),D0
|
|
MOVE.L D0,pt3D+x(A6) ;pt3D.x:=t*(src2.x-src1.x) + src1.x
|
|
@12 MOVE.L pt3D+z(A6),D0
|
|
MOVE.L D3,D1
|
|
AND.B #6,D1 ;left or bottom,
|
|
BEQ.S @13
|
|
NEG.L D0 ;-pt3D.z
|
|
@13 TST.B D4 ;left or right,
|
|
BEQ.S @14
|
|
MOVE.L D0,pt3D+x(A6) ;IF left IN c THEN pt3D.x := -pt3D.z ELSE
|
|
BRA.S @15 ;IF right IN c THEN pt3D.x := pt3D.z ELSE
|
|
@14 MOVE.L D0,pt3D+y(A6) ;IF bottom IN c THEN pt3D.y := -pt3D.z ELSE
|
|
;IF top IN c THEN pt3D.y := pt3D.z;
|
|
@15 LEA pt3D(A6),A0
|
|
CMP.B c1(A6),D3 ;IF c = c1 THEN
|
|
BNE.S @16
|
|
LEA c1(A6),A4 ;** note: A4 no longer means src2
|
|
LEA src1Copy(A6),A1 ;src1 := pt3D
|
|
BRA.S @17 ;ELSE
|
|
@16 LEA c2(A6),A4
|
|
LEA src2Copy(A6),A1 ;src2 := pt3D
|
|
@17 MOVE.L A1,A2 ;** note: A2 no longer means src1
|
|
MOVE.L (A0)+,(A1)+
|
|
MOVE.L (A0)+,(A1)+
|
|
MOVE.L (A0),(A1)
|
|
SUBQ #2,SP ;IF c = c1 THEN
|
|
MOVE.L A2,-(SP) ;c1 := Code(src1)
|
|
;ELSE
|
|
BSR Code ;c2 := Code(src2)
|
|
MOVE.B (SP)+,(A4)
|
|
BRA while
|
|
EndWhile
|
|
|
|
;if we reach here, the line from src1 to src2 is visible
|
|
MOVEQ #1,D7 ;Clip3D := TRUE;
|
|
;convert clip coords to screen coords
|
|
LEA src1Copy(A6),A2
|
|
MOVE.L dst1(A6),A4
|
|
BSR.S figDst
|
|
LEA src2Copy(A6),A2 ;dst2.H:=ROUND(hCenter + hSize * src2.x / src2.z)
|
|
MOVE.L dst2(A6),A4 ;dst2.V:=ROUND(vCenter + vSize * src2.y / src2.z)
|
|
BSR.S figDst
|
|
|
|
endItAll MOVE.B D7,24(A6)
|
|
MOVEM.L (SP)+,D3-D7/A2-A4
|
|
UNLK A6
|
|
Exit20 MOVE.L (SP),A0
|
|
ADD #20,SP
|
|
JMP (A0)
|
|
|
|
figDst SUB #20,SP ;(4 for _FixDiv, 4 for _FixMul, 2 for _FixRound) * 2
|
|
MOVEQ #4,D3 ;do 'v', 'y' first
|
|
@0 MOVE.L hSize(A3,D3),-(SP) ;h or v = 0, 4
|
|
MOVE.L z(A2),-(SP) ;src1 or src2
|
|
|
|
|
|
_FixDiv
|
|
MOVE.L x(A2,D3),-(SP) ;D3; x or y = 0, 4 {src1 or src2}
|
|
_FixMul
|
|
MOVE.L hCenter(A3,D3),D0 ;D3; h or v = 0, 4
|
|
ADD.L D0,(SP)
|
|
_FixRound
|
|
ASR #1,D3 ;make 4 into 2 (or 0 into 0)
|
|
EOR #2,D3 ;make 2 into 0 (0 into 2)
|
|
MOVE.W (SP)+,v(A4,D3) ;dst1.V:=ROUND(vCenter + vSize * src1.y / src1.z)
|
|
EOR #2,D3 ;fix D3 back
|
|
SUBQ #2,D3 ;dst1.H:=ROUND(hCenter + hSize * src1.x / src1.z)
|
|
BPL.S @0
|
|
RTS
|
|
|
|
|
|
Identity ;PROCEDURE Identity;
|
|
|
|
;reset the transform matrix to identity
|
|
|
|
MOVE.L 4(A5),A0 ;WITH thePort3D^ DO
|
|
MOVE.L (A0),A0
|
|
MOVEQ #1,D0
|
|
MOVE.B D0,ident(A0) ;ident:=TRUE; { SET FLAG SO xForm CAN BE SKIPPED }
|
|
LEA xForm(A0),A0
|
|
SWAP D0
|
|
MOVEQ #3,D1 ;FOR ROW:=0 TO 3 DO
|
|
@0 MOVEQ #3,D2 ;FOR COL:=0 TO 3 DO
|
|
@1 CMP D1,D2 ;IF ROW=COL
|
|
BNE.S @2
|
|
MOVE.L D0,(A0)+ ;THEN xForm[ROW,COL]:=65536
|
|
BRA.S @3
|
|
@2 CLR.L (A0)+ ;ELSE xForm[ROW,COL]:=0
|
|
@3 DBRA D2,@1
|
|
DBRA D1,@0
|
|
RTS ;END;
|
|
|
|
|
|
EXPORT Scale ;PROCEDURE Scale(xFactor, yFactor, zFactor: fixed);
|
|
|
|
;change xForm matrix to provide scaling
|
|
|
|
Scale
|
|
MOVEM.L D3-D4/A2-A3,-(SP) ;BEGIN
|
|
MOVE.L 4(A5),A0 ;WITH thePort3D^ DO
|
|
MOVE.L (A0),A0
|
|
CLR.B ident(A0) ;ident:=FALSE;
|
|
MOVEQ #3,D3 ;FOR ROW:=0 TO 3 DO (four rows)
|
|
LEA xForm(A0),A2
|
|
@0 LEA 32(SP),A3 ;xFactor + 4
|
|
MOVEQ #2,D4 ;three multiplies for a row
|
|
@1 SUBQ.L #4,SP
|
|
MOVE.L (A2),-(SP) ;xForm plus offset for each prior *
|
|
MOVE.L -(A3),-(SP) ;xFactor, then yFactor, then zFactor
|
|
_FixMul
|
|
MOVE.L (SP)+,(A2)+ ;xForm[ROW,0]:=xForm[ROW,0]*xFactor;
|
|
DBRA D4,@1 ;xForm[ROW,1]:=xForm[ROW,1]*yFactor
|
|
DBRA D3,@0 ;xForm[ROW,2]:=xForm[ROW,2]*zFactor
|
|
MOVEM.L (SP)+,D3-D4/A2-A3
|
|
MOVE.L (SP),A0
|
|
ADD #16,SP
|
|
JMP (A0) ;END
|
|
|
|
EXPORT Translate ;PROCEDURE Translate(dx, dy, dz: fixed);
|
|
|
|
;change xForm matrix to translate
|
|
|
|
Translate
|
|
MOVE.L 4(A5),A0 ;WITH thePort3D^ DO
|
|
MOVE.L (A0),A0
|
|
CLR.B ident(A0) ;ident:=FALSE;
|
|
LEA xForm+xf30(A0),A0
|
|
LEA 16(SP),A1
|
|
MOVEQ #2,D1
|
|
@0 MOVE.L (A0),D0
|
|
ADD.L -(A1),D0
|
|
MOVE.L D0,(A0)+ ;xForm[3,0]:=xForm[3,0]+dx;
|
|
DBRA D1,@0 ;xForm[3,1]:=xForm[3,1]+dy;
|
|
MOVE.L (SP),A0
|
|
ADD #16,SP
|
|
JMP (A0) ;END
|
|
|
|
|
|
EXPORT Yaw, Roll, Pitch
|
|
|
|
RotEntry MOVE.L (SP)+,A1 ;return address
|
|
LINK A6,#0
|
|
MOVEM.L A2-A4/D3-D7,-(SP) ;BEGIN
|
|
SUB #16,SP ;reserve space for FixDiv, FracSin & FracCos
|
|
MOVE.L 8(A6),-(SP)
|
|
MOVE.L #fixRad,-(SP)
|
|
|
|
_FixDiv
|
|
|
|
MOVE.L (SP),8(SP) ;save result for FracCos
|
|
|
|
_FracSin
|
|
|
|
MOVE.L (SP)+,D3 ;si
|
|
|
|
_FracCos
|
|
|
|
MOVE.L (SP)+,D4 ;co
|
|
MOVE.L 4(A5),A4 ;WITH thePort3D^ DO
|
|
MOVE.L (A4),A4
|
|
CLR.B ident(A4) ;ident := FALSE
|
|
MOVEQ #3,D5
|
|
JMP (A1)
|
|
|
|
Yaw ;PROCEDURE Yaw(yAngle: fixed);
|
|
|
|
;change xForm matrix to rotate yAngle degrees around y-Axis
|
|
|
|
BSR.S RotEntry ;yAngle := yAngle/radConst { convert degrees to rads }
|
|
;si:=SIN(yAngle)
|
|
;co:=COS(yAngle)
|
|
;WITH thePort3D^ DO ident := FALSE;
|
|
LEA xForm+xf02+48(A4),A2 ;TEMP := xForm[0,0]*co-xForm[0,2]*si (do row 3 first)
|
|
LEA xForm+xf00+48(A4),A3 ;xForm[0,2] := xForm[0,0]*si+xForm[0,2]*co
|
|
BRA.S CmnRot ;xForm[0,0] := TEMP
|
|
|
|
|
|
;TEMP := xForm[1,0]*co-xForm[1,2]*si
|
|
;xForm[1,2] := xForm[1,0]*si+xForm[1,2]*co
|
|
;xForm[1,0] := TEMP
|
|
|
|
;TEMP := xForm[2,0]*co-xForm[2,2]*si
|
|
;xForm[2,2] := xForm[2,0]*si+xForm[2,2]*co
|
|
;xForm[2,0] := TEMP
|
|
|
|
;TEMP := xForm[3,0]*co-xForm[3,2]*si
|
|
;xForm[3,2] := xForm[3,0]*si+xForm[3,2]*co
|
|
;xForm[3,0] := TEMP
|
|
|
|
Roll ;PROCEDURE Roll(zAngle: fixed);
|
|
|
|
;change xForm matrix to rotate zAngle degrees around z-Axis
|
|
|
|
BSR.S RotEntry ;zAngle := zAngle/radConst { convert degrees to rads }
|
|
;si:=SIN(zAngle)
|
|
;co:=COS(zAngle)
|
|
;WITH thePort3D^ DO ident := FALSE;
|
|
LEA xForm+xf00+48(A4),A2 ;TEMP := xForm[0,0]*co+xForm[0,1]*si (row 3 first)
|
|
LEA xForm+xf01+48(A4),A3 ;xForm[0,1] := xForm[0,1]*co-xForm[0,0]*si
|
|
BRA.S CmnRot ;xForm[0,0] := TEMP
|
|
|
|
;TEMP := xForm[1,0]*co+xForm[1,1]*si
|
|
;xForm[1,1] := xForm[1,1]*co-xForm[1,0]*si
|
|
;xForm[1,0] := TEMP;
|
|
|
|
;TEMP := xForm[2,0]*co+xForm[2,1]*si
|
|
;xForm[2,1] := xForm[2,1]*co-xForm[2,0]*si
|
|
;xForm[2,0] := TEMP;
|
|
|
|
;TEMP := xForm[3,0]*co+xForm[3,1]*si
|
|
;xForm[3,1] := xForm[3,1]*co-xForm[3,0]*si
|
|
;xForm[3,0] := TEMP
|
|
|
|
|
|
Pitch ;PROCEDURE Pitch(xAngle: fixed);
|
|
|
|
;change xForm matrix to rotate xAngle degrees around x-Axis
|
|
; D3 = si A2 = xForm + xf01
|
|
; D4 = co A3 = xForm + xf02
|
|
; A4 = thePort3D^
|
|
; D6 = xForm[0,1]
|
|
; D7 = xForm[0,2]
|
|
|
|
BSR.S RotEntry
|
|
LEA xForm+xf01+48(A4),A2 ;xForm[3,1]
|
|
LEA xForm+xf02+48(A4),A3 ;xForm[3,2]
|
|
CmnRot MOVE.L (A2),D6
|
|
MOVE.L (A3),D7
|
|
SUB #16,SP ;4 _FFixMuls
|
|
MOVE.L D6,-(SP)
|
|
MOVE.L D4,-(SP)
|
|
|
|
|
|
_FracMul
|
|
|
|
MOVE.L (SP),4(SP)
|
|
MOVE.L D7,-(SP)
|
|
MOVE.L D3,-(SP)
|
|
|
|
_FracMul
|
|
|
|
MOVE.L (SP)+,D0
|
|
ADD.L (SP)+,D0
|
|
MOVE.L D0,(A2) ;TEMP := xForm[0,1]*co+xForm[0,2]*si;
|
|
MOVE.L D6,-(SP)
|
|
MOVE.L D3,-(SP)
|
|
|
|
|
|
_FracMul
|
|
|
|
MOVE.L (SP),4(SP)
|
|
MOVE.L D7,-(SP)
|
|
MOVE.L D4,-(SP)
|
|
|
|
_FracMul
|
|
|
|
MOVE.L (SP)+,D0
|
|
SUB.L (SP)+,D0
|
|
MOVE.L D0,(A3) ;xForm[0,2] := xForm[0,2]*co-xForm[0,1]*si
|
|
;xForm[0,1] := TEMP
|
|
MOVEQ #16,D0 ;TEMP:=xForm[1,1]*co+xForm[1,2]*si
|
|
SUB.L D0,A2 ;xForm[1,2]:=xForm[1,2]*co-xForm[1,1]*si
|
|
SUB.L D0,A3
|
|
DBRA D5,CmnRot ;xForm[1,1] := TEMP
|
|
MOVEM.L (SP)+,D3-D7/A2-A4 ;TEMP:=xForm[2,1]*co+xForm[2,2]*si
|
|
UNLK A6 ;xForm[2,2]:=xForm[2,2]*co-xForm[2,1]*si
|
|
MOVE.L (SP)+,(SP) ;xForm[2,1] := TEMP
|
|
RTS ;TEMP:=xForm[3,1]*co+xForm[3,2]*si
|
|
;xForm[3,2]:=xForm[3,2]*co-xForm[3,1]*si
|
|
;xForm[3,1] := TEMP
|
|
|
|
|
|
EXPORT Skew ;PROCEDURE Skew(zAngle: fixed);
|
|
|
|
;change xForm matrix to skew zAngle degrees around z-Axis
|
|
;x := (x + y*TAN(zAngle)) zAngle limited to +-90 degrees
|
|
|
|
Skew LINK A6,#0
|
|
MOVEM.L D3/D5/A3-A4,-(SP)
|
|
SUB #16,SP ;space for FixDiv, FracSin, FracCos, FracRatio
|
|
MOVE.L 8(A6),-(SP)
|
|
MOVE.L #fixRad,-(SP)
|
|
|
|
|
|
_FixDiv ;{ co := COS(zAngle); }
|
|
;{IF ABS(co) > 1.0E-5 THEN BEGIN}
|
|
MOVE.L (SP),8(SP) ;copy for FracCos
|
|
|
|
_FracSin
|
|
|
|
MOVE.L (SP)+,4(SP) ;move for FracRatio
|
|
|
|
_FracCos
|
|
|
|
_FixDiv
|
|
|
|
MOVE.L (SP)+,D3 ;TA := SIN(zAngle)/co;
|
|
|
|
MOVE.L 4(A5),A4 ;WITH thePort3D^ DO
|
|
MOVE.L (A4),A4
|
|
CLR.B ident(A4) ;ident := FALSE
|
|
MOVEQ #8,D5 ;FOR COL := 0 TO 2
|
|
@0 LEA xForm+xf10(A4,D5),A3
|
|
MOVE.L xForm+xf00(A4,D5),-(SP)
|
|
MOVE.L D3,-(SP)
|
|
_FixMul
|
|
MOVE.L (SP)+,D0
|
|
ADD.L (A3),D0
|
|
MOVE.L D0,(A3) ;xForm[1,COL] := xForm[1,COL]+xForm[0,COL]*TA
|
|
SUBQ #4,D5
|
|
BNE.S @0
|
|
MOVEM.L (SP)+,D3/D5/A3-A4
|
|
UNLK A6
|
|
MOVE.L (SP)+,(SP)
|
|
RTS ;END
|
|
|
|
EXPORT SetPt3D ;PROCEDURE SetPt3D(VAR pt3D: Point3D; x,y,z: fixed);
|
|
|
|
SetPt3D LEA 20(SP),A1
|
|
MOVE.L -(A1),A0
|
|
MOVE.L -(A1),(A0)+ ;pt3D.x := x;
|
|
MOVE.L -(A1),(A0)+ ;pt3D.y := y;
|
|
MOVE.L -(A1),(A0) ;pt3D.z := z;
|
|
MOVE.L (SP),A0
|
|
ADD #20,SP
|
|
JMP (A0) ;END
|
|
|
|
EXPORT SetPt2D ;PROCEDURE SetPt2D(VAR pt2D: Point2D; x,y: fixed);
|
|
|
|
SetPt2D LEA 16(SP),A1
|
|
MOVE.L -(A1),A0
|
|
MOVE.L -(A1),(A0)+ ;pt2D.x := x;
|
|
MOVE.L -(A1),(A0) ;pt2D.y := y;
|
|
MOVE.L (SP),A0
|
|
ADD #16,SP
|
|
JMP (A0) ;END
|
|
|
|
END ;of Unit
|
|
|
|
|
|
|