MagiC PC kennt mehrere Schnittelstellen mit denen man Funktionen des Windowssystem aufrufen kann.
mec0 (MPS) Schnittstelle:
Diese dient dazu beliebigen (selbstgeschriebenen) Windowscode
auszuführen. Dieser wird in einer DLL abgelegt, und über illegale
Opcodes aus MagiC PC heraus aufgerufen.
mec1 Schnittstelle:
Hiermit kann ein vorgegebenes Set an Spezialfunktionen aufgerufen werden.
mec2 Schnittstelle:
Wird von XFS_PC.LDR zur Verfügung gestellt.
mec3 Schnittstelle:
Wird von MPC_ACC zur Kommunikation mit MagiCPC genutzt.
mecnvdi Schnittstelle:
Wird von NVDI_PC.DLL zur Verfügung gestellt.
0. Allgemeines
MPS = Magic_Programmier_Schnittstelle
Dateien des Demobeispieles:
mps_base.def | Die Exportliste der DLL, NICHT ÄNDERN |
mps_base.h | Definition der MPS_Schnittstelle, NICHT ÄNDERN |
mps_base.cpp | Basis-Funktionen der DLL, NICHT ÄNDERN |
mps_demo.h | Definitionen für die Demo-DLL |
mps_demo.cpp | Die MPS_Funktionen der Demo-DLL |
testmps.s | Motorola - Beispiel zum Aufruf der MPS-Funktionen des Demo-Beispieles |
Um eigene MPS_DLLs zu entwickeln, verwenden Sie bitte mps_base.def, mps_base.h und mps_base.cpp unverändert. Zu ändern/ergänzen sind mps_demo.h und mps_demo.cpp. Insbesondere wählen Sie bitte eine eigene DLL_ID in mps_demo.h zur Unterscheidung von anderen MPS_DLLs.
I. Konzept
Windowsseitig können über dynamische Bibliotheken (DLLs) beliebig viele Funktionen (im folgenden MPS_Funktionen genannt) eingerichtet werden, die innerhalb von MagiC_PC (motorolaseitig) aufgerufen werden können.
In der Startphase versucht MagiC_PC, alle DLLs im Unterverzeichnis MPS zu laden und zu starten. Dazu ruft MagiC PC drei von der DLL zu exportierende Funktionen auf (in dieser Reihenfolge):
mps_get_type(): muß 0x4701 liefern!
mps_get_functionlist(...): ermittelt DLL_ID und
MPS_Funktionsliste der DLL.
mps_magicinfo: teilt MagiC PC-eigene Daten/Funktionen mit, die
die DLL bei Bedarf verwenden kann.
Alle in 2) angemeldeten Funktionen können über spezielle Opcodes motorola-seitig aufgerufen werden. Näheres zum Aufruf siehe IV.
II. Zu exportierende Funktionen der DLL ("Basisfunktionen")
Eine MPS-DLL muß genau 3 C-Funktionen unter fester Ordinalzahl exportieren: (auch Basisfunktionen genannt) (siehe mfp_base.def, mfp_base.cpp, mfp_base.h)
@101: int mps_get_type()
Zweck: Dient der Rückversicherung, ob tatsächlich MPS_DLL
erwischt. !! Rückgabewert: 0x4701 !!
@102: int mps_get_functionlist(DWORD *mps_dll_id,MPS_fuptr
**p_funktionsliste);
Zweck: MagiC PC möchte DLL_ID und MPS_Funktionsliste wissen.
Rückgabewerte:
*mps_ddl_id: DLL_ID (4 Bytes, DLL_spezifisch zu wählen!)
*p_funktionsliste: Zeiger auf Liste der MPS_Funktionen.
return: 1: alles klar
@103: void mps_magicinfo(MPS_magicinfo *is);
Zweck: MagiC PC teilt eigene Infos / Funktionspointer mit, die
die DLL verwenden darf:
typedef struct { DWORD sizeof_str; // Größe von MPS_magicinfo DWORD magic_version; // z.B. 0x010001 DWORD magic_date; // z.B. 19960815 (aufsteigend) BYTE is_demo; // Ist demoversion? BYTE uu1, uu2, uu3; // noch unbenutzt, 0 // Adressumrechnung Motorola -> Intel BYTE *(*intel_adr)(DWORD motadr); // Pointer-Umrechnung Motorola -> Intel (NULL bleibt NULL!) BYTE *(*intel_ptr)(DWORD motptr); WORD (*swap_word)(WORD w); // Ein Word swappen DWORD (*swap_long)(DWORD dw); // Ein Langwort swappen } MPS_magicinfo;
III. Die frei definierbaren MPS_Funktionen einer DLL:
MPS_Funktionen haben grundsätzlich die Form
void funktion_blabla( MPS_motregs *motregs )
motregs zeigt dabei auf die Liste der Motorola-Register d0-a7. Der Inhalt der Register ist schon im richtigen Intel-ByteSex. Die Motorola-Register dürfen auch mit neuen Werten beschrieben werden.
Die DLL übergibt mit mps_get_functionlist die Liste der Adressen aller solcher MPS_Funktionen. Die Funktionsnummern entsprechen der Position der Funktion innerhalb der Liste. Soll eine Nummer freibleiben, ist als Adresse 0xffffffff (= -1) zu übergeben. Siehe auch mps_demo.cpp.
IV. Motorola-seitiger Aufruf
MPS_Funktionen werden durch einen 8-Byte-Opcode motorola-seitig aufgerufen:
dc.w $4fbf * 2 Bytes: nicht ändern dc.l DLL_ID * 4 Bytes: DLL-spezifische DLL_ID dc.w Fkt_Nr. * 2 Bytes: Funktionsnummer.
Die DLL_ID ist die über mps_get_functionlist mitgeteilte DLL_ID (4 Bytes!). Funktionsnummer ist die Position der Funktion in der über mps_get_functionlist mitgeteilten Funktionsliste (Zählung beginnt bei 0).
V. Sonstiges
Jede DLL sollte eine individuelle DLL_ID verwenden, um
Konflikte zwischen mehreren DLLs zu vermeiden (siehe mps_demo.h).
DLL_IDs mit gesetztem Bit 31 sind für uns (Application Systems) bzw.
für zugeteilte IDs reserviert. Bitte wählen Sie deshalb keine DLL_ID
mit gesetztem Bit 31! Falls wir Ihnen eine reservierte DLL_ID zuteilen
sollen, setzen Sie sich bitte mit Herrn Hoffmann von Application
Systems in Verbindung.
Folgende DLL IDs sind vergeben:
DLL ID | Programmname | Author |
0x003f5c66 | MPCTime | Robert Weiß |
0x2053434B | MPCSTiK | Dan Ackerman |
0x21342812 | Draconis Windows Sockets | |
0x44594a01 | In2Cat | Dimitri Junker |
0x44594a02 | Win_Lnk | Dimitri Junker |
0x4e415446 | mpsyield | |
0x50475752 | MPC_POWR | Emanuel Welter |
Achten Sie auf die Verschiebung des Adressraumes!!
Wollen Sie eine Motorola-Adresse DLL-seitig verwenden, ist zur
Konvertierung intel_adr(..) bzw. intel_ptr(..) aufzurufen (siehe
MPS_magicinfo in mps_base.h). Adressen aus dem DLL-Adressraum können
motorola-seitig NICHT verwendet werden!
Achten Sie auf den unterschiedlichen Byte-Sex zwischen
Motorola- und Intel-Prozessor. Worte und Langworte aus dem
Motorola-Adressraum müssen geswappt werden, damit sie in der DLL
richtig vorliegen. Beim eventuellen zurückschreiben ist wieder zu
swappen. Sie können dazu die Funktionen swap_word(..) bzw.
swap_long(..) aufrufen (siehe MPS_magicinfo in mps_base.h). Aber: Die
Elemente von MPS_motregs (d0-a7) liegen schon intelmäßig vor und
müssen nicht mehr geswappt werden.
; ======================================================== ; Export-Definitionen für MPS MagiC_PC Progr.Schnittstelle FS 15.08.96 ; ======================================================== ; ; !! NICHT ÄNDERN !! ; ================== EXPORTS mps_get_type @101 mps_get_functionlist @102 mps_magicinfo @103
// Tabsize: 3 // Letzte Änderung: 15.08.96 // Autor: FS // ------------------------------------------------------------------------ // // Die MagiC PC - Programmier-Schnittstelle // // mps_base.h: Basis-Include !! UNVERÄNDERT ÜBERNEHMEN !! // ====================== #ifdef __cplusplus extern "C" { #endif /* ======================================================================== Die vom Anwender frei definierbaren DLL-Funktionen haben die Form void mps_funktion(MPS_motregs *r), wobei r ein Pointer auf die 16 Motorola-Register darstellt, also: */ typedef struct { // MPS_motregs = Die Motorola-Register long d0,d1,d2,d3,d4,d5,d6,d7; long a0,a1,a2,a3,a4,a5,a6,a7; } MPS_motregs; // MPS_fuptr = Pointer auf eine MPS_Funktion: typedef void (*MPS_fuptr)(MPS_motregs *); /* ============================================================ Der DLL-Basisfunktion mps_info wird der folgende Infoblock MPS_infostr mitgegeben: */ typedef struct { DWORD sizeof_str; // Größe von MPS_infostr DWORD magic_version; // z.B. 0x010001 DWORD magic_date; // z.B. 19960815 (aufsteigend) BYTE is_demo; // Ist demoversion? BYTE uu1, uu2, uu3; // noch unbenutzt, 0 // Adressumrechnung Motorola -> Intel BYTE *(*intel_adr)(DWORD motadr); // Pointer-Umrechnung Motorola -> Intel (NULL bleibt NULL!) BYTE *(*intel_ptr)(DWORD motptr); WORD (*swap_word)(WORD w); // Ein Word swappen DWORD (*swap_long)(DWORD dw); // Ein Langwort swappen } MPS_magicinfo; // =============== zu exportieren sind 3 Basisfunktionen: ================= // int mps_get_type(); // @101 int mps_get_functionlist(DWORD *mps_dll_id, // @102 MPS_fuptr **p_funktionsliste); void mps_magicinfo(MPS_magicinfo *is); // @103 // // siehe auch mps_base.cpp, mps_base.def #ifdef __cplusplus } #endif
Querverweise: MagiC PC-Schnittstelle
// Tabsize: 3 // Letzte Änderung: 15.08.96 // Autor: FS // ------------------------------------------------------------------------ // Demobeispiel zu MagiC PC - Programmier-Schnittstelle (MPS) // // Teil 1: Basisfunktionen, UNVERÄNDERT übernehmen! // ======= // // ------------------------------------------------------------------------ #include "windows.h" #include "mps_base.h" #include "mps_demo.h" // // Die folgenden 3 Basisfunktionen müssen von der DLL exportiert werden: // // 1) Basisfunktion @101: Typabfrage // --------------------- int mps_get_type() // ---------------- { return(0x4701); // muß diesen Wert zurückgeben } // 2) Basisfunktion @102: MagiC PC fordert Id und Funktionsliste an. // --------------------- int mps_get_functionlist(DWORD *mps_dll_id,MPS_fuptr **p_funktionsliste) // ------------------------ { *mps_dll_id = DLL_ID; // benutzerdefinierte ID, siehe mps_demo.h *p_funktionsliste = my_funclist; // Zeiger auf Funktionsliste eintragen return(1); } // 3) Basisfunktion @103: MagiC PC übergibt MPS_magicinfo an die DLL // --------------------- void mps_magicinfo(MPS_magicinfo *is) // ------------- { m_info = *is; // Merken } // // ENDE Basisfunktionen --------------------------------------------------- //
Querverweise: MagiC PC-Schnittstelle
// Tabsize: 3 // Letzte Änderung: 15.08.96 // Autor: FS // ------------------------------------------------------------------------ // Demobeispiel zu MagiC PC - Programmier-Schnittstelle (MPS) // // Teil 2: Benutzer-definierte Funktionen, DLL_ID auf eigenen Wert ändern ! // ======= // // ------------------------------------------------------------------------ #define DLL_ID 0x01020304 // auf eigenen Wert ändern. // !! Werte mit gesetztem Bit 31 // reserviert für Appl.Systems. // ID-Reservierung: Bei Appl.Systems // (Herrn Hoffmann) anfragen! extern MPS_fuptr my_funclist[]; // Die Funktionsliste in der Demo-DLL extern MPS_magicinfo m_info; // wird von MagiC_PC übernommen
Querverweise: MagiC PC-Schnittstelle
// Tabsize: 3 // Letzte Änderung: 15.08.96 // Autor: FS // ------------------------------------------------------------------------ // Demobeispiel zu MagiC PC - Programmier-Schnittstelle (MPS) // // Teil 2: Benutzer-definierte Funktionen, frei änderbar. // ======= // // ------------------------------------------------------------------------ #include "windows.h" #include "mps_base.h" #include "mps_demo.h" MPS_magicinfo m_info; // global für die DLL // // Liste der benutzerdefinierten Funktionen (nach Bedarf ändern/erweitern): // ----------------------------------------------------------------------- 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-Funktion 0 demo_1, // Demo-Funktion 1 (MPS_fuptr) -1, // -1 (d.h Funktion Nummer 2 // nicht definiert) demo_3, // Demo-Funktion 3 copy_string, // Demo-Funktion 4 NULL // !! Am Listenende ein NULL-Eintrag !! } ; // ************************************************************************ // // Hier die benutzerdefinierten Funktionen: // ======================================== // // Demo_0 liefert nur in d0 den Wert 1 zurück: // static void demo_0(MPS_motregs *r) // ---------------------- { r->d0 = 1; // Demo-0 setzt d0 auf 1 return; } // Demo_1 addiert die Register d1 und d2; Ergebnis nach d0: // static void demo_1(MPS_motregs *r) // ---------------------- { r->d0 = r->d1 + r->d2; return; } // Demo_3 tut gar nichts: // static void demo_3(MPS_motregs *r) // ---------------------- { return; } // Demo-Routine4 copy_string kopiert einen String in den Motorola- // Adressraum: // ----------- // a0: Ziel-Adresse, // d0: Maximalzahl der Zeichen (incl. 0) // static void copy_string(MPS_motregs *r) // ----------------------- { static char string[] = "Dies ist ein Demo-Text von copy_string(..)"; int i, nchmax; char *ziel; nchmax = (int) r->d0; ziel = (char *) (*m_info.intel_ptr)(r->a0); if (nchmax<=0 || ziel==NULL) return; // ungültig? for (i=0; i<nchmax; i++) { if ((ziel[i] = string[i])==0) return; } ziel[nchmax-1] = 0; // zu lange->abschneiden return; }
Querverweise: MagiC PC-Schnittstelle
* FS 15.08.96 * * ============================================================= * Beispiel für den Aufruf der MPS-Funktionen von Motorola aus * ============================================================= * * Quelle Windows-seitig: * ---------------------- * mps_base.cpp, mps_demo.cpp * mps_code .equ $4fbf * !! NICHT ÄNDERN !! DLL_ID .equ $01020304 * hier eigene DLL_ID eintragen * -------------------------------------- 60 Bytes Puffer bufsize .equ 60 .bss .even buffer: ds.w bufsize * -------------------------------------- * * ------------------- Hier gehts los: --------------------------------- * .text .globl _main _main: moveq #-1,d0 * d0 auf -1 (zum Testen) * =========================== * Funktion 0 (Demo_0) aufrufen: dc.w mps_code * = $4fbf dc.l DLL_ID * = eigene DLL_ID dc.w 0 * Funktionsnummer (hier 0) * =========================== cmpi.l #1,d0 * müßte 1 zurückliefern bne fertig * Beispiel für Aufruf mit Parametern (copy_string) * ---------------------------------- movea.l #buffer,a0 * Zeiger auf Puffer für String move.l #bufsize,d0 * Max. Stringlänge (incl.0-Byte). * =========================== * Funktion 4 (copy_string) aufrufen: dc.w mps_code * = $4fbf dc.l DLL_ID * = eigene DLL_ID dc.w 4 * Funktionsnummer (hier 4) * =========================== bsr put_line * Zeile (a0) ausgeben fertig: bsr wait * Auf Tastendruck warten rts * * --------------------- ENDE Hauptroutine _main ------------------------ * * ------------------------ Zeile (a0) ausgeben ----------------------- put_line: moveq #13,d0 bsr put_char moveq #10,d0 put_lnext: bsr put_char move.b (a0)+,d0 bne put_lnext rts * ------------------------ Zeichen d0 ausgeben ----------------------- 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 * -------------------------- auf Tastendruck warten. -------------------- wait: move.w #2,-(sp) move.w #2,-(sp) trap #13 addq.l #4,sp rts
Querverweise: MagiC PC-Schnittstelle
Konzept
Die mec1-Schnittstelle ermöglicht es, im Motorola-Code vom
Emulator vorgegebene Funktionen aufrufen. Sie entspricht der
mec0-Schnittstelle; die Funktionen sind jedoch nicht in einer DLL frei
definierbar, sondern schon vom Emulator vorgegeben.
Aufruf: Die Funktionen werden einheitlich durch den Opcode
$43bf aufgerufen, mit nachfolgender Funktionsnummer, also 4 Bytes
Gesamtlänge. Beispiel:
dc.w $43bf,$0031
ruft die mec1-Funktion mit der Nummer 0x31 auf. ($43bf ist der
Opcode für chk <ea>,D1, mit <ea> = 111111 binär, also
ungültig). Die Parameter-Übergabe erfolgt wie bei mec0 über die
Motorola Register.
Die Funktionen
$0001 | long emu_version:
| ||||||||||||||||||
$0002 | long emu_enquire: Ermittelt Verschiedenes.
bisher definiert:
| ||||||||||||||||||
$0003 | void emu_getexepath: Ermittelt vollen Pfad (incl. Laufwerk,
ohne MAGIC_PC.EXE)
| ||||||||||||||||||
$0004 | int emu_install_newvdi:
| ||||||||||||||||||
$0008 |
| ||||||||||||||||||
$0009 |
| ||||||||||||||||||
$0010 | void dw_addline: ! ab 03.97
Text in neuer Zeile im Debug-Fenster ausgeben
| ||||||||||||||||||
$0011 | void dw_addtext: ! ab 03.97
Text im Debug-Fenster ausgeben
| ||||||||||||||||||
$0012 | void dw_formtxt: ! ab 03.97
Text sprintf-like im Debug-Fenster ausgeben
| ||||||||||||||||||
$0020 | enq_bigscreen
| ||||||||||||||||||
$0021 | new_bigscreen
| ||||||||||||||||||
$0022 |
| ||||||||||||||||||
$0028 |
| ||||||||||||||||||
$0031 | int printer_open ! ab 03.97
printer_open öffnet den Standarddrucker und beginnt ein neues Dokument
| ||||||||||||||||||
$0032 | int printer_close ! ab 03.97
printer_close beendet das zuvor geöffnete Dokument und schließt den Drucker
| ||||||||||||||||||
$0033 | int printer_write ! ab 03.97
| ||||||||||||||||||
$0040 | DWORD getTickCount ! ab 03.97
| ||||||||||||||||||
$0041 | DWORD getDrivePath ! ab 02.99
Die Funktion ermittelt den Windows-Pfad für ein Magic-Laufwerk.
| ||||||||||||||||||
$0042 | DWORD setClipboardDir ! ab 02.99
Beispiel: movea.l stringadr,a0 * dc.w $43bf,$0042 * mec1,Funktion $42 aufrufen tst.l d0 * -1: Fkt. nicht implementiert jl nichtimplementiert | ||||||||||||||||||
$0043 | long getMouseWheel
Beispiel: moveq #1,d0 * Position nach dem Auslesen * zurücksetzen dc.w $43bf,$0043 * mec1,Funktion $43 aufrufen tst.l d0 * Position seit letztem * zurücksetzen geändert je no_action <d0.l verarbeiten> | ||||||||||||||||||
$0045 | long setCompiler ! ab 17.06.99
|
Konzept
Die mec2-Schnittstelle wird von XFS_PC.LDR zur Verfügung
gestellt.
Aufruf: Die Funktionen werden einheitlich durch den Opcode
$45bf aufgerufen, mit nachfolgender Funktionsnummer, also 4 Bytes
Gesamtlänge. Beispiel:
dc.w $45bf,$0001
Die Funktionen
Details über die einzelnen Funktionen sind z.Z. noch nicht
bekannt.
Konzept
Die mec3-Schnittstelle wird von MPC_ACC zur Kommunikation mit
MagiCPC benutzt.
Aufruf: Die Funktionen werden einheitlich durch den Opcode
$47bf aufgerufen, mit nachfolgender Funktionsnummer, also 4 Bytes
Gesamtlänge. Beispiel:
dc.w $47bf,$0001
Die Funktionen
$0001 | long mpc_shutdown:
MagiCPC beenden.
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0002 | long mpc_restart:
MagiCPC neu starten.
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0010 | : long start_winfile
Windows-Programm ausführen.
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$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
|
Konzept
Die mecnvdi-Schnittstelle wird von NVDI_PC.DLL zur Verfügung
gestellt.
Aufruf: Die Funktionen werden einheitlich durch den Opcode
$41bf aufgerufen, mit nachfolgender Funktionsnummer, also 4 Bytes
Gesamtlänge. Beispiel:
dc.w $41bf,$0001
Die Funktionen
Details über die einzelnen Funktionen sind z.Z. noch nicht
bekannt.