;*======================================================================* ;* TITLE: TURTLE.S * ;* Function: Complete 3D Turtle Demo * ;* * ;* Project #: RAPIER * ;* Programmer: Rob Zdybel * ;* * ;* COPYRIGHT 1993 Atari Computer Corporation * ;* UNATHORIZED REPRODUCTION, ADAPTATION, DISTRIBUTION, * ;* PERFORMANCE OR DISPLAY OF THIS COMPUTER PROGRAM OR * ;* THE ASSOCIATED AUDIOVISUAL WORK IS STRICTLY PROHIBITED. * ;* ALL RIGHTS RESERVED. * ;* * ;*======================================================================* include "jaguar.inc" include "joytrick.inc" ; ; EXTERNAL SYMBOLS ; .extern cube ; Hand-Made Cube .extern TXTCRY_S .extern text3D .extern SORT_S .extern bsort .extern TURTLE_S .extern turtpak .extern TXTCRY_E .extern SORT_E .extern TURTLE_E .extern cubesize ; Hand-Made Cube .extern cubedata .extern gpuload .extern gpurun .extern gpuwait .extern make_olist .extern pad_now .extern pad_shot .extern readpad .extern vblank .extern vidinit .extern Transform .extern framecnt .extern bmp_data .extern DISPBUF0 .extern DISPBUF1 .extern ZBUF .extern TexVertPtr .extern VertexPtr .extern EndOfPack .globl _main .globl eyepts .globl texpts .globl mthpts .globl brpts ; ; USEFUL DEFINES ; RAMSIZE EQU $1000 ; 4K bytes INPUT6 EQU G_ENDRAM-$4 ; pointer to parameter 6 for GPU INPUT5 EQU INPUT6-$4 ; pointer to parameter 5 for GPU INPUT4 EQU INPUT5-$4 ; pointer to parameter 4 for GPU INPUT3 EQU INPUT4-$4 ; pointer to parameter 3 for GPU INPUT2 EQU INPUT3-$4 ; pointer to parameter 2 for GPU INPUT1 EQU INPUT2-$4 ; pointer to parameter 1 for GPU ; ; PROGRAM SEGMENT ; .text _main: move.l #DISPBUF0+15,d0 ; Set up screen buffers with and.l #~15,d0 ; draw_ptr on a 256 byte boundary move.l d0,draw_ptr addq #8,d0 move.l d0,disp_ptr jsr initurtl ; initialize turtles moveq.l #0,d0 moveq.l #-1,d1 move d0,gameover ; Game not over yet move.l d1,pad_now ; Clear the joypad move d0,ncubes move d0,rotate_flg move d1,amb_flg move d1,sun_flg move d1,bulb_flg move d0,scrublist ; ScrubList = Nil move #1,drawlist ; One Object framelp: move.l #$FFFFFFFF,PIT0 jsr clrscreen ; Clear the draw buffer jsr do_sort lea TXTCRY_S,a0 lea text3D,a1 move.l #TXTCRY_E,d0 sub.l #TXTCRY_S,d0 jsr gpuload ; Load Polyhedron Draw Routine into GPU RAM move.l PIT0,d0 move.l d0,time1 move drawlist,newlist drawlp: move newlist,d0 ; WHILE (DrawList <> Nil) DO Draw Object beq .drawxit move d0,d1 mulu #turtlsiz,d0 add.l #turtle,d0 ; D0 = Ptr to Turtle move.l d0,a0 move turtlnk(a0),newlist cmp #0,zposn(a0) blt drawlp lea turtle+turtlsiz,a1 move.l (a1)+,(a0)+ ; Cheat rotation by copying from one cube move.l (a1)+,(a0)+ move.l (a1)+,(a0)+ move.l (a1)+,(a0)+ move.w (a1)+,(a0)+ move.l #cubedata,model_ptr ; point to the appropriate model jsr gpuwait ; Wait for GPU Idle jsr do_fastdraw ; Start GPU/BLTTER Polyhedron Draw bra drawlp .drawxit: jsr readpad ; Read the Joypad jsr gpuwait ; Wait for GPU Idle move.l PIT0,d0 move.l d0,time2 move.l #$0,BORD1 ; **KLUDGE** Bug Test move.l disp_ptr,d0 move.l draw_ptr,disp_ptr move.l d0,draw_ptr ; Swap buffers move.l disp_ptr,bmp_data jsr input ; DEBUG Interpret the Joypad input move.l framecnt,d7 ; D7 = Current Frame for sync later .wsync: cmp.l framecnt,d7 beq .wsync ; Wait for video sync ; move gameover,d0 ; beq framelp ; UNTIL (Game Over) timecheck: move.l PIT0,d0 move.l d0,time3 ; move.l PIT0,d0 ; move.l d0,time3 ; go forever bra framelp stop: illegal ; **KLUDGE** FORCE EXIT TO ADB ; rts nop ; ; SUBROUTINE AREA ; ; ; INPUT Interpret Joypad results and act accordingly ; ; Given: ; PAD_NOW = Current Joypad reading ; PAD_SHOT = One-Shot Joypad ; ; Returns: ; Input handled ; ; Register Usage: ; All Registers Restored ; ; Externals: ; GPULOAD, DO_TURTLE ; ; NOTE: SHOULD CONVERT TO THE GPU. input: movem.l d0-d7/a0-a1,-(sp) lea TURTLE_S,a0 lea turtpak,a1 move.l #TURTLE_E,d0 sub.l #TURTLE_S,d0 jsr gpuload ; Load Turtle Package into GPU ; ; Handle ViewPoint Rotation and Translation ; move.l pad_now,d0 moveq #0,d1 btst.l #JOY_UP,d0 beq .noup addq #4,d1 ; PITCH Down .noup: btst.l #JOY_DOWN,d0 beq .nodwn subq #4,d1 ; PITCH Up .nodwn: moveq #0,d2 btst.l #JOY_LEFT,d0 beq .nolft addq #4,d2 ; YAW Left .nolft: btst.l #JOY_RIGHT,d0 beq .norit subq #4,d2 ; YAW Right .norit: moveq #0,d3 btst.l #KEY_1,d0 beq .nocw subq #4,d3 ; ROLL Clockwise .nocw: btst.l #KEY_3,d0 beq .noccw addq #4,d3 ; ROLL CounterClockwise .noccw: moveq #0,d4 btst.l #KEY_STAR,d0 beq .norev subq #4,d4 ; REVERSE .norev: btst.l #KEY_HASH,d0 beq .nofor addq #4,d4 ; FORWARD .nofor: btst.l #FIRE_A,d0 beq .nomor add #20,d4 ; FAST FORWARD .nomor: moveq #0,d0 jsr do_turtle ; ViewPoint Rotation and Translation ; ; Handle all other input ; move.l pad_shot,d0 btst.l #KEY_0,d0 beq .noquit move #-1,gameover ; 0 = Exit .noquit: ; ; Light Source Toggle and Intensity ; btst.l #FIRE_B,d0 beq .nob eor #-1,sun_flg ; Toggle Sun On/Off .nob: btst.l #FIRE_C,d0 beq .noc eor #-1,bulb_flg ; Toggle InScene On/Off .noc: btst.l #KEY_5,d0 beq .noa eor #-1,amb_flg ; Toggle Ambient On/Off .noa: move.l pad_now,d1 moveq #0,d2 btst.l #KEY_6,d1 beq .noinc addq #1,d2 ; Increase Intensity ; Since intensity isn't used in this version, overload this key and KEY_4 cmp #-160,stretch ble .skipstm sub #2,stretch .skipstm: .noinc: btst.l #KEY_4,d1 beq .nodec subq #1,d2 ; Decrease Intensity cmp #0,stretch bge .skipst add #2,stretch .skipst: .nodec: move amb_flg,d1 beq .litem ; IF (Ambient On) THEN Alter Ambient Intensity add.b d2,ambient+1 .litem: lea litemodel,a0 move ambient,(a0)+ move sun_flg,d1 ; Build a lighting model beq .nosun add.b d2,sun+1 ; IF (Sun On) THEN Update Intensity and add Sun lea sun,a1 move.l (a1)+,(a0)+ move.l (a1)+,(a0)+ .nosun: move bulb_flg,d1 beq .nobulb add.b d2,bulb+1 ; IF (Bulb On) THEN Update Intensity and add Bulb lea bulb,a1 move.l (a1)+,(a0)+ move.l (a1)+,(a0)+ .nobulb: move.w #0,(a0)+ ; ; CUBE Rotation and Propogation ; btst.l #KEY_7,d0 bne .less btst.l #KEY_9,d0 beq .same move ncubes,d2 ; More Cubes addq #1,d2 cmp #8,d2 bge .same ; BUT No more than EIGHT bra .cubes .less: move ncubes,d2 ; Fewer Cubes subq #1,d2 bmi .same ; BUT No fewer than ONE .cubes: lea turtle+turtlsiz,a0 move d2,ncubes ; Build the CUBES ;; keep track of number! move ncubes,d4 ; move d4,nturtles beq .noexp ext.l d4 add.l #1,d4 move.l d4,d1 mulu d4,d1 mulu d4,d1 move.l d1,nturtles .noexp: move #0,drawlist move #0,scrublist move d2,d4 move d2,d5 move d2,d6 moveq #0,d1 moveq #0,d2 moveq #0,d3 moveq #1,d7 .xcube: move d1,xposn(a0) ; Initialize a Cube move d2,yposn(a0) move d3,zposn(a0) move drawlist,turtlnk(a0) move d7,drawlist ; Link to DRAWLIST addq #1,d7 adda.l #turtlsiz,a0 add #$200,d1 dbra d4,.xcube ; All X move ncubes,d4 moveq #0,d1 add #$200,d2 dbra d5,.xcube ; All Y move ncubes,d5 moveq #0,d2 add #$200,d3 dbra d6,.xcube ; All Z .same: btst.l #KEY_8,d0 beq .norot eor #-1,rotate_flg .norot: move rotate_flg,d1 beq .done moveq #1,d0 moveq #6,d1 moveq #6,d2 moveq #6,d3 moveq #0,d4 jsr do_turtle ; Cube Rotation .done: movem.l (sp)+,d0-d7/a0-a1 rts ; ; INITURTL Initialize the TURTLE database ; ; Given: ; Control ; ; Returns: ; All Turtles initialized to Origin ; ; Register Usage: ; All Registers Restored ; ; Externals: ; ; initurtl: movem.l d0-d2/a0,-(sp) move.l #0,nturtles move.w #0,stretch lea turtle,a0 clr d0 move #$4000,d1 move #maxturtl-1,d2 .clrlp: move d1,xrite(a0) ; FOR (All Turtles) DO move d0,yrite(a0) ; Init to Origin - Ordirnally aligned move d0,zrite(a0) move d0,xdown(a0) move d1,ydown(a0) move d0,zdown(a0) move d0,xhead(a0) move d0,yhead(a0) move d1,zhead(a0) move d0,xposn(a0) move d0,yposn(a0) move d0,zposn(a0) move d0,turtlnk(a0) add.l #turtlsiz,a0 dbra d2,.clrlp lea turtle,a0 move #$fe00,zposn(a0) ; **DOUBLE*KLUDGE** Position Viewpt in front of object movem.l (sp)+,d0-d2/a0 rts ; ; CLRSCREEN BLTTER Zero fill the draw buffer and Zbuffer ; ; Given: ; DRAW_PTR = Ptr to Current draw buffer ; ; Returns: ; Draw buffer and Zbuffer zeroed ; ; Register Usage: ; All Registers Restored ; ; Externals: ; clrbuffer ; clrscreen: movem.l d0/a0,-(sp) moveq.l #0,d0 move.l draw_ptr,a0 jsr clrbuffer movem.l (sp)+,a0/d0 rts ; ; CLRBUFFER BLTTER Zero fill a 320x200x2 screen buffer ; ; Given: ; D0 = Data Pattern to fill with ; A0 = Ptr to Buffer to Clear ; ; Returns: ; Draw buffer zeroed ; ; Register Usage: ; All Registers Restored ; ; Externals: ; None ; clrbuffer: movem.l d0-d1/a0-a1,-(sp) move.l #B_CMD,a1 .waitblit: ; Wait for BLTTER Idle move.l (a1),d1 lsr.w #1,d1 bcc .waitblit move.l #(PITCH2|PIXEL16|WID320|XADDPHR),A1_FLAGS move.l a0,A1_BASE ; Point to the buffer move.l d0,B_PATD move.l d0,B_PATD+4 ; Select Fill Pattern clr.l d0 move.l d0,A1_PIXEL ; Point to (0,0) move.w #1,d0 swap d0 move.w #-320,d0 move.l d0,A1_STEP ; Step -320 x, +1 y each line move.w #200,d0 swap d0 move.w #320,d0 move.l d0,B_COUNT ; Do 320x200 move.l #(PATDSEL|UPDA1),B_CMD ; Start the BLTTER movem.l (sp)+,d0-d1/a0-a1 rts ; ; DO_TURTLE Execute the turtle package ; ; Given: ; d0 = Index of Turtle to Operate on ; d1 = PITCH ; d2 = YAW ; d3 = ROLL ; d4 = VELOCITY ; ; Returns: ; Turtle updated ; ; Register Usage: ; All Registers Restored ; ; Externals: ; GPURUN, GPUWAIT ; do_turtle: movem.l a0/d0-d4,-(sp) mulu #turtlsiz,d0 add.l #turtle,d0 ; D0 = Address of Turtle Record move.l d0,INPUT1 move.l d1,INPUT2 move.l d2,INPUT3 move.l d3,INPUT4 move.l d4,INPUT5 ; Remaining inputs lea TURTLE_S,a0 jsr gpurun ; run the GPU program movem.l (sp)+,a0/d0-d4 rts ; ; DO_FASTDRAW Execute the Polyhedron Draw package ; ; Given: ; D0 = Ptr to Turtle to Draw ; ; Returns: ; Object Drawn ; ; Register Usage: ; All Registers Restored ; ; Externals: ; GPURUN ; do_fastdraw: movem.l a0/d0,-(sp) jsr gpuwait move.l d0,INPUT3 ; Pass Ptr to Viewed Object move.l model_ptr,INPUT1 ; Ptr to Instance move.l #turtle,INPUT2 ; Turtle[0] is Viewer move.l #litemodel,INPUT4 ; Ptr to Lighting model move.l draw_ptr,INPUT5 ; tell GPU where to find parameters move.l #instance,INPUT6 ; use for vertex copies lea TXTCRY_S,a0 jsr gpurun ; run the GPU program movem.l (sp)+,a0/d0 rts ;*======================================================================* ;* ;* DO_SORT Execute GPU Bubble Sort ;* ;* Given: ;* DRAWLIST = Last Frame's Sorted See-ables (Inverted, Please) ;* SCRUBLIST = Last Frame's UNSee-ables ;* NTURTLES = Number of Active Turtles ;* TURTLE = Turtle Record Array ;* ;* Returns: ;* DRAWLIST = Painter's Sorted See-ables list root index ;* SCRUBLIST = UNSee-ables list root index ;* ;* Register Usage: ;* All Registers Restored ;* ;* Externals: ;* GPURUN, GPULOAD ;* ;*======================================================================* do_sort: movem.l a0/d0-d1,-(sp) jsr gpuwait ;* Wait for GPU Idle lea SORT_S,a0 lea bsort,a1 move.l #SORT_E,d0 sub.l #SORT_S,d0 jsr gpuload ; Load Polyhedron Draw Routine into GPU RAM move.l #turtle,INPUT1 ; Address of Viewpt Record move.l #drawlist,INPUT2 ; Address of Drawlist Root move.l #scrublist,INPUT3 ; Address of Scrublist Root move.l #turtle+turtlsiz,INPUT4 ; Address of Turtle[1] move.l nturtles,d0 beq skipsort move.l d0,INPUT5 ; Number of Active Turtles move.l #turtlsiz,d0 move.l d0,INPUT6 ; Length of a Turtle Record lea SORT_S,a0 jsr gpurun ; run the GPU program skipsort: movem.l (sp)+,d0-d1/a0 rts ; ; VARIABLE RAM ; .bss .even disp_ptr: ; Display buffer ptr .ds.l 1 draw_ptr: ; Draw buffer ptr .ds.l 1 zbuf_ptr: ; Z buffer ptr .ds.l 1 drawlist: ; Root (Index really) to List of See-able turtles .ds.w 1 scrublist: ; Root (Index really) to List of UNSee-able turtles .ds.w 1 newlist: .ds.w 1 model_ptr: ; Ptr to Instance .ds.l 1 .phrase instance: ; Storage for INSTANCE .ds.l 4*2048 ; 32K Bytes .phrase litemodel: ; Lighting Model .ds.w 12 ; Enough for Ambient and 2 sources gameover: ; Game Over Flag (0 ==> Game Active) .ds.w 1 rotate_flg: ; Cube rotation Flag (0 ==> Sit Still) .ds.w 1 sun_flg: ; Sun Lighting Flag (0 ==> No Sun) .ds.w 1 bulb_flg: ; InScene Lighting Flag (0 ==> No Bulb) .ds.w 1 amb_flg: ; Ambient Lighting Flag (0 ==> No Intensity Change) .ds.w 1 ncubes: ; Number of Cubes in space (Less One) .ds.w 1 nturtles: ; Number of turtles in space .ds.l 1 stretch: .ds.w 1 ; stretch factor to modify the cube time1: .ds.l 1 time2: .ds.l 1 time3: .ds.l 1 ; ; TURTLE RECORDS ; xrite = 0 ; IMPORTANT NOTE: yrite = xrite+2 ; These first record offsets are hard-wired zrite = yrite+2 ; into associated GPU routines. xdown = zrite+2 ; DO NOT Insert, Delete or Swap any of these ydown = xdown+2 ; ^ zdown = ydown+2 ; | xhead = zdown+2 ; | yhead = xhead+2 ; | zhead = yhead+2 ; | xposn = zhead+2 ; | yposn = xposn+2 ; | zposn = yposn+2 ; v turtlnk = zposn+2 ; Dont change this or anything above here turtlsiz = turtlnk+2 maxturtl = 1400 .phrase turtle: ; All Motion Objects .ds.b maxturtl*turtlsiz ; ; CONSTANT DATA ; .data ; .even .long ambient: ; Ambient Intensity .dc.w $80 bulb: ; InScene Light .dc.w $00FF ; Intensity .dc.w $f000 ; X .dc.w $f000 ; Y .dc.w $f000 ; Z ; .dc.w $80FF ; Intensity ; .dc.w $f000 ; X ; .dc.w $f000 ; Y ; .dc.w $f000 ; Z sun: ; Sun .dc.w $00ff ; Intensity .dc.w $4000 ; X .dc.w $0000 ; Y .dc.w $0000 ; Z .long texpts: dc.w 0,0,63,0,63,63,0,63 ; texturemap ptsin eyepts: dc.w 0,0,127,0,127,79,0,79 mthpts: dc.w 0,0,191,0,191,67,0,67 brpts: dc.w 0,0,191,0,191,119,0,119 .end ;*======================================================================* ;* EOF * ;*======================================================================*