TweetFollow Us on Twitter

Globals
Volume Number:2
Issue Number:4
Column Tag:Assembly Language Lab

DA Shows use of Globals and Resources

By Norman Braskat, El Toro, Ca

Desk Accessories from Assembly

Desk accessories are a very basic part of the Macintosh interface and the development of them need not be a major undertaking, if you follow the guidelines in this shell DA. In this month's column, I outline how to develop a desk accessory using assembly language that illustrates how menu items, windows, resources and global storage can be handled within the DA.

Editor's Notes

[This program was written and compiled entirely in assembly using Consulair's C compiler! That's right. If your tired of waiting for Apple to update the MDS assembler system to run under HFS without crashing, here is an alternative. The Consulair C compiler has a built-in MDS assembler that is fully MDS compatible! You simply run it like you would the MDS system. Be sure to get the latest release 4.53. This release includes version 1.53 of the famous Editor. It seems that Consulair went ahead and fixed up their own version of the editor, obtaining 1.53, before working under contract to bring Apple's editor and MDS system up to version 2.0. The result is that Bill's 1.53 editor is more solid and more compatible than the current 2.0d1 beta HFS editor being distributed by Apple to developers. However, when the final 2.0 release becomes released, that will be equivalent to the 1.53 Bill is distributing with Mac C version 4.53. Now if you understood all that, you should have no trouble with this month's column!

The link file shown at the end of the article is for the Mac C linker, which is MDS compatible and it works under HFS on the Mac Plus (the MDS one doesn't). You no longer need to patch or otherwise coerce the MDS linker into launching and finding it's files. The job file shown is also for the Mac C Exec and is the same as it would be under the MDS exec, only the Mac C version works! You can now invoke the job file from the editor and have the assembly, link and execution of a program proceed automatically. In this example, we execute the DA Mover program after linking so we can move the new DA into the system file and test it out. This actually works, although the DA Mover comes up without knowing what file to open. MacTutor is now offering the Consulair Mac C and the linker in our Technical software store for those who want to use it as either an MDS assembler replacement or a C system (still a good C system!) or both. For those who don't need a C system, we are also offering McAssembly which is nearly MDS compatible using a conversion utility and the Consulair Linker by itself. -Ed]

General Desk Accessory Information

To begin, the device manager executes the desk accessory as a procedure call of the following format to one of the five desk accessory procedures: Open, Control, Prime, Status, and Close.

(D0: ResultCode) := DA Procedure(A0: ParamBlock, A1: DCERecord ) 

The 'Open' command is called in response to a _OpenDeskAcc toolbox call and in general performs any initialization required by the desk accessory. When the user selects any DA from the Apple menu, the Finder or application calls _OpenDeskAcc. It should allocate any private storage required by the desk accessory, stores a handle to it in the dCtlStorage field of the DCE record, initializes any local variables, install any interrupt handlers, change interrupt vectors, create any windows, ... ect...

The 'Close' command is called in response to either _CloseDeskAcc toolbox call or by the segment launcher to close all the desk accessories, and in general it should undo what is done by the Open procedure, by releasing all memory used, removing any interrupt handlers, restoring any system state... ect ... If you must keep state between when the desk accessory is closed and later opened, store it in a re-locatable block of memory pointed to by the dCtlStorage field of the DCE record. In practice, 'Close' is called by System Click when the user clicks the go-away box of a system window belonging to a desk accessory, or by the application when the user selects "close" in the File menu for an open DA window. When that happens, storage used by the DA may be released. When a DA menu item 'quit' is called, the DA can do it's normal close function as part of a 'Control' call on the menu event without releasing that storage, thus keeping the variables until a 'Close' call or another 'Open' call. The code for this DA illustrates how this is done. A 'Close' from the go-away box of the DA's window will release the handle to the storage, but a 'Close' from the DA's menu will remove the menu and window without releasing the storage area, thus preserving variables until the next 'Open' call.

The 'PRIME' and 'STATUS' commands are called in response to a _Read, _Write, or _Status trap, and they are not used by desk accessories ( I think ). For cleaness sake I use empty procedures ( RTS's ). These routines would be used by drivers for printers and other I/O type devices.

The 'Control' command performs most of the work done by the desk accessory. It is called in response to one of the functions shown in figure 1 and in general will look like a case statement which decides what to do, and then does the required action. All events are handled as 'Control' calls and in general, any action during an active DA's life is handled as a 'Control' call.

As figure 1 shows, the A0 and A1 pointers allow access to all the information required to determine exactly what operations are requested and to execute them. The A0 register contains the pointer to the parameter block (see figure 3) while the A1 register contains the pointer to the DCE record (see figure 2). And for DA's, the result code returned in D0 should always be zero.

Pic. 1: Our DA does windows, menus...

Pic. 2: And alerts!

Device Control Entry Record

The DCE record (see figure 2 ) contains some information taken from the DA's header, the always present queing infromation, a handle to the DA's storage area, a pointer to the DA's window, and some other control information. Most desk accessorys are only interested in the 'dCtlStorage', 'dCtlRefNum', and the 'dCtlWindow' fields, and in general the rest of the record is only used by drivers and the device manager. Upon entry, A1 holds a pointer to the DCE record and great care must be taken to see that this pointer is preserved throughout the DA. Many DA errors are due to this pointer being clobbered by a trap call.

The dCtlStorage handle allows the desk accessory to have it's own global memory area seperate from the stack. The DA cannot use register A5 since that is used by the underlying application for it's globals. Care must be taken to unlock and deallocate any memory the DA may have when it is closed, since the device manager will not do this for you.

IO Parameter Block

The Parameter block pointed to by A0 (see figure 3) contains the action code and any data passed by the device manager. The csCode contains the action code and will be a value from 64 to 73. The parameter block will contain any data passed. Menu actions will pass the MenuID (28) followed by the MenuItemNum (30).

Support Resources

To use the 'DA MOVER' program for installing your desk accessory it will be necessary to make the resource ID's for alerts, dialogues, pictures, ect.. be a function of the DA's number. The equation used is:

ResurceID := (( DA's number ) x #32) + #$FFFFC000 + index

and

( DA's number ) := (- (DA's RefNum) - #1)

This would have the resources for DA (#12) starting at #-16000, with a maximum of #32. The assembler makes it a bit difficult to code this 16-bit 2's complement number, but I found that using a decimal value of 49536 in the resource header produces the desired equivalent of -16000. (See the resource section of the listing). Also, the DA name should have a null ($0) byte as the first character of the name, but the assembler won't let you do this in the resource header. The resource editor can be used to do this, but as it turns out, the Font/DA mover does it for you when it installs the DA.

Desk Accessory Header Format

The first 9 words of the desk accessory constitute a header and is followed by the DA's title string. Figure 4 defines the structure of the header block. With this information, we can start writting our desk accessory.

In this example, I have coded simple open, control and close procedures to check for and allocate global memory storage via A4. Once this is done, a central 'launch' routine is called that provides a single interface to the DA's major code blocks for open, control and close. The launch routine saves state and calls the three DA routines which then decode the action parameters and perform the necessary actions. When adapting this shell to your own needs, you simply place your open code, control code and close code in the three routines called by launch: OpenDA, MainDA and CloseDA.


; Asm language desk accessory.
;  © March 1986 by Norman Braskat 
; for  MacTutor.
; Extended to windows March 26,1986 
; by David Smith

RESOURCE 'DRVR' 12 'EXAMPLE DA'

INCLUDE MacTraps.D

.trap _DeBug$A9FF

StorageSize EQU   6

; Globals relative to A4 [dCtlStorage]
MenuHandleEQU   0;[long]
ResourceBaseEQU   4;[word]

csCode  EQU 26 ; control/status [word]
csParam EQU 28 ; parameters [20 bytes]
MenuItemNum EQU  30

; DCE item list
dCtlDriverEQU   0
dCtlFlagEQU  4
dCtlQuerEQU  6
dCtlHeadEQU  8
dCtlTailEQU 12
dCtlPositionEQU  16
dCtlStorage EQU  20
dCtlRefNumEQU  24
dCtlCurTicksEQU  26
dCtlWindowEQU  30
dCtlDelay EQU  34
dCtlMaskEQU 36
dCtlMenuEQU 38

; Toolbox equates
WindowKindEQU  $6C ;offset from wind. rec.

; Event parameter block equates from SysEqu
evtNum  EQU  0  ; event [word]
evtMessageEQU   2 ; msg [long]
evtTicks  EQU   6 ; TICKS [long]
evtMouseEQU  10   ; mouse pos.[long]
evtMeta EQU  14   ; meta key flags [byte]
evtMBut EQU  15   ; mouse button [byte]

JIODone  EQU $8FC ; IODone entry [pointer]

; Register Usage
; A0 = ParamBlock ptr, 
; A1 = DCE ptr, 
; A2 = evt table ptr from csParam(A0), 
; A3 = working DCE ptr (after launch) 
; A4 = globals (referenced to dctlstorage),
; A5 = application globals (not used), 
; A6 = frame ptr, 
; A7 = stack ptr.

; Useful Macros

MACRO PUSH value = 
 MOVE {value}, -(A7)
 |
MACRO PUSH.Lvalue=
 MOVE.L {value}, -(A7)
 |
MACRO POP  value =
 MOVE (A7)+, {value}
 |
MACRO POP.L  value =
 MOVE.L (A7)+, {value}
 |
MACRO EnableItem  value =
 MOVE.L MenuHandle(A4), -(A7)
 MOVE  {value}, -(A7)
 _EnableItem
 |
MACRO DisableItem value =
 MOVE.L MenuHandle(A4), -(A7)
 MOVE  {value}, -(A7)
 _DisableItem
 |
;------------------------------------------------------------------------------
; The following defines the desk accessorys resource header.

ENTRY:  DC.W$0400; control flags.
DELAY:  DC.W$0000; Service interval
EventMask:DC.W $0040 ; Event mask.
MenuID: DC.W$FEA1; DA MenuID's 
 DC.W Open - Entry ; Offset to Open
 DC.W Prime - Entry; Offset to Prime   
 DC.W Control - Entry; Offset to Control 
 DC.W Status - Entry ; Offset to Status  
 DC.W Close - Entry; Offset to Close
;--------------------------------------------------------------------------------
MenuTitle:DC.B 7 ;length byte
 DC.B 'Example'  ; menu title
.align 2
; The menu name string
MenuList: DC.B 18; List in bytes
 DC.B 'About;' ; Item #1 title
 DC.B 'Beep;'  ; Item #2 title
 DC.B '-;'; Item #3 title
 DC.B 'Close;' ; Item #4 title
 
Wbounds:DC.W100,100,140,300 ; window bounds
.align 2
;----------------------------------------------------------------
; Desk accessorys don't use Prime and Status

Prime:  RTS
Status: RTS

; The Open procedure allacates the storage area 
; builds the DA's menu list, and opens windows.
; Don't allocate a memory area if one is 
; already allocated.
; 
; The notation I use to document my code is a 
; psudo Alogal followed by the assembly code.
; Open
;BEGAN
;save users port (GetPort)
;IF ( dCtlStorage = #0 )
;     dCtlStorage := NewHandle( StorageSize, Clear )
;Launch( OpenDA )
;restore users port (SetPort)
;END
Open:
 ; Save the application's port because 
 ; the ROM doesn't do it for us on Open.
 push.l A1; Save A1 (DCE ptr.) 
 subq.l #4,SP  ; make room for the port
 move.l SP,-(SP) ; push a pointer to it
 _GetPort ; get it, on top of stack
 POP.L  D6; save port in D6
 pop.L  A1; restore DCE ptr.
 
 TST.L  dCtlStorage(A1) ; Storage allocated?
 BNE  Open_0; yes, skip allocation
 PUSH.L A0; no, Save A0 from wipe-out
 MOVE StorageSize,D0 ; storage handle to A0
 _NewHandle,Clear; get storage, zero block.
 MOVE.L A0, dCtlStorage(A1) ; handle in the DCE
 POP.L  A0; Restore A0 register  
Open_0:
 PEA  OpenDA   ; pointer to OpenDA proc  
 JSR  Launch; passed to launch code. 
 push.l D6; push users port
 _SetPort ; restore users port 
 CLR.L  D0; clear D0 for DA return
 RTS    ; Return to desk manager 
 
; The Control procedure handles most of 
; the work done by the desk accessory.
; If a memory area is not already allocated 
; we should never have been called, so just 
; return to the device manager.  Otherwise, 
; pass the MainDA procedure to the launch 
; code and then do it.

; Control
;BEGAN
;IF (dCtlStorage  #0)
;Launch(MainDA)
;JMP to IODone
;END
Control:
 TST.L  dCtlStorage(A1) ; storage area?
 BEQ  Control_0  ; No, so exit...
 PEA  MainDA   ; yes, pass MainDa function
 JSR  Launch; to the launch code. 
Control_0:; 
 CLR.L  D0; Clear D0 for return  
 MOVE.L JIODone, -(SP)  ; system IODone entry point 
 RTS    ; return to IODone.
 
; The Close procedure removes the DA's menu 
; and in general cleans up after the
; open and control procedures.   
; If a memory area is not already 
; allocated there is nothing to clean 
; up, so return to the device manager.  
; Otherwise, pass the CloseDA  procedure 
; to the launch code and then do it.
; After the returning from the lanch code, 
; deallocate the handle to storage area 
; and return to the device manager. Typically,
; close is only called by the system
; when the go-away box of a window is clicked.

; Close
;BEGAN
;save users port
;IF ( dCtlStorage  #0 )
;Launch( CloseDA )
;DeleteStorageArea
;restore users port
;END
Close:
 push.l A1; save DCE ptr.
 subq.l #4,SP  ; make room for the port
 move.l SP,-(SP) ; push a pointer to it
 _GetPort ; get it, on top of stack
 pop.l  D6; get port in D6
 pop.l  A1; restore DCE ptr.
 
 TST.L  dCtlStorage(A1) ; Storage area allocated?
 BEQ  Close_0  ; no so exit...
 PEA  CloseDA  ; yes, prepare for close
 JSR  Launch; do close stuff...
 MOVE.L dCtlStorage(A1),A0; get storage handle
 clr.l  dCtlStorage(A1)   ; clear handle (must do!)
 _DisposHandle   ; Deallocate handle 
Close_0:
 push.l D6; push port
 _SetPort ; restore users port
 CLR.L  D0; clear D0 for return
 RTS    ; and return to desk manager.
 
;-------------------------------------------------------------
; The Launch proc creates the environment 
; for the execuition of the DA's code.    

; Launch ( &Procedure )
;BEGAN
;SaveState
;A3 := DCE ptr
;A4 :=  [ HLock( dCtlStorage ) ]
;  Procedure
;HUnLock( dCtlStorage )
;RestoreState
;END
Launch:
 LINK A6,#0 ; Link in.
 MOVEM.LD1-D7/A0-A6,-(A7) ; Save register state
 PUSH.L A1; Save pointer to the DCE rec
 PUSH.L A0; Save pointer to param block
 MOVE.L A1, A3 ; move DCE to safe register.
 MOVE.L dCtlStorage(A3), A0 ; get dCtlStorage handle
 _HLock ; lock handle
 MOVE.L (A0),A4  ; A4 is used as the global reg
 POP.L  A0; Restore param block ptr.
 MOVE.L 8(A6),A2 ; get function off A6 stack 
 JSR  (A2); Call the passed procedure.
 POP.L  A1; restore DCE ptr.
 MOVE.L dCtlStorage(A1), A0 ; get storage handle
 _HUnLock ; Unlock handle
 MOVEM.L(A7)+, D1-D7/A0-A6; restore register state.
 UNLK A6; Link out.
 POP.L  A0; get return address
 ADD.L  #4, A7   ; pop off launch param
 JMP  (A0); return to caller
 
;-------------------------------------------------------------------------------

; 'OpenDA' routine installs the menu list 
; in the system bar, refreshes the menu 
; item states, and opens a window. In general, 
; this is where the code that must be 
; execuited on opening is placed.

;OpenDA (called by launch)
;BEGAN
;ResourceBase := #$FFFFC000 or (#32 x (-RefNum -1))
;IF ( MenuHandle   #0 ) 
;        MenuHandle := NewMenu( MenuID, &MenuTitle )
;AppendMenu( MenuHandle, &MenuList )
;InsertMenu( MenuHandle, #0 )
;DrawMenuBar
;RefreshMenu
;IF ( Windowptr   #0 ) 
;Windowptr := NewWindow( .. )
;save windowptr in ctl block
;set window kind to system window
;END
OpenDA:
 MOVE dCtlRefNum(A3),D0 ; DA mover requires  
 NEG  D0; support resources ID for a DA to be 
 SUBQ #1, D0; function of the DA ref. number. Use 
 ASL  #5, D0; value in ResourceBase(A4) for 
 OR#$C000,D0; your supporting resources. 
 MOVE D0,ResourceBase(A4)     ;save resource ID
 
 MOVE.L MenuHandle(A4),D0 ; menu handle?
 BNE  OpenDA_0 ; yes, don't add another.
 CLR.L  -(A7)    ; no, clear space
 PUSH MenuID; Push the MenuID
 PEA  MenuTitle  ; Push menu title ptr
 _NewMenu ; make new menu 
 MOVE.L (A7), MenuHandle(A4)  ; save menu handle. 
 PEA  MenuList ; Push pointer to item list.
 _AppendMenu; Append the menu
 PUSH.L MenuHandle(A4)  ; Push the handle
 CLR  -(A7) ; zero for append  last menu.
 _InsertMenu; insert the menu in the bar.
 _DrawMenuBar  ; Redraw the menu bar.
 
; Now open a window 

 tst.l  DCtlWindow(A3)  ; window open?
 bne.s  OpenDA_0 ; yes, skip this
 
 clr.l  -(SP)  ; room for window pointer
 clr.l  -(SP)  ; window on the heap
 pea  Wbounds  ; pointer to boundsRect
 pea  MenuTitle  ; pointer to title
 clr.w  -(SP)  ; false for visible
 move.w #0,-(SP) ; standard window type
 move.l #-1,-(SP); window in front
 move.w #$0100,-(SP) ; true for goAway box
 clr.l  -(SP)  ; refCon is 0
 _NewWindow ; do the allocation
 move.l (SP)+,A0 ; pop windowPtr off stack
 
; Save the window pointer away in the DCE for future use. 
; The system also uses the DCtlWindow field of the DCE 
; for setting up update events to system windows etc.

 move.l   A0,DCtlWindow(A3) ; save window ptr in DCE
 move.w DCtlRefNum(A3),WindowKind(A0) 

; All drivers, including ornaments, have a negative refnum.  
; The only way an application can know what the refnum 
; of this ornament is is by getting it from the 
; WindowKind field.  Applications must have the 
; refnum to do CloseDeskAcc().

OpenDA_0:
 JSR  RefreshMenu; Refresh the menu states. 
 RTS    ; Return

;---------------------------------------------------------
; The' RefreshMenu' routine, updates the display 
; state of the menu items in the DA's menu. 
; Enabled/Disabled, Checked/UnChecked, ect.  
; Note... The menu manager will not act on a disabled item.

; RefreshMenu
;BEGAN
;IF ( MenuHandle   #0 )   
;EnableItem( #1 )
;EnableItem( #2 )
;DisableItem( #3 )
;EnableItem( #4 )
;END

RefreshMenu:
 TST.L  MenuHandle(A4)  ; must be a menu handle s
 BEQ  RefreshMenu_0; to acces the menu.
 EnableItem #1 ; Enable menu item #1
 EnableItem #2 ; Enable menu item #2
 DisableItem#3 ; Disable menu item #3
 EnableItem #4 ; Enable menu item #4
RefreshMenu_0: 
 RTS

;-------------------------------------------------------------------------------
; This routine will delete the DA's menu, and window 
; and redraw the menu bar. Place your close functions here.

; CloseDA (called by launch)
;BEGAN
;IF ( MenuHandle   #0 )   
;DeleteMenu( MenuID )
;DisposeMenu( MenuHandle )
;IF ( WindowPointer   #0 )  
;Delete dCtlWindow( DCE Ptr )
;DisposeWindow( WindowPointer )
;DrawMenuBar
;END
CloseDA:
 TST.L  MenuHandle(A4)  ; If the menu handle is zero, 
 BEQ  CloseDA_0  ; there is nothing to delete.
 PUSH MenuID
 _DeleteMenu; Delete menu.
 PUSH.L MenuHandle(A4)
 _DisposMenu; Dispose of the menu
 CLR.L  MenuHandle(A4)  ; Zero the handle
 
; close window

 TST.L  DCtlWindow(A3)
 BEQ  CloseDA_0  ; no window to delete
 move.l DCtlWindow(A3),-(SP)  ; push the window ptr
 clr.l  DCtlWindow(A3)  ; clear window ptr
 _DisposWindow ; dispose window
 
CloseDA_0:
 _DrawMenuBar  ; Redraw the bar.
 RTS

;-------------------------------------------------------------------------------
; The MainDA routine looks like a case statement 
; which determines the necessary action and does it. 
; Control requests come here for all events, ect.

; MainDA(called by launch)
;  BEGAN
;CASE of csCODE
;64 : AccEvent
;65 : AccRun
;66 : AccCursor
;67 : AccMenu
;68 : AccUndo
;69 : NotUsed
;70 : AccCut
;71 : AccCopy
;72 : AccPaste
;73 : AccClear
; ELSE :Nop
;  END

;AccMenu
;BEGAN  
;CASE of MenuItemNum
;1: About; HiliteMenu; RefreshMenu;
;2: Beep; HiliteMenu; RefreshMenu;
;4: CloseDA;
;       ELSE : Nop;
;END

MainDA:
 MOVE csCode(A0), D0
 SUB  #64, D0
 ASL  #2, D0
 LEA  JumpTable, A2
 JMP  (A2,D0.W)  ; Case of (csCode(A0)-#64)

JumpTable:
 JMP  AccEvent
 JMP  AccRun
 JMP  AccCursor
 JMP  AccMenu
 JMP  AccUndo
 JMP  NotUsed
 JMP  AccCut
 JMP  AccCopy
 JMP  AccPaste
 JMP  AccClear

AccRun: RTS ;these here are not used
AccCursor:RTS
AccUndo:RTS
NotUsed:RTS
AccCut: RTS
AccCopy:RTS
AccPaste: RTS
AccClear: RTS

AccEvent:

 move.l CSParam(A0),A2  ; get the event pointer
 move.w EvtNum(A2),D0; get the event number
 ; event jump table  goes here
 subq #6,D0 ; is it an update?
 beq.s  Update ; if so, go handle it
 RTS

Update:
 move.l EvtMessage(A2),-(SP); push window ptr
 _BeginUpdate    ; begin the update
 move.l EvtMessage(A2),-(SP); push window ptr
 _SetPort ; set the port to our port
 bsr  DrawWindow ; draw the window
 move.l EvtMessage(A2),-(SP);  window ptr last time
 _EndUpdate ; end the update
 RTS
; --------------------------------------------------
DrawWindow:
 PUSH.L A0; save A0
 move.w #5,-(SP) ; move over 5 horizontal
 move.w #15,-(SP); and 15 vertical
 _MoveTo; do the move
 lea  MenuTitle,A0
 move.l A0,-(SP) ; pointer to the string
 _DrawString
 POP.L  A0; restore A0
 rts    ; done drawing
; ---------------------------------------------------

AccMenu:
 MOVE MenuItemNum(A0), D0
 CMP  #1, D0
 BEQ  MenuItem1
 CMP  #2, D0
 BEQ  MenuItem2
 CMP  #4, D0
 BEQ  MenuItem4
 RTS

MenuItem1:
 JSR  About
 BRA  Exit

MenuItem2:
 JSR  Beep
 BRA  Exit

MenuItem4:
 JSR  CloseDA
 RTS

Exit:   
 CLR  -(A7) ; UnHilite menu
 _HiliteMenu
 JSR  RefreshMenu; Refresh menu item states
 RTS

About:  
 CLR  -(A7)  
 PUSH ResourceBase(A4) 
 CLR.L  -(A7)
 _Alert
 POP  D0;alert parameter
 RTS    

Beep:   
 PUSH #15 ; Beep... 
 _SysBeep
 RTS
;--------------------------------------------------------------------------------
; resource ID numbers must be negative functions of 
; DA ref. number. Note that 49536 = 0000 C180
; which the assembler converts to -16000. Note that
; the assembler converts a 16-bit negative such 
; as -16000 to a 32-bit field, ie FFFF C180, 
; which doesn't work.
RESOURCE 'DITL' 49536 'EXAMPLE DITL'
 DC.W 0 
 DC.L 0
 DC.W 0
 DC.W 0
 DC.W 129
 DC.W 309
 DC.B 8
 DC.B 102
 DC.B 13, 13
DC.B  'This is a example of a MDS desk accessory which uses a menu.'
 DC.B 13, 13
 DC.B '       By Norman Braskat and MacTutor '
.ALIGN 2
RESOURCE 'ALRT' 49536 'EXAMPLE ALRT'
 DC.W $007A
 DC.W $0064
 DC.W $00FA
 DC.W $0186
 DC.W $C1A0
 DC.W $4444
.ALIGN 2
END

Notes from Volume 2 Number 5:

Asm Lab Comments for April

Norman Braskat

Thanks Dave for the Mac C (version 4.53); the built-in assembler works like a champ (Apple MDS really sucks). About the DA example in my Asm Lab article in the April 1986 issue of MacTutor, I recommend placing the save and restore graph port trap calls in the launch routine. This not only saves code, but saves and restores the current port during control calls. The other question I have concerns the set port after the beginUpdate call; Dan Weston's new book [see book review, this issue -Ed] shows it outside the update loop for an application, and inside the loop for a desk accessory as you placed it in my DA example on page 37 of the April issue. I think your way works because the current port is the same as the DA's window. But if we had multiple windows in a DA or we added a menu for clearing a window which was not currently selected, we would be changing the port during an update. Would this then be a problem?

Dave, you have a great publication and the only real source of assembly info around! Keep it up. PS. Your right... Dan's book is a real winner! [The Complete Book of Assembly Language Programming by Dan Weston, published by Scott Foresman & Co. due in bookstores next month. -Ed]

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Adobe After Effects CC 2018 16.1.3 - Cre...
After Effects CC 2018 is available as part of Adobe Creative Cloud for $52.99/month (or $20.99/month for a single app license). The new, more connected After Effects CC 2018 can make the impossible... Read more
Adobe Audition CC 2019 12.1.4 - Professi...
Audition CC 2019 is available as part of Adobe Creative Cloud for as little as $20.99/month (or $9.99/month if you're a previous Audition customer). Adobe Audition CC 2019 empowers you to create and... Read more
Adobe Premiere Pro CC 2019 13.1.5 - Digi...
Premiere Pro CC 2019 is available as part of Adobe Creative Cloud for as little as $52.99/month. The price on display is a price for annual by-monthly plan for Adobe Premiere Pro only Adobe Premiere... Read more
Navicat Premium Essentials 12.1.25 - Pro...
Navicat Premium Essentials is a compact version of Navicat which provides basic and necessary features you will need to perform simple administration on a database. It supports the latest features... Read more
Sketch 58 - Design app for UX/UI for iOS...
Sketch is an innovative and fresh look at vector drawing. Its intentionally minimalist design is based upon a drawing space of unlimited size and layers, free of palettes, panels, menus, windows, and... Read more
ClipGrab 3.8.5 - Download videos from Yo...
ClipGrab is a free downloader and converter for YouTube, Vimeo, Facebook and many other online video sites. It converts downloaded videos to MPEG4, MP3 or other formats in just one easy step Version... Read more
Dash 4.6.6 - Instant search and offline...
Dash is an API documentation browser and code snippet manager. Dash helps you store snippets of code, as well as instantly search and browse documentation for almost any API you might use (for a full... Read more
FotoMagico 5.6.8 - Powerful slideshow cr...
FotoMagico lets you create professional slideshows from your photos and music with just a few, simple mouse clicks. It sports a very clean and intuitive yet powerful user interface. High image... Read more
Civilization VI 1.2.4 - Next iteration o...
Sid Meier’s Civilization VI is the next entry in the popular Civilization franchise. Originally created by legendary game designer Sid Meier, Civilization is a strategy game in which you attempt to... Read more
Skype 8.52.0.138 - Voice-over-internet p...
Skype allows you to talk to friends, family and co-workers across the Internet without the inconvenience of long distance telephone charges. Using peer-to-peer data transmission technology, Skype... Read more

Latest Forum Discussions

See All

Lots of premium games are going free (so...
You may have seen over the past couple weeks a that a bunch of premium games have suddenly become free. This isn’t a mistake, nor is it some last hurrah before Apple Arcade hits, and it’s important to know that these games aren’t actually becoming... | Read more »
Yoozoo Games launches Saint Seiya Awaken...
If you’re into your anime, you’ve probably seen or heard of Saint Seiya. Based on a shonen manga by Masami Kurumada, the series was massively popular in the 1980s – especially in its native Japan. Since then, it’s grown into a franchise of all... | Read more »
Five Nights at Freddy's AR: Special...
Five Nights at Freddy's AR: Special Delivery is a terrifying new nightmare from developer Illumix. Last week, FNAF fans were sent into a frenzy by a short teaser for what we now know to be Special Delivery. Those in the comments were quick to... | Read more »
Rush Rally 3's new live events are...
Last week, Rush Rally 3 got updated with live events, and it’s one of the best things to happen to racing games on mobile. Prior to this update, the game already had multiplayer, but live events are more convenient in the sense that it’s somewhat... | Read more »
Why your free-to-play racer sucks
It’s been this way for a while now, but playing Hot Wheels Infinite Loop really highlights a big issue with free-to-play mobile racing games: They suck. It doesn’t matter if you’re trying going for realism, cart racing, or arcade nonsense, they’re... | Read more »
Steam Link Spotlight - The Banner Saga 3
Steam Link Spotlight is a new feature where we take a look at PC games that play exceptionally well using the Steam Link app. Our last entry talked about Terry Cavanaugh’s incredible Dicey Dungeons. Read about how it’s a great mobile experience... | Read more »
Combo Quest (Games)
Combo Quest 1.0 Device: iOS Universal Category: Games Price: $.99, Version: 1.0 (iTunes) Description: Combo Quest is an epic, time tap role-playing adventure. In this unique masterpiece, you are a knight on a heroic quest to retrieve... | Read more »
Hero Emblems (Games)
Hero Emblems 1.0 Device: iOS Universal Category: Games Price: $2.99, Version: 1.0 (iTunes) Description: ** 25% OFF for a limited time to celebrate the release ** ** Note for iPhone 6 user: If it doesn't run fullscreen on your device... | Read more »
Puzzle Blitz (Games)
Puzzle Blitz 1.0 Device: iOS Universal Category: Games Price: $1.99, Version: 1.0 (iTunes) Description: Puzzle Blitz is a frantic puzzle solving race against the clock! Solve as many puzzles as you can, before time runs out! You have... | Read more »
Sky Patrol (Games)
Sky Patrol 1.0.1 Device: iOS Universal Category: Games Price: $1.99, Version: 1.0.1 (iTunes) Description: 'Strategic Twist On The Classic Shooter Genre' - Indie Game Mag... | Read more »

Price Scanner via MacPrices.net

$250 prepaid Visa card with any Apple iPhone,...
Xfinity Mobile will include a free $250 prepaid Visa card with the purchase of any new iPhone, new line activation, and transfer of phone number to Xfinity Mobile. Offer is valid through October 27,... Read more
Sprint is offering the 64GB Apple iPhone 11 P...
Sprint has the new 64GB iPhone 11 Pro available for $12.50 per month for new customers with an eligible trade-in in of iPhone 7 or newer. That’s down from their standard monthly lease of $41.67. The... Read more
Final week: Apple’s 2019 Back to School Promo...
Purchase a new Mac using Apple’s Education discount, and take up to $400 off MSRP. All teachers, students, and staff of any educational institution with a .edu email address qualify for the discount... Read more
Save $30 on Apple’s AirPods at these reseller...
Amazon is offering discounts on new 2019 Apple AirPods ranging up to $30 off MSRP as part of their Labor Day sale. Shipping is free: – AirPods with Charging Case: $144.95 $15 off MSRP – AirPods with... Read more
Preorder your Apple Watch Series 5 today at A...
Amazon has Apple Watch Series 5 GPS models available for preorder and on sale today for $15 off Apple’s MSRP. Shipping is free and starts on September 20th: – 40mm Apple Watch Series 5 GPS: $384.99 $... Read more
21″ iMacs on sale for $100 off Apple’s MSRP,...
B&H Photo has new 21″ Apple iMacs on sale for $100 off MSRP with models available starting at $999. These are the same iMacs offered by Apple in their retail and online stores. Overnight shipping... Read more
2018 4 and 6-Core Mac minis on sale today for...
Apple resellers are offering new 2018 4-Core and 6-Core Mac minis for $100-$150 off MSRP for a limited time. B&H Photo has the new 2018 4-Core and 6-Core Mac minis on sale for up to $150 off... Read more
Save $150-$250 on 10.2″ WiFi + Cellular iPads...
Verizon is offering $150-$250 discounts on Apple’s new 10.2″ WiFi + Cellular iPad with service. Buy the iPad itself and save $150. Save $250 on the purchase of an iPad along with an iPhone. The fine... Read more
Apple continues to offer 13″ 2.3GHz Dual-Core...
Apple has Certified Refurbished 2017 13″ 2.3GHz Dual-Core non-Touch Bar MacBook Pros available starting at $1019. An standard Apple one-year warranty is included with each model, outer cases are new... Read more
Apple restocks 2018 MacBook Airs, Certified R...
Apple has restocked Certified Refurbished 2018 13″ MacBook Airs starting at only $849. Each MacBook features a new outer case, comes with a standard Apple one-year warranty, and is shipped free. The... Read more

Jobs Board

Student Employment (Blue *Apple* Cafe) Spri...
Student Employment (Blue Apple Cafe) Spring 2019 Penn State University Campus/Location: Penn State Brandywine Campus City: Media, PA Date Announced: 12/20/2018 Date Read more
Geek Squad *Apple* Master Consultation Agen...
**732907BR** **Job Title:** Geek Squad Apple Master Consultation Agent **Job Category:** Services/Installation/Repair **Location Number:** 000360-Williston-Store Read more
*Apple* Mobile Master - Best Buy (United Sta...
**728519BR** **Job Title:** Apple Mobile Master **Job Category:** Store Associates **Location Number:** 000853-Jackson-Store **Job Description:** **What does a Best Read more
*Apple* Mobility Pro - Best Buy (United Stat...
**733006BR** **Job Title:** Apple Mobility Pro **Job Category:** Store Associates **Location Number:** 000865-Conroe-Store **Job Description:** At Best Buy, our Read more
*Apple* Mobility Pro-Store 149 - Best Buy (U...
**731985BR** **Job Title:** Apple Mobility Pro-Store 149 **Job Category:** Store Associates **Location Number:** 000149-Towson-Store **Job Description:** At Best Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.