This is an old version from the tos.hyp. The new is on GitHub!

HomeEmulatorenMagiC Mac-SpezifikaSTEmulator

14.2 MagiC PC-Schnittstelle

MagiC PC kennt zwei Schnittelstellen mit denen man Funktionen des Windowssystem aufrufen kann.

14.2.1 mec0 (MPS) Schnittstelle

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):

  1. mps_get_type(): muß 0x4701 liefern!

  2. mps_get_functionlist(...): ermittelt DLL_ID und MPS_Funktionsliste der DLL.

  3. 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)

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

  1. 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

  2. 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!

  3. 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.

14.2.1.1 mps_base.h

; ========================================================
; 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

14.2.1.2 mps_base.def

// 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

14.2.1.3 mps_base.cpp

// 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

14.2.1.4 mps_demo.h

// 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

14.2.1.5 mps_demo.cpp

// 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

14.2.1.6 testmps.s

*                                                 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

14.2.2 mec1 Schnittstelle

  1. 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 ,D1, mit = 111111 binär, also ungültig). Die Parameter-Übergabe erfolgt wie bei mec0 über die Motorola Register.

  2. Die Funktionen

    $0001 long emu_version:

    Parameter: keine
    return: d0: Versions-Nummer
      d1: Versions-Datum
      d2: Bit0: Ist Demo-Version?
    $0002 long emu_enquire: Ermittelt Verschiedenes.

    Parameter: long d0: was willst Du wissen?
    return: long d0: Wert


    bisher definiert:

    was: 1: Versionsnumemr
      2: Versionsdatume
      3: Ist Demo?
    $0003 void emu_getexepath: Ermittelt vollen Pfad (incl. Laufwerk, ohne MAGIC_PC.EXE)

    Parameter: a0: char *bufadr (Buffer)
      d0: short nb_max (max. Byteszahl für Buffer)
    $0004 int emu_install_newvdi:

    Parameter: a0: Byte *bufadr (neuer Inhalt von NVDI_PC.DLL)
      d0: long nbytes (Länge)
    return: d0: >0: erfolgreich NVDI_PC.DLN erzeugt.
      Beim nächsten Hochstarten wird automatisch
      umbenannt in NVDI_PC.DLL, wie besprochen.
    $0010 void dw_addline:  ! ab 03.97

    Text in neuer Zeile im Debug-Fenster ausgeben

    Parameter: a0: Zeiger auf den Text.
    $0011 void dw_addtext:  ! ab 03.97

    Text im Debug-Fenster ausgeben

    Parameter: a0: Zeiger auf den Text.
    $0011 void dw_formtxt:  ! ab 03.97

    Text sprintf-like im Debug-Fenster ausgeben

    Parameter: a0: Zeiger auf den Format-String
      d0, d1, ... zusätzliche Parameter, passend zu
      dem Format-String der Formatstring entspricht
      ungefähr sprintf(format,...); Stringpointer
      sind jedoch nicht zulässig.
    $0031 int printer_open  ! ab 03.97

    printer_open öffnet den Standarddrucker und beginnt ein neues Dokument

    Parameter: a0: char *DocName (NULL-Pointer erlaubt)
    return: d0>0: alles klar
      d0<=0 Fehler
    $0032 int printer_close  ! ab 03.97

    printer_close beendet das zuvor geöffnete Dokument und schließt den Drucker

    Parameter: keine
    return: d0>0: alles klar
      d0<=0 Fehler
    $0033 int printer_write  ! ab 03.97

    Parameter: a0: Byte *pData; // Zeiger auf den DatenBuffer
    d0: long nBytes; // Zahl der Bytes im Buffer
    return: d0: übertragene Bytes.
    $0040 DWORD getTickCount  ! ab 03.97

    return: d0: TickCount (msec seit Start des Rechners)
    $0041 DWORD getDrivePath  ! ab 02.99

    Die Funktion ermittelt den Windows-Pfad für ein Magic-Laufwerk.

    Parameter: d0: DriveNr (0 für A:, 1 für B:, ...)
      a0: Textbuffer für den Pfad
      d1: Größe des Textbuffers
    return: d0: 0: nicht gefunden,
          1: Container-Laufwerk,
          2: xfs-Laufwerk (Windows-Laufwerk)
          4: Floppy-Laufwerk
    $0042 DWORD setClipboardDir  ! ab 02.99

    Parameter: a0: char *pPath // NULL: auf Default setzen
    return: d0: 1


    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

    Parameter: d0.l: 1: Position nach dem Auslesen zurücksetzen
          0: Position nach dem Auslesen nicht zurücksetzen
    return: d0.l: aktuelle Position des Mausrades


    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

    Parameter: d0.l: Auswahl, im Moment realisert:
      d0 = 1: Compiler ein/ausschalten:
      ————————-
      d1 = 0: Compiler aus,
      d1 = 1: Compiler ein
      d1 = -1: Modus erfragen (Nach meinen Erfahrungen
               funtioniert dies nicht, soll aber in
               der 6.20 funktionieren)
    return: alter Modus (0 oder 1).


HomeEmulatorenMagiC Mac-SpezifikaSTEmulator