CPC Rulez
https://cpcrulez.fr/forum/

Turbo Pascal v3 sur Amstrad CPC 6128
https://cpcrulez.fr/forum/viewtopic.php?f=4&t=6417
Page 1 sur 4

Auteur :  Nemo59 [ 11 Nov 2020, 11:09 ]
Sujet du message :  Turbo Pascal v3 sur Amstrad CPC 6128

Salut,

j'ouvre un sujet spécifique pour les dev en Turbo Pascal v3 sur CPC6128 et 6128+ en CP/M3 (appelé aussi CP/M+). Cela me servira d'aide-mémoire et pourra faire gagner du temps à ceux qui voudraient s'y essayer. Curieusement l'utilisation spécifique du TP3 sur CPC6128 ne semble pas très documentée (le CP/M et TP3 le sont très bien par contre). Pourtant il y a des choses très sympa à faire. Mon objectif à terme est le dév d'un jeu d'aventure texte/image dans cet environnement.

Déjà pourquoi développer en Turbo-Pascal sur CPC? On pourrait aussi se dire pourquoi utiliser encore ces bons vieux CPC ;D Chacun à sa réponse. Mais pourquoi utiliser un compilateur Pascal qui a plus de 35 ans et compile sur CPC à l'heure des cross-compilateurs modernes? Parce que je trouve intéressant d'utiliser un outil de l'époque qui tourne entièrement sur CPC. Parce que le TP3 est un compilateur très sympa, très compact et très fiable. Oui il y manque pas mal de chose vs les compilateurs Pascal plus récents mais l'essentiel y est. Et puis ça m'amuse de me pencher aussi sur le CP/M, cet ancêtre du MS/DOS que j'avais totalement ignoré à l'époque, cette époque où on pouvait 'tout' connaitre d'un ordinateur et de ses logiciels. Epoque intéressante et révolue à l'heure des machines, des OS et logiciels monstrueusement obèses. Ici 128ko et un processeur Z80A à 4MHz.

Mon environnement est composé d'un CPC6128+ avec un lecteur GOTEK externe + W10 avec WinAPE

Quelques liens pour commencer :

- Le CP/M+ : Lien à préciser
- Doc CP/M+ (et gestion des banks mémoire) : http://ucw.datatraveler.co.uk/manuals/cpm3-sys.pdf
- Les portages CP/M voir la rubrique spécifique Amstrad : https://www.seasip.info/Cpm/index.html
- Le CP/M+ en ROM, bien pratique avec WinAPE : https://cpcrulez.fr/GamesTest/applications_util-graduate_software_CPM_ROM_v2_AA.htm
- Le Turbo Pascal3 : Lien à préciser
- Doc TP3 : http://bitsavers.informatik.uni-stuttgart.de/pdf/borland/turbo_pascal/TURBO_Pascal_Reference_Manual_CPM_Version_3_Dec88.pdf
- Les codes du Z80 : https://clrhome.org/table/
- L'indispensable et remarquable guide du Firmware des CPC : https://archive.org/details/SOFT968TheAmstrad6128FirmwareManual

Ce que permet le TP3 sur CPC6128 et 6128+ :
- Des programmes d'un seul bloc jusque 61Ko
- Des projet de plus de 61ko avec la gestion des "overlays" de programmes
- Accès total au firmware
- Fichiers séquentiels indexés, fichiers binaires...
- Intégration facile de code assembleur
- Appel facile à des programmes assembleurs externes avec passages de paramêtre entrants/sortants
- Pointeurs
- Structures de données complexes
- Adresses absolues de mémoire pour les variables
- Une éditeur pleine page très pratique (une fois qu'on maitrise les raccourcis clavier!)
etc.

L'émulateur WinAPE apporte
- La possibilité d'utiliser NotePad++ pour éditer les sources avec coloration syntaxique
- Le mode Turbo et accélération de la vitesse pour des compilations quasi instantanées
- Surtout la possibilité des tester très facilement et debugger des routines ASM appelées par le Pascal
etc...

Pour une première approche de l'environnement TP3/CPM+/CPC6128 :

Auteur :  Nemo59 [ 11 Nov 2020, 11:38 ]
Sujet du message :  Re: Turbo Pascal v3 sur Amstrad CPC 6128

LE GRAPHISME
-----------------

Le TP3 et CPM+ permettent d'accéder aux fonctions du firmware. Mais comme le CPM+ gère un système particulier de banque mémoire (ce qui permet d'avoir 61ko de ram linéaire pour programmer, on verra plus tard çà en détail) il y a une subtilité. Les appels doivent passer un vecteur particulier à l'adresse #fc5a

Par exemple masquer le curseur texte qui se fait par un CALL #BB84 doit être appelé en TP3 par un CALL #FC5A DW #BB84
En TP3 ça peut se coder comme çà (HidTxtCur pour Hide Text Cursor) :
Code :
Procedure HidTxtCur;
 Begin InLine($cd/$fc5a/$bb7e); End;


Le programme Grafik3.inc fourni avec le TP3 utilise çà. Je l'ai réécris comme suit en ajoutant de nouvelles commandes (work in progress). L'idée est de créer des unités thématique UGraph/USound/UKeyboard etc... (même si les UNITS Pascal n'apparaissent qu'avec les versions ultérieures de TP).

