MagiC PC kennt zwei 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.
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 BYTE *(*intel_adr)(DWORD motadr); // Adressumrechnung Motorola -> Intel BYTE *(*intel_ptr)(DWORD motptr); // Pointer-Umrechnung Motorola -> Intel (NULL bleibt NULL!) 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 |
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 BYTE *(*intel_adr)(DWORD motadr); // Adressumrechnung Motorola -> Intel BYTE *(*intel_ptr)(DWORD motptr); // Pointer-Umrechnung Motorola -> Intel (NULL bleibt NULL!) 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,MPS_fuptr **p_funktionsliste); // @102 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) Basisfuktion @101: Typabfrage // --------------------- int mps_get_type() // ---------------- { return(0x4701); // muß diesen Wert zurückgeben } // 2) Basisfuktion @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) Basisfuktion @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; iabschneiden 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 von
Emulator vorgebenene 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
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: | ||||||||||||||||||
$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
| ||||||||||||||||||
$0011 | void dw_formtxt: ! ab 03.97 Text sprintf-like im Debug-Fenster ausgeben
| ||||||||||||||||||
$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 | ||||||||||||||||||
$0045 | long setCompiler ! ab 17.06.99
|