May 97 Tips
Volume Number: 13 (1997)
Issue Number: 5
Column Tag: Tips & Tidbits
Tips & Tidbits
By Steve Sisak
File Manager Tip
If you've got a program, such as a compiler, which creates a temporary file, writes and reads from it, and then no longer needs the data, don't just close it and delete it; doing so usually causes the temporary data to be written to disk. Before closing it, call SetEOF(fRefNum, 0); This tells the disk cache that none of the data associated with the file need ever be written.
Jorg Brown
brown@connectix.com
Running m68k Codes "Compiled-in" (embedded) in a PowerPC Program
Here is a tip I bumped into recently. I wanted to run a sequence of m68k instructions (actually, to perform a system trap) on a PowerMac. Usually, this is a trivial task: compile the code in the 68k universe (for example, with in-line assembly supported by many m68k C/C++ compilers). From within a PowerPC application, one can call PowerPC glue code to the trap, which is probably present in the InterfaceLib'.
Unfortunately, neither of these easy options would apply in my case: I only have a PowerPC compiler (I don't have disk space to install both 68k and PowerPC parts of the CodeWarrior). The trap I wanted to call (_ReadXPRam), is not an "official" one, thus there is no glue code for it in PowerPC libraries. Nevertheless, I found an easy way to run a sequence of 68k codes "compiled in" a PowerPC executable, and pass data in and out. By the way, this is working code that prints the contents of the xPRAM (more on xPRAM can be found at http://pobox.com/~oleg/ftp/xPRAM.html).
// Printing out the contents of the xPRAM
// The trick is that _ReadXPRam/_WriteXPRam traps are available only
// from within 68K universe. So, if this code runs in the PowerPC mode,
// we've got to switch universes before running M68K code sequences...
#include <stdio.h>
#include <MixedMode.h>
// This is
// CLR.L D0 address would be 0
// MOVE.W $4(A7),D0 size -> lo word of d0
// SWAP D0 size -> hi word of d0
// MOVEA.L 6(A7),A0where -> A0
// _ReadXPRam
// MOVEA.L (A7)+,A0 standard PASCAL epilogue
// ADDQ.W #$6,A7
// JMP (A0)
// RTS
// This is a sequence of M68K instructions; unfortunately,
// a PowerMac compiler doesn't understand them. So we've
// got to assemble by hand <sigh>
//
// BTW, to write into xPRAM, replace 0xA051 in the sequence
// below with 0xA052
//pascal void read_extended_PRAM(char * where, const short size) =
static short read_extended_PRAM []=
{ 0x4280, 0x302F, 0x0004, 0x206F, 0x006, 0x4840, 0xA051, 0x205F, 0x5C4F,
0x4ED0 };
#define COMP_NORET_2(name, a1, a2) \
name##_procinfo = kPascalStackBased \
| STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(a1))) \
| STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(a2)))
#define RD_ALLOC(routine) static RoutineDescriptor \
routine##_RD = BUILD_ROUTINE_DESCRIPTOR \
(routine##_procinfo, routine)
enum {
COMP_NORET_2(read_extended_PRAM,char *,const short)
};
void main(void)
{
unsigned char whole_xPRAM_buffer[256];
UniversalProcPtr u_read_extended_PRAM =
NewRoutineDescriptor((long (*)())read_extended_PRAM,
read_extended_PRAM_procinfo,
kM68kISA);
CallUniversalProc(u_read_extended_PRAM,
read_extended_PRAM_procinfo,
whole_xPRAM_buffer,
sizeof(whole_xPRAM_buffer));
DisposeRoutineDescriptor(u_read_extended_PRAM);
printf("\ncontents of the xPRAM\n");
for(register int i=0; i<sizeof(whole_xPRAM_buffer); i+=16)
{
printf("\n%04x ",i);
for(register int j=0; j<16; j++)
printf("%s%02x", j%4 == 0 ? " " : "",
whole_xPRAM_buffer[i+j]);
}
}
Oleg Kiselyov
oleg@pobox.com