home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / sysext / da / insect.sit / Insect.asm < prev    next >
Assembly Source File  |  1989-05-15  |  16KB  |  623 lines

  1.  
  2. ;    This is the crawling insect DA, disassembled and tweaked.
  3. ;    Should work on all kinds of screens now.
  4. ;    Fixed crashes due to calling _Random in VBL with invalid A5.
  5. ;    Added option-open and cmd-opt-open features to kill bugs.
  6.  
  7. ;    E.M.Vishniac
  8. ;    P.O. Box 1357
  9. ;    East Arlington, MA 02174
  10.  
  11. ;    March 7, 1987
  12.  
  13. ;    Thanks to MacNosy for invaluable assistance.
  14.  
  15. ;    When opened, the crawling insect DA starts a bug working its way
  16. ;    up the screen.  Opening the DA repeatedly creates more bugs.
  17. ;    Option-opening the DA kills one bug (the youngest).
  18. ;    Command-option-opening the DA kills all the bugs.
  19.  
  20. ;    Though the DA is useless, except for laughs, it is an interesting
  21. ;    example of a VBL task.
  22.  
  23. ; A lesson:
  24. ;    The original Insect DA crashed at Random times.  The
  25. ;    reason was that ResetBug calls _Random, which
  26. ;    uses the quickdraw globals.  In a VBL task, A5 may not
  27. ;    be current.  To guard against problems, load A5 with
  28. ;    CurrentA5 in the VBL.
  29. ;    Actually, that's not perfect, since CurrentA5 might
  30. ;    not be valid at some times!  So, we won't use A5 at 
  31. ;    all - we'll use our own Random routine. 5/15/89.
  32.  
  33.     Include    Traps.D
  34.     Include    SysEquX.D
  35.     Include    QuickEquX.D
  36.     Include    ToolEqu.D
  37.     Include    SysErr.D
  38.  
  39. macro    POP    p1 =
  40.     move    (A7)+,{P1}    |
  41.  
  42. macro    POP.L    p1 =
  43.     move.L    (A7)+,{P1}    |
  44.  
  45. macro    PUSH    p1 =
  46.     move    {P1},-(a7)    |
  47.  
  48. macro    PUSH.L    p1 =
  49.     move.L    {P1},-(a7)    |
  50.  
  51.  
  52. jHideCursor    equ    $800    ; address of HideCursor routine
  53.  
  54. BugInterval    equ    7    ; ticks between VBL task runs
  55. BugHeight    equ    16    ; bug is 16 rows high
  56.  
  57.  
  58.     RESOURCE    'DRVR' 31 'Insect' 00
  59.  
  60. Insect
  61.     DC.W    $4F,0,0,0    ; flags, delay, emask, menu
  62.  
  63.     DC.W    Open        ; open routine
  64.     DC.W    Close        ; no prime
  65.     DC.W    Close        ; no control
  66.     DC.W    Close        ; no status
  67.     DC.W    Close        ; no close
  68.                 ; No name?
  69.  
  70.     ; In case someone gets the DA without source code...
  71.     DC.B    '    For source code, send a diskette '
  72.     DC.B    'and a self-addressed, stamped envelope to: '
  73.     DC.B    'Ephraim Vishniac / P.O. Box 1357 '
  74.     DC.B    '/ East Arlington, MA 02174. '
  75.     DC.B    'No postage = no reply.      '
  76.     .align    2
  77.  
  78. ; Starting here, the code and data are copied
  79. ; into the system heap when the DA is opened.
  80.  
  81. BugBase
  82.     DC.B    'BUG '        ; signature
  83.  
  84.  
  85. MyVBLTask
  86.     DC.L    0        ; qLink
  87.     DC.W    1        ; qType
  88.     DC.L    0        ; vblAddr
  89.     DC.W    BugInterval    ; vblCount
  90.     DC.W    0        ; vblPhase
  91.  
  92.  
  93. oldHide        DC.L    0    ; jHideCursor
  94. oldShow        DC.L    0    ; jShowCursor
  95. oldShield    DC.L    0    ; jShieldCursor
  96.  
  97. ; Here's the local data used by the VBL task.
  98. LocalData    equ    *
  99.  
  100. PaintLoc    equ    *-LocalData
  101.         DC.L    0        ; [long] address to paint bug
  102. Generation    equ    *-LocalData
  103.         DC.W    0        ; [word] bug generation
  104. Saved        equ    *-LocalData
  105.         DC.B    0        ; [byte] We've saved the screen data
  106.         DC.B    0        ; [byte] for aligment
  107. MyScrnBase    equ    *-LocalData
  108.         DC.L    0        ; [long] start of screen bitmap
  109. MyScrnRow    equ    *-LocalData
  110.         DC.W    0        ; [word] size of screen low in bytes
  111. MyScrnRect    equ    *-LocalData
  112.         DC.W    0,0,0,0        ; [rect] screen rectangle
  113.  
  114. ShieldRect    equ    *-LocalData
  115.         DC.W    0,0,0,0        ; [rect] rectangle for ShieldCursor
  116. ShieldReturn    equ    *-LocalData
  117.         DC.L    0        ; [long] return addr from ShieldCursor
  118. ShieldSR    equ    *-LocalData
  119.         DC.W    0        ; [word] SR in ShieldCursor
  120. ScreenData    equ    *-LocalData
  121.         DCB.W    16,0        ; [16 words] saved screen data
  122. RandomSeed    equ    *-LocalData
  123.         DC.L    0        ; [long] seed for random numbers
  124.  
  125.  
  126. ; This is the main bug task, called every BugInterval clock ticks
  127. ; by the VBL manager.
  128.  
  129. MyVBLproc
  130.     Move    SR,-(A7)        ; save status
  131.     OrI    #$100,SR        ; mask off some interrupts. needed?
  132.  
  133.     Lea    MyVBLTask,A0
  134.     Move    #1,vblCount(A0)        ; we might have to defer...
  135.     Tst.B    CrsrBusy        ; Cursor busy?
  136.     Bne    @0            ; exit if so
  137.  
  138.     Move    #BugInterval,vblCount(A0)    ; renew our task
  139.     Bsr    Generate        ; do our stuff
  140.  
  141. @0    Move    (A7)+,SR        ; restore status
  142.     Rts                ; and exit
  143.  
  144.  
  145. ; This routine produces a new generation of the bug.
  146.  
  147. Generate
  148.     MoveM.L    D7/A2-A4,-(A7)        ; save registers
  149.  
  150.     Lea    LocalData,A4
  151.  
  152.     Move    CrsrState,D7        ; D7 = Cursor state
  153.     Tst.L    (A4)            ; anything doing?
  154.     Beq    @3            ; exit if not
  155.  
  156.     Bsr    DoOldHide        ; hide the cursor
  157.  
  158.     Bsr    PaintOverBug        ; restore the screen
  159.  
  160.     Move    Generation(A4),D0    ; D0.W = bug generation
  161.     AddQ    #1,D0            ; increment generation
  162.     CmpI    #6,D0            ; there are six generations
  163.     Bne    @1            ; skip if not wrapped
  164.     Clr    D0            ; else wrap to zero
  165. @1    Move    D0,Generation(A4)    ; update generation
  166.  
  167.     Move.L    (A4),A0            ; A0 = place to paint
  168.     Sub.W    MyScrnRow(A4),A0    ; previous row
  169.     Move.L    A0,(A4)            ; update
  170.  
  171.     CmpA.L    MyScrnBase(A4),A0    ; off top?
  172.     Bge    @2            ; skip if not
  173.     Bsr    ResetBug        ; else pick a new location
  174.  
  175. @2    Bsr    DrawBugPlus        ; Draw bug if cursor wasn't obscure
  176.  
  177.     Bsr    DoOldShow        ; show the cursor
  178.  
  179. @3    MoveM.L    (A7)+,D7/A2-A4        ; restore registers
  180.     MoveQ    #0,D0            ; and end update
  181.     Rts
  182.  
  183.  
  184. ; This substitute for HideCursor makes sure that the bug is hidden
  185. ; whenever the cursor is hidden.
  186.  
  187. MyHide
  188.     Move    SR,-(A7)        ; simulate exception
  189.     OrI    #$100,SR        ; disable some interrupts
  190.  
  191.     Bsr    DoOldHide        ; hide the cursor
  192.  
  193.     MoveM.L    D0-D1/A0-A4,-(A7)    ; save registers
  194.  
  195.     Lea    LocalData,A4        ; We hide when the cursor hides
  196.     Tst.L    (A4)            ; are we active?
  197.     Beq    @1            ; exit if not
  198.  
  199.     Bsr    PaintOverBug        ; restore the screen
  200.  
  201. @1    MoveM.L    (A7)+,D0-D1/A0-A4    ; restore registers
  202.     Move    (A7)+,SR        ; restore status register
  203.     Rts
  204.  
  205. DoOldHide
  206.     Push.L    oldHide        ; run the original HideCursor
  207.     Rts
  208.  
  209.  
  210. ; This substitute for ShowCursor makes sure that the bug is visible
  211. ; whenever the cursor is visible.
  212.  
  213. MyShow
  214.     Move    SR,-(A7)        ; simulate exception
  215.     OrI    #$100,SR        ; disable interrupts
  216.  
  217.     MoveM.L    D0-D1/A0-A4,-(A7)    ; save registers
  218.     Lea    LocalData,A4
  219.     Tst.L    (A4)            ; are we active?
  220.     Beq    @2            ; exit if not
  221.     Move    CrsrState,D0        ; D0 = Cursor State
  222.     Beq    @1            ; branch if State = Visible
  223.     CmpI    #-1,D0            ; State = obscure?
  224.     Bne    @2            ; exit if not
  225.  
  226. @1    Bsr    DrawBug            ; cursor state is Visible or Obscure
  227.  
  228. @2    MoveM.L    (A7)+,D0-D1/A0-A4    ; restore registers
  229.     Bsr    DoOldShow        ; restore cursor
  230.     Move    (A7)+,SR        ; restore SR
  231.     Rts
  232.  
  233. DoOldShow
  234.     Push.L    oldShow        ; run the original ShowCursor
  235.     Rts
  236.  
  237.  
  238. ; This substitute for ShieldCursor does for the bug what
  239. ; ShieldCursor does for the cursor.
  240.  
  241. vak_1    EQU    4
  242. param2    EQU    8
  243. param1    EQU    12
  244.  
  245. MyShield
  246.     Link    A6,#0
  247.     Push.L    A4
  248.     Lea    LocalData,A4
  249.     Move    SR,ShieldSR(A4)            ; save SR
  250.     OrI    #$100,SR
  251.     Move.L    vak_1(A6),ShieldReturn(A4)    ; save return address
  252.     Move.L    param2(A6),ShieldRect(A4)    ; save rectangle
  253.     Move.L    param1(A6),ShieldRect+4(A4)
  254.     Pop.L    A4        ; end use of local vars
  255.     UnLk    A6
  256.  
  257.     AddQ.L    #4,A7        ; trash return address so ShieldCursor can work
  258.  
  259.     Bsr    DoOldShield        ; shield the cursor
  260.  
  261.     MoveM.L    D0-D1/A1-A4,-(A7)    ; save regs
  262.     Lea    LocalData,A4
  263.     Tst.L    (A4)            ; are we active?
  264.     Beq    @2            ; exit if not
  265.  
  266.     Bsr    GetBugRect        ; get bug rectangle on stack
  267.  
  268.     Move    (A7),D0            ; D0 = bug bottom
  269.     Cmp.W    ShieldRect+4(A4),D0    ; compare to ShieldRect top
  270.     Ble    @1            ; exit if bug's clear above
  271.  
  272.     Move    2(A7),D0        ; D0 = bug right
  273.     Cmp.W    ShieldRect+6(A4),D0    ; compare to ShieldRect left
  274.     Ble    @1            ; exit if bug's clear left
  275.  
  276.     Move    4(A7),D0        ; D0 = bug top
  277.     Cmp.W    ShieldRect(A4),D0    ; compare to ShieldRect bottom
  278.     Bge    @1            ; exit if bug's clear below
  279.  
  280.     Move    6(A7),D0        ; D0 = bug left
  281.     Cmp.W    ShieldRect+2(A4),D0    ; compare to ShieldRect right
  282.     Bge    @1            ; exit if bug's clear right
  283.  
  284.     ; Bug's in the affected rectangle
  285.     Bsr    DoOldHide        ; hide the cursor
  286.     Bsr    PaintOverBug        ; restore the screen
  287.     Bsr    DoOldShow        ; restore the cursor
  288.  
  289. @1    AddQ.L    #8,A7            ; remove rect from stack
  290. @2    MoveA.L    ShieldReturn(A4),A0    ; A0 = return address
  291.     Move    ShieldSR(A4),SR        ; restore SR
  292.     MoveM.L    (A7)+,D0-D1/A1-A4    ; restore registers
  293.     Jmp    (A0)
  294.  
  295. DoOldShield
  296.     Push.L    oldShield        ; call old ShieldCursor
  297.     Rts
  298.  
  299.  
  300. ; Construct the Rect for the bug's current location and return it
  301. ; on the stack, of all places.
  302.  
  303. GetBugRect
  304.     Pop.L    A0            ; A0 = return address
  305.     Move.L    (A4),D1            ; D1 = place to paint screen
  306.     Sub.L    MyScrnBase(A4),D1    ; D1 = screen offset
  307.     DivU    MyScrnRow(A4),D1    ; D1.W = row; high word = column
  308.     Move    D1,D0            ; D0.W = row
  309.     Swap    D1            ; low word = column byte
  310.     Ext.L    D1            ; D1 = left edge, byte offset
  311.     LSL    #3,D1            ; D1 = left edge, bit offset
  312.     Push    D1            ; push for caller
  313.     AddI    #16,D1            ; D1 = right edge, bit offset
  314.  
  315.     Ext.L    D0            ; D0 = top edge, row number
  316.     Push    D0            ; push for caller
  317.     AddI    #16,D0            ; D0.L = bottom edge, row #
  318.     Push    D1            ; push right edge
  319.     Push    D0            ; push bottom edge
  320.     Jmp    (A0)            ; return with Rect on stack
  321.  
  322.  
  323. ; Pick a starting location for the bug and reset the bug generation.
  324.  
  325. ResetBug
  326.     Clr    -(A7)            ; for random number
  327.     Bsr    MyRandom        ; random number generator
  328.     Clr.L    D0            ; clear high word
  329.     Pop    D0            ; D0.W = random number
  330.     DivU    MyScrnRow(A4),D0    ; pick random column
  331.     Swap    D0            ; D0.W = some random column
  332.     BClr    #0,D0            ; force word alignment
  333.     Ext.L    D0
  334.     Add.L    MyScrnBase(A4),D0    ; add start of screen
  335.     Move.W    MyScrnRect+botRight(A4),D1    ; depth of screen
  336.     Sub.W    #16,D1            ; less height of bug
  337.     MulU    MyScrnRow(A4),D1    ; offset that many bytes
  338.     Add.L    D1,D0            ; screen + lines
  339.     Move.L    D0,(A4)            ; save as place to paint
  340.     Clr    Generation(A4)        ; start at first generation
  341.     Rts
  342.  
  343.  
  344. ; Save the screen image which would be covered by the bug.
  345.  
  346. SaveUnderBug
  347.     Lea    ScreenData(A4),A0    ; A0 = pointer to screen data area
  348.     MoveA.L    (A4),A1            ; A1 = place to paint bug
  349.  
  350.     Move    #BugHeight-1,D1
  351. @1    Move    (A1),(A0)+        ; save a long
  352.     AddA.W    MyScrnRow(A4),A1    ; next row
  353.     DBra    D1,@1            ; all the rows
  354.     Rts
  355.  
  356.  
  357. ; Draw the bug if the cursor is not obscured.
  358.  
  359. DrawBugPlus
  360.     Tst.B    D7            ; cursor obscure? (obscure = -1)
  361.     Bpl    DrawBug            ; branch if visible or nested
  362.     Rts                ; exit if obscure
  363.  
  364. ; Draw the bug if it's not drawn already.
  365. ; (Previously saved screen data means the bug is out there.)
  366.  
  367. DrawBug
  368.     BSet.B    #0,Saved(A4)        ; saved screen data?
  369.     Bne    @2            ; exit if already saved
  370.  
  371.     Bsr    SaveUnderBug        ; save screen data
  372.  
  373.     Lea    BugImages,A0
  374.     Lea    BugMasks,A2
  375.     Move    Generation(A4),D0    ; D0.W = bug generation
  376.     Ext.L    D0            ; D0.L = ditto
  377.     ASL    #5,D0            ; generation * 32
  378.     AddA.L    D0,A0            ; offset into bug images
  379.     AddA.L    D0,A2            ; offset into bug masks
  380.     MoveA.L    (A4),A1            ; A1 = place to paint
  381.  
  382.     Move    #BugHeight-1,D1
  383. @1    Move    (A2)+,D0        ; fetch mask
  384.     Not    D0
  385.     And    D0,(A1)
  386.     Move    (A0)+,D0        ; fetch image
  387.     Eor    D0,(A1)
  388.     AddA.W    MyScrnRow(A4),A1    ; next row
  389.     DBra    D1,@1
  390. @2    Rts
  391.  
  392.  
  393. ; Restore the screen data that the bug stepped on.
  394.  
  395. PaintOverBug
  396.     BClr.B    #0,Saved(A4)        ; Screen saved before? (It's not now.)
  397.     Beq    @2            ; exit if no screen data
  398.  
  399.     Lea    ScreenData(A4),A0    ; A0 = pointer to saved screen data
  400.     MoveA.L    (A4),A1            ; A1 = place to start painting on screen
  401.  
  402.     Move    #BugHeight-1,D1
  403. @1    Move    (A0)+,(A1)        ; copy a word
  404.     AddA.W    MyScrnRow(A4),A1    ; skip to next row
  405.     DBra    D1,@1            ; and copy them all
  406. @2    Rts
  407.  
  408. ; Generate a random number.  This is stolen from the Mac Plus ROM code.
  409. ; Instead of using the QD global seed, it uses one from our local vars.
  410.  
  411. MyRandom
  412.     Move.W    #$41A7,D0
  413.     Move.W    D0,D2
  414.     Mulu.W    RandomSeed+2(A4),D0
  415.     Move.L    D0,D1
  416.     Clr.W    D1
  417.     Swap    D1
  418.     Mulu.W    RandomSeed(A4),D2
  419.     Add.L    D1,D2
  420.     Move.L    D2,D1
  421.     Add.L    D1,D1
  422.     Clr.W    D1
  423.     Swap    D1
  424.     Andi.L    #$FFFF,D0
  425.     Subi.L    #$7FFFFFFF,D0
  426.     Andi.L    #$7FFF,D2
  427.     Swap    D2
  428.     Add.L    D1,D2
  429.     Add.L    D2,D0
  430.     Bpl.S    @0
  431.     Addi.L    #$7FFFFFFF,D0
  432. @0    Move.L    D0,RandomSeed(A4)
  433.     Cmpi.W    #$8000,D0
  434.     Bne.S    @1
  435.     Clr.W    D0
  436. @1    Move.W    D0,4(A7)
  437.     Rts
  438.  
  439. ; Here's the actual bug data.
  440. ; First are the bug images, then the bug masks.
  441. ; There are six sets of data for six bug generations.
  442. BugImages
  443.     DC.L    $00102010,$11A00E40,$02400181,$8662781C
  444.     DC.L    $08100811,$781E8810,$0810381E,$442183C0
  445.  
  446.     DC.L    $20041008,$09900660,$02400180,$0661781E
  447.     DC.L    $88108810,$781E0811,$8810781C,$042203C1
  448.  
  449.     DC.L    $08000804,$05880270,$02408180,$4660381E
  450.     DC.L    $08110811,$781E8810,$0811781E,$842003C0
  451.  
  452.     DC.L    $20001000,$09800678,$02440181,$8662781C
  453.     DC.L    $08108810,$781E0811,$0810381E,$442183C0
  454.  
  455.     DC.L    $00002004,$11880E70,$02400180,$0661781E
  456.     DC.L    $88100811,$781E8810,$8810781C,$042203C1
  457.  
  458.     DC.L    $00040008,$01901E60,$22408180,$4660381E
  459.     DC.L    $08118810,$781E0811,$0811781E,$842003C0
  460.  
  461. BugMasks
  462.     DC.L    $00102010,$11A00FC0,$03C00181,$87E27FFC
  463.     DC.L    $0FF00FF1,$7FFE8FF0,$0FF03FFE,$47E183C0
  464.  
  465.     DC.L    $20041008,$099007E0,$03C00180,$07E17FFE
  466.     DC.L    $8FF08FF0,$7FFE0FF1,$8FF07FFC,$07E203C1
  467.  
  468.     DC.L    $08000804,$058803F0,$03C08180,$47E03FFE
  469.     DC.L    $0FF10FF1,$7FFE8FF0,$0FF17FFE,$87E003C0
  470.  
  471.     DC.L    $20001000,$098007F8,$03C40181,$87E27FFC
  472.     DC.L    $0FF08FF0,$7FFE0FF1,$0FF03FFE,$47E183C0
  473.  
  474.     DC.L    $00002004,$11880FF0,$03C00180,$07E17FFE
  475.     DC.L    $8FF00FF1,$7FFE8FF0,$8FF07FFC,$07E203C1
  476.  
  477.     DC.L    $00040008,$01901FE0,$23C08180,$47E03FFE
  478.     DC.L    $0FF18FF0,$7FFE0FF1,$0FF17FFE,$87E003C0
  479.  
  480. StaticSize    equ    *-MyVBLProc    ; size of non-variable stuff
  481. FullSize    equ    *-BugBase    ; size of everything
  482.  
  483. ; Open: Install the bug in the system heap, hook it into the cursor
  484. ;    routines, and put it in the VBL queue.
  485.  
  486. Open    MoveM.L    A3-A5/D7,-(A7)        ; save registers
  487.     Move.L    CurrentA5,A5        ; make sure A5 is OK
  488.  
  489.     ; Why are we here?
  490.     Link    A6,#-evtBlkSize        ; space for event record
  491.     Clr.W    -(A7)            ; for event-avail result
  492.     Clr.W    -(A7)            ; we want no events!
  493.     Pea    -evtBlkSize(A6)        ; our event block
  494.     _EventAvail            ; see what's going down
  495.     Tst.W    (A7)+            ; toss result
  496.     Move.W    evtMeta(A7),D7        ; save modifiers
  497.     UnLk    A6            ; discard event record
  498.     BTst.L    #optionKey,D7        ; option key down?
  499.     Bne    KillBug            ; if so, go kill a bug
  500.  
  501.     ; No option key, so it's time to spawn a bug
  502.     ; Get some sysheap space
  503.     Move.L    #FullSize,D0        ; stuff to copy into sysheap
  504.     Move.L    D0,D4
  505.     _NewPtr ,SYS+CLEAR    ; (D0/byteCount:Size):A0\Ptr
  506.     Tst    D0            ; got the storage?
  507.     Bmi    com_2            ; beep if error
  508.  
  509.     ; A0 = our pointer in SysHeap
  510.     Move.L    A0,A3            ; save our pointer
  511.  
  512.     ; save the addresses of the cursor routines
  513.     Lea    jHideCursor,A0        ; A0 = addr of jHideCursor
  514.     Lea    oldHide,A1        ; our storage for old hooks
  515.     Move.L    (A0)+,(A1)+        ; jHideCursor
  516.     Move.L    (A0)+,(A1)+        ; jShowCursor
  517.     Move.L    (A0),(A1)        ; jShieldCursor
  518.  
  519.     ; initialize bug's local data
  520.     Lea    LocalData,A4        ; A4 = local data for bug
  521.     
  522.     Move.L    Time,RandomSeed(A4)    ; seed our number generator
  523.  
  524.     Move.L    (A5),A1            ; A1 = qd globals
  525.     Push.L    thePort(A1)        ; save current port
  526.  
  527.     Link    A6,#-GrafSize        ; space for a GrafPort
  528.     Push.L    A7            ; our GrafPort
  529.     _OpenPort            ; get a full-screen port
  530.     Move.L    portBits+BaseAddr(A7),MyScrnBase(A4)
  531.                     ; start of screen
  532.     Move.W    portBits+RowBytes(A7),MyScrnRow(A4)
  533.                     ; bytes in row
  534.     Move.L    portBits+bounds+topLeft(A7),MyScrnRect(A4)
  535.     Move.L    portBits+bounds+botRight(A7),MyScrnRect+4(A4)
  536.                     ; the screen's rectangle
  537.     Push.L    A7            ; our short-lived GrafPort
  538.     _ClosePort            ; say goodbye!
  539.     UnLk    A6            ; restore stack
  540.  
  541.     _SetPort            ; restore user's port
  542.  
  543.     Jsr    ResetBug        ; set bug's starting point
  544.  
  545.     ; copy the essential stuff into our sysheap block
  546.     MoveA.L    A3,A1            ; A1 = our sysheap pointer
  547.     Lea    BugBase,A0
  548.     Move.L    D4,D0            ; D0 = our pointer's length
  549.     _BlockMove    ; (A0/srcPtr, A1/destPtr:Ptr; D0/byteCount:Size)
  550.  
  551.     ; replace the cursor hooks with our own
  552.     Lea    jHideCursor,A0        ; A0 = addr of jHideCursor
  553.     Lea    MyHide-BugBase(A3),A1    ; our HideCursor
  554.     Move.L    A1,(A0)+        ; replace jHideCursor
  555.     Lea    MyShow-BugBase(A3),A1    ; our ShowCursor
  556.     Move.L    A1,(A0)+        ; replace jShowCursor
  557.     Lea    MyShield-BugBase(A3),A1    ; our ShieldCursor
  558.     Move.L    A1,(A0)            ; replace jShieldCursor
  559.  
  560.     ; start our VBL task
  561.     Lea    MyVBLTask-BugBase(A3),A0    ; A0 = MyVBLTask
  562.     Lea    MyVBLproc-BugBase(A3),A1    ; A1 = MyVBLproc
  563.     Move.L    A1,vblAddr(A0)        ; set VBL procedure
  564.     _VInstall    ; (A0/VBLTaskPtr:QElemPtr):D0\OSErr
  565. Feature
  566. OpenExit
  567.     MoveM.L    (A7)+,A3-A5/D7        ; restore registers
  568.     Move.W    #OpenErr,D0        ; return an error (we're not open)
  569.     Rts
  570.  
  571. ;-refs - Open
  572.  
  573. com_2    Push    #15            ; give a beep!
  574.     _SysBeep ; (duration:INTEGER)
  575.     Bra    OpenExit
  576.  
  577. ; Let's kill a bug!
  578. KillBug
  579.     Move.L    jHideCursor,A3        ; A3 = HideCursor routine
  580.     CmpI.L    #'BUG ',BugBase-MyHide(A3)    ; check signature
  581.     Bne    Feature            ; branch if not a bug
  582.  
  583.     Lea    MyVBLProc-MyHide(A3),A0    ; start of static stuff
  584.     Lea    MyVBLProc,A1        ; compare to our copy
  585.     Move.W    #StaticSize-1,D0    ; bytes to check
  586. @0    CmpM.B    (A0)+,(A1)+        ; compare
  587.     Bne    Feature            ; exit if not our bug
  588.     DBra    D0,@0
  589.  
  590.     ; It looks like one of our bugs.  Kill it.
  591.     Lea    MyVBLTask-MyHide(A3),A0    ; our task pointer
  592.     _VRemove            ; stop the bug!
  593.     Bne    com_2            ; exit if error
  594.  
  595.     _HideCursor            ; Hides bugs too!
  596.  
  597.     ; Restore the old cursor routines
  598.     Lea    oldHide-MyHide(A3),A0    ; saved routine pointers
  599.     Lea    jHideCursor,A1        ; where they came from
  600.     Move.L    (A0)+,(A1)+        ; restore old routines
  601.     Move.L    (A0)+,(A1)+
  602.     Move.L    (A0),(A1)
  603.  
  604.     ; Release the memory
  605.     Lea    BugBase-MyHide(A3),A0    ; start of block
  606.     _DisposPtr
  607.  
  608.     _ShowCursor            ; restore cursor state
  609.  
  610.     Push    #5            ; give a beep
  611.     _SysBeep ; (duration:INTEGER)
  612.     Move.L    #10,A0            ; take a break
  613.     _Delay
  614.  
  615.     BTst.L    #cmdKey,D7        ; kill all bugs?
  616.     Bne    KillBug            ; Yes!
  617.  
  618.     Bra    OpenExit        ; else exit
  619.  
  620.  
  621. Close    MoveQ    #0,D0
  622.     Rts
  623.