mirror of
https://github.com/elliotnunn/supermario.git
synced 2024-11-25 09:30:50 +00:00
368 lines
11 KiB
C
368 lines
11 KiB
C
|
/*
|
|||
|
File: MixedMode.h
|
|||
|
|
|||
|
Contains: Headers and interfaces for the Mixed Mode mechanism
|
|||
|
|
|||
|
Written by: Bruce Jones
|
|||
|
|
|||
|
Copyright: © 1992 by Apple Computer, Inc., all rights reserved.
|
|||
|
|
|||
|
Change History (most recent first):
|
|||
|
|
|||
|
<1> 12/7/92 DRF first checked in
|
|||
|
<18> 11/13/92 DRF Fix a bug in BuildRoutineDescriptor macro. We were building
|
|||
|
kLoadAndExecute RDs and not kExecute types! Of course,
|
|||
|
CodeFragMgrDispatch and MixedModeDispatch were the only two
|
|||
|
users of this macro, so nobody knew it was broken.
|
|||
|
<17> 11/8/92 BKJ Rolled back
|
|||
|
<13+> 10/26/92 SP Adding definition for m68KRegisterSizePhase
|
|||
|
<13> 10/22/92 DRF Added inline 68K trap glue for NewRoutineDescriptor and
|
|||
|
DisposeRoutineDescriptor
|
|||
|
<12> 10/19/92 DRF Changed declaration of NewRoutineDescriptor and
|
|||
|
DisposeRoutineDescriptor to match Sean’s clearer syntax.
|
|||
|
<11> 10/13/92 SP Changing all m68k's to m68K
|
|||
|
<10> 10/08/92 SP Adding phase and offset enum for the parameters.
|
|||
|
<9> 10/4/92 BKJ Current version is 1
|
|||
|
<8> 10/1/92 jrg Made smaller enum blocks and changed typedef for InterfaceTool
|
|||
|
<7> 9/29/92 BKJ Fix bug in BuildRoutineDescriptor macro.
|
|||
|
<6> 9/28/92 stb add special cases as used by the rest of the public interfaces
|
|||
|
<5> 9/18/92 LC changing kGoMixedMode to 0xFEED0000
|
|||
|
<4> 9/10/92 EPT Added (long) typecasts to enum constants. Changed constants to
|
|||
|
conform to new procInfo definition.
|
|||
|
<3> 9/9/92 LC Added Macro "BuildRoutineDescriptor, which allows static
|
|||
|
declaration of a routine descriptor at compile time. In order
|
|||
|
to have this macro, many private declarations had to be brought
|
|||
|
over from MixedModeApplePrivate.h, including kGoMixedMode, and
|
|||
|
kMixedModeMagicCookie.
|
|||
|
<2> 9/2/92 BKJ Get rid of numParams parameter to BuildProcInfo &
|
|||
|
CallRoutineDescriptor calls.
|
|||
|
<1> 9/1/92 BKJ first checked in
|
|||
|
8/28/92 BKJ change to reflect latest ERS
|
|||
|
6/5/92 BKJ Continued Development
|
|||
|
4/17/92 BKJ Created
|
|||
|
|
|||
|
*/
|
|||
|
|
|||
|
|
|||
|
|
|||
|
#ifndef __MIXEDMODE__
|
|||
|
#define __MIXEDMODE__
|
|||
|
|
|||
|
#ifndef __TYPES__
|
|||
|
#include <Types.h>
|
|||
|
#endif
|
|||
|
|
|||
|
#define kGoMixedMode 0xFEED0000
|
|||
|
|
|||
|
#define kMixedModeMagicCookie 0x4B4F4348
|
|||
|
|
|||
|
#define PARAMETER_SIZE(size) \
|
|||
|
(((size) == 4) ? 3 : (((size) == 2) ? 1 : (((size) == 1) ? 2 : 0)))
|
|||
|
|
|||
|
enum {
|
|||
|
kResultPhase = 4, /* bit offset for result field */
|
|||
|
kParameterPhase = 6,
|
|||
|
kParameterOffset = 2,
|
|||
|
m68KRegisterOffset = 6,
|
|||
|
m68KRegisterOut = 0x20,
|
|||
|
m68KRegisterIn = 0x10,
|
|||
|
m68KRegisterParameterPhase = 2,
|
|||
|
m68KRegisterA0 = 0,
|
|||
|
m68KRegisterA1 = 1,
|
|||
|
m68KRegisterD0 = 2,
|
|||
|
m68KRegisterD1 = 3
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
enum {
|
|||
|
kPStackBased = 0,
|
|||
|
kCStackBased = 1,
|
|||
|
kRegisterBased = 2,
|
|||
|
kD0DispStackBased = 8,
|
|||
|
kD1DispStackBased = 12,
|
|||
|
kStackDispStackBased = 14,
|
|||
|
kStackDispRegisterBased = 10,
|
|||
|
kSpecialCaseProcInfoType = 5
|
|||
|
};
|
|||
|
typedef short CallingConventionType;
|
|||
|
|
|||
|
|
|||
|
enum {
|
|||
|
// the Mixed Mode error codes
|
|||
|
mmInternalError = -2526,
|
|||
|
kMMErr2 = -2527,
|
|||
|
kMMErr3 = -2528,
|
|||
|
kMMErr4 = -2529,
|
|||
|
kMMErr5 = -2530,
|
|||
|
kMMErr6 = -2531,
|
|||
|
kMMErr7 = -2532,
|
|||
|
kMMErr8 = -2533,
|
|||
|
kMMErr9 = -2534,
|
|||
|
kMMErr10 = -2535
|
|||
|
};
|
|||
|
typedef short MMErrType;
|
|||
|
|
|||
|
enum {
|
|||
|
kRegisterD0 = 0,
|
|||
|
kRegisterD1,
|
|||
|
kRegisterD2,
|
|||
|
kRegisterD3,
|
|||
|
kRegisterD4,
|
|||
|
kRegisterD5,
|
|||
|
kRegisterD6,
|
|||
|
kRegisterD7,
|
|||
|
kRegisterA0,
|
|||
|
kRegisterA1,
|
|||
|
kRegisterA2,
|
|||
|
kRegisterA3,
|
|||
|
kRegisterA4,
|
|||
|
kRegisterA5,
|
|||
|
kRegisterA6,
|
|||
|
kRegisterA7
|
|||
|
};
|
|||
|
typedef short RegisterSelectorType;
|
|||
|
|
|||
|
enum {kLoadAndExecute = 0, kExecute, kReturnFrom};
|
|||
|
typedef short SelectorType;
|
|||
|
|
|||
|
enum {kCodeTypeUnknown = -1, kCodeTypeCurrentWorld, kCodeType68K, kCodeTypePower};
|
|||
|
typedef long CodeType;
|
|||
|
|
|||
|
typedef long ProcInfoType;
|
|||
|
|
|||
|
typedef struct private_RoutineDescriptor* RoutineDescriptor;
|
|||
|
|
|||
|
|
|||
|
/* ProcInfo selectors for each of the parameters */
|
|||
|
|
|||
|
/* Pascal and C Stack based parameter constants */
|
|||
|
/* Stack-based dispatched uses these, but only P2 and up */
|
|||
|
enum {
|
|||
|
m68KStackP1Byte = (long)0x00000080,
|
|||
|
m68KStackP1Word = (long)0x00000040,
|
|||
|
m68KStackP1Long = (long)0x000000C0,
|
|||
|
m68KStackP2Byte = (long)0x00000200,
|
|||
|
m68KStackP2Word = (long)0x00000100,
|
|||
|
m68KStackP2Long = (long)0x00000300,
|
|||
|
m68KStackP3Byte = (long)0x00000800,
|
|||
|
m68KStackP3Word = (long)0x00000400,
|
|||
|
m68KStackP3Long = (long)0x00000C00,
|
|||
|
m68KStackP4Byte = (long)0x00002000,
|
|||
|
m68KStackP4Word = (long)0x00001000,
|
|||
|
m68KStackP4Long = (long)0x00003000,
|
|||
|
m68KStackP5Byte = (long)0x00008000,
|
|||
|
m68KStackP5Word = (long)0x00004000,
|
|||
|
m68KStackP5Long = (long)0x0000C000,
|
|||
|
m68KStackP6Byte = (long)0x00020000,
|
|||
|
m68KStackP6Word = (long)0x00010000,
|
|||
|
m68KStackP6Long = (long)0x00030000,
|
|||
|
m68KStackP7Byte = (long)0x00080000,
|
|||
|
m68KStackP7Word = (long)0x00040000,
|
|||
|
m68KStackP7Long = (long)0x000C0000,
|
|||
|
m68KStackP8Byte = (long)0x00200000,
|
|||
|
m68KStackP8Word = (long)0x00100000,
|
|||
|
m68KStackP8Long = (long)0x00300000,
|
|||
|
m68KStackP9Byte = (long)0x00800000,
|
|||
|
m68KStackP9Word = (long)0x00400000,
|
|||
|
m68KStackP9Long = (long)0x00C00000,
|
|||
|
m68KStackP10Byte = (long)0x02000000,
|
|||
|
m68KStackP10Word = (long)0x01000000,
|
|||
|
m68KStackP10Long = (long)0x03000000,
|
|||
|
m68KStackP11Byte = (long)0x08000000,
|
|||
|
m68KStackP11Word = (long)0x04000000,
|
|||
|
m68KStackP11Long = (long)0x0C000000,
|
|||
|
m68KStackP12Byte = (long)0x20000000,
|
|||
|
m68KStackP12Word = (long)0x10000000,
|
|||
|
m68KStackP12Long = (long)0x30000000,
|
|||
|
m68KStackP13Byte = (long)0x80000000,
|
|||
|
m68KStackP13Word = (long)0x40000000,
|
|||
|
m68KStackP13Long = (long)0xC0000000
|
|||
|
};
|
|||
|
|
|||
|
enum {
|
|||
|
/* Register based parameter constants */
|
|||
|
/* Also used for register-based dispatching */
|
|||
|
m68KRegisterP1In = (long)0x00000400,
|
|||
|
m68KRegisterP1Out = (long)0x00000800,
|
|||
|
m68KRegisterP1InOut = (long)0x00000C00,
|
|||
|
m68KRegisterP2In = (long)0x00010000,
|
|||
|
m68KRegisterP2Out = (long)0x00020000,
|
|||
|
m68KRegisterP2InOut = (long)0x00030000,
|
|||
|
m68KRegisterP3In = (long)0x00400000,
|
|||
|
m68KRegisterP3Out = (long)0x00800000,
|
|||
|
m68KRegisterP3InOut = (long)0x00C00000,
|
|||
|
m68KRegisterP4In = (long)0x10000000,
|
|||
|
m68KRegisterP4Out = (long)0x20000000,
|
|||
|
m68KRegisterP4InOut = (long)0x30000000
|
|||
|
};
|
|||
|
|
|||
|
enum {
|
|||
|
m68KRegisterP1Byte = (long)0x00000200,
|
|||
|
m68KRegisterP1Word = (long)0x00000100,
|
|||
|
m68KRegisterP1Long = (long)0x00000300,
|
|||
|
m68KRegisterP2Byte = (long)0x00008000,
|
|||
|
m68KRegisterP2Word = (long)0x00004000,
|
|||
|
m68KRegisterP2Long = (long)0x0000C000,
|
|||
|
m68KRegisterP3Byte = (long)0x00200000,
|
|||
|
m68KRegisterP3Word = (long)0x00100000,
|
|||
|
m68KRegisterP3Long = (long)0x00300000,
|
|||
|
m68KRegisterP4Byte = (long)0x08000000,
|
|||
|
m68KRegisterP4Word = (long)0x04000000,
|
|||
|
m68KRegisterP4Long = (long)0x0C000000
|
|||
|
};
|
|||
|
|
|||
|
enum {
|
|||
|
m68KRegisterP1A0 = (long)0x00000000,
|
|||
|
m68KRegisterP1A1 = (long)0x00000040,
|
|||
|
m68KRegisterP1D0 = (long)0x00000080,
|
|||
|
m68KRegisterP1D1 = (long)0x000000C0,
|
|||
|
m68KRegisterP2A0 = (long)0x00000000,
|
|||
|
m68KRegisterP2A1 = (long)0x00001000,
|
|||
|
m68KRegisterP2D0 = (long)0x00002000,
|
|||
|
m68KRegisterP2D1 = (long)0x00003000,
|
|||
|
m68KRegisterP3A0 = (long)0x00000000,
|
|||
|
m68KRegisterP3A1 = (long)0x00040000,
|
|||
|
m68KRegisterP3D0 = (long)0x00080000,
|
|||
|
m68KRegisterP3D1 = (long)0x000C0000,
|
|||
|
m68KRegisterP4A0 = (long)0x00000000,
|
|||
|
m68KRegisterP4A1 = (long)0x01000000,
|
|||
|
m68KRegisterP4D0 = (long)0x02000000,
|
|||
|
m68KRegisterP4D1 = (long)0x03000000
|
|||
|
};
|
|||
|
|
|||
|
enum {
|
|||
|
|
|||
|
/* Dispatched constants for kStackDispRegisterBased type (selector on stack) */
|
|||
|
m68KStackSelectorByte = (long)0x00000020,
|
|||
|
m68KStackSelectorWord = (long)0x00000010,
|
|||
|
m68KStackSelectorLong = (long)0x00000030,
|
|||
|
|
|||
|
/* Dispatched constants for all dispatched stack-based types */
|
|||
|
m68KRegSelectorByte = (long)0x00000080,
|
|||
|
m68KRegSelectorWord = (long)0x00000040,
|
|||
|
m68KRegSelectorLong = (long)0x000000C0,
|
|||
|
|
|||
|
/* Selectors for the ProcInfo result size fields */
|
|||
|
kNoReturnValue = (long)0x00000000,
|
|||
|
k68KByteReturned = (long)0x00000020,
|
|||
|
k68KWordReturned = (long)0x00000010, /* 68K word - two bytes */
|
|||
|
k68KLongReturned = (long)0x00000030 /* 68K long - four bytes */
|
|||
|
};
|
|||
|
|
|||
|
/* all of the special cases enumerated */
|
|||
|
enum {
|
|||
|
kSpecialCaseHighHook = 0x0100,
|
|||
|
kSpecialCaseCaretHook = 0x0100,
|
|||
|
kSpecialCaseEOLHook = 0x0200,
|
|||
|
kSpecialCaseWidthHook = 0x0300,
|
|||
|
kSpecialCaseNWidthHook = 0x0400,
|
|||
|
kSpecialCaseTextWidthHook = 0x0500,
|
|||
|
kSpecialCaseDrawHook = 0x0600,
|
|||
|
kSpecialCaseHitTestHook = 0x0700,
|
|||
|
kSpecialCaseTEFindWord = 0x0800,
|
|||
|
kSpecialCaseADBRoutines = 0x0900,
|
|||
|
kSpecialCaseProtocolHandler = 0x0A00,
|
|||
|
kSpecialCaseSocketListener = 0x0B00
|
|||
|
};
|
|||
|
/*
|
|||
|
Explanation of special cases:
|
|||
|
*****************************
|
|||
|
1 = C calling conventions, Rect on stack, pointer in A3, no return value
|
|||
|
2 = Register-based; inputs in D0, A3, A4; output is Z flag of
|
|||
|
status register (see VI-15-26)
|
|||
|
3 = Register-based; inputs in D0, D1, A0, A3, A4; output in D1 (see VI-15-27)
|
|||
|
4 = Register-based; inputs in D0, D1, D2, A0, A2, A3, A4; output in D1
|
|||
|
(see VI-15-27)
|
|||
|
5 = Register-based; inputs in D0, D1, A0, A3, A4; output in D1 (see VI-15-28)
|
|||
|
6 = Register-based; inputs in D0, D1, A0, A3, A4; no output (see VI-15-28)
|
|||
|
7 = Register-based; inputs in D0, D1, D21, A0, A3, A4; outputs in
|
|||
|
D0, D1, D2 (See VI-15-29)
|
|||
|
8 = Register-based; inputs in D0, D2, A3, A4; outputs in D0, D1 (see VI-15-30)
|
|||
|
9 = Register-based; inputs in A0, A1, A2, D0; no outputs (see V-371)
|
|||
|
A = Register-based; inputs in A0, A1, A2, A3, A4, D1.w; output in Z (see II-326)
|
|||
|
B = Register-based; inputs in A0, A1, A2, A3, A4, D0.b, D1.w; output in Z
|
|||
|
(see II-329)
|
|||
|
|
|||
|
*/
|
|||
|
|
|||
|
RoutineDescriptor
|
|||
|
NewRoutineDescriptor(ProcPtr theProc,
|
|||
|
ProcInfoType procInfo,
|
|||
|
CodeType typeOfCode)
|
|||
|
= {0x303C,0x0000,0xAA59}; /* <13> */
|
|||
|
|
|||
|
void
|
|||
|
DisposeRoutineDescriptor (RoutineDescriptor theDescriptor)
|
|||
|
= {0x303C,0x0001,0xAA59}; /* <13> */
|
|||
|
|
|||
|
long
|
|||
|
CallRoutineDescriptor (RoutineDescriptor theRoutine,
|
|||
|
ProcInfoType procInfo,
|
|||
|
...);
|
|||
|
CodeType
|
|||
|
GetCodeType (RoutineDescriptor theDescriptor);
|
|||
|
|
|||
|
OSErr
|
|||
|
SetCodeType (RoutineDescriptor theDescriptor,
|
|||
|
CodeType newCodeType);
|
|||
|
|
|||
|
ProcInfoType
|
|||
|
BuildProcInfo(CallingConventionType callingConvention,
|
|||
|
short resultSize,
|
|||
|
...);
|
|||
|
|
|||
|
ProcInfoType
|
|||
|
GetProcInfo (RoutineDescriptor theDescriptor);
|
|||
|
|
|||
|
OSErr
|
|||
|
SetProcInfo (RoutineDescriptor theDescriptor,
|
|||
|
ProcInfoType newProcInfo);
|
|||
|
|
|||
|
ProcPtr
|
|||
|
GetTheProc (RoutineDescriptor theDescriptor);
|
|||
|
|
|||
|
OSErr
|
|||
|
SetTheProc (RoutineDescriptor theDescriptor,
|
|||
|
ProcPtr newProc);
|
|||
|
|
|||
|
long
|
|||
|
GetEmulatorRegister (RegisterSelectorType registerSelector);
|
|||
|
|
|||
|
long
|
|||
|
SetEmulatorRegister (RegisterSelectorType registerSelector,
|
|||
|
long newValue);
|
|||
|
|
|||
|
|
|||
|
enum {kRoutineDescriptorVersion = 1};
|
|||
|
|
|||
|
struct private_RoutineDescriptor {
|
|||
|
long goMixedMode; // unused 68K instruction 0
|
|||
|
long magicCookie; // unique identifier 4
|
|||
|
SelectorType selector; // mixed mode selector 8
|
|||
|
short version; // 0 for now, increment as needed 10
|
|||
|
ProcInfoType procInfo; // calling conventions 12
|
|||
|
ProcPtr customParamProc; // Procedure to convert params 16
|
|||
|
CodeType executionMode; // to different types of code 20
|
|||
|
ProcPtr procDescriptor; // Descriptor of routine we are going to call 24
|
|||
|
long unused; // must be 0 28
|
|||
|
};
|
|||
|
|
|||
|
typedef struct private_RoutineDescriptor private_RoutineDescriptor;
|
|||
|
typedef private_RoutineDescriptor *private_RoutineDescriptorPtr, **private_RoutineDescriptorHandle;
|
|||
|
|
|||
|
/* a macro which creates a static instance of a routine descriptor */
|
|||
|
#define BuildRoutineDescriptor(procInfo, procedure) \
|
|||
|
{ \
|
|||
|
kGoMixedMode, /* GoMixedMode instruction */ \
|
|||
|
kMixedModeMagicCookie, /* Mixed Mode magic cookie */ \
|
|||
|
kExecute, /* selector <18> */ \
|
|||
|
kRoutineDescriptorVersion, /* version */ \
|
|||
|
(procInfo), /* ProcInfo */ \
|
|||
|
0, /* custom param proc */ \
|
|||
|
kCodeTypePower, /* execution mode */ \
|
|||
|
(void *) (procedure), /* theProc */ \
|
|||
|
0, /* list terminator */ \
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
#endif
|