Skip to content

Instantly share code, notes, and snippets.

@steventroughtonsmith
Created January 16, 2015 02:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save steventroughtonsmith/5ad1ac4ebbf883de05b1 to your computer and use it in GitHub Desktop.
Save steventroughtonsmith/5ad1ac4ebbf883de05b1 to your computer and use it in GitHub Desktop.
MPW Link Out Of Memory
***************************************************************************
****
**** DESK ACCESSORY and DEVICE DRIVER Entry Code/Data
****
***************************************************************************
STRING PASCAL
INCLUDE 'Events.a'
INCLUDE 'Devices.a'
INCLUDE 'Traps.a'
INCLUDE 'Quickdraw.a'
CASE OBJ
**************************** DESK ACCESSORY ENTRY **************************
IMPORT %DRVRMain
DAEntry Proc Export ; See Device Manager IM:2
;
; First we need to set the drvrFlags (IM II-188), choose from
;
; dReadEnable enable driver for read operations (drivers only)
; dWritEnable enable driver for writing (drivers only)
; dCtlEnable enable driver/da for control operations
; dStatEnable enable driver/da for status operations (drivers only)
; dNeedGoodBye driver/da needs a "goodbye kiss"
; dNeedTime driver/da needs "main thread" time
; dNeedLock driver will be accessed at interrupt level (drivers only)
;
DC.B (1<<dCtlEnable) + (1<<dNeedTime) ; periodic, control flags set
DC.B 0 ; Lower byte is unused
;
; Next is the the drvrDelay (IM II-188), set only if dNeedTime flag set above
;
DC.W 5*60 ; 5 sec periodic update
;
; Next is the the drvrEMask (IM I-444), which events DA can respond to...
; Must be NIL for drivers, for DA's choose from
; mButDwnEvt mouse button down is event 1
; keyDwnEvt key down is event 3
; keyUpEvt key up is event 4
; autoKeyEvt auto-repeated key is event 5
; updatEvt update event
; activateEvt activate/deactive event
;
DC.W (1<<updateEvt) ; Handle activate, update events
;
; Next is the the drvrMenu (IM I-444), Menu ID of DA's menu, or NIL
;
DC.W 0 ; No associated menu
;
; Next are the offsets to the main routines of the driver/DA
;
DC.W %DRVRMain - DAEntry ; Open routine
DC.W %DRVRMain - DAEntry +4 ; Prime - unused for DA's
DC.W %DRVRMain - DAEntry +8 ; Control
DC.W %DRVRMain - DAEntry +12 ; Status - unused for DA's
DC.W %DRVRMain - DAEntry +16 ; Close
;
; Next are the offsets to the main routines of the driver/DA
;
DAName
DC.B 'Memory' ; DA/DRVR Name
ORG DAName+32 ; Pad string out to 32 bytes
END
SymOptions = -sym Full
SymOpt = $(SymOptions)
COptions = -w 17 -proto strict $(SymOpt) -D OLDROUTINELOCATIONS=0
all : Memory
%.c.o: %.c
mpw SC $< -o $@ $(COptions)
%.a.o: %.a
mpw asm $< -o $@
DACreator ='movr'
DAType ='dfil'
Memory: Memory.c.o DAEntry.a.o
mpw Link $(SymOptions) -da -rt DRVR=12 -m DAEntry \
-sg Memory DAEntry.a.o "{Libraries}"DRVRRuntime.o Memory.c.o \
"{Libraries}"MacRuntime.o "{Libraries}"Interface.o -o Memory \
-c $(DACreator) -t $(DAType)
clean:
rm -f Memory Memory.c.o DAEntry.a.o Memory.SYM
/*
File Memory.c
Copyright Apple Computer, Inc. 1985-1987, 1995
All rights reserved.
* Memory - report the amount of free space in the
* application and system heap, and on the boot volume.
*
* This is the sample C desk accessory. The desk accessory does not
* use any global variables. Instead, it allocates a handle to a
* structure that holds some "global" variables. This sample program
* could be written without having to use this structure, but then it
* wouldn't be as informative...
*/
#include <Types.h>
#include <Devices.h>
#include <Fonts.h>
#include <NumberFormatting.h>
#include <TextUtils.h>
#include <Windows.h>
/*
* Macro to compute owned resource id
*/
#define OWNEDRSRCID(id) (0xC000 | (((-(id)) - 1) << 5))
/*
* String constant indexes for STR# resource
*/
#define APPHEAP 1
#define SYSHEAP 2
#define DISK 3
#define FREEON 4
#define ACCEVENT 64
#define ACCRUN 65
/* This structure type holds the global variables used by this desk accessory */
typedef struct {
int rsrcID; /* Computed rsrc id of STR# and WIND resources */
Str255 strBuf; /* Buffer to read strings into */
} Globals;
/*
* Forward declarations
*/
static void doCtlEvent(register EventRecord *theEvent, Globals *globals);
static void doPeriodic(DCtlPtr dCtl);
static void drawWindow(WindowPtr window, Globals *globals);
static void printNum(unsigned long);
static StringPtr text(int index, Globals *globals);
pascal short DRVROpen(CntrlParam *ctlPB, DCtlPtr dCtl)
{
#pragma unused (ctlPB)
GrafPtr savePort;
WindowPeek myWindow;
long heapGrow;
/*
* If the windowPtr is non-nil, we already have a window open.
* This desk accessory ignores multiple opens.
*/
if (dCtl->dCtlWindow != nil)
return noErr;
GetPort(&savePort);
/*
* Get a handle to some storage that will hold our pseudo-global
* variables. Save the handle in a location accessible by
* all the driver routines.
*/
dCtl->dCtlStorage = NewHandle(sizeof(Globals));
/*
* Compute the resource id of the owned 'STR#' resource that
* contains all of the program's text strings. The id is saved
* in one place that can be accessed by all the driver routines.
*/
((Globals *)(*dCtl->dCtlStorage))->rsrcID = OWNEDRSRCID(dCtl->dCtlRefNum);
/*
* wStorage = nil (allocate on the heap)
* visible = false, behind = -1, goAway = true, refCon = 0
*/
myWindow = (WindowPeek)GetNewWindow(((Globals *)(*dCtl->dCtlStorage))->rsrcID, nil, (WindowPtr) -1);
/*
* Set windowKind to the DA refNum, which is negative.
*/
myWindow->windowKind = dCtl->dCtlRefNum;
/*
* Store the windowPtr in the Device Control Entry
*/
dCtl->dCtlWindow = (WindowPtr)myWindow;
/*
* Now compact the heap in the most violent way.
* Purge whatever's purgeable.
*/
(void) MaxMem(&heapGrow);
SetPort(savePort);
return noErr;
}
pascal short DRVRPrime(CntrlParam *ctlPB, DCtlPtr dCtl)
{
#pragma unused (ctlPB, dCtl)
return noErr; /* Not used in this desk accessory */
}
pascal short DRVRStatus(CntrlParam *ctlPB, DCtlPtr dCtl)
{
#pragma unused (ctlPB, dCtl)
return noErr; /* Not used in this desk accessory */
}
pascal short DRVRControl(CntrlParam *ctlPB, DCtlPtr dCtl)
{
/*
* The current grafPort is saved & restored by the Desk Manager
*/
switch (ctlPB->csCode) {
case ACCEVENT: /* accEvent */
HLock(dCtl->dCtlStorage); /* Lock handle since it will be dereferenced */
doCtlEvent( *((EventRecord **) &ctlPB->csParam[0]),
(Globals *)(*dCtl->dCtlStorage));
HUnlock(dCtl->dCtlStorage);
break;
case ACCRUN: /* periodicEvent */
doPeriodic(dCtl);
break;
default:
break;
}
return 0;
}
static void doCtlEvent(register EventRecord *theEvent, Globals *globals)
{
register WindowPtr myWindow;
if (theEvent->what == updateEvt) {
myWindow = (WindowPtr) theEvent->message;
SetPort(myWindow);
BeginUpdate(myWindow);
drawWindow(myWindow, globals);
EndUpdate(myWindow);
}
}
static void doPeriodic(DCtlPtr dCtl)
{
SetPort(dCtl->dCtlWindow);
HLock(dCtl->dCtlStorage); /* Lock handle since it will be dereferenced */
drawWindow(dCtl->dCtlWindow, (Globals *)(*dCtl->dCtlStorage));
HUnlock(dCtl->dCtlStorage);
}
/*
* Display the contents of the window.
* The current port is assumed to be set to the window.
*/
static void drawWindow(WindowPtr window, Globals *globals)
{
THz saveZone;
Str27 volName;
HVolumeParam myParamBlk;
if (window == nil)
return; /* "can't happen" */
TextMode(srcCopy);
TextFont(kFontIDMonaco);
TextSize(9);
MoveTo(6, 10);
TextFace(bold);
saveZone = GetZone();
DrawString(text(APPHEAP, globals));
SetZone(ApplicationZone());
printNum(FreeMem());
DrawString(text(SYSHEAP, globals));
SetZone(SystemZone());
printNum(FreeMem());
SetZone(saveZone);
DrawString(text(DISK, globals));
myParamBlk.ioNamePtr = volName;
myParamBlk.ioVRefNum = 0; /* Boot volume */
myParamBlk.ioVolIndex = 0;
(void) PBHGetVInfo((HParmBlkPtr)&myParamBlk, false);
printNum((unsigned long)myParamBlk.ioVAlBlkSiz * myParamBlk.ioVFrBlk);
DrawString(text(FREEON, globals));
TextFace(underline);
DrawString(volName);
}
static void printNum(unsigned long num)
{
unsigned char numStr[32];
TextFace(normal);
NumToString(num, numStr); /* Its possible that a large unsigned
will come back negative! */
DrawString(numStr);
TextFace(bold);
}
pascal short DRVRClose(char *ctlPB, DCtlPtr dCtl)
{ /* Save & Restore current grafPort? */
#pragma unused (ctlPB)
WindowPtr window;
window = (WindowPtr) dCtl->dCtlWindow;
if ( window != nil) {
dCtl->dCtlWindow = nil;
DisposeHandle(dCtl->dCtlStorage);
DisposeWindow(window);
}
return 0;
}
static StringPtr text(int index, Globals *globals)
{
GetIndString(globals->strBuf, globals->rsrcID, index);
return(globals->strBuf);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment