home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 5 / DATAFILE_PDCD5.iso / demos / baah / TinyDemos / 3dStars1Kb / StarsSrc < prev   
Encoding:
Text File  |  1996-09-16  |  16.7 KB  |  381 lines

  1. ;                                     \|/
  2. ;                                     O O
  3. ; --------------------------------oOO--U--OOo--------------------------------
  4. ; -                                                                         -
  5. ; -                           3d Starfield in 1Kb.
  6. ; -                   © Alain BROBECKER (baah/Arm's Tech)                   -
  7. ; -                                                         April-Sept 1996 -
  8. ; ---------------------------------------------------------------------------
  9. ;   Wow, a nice starfield in 1Kb, with a bitplane effect, depth shading and a
  10. ; small logo. Some will say it could be even smaller, but please consider I
  11. ; don' t use FPU for creating tables and it runs at 50Hz on my 8Mhz Arm2 with
  12. ; 118*16=1888 stars drawn each VBl. (I went up to 2048 stars by unrolling the
  13. ; drawing loop and a faster CLS) In order to have the demo under 1Kb, I had
  14. ; to avoid the 'adr' and remove some tidies. (random germ, division rounding)
  15. ; By setting the 'normal' var to 1, you' ll have it assembled normally, else
  16. ; you' ll have the 1Kb tweaked version.
  17.  
  18. #name       3dStars1Kb
  19. #set        normal = 0              ; 1 for normal code, 0 for 1Kb.
  20.  
  21. ;------ Constants -----------------------------------------------------------
  22. #set        inv_N = 18              ; Shift for fixed point inverses.
  23. #set        inv_nb = 2048           ; Nb of inverses to calculate.
  24. #set        sin_N = 16              ; Shift for fixed point sinuses.
  25. #set        sin_pow = 10            ; 2^sin_pow is the nb of angles.
  26. #set        sin_nb = 1<<(sin_pow-3) ; Nb of angles between [0;pi/4[.
  27. #set        eye2 = 8
  28. #set        eye = 1<<(eye2-1)       ; Distance between eye and camera.
  29. ;------ BSS Offsets ---------------------------------------------------------
  30. #set        inverses = 0            ; Inverses table.
  31. #set        sinus = inverses+4*inv_nb ; Sinus table.
  32. #set        stars = sinus+4*sin_nb*10 ; Stars coords.
  33. #set        end = stars+4*512*2*4
  34.  
  35. ;****************************************************************************
  36. ;****************************************************************************
  37. ;*****                                                                  *****
  38. ;*****                              MACROS                              *****
  39. ;*****                                                                  *****
  40. ;****************************************************************************
  41. ;****************************************************************************
  42.  
  43. ;====> Umul64 <=====================
  44. ; This macro performs an unsigned 32*32 bits multiply.
  45. ;   [m0|m1]=m2*m3. You can choose [m2|m3]=[m0|m1]
  46. ;   It destroys m0,m1,m4,m5,m6 and the flags. (C is the carry flag)
  47. macro umul64 m0,m1,m2,m3,m4,m5,m6
  48. { mov       m4,m2,lsr #16           ; m4=up(m2).
  49.   sub       m5,m2,m4,lsl #16        ; m5=down(m2).
  50.   mov       m0,m3,lsr #16           ; m0=up(m3).
  51.   sub       m1,m3,m0,lsl #16        ; m1=down(m3).
  52.   mul       m6,m5,m0                ; m6=down(m2)*up(m3).
  53.   mul       m0,m4,m0                ; m0=up(m2)*up(m3).
  54.   mlaS      m6,m1,m4,m6             ; C+m6=up(m2)*down(m3)+down(m2)*up(m3).
  55.   adc       m0,m0,m6,lsr #16
  56.   mul       m1,m5,m1                ; m1=down(m2)*down(m3).
  57.   addS      m1,m1,m6,lsl #16
  58.   adc       m0,m0,#0                ; [m0|m1]=m2*m3.
  59. }
  60. ;====> Adjust64 <===================
  61. ; This macro adjusts the 64 bits result to 32 bits, according to the fixed
  62. ; point shift factor. (c0)
  63. ;   m0=[m1|m2]>>c0. You can choose m1=m0.
  64. ;   It destroys m0.
  65. macro adjust64 m0,m1,m2,c0
  66. { mov       m0,m1,lsl #32-c0
  67.   add       m0,m0,m2,lsr #c0
  68. }
  69. ;====> Add64 <======================
  70. ; This macro performs a 64 bits addition.
  71. ;   [m0|m1]=[m2|m3]+[m4|m5]. You can choose [m2|m3] or [m4|m5]=[m0|m1].
  72. ;   It destroys [m0|m1] and the flags.
  73. macro add64 m0,m1,m2,m3,m4,m5
  74. { addS      m1,m3,m5
  75.   adc       m0,m2,m4
  76. }
  77. ;====> Sub64 <======================
  78. ; This macro performs a 64 bits substract.
  79. ;   [m0|m1]=[m2|m3]-[m4|m5]. You can choose [m2|m3] or [m4|m5]=[m0|m1].
  80. ;   It destroys [m0|m1] and the flags.
  81. macro sub64 m0,m1,m2,m3,m4,m5
  82. { subS      m1,m3,m5
  83.   sbc       m0,m2,m4
  84. }
  85. ;====> Random32 <===================
  86. ; This macro takes a random number, and makes a new one.
  87. macro random32 m0
  88. { eor       m0,m0,m0,rrx
  89.   adc       m0,m0,m0,ror #7
  90. }
  91.  
  92. ;****************************************************************************
  93. ;****************************************************************************
  94. ;*****                                                                  *****
  95. ;*****                               CODE                               *****
  96. ;*****                                                                  *****
  97. ;****************************************************************************
  98. ;****************************************************************************
  99.  
  100. .proggy_start
  101.   swi       OS_WriteS               ; Switch to mode 12 and then 9.
  102.   dcb 22,12,22,9,0
  103. ALIGN
  104.   swi       OS_RemoveCursors        ; Who needs them?
  105.   adr       r0,videoram_adress      ; Get videoram adress.
  106.   mov       r1,r0
  107.   swi       OS_ReadVduVariables
  108. ; Change colors.
  109.   adr       r0,setpal_string        ; Use this color format.
  110.   mov       r2,r0                   ; r2 points on colors.
  111.   mov       r1,#6                   ; Write 6 bytes.
  112.   mov       r14,#&f                 ; Nb of colors to change.
  113. ._one_color
  114.   strB      r14,[r0,#1]             ; Save color number.
  115.   ldrB      r3,[r2,#-1]!            ; Load value.
  116.   strB      r3,[r0,#3]              ; Copy it as red.
  117.   strB      r3,[r0,#4]              ; .. green.
  118.   strB      r3,[r0,#5]              ; .. blue.
  119.   swi       OS_WriteN
  120.   subS      r14,r14,#1              ; One color changed.
  121.   bGE       _one_color
  122. #if normal
  123.   adr       r1,mouse_pointer        ; Mouse pointer block.
  124. #else
  125.   add       r1,r0,#6
  126. #endif
  127.   mov       r0,#&15                 ; Mouse pointer redefinition.
  128.   swi       OS_Word
  129.   mov       r0,#&6a                 ; Plot pointer.
  130.   mov       r1,#2                   ; number 2 (delinked)
  131.   swi       OS_Byte
  132. ;----------------------------------------------------------------------------
  133. ; Creates the inverses table. This routine has been previously released
  134. ; through the "Memory War" article. (October 95)
  135. .make_inverses
  136. #if normal
  137.   adr       r0,bss+inverses+4       ; Create table here.
  138. #else
  139.   mov       r0,#&8400               ; Or here.
  140. #endif
  141.   mov       r1,#1                   ; Used by the division routine.
  142.   mov       r2,#1                   ; r2 is the current divisor.
  143. ._make_one_inverse
  144.   mov       r3,#1<<inv_N            ; r3=dividend.
  145.   mov       r4,#0                   ; r4 will contain the quotient.
  146.   mov       r5,#inv_N               ; r5=Shift for the division.
  147. ._divide_one_step
  148.   cmp       r3,r2,lsl r5            ; dividend bigger than divisor<<r5?
  149.   subGE     r3,r3,r2,lsl r5         ; Yes, then dividend-=divisor<<r5,
  150.   addGE     r4,r4,r1,lsl r5         ;   and add 1<<r5 to the quotient.
  151.   subS      r5,r5,#1                ; Next shift.
  152.   bGE       _divide_one_step
  153. #if normal
  154.   cmp       r2,r3,lsl #1            ; Flags=divisor-2*rest.
  155.   addLE     r4,r4,#1                ; Round to nearest integer.
  156. #endif
  157.   str       r4,[r0],#4              ; Save dividend/divisor.
  158.   add       r2,r2,#1                ; One inverse calculated.
  159.   cmp       r2,#inv_nb              ; It was the last one?
  160.   bNE       _make_one_inverse
  161. ;----------------------------------------------------------------------------
  162. ; Creates the sinus table. As for the inverses creation, the routine has
  163. ; already been released through "Memory War".
  164. .make_sinus
  165. #if normal
  166.   adr       r0,bss+sinus            ; Create table here.
  167. #endif
  168.   ldr       r1,sinA                 ; r1=sinA*2^28.
  169.   ldr       r2,cosA                 ; r2=cosA*2^28.
  170.   mov       r3,#0                   ; r3=sin0*2^28.
  171.   mov       r4,#1<<28               ; r4=cos0*2^28.
  172.   mov       r5,#sin_nb+1
  173. .make_one_sinus
  174.   mov       r6,r4,lsr #28-sin_N     ; r6=cosN*2^sin_N.
  175.   str       r6,[r0,#sin_nb*2*4]     ; Save sin(N+pi/2)=cosN.
  176.   mov       r6,r3,lsr #28-sin_N     ; r6=sinN*2^sin_N.
  177.   str       r6,[r0],#4              ; Save sinN.
  178.   umul64 r6,r7,r1,r3,r8,r9,r10      ; [r6|r7]=sinN*sinA.
  179.   umul64 r8,r9,r2,r4,r10,r11,r12    ; [r8|r9]=cosN*cosA.
  180.   sub64 r6,r7,r8,r9,r6,r7           ; [r6|r7]=cos(N+1)=cosN*sin1-sinN*sin1.
  181.   umul64 r3,r8,r3,r2,r9,r10,r11     ; [r3|r8]=sinN*cosA.
  182.   umul64 r4,r9,r4,r1,r10,r11,r12    ; [r4|r9]=cosN*sinA.
  183.   add64 r3,r8,r3,r8,r4,r9           ; [r3|r8]=sin(N+1)=sinN*cos1+cosN*sin1.
  184.   adjust64 r3,r3,r8,28              ; r1=sin(N+1)=sinN*cos1+cosN*sin1.
  185.   adjust64 r4,r6,r7,28              ; r2=cos(N+1)=cosN*sin1-sinN*sin1.
  186.   subS      r5,r5,#1                ; One sinus processed.
  187.   bNE       make_one_sinus
  188.   sub       r0,r0,#4                ; Complete the table by stupid copy.
  189.   mov       r1,r0                   ; Point on the position which are like
  190.   add       r2,r0,#sin_nb*8         ;  (pi/4+k*(pi/2))   0<=k<=4
  191.   mov       r3,r2
  192.   add       r4,r2,#sin_nb*8
  193.   mov       r5,r4
  194.   add       r6,r4,#sin_nb*8
  195.   mov       r7,r6
  196.   add       r8,r6,#sin_nb*8
  197.   mov       r9,r8
  198.   mov       r10,#sin_nb+1           ; Copy sin_nb+1 values.
  199. ._make_sinus_copy
  200.   ldr       r11,[r0],#-4
  201.   str       r11,[r3],#4             ; sin(pi-X)=sinX.
  202.   str       r11,[r8],#-4            ; sin(2*pi+X)=sinX.
  203.   rsb       r11,r11,#0
  204.   str       r11,[r4],#-4            ; sin(pi+X)=-sinX.
  205.   str       r11,[r7],#4             ; sin(2*pi-X)=-sinX.
  206.   ldr       r11,[r2],#-4
  207.   str       r11,[r1],#4             ; cos(-X)=cosX.
  208.   subS      r10,r10,#1              ; One value copied.
  209.   strNE     r11,[r9],#4             ; cos(2*pi+X)=cosX. No copy if r10=0.
  210.   rsb       r11,r11,#0
  211.   str       r11,[r5],#4             ; cos(pi-X)=-cosX.
  212.   str       r11,[r6],#-4            ; cos(pi+X)=-cosX.
  213.   bNE       _make_sinus_copy
  214. ;----------------------------------------------------------------------------
  215. ; Randomly create starfield. (4 stars for each z)
  216. #if normal
  217.   adr       r0,bss+stars            ; Create stars here.
  218. #else
  219.   mov       r0,#&8400+stars
  220. #endif
  221.   add       r1,r0,#4*512*4          ; We' ll copy them here too.
  222.   mov       r2,#512*4               ; Nb of stars to create.
  223.   ldr       r3,random_germ          ; Load random germ.
  224.   mvn       r4,#&7f0000             ; Put &ff8001ff in r4.
  225.   sub       r4,r4,#&fe00
  226. .make_one_star
  227.   and       r5,r4,r3                ; r5=y|x. (Both in [0;511])
  228.   str       r5,[r0],#4              ; Save it.
  229.   str       r5,[r1],#4              ; Twice.
  230.   random32  r3                      ; Next random numbers.
  231.   subS      r2,r2,#1                ; One star created.
  232.   bNE       make_one_star
  233. ;----------------------------------------------------------------------------
  234. ; The demo begins here.
  235. .one_frame
  236.   mov       r0,#&13                 ; Wait for Vsync.
  237.   swi       OS_Byte
  238.   ldrB      r12,workscreen_nb       ; Load nb of previous workscreen.
  239.   eor       r12,r12,#1              ; New workscreen_nb.
  240.   strB      r12,workscreen_nb       ; Save it.
  241.   rsb       r1,r12,#2               ; r1=new showscreen_nb.
  242.   mov       r0,#&71                 ; And show it.
  243.   swi       OS_Byte
  244.   ldr       r1,videoram_adress
  245.   add       r0,r12,r12,lsl #2
  246.   add       r0,r1,r0,lsl #5+8       ; r0=video+workscreen*160*256.
  247.   add       r0,r0,#8*160
  248. ; Clear plane(0) and copy plane(i) to plane(i+1).
  249.   mov       r1,#%11101110           ; Put mask in r1.
  250.   add       r1,r1,r1,lsl #8
  251.   add       r1,r1,r1,lsl #16
  252.   mov       r2,#800
  253. ._clear_many
  254.   ldmia r0,{r3-r14}:and r3,r1,r3,lsl #1:and r4,r1,r4,lsl #1
  255.   and r5,r1,r5,lsl #1:and r6,r1,r6,lsl #1:and r7,r1,r7,lsl #1
  256.   and r8,r1,r8,lsl #1:and r9,r1,r9,lsl #1:and r10,r1,r10,lsl #1
  257.   and r11,r1,r11,lsl #1:and r12,r1,r12,lsl #1:and r13,r1,r13,lsl #1
  258.   and r14,r1,r14,lsl #1:stmia r0!,{r3-r14}
  259.   subS      r2,r2,#1
  260.   bNE       _clear_many
  261.   sub       r0,r0,#160*240          ; r0 back to workscreen adress.
  262. ; Calculate addx,addy and addz.
  263.   adr       r1,addz
  264.   ldmia     r1,{r2-r3}              ; r2=addz | r3=alpha.
  265.   sub       r2,r2,#3<<(32-9)        ; addz-=3.
  266.   add       r3,r3,#1<<(32-sin_pow)  ; alpha+=1.
  267.   stmia     r1,{r2-r3}
  268.   add       r1,r3,r3                ; r1=2*alpha.
  269.   add       r4,r1,r3                ; r4=3*alpha.
  270. #if normal
  271.   adr       r5,bss+sinus
  272. #else
  273.   mov       r5,#&8400+sinus
  274. #endif
  275.   ldr       r3,[r5,r3,lsr #32-sin_pow-2] ; r3=sin(alpha)<<sin_N.
  276.   add       r5,r5,#128*4            ; r5 points on cos table.
  277.   ldr       r1,[r5,r1,lsr #32-sin_pow-2] ; r1=cos(2*alpha)<<sin_N.
  278.   ldr       r4,[r5,r4,lsr #32-sin_pow-2] ; r4=cos(3*alpha)<<sin_N.
  279.   mul       r4,r3,r4                ; r4=cos(3*alpha)*sin(alpha)<<2*sin_N.
  280.   mul       r1,r3,r1                ; r1=cos(2*alpha)*sin(alpha)<<2*sin_N.
  281.   mov       r1,r1,lsr #2*sin_N-9
  282.   mov       r4,r4,asr #2*sin_N-9
  283.   add       r1,r1,r4,lsl #32-9      ; r1=addy | addx.
  284. ; Now we can draw the stars.
  285. ; r0=videoram adress   r1=addy|addx   r2=addz (bits 23-31)
  286. #if normal
  287.   adr       r3,bss+stars            ; Make r3 points on first stars to draw.
  288. #else
  289.   mov       r3,#&8400+stars
  290. #endif
  291.   add       r2,r3,r2,lsr #32-9-4
  292. #if normal
  293.   adr       r3,bss+inverses+(512+eye)*4 ; r3 points on first z to use.
  294. #else
  295.   mov       r3,#&8400+inverses+(512+eye)*4
  296. #endif
  297.   mov       r4,#120<<(inv_N-eye2)   ; For screen recentering.
  298.   mov       r5,#160<<(inv_N-eye2)
  299.   mov       r6,#%1000               ; Color to draw with.
  300. ._one_color
  301.   mov       r7,#118                 ; draw 118 z with this color.
  302. ._four_stars
  303.   ldr       r8,[r3],#-4             ; r8=2^inv_N/(z+eye).
  304.   mov       r9,#4                   ; Draw 4 stars with same z.
  305. ._one_star
  306.   ldr       r10,[r2],#4             ; r10=y|x.
  307.   add       r10,r10,r1              ; y+=addy | x+=addx.
  308.   mov       r11,r10,asr #32-9       ; r11=y+addy. (-256;255)
  309.   mov       r10,r10,lsl #32-9       ; Wrap x values.
  310.   mov       r10,r10,asr #32-9       ; r10=x+addx. (-256;255)
  311.   mlaS      r11,r8,r11,r4           ; r11=((y+addy)*eye/(z+eye))+120.
  312.   mlaGES    r10,r8,r10,r5           ; r10=((x+addx)*eye/(z+eye))+120.
  313.   bMI       _next_star              ; Stop if x<0 or y<0.
  314.   cmp       r11,#240<<(inv_N-eye2)
  315.   cmpMI     r10,#320<<(inv_N-eye2)
  316.   bGE       _next_star              ; Stop if x>=320 or y>=240.
  317.   mov       r11,r11,lsr #(inv_N-eye2) ; r11=y_screen. (0;255)
  318.   add       r11,r11,r11,lsl #2
  319.   add       r11,r0,r11,lsl #5       ; r11 points on good hline.
  320.   tst       r10,#1<<(inv_N-eye2)    ; x odd or even?
  321.   ldrB      r10,[r11,r10,lsr #(inv_N+1-eye2)]! ; r11=(x/2;y) and load byte.
  322.   orrEQ     r10,r10,r6              ; If x even.
  323.   orrNE     r10,r10,r6,lsl #4       ; If x odd.
  324.   strB      r10,[r11]               ; Save modified byte.
  325. ._next_star
  326.   subS      r9,r9,#1                ; One star drawn.
  327.   bNE       _one_star
  328.   subS      r7,r7,#1                ; Four stars drawn.
  329.   bNE       _four_stars
  330.   movS      r6,r6,lsr #1            ; Next color.
  331.   bNE       _one_color              ; If color<>0 we continue to draw,
  332.   swi       OS_ReadEscapeState      ; Escape key pressed?
  333.   bCC       one_frame               ; No, so we continue.
  334.   swi       OS_Exit                 ; That' s all folks.
  335.  
  336. ;****************************************************************************
  337. ;****************************************************************************
  338. ;*****                                                                  *****
  339. ;*****                            MAIN DATAS                            *****
  340. ;*****                                                                  *****
  341. ;****************************************************************************
  342. ;****************************************************************************
  343.  
  344. .videoram_adress dcd 148,-1 ; Values for swi OS_ReadVduVariables.
  345.  
  346. .random_germ            ; The magical random number.
  347. #if normal
  348.   dcd &eb1a2c37
  349. #endif
  350. .cosA dcd 268430403     ; cos((pi/4)/sin_nb)*2^28.
  351. .sinA dcd 1647089       ; sin((pi/4)/sin_nb)*2^28.
  352.  
  353. .addz  dcd 0            ; Speed along the z-axis.
  354. .alpha dcd 0            ; Angle for stars movements.
  355.  
  356.   dcb &00,&bb,&77,&ee,&55,&dd,&99,&ff ; Colors.
  357.   dcb &44,&cc,&88,&ff,&66,&ee,&aa,&ff
  358. .setpal_string dcb 19,0,16,0,0,0 ; String format to set palette.
  359. .workscreen_nb          ; Next byte will be used as this.
  360. .mouse_pointer
  361.   dcb 0,2 ,8,7, 0,0     ; Redefine Mouse shape nb2 with Widht=32 | Height=7.
  362.   dcd mouse_shape
  363. .mouse_shape
  364.   dcb %00001010,%00000000,%00000000,%00000000 ; Here' s the logo.
  365.   dcb %00000000,%00000000,%00001010,%00000000
  366.   dcb %00001010,%00000000,%00000000,%00000000
  367.   dcb %00000000,%00000000,%00001010,%00000000
  368.   dcb %10001010,%00001010,%10101000,%00001010
  369.   dcb %10101000,%00001010,%10001010,%00001010
  370.   dcb %00101010,%00101000,%00001010,%00101000
  371.   dcb %00001010,%00101000,%00101010,%00101000
  372.   dcb %00001010,%00101000,%00001010,%00101000
  373.   dcb %00001010,%00101000,%00001010,%00101000
  374.   dcb %00001010,%00101000,%00001010,%00101010
  375.   dcb %00001010,%00101010,%00001010,%00001010
  376.   dcb %10101000,%00001010,%10101000,%00101000
  377.   dcb %10101000,%00101000,%00001010,%00101010
  378.  
  379. ;----------------------->  THIS MUST BE AT VERY END  <-----------------------
  380. .bss
  381.