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