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

#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  ***
// *****************************
function00();//vecteur d'initialisations
function01();//fonction 1 - appel depuis basic avec |HELLO,param1,param2,...
void skip00();//sauts divers
void skip02();
void skip04();

// **************************
// ***  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 x=0;int y=0;
int nbrParam=0;        //nombre de paramètres de la commande BASIC
int BasicParams[32];    //32 paramètres maxi
//--------------------------------------------------------------------------------------

typedef int (*PtrFunct)();    // défini "type" pointeur de fonction
PtrFunct CppVecTb[20];      // table des vecteurs du module(128 vecteurs maxi)
//autre ex:>>> typedef int (*PtrFunct)(int, int);PtrFunct pf;

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

//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 (*)1ere adresse Cpc accessible(pour les modules C++ l'accès
                                // à la mémoire Z80 n'est possible qu'à travers l'interruption INT 018H)
  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];     // (V1.19c) 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 (*)
                        //       ou nombre de pages à allouer (si<>0 au chargement)
                        //       ou nombre de pages connectées (*)
                        //       ou nombre de pages à connecter (si<>0)
                        // (l'émulateur réserve 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[20];        // s02FH 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
X86Tb.MnemosBASIC=&MnemosBASIC[0]; // w010h offset mnémoniques
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.S28H[0]=4;                    // nombre de pages à connecter(toujours 4 pour les modules C++)
return &X86Tb;// transmet l'offset de la table d'implémentation du module à l'émulateur

}

void BackToZ80(){//Return to Z80
//(x&y=global integers)
asm{push ax};x=X86Tb.W2BH;y=X86Tb.W2DH;asm {pop ax;cli;mov ss,x;mov sp,y;sti;retf}
}

function00(){//vecteur 0 d'initialisation appelé au boot Cpc
    asm {//Init fonction pour appel depuis CPC
        mov bp,cs;cli;mov ss,bp;mov sp,STACK_INIPTR;sti;mov bp,sp
    }
    printf(" HELLO    1.0\n"); // message INIT
    asm {stc}//marque ok pour vecteur INIT
    BackToZ80();//Return to Z80
}

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
    asm{
        and ax,01Fh        // 32 paramètres max
        mov nbrParam,ax    // nombre de paramètres
        mov cl,al
        xor ch,ch
        add cx,cx        // taille transfert
        jz short skip04    // sauter si pas de paramètre
        mov di,offset BasicParams
        mov ah,5        // read bloc banque 0 Cpc
        int 018h
        }
skip04:
return nbrParam;
}

//cette fonction peut être appelée depuis main() pour tests
function01(){//function 1 - call from basic with |HELLO,param1,param2,...
    if (GsSeg!=0){    //Data segment of the emulator CpcAlive
                    //=flag appel depuis émulateur
        asm{//Init fonction pour appel depuis CPC
            mov bp,cs;cli;mov ss,bp;mov sp,STACK_INIPTR;sti;mov bp,sp
        }
    }
       
    //---------------------------------
    //Free C++ area
    if (BasicParamInput()!=0){//charge paramètres de la commande BASIC
        printf("Nbre de parametres=%d\n",nbrParam);
    }
    printf("HELLO CPC");
    //---------------------------------

    if (GsSeg==0x0){return 0;}    //retour main() si appel depuis main()
    BackToZ80();                //sinon retour Z80
}

// transmet l'offset de la table d'implémentation du module à l'émulateur
struct X86TbStruct *main() // fonction d'entrée du programme
{
    CppVecTb[0]=&function00;// 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;

}