supermario/bin/MPW-3.2.3/Examples/AExamples/Sample.inc1.a
2019-06-29 22:17:03 +08:00

371 lines
13 KiB
Plaintext

*
* Apple Macintosh Developer Technical Support
*
* MultiFinder-Aware Simple Sample Application
*
* Sample
*
* Sample.inc1.a - Assembler Source
*
* Copyright © Apple Computer, Inc. 1989-1990
* All rights reserved.
*
* Versions:
* 1.00 08/88
* 1.01 11/88
* 1.02 04/89 MPW 3.1
* 1.03 02/90 MPW 3.2
*
* Components:
* Sample.a Feb. 1, 1990
* Sample.inc1.a Feb. 1, 1990
* SampleMisc.a Feb. 1, 1990
* Sample.r Feb. 1, 1990
* Sample.h Feb. 1, 1990
* Sample.make Feb. 1, 1990
*
* Sample is an example application that demonstrates how to
* initialize the commonly used toolbox managers, operate
* successfully under MultiFinder, handle desk accessories,
* and create, grow, and zoom windows.
*
* It does not by any means demonstrate all the techniques
* you need for a large application. In particular, Sample
* does not cover exception handling, multiple windows/documents,
* sophisticated memory management, printing, or undo. All of
* these are vital parts of a normal full-sized application.
*
* This application is an example of the form of a Macintosh
* application; it is NOT a template. It is NOT intended to be
* used as a foundation for the next world-class, best-selling,
* 600K application. A stick figure drawing of the human body may
* be a good example of the form for a painting, but that does not
* mean it should be used as the basis for the next Mona Lisa.
*
* We recommend that you review this program or TESample before
* beginning a new application.
* ----------- DEBUGGING INFORMATION -------------
* This is used as a global switch to turn off the generation of debugging information.
* The MACRO "DbgInfo" will generate this debugging information if set to 1.
DebuggerInfo EQU 1
* ================================================
* -------- MACRO DEFINITIONS SECTION ----------
* ================================================
* ------------- GENERATE A PASCAL "CASE" OR "IF" SEQUENCE -------------
* The following macro is used to generate a branch based on an index value
* in a D-register with a value from 0 to N. The branch is through a table
* of relative addresses also generated by this macro. The macro is called
* in one of two forms as follows:
* {Form #1} Case# (Dreg,Default),case0,case1,...caseN
* {Form #2} Case#.<size> (Dreg,IF),(cst0,case0),...,(cstN,caseN)
* In Form #1, the "Default" specifies a label for any omitted case labels not
* specified explicitly. The "case0", "case1",..."caseN" are case labels
* identifying the various cases to be processed. A case label may be omitted,
* in which case the "Default" is used. The "Default" may also be omitted, but
* in that case all case labels must be specified. If there are fewer case labels
* than there are cases, but there are N possible values for the case index, the
* proper number of trailing commas must be supplied to generate the defaults.
* In Form #2, the default is specified as the word "IF". In this form the macro
* generates a set of compares (CMPI's) and branches (BEQ) for each specified
* case (there is no implicit default). Each case is a constant/label pair.
* The constant is compared (CMPI.W) and an branch is done (BEQ) to the case if
* the Dreg equals the constant. A size may be specified for all the branches
* as a <size> attribute to the Case# call itself. This must either be an "S"
* or "W" to generate BEQ.S's or BEQ.W's. The default is for "S".
MACRO
Case#.&Size &IdxDef
PRINT Push,NoMDir ; only list generated code
LCLA &i ; index to macro parameters
LCLA &n ; total number of macro parameters
LCLC &Dreg,&Def ; the Dreg and Default parameters
LCLC &sz ; the <size> value
&Dreg SETC &IdxDef[1] ; pick off 1st opnd of sublist
&Def SETC &IdxDef[2] ; pick off 2nd opnd of sublist
&n SETA &Nbr(&Syslist) ; done for efficiency
&i SETA 2 ; cases start at 2nd parameter
IF &UpCase(&Def) <> 'IF' THEN
.* Create the jump table and the index value
* -----------------------------------------------
ADD &Dreg,&Dreg
MOVE Case&SysNdx(&Dreg),&Dreg
JMP Case&SysNdx(&Dreg)
Case&SysNdx
WHILE &i <= &n DO ; process each case label
IF &SysList[&i] <> '' THEN
DC.W &SysList[&i]-Case&SysNdx
ELSE
DC.W &Def-Case&SysNdx
ENDIF
&i: SETA &i+1 ; count off parameter
ENDWHILE
ELSE ; process (Cst,lbl) pairs
.* Create a series of CMPI and BEQ instructions
* -----------------------------------------------
&Sz: SETC &Default(&Size, 'S') ; setup size attribute
WHILE &i <= &n DO ; process each (Cst,lbl) pair
CMPI #&SysList[&i,1],&Dreg
BEQ.&Sz &SysList[&i,2]
&i: SETA &i+1 ; count off parameter
ENDWHILE
ENDIF
PRINT Pop ; restore original print status
ENDM
* ------------- GENERATE DEBUGGER SYMBOL INFORMATION -------------
* This Macro will generate information for the debugger to read and display
* as its module name. This aids in debugging Asm code while looking at it
* in the debugger. This macro can only work if called at the end of stack
* frame. The appearance of the Macro statement in the source code must occur
* immediately after the final "JMP (A0)" or "RTS" instruction following the UNLINK.
* Spaces may be included in the name, but no quotes are allowed.
* {Form #1} DbgInfo ModName
* {Form #2} DbgInfo.New Really Long Module Name For MacsBug 6.0
* There are now two naming conventions used in MacsBug, Form #1 is the older MacsBug,
* or TMON, and Form #2 is the newer MacsBug 6.0. The older method would only
* allow for a fixed length of eight characters. If a shorter name is passed to
* this Macro, it will extend the length to 8 chars with trailing spaces.
* MacsBug 6.0 will now allow for a variable length C type string. This Macro will
* create the proper DC statements and takes into account word alignment issues.
MACRO
DbgInfo.&Opt &ModName# ; the name to be used in the Debugger
PRINT Push,NoMDir ; Only list generated code
LCLC &DbgName# ; name to generate for MacsBug
LCLC &DbgTemp ; temporary name variable
LCLC &New ; variable used to test old vs. new
LCLC &S ; variable used to save PRINT state
IF DebuggerInfo THEN ; do we want debugging info?
IF &ModName# ≠ '' THEN ; did we get a module name?
&New: SETC &UpCase(&Opt) ; make option all upper case
IF (&New = 'NEW') THEN ; do we want new style?
.* Create the new MacsBug naming convention
* -----------------------------------------------
&DbgTemp: SETC &ModName# ; generate new type symbols
IF &Len(&ModName#) < 32 THEN ; if module name < 32 chars
IF &Len(&ModName#) // 2 = 0 THEN ; add space if even so that...
&DbgTemp: SETC &Concat(&ModName#,' ') ; string length plus length byte...
ENDIF ; will align to word boundary
&DbgName#: SETC &Concat(&Chr($80 + &Len(&ModName#)), &DbgTemp)
ELSE ; Length > 32 characters
IF &Len(&ModName#) // 2 = 1 THEN ; add space if length is odd
&DbgTemp: SETC &Concat(&ModName#,' ')
ENDIF
&DbgName#: SETC &Concat(&Chr($80), &Chr(&Len(&ModName#)), &DbgTemp)
ENDIF
ELSE ; make it the older style
.* Create the older MacsBug naming convention
* -----------------------------------------------
IF &Len(&ModName#) < 8 THEN ; if module name < 8 chars
&DbgName#: SETC &Concat(&ModName#,' ') ; add at least 7 spaces
&DbgName#: SETC &Concat(&Chr($80 + &ORD(&SubStr(&DbgName#,1,1))), &SubStr(&DbgName#,2,7))
ELSE ; there are at least 8 chars
&DbgName#: SETC &Concat(&Chr($80 + &ORD(&SubStr(&ModName#,1,1))), &SubStr(&ModName#,2,7))
ENDIF
ENDIF
.* Create the DC.B with the debugger name, and include the NULs if new MacsBug option
* -----------------------------------------------
&S: SETC &Setting('STRING') ; preserve STRING status
IF &S ≠ 'ASIS' THEN ; only change it if not already ASIS
STRING ASIS
DC.B '&DbgName#'
IF (&New = 'NEW') THEN
DC.W 0 ; fake literal size for new MacsBug
ENDIF
STRING &S
ELSE
DC.B '&DbgName#'
IF (&New = 'NEW') THEN
DC.W 0 ; fake literal size for new MacsBug
ENDIF
ENDIF
ENDIF
ENDIF
PRINT Pop ; restore original print status
ENDM
* ================================================
* --------------- EQUATE SECTION ---------------
* ================================================
* Some various EQUATES we'll use throughout the program.
* -----------------------------------------------
False EQU 0 ; the value of False
True EQU $0100 ; and you thought True = 1, HA!
NIL EQU 0 ; a NIL pointer to test against
ToolTrapBit EQU 11 ; this bit is on for Tool traps
WaitNextEvent EQU $A860 ; the WaitNextEvent trap number
Unimplemented EQU $A89F ; the Unimplemented trap number
EnvironsVersion EQU 1 ; this is the version of the SysEnvirons we want
SleepValue EQU $7FFFFFFF ; the sleeping time ($7FFFFFFF = MaxLongInt)
SuspendResume EQU 1 ; the suspend/resume event number of an OSEvent
NoEvents EQU 0 ; no events mask
ExtremeNeg EQU -32768 ; for wide open rects and regions, see AdjustCursor
ExtremePos EQU 32767-1 ; -1 is because of a bug in regions, see AdjustCursor
* This is the minimum result from the following equation:
* applLimit - applZone = minimum heap size
* for the application to run. It will insure that enough memory will
* be around for reasonable-sized scraps, FKEYs, etc. to exist with the
* application, and still give the application some 'breathing room'.
* To derive this number, we ran under a MultiFinder partition that was
* our requested minimum size, as given in the 'SIZE' resource.
MinHeap EQU 21*1024 ; minimum heap size in bytes
* This is the minimum exceptable result from PurgeSpace, when called
* at initialization time, for the application to run. This number acts
* as a double-check to insure that there really is enough memory for the
* application to run, including what has been taken up already by
* pre-loaded resources, the scrap, code, and other sundry memory blocks.
MinSpace EQU 8*1024 ; minimum stack space in bytes
* The following equates use for resources. That's why they have a "r" in front.
* -----------------------------------------------
rMenuBar EQU 128 ; application's menu bar
rUserAlert EQU 129 ; error alert for user
rWindow EQU 128 ; application's window
rAboutAlert EQU 128 ; about alert
rStopRect EQU 128 ; rectangle for Stop light
rGoRect EQU 129 ; rectangle for Go light
* The following equates are for menu definitions, obviously.
* -----------------------------------------------
AppleMenu EQU 128 ; Apple menu
AboutItem EQU 1
FileMenu EQU 129 ; File menu
NewItem EQU 1
OpenItem EQU 2
CloseItem EQU 4
SaveItem EQU 5
SaveAsItem EQU 6
RevertItem EQU 7
PageSetupItem EQU 9
PrintItem EQU 10
QuitItem EQU 12
EditMenu EQU 130 ; Edit menu
UndoItem EQU 1
CutItem EQU 3
CopyItem EQU 4
PasteItem EQU 5
ClearItem EQU 6
LightMenu EQU 131 ; Light menu
StopItem EQU 1
GoItem EQU 2
* -----------------------------------------------
DITopLeft EQU $00500070 ; position of Disk Init dialogs
* ================================================
* ---------------- RECORD TYPES ----------------
* ================================================
* This section is declaring record structures. These records are
* templates. No data is allocated at this point. These are just
* structures, similar to Pascal TYPEs. They simply generate a list
* of equate offsets. Since none of these types are defined already
* in the MPW AIncludes, we'll need to define them.
* ------------- MOUSE POINT TYPE -------------
Point RECORD 0
v DS.W 1
h DS.W 1
ORG v
vh DS.W h
ENDR
* ------------- RECTANGLE TYPE -------------
Rect RECORD 0
Top DS.W 1
Left DS.W 1
Bottom DS.W 1
Right DS.W 1
ORG Top
TopLeft DS.L 1
BotRight DS.L 1
ENDR
* ------------- BITMAP TYPE -------------
BitMap RECORD 0
baseAddr DS.L 1
rowBytes DS.W 1
bounds DS.L Rect
ENDR
* ------------- EVENT RECORD TYPE -------------
EventRecord RECORD 0
What DS.W 1
Message DS.L 1
When DS.L 1
Where DS.L Point
Modify DS.W 1
ENDR
* ------------- THE QUICKDRAW WORLD -------------
MyQDGlobals RECORD 0,DECREMENT
GrafPort DS.L 1
White DS.B 8
Black DS.B 8
Gray DS.B 8
LtGray DS.B 8
DkGray DS.B 8
Arrow DS.B cursRec
ScreenBits DS.B BitMap
RandSeed DS.L 1
ORG -GrafSize
ENDR
* ------------- ALL OF OUR GLOBAL DATA -------------
* Note the minimal amount of globals we're using. Data such as
* the EventRecord, WindowRecords, etc. do not belong in global data
* allocation. Only data that basically doesn't change through out the
* execution of the program is considered global. The boolean flags are
* global, since they affect the state of the program at any given time.
* Also note that any appearance of a DS outside of a stack frame will
* be allocated off of A5 and becomes part of global data storage.
AppGlobals RECORD 0 ; this is our global data storage
Stopped DS.W 1 ; boolean for the state of the light
HasWNEvent DS.W 1 ; boolean for WaitNextEvent trap, see ForceEnvirons
InBackground DS.W 1 ; boolean for if in background, see OSEvent
StopRect DS Rect ; rect for the Stop light, set from a resource
GoRect DS Rect ; rect for the Go light, set from a resource
Mac DS SysEnvRec ; the system environment record, see ForceEnvirons
ENDR