Rose
 Volume Number: 3 Issue Number: 1 Column Tag: Assembly Language Lab

# Rose Curve Generator

By Victor Barger, Waunakee, WI

An application of mathematics which produces fascinating designs is the graphing of trigonometric functions using polar coordinates. Each function leads to a beautiful design which bears a strong resemblance to a flower, such as the rose. With its excellent graphics capabilities and superior user interface, the Macintosh is perfect for quickly plotting “rose” functions on the screen with a program simple enough that anyone can use it. The application described in this article takes full advantage of these capabilities to allow the user to experience the graphic beauty of trigonometry.

## Using Rose Curves

After launching Rose Curves, a window will open in the center of the screen and the default function will be drawn inside. (See Figure 1) Both the standard apple menu and a Control menu will be in the menu bar. The apple menu contains the item “About Rose Curves...” and the names of all desk accessories available to the user from the System file. Under the Control menu are two options: Change Parameters and Quit. When the Change Parameters item is selected a window similar to the one in Figure 2 is opened in the center of the screen. With this window the user can select the function to be drawn, choose the size of the drawing and indicate whether the drawing should be multilayered. Function and size are selected by clicking on the appropriate function name or size. For example, selecting cos (sin 100r) gives the design in Figure 3. If multilayered is selected, the function will be drawn at the original size and then shrunk repeatedly to create a “layered” effect, making the design more interesting: See Figure 4.

## Entering the Program

Start up the Macintosh 68000 Development System. The startup disk should be titled ‘MDS1’ and the external disk ‘MDS2.’ The applications Edit, Asm, Link, Exec and RMaker should be on MDS1 and a folder entitled ‘.D Files’ with SysEqu.D, ToolEqu.D, QuickEqu.D, and MacTraps.D inside on MDS2. To make Rose Curves work on a Macintosh 512 with the old ROM, FixMath.Txt and FixMath.Rel must also be in the .D Files folder (The information on where to get these two files is under How Rose Curves Works). FixTraps.Txt and FixTraps.Rel are files which were distributed by Apple Computer under the Apple Software Supplement to aid assembly language programmers in calculating basic arithmetic and trigonometric functions. As the program is presented here, you have everything you need to type the program in and run it on a new ROM machine, since the FixTraps necessary for this program are explicitly defined with the ".TRAPS" statement at the start of the program. The program may also be entered into the new MPW assembler, or assembled with the Consulair C system, which includes the complete MDS assembler built-in.

To create the program, simply assemble the Rose.Asm listing. Then compile the resource file with RMaker. Finally execute the linker on the link file listing and the program object file and resource object file (both ".REL" files) will be linked together, an application generated, and the cute rose application icon should appear on the disk. Double click "Rose Curves" and your in business making fascinating polar coordinate art.

## How Rose Curves Works

The program begins by initializing the standard managers, initializing its variables, setting up the menu bar and opening the window. The initialized variables are Equation, Scale, RealScale, Multilayered and drawn. Equation contains the item number of the selected function in the Change Parameters dialog. To obtain the real equation number, subtract 3 from Equation. Scale is the item number of the selected scale or “size” and RealScale is the actual scalar multiplied on each point before drawing it. Multilayered determines whether the rose will be layered. Finally, drawn is a boolean expression which determines whether the window needs to be updated by redrawing the rose (false) or simply by copying the rose from the offscreen bitmap (true). The offscreen bitmap is also created in this routine. To create a bitmap, create an area in memory with space for a pointer, a word and a rectangle. In Rose Curves, this appears at the end of the program under the label windowBitMap. Now select the rectangle of the bitmap and calculate the rowbytes with the equation

```       rowbytes = int((xright - xleft)/8+1)
```

If rowbytes is odd, round it up. Suppose our rectangle is 0, 0, 50, 96 (remember that a QuickDraw rectangle is stored as y1, x1, y2, x2). Then rowbytes would be 14 and the bitmap would look like this:

```myBitMapDC.L0  ;pointer to bitmap storage
DC14 ;rowbytes
DC0, 0, 50, 96  ;boundsRect
```

The size of the bitmap storage must be determined before it can be created. Use the equation

``` size = rowbytes * (ybottom - ytop)
```

To create the bitmap, use the following routine.

