TweetFollow Us on Twitter

Mar 96 Tips
Volume Number:12
Issue Number:3
Column Tag:Tips & Tidbits

Tips & Tidbits

By Steve Sisak, Contributing Editor

Note: Source code files accompanying article are located on MacTech CD-ROM or source code disks.

Calling PowerPC Code
From 68K Code

There is a lot of information out there about calling 68K code from PowerPC code, but there is very little about calling PowerPC code from 68K code.

Here is a nice method for calling PowerPC code from 68K code. I am using CodeWarrior 7. This is a bit lengthy so hang in there:

There are three steps required to get things up and running. Let’s look at a sample scenario:

You have a 68K application that you just can’t convert to PowerPC code (I don’t know why you can’t convert it, but just bear with me), but you can take some of the time-critical code and convert it to a PowerPC shared library and call it from the 68K code.

Suppose you have two functions that perform data compression:

long  CompressData(  unsigned char *inBuffer, 
 unsigned char *outBuffer,
 unsigned long inBufferSize );
   
long  UncompressData(unsigned char *inBuffer, 
 unsigned char *outBuffer, 
 unsigned long inBufferSize );

Step 1 - Create a PPC shared library containing your functions.

We are going to export these functions using the #pragma export directive. This is set in the PPC Prefs area of Codewarrior preferences.

“the shared library”
// Prototypes

#pragma export on

#ifdef __cplusplus
extern "C" {
#endif

long  CompressData(  unsigned char *inBuffer, 
 unsigned char *outBuffer, 
 unsigned long inBufferSize );
   
long  UncompressData(   unsigned char *inBuffer,
 unsigned char *outBuffer,
 unsigned long inBufferSize );

#ifdef __cplusplus
}
#endif

#pragma export off
// CompressData

long  CompressData( unsigned char *inBuffer, unsigned char 
   *outBuffer, unsigned long inBufferSize )
{
    ... compress data code
}

// UncompressData
   
long  UncompressData( unsigned char *inBuffer, unsigned char 
     *outBuffer, unsigned long inBufferSize )
{
    ... uncompress data code
}

Set the project type to a shared library and build the project. We now have a PowerPC shared library that we will use in Step 2.


Step 2 - Create a resource-based PEF Fragment that references our shared library.

We create a header file that defines some mixed mode information.

