_ReadXPRam
/_WriteXPRam
actually work
Offset (hex) | Length (dec) | Related to |
1 | 1 | Used by a system program _InternalWait
|
8 | 4 | Looks like the last 4 bytes of the regular PRAM (See IM, Vol II, OS Util) |
10 | 16 | Looks like the first 16 bytes of the regular PRAM (See IM, Vol II, OS Util) |
78 | 4 | Startup Disk info (apparently, SCSI id) |
7C | 2 | System Beep. As was pointed out earlier, it is
in fact an id (short int ) of the corresponding
'snd ' resource in the System file;accessed through the Sound control panel |
7E | 1 | Used by a system program _InitProcMenu
|
7F | 1 | Apparently it has something to do with the way windows and dialogs appear on the screen |
80 | 2 | Used by a system program _GetVideoDefault apparently, some default video settings |
82 | 6 | Hilite Color, apparently in the RGB format, set up through the Color control panel |
8A | 1 | Bit field: Memory/cache control flags
|
AF | 1 | Has something to do with the RAM disk size
|
B8 | 4 | A 32-bit field whose
|
BD | 33 | looks like the name of the default AppleTalk zone (in Str32 format)Used (and set!) by some system programs in ROM ,
|
DE | 2 | at addresses 8009d544 and 8009d73C
|
E0 | 4 | has something to do with the network: an AppleTalk active/inactive flag, and the selected network access (say, LocalTalk
or EtherTalk). See Chooser and Network control panel |
E4 | 12 | Latitude/Longitude of the place this Mac is at. Set up through the Map control panel |
xPRAM
settings, and restore them at a later moment:
PRAM
, and apparently all (or a part of) xPRAM
, although xPRAM
is not mentioned by name.
xPRAM
given the field's offset
and length
:
LEA buf,a0 ; where to get/put the info MOVE.W length,d0 SWAP d0 ; Length in the hi word of D0 MOVE.W offset,d0 ; Offset in the lo word of D0 DC.W $A051 or $A052 ; _ReadXPRam or _WriteXPRamOn return,
D0
contains 0
(no error) or -1
(failure: say, the offset
is not within the 256-byte xPRAM
).xPRAM
: set the offset
to 0
and the length
to 256
. Note, some old Mac models (II's and IIx's) had a bug in their ROM that prevents from writing the very last byte of xPRAM
(offset=255
).
size
bytes of the xPRAM
into a (previously allocated) buffer where
, starting from the beginning of xPRAM
:
// This is // CLR.L D0 offset would be 0 // MOVE.W (A7)+,D0 size -> lo word of d0 // SWAP D0 size -> hi word of d0 // MOVEA.L (A7)+,A0 where -> A0 // _ReadXPRam pascal void read_extended_PRAM(char * where, const short size) = { 0x4280, 0x301F, 0x4840, 0x205F, 0xA051 };When I wrote this code, I had only Symantec C++ 6.0.1 compiler, which didn't permit
asm{}
inlines in C++ code. So I had to code in hex...
Writing to xPRAM
is similar to reading, only one has to use trap A052
rather than A051
. The following function writes size
bytes from a buffer where
into xPRAM
, starting at offset
:
// This is // MOVE.L (A7)+,D0 // MOVEA.L (A7)+,A0 where -> A0 // _WriteXPRam pascal void write_extended_PRAM (const char * where, const short offset, const short size) = {0x201F, 0x205F, 0xA052};
A051
/A052
traps in MacsBug):0x50f00000
(or something like this).
xPRAM
layout_ReadXPRam
/_WriteXPRam
are not documented, let alone the xPRAM
.A051
(_ReadXPRam
) and A052
(_WriteXPRam
), and let the system go on booting and run. I played with all control panels and watched if setting/resetting some values ends up in the debugger. There, a mere peek at the contents of D0
will tell everything: the location (byte-offset) in xPRAM
that is being read/written is in the lower-order word of D0
, and the size of the data is in the high-order-word. This is exactly the way I reengineered the xPRAM
map (well, I also disassembled a few control panels, e.g., Sound, Cache, and Memory)
.cpt.hqx
, 29K]
// 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 offset would be 0 // MOVE.W $4(A7),D0 size -> lo word of d0 // SWAP D0 size -> hi word of d0 // MOVEA.L 6(A7),A0 where -> 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]); } }I tested the code on PowerMac 7100/80 and 8500/132, using CodeWarrior C++ versions 9 and 12.
oleg-at-okmij.org