``` move.l #size,D0
_NewPtr;allocate new pointer
lea  myBitMap,A1
move.l A0,(A1)  ;put the pointer to the
;storage in myBitMap
```

To copy a picture from the current window to myBitMap, use this routine

``` pea  aPort(A5)  ;storage for the port
_GetPort ;get the current port
move.l aPort(A5),A0 ;put the port pointer in A0
pea  portBits(A0) ;push ptr to port’s bitmap
pea  myBitMap ;push ptr to our bitMap
pea  srcRect  ;push srcRect
pea  dstRect  ;push dstRect
clr  -(SP) ;srcCopy
_CopyBits;copy the bits
```

Finally, remember to dispose of the bitmap’s storage after finishing with it. This is accomplished simply with

```move.l  myBitMap,A0
_DisposPtr
```

The EventLoop allows desk accessories to perform their periodic events by calling _SystemTask and, if an event occurs, branches to HandleEvent which transfers execution to the appropriate routine: Activate, Update, KeyDown or MouseDown. The Activate routine activates or deactivates the Rose Curves window depending on what the user requested. Update updates the window by either drawing the curve or using _CopyBits, depending on whether the curve had been drawn previously. KeyDown checks if the command-key was down when the KeyDown event occurred by testing bit eight of the ModifyReg. If bit eight equals one, a command-key was pressed and _MenuKey is called to determine the appropriate menuNumber and itemNumber for Choices, the routine which handles menu selections. MouseDown finds the area the mouse was clicked in using _FindWindow and jumps to the appropriate routine to handle the click.

The heart of the program lies in the DrawRose subroutine. Before outlining how it operates, an explanation of the fixed-point math routines is needed. Fixed-point math is not as accurate as floating-point math, but much faster. With graphics programs, speed is often much more important than accuracy, especially when there is the possibility of losing the user’s attention. Since Apple elected not to implement the fixed-point routines into the old toolbox, they released the file's FixTraps. Txt and FixMath.Rel in the Apple Software Supplement of May 6, 1985. These files are available from local user groups, bulletin boards, Apple dealerships or directly from Apple. FixTraps.Txt includes a nice description of the “toolbox additions” and FixMath.Rel contains the actual routines. To use the fixed-point routines on a Macintosh with the old ROM, type ‘INCLUDE FixTraps.Txt’ at the beginning of your .Asm file. Also include the line ‘FixTraps’ after the name of the application under development in the .Link file. To use the fixed-point routines on a Macintosh with the new ROM, simply define the trap using .TRAP at the beginning of the ASM file as we did in our listing here. The complete list of new fixed-point traps is as follows:

Long2Fix \$A83F

FracSin \$A848

FracSqrt \$A849

FracMul \$A84A

FracDiv \$A84B

FixAtan2 \$A818

FixDiv \$A84D

Fix2Long \$A840

Fix2Frac \$A841

Frac2Fix \$A842

Fix2X \$A843

X2Fix \$A844

Frac2X \$A845

X2Frac \$A846

FracCos \$A847

The fixed-point routines support three types of numbers: longint (long integer), fixed, and fract (fractional). Type longint represents integers between ±2147483647, type fixed represents fractional quantities between ±32768 with about 5 digits of accuracy and type fract represents fractional quantities between ±2 with about 9 digits of accuracy. Rose Curves uses _FracSin, _FracCos, _FixMul and _FracMul to perform its arithmetic operations. These routines work like any other toolbox trap: space is cleared on the stack for the result, the parameters are pushed on the stack and the trap is called. The Pascal definitions for these routines are

```function FracSin( x : Fixed ) : Fract
function FracCos( x : Fixed ) : Fract
function FixMul( x, y : Fixed ) : Fixed
function FracMul( x, y : Fract ) : Fract
```

With _FixMul and _FracMul it is possible to pass parameters of different types than specified. For example, one could pass x as type longint and y as type fixed to _FixMul and the result would be type longint. The following table contains the result types for multiplying different types using _FixMul and _FracMul.

_FixMul _FracMul

x y result x y result

fixed fixed fixed fract fract fract

longint fixed longint longint fract longint

fixed longint longint fract longint longint

fract fixed fract fixed fract fixed

fixed fract fract fract fixed fixed

Note: To convert a number to type Fract, multiply it by 65536. To convert a number to type Fixed, multiply it by 32768.

