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]

 
AAPL
$97.03
Apple Inc.
-0.16
MSFT
$44.40
Microsoft Corpora
-0.47
GOOG
$593.35
Google Inc.
-2.63

MacTech Search:
Community Search:

Software Updates via MacUpdate

Audio Hijack Pro 2.11.0 - Record and enh...
Audio Hijack Pro drastically changes the way you use audio on your computer, giving you the freedom to listen to audio when you want and how you want. Record and enhance any audio with Audio Hijack... Read more
Intermission 1.1.1 - Pause and rewind li...
Intermission allows you to pause and rewind live audio from any application on your Mac. Intermission will buffer up to 3 hours of audio, allowing users to skip through any assortment of audio... Read more
Airfoil 4.8.7 - Send audio from any app...
Airfoil allows you to send any audio to AirPort Express units, Apple TVs, and even other Macs and PCs, all in sync! It's your audio - everywhere. With Airfoil you can take audio from any... Read more
Microsoft Remote Desktop 8.0.8 - Connect...
With Microsoft Remote Desktop, you can connect to a remote PC and your work resources from almost anywhere. Experience the power of Windows with RemoteFX in a Remote Desktop client designed to help... Read more
xACT 2.30 - Audio compression toolkit. (...
xACT stands for X Aaudio Compression Toolkit, an application that encodes and decodes FLAC, SHN, Monkey’s Audio, TTA, Wavpack, and Apple Lossless files. It also can encode these formats to MP3, AAC... Read more
Firefox 31.0 - Fast, safe Web browser. (...
Firefox for Mac offers a fast, safe Web browsing experience. Browse quickly, securely, and effortlessly. With its industry-leading features, Firefox is the choice of Web development professionals... Read more
Little Snitch 3.3.3 - Alerts you to outg...
Little Snitch gives you control over your private outgoing data. Track background activityAs soon as your computer connects to the Internet, applications often have permission to send any... Read more
Thunderbird 31.0 - Email client from Moz...
As of July 2012, Thunderbird has transitioned to a new governance model, with new features being developed by the broader free software and open source community, and security fixes and improvements... Read more
Together 3.2 - Store and organize all of...
Together helps you organize your Mac, giving you the ability to store, edit and preview your files in a single clean, uncluttered interface. Smart storage. With simple drag-and-drop functionality,... Read more
Cyberduck 4.5 - FTP and SFTP browser. (F...
Cyberduck is a robust FTP/FTP-TLS/SFTP browser for the Mac whose lack of visual clutter and cleverly intuitive features make it easy to use. Support for external editors and system technologies such... Read more

Latest Forum Discussions

See All

LEX Goes Free For One Day In Honor of Ne...
LEX Goes Free For One Day In Honor of New Update Posted by Jennifer Allen on July 24th, 2014 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Thomas Was Alone Goes Universal, Slashes...
Thomas Was Alone Goes Universal, Slashes Price to $3.99 Posted by Ellis Spice on July 24th, 2014 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Meerkatz Challenge Review
Meerkatz Challenge Review By Jennifer Allen on July 24th, 2014 Our Rating: :: FONDLY PUZZLINGUniversal App - Designed for iPhone and iPad Cute and challenging, Meerkatz Challenge is a fun puzzle game, particularly for fans of... | Read more »
Book Your Appointment with F.E.A.R. this...
Book Your Appointment with F.E.A.R. | Read more »
It Came From Canada: Epic Skater
For all the hate that it gets for being a pastime for slackers, skateboarding really does require a lot of skill. All those flips and spins take real athleticism, and there’s all the jargon to memorize. Fortunately for us less extreme individuals,... | Read more »
Cultures Review
Cultures Review By Jennifer Allen on July 24th, 2014 Our Rating: :: SLOW-PACED EMPIRE BUILDINGiPad Only App - Designed for the iPad Cute it might seem, but Cultures is a bit too slow paced when it comes to those pesky timers to... | Read more »
More Paintings Have Been Added to Paint...
More Paintings Have Been Added to Paint it Back! Posted by Jessica Fisher on July 24th, 2014 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
The Order of Souls Review
The Order of Souls Review By Campbell Bird on July 24th, 2014 Our Rating: :: STORY GRINDUniversal App - Designed for iPhone and iPad The Order of Souls is a free-to-play, turn-based RPG with a genre-mixing art style, interesting... | Read more »
Revolution 60 Review
Revolution 60 Review By Jordan Minor on July 24th, 2014 Our Rating: :: LASS EFFECTUniversal App - Designed for iPhone and iPad Revolution 60 is a bold, cinematic action game with ambition to spare.   | Read more »
Matter (Photography)
Matter 1.0.1 Device: iOS Universal Category: Photography Price: $1.99, Version: 1.0.1 (iTunes) Description: Add stunning 3D effects to your photos with real-time shadows and reflections. Export your creations as photos or video loops... | Read more »

Price Scanner via MacPrices.net

Save on 5th generation refurbished iPod touch...
The Apple Store has Apple Certified Refurbished 5th generation iPod touches available starting at $149. Apple’s one-year warranty is included with each model, and shipping is free. Many, but not all... Read more
What Should Apple’s Next MacBook Priority Be;...
Stabley Times’ Phil Moore says that after expanding its iMac lineup with a new low end model, Apple’s next Mac hardware decision will be how it wants to approach expanding its MacBook lineup as well... Read more
ArtRage For iPhone Painting App Free During C...
ArtRage for iPhone is currently being offered for free (regularly $1.99) during Comic-Con San Diego #SDCC, July 24-27, in celebration of the upcoming ArtRage 4.5 and other 64-bit versions of the... Read more
With The Apple/IBM Alliance, Is The iPad Now...
Almost since the iPad was rolled out in 2010, and especially after Apple made a 128 GB storage configuration available in 2012, there’s been debate over whether the iPad is a serious tool for... Read more
MacBook Airs on sale starting at $799, free s...
B&H Photo has the new 2014 MacBook Airs on sale for up to $100 off MSRP for a limited time. Shipping is free, and B&H charges NY sales tax only. They also include free copies of Parallels... Read more
Apple 27″ Thunderbolt Display (refurbished) a...
The Apple Store has Apple Certified Refurbished 27″ Thunderbolt Displays available for $799 including free shipping. That’s $200 off the cost of new models. Read more
WaterField Designs Unveils Cycling Ride Pouch...
High end computer case and bag maker WaterField Designs of San Francisco now enters the cycling market with the introduction of the Cycling Ride Pouch – an upscale toolkit with a scratch-free iPhone... Read more
Kingston Digital Ships Large Capacity Near 1T...
Kingston Digital, Inc., the Flash memory affiliate of Kingston Technology Company, Inc.,has announced its latest addition to the SSDNow V300 series, the V310. The Kingston SSDNow V310 solid-state... Read more
Apple’s Fiscal Third Quarter Results; Record...
Apple has announced financial results for its fiscal 2014 third quarter ended June 28, 2014, racking up quarterly revenue of $37.4 billion and quarterly net profit of $7.7 billion, or $1.28 per... Read more
15-inch 2.0GHz MacBook Pro Retina on sale for...
B&H Photo has the 15″ 2.0GHz Retina MacBook Pro on sale for $1829 including free shipping plus NY sales tax only. Their price is $170 off MSRP. B&H will also include free copies of Parallels... Read more

Jobs Board

Project Manager / Business Analyst, WW *Appl...
…a senior project manager / business analyst to work within our Worldwide Apple Fulfillment Operations and the Business Process Re-engineering team. This role will work Read more
Sr. Manager, *Apple* Deployment Programs fo...
**Job Summary** Apple is seeking candidates for a new position on the Education Content and Technology team. iPad and Mac is in the hands of millions of teachers and Read more
Sr Software Lead Engineer, *Apple* Online S...
Sr Software Lead Engineer, Apple Online Store Publishing Systems Keywords: Company: Apple Job Code: E3PCAK8MgYYkw Location (City or ZIP): Santa Clara Status: Full Read more
Senior Interaction Designer, *Apple* Online...
**Job Summary** Apple is looking for a hands on Senior…will be a key player in designing for the Apple Online Store. The ideal designer will have a Read more
*Apple* Sales Chat Rep - Apple (United State...
…is looking for motivated, outgoing, and tech savvy individuals who want to offer Apple Customers an unparalleled customer experience over chat. At Apple , we believe Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.