J'avais au départ repris les noms des commandes du Firmware mais c'est très verbeux. Je suis parti sur des instructions par blocs de 3 lettres (qui vont sans doute changer un peu l'usage).

Un exemple de programme (résolution du parcours du cavalier) :


Les sources :

Code :
{ =================================================
   UGraph : Unite graphique CPC6128 v0.1 - GC 2020
  ------------------------------------------------- }

Const TagFlag : Boolean = False;
      TagAddr : Integer = 0;
Var BGraph:Byte; IGraph1,IGraph2:Integer;

Procedure SetTxtCur(X,Y:Byte);
Begin InLine($3a/X/$67/$3a/Y/$6f/$cd/$fc5a/$bb75); End;

Procedure GetTxtCur(Var X,Y:Byte);
Begin InLine($cd/$fc5a/$bb78/$7c/$32/X/$7d/$32/Y); End;

Procedure DspTxtCur;
Begin InLine($cd/$fc5a/$bb7b); End;

Procedure HidTxtCur;
Begin InLine($cd/$fc5a/$bb7e); End;

Procedure SetTxtPap(Paper:byte);
Begin InLine($3a/Paper/$cd/$fc5a/$bb96); End;

Procedure SetTxtPen(Pen:byte);
Begin InLine($3a/Pen/$cd/$fc5a/$bb90); End;

Procedure IniGra;
Begin InLine($cd/$fc5a/$bbba);End;

Procedure SetMod(Mode:Byte);
Begin InLine($3a/Mode/$cd/$fc5a/$bc0e); End;

Function EncInk(InkNumber:Byte):Byte;
Begin
 InLine($3a/InkNumber/$cd/$fc5a/$bc2c/$32/BGraph);
 EncInk:=BGraph;
End;

Procedure SetInk(Ink,C1,C2:Byte);
Begin InLine($3a/C1/$47/$3a/C2/$4f/$3a/Ink/$cd/$fc5a/$bc32); End;

Procedure SetBdr(C1,C2:Byte);
Begin InLine($3a/C1/$47/$3a/C2/$4f/$cd/$fc5a/$bc38); End;

Procedure DrwScrFldBox(EncodedInk:Byte; Adr:Integer; WidthBytes,Height:Byte);
Begin
 InLine($3a/EncodedInk/$4f/$2A/Adr/$3a/WidthBytes/$57/$3a/Height/$5f/$cd/$fc5a/$bc47);
End;

Procedure DrwScrHorLin(EncodedInk:Byte; XStart,XEnd,Y:Integer);
Begin
 Inline($3a/EncodedInk/$ed/$5b/XStart/$ed/$4b/XEnd/$2a/Y/$cd/$fc5a/$bc5f);
End;

Procedure DrwScrVerLin(EncodedInk:Byte; YStart,YEnd,X:Integer);
Begin
 Inline($3a/EncodedInk/$ed/$5b/X/$ed/$4b/YEnd/$2a/YStart/$cd/$fc5a/$bc62);
End;

Procedure GetScrDotAdr(X,Y:Integer; Var Addr:Integer; Var Mask:Byte);
Begin
 InLine($ed/$5b/X/$2a/Y/$cd/$fc5a/$bc1d/$22/IGraph1/$79/$32/BGraph);
 Addr:=IGraph1; Mask:=BGraph;
End;

Procedure MovAbs(x,y:Integer);
Begin InLine($2a/x/$eb/$2a/y/$cd/$fc5a/$bbc0) End;

Procedure MovRel(x,y:Integer);
Begin InLine($2a/x/$eb/$2a/y/$cd/$fc5a/$bbc3) End;

Procedure SetOrg(x,y:Integer);
Begin InLine($2a/x/$eb/$2a/y/$cd/$fc5a/$bbc9) End;

Procedure SetWinWdt(x1,x2:Integer);
Begin inline($2a/x2/$eb/$2a/x1/$cd/$fc5a/$bbcf) End;

Procedure SetWinHht(y1,y2:Integer);
Begin InLine($2a/y2/$eb/$2a/y1/$cd/$fc5a/$bbd2) End;

Procedure DrwLinAbs(x,y:Integer);
Begin InLine($2a/x/$eb/$2a/y/$cd/$fc5a/$bbf6) End;

Procedure DrwLinRel(x,y:Integer);
Begin InLine($2a/x/$eb/$2a/y/$cd/$fc5a/$bbf9) End;

Procedure DrwPntAbs(x,y:Integer);
Begin InLine($00/$ed/$ff/$2A/x/$eb/$2A/y/$cd/$fc5a/$bbea/$ed/$ff) End;

Procedure DrwPntRel(x,y:Integer);
Begin InLine($2A/x/$eb/$2a/y/$cd/$fc5a/$bbed) End;

Function GetPntAbs(x,y:Integer):Byte;
Begin InLine($2a/x/$eb/$2a/y/$cd/$fc5a/$bbf0/$32/BGraph);
      GetPntAbs:=BGraph;
End;

Function GetPntRel(x,y:Integer):Byte;
Begin InLine($2a/x/$eb/$2a/y/$cd/$fc5a/$bbf3/$32/BGraph);
      GetPntRel:=BGraph;
End;

Procedure SetGraPen(Pen:Byte);
Begin InLine($3a/Pen/$cd/$fc5a/$bbde) End;

Procedure SetGraPap(Paper:Byte);
Begin InLine($3A/Paper/$cd/$fc5a/$bbe4) End;

Procedure GetGraCur(Var X,Y:Integer);
Begin
 InLine($cd/$fc5a/$bbc6/$22/IGraph2/$eb/$22/IGraph1);
 X:=IGraph1; Y:=IGraph2;
End;

Procedure ClrGraWin;
Begin InLine($cd/$fc5a/$bbdb) End;

Procedure DrwGraChr(Ch:char);
Begin InLine($3a/Ch/$cd/$fc5a/$bbfc) End;

Procedure SetLinMsk(Mask:Byte);
Begin InLine($3A/Mask/$cd/$fc5a/$bd4c) End;

Procedure SetPalMod1(c0,c1,c2,c3:Byte);
Begin
 SetInk(0,c0,c0);SetInk(1,c1,c1);SetInk(2,c2,c2);SetInk(3,c3,c3);
End;

Procedure DrwScrRec(E:Byte; x1,y1,x2,y2:Integer);
Begin
 DrwScrHorLin(E,x1,x2,y1);
 DrwScrHorLin(E,x1,x2,y2);
 DrwScrVerLin(E,y1,y2,x1);
 DrwScrVerLin(E,y1,y2,x2);
End;

Procedure SetTxtWin(c1,c2,l1,l2:Byte);
Begin
 InLine($3a/c1/$67/$3a/c2/$57/$3a/l1/$6f/$3a/l2/$5f/$cd/$fc5a/$bb66);
End;

Procedure GrafOut(ch:Char);
Begin
  InLine($3a/ch/$cd/$fc5a/$bbfc);
End;

Procedure SetTag;
Begin
  If Not TagFlag Then Begin
   TagAddr:=ConOutPtr; TagFlag:=True; ConOutPtr:=Addr(GrafOut);
  End;
End;

Procedure RmvTag;
Begin
  If TagFlag Then Begin
    ConOutPtr:=TagAddr; TagFlag:=False;
  End;
End;


Et le source correspondant :

Code :
Program Cavalcade;
{$i Ugraph.inc}

Type TCoord=Record
        x,y: Integer;
      End;

Const Dep: Array[1..8] Of TCoord =
           ((x: 1;y: 2),(x: 2;y: 1),(x: 2;y:-1),(x: 1;y:-2),
            (x:-1;y:-2),(x:-2;y:-1),(x:-2;y: 1),(x:-1;y: 2));

Var x,y,i,j,Adr,Err: Integer;
    b,E0,E1,E2,E3,Mini,iMini,Total: Byte;
    PCav, nPCav: TCoord;
    Echiquier:Array[-1..10,-1..10] Of Boolean;
    Rep : String[2];

Begin
 PCav.x:=0;
 Repeat
  For i:=-1 To 10 Do
   For j:=-1 To 10 Do
    If (i In [1..8]) And (j In [1..8])
     Then Echiquier[i,j]:=True
     Else Echiquier[i,j]:=False;

  {Dessin de l'echiquier et fenetre resultat}
  SetPalMod1(1,1,1,1);
  SetBdr(1,1); SetMod(1);
  E0:=EncInk(0);E1:=EncInk(1); E2:=EncInk(2); E3:=EncInk(3);
  DrwScrRec(E3,19,20,180,181); DrwScrRec(E3,18,19,181,182);
  GetScrDotAdr(20,180,Adr,b); DrwScrFldBox(E1,Adr,40,160);
  For y:=1 To 8 Do
   For x:=1 To 8 Do Begin
    GetScrDotAdr(20*x,200-20*y,Adr,b);
    If (x Mod 2<>y Mod 2) Then DrwScrFldBox(E2,Adr,5,20)
   End;
  SetPalMod1(1,13,26,0);
  SetTag;
   SetGraPen(2);
   For x:=1 To 8 Do Begin
     MovAbs(16+x*40,30); Write(Char(x+64));
     MovAbs(14,30+x*40); Write(x);
   End;
  RmvTag;
  HidTxtCur;

  SetTxtWin(24,39,2,20); GotoXY(1,1);
  IF PCav.x<>0 Then Begin

  {Resolution}

   Echiquier[PCav.x,PCav.y]:=False;
   DrwScrRec(E3,7+20*PCav.x, 7+20*PCav.y,13+20*PCav.x,13+20*PCav.y);
   SetGraPen(3); SetGraPap(0);
   Repeat
    Mini:=9; iMini:=0;
    For i:=1 To 8 Do Begin
     nPCav.x:=PCav.x+Dep[i].x; nPCav.y:=PCav.y+Dep[i].y;
     Total:=0;
     If Echiquier[nPCav.x,nPCav.y] Then Begin
      For j:=1 To 8 Do
       If Echiquier[nPCav.x+Dep[j].x,nPCav.y+Dep[j].y] Then Total:=Total+1;
      If  (Total<Mini) Or ((Total=Mini) And (Random(10)>5)) Then Begin
       Mini:=Total; iMini:=i
      End;
     End;
    End;
    If iMini<>0 Then Begin
     DrwScrRec(E3,9+20*PCav.x, 9+20*PCav.y,11+20*PCav.x,11+20*PCav.y);
     MovAbs(20+40*PCav.x,20+40*PCav.y);
     PCav.x:=PCav.x+Dep[iMini].x;PCav.y:=PCav.y+Dep[iMini].y;
     Echiquier[PCav.x,PCav.y]:=False;
     DrwLinAbs(20+40*PCav.x,20+40*PCav.y);
    End;
   Until iMini=0;
   DrwScrRec(E3,8+20*PCav.x, 8+20*PCav.y,12+20*PCav.x,12+20*PCav.y);

   WriteLn('Entree : Repete');
   WriteLn('Q : Quitte');
  End Else Begin
   PCav.x:=1; PCav.y:=1;
  End;
  WriteLn('Position? Ex:C3');
  DspTxtCur; ReadLn(Rep);
  Case UpCase(Rep[1]) Of
    'A'..'H' :  Begin
      PCav.x:=Ord(UpCase(Rep[1]))-64;
      If Not(Pcav.x In [1..8]) Then PCav.x:=1;
      Val(Rep[2],PCav.y,Err);
      If Not(PCav.y In [1..8]) Then PCav.y:=1;
    End;
  End;
 Until UpCase(Rep[1])='Q';
 SetMod(2); SetInk(1,26,26);
End.

Auteur :  Nemo59 [ 11 Nov 2020, 11:45 ]
Sujet du message :  Re: Turbo Pascal v3 sur Amstrad CPC 6128

LE SON
---------
Idem, utilisation du Firmawre.
Exemple de résultat :

L'unité USound.inc :
Code :
{=============================================
  USound : Unite son, CPC6128, v0.1 GC 2020
  --------------------------------------------}
Const ChnA=$1;  ChnB= $2;  ChnC=$4;
      RdvA=$8;  RdvB=$10;  RdvC=$20;
      Hold=$40; Flush=$80;

Type

 TSound = Record
   Channel, EnvVol, EnvTon: Byte;
   Period: Integer;
   Noise, Volume: Byte;
   Duration: Integer;
 End;

 TSection = Record
   Cnt, Siz, Tim: Byte;
 End;

 TEnv = Record
   NbrSec: Byte;
   Sec: Array[1..5] Of TSection;
 End;

Procedure RazSnd;
 Begin InLine($cd/$fc5a/$bca7); End;

Procedure AddSndQue(Sound:TSound);
 Begin
  InLine($21/Sound/$cd/$fc5a/$bcaa);
 End;

Function TstSndQue(Chn:Byte):Byte;
 Var bSnd:Byte;
 Begin
  InLine($3a/Chn/$cd/$fc5a/$bcad/$32/bSnd);
  TstSndQue:=bSnd;
 End;

Procedure SetEnvVol(EnvNbr:Byte; Env:TEnv);
 Begin InLine($3a/EnvNbr/$21/Env/$cd/$fc5a/$bcbc);End;

Procedure SetEnvTon(EnvNbr: Byte; Env: TEnv);
 Begin InLine($3a/EnvNbr/$21/Env/$cd/$fc5a/$bcbf) End;

Procedure RlsChn(Channel:Byte);
 Begin InLIne($3a/Channel/$cd/$fc5a/$bcb3) End;



Exemple de programme :

Code :
Program Son;
{$i USound.inc}

Var Sound,Sound2 : Tsound; Env,Env2: TEnv;

Begin

 WriteLn('-> Debut du prgramme');
 RazSnd;

 With Env Do Begin
  NbrSec:=3 Or $80; { 'Or $80' permet la repetition de l'enveloppe}
  Sec[1].Cnt:=50;  Sec[1].Siz:=-3; Sec[1].Tim:=1;
  Sec[2].Cnt:=1;   Sec[2].Siz:=0;  Sec[2].Tim:=40;
  Sec[3].Cnt:=150; Sec[3].Siz:=1;  Sec[3].Tim:=1;
 End;
 SetEnvTon(1,Env);

 With Env Do Begin
  NbrSec:=2 Or $80;
  Sec[1].Cnt:=10; Sec[1].Siz:= 4; Sec[1].Tim:=2;
  Sec[2].Cnt:=5;  Sec[2].Siz:=-8; Sec[2].Tim:=2;
 End;
 SetEnvTon(2,Env);

 With Env Do Begin
  NbrSec:=2 Or $80;
  Sec[1].Cnt:=20; Sec[1].Siz:= 4; Sec[1].Tim:=6;
  Sec[2].Cnt:=10; Sec[2].Siz:=-8; Sec[2].Tim:=2;
 End;
 SetEnvTon(3,Env);

 With Env Do Begin
  NbrSec:=1;
  Sec[1].Cnt:=1; Sec[1].Siz:=0; Sec[1].Tim:=240;
 End;
 SetEnvVol(1,Env);

 Env.Sec[1].Tim:=100;
 SetEnvVol(2,Env);

 Env.Sec[1].Siz:=1; Env.Sec[1].Cnt:=12; Env.Sec[1].Tim:=60;
 SetEnvVol(5,Env);

 With Env2 Do Begin
  NbrSec:=3;
  Sec[1].Cnt:=14; Sec[1].Siz:=1;  Sec[1].Tim:=50;
  Sec[2].Cnt:=1;  Sec[2].Siz:=1;  Sec[2].Tim:=2500;
  Sec[3].Cnt:=15; Sec[3].Siz:=-1; Sec[3].Tim:=100;
 End;
 SetEnvVol(3,Env2);

 With Sound Do Begin
  Channel:=ChnA; EnvVol:=5; EnvTon:=1; Period:=230;
  Noise:=0; Volume:=0; Duration:=-1;
 End;
 AddSndQue(Sound);

 Sound.EnvVol:=1; Sound.Volume:=12;Sound.Duration:=-2;
 AddSndQue(Sound);

 Sound.Channel:=ChnA Or RdvC; Sound.Duration:=-2;
 AddSndQue(Sound);

 Sound.Channel:=ChnA Or RdvB; Sound.Duration:=-5;
 AddSndQue(Sound);

 With Sound2 Do Begin
  Channel:=ChnC Or RdvA; EnvVol:=2; EnvTon:=2; Period:=110;
  Noise:=0; Volume:=15; Duration:=-15;
 End;
 AddSndQue(Sound2);

 With Sound2 Do Begin
  Channel:=ChnB Or RdvA; EnvVol:=3; EnvTon:=3;
  Noise:=12; Duration:=2650; Period:=8000; Volume:=0;
 End;
 AddSndQue(Sound2);

 Env.Sec[1].Siz:=-1;
 SetEnvVol(4,Env); Sound.EnvVol:=4; Sound.Channel:=ChnA;
 Sound.Duration:=0;
 AddSndQue(Sound);

 WriteLn('-> Fin du programme. Le Turbo Pascal ne fait deja plus rien!');
 WriteLn('   Les bruitages s''effectuent en tache de fond');
 WriteLn('    - 3 canaux stereos, enveloppes de volumes, de tons, bruits, repetitions.');
 WriteLn('    - Gestion des ''rendez-vous'' entre canaux');
 Repeat Until KeyPressed;

 RazSnd;

End.

Auteur :  norecess464 [ 11 Nov 2020, 14:00 ]
Sujet du message :  Re: Turbo Pascal v3 sur Amstrad CPC 6128

Bonjour,
Je ne fais pas parti des personnes intéressées par l'utilisation du Pascal sur Amstrad, et encore moins sous CP/M.
Cependant, l'information sur ce sujet est rarissime, donc je ne peux que te féliciter pour documenter tout cela !
Cela me rappelle, il y a quelques années sur ce meme forum, un certain "SPOKE" qui était très actif et faisait partager plein d'info intéressantes sur CP/M.
Pour l'Histoire, avec un grand H ! :D

Auteur :  Nemo59 [ 11 Nov 2020, 14:34 ]
Sujet du message :  Re: Turbo Pascal v3 sur Amstrad CPC 6128

norecess464 a écrit :
Bonjour,
Je ne fais pas parti des personnes intéressées par l'utilisation du Pascal sur Amstrad, et encore moins sous CP/M.
Cependant, l'information sur ce sujet est rarissime, donc je ne peux que te féliciter pour documenter tout cela !
Cela me rappelle, il y a quelques années sur ce meme forum, un certain "SPOKE" qui était très actif et faisait partager plein d'info intéressantes sur CP/M.
Pour l'Histoire, avec un grand H ! :D


Merci... Le fait que ce soit peu documenté est assez stimulant en fait... Pour le son je vais essayer de lancer des procédures Pascal quand les "queues" sont vides, ça doit être possible d'après la doc de Borland qui précise que le Pascal sait gérer les interruptions et j'ai compris comment appeler des procédures Pascal en ASM. Ca permettrait aussi de faire l'équivalent des commandes EVERY ou AFTER du Basic. Pour la suite on va voir la gestion des banks mémoires et l'accès à la RAM vidéo qui se trouve dans le mode d'organisation mémoire 1 à l'adresse #4000 (block 1). Le premiers tests sont concluants, par contre dès qu'on commence à jongler avec les banks mémoires ça devient chaud.

De ce que je comprends le CPM+ utilise les modes mémoires 1, 2 et 3 et la ROM basse. Le Turbo Pascal utilise le mode 2 (ce que le CPM+ appelle zone TPA : 61ko + quelques ko réservés dans ces 64ko en partie basse et haute de cette RAM pour gérer le Bank switching et les interuptions). Le block 7 (en mémoire haute) est toujours accessible. En debuggant j'ai l'impression que la config mémoire 3 est essentiellement utilisée comme cache et pour les accès disques.


Organization Block accessed at memory address
Code :
Mode mem #0000#4000 #8000 #C000
0 0 1 2 3
1 0 1 2 7
2 4 5 6 7
3 0 3 2 7
4 0 4 2 3
5 0 5 2 3
6 0 6 2 3
7 0 7 2 3

Auteur :  breiztiger [ 11 Nov 2020, 18:55 ]
Sujet du message :  Re: Turbo Pascal v3 sur Amstrad CPC 6128

Que de souvenirs ...

J’utilisais le tp sous cpm au lycée

J’avais un lecteur 5P1/4 qui me permettais d’échanger les fichiers entre les pc Goupil du bahut et mon brave cpc

De mémoire j’utilisais les extensions gx pour les graphes
https://www.cpc-p0wer.com/index.php?pag ... l&num=5924

Je vais essaye de trouvé un peu de temps pour tester tes U

Merci pour ta dévotion :biere:

Auteur :  Nemo59 [ 11 Nov 2020, 22:20 ]
Sujet du message :  Re: Turbo Pascal v3 sur Amstrad CPC 6128

Pour le clavier et joysticks

Code :
{ Unité KeyBoard, UKbd.inc}

Const Up=$1; Down=$2;Left=$4;Right=$8;Fire2=$10;Fire1=$20;

Var KbdChr, Car:Char;
    KbdByt : Byte;

Function GetChr:Char; { Touche 'au vol'}
 Begin
  InLine($cd/$fc5a/$da/$00/$79/$32/KbdChr);
  GetChr:=KbdChr;
 End;

Function StpChr:Char; { Attend une touche }
 Begin
  Inline($cd/$fc5a/$bb06/$32/KbdChr);
  StpChr:=KbdChr;
 End;

Function TstKey(Key:Byte):Boolean;
 Begin
  InLine($3a/Key/$cd/$fc5a/$bb1e/$3e/$00/$28/$02/$3e/$ff/$32/KbdByt);
  If KbdByt=0 Then TstKey:=False Else TstKey:=True;
 End;

Function GetJoyA:Byte;
 Begin
  InLine($cd/$fc5a/$bb24/$32/KbdByt);
  GetJoyA:=KbdByt;
 End;

Function GetJoyB:Byte;
 Begin
  InLine($cd/$fc5a/$bb24/$7d/$32/KbdByt);
  GetJoyB:=KbdByt;
 End;


Pour les Joysticks si on veut tester à la fois "Haut et Fire1" par exemple appuyés en même temps sur le premier Joystick, faire :

If GetJoyA = Up Or Fire1 Then ...
etc avec des 'Or' pour toutes les combinaisons. C'est un peu contre-intuitif mais logique vu qu'on teste les bits.

Si même action pour Fire1 et Fire2 par exemple faire:

If GetJoyA in [Fire1, Fire2] Then ...

Auteur :  Nemo59 [ 14 Nov 2020, 15:35 ]
Sujet du message :  Re: Turbo Pascal v3 sur Amstrad CPC 6128

Salut tout le monde... Un Amstrad CPC+ et ma période Turbo Pascal, c'est l'occasion de tester les Sprites Hard dans cet environnement :D Et bien voilà ce que ça donne :



Coté source, l'unité USprite est très compacte et simple :
Code :
{ ---------------------------------------------------------------
  Unite USprite. Gestion des Sprite hardware CPC+ v0.1  GC-2020
 ----------------------------------------------------------------}
Type
 TSpr =  Array[0..$ff] Of Byte;
 TSprPos = Record x,y: Integer; z: Byte; Bazar : Integer; End;

Const
 Zy1=1; Zy2=2; Zy4=3; Zx1=4; Zx2=8; Zx4=12;

Var
 TbSpr:      Array[0..15] Of TSpr    Absolute $4000;
 TbSprPos: Array[0..15] Of TPoSpr  Absolute $6000;
 TbPal:      Array[1..15] Of Integer Absolute $6422;

Procedure DlkAsic; { Delock ASIC }
 Type TCode = Array[1..17] Of Byte;
 Const Code:TCode=(255,0,255,119,179,81,168,212,98,57,156,70,43,21,138,205,238);
 Var b:Byte;
 Begin For b:=1 To 17 Do Port[$bc00]:=Code[b]; End;

Procedure OpnAsic; Begin Port[$7f00]:=$b8 End;

Procedure CloAsic; Begin Port[$7f00]:=$a0 End;

Procedure SetSprPal(n,r,v,b:Byte);
 Begin TbPal[n]:=v*256+16*r+b; End;


et un exemple d'utilisation :

Code :
Program Sprite;
{$i UGraph.inc}
{$i UKbd.inc}
{$i USprite.inc}
{$i pacman.spr}
Var r,v,b:Byte;
Begin
 HidTxtCur; SetMod(1); SetBdr(0,0);
 DlkAsic; OpnAsic;
 SetSprPal(1,0,0,15);  SetSprPal(2,1,1,1);
 SetSprPal(3,15,15,15);SetSprPal(4,0,0,0);
 TbSpr[0]:=Fantome;
 With TbSprPos[0] Do Begin x:=160; y:=100; z:=Zx2+Zy1 End;
 Repeat
  With TbSprPos[0] Do
   Case GetJoyA of
    Up   : y:=y-1;
    Down : y:=y+1;
    Right: x:=x+2;
    Left : x:=x-2;
   End;
 Until GetJoyA=Fire1;

 TbSprPos[0].z:=Zx4+Zy2;
 For r:=3 to 15 Do
  For v:=3 To 15 Do
   For b:=3 To 15 Do
    SetSprPal(3,r,v,b);
 TbSprPos[0].z:=0;
 CloAsic;
 RazKbdBuf; SetInk(0,0,0); SetMod(2);
End.


J'ai commencé une version qui déplace les yeux des fantômes en fonction de leur direction. Ca marche mais coder sans éditeur de sprite ça devient galère, vais voir çà. Il suffit de modifier dans l'ASIC les octets contenant les pixels des sprites à changer.

Sur les Sprites Hard, peu de chose à ajouter qu'on ne trouve pas déjà en ligne. Quand on a compris le truc c'est simple à utiliser. Parmi les trucs bizarres, je ne comprends pas pourquoi les zooms sont codés sur 4 octets comme décris ici : https://sites.google.com/site/asmtradcpc/asic-cpc-gx4000/x-tableau-de-la-page-io-asic
J'ai bêtement perdu 1 heure à cause de çà par etourderie:O Je me demande bien à quoi servent ces 2 octets en plus...

Sinon c'est étonnamment simple ;D Il faut juste être vigilant sur la gestion des blocs mémoire pour ne pas utiliser le bloc de &4000 à &8000 en même temps que les accès ASIC. Tout ça m'a d'ailleurs fait réaliser qu'on peut très probablement utiliser 2 pages videos en Turbo Pascal sur CPC (à condition de sacrifier une partie des 61ko de Ram du Pascal)...

Sur les spécificités du Turbo Pascal :
-> "Port" est équivalent des "Out" en basic ou ASM
-> 'Absolute' permet de positionner des variables en mémoire. En l'occurrence ici la mémoire de l'ASIC.
-> Bien sur le TP ne "sait pas" où pointe la mémoire de &4000 à &8000 (rn RAM, sur l'ASIC, sur la vidéo?). C'est au programmeur d'être vigilant. C'est la joie des 8 bits ;D
-> Ca se goupille plutôt bien ici puisque qu'un programme TP compilé en RAM est placé au dessus de &8000. Et sur disque (en .com) à partir de &20e2. Il faudra juste être vigilant sur les "gros programmes". Soit placer tout le code qui utilise l'Asic dans des sous-programmes en début de mémoire (et faire gaffe aux pointeurs...). Soit changer les paramètres de compilation pour compiler au dessus de &8000, là se sera très "safe" mais on perd de la RAM. Bref rien de bloquant.
- Les calculs trigos sont très lents :O (je pensais qu'il y avait un bug...). Bon on s'en fout un peu ;D

A noter qu'il est très facile de copier un sprite (ou ses positions et zoom) dans un autre par une simple affectation.
Par exemple :

Code :
TbSpr[15]:=TbSpr[0] copie le dessin du sprite 0 en sprite 15.
Idem pour les coordonnées et zoom
TbSprPos[15]:=TbSprPos[0]

Pour 'swapper' deux sprites (juste les images) :

Procedure SwpSpr(Var Spr1, Spr2 : TSpr);
 Var Tmp : TSpr
 Begin Tmp:=Spr1; Spr1:=Spr2; Spr2:=Tmp End;


On pourrait aussi facilement créer des "mega sprites" composés de axb sprites 16x16. Par exemple un gros sprite de 64x64 pixels en 16 couleurs parmi 4096, zoomable en plus.

Finalement mon exploration de TP est bien plus fructueuse que je ne le pensais. Si j'ajoute que le TP gère très bien les "overlays' (morceaux de programmes sur disque qui peut en remplacer un autre), il y a quoi bien s'amuser...

PS : Je découvre que WinAPE est développé en... Pascal. J'aime bien ce genre de coïncidence ;D en tout cas cet émulateur est formidable !

Auteur :  Nemo59 [ 17 Nov 2020, 13:04 ]
Sujet du message :  Re: Turbo Pascal v3 sur Amstrad CPC 6128

J'ai moins de temps là et pas mon CPC+ sous la main. Mais en faisant quelques tests avec l'émulateur à vitesse réelle je suis agréablement étonné de la rapidité d'animation des Sprites alors qu'il y quand même 256 octets à copier pour chaque image (dans le pire des cas où on change tous les octets du sprite, pour les fantomes pacman c'est juste quelques octets, et on peut aussi animer en utilisant plusieurs sprite hard pour une animation, ou jouer sur la palette des couleurs... bref il y a x façons de faire ou de combiner tout ça... (Dommage qu'il n'ait pas plus de sprites hard dispo). Mise à jour position d'après un tableau+mise à jour totale de l'image du sprite 16x16 + affichage + boucle = moins de 0.003 sec en Pascal sans aucun code assembleur. Doit y avoir une erreur lol... ? J'ai testé aussi une fonction PLOT (NrSprite, x,y,couleur) à l'intérieur d'un sprite (ou bloc de sprites...).

Savez-vous ou je peux trouver des sprites animés en 16*16 en 16 couleurs pour mes essais? et même des 32x32 ou autre formats ? Et si il y a la palette CPC+ avec c'est encore mieux ;D

EDIT : J'ai fais un test sur le vrai CPC+ et pas d'erreur sur la vitesse de 0.00265 sec. y compris le déplacement, et chargement des 255 octets pour l'animation(26,5s pour 10.000 boucles...) :O Copier 256 octets en ASM sur CPC prend combien?
de plus comme ça n'a aucun intérêt d'aller aussi vite pour l'animation ca prendra en fait beaucoup moins de temps que çà.

En plus c'est d'une simplicité totale, l'animation du sprite se faisant par une simple affectation :
TbSpr[nr du Sprite]:=Animation[Nr image]
Pour une animation cyclique : Animation[ Cycle mod Nombre d'image]

Le code pour l'animation (parcours sur une ellipse avec un cycle d'animation:

Code :
 For i:=1 To 100 Do            {100 tours de l'ellipse}
  For j:=1 To 100 Do Begin     {Ellipse précalculée de 100 positions xy}
   TbSprPos[0].xy:=Ellipse[j]; {Force position du sprite hard n°0}
   TbSpr[0]:=Tableau[j Mod 16];{Change l'image du sprite, animation de 16 images dans Tableau[0..15] Of TSpr}
  End;




C'est pas évident avec cette série de sprites (seule la couleur change et mon cpc+ est en N&B) mais le sprite est bien rechargé après chaque affichage (je ne joue pas sur la palette). Il y a un seul sprite au début que je recopie dans un tableau en changeant chaque fois l'encre principale du Sprite par une encre aléatoire. Comme j'ai trouvé toute une collection publique d'animation de sprites 16x16, ce sera plus parlant ;D (... à suivre...)
Plus simple on peut pas, lol... Si j'arrive à gérer les "événements" du firmware, là ça va devenir génial et encore pplus facile à utiliser ;D....

Auteur :  Plissken [ 18 Nov 2020, 12:45 ]
Sujet du message :  Re: Turbo Pascal v3 sur Amstrad CPC 6128

le zoom des sprites prends 4 bits sur un octet.Il y a 3 valeurs de zoom en x et 3 aussi en Y ,exemple pour le zoom max : %00001111 et le minimum %00000101 mettre l'un des 2 zooms à 0 équivaut à ne pas afficher le sprite.

les couleurs sont codées sur 2 octets,1 pour rouge et bleu et le 2e pour le vert,mais seul 4 bits sont utilisés(4 bits par couleur)
les data des sprites peuvent aller de 0 à 15 (4 bits) mais prennent 1 octet tout de même.

Des éditeurs de sprites il y en a au moins quatre : dans la rom impdraw d'AST, l'éditeur de sprite d'IRON(rom) ,CPC+ Sprite Editor v1.0,Hard Sprite Designer Version Beta 3(je ne sais pas s'il propose la sauvegarde celui-la).

Quant à trouver des sprites tous prêt,tu peu aller sur le site https://www.spriters-resource.com/ il y a pas mal de sprites venant d'ordi/console en tout genre

Auteur :  Nemo59 [ 18 Nov 2020, 17:37 ]
Sujet du message :  Re: Turbo Pascal v3 sur Amstrad CPC 6128

Merci pour les liens.

Ca marche très bien et j'obtiens une anim sympa avec des Sprites animés je vais finaliser et optimiser tout ça... J'ai essayé AMSprite qui est bien (mais avec quelques bug sans conséquence en w10) mais ça prends beaucoup de temps à faire :/ . Comme tu le dis, sans compression ça consomme _énormément_ de mémoire :O 256 octets par image 16x16! Si on fait pas gaffe on est vite à 64ko lol. Réduire à 128 est facile sans perte de qualité (mais prends du temps CPU pour décompresser, mais on peut décompresser juste ce dont on a besoin au debut dans tel ou tel tableau, idem pour les symétrie droite-gauche) et même à 66 octets si on limite le nombre de couleurs d'un sprite à 4 (même plutôt 3 avec la transparence) avec une mini-palette parmi les 15 de tous les Sprites.

Auteur :  Plissken [ 19 Nov 2020, 10:49 ]
Sujet du message :  Re: Turbo Pascal v3 sur Amstrad CPC 6128

De rien :)

comme un octet de sprite hard ne se sert que de 4bits,on peu dans un fichier,se servir des 4 autres bits pour d'autre sprites,il y aura juste une moulinette( :D ) a faire quand on voudra envoyer les datas dans les sprites,mais ça donnera un fichier de 2048ko avec 32 sprites au lieu de 16.

Si on veu des sprites monochromes,un octet pourrai contenir 8 sprites differents vu que l'on a besoin que d'une seule couleur.

Et des sprites en 4 couleurs,un octet pourrai en stocker 4,pas mal de bidouilles à tester au final :)

Auteur :  Nemo59 [ 19 Nov 2020, 12:43 ]
Sujet du message :  Re: Turbo Pascal v3 sur Amstrad CPC 6128

Plissken a écrit :
De rien :)

comme un octet de sprite hard ne se sert que de 4bits,on peu dans un fichier,se servir des 4 autres bits pour d'autre sprites,il y aura juste une moulinette( :D ) a faire quand on voudra envoyer les datas dans les sprites,mais ça donnera un fichier de 2048ko avec 32 sprites au lieu de 16.

Si on veut des sprites monochromes,un octet pourrai contenir 8 sprites differents vu que l'on a besoin que d'une seule couleur.

Et des sprites en 4 couleurs,un octet pourrai en stocker 4,pas mal de bidouilles à tester au final :)


Oui, il y a vraiment de quoi faire. Le meilleur compromis serait peut-être de stocker les sprites "compressés" quand ils ne sont pas utilisés et les décompresser "à l'usage" mais pas en en temps réel à chaque fois (une fois par tableau pour faire simple). Il faudra alors juste une zone tampon pour tous les sprites utilisés en même temps... J'ai retesté Antiriad qui est un jeu qui m'avait beaucoup marqué et en fait il y très peu de sprites actifs en même temps... Pourtant le résultat est top, mais il y a dû avoir un travail énorme sur chaque pixel et coté palette de couleurs! Hors le personnages principal les autres animations doivent avoir 2 ou 3 images.

Question de béotien dont je ne suis même sur qu'elle ait un sens : pour un jeu de plateforme genre CPC quel est le "frame rate" raisonnable? Ou dit autrement : quelle fréquence / sec pour tester la manette et bouger le perso principal en gardant un bon confort d'usage?

Auteur :  TotO [ 19 Nov 2020, 13:53 ]
Sujet du message :  Re: Turbo Pascal v3 sur Amstrad CPC 6128

Tout dépend si tu déplaces au char ou au pixel.
Je dirais qu'en MODE 0 il faut être en 50Hz au pixel pour avoir la même amplitude qu'au char à 12.5Hz.

Auteur :  Nemo59 [ 19 Nov 2020, 17:01 ]
Sujet du message :  Re: Turbo Pascal v3 sur Amstrad CPC 6128

Nouvelle video vitesse réelle avec des Sprite animés :



Est-il possible de tester l'état du joystick plus rapidement que le firmware avec un CALL &bb24?

Page 1 sur 4 Le fuseau horaire est UTC+1 heure
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/