DrawRose begins by changing the cursor to a watch, setting the counter to 721 steps (1 + 360° x 1/increment), the increment to 572 (.5° in fixed-point radians) and the present angle to 0. It then loops until the counter is zero, evaluating the current function (bsr EvalFunction), converting the function result to rectangular coordinates and scaling and centering the points. After completing each layer, the program decreases the scale by 20 and redraws the curve if multilayered was selected. After drawing all of the layers, the variable drawn is set to true and the image in the window is copied onto the offscreen bitmap for future update events.

## Possible Modifications

Rose Curves could be improved in several ways. The most obvious way would be to add more functions to the program. To accomplish this, add the “function” buttons in the Rose.R file and add the subroutines to evaluate the new functions to Rose.Asm. Note that the displacement to the function must be included in the equation table for the new subroutine to be executed. To do this, add the line DC functionLabel-EquationTable after the line DC Six-EquationTable. As more functions are added, keep adding the labels to the equation table. The second improvement would be to decrease the time required to draw the rose when multilayered is on. To do this, copy the image of the rose into an offscreen bitmap using _CopyBits after the first rose has been drawn. Then shrink CopyBits’ dstRect and copy the rose from the offscreen bitmap onto the screen. Although many times faster, this method greatly reduces the accuracy with which layers are drawn since they are being scaled by _CopyBits, not mathematically graphed. An option to this problem would be to include a checkbox in the Change Parameters dialog titled ‘Accurate Multilayers.’ If selected, Rose Curves would draw the layers using its normal drawing routine. If not, Rose Curves would use the copy-and-shrink method, thus giving the user the choice of accuracy or speed.

