MagiC PC knows sveral interfaces with which one can call up functions of the Windows system.
mec0 (MPS) interface:
This serves for executing any kind of (self-written) Windows code.
It is stored in a DLL and called via illegal opcodes from within
MagiC PC.
mec1 interface:
With this a predefined set of special functions can be called.
mec2 Schnittstelle:
Is provided by XFS_PC.LDR.
mec3 Schnittstelle:
Used by MPC_ACC for communication with MagiCPC.
mecnvdi Schnittstelle:
Is provided by NVDI_PC.DLL.
0. General remarks
MPS = Magic_Programmier_Schnittstelle = MagiC programmer's interface
Files of the demo example:
mps_base.def | The export list of the DLL, DO NOT ALTER! |
mps_base.h | Definition of the MPS interface, DO NOT ALTER! |
mps_base.cpp | Basic functions of the DLL, DO NOT ALTER! |
mps_demo.h | Definitions for the demo-DLL |
mps_demo.cpp | The MPS_functions of the demo-DLL |
testmps.s | Motorola - Example for calling the MPS functions of the demo |
To develop your own MPS_DLLs, please use mps_base.def, mps_base.h and mps_base.cpp unaltered. You can alter/supplement mps_demo.h and mps_demo.cpp. In particular, please choose your own DLL_ID in mps_demo.h for differentiation from other MPS_DLLs.
I. Concept
Windows-side one can use dynamic link libraries (DLLs) to establish any number of functions (called 'MPS_functions' in the following) which can be called within MagiC PC (Motorola-side).
In the start-up phase MagiC PC attempts to load and start all DLLs in the MPS subdirectory. For this MagiC PC calls three functions to be exported from the DLL (in this order):
mps_get_type(): Must return 0x4701!
mps_get_functionlist(...): Obtains DLL_ID and MPS_functions
list of the DLL.
mps_magicinfo: Provides information about MagiC PC's own data
and functions which the DLL may use on demand.
All functions declared in 2) can be called via special opcodes on the Motorola side. See part IV for more about the call.
II. Functions of the DLL to be exported ('Basic functions')
An MPS_DLL must export exactly 3 C functions under fixed ordinal numbers (these are also called basic functions): (see mfp_base.def, mfp_base.cpp, mfp_base.h)
@101: int mps_get_type()
Purpose: Serves for reassurance that it was really MPS_DLL that
was caught. !! Return value: 0x4701 !!
@102: int mps_get_functionlist(DWORD *mps_dll_id,MPS_fuptr
**p_funktionsliste);
Purpose: MagiC PC wants to know DLL_ID and MPS_functionlist.
Return values:
*mps_ddl_id: DLL_ID (4 bytes, to be selected DLL-specifically!)
*p_functionslist: Pointer to list of the MPS_functions.
Return: 1: All OK
@103: void mps_magicinfo(MPS_magicinfo *is);
Purpose: Provides information about MagiC PC's own info /
function pointers which the DLL may use:
typedef struct { DWORD sizeof_str; // Size of MPS_magicinfo DWORD magic_version; // e.g. 0x010001 DWORD magic_date; // e.g. 19960815 (ascending) BYTE is_demo; // Is it a demo version? BYTE uu1, uu2, uu3; // Still unused, 0 // Convert address Motorola -> Intel BYTE *(*intel_adr)(DWORD motadr); // Convert pointer Motorola -> Intel BYTE *(*intel_ptr)(DWORD motptr); WORD (*swap_word)(WORD w); // Swap one WORD DWORD (*swap_long)(DWORD dw); // Swap one LONGword } MPS_magicinfo;
III. The freely definable MPS_functions of a DLL:
MPS_functions basically have the form:
void function_blabla( MPS_motregs *motregs )
motregs here points to a list of the Motorola registers d0-a7. The contents of the registers is already in the correct Intel byte order. The Motorola registers may also have new values written to them.
With mps_get_functionlist the DLL passes the list of addresses of all such MPS_functions. The function numbers correspond to the position of the function within the list. If a number is to remain free, then its address is passed as 0xffffffff (= -1). See also mps_demo.cpp.
IV. Motorola-side call
MPS_functions are called by a Motorola-side 8-byte opcode:
dc.w $4fbf * 2 bytes: Do not alter! dc.l DLL_ID * 4 bytes: DLL-specific DLL_ID dc.w Fkt_no. * 2 bytes: Function number
DLL_ID is the DLL_ID (4 bytes!) passed via mps_get_functionlist. Function number is the position of the function in the function list passed by mps_get_functionlist (count starts at 0).
V. Miscellaneous
Each DLL should use an individual DLL_ID to prevent conflicts
between multiple DLLs (see mps_demo.h). DLL_IDs with bit 31 set are
reserved for us (Application Systems) or for allocated IDs. Therefore
please do not choose a DLL_ID with set bit 31! If we are to allocate a
reserved DLL_ID to you, please get in touch with Herr Hoffmann of
Application Systems Heidelberg.
The following DLL_IDs have been allocated:
DLL_ID | Program name | Author |
0x003f5c66 | MPCTime | Robert Weiß |
0x2053434B | MPCSTiK | Dan Ackerman |
0x21342812 | Draconis Windows Sockets | |
0x44594a01 | In2Cat | Dimitri Junker |
0x44594a02 | Win_Lnk | Dimitri Junker |
0x50475752 | MPC_POWR | Emanuel Welter |
Pay attention to the displacement of the address space!! If you
want to use a Motorola address on the DLL side, you should call
intel_adr(..) or intel_ptr(..) respectively for conversion (see
MPS_magicinfo in mps_base.h). Addresses from the DLL address space can
not be used Motorola-side!
Also pay attention to the different byte order between Motorola
and Intel processors. WORDs and LONGwords from the Motorola address
space have to be swapped so that they lie correctly in the DLL. If
anything is written back then it has to be swapped once more. For this
you can call the functions swap_word(..) or swap_long(..) (see
MPS_magicinfo in mps_base.h). BUT: Elements of MPS_motregs (d0-a7) are
already in the Intel order and do not have to be swapped.
; ========================================================== ; Export definitions for MPS MagiC PC programmer's interface FS 15.08.96 ; ========================================================== ; ; !! DO NOT ALTER !! ; ================== EXPORTS mps_get_type @101 mps_get_functionlist @102 mps_magicinfo @103
// Tab size: 3 // Last change: 15.08.96 // Author: FS // ------------------------------------------------------------------------ // // The MagiC PC programmer's interface // // mps_base.h: Basic include !! ADOPT UNALTERED !! // ===================== #ifdef __cplusplus extern "C" { #endif /* ======================================================================== The DLL functions freely definable by the user have the form: void mps_function(MPS_motregs *r), where r represents a pointer to the 16 Motorola registers, so: */ typedef struct { // MPS_motregs = The Motorola registers long d0,d1,d2,d3,d4,d5,d6,d7; long a0,a1,a2,a3,a4,a5,a6,a7; } MPS_motregs; // MPS_fuptr = Pointer to a MPS_function: typedef void (*MPS_fuptr)(MPS_motregs *); /* ====================================================================== The DLL basic function mps_info is passed the following info block MPS_infostr: */ typedef struct { DWORD sizeof_str; // Size of MPS_infostr DWORD magic_version; // e.g. 0x010001 DWORD magic_date; // e.g. 19960815 (ascending) BYTE is_demo; // Is it a demo-version? BYTE uu1, uu2, uu3; // Still unused, 0 BYTE *(*intel_adr)(DWORD motadr); // Convert address Motorola -> Intel BYTE *(*intel_ptr)(DWORD motptr); // Convert pointer Motorola -> Intel WORD (*swap_word)(WORD w); // Swap one WORD DWORD (*swap_long)(DWORD dw); // Swap one LONGword } MPS_magicinfo; // =============== 3 basic functions to be exported: ================== // int mps_get_type(); // @101 int mps_get_functionlist(DWORD *mps_dll_id, MPS_fuptr **p_functionslist); // @102 void mps_magicinfo(MPS_magicinfo *is); // @103 // // See also mps_base.cpp, mps_base.def #ifdef __cplusplus } #endif
See also: MagiC PC interface
// Tab size: 3 // Last change: 15.08.96 // Author: FS // ------------------------------------------------------------------------ // Demo example for MagiC PC programmer's interface (MPS) // // Part 1: Basic functions, adopt UNCHANGED! // ======= // // ------------------------------------------------------------------------ #include "windows.h" #include "mps_base.h" #include "mps_demo.h" // // The following 3 basic functions must be exported by the DLL: // // 1) Basic function @101: Type query // --------------------- int mps_get_type() // ---------------- { return(0x4701); // Must return this value } // 2) Basic function @102: MagiC PC requests ID and function list // ----------------------- int mps_get_functionlist(DWORD *mps_dll_id,MPS_fuptr **p_functionslist) // ------------------------ { *mps_dll_id = DLL_ID; // User-defined ID, see mps_demo.h *p_functionslist = my_funclist; // Enter pointer to function list return(1); } // 3) Basic function @103: MagiC PC passes MPS_magicinfo to the DLL // ----------------------- void mps_magicinfo(MPS_magicinfo *is) // ------------- { m_info = *is; // Remember } // // END basic functions ---------------------------------------------------- //
See also: MagiC PC interface
// Tab size: 3 // Last change: 15.08.96 // Author: FS // ------------------------------------------------------------------------ // Demo example for MagiC PC programmer's interface (MPS) // // Part 2: User-defined functions, change DLL_ID to your own value !!! // ======= // // ------------------------------------------------------------------------ #define DLL_ID 0x01020304 // Change to your own value // !! Values with bit 31 set are // reserved for Appl.Systems. // ID reservation: Apply to // Appl. Systems (Herr Hoffmann)! extern MPS_fuptr my_funclist[]; // Function list in the demo-DLL extern MPS_magicinfo m_info; // Is adopted by MagiC PC
See also: MagiC PC interface
// Tab size: 3 // Last change: 15.08.96 // Author: FS // ------------------------------------------------------------------------ // Demo example for MagiC PC programmer's interface (MPS) // // Parl 2: User-defined functions, freely alterable // ======= // // ------------------------------------------------------------------------ #include "windows.h" #include "mps_base.h" #include "mps_demo.h" MPS_magicinfo m_info; // Global for the DLL // // List of the user-defined functions (alter/extend as required): // ------------------------------------------------------------------ static void demo_0(MPS_motregs *r); static void demo_1(MPS_motregs *r); static void demo_3(MPS_motregs *r); static void copy_string(MPS_motregs *r); MPS_fuptr my_funclist[] = { demo_0, // Demo function 0 demo_1, // Demo function 1 (MPS_fuptr) -1, // -1 (i.e function No.2 not defined) demo_3, // Demo function 3 copy_string, // Demo function 4 NULL // !! A NULL-entry at list end !! } ; // ****************************************************************** // // Here the user-defined functions: // ================================ // // Demo_0 only returns the value 1 in d0: // static void demo_0(MPS_motregs *r) // ---------------------- { r->d0 = 1; // Demo-0 sets d0 to 1 return; } // Demo_1 adds the registers d1 and d2; result to d0: // static void demo_1(MPS_motregs *r) // ---------------------- { r->d0 = r->d1 + r->d2; return; } // Demo_3 does nothing at all! // static void demo_3(MPS_motregs *r) // ---------------------- { return; } // Demo routine_4 copy_string copies a string to Motorola address space: // ----------- // a0: Destination address, // d0: Maximum number of characters (incl. 0) // static void copy_string(MPS_motregs *r) // ----------------------- { static char string[] = "This is a demo-text of copy_string(..)"; int i, nchmax; char *dest; nchmax = (int) r->d0; dest = (char *) (*m_info.intel_ptr)(r->a0); if (nchmax<=0 || dest==NULL) return; // Invalid? for (i=0; i<nchmax; i++) { if ((dest[i] = string[i])==0) return; } dest[nchmax-1] = 0; // Too long->truncate return; }
See also: MagiC PC interface
* FS 15.08.96 * * =========================================================== * Sample for the call of the MPS functions from Motorola side * =========================================================== * * Source Windows-side: * -------------------- * mps_base.cpp, mps_demo.cpp * mps_code .equ $4fbf * !! DO NOT ALTER !! DLL_ID .equ $01020304 * Enter own DLL_ID here * -------------------------------------- 60 bytes buffer bufsize .equ 60 .bss .even buffer: ds.w bufsize * -------------------------------------- * * ------------------- Here we go: ----------------------------------- * .text .globl _main _main: moveq #-1,d0 * d0 to -1 (for testing) * =========================== * Call function 0 (Demo_0): dc.w mps_code * = $4fbf dc.l DLL_ID * = Own DLL_ID dc.w 0 * Function number (here 0) * =========================== cmpi.l #1,d0 * Should return 1 bne finish * Example for call with parameters (copy_string) * ---------------------------------- movea.l #buffer,a0 * Pointer to buffer for string move.l #bufsize,d0 * Max. string length (incl.0-byte) * =========================== * Call function 4 (copy_string): dc.w mps_code * = $4fbf dc.l DLL_ID * = Own DLL_ID dc.w 4 * Function number (here 4) * =========================== bsr put_line * Output line (a0) finish: bsr wait * Wait for keypress rts * * --------------------- END main routine _main ----------------------- * * ------------------------ Output line (a0) -------------------------- put_line: moveq #13,d0 bsr put_char moveq #10,d0 put_lnext: bsr put_char move.b (a0)+,d0 bne put_lnext rts * ------------------------ Output chatacter d0 ----------------------- put_char: movem.l d0-d2/a0-a2,-(sp) move.w d0,-(sp) move.w #2,-(sp) move.w #3,-(sp) trap #13 addq.l #6,sp movem.l (sp)+,d0-d2/a0-a2 rts * -------------------------- Wait for keypress ----------------------- wait: move.w #2,-(sp) move.w #2,-(sp) trap #13 addq.l #4,sp rts
See also: MagiC PC interface
Concept
The mec1 interface makes it possible to call functions
predefined by the emulator in Motorola code. In principle it is
similar to the mec0 (MPS) interface, though the functions are not
freely definable in a DLL but already predefined by the emulator.
Call: The functions are called uniformly by the opcode $43bf,
followed by a function number, thus with 4 bytes total length.
Example:
dc.w $43bf,$0031
calls the mec1 function with the number 0x31. ($43bf is the
opcode for chk <ea>,d1, with <ea> = 111111 binary, so
invalid). Parameter passing is, as with mec0, via the Motorola
registers.
The functions
$0001 | long emu_version:
| ||||||||||||||||||
$0002 | long emu_enquire: Obtains diverse information
bisher definiert:
| ||||||||||||||||||
$0003 | void emu_getexepath: Obtains the full path (including drive,
without MAGIC_PC.EXE)
| ||||||||||||||||||
$0004 | int emu_install_newvdi:
| ||||||||||||||||||
$0008 |
| ||||||||||||||||||
$0009 |
| ||||||||||||||||||
$0010 | void dw_addline: ! As of 03.97
Output text in new line in the debug window
| ||||||||||||||||||
$0011 | void dw_addtext: ! As of 03.97
Output text in debug window
| ||||||||||||||||||
$0012 | void dw_formtxt: ! As of 03.97
Output text sprintf-like in debug window
| ||||||||||||||||||
$0020 | enq_bigscreen
| ||||||||||||||||||
$0021 | new_bigscreen
| ||||||||||||||||||
$0022 |
| ||||||||||||||||||
$0028 |
| ||||||||||||||||||
$0031 | int printer_open ! As of 03.97
printer_open Opens the standard printer and starts a new document
| ||||||||||||||||||
$0032 | int printer_close ! As of 03.97
printer_close Terminates the previously opened document and closes the printer
| ||||||||||||||||||
$0033 | int printer_write ! As of 03.97
| ||||||||||||||||||
$0040 | DWORD getTickCount ! As of 03.97
| ||||||||||||||||||
$0041 | DWORD getDrivePath ! ab 02.99
The function obtains the Windows path for a MagiC drive
| ||||||||||||||||||
$0042 | DWORD setClipboardDir ! ab 02.99
Beispiel: movea.l stringadr,a0 * dc.w $43bf,$0042 * mec1, call function $42 tst.l d0 * -1: Function not implemented jl nichtimplementiert | ||||||||||||||||||
$0043 | long getMouseWheel
Beispiel: moveq #1,d0 * Reset position after readout dc.w $43bf,$0043 * mec1, call function $43 tst.l d0 * Position altered since last reset je no_action <d0.l verarbeiten> | ||||||||||||||||||
$0045 | long setCompiler ! As of 17.06.99
|
Concept
The mec2 interface is provided by XFS_PC.LDR.
Call: The functions are called uniformly by the opcode $45bf,
followed by a function number, thus with 4 bytes total length.
Example:
dc.w $45bf,$0001
The functions
Details about the various functions or not known yet.
Concept
The mec3 is used by MPC_ACC for communication with MagiCPC.
Call: The functions are called uniformly by the opcode $47bf,
followed by a function number, thus with 4 bytes total length.
Example:
dc.w $47bf,$0001
The functions
$0001 | long mpc_shutdown:
Terminate MagiCPC.
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0002 | long mpc_restart:
Restart MagiCPC.
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0010 | : long start_winfile
Execute windows program.
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0020 | : long mpc_control
This function has several subfunctions, whose number is passed in d0.l
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
others | For unknown/illegal function codes, -1 is returned in d0.l
|
Concept
The mec2 interface is provided by NVDI_PC.DLL.
Call: The functions are called uniformly by the opcode $41bf,
followed by a function number, thus with 4 bytes total length.
Example:
dc.w $41bf,$0001
The functions
Details about the various functions or not known yet.