“the header file”
#ifdef __cplusplus
extern "C" {
#endif

typedef long (*CompressDataProcPtr)( unsigned char *inBuffer, 
 unsigned char *outBuffer, unsigned long inBufferSize );
typedef long (*UncompressDataProcPtr)( unsigned char *inBuffer, 
 unsigned char *outBuffer, unsigned long inBufferSize);

#if GENERATINGCFM || USESROUTINEDESCRIPTORS

typedef UniversalProcPtr CompressDataUPP;
typedef UniversalProcPtr UncompressDataUPP;

enum {
 uppCompressDataProcInfo = kCStackBased
 | RESULT_SIZE( SIZE_CODE( sizeof( long ) ) )
 | STACK_ROUTINE_PARAMETER( 1, SIZE_CODE( 
 sizeof( unsigned char *) ) )
 | STACK_ROUTINE_PARAMETER( 2, SIZE_CODE( 
 sizeof( unsigned char *) ) ) | STACK_ROUTINE_PARAMETER( 3, SIZE_CODE( 

 sizeof( long ) ) )
};

enum {
 uppUncompressDataProcInfo = kCStackBased
 | RESULT_SIZE( SIZE_CODE( sizeof( long ) ) )
 | STACK_ROUTINE_PARAMETER( 1, SIZE_CODE( 
 sizeof( unsigned char *) ) )
 | STACK_ROUTINE_PARAMETER( 2, SIZE_CODE( 
 sizeof( unsigned char *) ) )
 | STACK_ROUTINE_PARAMETER( 3, SIZE_CODE( 
 sizeof( long ) ) )
};

#else

typedef CompressDataProcPtr CompressDataUPP;
typedef UncompressDataProcPtr UncompressDataUPP;
#endif

//============================================================
// Extern Globals
//

#ifndef powerc

extern CompressDataUPP    myCompressDataUPP;
extern UncompressDataUPP  myUncompressDataUPP;

#endif

//============================================================
// Macros
//

#if GENERATINGPOWERPC || defined(powerc) || defined (__powerc)

#define myCompressData( a, b, c )  CompressData( a, b, c )
#define myUncompressData( a, b, c )UncompressData( a, b, c )

#else

#define myCompressData( a, b, c ) \  
 (*(CompressDataUPP)myCompressDataUPP( a, b, c )
#define myUncompressData( a, b, c  ) \
 (*(CompressDataUPP)myUncompressDataUPP( a, b, c )

#endif

//============================================================
// Prototypes
//

long CompressData( unsigned char *inBuffer, unsigned char 
    *outBuffer, unsigned long inBufferSize );
long UncompressData( unsigned char *inBuffer, unsigned char 
  *outBuffer, unsigned long inBufferSize );

#ifdef __cplusplus
}
#endif

Now we define the source file:

“the source file”
#include "the header file"

#ifdef __cplusplus
extern "C" {
#endif

#if GENERATINGPOWERPC || defined(powerc) || defined (__powerc)
#pragma options align=mac68k
#endif

#ifdef __CFM68K__
#pragma lib_export on
#endif

RoutineDescriptorCompressDataRD = 
 BUILD_ROUTINE_DESCRIPTOR(  uppCompressDataProcInfo, 
 CompressData );

RoutineDescriptorUncompressDataRD = 
 BUILD_ROUTINE_DESCRIPTOR(  uppUncompressDataProcInfo, 
 UncompressData );


#ifdef __CFM68K__
#pragma lib_export off
#endif

#if GENERATINGPOWERPC || defined(powerc) || defined (__powerc)
#pragma options align=reset
#endif

#ifdef __cplusplus
}
#endif

Add the shared library we built in Step 1 to this project.

Set the project type to shared library and build the project. We now have a PowerPC shared library that we want to convert to a resource. (Note: we don’t export this as a PowerPC code resource with no header, since we would get link errors for an undefined main entry.)

Open the file up in a resource editor and create a new resource (I use a type of 'PEF ', but any will do). Move the PEF code from the data fork into this resource. (If your resource editor will not do this, then it is a simple matter of creating a small application that will do this for you; this excercise is left for the reader.)

We now have a resource file that we will add to our 68K project.


Step 3 - Add 68K support code to your project

Your 68K project needs to have a bit of support code to get the code resource and load it in as a code fragment. Add to your code:

#include "the header file"

We need to declare some globals for the universal procs that will store the address of the routine descriptors. Add to your code:

#ifndef powerc
CompressDataUPP  myCompressDataUPP;
UncompressDataUPPmyUncompressDataUPP;
#endif

The following function takes care of checking for the existence of the CFM and Mixed Mode managers. We pass it a pointer to a CFragConnectionID variable and a Handle variable, which we will use later on for clean up. Add to your code:

#ifndef powerc

// SetupPPCNativeCode

OSErr SetupPPCNativeCode( CFragConnectionID *connID, 
 Handle *PEFHandle,
   ResType codeFragmentType, 
 short codeFragmentID )
{
 OSErr  theErr = noErr;
 long   templong;
 Str255 failedFragName;
 

    // get PEF container resource from our resource fork
 
 *PEFHandle = ::Get1Resource( codeFragmentType, codeFragmentID );
 theErr = ::ResError();
 if( !(*PEFHandle) )
 {
 if( theErr )  
 return( theErr );
 else
 return( ::MemError() );
 }
 
    // Check for Mixed Mode Manager and Code Fragment Manager (CFM)
 
 Boolean  hasMixedMode = !Gestalt( gestaltMixedModeAttr, 
 &templong );
 Boolean  hasCFM = !Gestalt( gestaltCFMAttr, &templong );
 
 theErr = Gestalt( gestaltSysArchitecture, &templong );
 if( ( theErr ) || 
 ( templong == gestalt68k ) ||
 ( !hasCFM ) ||
 ( !hasMixedMode ) )
 {
 ::ReleaseResource( *PEFHandle );
 return( -1 );
 }
 
 DetachResource( *PEFHandle );
 MoveHHi( *PEFHandle );
 HLock( *PEFHandle );
 
    // Assume this is PowerPC code, so it must be “prepared”
 
 theErr = ::GetMemFragment( (Ptr)**PEFHandle, 0, 0,            
 kNewCFragCopy, connID, 0, failedFragName );
 if( theErr )
 {
 DisposeHandle( *PEFHandle );
 return( theErr );
 }

 CFragSymbolClassmyClass;
 
 if( !theErr )
 theErr = ::FindSymbol( *connID, 
    (ConstStr255Param)"\pCompressDataRD", 
    (Ptr*)&myCompressDataUPP, 
    &myClass );
 if( !theErr )
 theErr = ::FindSymbol( *connID, 
    (ConstStr255Param)"\pUncompressDataRD", 
    (Ptr*)&myUncompressDataUPP, 
    &myClass );

 if( theErr )
 {
 DisposeHandle( *PEFHandle );
 return( theErr );
 }
 
 return( noErr );
}

The following function takes the connection id and handle returned from SetupPPCNativeCode, frees the connection and disposes of the handle. Add to your code:

// TearDownPPCNativeCode

void TearDownPPCNativeCode( CFragConnectionID connID, Handle PEFHandle 
)
{
 ::CloseConnection( &connID );
 if( PEFHandle )
 ::DisposeHandle( PEFHandle );
}

#endif

Build your 68K project as you normally would and be sure to include the resource file we created in Step 2 and ensure the the shared library we created in Step 1 is either in the Extensions folder of the System Folder or in the same directory as the application.

Here is what you would do the call the PowerPC code from 68K:

long PowerPC_Compress( unsigned char *inBuffer, unsigned char 
    *outBuffer, unsigned long inBufferSize )
{
 #ifndef powerc
 
    // For efficiency you would probably put this call in initialization code.
    // sConnID and sPEFHandle are static globals.
 
 OSErr err = SetupPPCNativeCode( &sConnID, &sPEFHandle, 
 'PEF ', 128 );
 if( err )
 return( 0 );  // We couldn’t compress anything so return 0
 #endif
 
 long   result = 0;
 
 result = myCompressData( inBuffer, outBuffer, inBufferSize );
 
 #ifndef powerc
 
    // For efficiency you would probably put this call in termination code.
 
 TearDownPPCNativeCode( sConnID, sPEFHandle );
 #endif
}

long PowerPC_Uncompress( unsigned char *inBuffer, 
 unsigned char *outBuffer, unsigned long inBufferSize )
{
 #ifndef powerc
 
    // For efficiency you would probably put this call in initialization code.
    // sConnID and sPEFHandle are static globals.
 
 OSErr err = SetupPPCNativeCode( &sConnID, &sPEFHandle, 
 'PEF ', 128 );
 if( err )
 return( 0 );  // We couldn’t compress anything so return 0
 #endif
 
 long   result = 0;
 
 result = myUncompressData( inBuffer, outBuffer, inBufferSize );
 
 #ifndef powerc
 
    // For efficiency you would probably put this call in termination code.
 
 TearDownPPCNativeCode( sConnID, sPEFHandle );
 #endif
}


That’s all there is to it. Enjoy and happy coding.

- Chris Rudolph

[BuildRoutineDescriptor() doesn’t work right with CFM68k; use NewRoutineDescriptor() instead. BuildRoutineDescriptor() generates code so you need to call MakeDataExecutable() after it. - sgs]

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

BitTorrent Sync 2.0.82 - Sync files secu...
BitTorrent Sync allows you to sync unlimited files between your own devices, or share a folder with friends and family to automatically sync anything. File transfers are encrypted. Your information... Read more
Google Drive 1.20 - File backup and shar...
Google Drive is a place where you can create, share, collaborate, and keep all of your stuff. Whether you're working with a friend on a joint research project, planning a wedding with your fiancé, or... Read more
Simon 4.0.3 - Monitor changes and crashe...
Simon monitors websites and alerts you of crashes and changes. Select pages to monitor, choose your alert options, and customize your settings. Simon does the rest. Keep a watchful eye on your... Read more
Vitamin-R 2.23 - Personal productivity t...
Vitamin-R creates the optimal conditions for your brain to work at its best by structuring your work into short bursts of distraction-free, highly focused activity alternating with opportunities for... Read more
iDefrag 5.0.0 - Disk defragmentation and...
iDefrag helps defragment and optimize your disk for improved performance. Features include: Supports HFS and HFS+ (Mac OS Extended). Supports case sensitive and journaled filesystems. Supports... Read more
PCalc 4.2 - Full-featured scientific cal...
PCalc is a full-featured, scriptable scientific calculator with support for hexadecimal, octal, and binary calculations, as well as an RPN mode, programmable functions, and an extensive set of unit... Read more
FileZilla 3.10.2 - Fast and reliable FTP...
FileZilla (ported from Windows) is a fast and reliable FTP client and server with lots of useful features and an intuitive interface. Version 3.10.2: Note: Now requires a 64-bit Intel processor.... Read more
The Hit List 1.1.11 - Advanced reminder...
The Hit List manages the daily chaos of your modern life. It's easy to learn - it's as easy as making lists. And it's powerful enough to let you plan, then forget, then act when the time is right.... Read more
Bartender 1.2.32 - Organize your menu ba...
Bartender lets you organize your menu bar apps. Features: Lets you tidy your menu bar apps how you want. See your menu bar apps when you want. Hide the apps you need to run, but do not need to... Read more
ClamXav 2.7.5 - Free virus checker, base...
ClamXav is a free virus checker for OS X. It uses the tried, tested, and very popular ClamAV open source antivirus engine as a back end. I hope you like and use ClamXav a lot and that it helps keep... Read more

Protect Yourself from an Onslaught of Ca...
Surprise Attack Games has announced a Cat-astrophic new physics puzzler called Fort Meow! In the game, a young girl named Nia finds her grandfather’s journal which triggers an all mighty feline attack! Why do the cats want the journal? Who knows,... | Read more »
GDC 2015 – Jelly Reef will be Game Oven’...
GDC 2015 – Jelly Reef will be Game Oven’s Last Hurrah, and it Seems like a Good Note to Go Out on Posted by Rob Rich on March 4th, 2015 [ permalink ] It’s sad knowing that Game Oven ( | Read more »
daWindci Deluxe Review
daWindci Deluxe Review By Campbell Bird on March 4th, 2015 Our Rating: :: BLUSTERY PUZZLESUniversal App - Designed for iPhone and iPad This updated puzzle game offers some creative gameplay and new mechanics, but still suffers from... | Read more »
Dungeon Hunter 5 Coming on March 12
Gameloft has excitedly announced that Dungeon Hunter 5 is on its way! Once again, you will adventure across the land of Valenthia exploring dungeons and fighting monsters. The game will have a new asynchronous multiplayer mode called Strongholds... | Read more »
GDC 2015 – The Sandbox 2 is Coming, and...
GDC 2015 – The Sandbox 2 is Coming, and Now it has Textures! | Read more »
Warner Bros. Interactive Announces Mort...
Mortal Kombat X, by Warner Bros. and NetherRealm Studios, will be a a free-to-play fighting/card-battle Mortal Kombat game. The game promises card collecting, multiplayer team combat, classic characters such as Scorpion, Sub-Zero and Raiden, and the... | Read more »
GDC 2015 – Piloteer is Whitaker Trebella...
GDC 2015 – Piloteer is Whitaker Trebella’s Latest Project, and it’s Definitely Something DIfferent Posted by Rob Rich on March 3rd, 2015 [ permalink ] You know | Read more »
PangoLand Review
PangoLand Review By Amy Solomon on March 3rd, 2015 Our Rating: :: COME VISIT PANGO AND FRIENDSUniversal App - Designed for iPhone and iPad PangoLand is an open-ended world full of familiar characters, bright colors and interactive... | Read more »
Knights of Pen & Paper is Leveling U...
With the roll of a die and a critical success, Paradox Interactive has announced Knights of Pen & Paper 2! You’ll be taking your place at the table once again in this sequel to Knights of Pen & Paper +1 Edition. The game will introduce the... | Read more »
GDC 2015 – Project Highrise is an Intere...
GDC 2015 – Project Highrise is an Interesting Idea from SomaSim Posted by Rob Rich on March 3rd, 2015 [ permalink ] You might know SomaSim best from their gold rush sim, 1849< | Read more »

Price Scanner via MacPrices.net

Mac Pros on sale for up to $279 off MSRP
Amazon has Mac Pros in stock and on sale for up to $279 off MSRP. Shipping is free: - 4-Core Mac Pro: $2725.87, $273 off MSRP (9%) - 6-Core Mac Pro: $3719.99, $279 off MSRP (7%) Read more
Sale! 13-inch Retina MacBook Pros for up to $...
B&H Photo has 13″ Retina MacBook Pros on sale for up to $205 off MSRP. Shipping is free, and B&H charges NY sales tax only: - 13″ 2.6GHz/128GB Retina MacBook Pro: $1219.99 save $80 - 13″ 2.... Read more
Another Tranche Of IBM MobileFirst For iOS Ap...
IBM has announced the next expansion phase for  its IBM MobileFirst for iOS portfolio, with a troika of new apps to address key priorities for the Banking and Financial Services, Airline and Retail... Read more
Sale! 15-inch Retina MacBook Pros for up to $...
B&H Photo has the new 2014 15″ Retina MacBook Pros on sale for up to $250 off MSRP for a limited time. Shipping is free, and B&H charges NY sales tax only: - 15″ 2.2GHz Retina MacBook Pro: $... Read more
WaterField Designs Introduces the Minimalist...
With Apple Pay gaining popularity, Android Pay coming in May 2015, and loyalty cards and receipts that can be accessed from smartphones, San Francisco’s WaterField Designs observes that it may be... Read more
Sale! 15-inch 2.2GHz Retina MacBook Pro for $...
 Best Buy has the 15″ 2.2GHz Retina MacBook Pro on sale for $1774.99 $1799.99, or $225 off MSRP. Choose free home shipping or free local store pickup (if available). Price valid for online orders... Read more
13-inch 2.5GHz MacBook Pro (refurbished) avai...
The Apple Store has Apple Certified Refurbished 13″ 2.5GHz MacBook Pros available for $170 off the cost of new models. Apple’s one-year warranty is standard, and shipping is free: - 13″ 2.5GHz... Read more
13-inch 2.5GHz MacBook Pro on sale for $100 o...
B&H Photo has the 13″ 2.5GHz MacBook Pro on sale for $999.99 including free shipping plus NY sales tax only. Their price is $100 off MSRP. Read more
27-inch 3.5GHz 5K iMac in stock today and on...
 B&H Photo has the 27″ 3.5GHz 5K iMac in stock today and on sale for $2299 including free shipping plus NY sales tax only. Their price is $200 off MSRP, and it’s the lowest price available for... Read more
Apple Launches Free Web-Based Pages and Other...
Apple’s new Web-only access to iWork productivity apps is a free level of iCloud service available to anyone, including people who don’t own or use Apple devices. The service includes access to Apple... Read more

Jobs Board

*Apple* Solutions Consultant - Retail Sales...
**Job Summary** As an Apple Solutions Consultant (ASC) you are the link between our customers and our products. Your role is to drive the Apple business in a retail Read more
*Apple* Pay Automation Engineer - iOS System...
**Job Summary** At Apple , great ideas have a way of becoming great products, services, and customer experiences very quickly. Bring passion and dedication to your job Read more
Sr. Technical Services Consultant, *Apple*...
**Job Summary** Apple Professional Services (APS) has an opening for a senior technical position that contributes to Apple 's efforts for strategic and transactional Read more
Event Director, *Apple* Retail Marketing -...
…This senior level position is responsible for leading and imagining the Apple Retail Team's global engagement strategy and team. Delivering an overarching brand Read more
*Apple* Pay - Site Reliability Engineer - Ap...
**Job Summary** Imagine what you could do here. At Apple , great ideas have a way of becoming great products, services, and customer experiences very quickly. Bring Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.