```;File: Rose.Asm
;---------------------------------------------
;Rose Curves draws curves expressed as a
; function of r and theta.
;Written by Victor Barger on April 2, 1986.
;---------------------------------------------
INCLUDEMacTraps.D
INCLUDEQuickEqu.D
INCLUDEToolEqu.D
;---------------------------------------------
.trap  _FracMul \$A84A  ;New Roms
.trap  _FracCos \$A847
.trap  _FracSin \$A848
;----------------------------------------------
TopButton EQU  D3
BottomButtonEQU  D4
ModifyReg EQU  D4
Increment EQU  D4
Counter EQU D5
CheckBoxEQU D6
FuncResultEQU  A4

ParamDlgIDEQU  2000
DrawWindIDEQU  2001

InitialScaleEQU  13
RealInitScale  EQU 460
;-------------------------------------------------
Start
bsr  InitManagers ;initialize managers
bsr  InitVariables;initialize variables
bsr  SetupWindow;draw the window

EventLoop
clr  -(SP)
move #\$0FFF,-(SP)
pea  EventRecord
_GetNextEvent   ;get the next event
move (SP)+,D0
beq.s  EventLoop;no event, loop back
bsr  HandleEvent;handle the event
beq.s  EventLoop;if 0, continue; else quit
rts

Beep
move #12,-(SP)
_SysBeep
rts
;---------------------------------------------------
InitManagers
pea  -4(A5)
_InitGraf
_InitFonts
move.l #\$0000FFFF,D0
_FlushEvents
_InitWindows
clr.l  -(SP)
_InitDialogs
_TEInit
_InitCursor
rts
;---------------------------------------------------
InitVariables
move #3,Equation(A5)
move #InitialScale,Scale(A5)
move.l #RealInitScale,RealScale(A5)
clr  Multilayered(A5)  ;not multilayered
move.l #11520,D0
_NewPtr;create a new bit map
lea  windowBitMap,A1
move.l A0,(A1)  ;remember the pointer
clr  drawn(A5)  ;not drawn yet
rts
;-----------------------------------------------------
clr.l  -(SP)
move.l (SP),-(SP)
clr  -(SP)
move.l #'DRVR',-(SP)

clr.l  -(SP)
clr  -(SP)

rts
;------------------------------------------------------
SetupWindow
clr.l  -(SP)
move #DrawWindID,-(SP)
pea  WindowStorage(A5)
move.l #-1,-(SP)
_GetNewWindow   ;get the RoseCurves Window
move.l (SP),DrawPtr(A5)
_SetPort ;set the new grafport
rts
;------------------------------------------------------
HandleEvent
move Modify,ModifyReg
move What,D0
move EventTable(D0),D0
jmp  EventTable(D0)

EventTable
DCNextEvent-EventTable
DCMouseDown-EventTable
DCNextEvent-EventTable
DCKeyDown-EventTable
DCNextEvent-EventTable
DCKeyDown-EventTable
DCUpdate-EventTable
DCNextEvent-EventTable
DCActivate-EventTable
DCNextEvent-EventTable
DCNextEvent-EventTable
;-------------------------------------------------------
Activate
move.l DrawPtr(A5),D0
cmp.l  Message,D0 ;was it our window?
bne  NextEvent  ;no, get next event
btst #0,ModifyReg ;activate?
beq  NextEvent  ;no, deactivate

SetOurPort
move.l DrawPtr(A5),-(SP) ;push pointer to draw window
_SetPort ;set our port
bra  NextEvent
;-------------------------------------------------------
Update
move.l Message,D0 ;get the window ptr
cmp.l  DrawPtr(A5),D0
bne  NextEvent

tst  drawn(A5)
bne.s  copyIt
move.l DrawPtr(A5),-(SP) ;push window ptr
_SetPort ;set the port
move.l DrawPtr(A5),-(SP)
_BeginUpdate
move.l DrawPtr(A5),-(SP)
_EndUpdate
pea  windowRect
_EraseRect
bsr  DrawRose   ;draw the rose
bra  NextEvent

copyIt
move.l DrawPtr(A5),-(SP) ;push window ptr
_SetPort ;set the port
move.l DrawPtr(A5),-(SP)
_BeginUpdate
pea  windowBitMap ;get the rose from the bitMap
move.l drawPtr(A5),A0
pea  portBits(A0) ;put the rose in our window
pea  windowRect ;same rect for src and dest
pea  windowRect
clr  -(SP) ;srcCopy
_CopyBits;copy It
move.l DrawPtr(A5),-(SP)
_EndUpdate
bra  NextEvent
;-----------------------------------------------------
KeyDown
btst #8,ModifyReg ;is the command key down?
beq  NextEvent  ;no, exit
clr.l  -(SP)    ;space for menu and item
move Message+2,-(SP);get character
_MenuKey ;see if its a command
bra.s  Choices
;------------------------------------------------------
MouseDown
clr  -(SP) ;space for result
move.l Point,-(SP);get mouse coordinates
pea  WWindow    ;push event window
_FindWindow;find the window
move (SP)+,D0   ;get region number
add  D0,D0 ;*2 for index into table
move WindowTable(D0),D0  ;point to routine offset

WindowTable
DCNextEvent-WindowTable  ;in desk (not used)
DCSystemEvent-WindowTable;in system window
DCNextEvent-WindowTable  ;in content (not used)
DCNextEvent-WindowTable  ;in drag (not used)
DCNextEvent-WindowTable  ;in grow (not used)
DCQuitRoutine-WindowTable;in go away
;-----------------------------------------------------
SystemEvent
pea  EventRecord;ptr to the event record
move.l WWindow,-(SP);push window ptr
_SystemClick    ;let system take care of it
bra  NextEvent  ;next event
;-------------------------------------------------------
clr.l  -(SP)    ;space for menu choice
move.l Point,-(SP);mouse at time of event

Choices
bne.s  NotQuit  ;no
bne.s  NotQuit  ;no, continue
QuitRoutine
move.l DrawPtr(A5),-(SP) ;push ptr to draw window
_CloseWindow    ;close the window
move.l windowBitMap,A0
_DisposPtr ;dispose of the bitmap
move #-1,D0;say it was Quit
rts

NotQuit
beq  ParameterChange;yes

ChoiceReturn
;fall through get next event
;---------------------------------------------------------
NextEvent
moveq  #0,D0    ;say it's not Quit
;--------------------------------------------------------
rts
;--------------------------------------------------------
beq.s  Info

pea  DeskName
_GetItem ;get name of the desk accessory
clr  -(SP)
pea  DeskName
_OpenDeskAcc    ;open the desk accessory
move (SP)+,D0

RestoreOurPort
bsr  SetOurPort
bra  ChoiceReturn

Info
clr  -(SP)
clr.l  -(SP)
move (SP)+,D0
bra  RestoreOurPort
;---------------------------------------------------------
ParameterChange
clr.l  -(SP)
move #ParamDlgID,-(SP)
pea  DStorage
move.l #-1,-(SP)
_GetNewDialog   ;get the dialog
move.l (SP),ParamDlgPtr(A5);preserve the dialogPtr

_SetPort ;set the port

move Equation(A5),TopButton;TopButton = current button
;highlighted in top section
move TopButton,D0
bsr  FindButton ;sub. to return handle
move.l itemHandle(A5),-(SP)
move #1,-(SP)
_SetCtlValue    ;highlight the button

move Scale(A5),BottomButton;BottomButton = current
; button in bottom section
move BottomButton,D0
bsr  FindButton
move.l itemHandle(A5),-(SP)
move #1,-(SP)
_SetCtlValue    ;highlight the button

move Multilayered(A5),CheckBox
move #17,D0
bsr  FindButton ;get handle to check-box
move.l itemHandle(A5),-(SP)
move CheckBox,-(SP)
_SetCtlValue    ;check or uncheck it

RepeatLoop
clr.l  -(SP)
pea  ItemHit
_ModalDialog    ;modal dialog

move ItemHit,D1
cmp  #2,D1 ;was it Cancel?
beq  Done;yes
cmp  #1,D1 ;was it OK?
beq  SetNewParams ;yes
cmp  #9,D1 ;was it in the bottom set?
bge.s  BottomSet;yes

move TopButton,D0
move D1,TopButton ;set new button number
bsr  FindButton ;get handle to last button
move.l itemHandle(A5),-(SP)
clr  -(SP)
_SetCtlValue    ;unhighlight last button

move TopButton,D0
bsr  FindButton
move.l itemHandle(A5),-(SP)
move #1,-(SP)
_SetCtlValue    ;highlight new button
bra.s  RepeatLoop

BottomSet
cmp  #14,D1;in bottom set?
bge.s  CheckForBox;no

move BottomButton,D0
move D1,BottomButton
bsr  FindButton ;get handle to last button
move.l itemHandle(A5),-(SP)
clr  -(SP)
_SetCtlValue    ;unhighlight last button

move BottomButton,D0
bsr  FindButton
move.l itemHandle(A5),-(SP)
move #1,-(SP)
_SetCtlValue    ;highlight new button
bra  RepeatLoop

CheckForBox
cmp  #17,D1;click in the check box?
bne  RepeatLoop
cmp  #1,CheckBox
bne.s  NotOne
move #0,CheckBox
bra.s  SetCheck

NotOne
move #1,CheckBox
SetCheck
move #17,D0
bsr  FindButton ;get handle to check-box
move.l itemHandle(A5),-(SP)
move CheckBox,-(SP)
_SetCtlValue    ;check or uncheck it
bra  RepeatLoop

SetNewParams
clr  drawn(A5)
move TopButton,Equation(A5);set new equation number
move BottomButton,Scale(A5);set new scale
move CheckBox,Multilayered(A5)  ;set multilayered
move Scale(A5),D0
sub  #9,D0
asl.l  #2,D0
move.l ScaleTable(D0),RealScale(A5) ;look up real scale

Done
move.l ParamDlgPtr(A5),-(SP)
_CloseDialog    ;close the dialog
bra  RestoreOurPort

ScaleTable
DC.L 140,220,300,380,460
;------------------------------------------------------
FindButton
move.l ParamDlgPtr(A5),-(SP)
move D0,-(SP)
pea  itemType
pea  itemHandle(A5)
pea  dispRect
_GetDItem;get handle to itemnumber in D0
rts
;-------------------------------------------------------
;to convert a fract number to type fract, multipy by 65536
DrawRose
clr.l  -(SP)
move #4,-(SP)
_GetCursor ;get the watch cursor (ID=4)
move.l (SP)+,D0
move.l D0,A0
move.l (A0),-(SP)
_SetCursor ;set the new cursor

move.l RealScale(A5),-(SP) ;preserve the realScale
DrawRose1
move #720,Counter ;721 steps (360 x 2)
move.l #572,Increment    ;572 = .5° increment in radians
;(.5Π/180)*65536

nextDegree

sub  #14,SP
_FracSin
move.l FuncResult,-(SP)
move.l RealScale(A5),-(SP)
_FixMul;y = y * realScale
_HiWord
move (SP)+,y(A5);y = int(y)

sub  #14,SP
_FracCos
move.l FuncResult,-(SP)
move.l RealScale(A5),-(SP)
_FixMul;x = x * realScale
_HiWord
move (SP)+,x(A5);x = int(x)

move x(A5),D0
move D0,-(SP)   ;x = x + 154

move y(A5),D0
move D0,-(SP)   ;y = y + 144

bne.s  NotFirst
_MoveTo;moveto x,y if first point
bra.s  Skip

NotFirst
_LineTo;else lineto x,y
Skip
dbra Counter,nextDegree  ;loop back
cmp  #1,Multilayered(A5) ;another layer?
bne.s  NoExtraLayers;no
move.l #20,D0
sub.l  D0,RealScale(A5)  ;decrease the real scale by 20
cmp.l  RealScale(A5),D0  ;is the real scale = 20?
bne  DrawRose1  ;no, do next layer

NoExtraLayers
move #1,drawn(A5) ;the rose has been drawn
move.l drawPtr(A5),A0
pea  portBits(A0) ;put the rose in our window
pea  windowBitMap ;get from offscreen bitmap
pea  windowRect ;same size windowRect
pea  windowRect
clr  -(SP) ;srcCopy
_CopyBits;copy the bits
move.l (SP)+,RealScale(A5)
_InitCursor
rts
;----------------------------------------------------
EvalFunction
move Equation(A5),D0
sub  #3,D0
move EquationTable(D0),D0
jmp  EquationTable(D0)

EquationTable
DCOne-EquationTable ;sin 4r
DCTwo-EquationTable ;cos (2 sin r)
DCThree-EquationTable  ;cos (2 sin 2r)
DCFour-EquationTable;cos (sin 100r)
DCFive-EquationTable;cos (sin 8 r)
DCSix-EquationTable ;cos (4 sin 2r)
;-------------------------------------------------------
None
move.l #0,FuncResult
rts
;-------------------------------------------------------
One
;sin 4r
clr.l  -(SP)
asl.l  #2,D0
move.l D0,-(SP)
_FracSin
rts
;-------------------------------------------------------
Two
;cos (2 sin r)
subq #8,SP
_FracSin
move.l (SP),D0
asr.l  #7,D0
asr.l  #6,D0    ;convert to fixed x 2
move.l D0,(SP)
_FracCos
move.l (SP)+,FuncResult  ;fn r(Radians) = cos (2 sin r)
rts
;--------------------------------------------------------
Three
;cos (2 sin 2r)
subq #8,SP
asl.l  #1,D0
move.l D0,-(SP)
_FracSin
move.l (SP),D0
asr.l  #7,D0
asr.l  #6,D0    ;convert to fixed x 2
move.l D0,(SP)
_FracCos
move.l (SP)+,FuncResult  ;fn r(Radians) = cos (2 sin 2r)
rts
;-------------------------------------------------------
Four
;cos (sin 100r)
sub  #12,SP
move.l #3276800,-(SP)
_FixMul
_FracSin
move.l (SP),D0
asr.l  #7,D0
asr.l  #7,D0    ;convert to fixed
move.l D0,(SP)
_FracCos
move.l (SP)+,FuncResult  ;fn r(Radians) = cos (sin 100r)
rts
;--------------------------------------------------------
Five
;cos (sin 8 r)
subq #8,SP
asl.l  #3,D0
move.l D0,-(SP)
_FracSin
move.l (SP),D0
asr.l  #7,D0
asr.l  #7,D0
move.l D0,(SP)
_FracCos
move.l (SP)+,FuncResult  ;fn r(Radians) = cos (sin 8r)
rts
;---------------------------------------------------------
Six
;cos (4 sin 2r)
subq #8,SP
asl.l  #1,D0
move.l D0,-(SP)
_FracSin
move.l (SP),D0
asr.l  #7,D0
asr.l  #5,D0
move.l D0,(SP)
_FracCos
move.l (SP)+,FuncResult  ;fn r(Radians) = cos (4 sin 2r)
rts
;------------------ Local Variables -----------------
EventRecord
What:  DC0
Message: DC.L 0
When:  DC.L0
Point: DC.L0
Modify:DC0
WWindow: DC.L 0

windowRectDC0,0,288,308
windowBitMapDC.L 0
DC40
DC0,0,288,308

ItemHit DC0
itemTypeDC0
dispRectDC0,0,0,0
DStorageDCB DWindLen,0
DeskNameDCB 16,0
;-------------- Application Globals ----------------
WindowStorage  DSWindowSize ;storage for draw window
DrawPtr DS.L1    ;pointer to draw window
EquationDS1 ;equation number
Scale   DS1 ;scale
RealScale DS.L 1 ;longint real scale
MultiLayeredDS 1 ;multilayered (0 = false, 1 = true)
ParamDlgPtr DS.L 1 ;pointer to the parameter dialog
itemHandleDS.L 1 ;itemHandle
yDS1    ;y-value
xDS1    ;x-value
drawn   DS1
;--------------------------------------------------------
END
```

