home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 5 / DATAFILE_PDCD5.iso / demos / baah / CakeHead2 / Cake2_Src / ZoomerPart < prev   
Encoding:
Text File  |  1995-10-21  |  23.0 KB  |  539 lines

  1. ;                                     \|/
  2. ;                                     O O
  3. ; --------------------------------oOO--U--OOo--------------------------------
  4. ; |                                                                         |
  5. ; |              16 colours Zoomer with realtime generated code.            |
  6. ; |                       By Alain BROBECKER. (as Baah)                     |
  7. ; |                                                                         |
  8. ; ---------------------------------------------------------------------------
  9. ;
  10. ;    * The only interesting thing in here is the realtime code generator.
  11. ; All the rest is a mere demonstration of its ability, so go have a look
  12. ; at it to have more infos... I' m quite sorry of this fact, but the
  13. ; rest of this code is not very good. (I mean I' m not satisfied with it)
  14. ;    * When called, this part of the demo assumes all colors are set to
  15. ; black! Also, I' m using some of the tables (inverses;sin-cos) created
  16. ; in the main part! Anyway, I don' t think all this is very hard to
  17. ; understand!
  18.  
  19. #set        zoom_img_w = 120        ; Must be a multiple of 8.
  20. #set        zoom_img_h = 153
  21. #set        zoom_ystart = -330
  22. #set        zoom_yend = 175
  23. #set        zoom_vy = 1
  24. #set        zoom_shift = 9          ; Shift for sinus, gives the amplitued.
  25. #set        zoom_vangle = 3
  26.  
  27. .zoomer_part
  28.   stmfd     r13!,{r0-r12,r14}
  29. ; First, clear the whole videoram.
  30.   bl        get_showscreen          ; r0=showscreen adress.
  31.   mov       r1,#&0                  ; r1=fill pattern.
  32.   bl        clear_mode9
  33.   bl        get_workscreen          ; r0=workscreen adress.
  34.   mov       r1,#&0                  ; r1=fill pattern.
  35.   bl        clear_mode9
  36. ; Then, put the palette.
  37.   adr       r2,_zoomer_colors
  38.   bl        set_palette
  39.  
  40.   mov       r0,#zoom_ystart         ; First position of the zoomer.
  41.   str       r0,_y_position
  42. ._zoomer_one_frame
  43.   bl        wait_and_swap           ; Wait vsync and swap screen.
  44.   str       r0,_workscreen_ad
  45. ; Clear the image which was displayed two vbls before!
  46.   adr       r1,_previous_y
  47.   ldmia     r1,{r2-r3}              ; r2=y_pos(-1) | r3=y_pos(-2).
  48.   str       r2,[r1,#4]              ; Next VBl y_pos(-1) will be y_pos(-2).
  49.   mov       r1,r3                   ; r1=y_pos(-2).
  50.   bl        _clear_box              ; Clear box.
  51. ; Here we do the calculations to know the width of the image on screen
  52. ; (scr_w), its height (scr_h) and its position. (First visible y=screen_y)
  53.   ldr       r0,_y_position          ; y_pos+=vy.
  54.   add       r0,r0,#zoom_vy
  55.   cmp       r0,#zoom_yend           ; y_pos>yend?
  56.   ldmGEfd   r13!,{r0-r12,pc}        ; Yes, then quit.
  57.   str       r0,_y_position          ; Save new y_pos.
  58.   ldr       r1,_angle               ; Angle-=vangle.
  59.   add       r1,r1,#zoom_vangle
  60.   cmp       r1,#512                 ; angle>512?.
  61.   subGE     r1,r1,#512              ; Then wrap to beginning of table.
  62.   str       r1,_angle               ; Save new angle.
  63.   adr       r2,bss+sin_cos_ad
  64.   ldr       r1,[r2,r1,lsl #2]       ; r1=65536*sin(angle).
  65.   movS      r1,r1,asr #zoom_shift   ; r1=amplitude*sin(angle).
  66.   rsbMI     r1,r1,#0                ; r1=z=abs(dist*sin(angle)).
  67.   add       r1,r1,#128              ; r1=z+dist_eye.
  68.   adr       r4,bss+inv_ad
  69.   ldr       r1,[r4,r1,lsl #2]       ; r1=65536/(z+dist_eye).
  70.   mul       r12,r0,r1               ; r12=y*65536/(z+dist_eye).
  71.   mov       r12,r12,asr #9          ; r12=y*dist_eye/(z+dist_eye).
  72.   add       r12,r12,#160            ; r12=screen_y.
  73.   str       r12,_previous_y         ; Save it for next time.
  74.   mov       r0,#zoom_img_h
  75.   mul       r11,r0,r1
  76.   mov       r11,r11,asr #9          ; r11=scr_h=img_h*dist_eye/(z+dist_eye).
  77. ; Generate the zoomer code.
  78.   mov       r0,#zoom_img_w          ; r0=Original size.
  79.   mul       r1,r0,r1                ; r1=img_w*(z+dist_eye).
  80.   mov       r1,r1,asr #9            ; r1=zoomed_size.
  81.   mov       r2,#160
  82.   sub       r2,r2,r1,lsr #1         ; r2=x_position. (From left)
  83.   bl        generate_zoomer_code
  84. ; Here we go for the drawing of the image. Of course, as the object is
  85. ; y zoomed too, we have to calculate the y_zoom_coef (=original/zoomed).
  86. ; Then we can start drawing the object.
  87.   ldr       r0,[r4,r11,lsl #2]      ; r0=65536/zoomed_h.
  88.   mov       r1,#zoom_img_h          ; r1=original_h.
  89.   mul       r6,r0,r1                ; r6=65536*(original_h/zoomed_h).
  90.   mov       r7,#0                   ; r7=65536*src_y_pos.
  91.   adr       r8,_image               ; Adress of source image.
  92.   ldr       r9,_workscreen_ad       ; Adress of workscreen.
  93.   add       r9,r9,#160              ; We point on the righ border.
  94.   mov       r2,#&f0000000           ; Used by the zoomer.
  95.   adr       r14,_next_line          ; I want to be back..
  96. ._one_line
  97.   addS      r0,r12,r12,lsl #2       ; r0=screen_y*5.
  98.   bMI       _next_line              ; If screen_y<0, line is not visible.
  99.   cmp       r12,#256                ; Same comment if screen_y>255, but
  100.   bGE       _end_frame              ;    then no more line is visible.
  101.   add       r0,r9,r0,lsl #5         ; r0 points on screen_y line.
  102.   mov       r1,r7,lsr #16           ; r1=int(src_y_pos).
  103.   mov       r3,#zoom_img_w/2        ; r3=nb of bytes per src_line.
  104.   mla       r1,r3,r1,r8             ; r1 points on good source line.
  105.   bl        zoom_routine
  106. ._next_line
  107.   add       r12,r12,#1              ; Next screen line.
  108.   add       r7,r7,r6                ; src_y_pos+=(original_h/zoomed_h).
  109.   mov       r0,r7,lsr #16           ; r0=int(src_y_pos).
  110.   cmp       r0,#zoom_img_h          ; Beyond the image?
  111.   bLT       _one_line
  112. ._end_frame                         ; Everything done, go on...
  113.   b         _zoomer_one_frame
  114.  
  115.  
  116. ; ===========================================================================
  117. ; =                                                                         =
  118. ; =                                 DATAS                                   =
  119. ; =                                                                         =
  120. ; ===========================================================================
  121.  
  122. ._angle
  123.   dcd       0
  124. ._y_position
  125.   dcd       0
  126. ._previous_y
  127.   dcd       0,0
  128.  
  129. ._workscreen_ad
  130.   dcd       0
  131.  
  132. ._image
  133.   incbin    Datas.NewNours
  134.  
  135. ._zoomer_colors
  136.   dcb       &00,&00,&00,&55,&55,&77,&99,&99,&99,&ee,&ee,&ee
  137.   dcb       &bb,&77,&88,&cc,&88,&99,&dd,&99,&aa,&aa,&99,&bb
  138.   dcb       &88,&aa,&cc,&55,&aa,&dd,&44,&99,&cc,&33,&88,&bb
  139.   dcb       &22,&77,&aa,&11,&66,&99,&bb,&bb,&dd,&88,&88,&aa
  140.  
  141. ; ===========================================================================
  142. ; ===========================================================================
  143. ; =                                                                         =
  144. ; =                               ROUTINES                                  =
  145. ; =                                                                         =
  146. ; ===========================================================================
  147. ; ===========================================================================
  148.  
  149.  
  150. ;----------------------------------------------------------------------------
  151. ; This routine simply clears a box of the maximum size of the image.
  152. ; Note that if you want to change the width of the box cleared, you must
  153. ; get your hands dirty and made this by your own. Full clipping is provided.
  154. ; I assume the box is centered on screen, and in fact I took a box a bit
  155. ; bigger than maximum image....
  156. ; Parameters of this routine...
  157. ;           r0=videoram adress.
  158. ;           r1=y pos of first line.
  159. ._clear_box
  160.   stmfd     r13!,{r0-r12,r14}
  161.   addS      r2,r1,#zoom_img_h-1     ; r2=ymax<0?
  162.   ldmMIfd   r13!,{r0-r12,pc}        ; Then box is invisible.
  163.   cmp       r1,#256                 ; r1=ymin>255?
  164.   ldmGEfd   r13!,{r0-r12,pc}        ; Same comment.
  165.   mov       r14,#zoom_img_h         ; Nb of lines to clear.
  166.   cmp       r1,#0                   ; ymin<0?
  167.   addMI     r14,r14,r1              ; Then draw image_h+ymin lines,
  168.   movMI     r1,#0                   ;   and start at line y=0.
  169.   subS      r2,r2,#255              ; ymax>255?
  170.   subGT     r14,r14,r2              ; Then draw image_h-(ymax-255) lines.
  171.   add       r1,r1,r1,lsl #2         ; Make r0 point on first line to clear.
  172.   add       r0,r0,r1,lsl #5
  173.   add       r0,r0,#4+(320-zoom_img_w)/4 ; Box centered.
  174.  
  175.   mov r1,#0:mov r2,r1:mov r3,r1:mov r4,r1:mov r5,r1:mov r6,r1
  176.   mov r7,r1:mov r8,r1:mov r9,r1:mov r10,r1:mov r11,r1:mov r12,r1
  177. ._clear_one_line
  178.   stmia     r0!,{r1-r12}            ; 120/8 => 15 longs.
  179.   stmia     r0!,{r1-r4}
  180.   add       r0,r0,#(320-zoom_img_w)/2-4 ; Next line.
  181.   subS      r14,r14,#1
  182.   bNE       _clear_one_line
  183.   ldmfd     r13!,{r0-r12,pc}        ; Bye...
  184.  
  185.  
  186. ; ***************************************************************************
  187. ; *****                                                                 *****
  188. ; *****              Routine generating a zoomer routine.               *****
  189. ; *****                 By Alain BROBECKER. (as Baah)                   *****
  190. ; *****                        Februar 1995.                            *****
  191. ; *****                                                                 *****
  192. ; ***************************************************************************
  193. ;
  194. ; >-------------------------------------------------------------------------<
  195. ; Parameters of generating routine...
  196. ;           r0=original size of hline.
  197. ;           r1=zoomed size of hline.
  198. ;           r2=x position. (From right to left...)
  199. ;
  200. ; >-------------------------------------------------------------------------<
  201. ; Parameters of the generated zoom routine...
  202. ;           r0=adress of dest hline. (Adress of the right border...)
  203. ;           r1=adress of source hline.
  204. ;           r2=$f000000. (Mask used to isolate source pixies.)
  205. ;           r3,r4 & r5 are modified.
  206. ;           r14=return adress.
  207. ;   Only r2 and r14 are left unchanged. r3 is used to load a source word,
  208. ; r4 will contain isolated source pixies and r5 will contain the dest word.
  209. ;
  210. ; >-------------------------------------------------------------------------<
  211. ;                        Some (usefull) explanations...
  212. ;                        ------------------------------
  213. ; In the zoom routine...
  214. ;   * I isolate the source pixels into r4, and then I mix it to the others
  215. ; pixels already contained in r5. Of course, the first pixie of each longword
  216. ; (ie the pixie contained in bits 28-31) is isolated directly in r5. The
  217. ; mixing and isolation of a pixies are requiring registers rotations.
  218. ;   * I'm generating the code for 8 pixies in one time, this proves to be
  219. ; faster and much easier, because then the rotations for the pixels mixing
  220. ; are always known.
  221. ;   * There was, in the first version I coded, a fucking bug!.. In fact I
  222. ; didn' t know that 'r?,ror #0' is not a legal operand! At this time the
  223. ; drawing was from left to right (classical then) and I had to use a
  224. ; 'ror #0'. So I should have replaced this by a 'lsl #0', and then there
  225. ; should have been a supplementary test. So, I found a neat (I hope) 'trick'
  226. ; which allows me not to care about the 'ror #0' and which proves faster at
  227. ; the same time... First, the mixing rotations are no problem, (see above) so
  228. ; I simply had to avoid 'ror #0' during isolation rotations, and this is done
  229. ; by simply avoid to generate rors.. So I decided to isolate the pixies in
  230. ; the bits 28-31 of r4, and so I only have to use shifts left. But then,
  231. ; if I was drawing from left to right, it would be shitty cos I would have
  232. ; the first pixie, normally contained in bits 0-3 which will be isolated
  233. ; in bits 28-31. But now, if you consider drawing from right to left, the
  234. ; (small) problem quite simply disappears! Of course, there may have been
  235. ; others solutions, but I bet they would not be as easy. So, now you can
  236. ; understand why I am able to isolate directly the first pixie. Well, anyway,
  237. ; the very important thing is to know that 'ror #0' is no LEGAL instruction!
  238. ; (It' s replaced by 'rrx' which seems the same as 'ror #1'.)
  239. ;   * Hum, er.. I said the problem disappeared, and that' s right, but of
  240. ; course another problem came to replace the last one.. Anyway this new
  241. ; problem is not all that big.. In fact you must only know that the source
  242. ; image must be organized in a strange way! Considering the standard left
  243. ; to right image, you must take its symmetric longword per longword. (But
  244. ; not the symmetric of the longwords!...) See the 'ConvPic' basic proggy.
  245. ;   * The generated routine always begin with 'lsr r3,[r1]', so it is
  246. ; stupid to generate it each time.. Just let it be inchanged.
  247. ;
  248. ; The generated routine looks like this...(If x_pos mod(8)=0).
  249. ;   ldr     r3,[r1]                 ; r3=source long.
  250. ;   and     r5,r2,r3,lsl #0         ; bits 28-31 of r5=src_pixie 0.
  251. ;   and     r4,r2,r3,lsl #16        ; bits 28-31 of r4=src_pixie 4.
  252. ;   add     r5,r5,r4,ror #4         ; Mix.
  253. ;   ldr     r3,[r1,#4]!
  254. ;   and     r4,r2,r3                ; bits 28-31 of r4=src_pixie 8.
  255. ;   add     r5,r5,r4,ror #8         ; Mix.
  256. ;   and     r4,r2,r3,lsl #16        ; bits 28-31 of r4=src_pixie 12.
  257. ;   add     r5,r5,r4,ror #12        ; Mix.
  258. ;   ....
  259. ;   str     r5,[r0],#-4             ; Save zoomed long.
  260. ;   ....
  261.  
  262. .generate_zoomer_code
  263.   stmfd     r13!,{r0-r12,r14}
  264.   adr       r3,zoom_routine+4       ; r3 points on zoom routine+4.
  265.   adr       r4,_opcodes
  266.   ldmia     r4!,{r5-r12,r14}        ; Load opcodes.
  267.   adr       r4,bss+inv_ad           ; Make r4 point on inverses table.
  268.   ldr       r4,[r4,r1,lsl #2]       ; r4=65536/zoomed_size.
  269.   mul       r0,r4,r0                ; r0=zoom=65536*(original/zoomed).
  270.   and       r4,r2,#&7               ; r4=dest=x_pos mod(8).
  271.   sub       r2,r2,r4                ; r2=x_pos-(x_pos mod(8))=2*offset.
  272.   add       r5,r5,r2,lsr #1         ; r5='sub r0,r0,#offset'.
  273.   str       r5,[r3],#4              ; Generate 'sub r0,r0,#offset'.
  274.   rsb       r2,r4,#8                ; r2=dest2=8-x_pos mod(8).
  275.   mov       r5,#0                   ; r5=src_pos.
  276.   cmp       r1,r2                   ; Flags=nb_dest-dest2.
  277.   bMI       _only_one_long
  278.   cmp       r4,#0                   ; Flags=dest-0.
  279.   bEQ       _full_longs_generation  ; If dest=0, first word is full.
  280.  
  281. ; >-------------------------------------------------------------------------<
  282. ; The first longword of the dest is not full, generate the routine according
  283. ; to this fact.
  284.  
  285. ._first_long_generation
  286.   str       r8,[r3],#4              ; Generate 'and r4,r2,r3,lsl #0'.
  287.   add       r5,r5,r0                ; src_pos=src_pos+zoom.
  288.   add       r6,r6,r4,lsl #9         ; r6='mov r5,r4,ror #dest*4'.
  289.   str       r6,[r3],#4
  290.   sub       r1,r1,r2                ; nb_dest=nb_dest-dest2.
  291.   add       r4,r4,#1                ; dest=dest+1.
  292.   cmp       r4,#8                   ; Flags=dest-8.
  293.   bEQ       _end_first_long
  294. ._first_long
  295.   mov       r6,r5,lsr #17           ; r6=int(src_pos/2).
  296.   bicS      r6,r6,#&3               ; r6=(src_pos-(src_pos mod(8))/2.
  297.   addNE     r6,r11,r6               ; r6='ldr r3,[r1,#..]!'.
  298.   strNE     r6,[r3],#4              ; Generate it.
  299.   bicNE     r5,r5,#&3f80000         ; r5=src_pos mod(8).
  300.   mov       r6,r5,lsr #16           ; r6=int(src_pos).
  301.   add       r6,r8,r6,lsl #9         ; r6='and r4,r2,r3,lsl #src_pos*4'.
  302.   str       r6,[r3],#4              ; Generate it.
  303.   add       r5,r5,r0                ; src_pos=src_pos+zoom.
  304.   add       r6,r9,r4,lsl #9         ; r6='add r5,r5,r4,ror #dest*4'.
  305.   str       r6,[r3],#4              ; Generate it.
  306.   add       r4,r4,#1                ; dest=dest+1.
  307.   cmp       r4,#8                   ; Gnerate dest points until word is full.
  308.   bNE       _first_long
  309. ._end_first_long
  310.   str       r12,[r3],#4             ; Generate 'str r5,[r0],#-4'.
  311.  
  312. ; >-------------------------------------------------------------------------<
  313. ; This routine generate code in the case when dest longwords are full.
  314. ; (i.e. there is more than 8 pixies to generate still.)
  315.  
  316. ._full_longs_generation
  317.   subS      r1,r1,#8                ; nb_dest=nb_dest-8.
  318.   bMI       _last_long_generation
  319. ._full_longs
  320. ; Generates code for first source pixie... Isolate directly in dest long.
  321.   mov       r6,r5,lsr #17           ; r6=int(src_pos/2).
  322.   bicS      r6,r6,#&3               ; r6=(src_pos-(src_pos mod(8))/2.
  323.   addNE     r6,r11,r6               ; r6='ldr r3,[r1,#..]!'.
  324.   strNE     r6,[r3],#4              ; Generate it.
  325.   bicNE     r5,r5,#&3f80000         ; r3=src_pos mod(8).
  326.   mov       r6,r5,lsr #16           ; r6=int(src_pos).
  327.   add       r6,r7,r6,lsl #9         ; r6='and r5,r2,r3,lsl #src_pos*4'.
  328.   str       r6,[r3],#4              ; Generate it.
  329.   add       r5,r5,r0                ; src_pos=src_pos+zoom.
  330. ; ... second pixie. Use the 'add r5,r5,r4,ror #4' to mix dest pixies.
  331.   mov       r6,r5,lsr #17           ; r6=int(src_pos/2).
  332.   bicS      r6,r6,#&3               ; r6=(src_pos-(src_pos mod(8))/2.
  333.   addNE     r6,r11,r6               ; r6='ldr r3,[r1,#..]!'.
  334.   strNE     r6,[r3],#4              ; Generate it.
  335.   bicNE     r5,r5,#&3f80000         ; r3=src_pos mod(8).
  336.   mov       r6,r5,lsr #16           ; r6=int(src_pos).
  337.   add       r6,r8,r6,lsl #9         ; r6='and r4,r2,r3,lsl #src_pos*4'.
  338.   str       r6,[r3],#4              ; Generate it.
  339.   add       r5,r5,r0                ; src_pos=src_pos+zoom.
  340.   str       r10,[r3],#4             ; Generate 'add r5,r5,r4,ror #4'.
  341. ; ... 3rd to 8th pixies... Generates 'add r5,r5,r4, ror #?'.
  342.   mov       r6,r5,lsr #17           ; 3rd.
  343.   bicS      r6,r6,#&3
  344.   addNE     r6,r11,r6
  345.   strNE     r6,[r3],#4
  346.   bicNE     r5,r5,#&3f80000
  347.   mov       r6,r5,lsr #16
  348.   add       r6,r8,r6,lsl #9
  349.   str       r6,[r3],#4
  350.   add       r5,r5,r0
  351.   add       r6,r9,#8<<7             ; r6='add r5,r5,r4,ror #8'.
  352.   str       r6,[r3],#4
  353.   mov       r6,r5,lsr #17           ; 4th.
  354.   bicS      r6,r6,#&3
  355.   addNE     r6,r11,r6
  356.   strNE     r6,[r3],#4
  357.   bicNE     r5,r5,#&3f80000
  358.   mov       r6,r5,lsr #16
  359.   add       r6,r8,r6,lsl #9
  360.   str       r6,[r3],#4
  361.   add       r5,r5,r0
  362.   add       r6,r9,#12<<7            ; r6='add r5,r5,r4,ror #12'.
  363.   str       r6,[r3],#4
  364.   mov       r6,r5,lsr #17           ; 5th.
  365.   bicS      r6,r6,#&3
  366.   addNE     r6,r11,r6
  367.   strNE     r6,[r3],#4
  368.   bicNE     r5,r5,#&3f80000
  369.   mov       r6,r5,lsr #16
  370.   add       r6,r8,r6,lsl #9
  371.   str       r6,[r3],#4
  372.   add       r5,r5,r0
  373.   add       r6,r9,#16<<7            ; r6='add r5,r5,r4,ror #16'.
  374.   str       r6,[r3],#4
  375.   mov       r6,r5,lsr #17           ; 6th.
  376.   bicS      r6,r6,#&3
  377.   addNE     r6,r11,r6
  378.   strNE     r6,[r3],#4
  379.   bicNE     r5,r5,#&3f80000
  380.   mov       r6,r5,lsr #16
  381.   add       r6,r8,r6,lsl #9
  382.   str       r6,[r3],#4
  383.   add       r5,r5,r0
  384.   add       r6,r9,#20<<7            ; r6='add r5,r5,r4,ror #20'.
  385.   str       r6,[r3],#4
  386.   mov       r6,r5,lsr #17           ; 7th.
  387.   bicS      r6,r6,#&3
  388.   addNE     r6,r11,r6
  389.   strNE     r6,[r3],#4
  390.   bicNE     r5,r5,#&3f80000
  391.   mov       r6,r5,lsr #16
  392.   add       r6,r8,r6,lsl #9
  393.   str       r6,[r3],#4
  394.   add       r5,r5,r0
  395.   add       r6,r9,#24<<7            ; r6='add r5,r5,r4,ror #24'.
  396.   str       r6,[r3],#4
  397.   mov       r6,r5,lsr #17           ; 8th.
  398.   bicS      r6,r6,#&3
  399.   addNE     r6,r11,r6
  400.   strNE     r6,[r3],#4
  401.   bicNE     r5,r5,#&3f80000
  402.   mov       r6,r5,lsr #16
  403.   add       r6,r8,r6,lsl #9
  404.   str       r6,[r3],#4
  405.   add       r5,r5,r0
  406.   add       r6,r9,#28<<7            ; r6='add r5,r5,r4,ror #28'.
  407.   str       r6,[r3],#4
  408.  
  409.   str       r12,[r3],#4             ; Generate 'str r5,[r0],#-4'.
  410.   subS      r1,r1,#8                ; nb_dest=nb_dest-8.
  411.   bPL       _full_longs             ; More than 8 pixies left?
  412.  
  413. ; >-------------------------------------------------------------------------<
  414. ; Generate code which will fill the last longword...
  415. ; Quite similar to the full long generation, except that we must test
  416. ; at each different dest point if we have finished, and that we will never
  417. ; have a 8th pixie.
  418.  
  419. ._last_long_generation
  420.   addS      r1,r1,#8                ; r1=nb of points still to draw.
  421.   BEQ       _the_end                ; All points drawn?
  422.  
  423.   mov       r6,r5,lsr #17           ; 1st pixie.
  424.   bicS      r6,r6,#&3
  425.   addNE     r6,r11,r6
  426.   strNE     r6,[r3],#4
  427.   bicNE     r5,r5,#&3f80000
  428.   mov       r6,r5,lsr #16
  429.   add       r6,r7,r6,lsl #9         ; r6='and r5,r2,r3,lsl #src_pos*4'.
  430.   str       r6,[r3],#4
  431.   subS      r1,r1,#1
  432.   bEQ       _last_long_save
  433.   add       r5,r5,r0
  434.   mov       r6,r5,lsr #17           ; 2nd.
  435.   bicS      r6,r6,#&3
  436.   addNE     r6,r11,r6
  437.   strNE     r6,[r3],#4
  438.   bicNE     r5,r5,#&3f80000
  439.   mov       r6,r5,lsr #16
  440.   add       r6,r8,r6,lsl #9         ; r6='and r4,r2,r3,lsl #src_pos*4'.
  441.   str       r6,[r3],#4
  442.   str       r10,[r3],#4             ; Generate 'add r5,r5,r4,ror #4'.
  443.   subS      r1,r1,#1
  444.   bEQ       _last_long_save
  445.   add       r5,r5,r0
  446.   mov       r6,r5,lsr #17           ; 3rd.
  447.   bicS      r6,r6,#&3
  448.   addNE     r6,r11,r6
  449.   strNE     r6,[r3],#4
  450.   bicNE     r5,r5,#&3f80000
  451.   mov       r6,r5,lsr #16
  452.   add       r6,r8,r6,lsl #9
  453.   str       r6,[r3],#4
  454.   add       r6,r9,#8<<7             ; r6='add r5,r5,r4,ror #8'.
  455.   str       r6,[r3],#4
  456.   subS      r1,r1,#1
  457.   bEQ       _last_long_save
  458.   add       r5,r5,r0                ; src_pos=src_pos+zoom.
  459.   mov       r6,r5,lsr #17           ; 4th.
  460.   bicS      r6,r6,#&3
  461.   addNE     r6,r11,r6
  462.   strNE     r6,[r3],#4
  463.   bicNE     r5,r5,#&3f80000
  464.   mov       r6,r5,lsr #16
  465.   add       r6,r8,r6,lsl #9
  466.   str       r6,[r3],#4
  467.   add       r6,r9,#12<<7            ; r6='add r5,r5,r4,ror #12'.
  468.   str       r6,[r3],#4
  469.   subS      r1,r1,#1
  470.   bEQ       _last_long_save
  471.   add       r5,r5,r0
  472.   mov       r6,r5,lsr #17           ; 5th.
  473.   bicS      r6,r6,#&3
  474.   addNE     r6,r11,r6
  475.   strNE     r6,[r3],#4
  476.   bicNE     r5,r5,#&3f80000
  477.   mov       r6,r5,lsr #16
  478.   add       r6,r8,r6,lsl #9
  479.   str       r6,[r3],#4
  480.   add       r6,r9,#16<<7            ; r6='add r5,r5,r4,ror #16'.
  481.   str       r6,[r3],#4
  482.   subS      r1,r1,#1
  483.   bEQ       _last_long_save
  484.   add       r5,r5,r0
  485.   mov       r6,r5,lsr #17           ; 6th.
  486.   bicS      r6,r6,#&3
  487.   addNE     r6,r11,r6
  488.   strNE     r6,[r3],#4
  489.   bicNE     r5,r5,#&3f80000
  490.   mov       r6,r5,lsr #16
  491.   add       r6,r8,r6,lsl #9
  492.   str       r6,[r3],#4
  493.   add       r6,r9,#20<<7            ; r6='add r5,r5,r4,ror #20'.
  494.   str       r6,[r3],#4
  495.   subS      r1,r1,#1
  496.   bEQ       _last_long_save
  497.   add       r5,r5,r0
  498.   mov       r6,r5,lsr #17           ; 7th.
  499.   bicS      r6,r6,#&3
  500.   addNE     r6,r11,r6
  501.   strNE     r6,[r3],#4
  502.   bicNE     r5,r5,#&3f80000
  503.   mov       r6,r5,lsr #16
  504.   add       r6,r8,r6,lsl #9
  505.   str       r6,[r3],#4
  506.   add       r6,r9,#24<<7            ; r6='add r5,r5,r4,ror #24'.
  507.   str       r6,[r3],#4
  508.  
  509. ._last_long_save
  510.   str       r12,[r3],#4             ; Generate 'str r5,[r0],#-4'.
  511.  
  512. ._the_end
  513.   str       r14,[r3],#4             ; Generate the 'mov pc,r14'
  514.   ldmfd     r13!,{r0-r12,pc}
  515.  
  516. ; >-------------------------------------------------------------------------<
  517. ; The case where the zoomed image is contained in one long is not
  518. ; implemented because it is dull. Not hard to do anyway...
  519. ._only_one_long
  520.   str       r14,[r3],#4             ; Generate 'mov pc,r14'.
  521.   ldmfd     r13!,{r0-r12,pc}
  522.  
  523. ; >-------------------------------------------------------------------------<
  524. ; This contains all the opcodes used in the zoomer routine.
  525. ._opcodes
  526.   sub       r0,r0,#0
  527.   dcd       $e1a05064               ; 'mov r5,r4,ror #0'.
  528.   and       r5,r2,r3,lsl #0
  529.   and       r4,r2,r3,lsl #0
  530.   dcd       $e0855064               ; 'add r5,r5,r4,ror #0'.
  531.   add       r5,r5,r4,ror #4
  532.   ldr       r3,[r1,#0]!
  533.   str       r5,[r0],#-4
  534.   mov       pc,r14
  535.  
  536. .zoom_routine
  537.   ldr       r3,[r1]                 ; Always the first instruction.
  538.   dbd       320*4
  539.