home *** CD-ROM | disk | FTP | other *** search
/ Carousel Volume 2 #1 / carousel.iso / mactosh / code / p_dissbi.sit / DissBits / dissbytes.a < prev    next >
Encoding:
Text File  |  1985-06-01  |  12.2 KB  |  282 lines  |  [TEXT/MACA]

  1. ;
  2. ;  procedure dissBytes (srcBits, dstBits: bitMap); external;
  3. ;
  4. ; mike morton
  5. ; release: 14 february 1985            (happy birthday, chuck!)
  6. ;
  7. ; version one.  somewhat tested, but not in a wide variety of programs.
  8. ;
  9. ; ******************************************************************************
  10. ; *                                           *
  11. ; *               copyright 1985 by michael s. morton               *
  12. ; *    please see details below on using, copying and changing this source.    *
  13. ; *                                           *
  14. ; ******************************************************************************
  15. ;
  16. ;
  17. ; about dissBytes:
  18. ; ---------------
  19. ;
  20. ; dissBytes copies one whole bitMap to another, moving bytes in a pseudo-random order.  its function is a
  21. ; SUBSET of dissBits', with these restrictions:
  22. ;     -     you must copy an entire bitmap to another of equal size.
  23. ;     -     the bitmap.bounds rectangle must be the full width of the bitmap.  this probably means your
  24. ;     destination bitmap is the whole screen.
  25. ;     -     the bitmap must not contain more than 64k bytes (this should be no problem; the screen is only 21kb).
  26. ; the full screen will dissolve in about 0.3 seconds.  it would be nice to have the effect run a little bit
  27. ; slower, but that shows up the fact that the data are moved a byte at a time, giving an effect like a short
  28. ; burst of bad TV reception.
  29. ;
  30.  
  31. ; sample calling code:
  32. ; -------------------
  33. ;
  34. ; this code is loosely taken from the cursor editor.  it uses three bitmaps, which take up a lot of
  35. ; memory.  one is the real screen; the second saves the original screen while we play; the third has new
  36. ; stuff drawn into it, and is dissolved onto the real screen.  to restore the original stuff, we dissolve
  37. ; from the second to the first.     a real program would more likely generate update events for the affected
  38. ; area.     note that we dissolve the WHOLE screen, and thus we have to copy everything to the third bitmap
  39. ; before we start drawing the things we want to dissolve in.
  40. ; (caveat: this code has been edited a lot from the actual application; it's never really run.)
  41. ;
  42. ;   var
  43. ;      anEvent: eventRecord;                { used to wait for a mousedown }
  44. ;      oldPbits:     bitmap;                { original screen bitmap }
  45. ;      newBits:         bitmap;                { bitmap to draw in between setUpFade and doFade }
  46. ;      savBits:         bitmap;                { bitmap to save the screen in }
  47. ;      dissrect:     rect;                { dissolve rectangle }
  48. ;
  49. ;   dissrect := theport^.portbits.bounds;       { steal the screen bounds }
  50. ;   newBits := thePort^.portbits.bounds;        { and, in fact, the whole bitmap }
  51. ;   newBits.baseAddr := qdptr(newptr(            { except the base address points to this new storage }
  52. ;                newBits.rowbytes*(dissrect.bottom-dissrect.top))); { width times height }
  53. ;   savBits := newBits;                    { temp for old screen looks just the same... }
  54. ;   savBits.baseAddr := qdptr(newptr(
  55. ;                savBits.rowbytes*(dissrect.bottom-dissrect.top))); { ...but has yet another bitmap }
  56. ;   oldPbits := thePort^.portBits;            { remember where the screen is }
  57. ;   setPortBits (newBits);                { but for now, we draw in here }
  58. ;
  59. ;   copyBits (oldPbits, newBits, dissrect, dissrect, srcCopy, nil); { copy the original screen here }
  60. ;   copyBits (oldPbits, savBits, dissrect, dissrect, srcCopy, nil); { and save a copy which we won't trash }
  61. ;
  62. ;       (*** do all the drawing you want here; it'll go to the offscreen bitmap "newBits". ***)
  63. ;
  64. ;   dissBytes (newBits, oldPbits)            { put new stuff on screen, slowly }
  65. ;   flushEvents (mDownMask+keyDownMask, 0);     { ignore mousedowns from during the dissolve }
  66. ;   repeat until getnextevent(mDownMask+keyDownMask,anevent); { wait for them to click or type }
  67. ;   dissBytes (savBits, oldPBits)            { restore the screen, also slowly }
  68. ;
  69. ;   disposPtr (ptr(newBits.baseAddr));            { toss stuff we drew }
  70. ;   disposPtr (ptr(savBits.baseAddr));            { and space we used to save the original screen }
  71. ;   setPortBits (oldPbits);                { go back to drawing on the real screen }
  72. ;
  73.  
  74. ;
  75. ; duplication and use of this routine:
  76. ; -----------------------------------
  77. ;
  78. ; this is freeware.  you're welcome to copy it and use it in programs.  you're welcome to modify it, as long
  79. ; as you leave everything up until this section unchanged.  you're welcome to port it to other machines;
  80. ; i'd appreciate hearing about efforts to do this.
  81. ;
  82. ; if you use it for profit, i ask that you pay for my work.  why?
  83. ;
  84. ;       o if you have problems using it, i'll try to help you debug it.
  85. ;       o i'll send you improved, debugged, faster versions.
  86. ;       o i'll tell you about future products.
  87. ;
  88. ; how much should you pay?  my suggestion is:
  89. ;       (cost of one copy of the program) * (log10 of number of copies sold)
  90. ; if the subroutine is an integral part of your program, double the amount.
  91. ; if it's a frill (e.g., you dissolve in your "About MacWhatever"), halve it.
  92. ;
  93. ; i find it hard to believe that any damages to you or anyone else could come from
  94. ; bugs in this routine.     but, alas, whether or not you pay me, alas, i can't be
  95. ; liable in any way for any problems in it.
  96. ;
  97. ; send comments, contributions, criticisms, or whatever to:
  98. ;       mike morton
  99. ;       6 blackwood street, #102
  100. ;       boston, mass.  02115
  101. ; if you'd like to hear about what else i've produced (as of this writing, it's not a whole lot), send a
  102. ; self-addressed, stamped envelope to the address above.
  103. ;
  104.  
  105. ;
  106. ;       -- end of introduction; real stuff starts here --
  107. ;
  108.  
  109. ;
  110. ; include files:
  111. ;       tlasm/graftypes -- definitions of "bitMap" and "rect"
  112. ;       tlasm/quickmacs -- macros for quickdraw calls (e.g., _hidecursor)
  113. ;
  114.  
  115. .nolist
  116. .include tlasm/graftypes
  117. .include tlasm/quickmacs
  118. .list
  119.  
  120. ;
  121. ; copy one bitmap to another.  the bitmap must be contiguous (i.e., the bounds rect
  122. ; must be as wide as "rowbytes"), the bitmaps must be the same size, and the number of bytes in the
  123. ; bitmap must be under 64k.  if any of these conditions aren't met, the routine returns WITHOUT
  124. ; DOING ANYTHING.
  125. ;
  126.  
  127. .proc   dissBytes
  128.         link A6,#0                ; set up an empty stack frame (no local storage)
  129.         movem.l D3/A2,-(A7)            ; save registers for our caller
  130.  
  131.         move.l 8(A6),A1                ; point to destination bitmap with A1
  132.         move.l 12(A6),A0            ; and to the source bitmap with A0
  133.  
  134. ;
  135. ; check that the bitmaps match in size:
  136. ;
  137.  
  138.         move.w bounds+bottom(A0),D0     ; pick up source.bounds.bottom
  139.         sub.w bounds+top(A0),D0            ; find (source.bounds.bottom-source.bounds.top)
  140.         swap D0                    ; cache that in the top half of D0
  141.         move.w bounds+right(A0),D0      ; and find (source.bounds.right...
  142.         sub.w bounds+left(A0),D0        ; ...-source.bounds.left)
  143.  
  144.         move.w bounds+bottom(A1),D1     ; pick up dest.bounds.bottom
  145.         sub.w bounds+top(A1),D1            ; find (dest.bounds.bottom-dest.bounds.top)
  146.         swap D1                    ; cache that in the top half of D1
  147.         move.w bounds+right(A1),D1      ; and find (dest.bounds.right...
  148.         sub.w bounds+left(A1),D1        ; ...-dest.bounds.left)
  149.  
  150.         cmp.l D0,D1                ; do height and width of rectangles match?
  151.         bne.s noBytes                ; nope -- can't handle this
  152.  
  153.         move.w rowbytes(A0),D2            ; pick up bytes-per-row in D2
  154.         cmp.w rowbytes(A1),D2            ; do they match?
  155.         bne.s noBytes                ; nope -- they must for us to copy
  156.  
  157.         move.w D2,D3                ; set byte count aside in D3
  158.         lsl.w #3, D2                ; turn byte count into bit (pixel) count
  159.         cmp.w D2,D0                ; compare against width of both bounds rects
  160.         bne.s noBytes                ; bounds rect must span the whole bitmap!
  161.  
  162.         swap D1                    ; bring rect height to D1.w
  163.         mulu D1,D3                ; multiply width in bytes times height to find bytes in the rectangle
  164.         move.l D3,D0                ; copy that to D0 so we can...
  165.         bsr log2                ; convert byte count per rect to ceil(log2(byte count)) in D0.w
  166.         swap D3                    ; now make sure that the number of bits fits in a word...
  167.         tst.w D3                ; like so
  168.         bne.s noBytes                ; sorry, too large; i want to use word ops in the main loop
  169.         swap D3                    ; now put D3 back
  170.  
  171.         lsl.w #2,D0                ; make the table stride right [sic?] (longwords)
  172.         lea TABLE,A2                ; point to the table of XOR masks
  173.         move.l 0(A2,D0.w),D1            ; grab the correct magic mask in D1
  174.  
  175.         move.l D1,D2                ; 1st sequence element is the mask itself
  176.  
  177.         move.l baseAddr(A0),A0            ; pick up a pointer to the actual source stuff
  178.         move.l baseAddr (A1),A1            ; and to the target (most likely the screen)
  179.         _hideCurs                ; don't let the cursor get in our way
  180.         bra.s BYTELP                ; jump into the loop
  181.  
  182. ; register usage for the loop:
  183. ;       D1 is the magic XOR mask to generate the sequence
  184. ;       D2 is the current sequence element
  185. ;       D3 is the number of bytes in the bitmap (1 more than the highest byte offset)
  186. ;       A0 points to the source bitmap's data
  187. ;       A1 points to the destination bitmap's data
  188.  
  189. BYTESEQ
  190.         eor.w D1,D2                ; go to the next sequence element
  191. BYTELP
  192.         cmp.w D2,D3                ; is D2 within the range (1..D3-1)?
  193.         ble.s BYTENEXT                ; nope: don't copy this byte
  194. BYTECOPY
  195.         move.b 0(A0,D2.w),0(A1,D2.w)    ; copy D2'th byte from A0's data to A1's data
  196. BYTENEXT
  197.         lsr.w #1,D2                ; slide one bit to the right
  198.         bhi.s BYTECOPY                ; if no carry out, but not zero, loop
  199.         bne.s BYTESEQ                ; if carry out, but not zero, loop earlier
  200.  
  201.         move.b (A0),(A1)            ; copy the zero'th element, which the sequence doesn't hit
  202.         _showCurs                ; bring back the cursor (or at least undo one level of hiding)
  203.  
  204. NOBYTES                        ; here when we can't copy
  205.         movem.l (A7)+,D3/A2            ; pop needed registers
  206.         unlk A6                    ; delete our empty stack frame
  207.         move.l (A7)+,A0                ; pop our return
  208.         add.l #8,A7                ; deallocate parameters
  209.         jmp (A0)                ; and return
  210.  
  211.  
  212. ;
  213. ; -----------------------------------------------------------------------------------
  214. ;
  215. ; table of (longword) masks to XOR in strange Knuthian algorithm.  the first table
  216. ; entry is for a bit-width of two, so the table actually starts two longwords before
  217. ; that.     hardware jocks among you may recognize this scheme as the software analog
  218. ; of a "maximum-length sequence generator".
  219. ;
  220.  
  221. table   .equ *-8                ; first element is #2; stride is four bytes
  222. .long   3o                    ; 2
  223. .long   6o                    ; 3
  224. .long   14o                    ; 4
  225. .long   24o                    ; 5
  226. .long   60o                    ; 6
  227. .long   140o                    ; 7
  228. .long   270o                    ; 8
  229. .long   420o                    ; 9
  230. .long   1100o                    ; 10
  231. .long   2400o                    ; 11
  232. .long   6240o                    ; 12
  233. .long   15400o                    ; 13
  234. .long   32400o                    ; 14
  235. .long   60000o                    ; 15
  236. .long   132000o                    ; 16
  237. .long   220000o                    ; 17
  238. .long   402000o                    ; 18
  239. .long   1620000o                ; 19
  240. .long   2200000o                ; 20
  241. .long   5000000o                ; 21
  242. .long   14000000o                ; 22
  243. .long   20400000o                ; 23
  244. .long   66000000o                ; 24
  245. .long   110000000o                ; 25
  246. .long   342000000o                ; 26
  247. .long   710000000o                ; 27
  248. .long   1100000000o                ; 28
  249. .long   2400000000o                ; 29
  250. .long   6240000000o                ; 30
  251. .long   11000000000o                ; 31
  252. .long   24300000000o                ; 32
  253.  
  254. ;
  255. ; -----------------------------------------------------------------------------------
  256. ;
  257. ; log2 -- find the ceiling of the log, base 2, of a number.
  258. ;
  259. ; calling sequence:
  260. ;       move.l N,D0                ; store the number in D0
  261. ;       bsr LOG2                ; call us
  262. ;       move.w D0,...                ; D0 contains the word result
  263. ;
  264. ; registers used: D2, (D0)
  265. ;
  266.  
  267. LOG2
  268.         tst.l D0                ; did they pass us a zero?
  269.         beq.s LOGDONE                ; call log2(0) zero -- what the heck...
  270.         sub.l #1,D0                ; so 2**n works right (sigh)
  271.         beq.s LOGDONE                ; if D0 was one, answer is zero
  272.         move.w #32,D2                ; initialize count
  273. LOG2LP
  274.         lsl.l #1,D0                ; slide bits to the left by one
  275.         dbcs D2,LOG2LP                ; decrement and loop until a bit falls off
  276.  
  277.         move.w D2,D0                ; else save our value where we promised it
  278. LOGDONE                        ; here with final value in D0
  279.         rts                    ; and return
  280.  
  281. .end                        ; procedure dissBytes
  282.