Community Search:
MacTech Search:

Capto 1.2.9 - \$29.99
Capto (was Voila) is an easy-to-use app that takes capturing, recording, video and image editing to the next level. With an intelligent file manager and quick sharing options, Capto is perfect for... Read more
Opera 51.0.2830.40 - High-performance We...
Opera is a fast and secure browser trusted by millions of users. With the intuitive interface, Speed Dial and visual bookmarks for organizing favorite sites, news feature with fresh, relevant content... Read more
GarageSale 7.0.13 - Create outstanding e...
GarageSale is a slick, full-featured client application for the eBay online auction system. Create and manage your auctions with ease. With GarageSale, you can create, edit, track, and manage... Read more
1Password is a password manager that uniquely brings you both security and convenience. It is the only program that provides anti-phishing protection and goes beyond password management by adding Web... Read more
Evernote 7.0.1 - Create searchable notes...
Evernote allows you to easily capture information in any environment using whatever device or platform you find most convenient, and makes this information accessible and searchable at anytime, from... Read more
MacUpdate Desktop 6.2.0 - \$20.00
MacUpdate Desktop brings seamless 1-click app installs and version updates to your Mac. With a free MacUpdate account and MacUpdate Desktop 6, Mac users can now install almost any Mac app on... Read more
HoudahSpot is a versatile desktop search tool. Use HoudahSpot to locate hard-to-find files and keep frequently used files within reach. HoudahSpot will immediately feel familiar. It works just the... Read more
EtreCheck 4.0.4 - For troubleshooting yo...
EtreCheck is an app that displays the important details of your system configuration and allow you to copy that information to the Clipboard. It is meant to be used with Apple Support Communities to... Read more
WhatsApp 0.2.8361 - Desktop client for W...
WhatsApp is the desktop client for WhatsApp Messenger, a cross-platform mobile messaging app which allows you to exchange messages without having to pay for SMS. WhatsApp Messenger is available for... Read more
iClock is a menu-bar replacement for Apple's default clock but with 100x features. Have your Apple or Google calendar in the menubar. Have the day, date, and time in different fonts and colors in the... Read more

