Source/StubMod.c

/*
    StubMod.c
    This file creates the 68k 'ADgm' resource to call your PPC module.
    Its designed to be compiled as a code resource and then included in your PPC shared libary project.
 
    Created by Steve Zellers
    6/2/95  aea (Andrew Armstrong) Modifed for CodeWarrior & proper CPU checking.
    05/30/96    smz     rewrote for "fat" CFM modules
*/
 
#define GENERATING68K 1
#include <ConditionalMacros.h>
#include <CodeFragments.h>
#include <MixedMode.h>
#include <Types.h>
#include <OSUtils.h>
#include <Resources.h>
#include <Memory.h>
#include <A4Stuff.h>
#include <Quickdraw.h>
#include <LowMem.h>
#include <GestaltEqu.h>
 
#include "GraphicsModule_Types.h"
 
#define kFragmentName   "\pmain"
#define kEntryPointName "\pmain"
 
typedef pascal OSErr (*ModuleProcPtr)(Handle* storage, RgnHandle rgn, short msg, GMParamBlockPtr params);
 
enum {
    eModuleDispatchSelector = kPascalStackBased
         | RESULT_SIZE(SIZE_CODE(sizeof(OSErr)))
         | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof( Handle*)))
         | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof( RgnHandle)))
         | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(short)))
         | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof( GMParamBlock*)))
};
 
static ConnectionID theConnectionID;
static Ptr theEntryPoint;
static ModuleProcPtr theDescriptor = nil;
 
static OSErr LocateFile(short refNum, FSSpec* location, long* fileLen)
{
    FCBPBRec fcbPB;
    OSErr result;
 
    fcbPB.ioNamePtr = (StringPtr)location->name;
    fcbPB.ioCompletion = nil;
    fcbPB.ioFCBIndx = 0;
    fcbPB.ioRefNum = refNum;
    result = PBGetFCBInfo(&fcbPB, false);
    if (result == noErr) {
        location->vRefNum = fcbPB.ioFCBVRefNum;
        location->parID = fcbPB.ioFCBParID;
        *fileLen = fcbPB.ioFCBPLen;
    }
 
    return result;
}
 
static Boolean onPowerPC()
{
    long result;
    return Gestalt(gestaltNativeCPUtype, &result) == noErr && result >= gestaltCPU601;
}
 
static RoutineDescriptor theRTD = BUILD_ROUTINE_DESCRIPTOR(eModuleDispatchSelector, nil);
 
pascal OSErr main(Handle* storage, RgnHandle rgn, short msg, GMParamBlockPtr params)
{
    OSErr err = noErr;
    long cfmPresent;
    long oldA4;
 
    oldA4 = SetCurrentA4();
 
    err = Gestalt(gestaltCFMAttr, &cfmPresent);
    if (err != noErr) {
        Handle errorHandle;
        
        errorHandle = Get1Resource('STR ', 150);
        
        if (!errorHandle)
            BlockMove("\pSorry, this module requires the Code Fragment Manager.", params->errorMessage, 255);
        else {
            HLock(errorHandle);
            BlockMove(*errorHandle, params->errorMessage, 255);
            ReleaseResource(errorHandle);
        }
 
        ExitCodeResource();
        return -1;  
    }
 
    // open the fragment
    if (msg == Initialize || msg >= ButtonMessage) {
        Ptr exportedEntryPoint;
        SymClass theClass;
        FSSpec thisSpec;
        long thisLen;
 
        LocateFile(LMGetCurMap(), &thisSpec, &thisLen);
        err = GetDiskFragment(&thisSpec, 0, kWholeFork, kFragmentName, kLoadNewCopy, &theConnectionID, (Ptr*) &exportedEntryPoint, params->errorMessage);
 
        if (err == noErr)
            err = FindSymbol(theConnectionID, kEntryPointName, &theEntryPoint, &theClass);
    
        if (err == noErr) {
            theRTD.routineRecords[0].procDescriptor = (ProcPtr) theEntryPoint;
            if (onPowerPC()) {
                theRTD.routineRecords[0].ISA = kPowerPCISA | kPowerPCRTA;
            } else {
                theRTD.routineRecords[0].ISA = kM68kISA | kCFM68kRTA;
            }
            theDescriptor = (ModuleProcPtr) &theRTD;
        }
    }
    
    if (theDescriptor && (err == noErr)) {
        err = (*theDescriptor)(storage, rgn, msg, params);
    }
 
    if (msg == Close || err != noErr || msg >= ButtonMessage) {
        CloseConnection(&theConnectionID);
 
    }
 
    ExitCodeResource();
    return err;
}