Created
January 16, 2015 02:08
-
-
Save steventroughtonsmith/5ad1ac4ebbf883de05b1 to your computer and use it in GitHub Desktop.
MPW Link Out Of Memory
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
*************************************************************************** | |
**** | |
**** 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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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