## Latest Forum Discussions

The best games like Florence
Florence is a great little game about relationships that we absolutely adored. The only problem with it is it's over a little too soon. If you want some other games with some emotional range like Florence, check out these suggestions: [Read more] | Read more »
Angry Birds Champions adds cash prizes t...
Collaborating with developer Rovio Entertainment, GSN Games has released a twist on the Angry Birds formula. Angry Birds Champions features the same bird-flinging gameplay, but now you can catapult Red and co for cash. | Read more »
Around the Empire: What have you missed...
148Apps is part of a family. A big family of sites that make sure you're always up to date with all the portable gaming news. Just like a real family, I guess. I don't know, my mum never told me anything about Candy Crush to be fair. [Read more] | Read more »
The Battle of Polytopia Guide - Tips for...
The addition of multiplayer to The Battle of Polytopia has catapulted the game from a fun enough time waster to a fully-fledged 4X experience on your phone. We've been playing quite a few matches over the past week or so, and we've put together a... | Read more »
All the best games on sale for iPhone an...
Hi there, and welcome to our round up of all the best games that are on sale for iOS at the moment. It's not a vintage week in terms of numbers, but I'm pretty sure that every single one of these is worth picking up if you haven't already played... | Read more »
Disc Drivin' 2 Guide - Tips for the...
We're all still playing quite a bit of Disc Drivin' 2 over here at 148Apps, and we've gotten pretty good at it. Now that we've spent some more time with the game and unlocked more powerups, check out some of these more advanced tips: | Read more »
Alto's Odyssey Guide - How to Tackl...
Alto’s Odyssey is a completely stunning and serene runner, but it can also be a bit tricky. Check out these to try and keep your cool while playing this endless runner: Don’t focus too much on tasks [Read more] | Read more »
Here's everything you need to know...
Alto's Odyssey is a really, really good game. If you don't believe me, you should definitely check out our review by clicking this link right here. It takes the ideas from the original Alto's Adventure, then subtly builds on them, creating... | Read more »
Alto's Odyssey (Games)
Alto's Odyssey 1.0.1 Device: iOS Universal Category: Games Price: \$4.99, Version: 1.0.1 (iTunes) Description: Just beyond the horizon sits a majestic desert, vast and unexplored. Join Alto and his friends and set off on an endless... | Read more »
Vainglory 5v5: Everything you need to kn...

