CpcAlive est un
environnement
de programmation
compatible
Amstrad CPC
pour création
d'animations
 graphiques.




Les mots clés du basic Cpc

Les messages d'erreur du basic Cpc

La mémoire

La gestion des disquettes


Z80: opcodes et programmation

Installateur CpcAlive pour
Windows & DosBox

Documentation CpcAlive






English

**  Exemple de module C++ pour l'émulateur CpcAlive **




/* HELLO.CPP -
Ce programme est un module CpcAlive et il doit être compilé
seulement avec le compilateur 
Borland Turbo C++ Version 3.0(1992) avec la commande:
tcc -mt -lt HELLO.cpp
qui produira un fichier de format compatible Dos avec une extension .COM
Toutes le variables utilsées dans les lignes en langage assembleur doivent être "globales"
- Chargement à partir de la ligne de commande Dos:  ! HELLO.COM
- Chargement à partir d'un fichier de commandes CpcAlive:  HELLO.COM
- Chargement à partir de l'interpréteur basic du Cpc:  |INPUT,"HELLO.COM":CALL 0
-----------------------------------------------------------------------------
!! nécessite la version V1.19i ou plus de l'émulateur CpcAlive !!
-----------------------------------------------------------------------------*/

#include <stdio.h>
#include <string.h>

#if defined(__TURBOC__) || defined(_MSC_VER)
    #include <conio.h>
#else
    #define _MAX_PATH 250
    #define stricmp(x,y) strcasecmp(x,y)
    #define strnicmp(x,y,z) strncasecmp(x,y,z)
#endif
#define STACK_INIPTR -2

// *****************************
// ***  Fonction prototypes  ***
// *****************************
CallFunctions();//routine d'appel des fonctions C++
ModuleInit();//vecteur d'initialisations
function01();//fonction 1 - appel depuis basic avec |HELLO,param1,param2,...
void skip00();//sauts divers
void skip02();

// **************************
// ***  Global variables  ***
// **************************

//--------------------------------------------------------------------------------------
//!!!!Toutes les variables utilsées dans les lignes en langage assembleur doivent être "globales"!!!!
int GsSeg=0;//Segment data de l'émulateur CpcAlive=flag appel depuis émulateur
int BasicParams[32];    //32 paramètres maxi
int nbrParam=0;        //nombre de paramètres de la commande BASIC
//--------------------------------------------------------------------------------------
typedef int (*PtrFunct)();    // défini "type" pointeur de fonction
PtrFunct CppVecTb[20];      // table des vecteurs du module(128 vecteurs maxi)
PtrFunct FunctionOfs;int ssBak=0;int spBak=0;//valeurs temporaires
//autre ex:>>> typedef int (*PtrFunct)(int, int);

#if !defined(NO_MNEMOS)
   char MnemosBASIC[] = {// Mnémoniques d'appels depuis le BASIC CPC
   'I','N','I','T'|0x80,         //CppVecTb[0]=fonction 0 - initialisations
   'H','E','L','L','O'|0x80,    //CppVecTb[0]=fonction 1 - appel depuis basic avec |HELLO,param1,param2,...
                                  //...
   '\0'};                        //marque fin de table
#endif

//structure table d'implémentation du module
struct X86TbStruct {//s=string,w=word,b=byte,*=valeurs générées par le système
  char mark[6];                    // s000h marque("X86CPC")
  int X86TbVersion;                // w006h version table
  PtrFunct *CppVecTb;          // w008h adresse table vecteurs d'entrée
  int W0AH[3];                    // w00Ah réservé
  char *MnemosBASIC;         // w010h offset mnémoniques
  char B12H[4];           // 4 valeurs
                                // b012h (*)reçoit le numéro de module X86
                                // b013h numéro module complément
                                // b014h (*)reçoit le numéro de la rom Z80 associée
                                // b015h indicateur pour connection banques Cpc ou modules compléments
  int W16H;                 // w016h réservé
  char S18H[6];        // 4 valeurs
                        // b018h réservé
                        // w019h (*)reçoit le handle ems associé au module
                        // w01Bh (*)reçoit le numéro logique première page du module
                        // b01Dh réservé
  int W1EH[5];     // utiliser le même modèle que les fonctions de la table CppVecTb pour programmer ces fonctions
                        // w01Eh adresse appelée à l'arrêt de l'émulateur (0=pas d'appel)
                        // w020h adresse appelée à la mise en veille de l'émulateur (0=pas d'appel)
                        // w022h adresse appelée au retour de veille de l'émulateur (0=pas d'appel)
                        // w024h adresse appelée au chargement du module (0=pas d'appel)
                        // w026h réservé
  char S28H[3];   // 2 valeurs
                        // b028h reçoit le nombre de pages allouées au module (*)
                        //         (toujours 4 pages pour les modules C++)
                        // w029h réservé
  int W2BH;             // w02Bh(*)SS segment pile émulateur
  int W2DH;             // w02Dh(*)SP pointeur pile émulateur
  char S2FH[1];            // s02FH réservé
  PtrFunct W30H;        // w030h offset routine d'appel des fonctions C++
  PtrFunct W32H;        // w032h (*)reçoit l'adresse de la fonction appelée
  char S34H[100];        // s034H réservé
};

