************************************************************ * * * 60 Bytes Starfield Routine by RAYLIGHT of PowerLine. * * ==================================================== * * * * R Henrik Magnusson, June 1997. * * (E-Mail Currently at: henrikm@hotmail.com) * * For the starfield competition at #amycoders... * * * * * * This starfield routine follows all the written rules * * for the starfield competition: * * ==================================================== * * * * - Exactly 512 Stars is calculated each frame. * * (In the first frame 0-511 stars is calculated) * * * * - Approx. 90-95% of the stars are visible each frame * * * * - A star is made of one pixel in one bitplane. * * * * - Perspective projection with eyepoint at (0,0,0). * * * * - Clipping at screen borders (0-319,0-255). * * * * - Each star is moving on the Z-axis, towards the * * observer. * * * * - A star that passes the eyepoint in Z-direction, is set * * to a "random" position in 3D-space. (Pseudo-random is * * a more correct definition...) * * * * - The position (0,0,0) in 3D-space is equal to the * * position (160,128) on the screen. * * * * - No system routines are used, no hardware access is * * done. * * * * ==================================================== * * * * This routine uses the stack for storing variables. It * * is asumed that the stack is cleared at program entry. * * The Amiga OS does this automatically when running a * * program. However, when running it from Asm-One, the * * stack is NOT cleared, which results in a less * * attractive starfield in the beginning. In short terms: * * THIS ROUTINE IS DESIGNED TO, TOGETHER WITH A STARTUP * * CODE, RUN AS A STAND-ALONE EXECUTABLE! * * * * Read the inline comments for information about the * * techniques used in the routine. * * * * The routine uncommented: * * ======================== * * * * moveq #-128,d5 * * lea -512*3*2-32(a7),a1 * *.lop movem.w (a1)+,d1-d3 * * subq.w #7,-(a1) * * bgt.b .ok * * sub.l (a1),d0 * * add.w d0,(a1) * * eor.l d0,-(a1) * * addq.l #4,a1 * *.ok divs.w (a1),d1 * * divs.w (a1)+,d2 * * cmp.w #160,d1 * * bge.b .skip * * add.w #160,d1 * * blt.b .skip * * cmp.w d5,d2 * * ble.b .skip * * add.w d5,d2 * * bgt.b .skip * * muls.w #-320,d2 * * add.w d1,d2 * * bfset (a0){d2:1} * *.skip sub.w d5,d6 * * bvc.b .lop * * * ************************************************************ ********************* *********************** ****** . . ****** **** . . . Init & Exit code . ` **** *** ' . ```````````````` . *** ** . . . . . ` . . ** ** ` written in a hurry for . . ** *** . : . . `````````````````````` . *** **** #Amycoders' starfield compo by **** ****** . ``````````````````````````` morbid ********************* *********************** bsr CloseWB ; Flush view and disable multitasking bsr OpenScreen ; Set pointers and sync jsr Starfield_init ;Init starfield ** ************************************************************ ************************************************************ ** ** >>> M A I N <<< ** Main btst #6,$bfe001 beq Exit ************************************************************ bsr DisplayScreen jsr Starfield ;call starfield (a0=Bitplane) bra Main ** ************************************************************ ** ** Flush view & disable system ** CloseWB movea.l 4.w,a6 ; exec base jsr -132(a6) ; Forbid jsr -120(a6) ; Disable lea GfxName(pc),a1 ; graphics.library moveq #0,d0 ; whatever verision jsr -552(a6) ; open it ! move.l d0,GfxBase ; store gfxbase movea.l d0,a6 ; gfxbase in a6 move.l $22(a6),OldView ; store system view move.l $26(a6),OldCop ; store system copper sub.l a1,a1 jsr -222(a6) ; flush view (LoadView) jsr -270(a6) ; WaitTOF jsr -270(a6) ; twice for interlaced views move.w $dff002,OldDMAcon ; store old dma control register ori.w #$8000,OldDMAcon ; set bit #15 move.w #$7fff,$dff096 move.w #$8380,$dff096 rts GfxName dc.b 'graphics.library',0 even GfxBase dc.l 0 OldView dc.l 0 OldCop dc.l 0 OldDMAcon dc.w 0 cnop 0,4 ** ************************************************************* ** ** Display Screen ** DisplayScreen movem.l d0-d1,-(sp) move.b $bfe801,d0 .wait cmp.b $bfe801,d0 beq.b .wait move.l screen_logical(pc),d0 move.l screen_physical(pc),screen_logical move.l d0,screen_physical lea copper_bpl,a0 move.w d0,6(a0) ; lower part of bpl address swap d0 move.w d0,2(a0) ; higher word movea.l screen_logical(pc),a0 moveq #0,d0 move.l #(320/32)*256-1,d1 .clear move.l d0,(a0)+ ; clear logical screen dbf d1,.clear lea -(320/8)*256(a0),a0 movem.l (sp)+,d0-d1 rts screen_physical dc.l 0 screen_logical dc.l 0 ** ************************************************************* ** ** Open Screen ** OpenScreen lea $dff000,a5 move.w #$2c81,$08e(a5) ; display window start pos move.w #$2cc1,$090(a5) ; display window stop pos move.w #$0038,$092(a5) ; data fetch start pos move.w #$00d0,$094(a5) ; data fetch stop pos move.l #ScreenA,screen_logical move.l #ScreenB,screen_physical bsr DisplayScreen rts ** ************************************************************** ** ** Open WB ** Exit lea $dff000,a5 move.w #$7fff,$96(a5) ; clear dmacon move.w OldDMAcon(pc),$96(a5) ; set old bits move.l GfxBase(pc),a6 ; gfxbase in a6 move.l OldCop(pc),$80(a5) ; restart old copperlist move.l OldView(pc),a1 jsr -222(a6) ; Load system view move.l a6,a1 move.l 4.w,a6 jsr -414(a6) ; close graphics.library jsr -126(a6) ; Enable jsr -138(a6) ; Permit rts ************************************************************************ section screens,bss_c ScreenA ds.b (320*256)/8 ScreenB ds.b (320*256)/8 ************************************************************************ section copperlist,data_c Copper dc.l $01001000 ; bplcon0 dc.l $01080000 ; bpl1mod dc.l $010a0000 ; bpl2mod dc.l $01800000 ; colour 0 = black dc.l $01820fff ; colour 1 = white copper_bpl dc.l $00e00000 ; bpl1pth dc.l $00e20000 ; bpl1ptl dc.l $fffffffe ************************************************************************** ************************************************************************** ** ** ** Your starfield code starts here ** ** ************************************************************************** ************************************************************************** section code,code ;put your code here ********************************************* ** Do all initialisations here ********************************************* Starfield_init: a b rts ********************************************* ** This routine is called once a frame ** ** The destination Bitplane is given in a0 ********************************************* Starfield: ***************************************************** * 60 Bytes Starfield Routine by Raylight/PowerLine. * * ------------------------------------------------- * * R Henrik Magnusson, June 1997 * * (E-Mail Currently at: henrikm@hotmail.com) * * * ***************************************************** c moveq #-128,d5 ;The value 128 is used for ;3 things: Clipping, centering ;the perspective, and as adder ;to the loop counter. Since ;a moveq #128,d5 is not allowed ;the code must be designed for ;-128. lea -512*3*2-32(a7),a1 ;Using the stack saves 2 bytes. ;(3072+32) bytes of stack space ;is used. The 32 extra bytes is ;as safety offset to compensate ;for the "jsr Starfield" etc... ;A stack overflow happens only ;if the init routine uses more ;than *1000* bytes of stack, ;which should be VERY rare and ;stupid... .lop *** Load X,Y,Z Coords *** movem.w (a1)+,d1-d3 *** Move and Randomize Out of Sight Points *** subq.w #7,-(a1) ;We simply subtract the velocity bgt.b .ok ;from the Z-coordinate and then ;test if the coordinate is below ;zero. If so, we randomize new ;X,Y,Z coordinates. sub.l (a1),d0 ;d0 is the "random" register, ;which is increased with the ;current point's Z-coord, and ;the next point's ;Z-coord * 65536. add.w d0,(a1) ;The Z-coord is increased with ;the "random" register. Since ;the the rules does NOT mention ;any limits in 3D-space for the ;randomized point's new ;coordinates, NO boundary tests ;is done. The point could appear ;very far away, or at a negative ;Z-coordinate. However, if a point ;is randomized to a negative ;Z-coord, it will be randomized ;again the next frame, and most ;likely appear at a positive Z-coord. eor.l d0,-(a1) ;The X,Y-coords are updated too... addq.l #4,a1 .ok *** 3D projection *** divs.w (a1),d1 ;This is the actual 3D-projection. divs.w (a1)+,d2 *** Centering + Clipping *** cmp.w #160,d1 bge.b .skip add.w #160,d1 blt.b .skip cmp.w d5,d2 ble.b .skip add.w d5,d2 ;The Y-coord is treated as bgt.b .skip ;negative, to allow a moveq at ;the top of the routine. This ;is done to be able to have the ;(0,0,0) at exactly (160,128) ;as stated in the rules. *** Plot Point *** muls.w #-320,d2 ;By having a negative value, we ;make the negative Y-coord ;positive again. add.w d1,d2 ;Destination offset = Y*320+X bfset (a0){d2:1} ;Plot the point! .skip sub.w d5,d6 ;This is a tricky thing! Since bvc.b .lop ;The clipping uses the value -128, ;so we can reuse it here and save ;some bytes. We know that 128*512 ;is equal to 65536. So, if we add ;128 to a .w-counter, for each pixel ;calculated, an overflow will ;occur after 512 points. The nice ;thing about it is that is does NOT ;matter which value the counter ;contains at program entry. After ;one frame the counter will be ;between 0 and 127, which means ;that 512 stars will be calculated ;no matter what. A normal dbra ;loop would be 8 bytes, this ;one is 4... d rts printt "Length of code:" printv ((b-a)+(d-c)) section bss,bss ;put your tables here .