## Price Scanner via MacPrices.net

Use your Apple Education discount and save up...
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
Apple Canada offers 2017 21″ and 27″ iMacs fo...
Canadian shoppers can save up to \$470 on the purchase of a 2017 current-generation 21″ or 27″ iMac with Certified Refurbished models at Apple Canada. Apple’s refurbished prices are the lowest... Read more
9″ iPads available online at Walmart for \$50...
Walmart has 9.7″ Apple iPads on sale for \$50 off MSRP for a limited time. Sale prices are for online orders only, in-store prices may vary: – 9″ 32GB iPad: \$279.99 \$50 off – 9″ 128GB iPad: \$379.99 \$... Read more
15″ Apple MacBook Pros, Certified Refurbished...
Save \$360-\$420 on the purchase of a 2017 15″ MacBook Pro with Certified Refurbished models at Apple. Apple’s refurbished prices are the lowest available for each model from any reseller. An standard... Read more
Amazon restocks MacBook Pros with models avai...
Amazon has restocked 15″ and 13″ Apple MacBook Pros with models on sale for up to \$251 off MSRP. Shipping is free. Note that stock of some Macs may come and go (and some sell out quickly), so check... Read more
Lowest price of the year: 15″ 2.8GHz Apple Ma...
Amazon has the 2017 Space Gray 15″ 2.8GHz MacBook Pro on sale today for \$251 off MSRP. Shipping is free: – 15″ 2.8GHz Touch Bar MacBook Pro Space Gray (MPTR2LL/A): \$2148, \$251 off MSRP Their price is... Read more
Apple restocks full line of Certified Refurbi...
Apple has restocked a full line of Apple Certified Refurbished 2017 13″ MacBook Pros for \$200-\$300 off MSRP. A standard Apple one-year warranty is included with each MacBook, and shipping is free.... Read more
Lowest sale price available for 13″ 1.8GHz Ma...
Focus Camera has the 2017 13″ 1.8GHz/128GB Apple MacBook Air on sale today for \$829 including free shipping. Their price is \$170 off MSRP, and it’s the lowest price available for a current 13″... Read more
21-inch 2.3GHz iMac on sale for \$999, \$100 of...
B&H Photo has the 2017 21″ 2.3GHz iMac (MMQA2LL/A) in stock and on sale for \$999 including free shipping plus NY & NJ tax only. Their price is \$100 off MSRP. Read more
Apple refurbished Mac minis in stock again st...
Apple has restocked Certified Refurbished Mac minis starting at \$419. Apple’s one-year warranty is included with each mini, and shipping is free: – 1.4GHz Mac mini: \$419 \$80 off MSRP – 2.6GHz Mac... Read more

## Jobs Board

*Apple* Retail - Multiple Positions - Apple,...
Job Description: Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
*Apple* Retail - Multiple Positions - Apple,...
Job Description:SalesSpecialist - Retail Customer Service and SalesTransform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
*Apple* Retail - Multiple Positions - Apple,...
Job Description: Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
*Apple* Solutions Consultant - Apple (United...
# Apple Solutions Consultant Job Number: 113523441 Orange, CA, California, United States Posted: 21-Feb-2018 Weekly Hours: 40.00 **Job Summary** Are you passionate Read more
*Apple* Retail - Multiple Positions - Apple,...
Job Description:SalesSpecialist - Retail Customer Service and SalesTransform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more