struct X86TbStruct X86Tb;//table d'implémentation du module

struct X86TbStruct *X86TbSet(){  // init table d'implémentation du module
strcpy(X86Tb.mark,"X86CPC");       // s000h marque("X86CPC")
X86Tb.X86TbVersion=1;                // w006h version table
X86Tb.CppVecTb=&CppVecTb[0];  // w008h adresse table vecteurs d'entrée
#if defined(NO_MNEMOS)
    X86Tb.MnemosBASIC=0;       // w010h offset mnémoniques (0=pas de mnémoniques)
    X86Tb.W24H=&ModuleInit;    // fonction appelée au chargement du module
#else
    X86Tb.MnemosBASIC=&MnemosBASIC[0];    // w010h offset mnémoniques
#endif
X86Tb.B12H[0]=-1;           // b012h (*)reçoit le numéro de module X86
X86Tb.B12H[1]=-1;           // b013h numéro module complément
X86Tb.B12H[2]=-1;           // b014h (*)reçoit le numéro de la rom Z80 associée
X86Tb.B12H[3]=-1;           // b015h indicateur pour connection banques Cpc ou modules compléments
X86Tb.W30H=&CallFunctions;    // routine d'appel des fonctions C++
return &X86Tb;// transmet l'offset de la table d'implémentation du module à l'émulateur

}

CallFunctions(){//routine d'appel des fonctions C++
asm {mov bp,cs;cli;mov ss,bp;mov sp,STACK_INIPTR;sti;mov bp,sp;push ax}
FunctionOfs=X86Tb.W32H;ssBak=X86Tb.W2BH;spBak=X86Tb.W2DH;
asm {pop ax;call FunctionOfs;cli;mov ss,ssBak;mov sp,spBak;sti;retf}
}

ModuleInit(){//vecteur 0 d'initialisation appelé au boot Cpc
#if !defined(NO_MNEMOS)
    printf(" HELLO    1.1\n"); // message INIT
    asm {stc}//marque ok pour vecteur INIT
#endif
}

int BasicParamInput(){//charge paramètres de la commande BASIC
//<AL=nombre de paramètres
//  SI pointe paramètres dans la ram cpc
//>Les valeurs récoltées dans le tableau BasicParams seront des pointeurs vers les données de chaque
//  variables (chaines de caractères par exemple), sauf pour les valeurs entières qui pouront être traitées telles quelles.

if (GsSeg==0){return 0;}//segment data de l'émulateur CpcAlive=flag appel depuis émulateur
nbrParam=_AX & 0x1f;   // 32 paramètres max
if (nbrParam){
    _CX=nbrParam*2;   // taille transfert
    _AH=5;                // lire bloc banque 0 Cpc (voir accès à la mémoire du Cpc via int 018h)
    asm{
        mov di,offset BasicParams
        int 018h
    }
}
return nbrParam;
}

function01(){//function 1 - call from basic with |HELLO,param1,param2,...
//---------------------------------
//Free C++ area
int i;
if (BasicParamInput()!=0){//charge paramètres de la commande BASIC
    printf("Nbre de parametres=%d\n",nbrParam);
    for (i = 0; i < nbrParam; i++){printf("0x%x=valeur ou pointeur parametre %d\n",BasicParams[i],i);}
}
printf("HELLO CPC");
//---------------------------------
}

// transmet l'offset de la table d'implémentation du module à l'émulateur
struct X86TbStruct *main() // fonction d'entrée du programme
{
    CppVecTb[0]=&ModuleInit;// vecteurs du module
    CppVecTb[1]=&function01;// vecteurs du module

    GsSeg=0;    //Data segment of the emulator CpcAlive
                //=flag appel depuis émulateur
    asm {
        cmp byte ptr cs:[01B1h],090h    // appel depuis émulateur ?(.COM)
        jz short skip00                    // oui sauter
        cmp byte ptr cs:[0B1h],090h        // appel depuis émulateur ?(.EXE)
        jnz short skip02                // non sauter
    }

skip00:

    asm {
        db 0Fh,0A8H    //PUSH GS(Data segment of the emulator CpcAlive)
        pop GsSeg    //!=0 -> appel depuis émulateur
    }
    return X86TbSet();// transmet l'offset de la table d'implémentation du module à l'émulateur

skip02:

    //pour test à partir du DOS
    function01();//fonction 1

    if (getch() == 0) getch();

  return 0;

}