forum

Navigation du forum
Vous devez vous identifier pour créer des messages et des sujets.

Nouveau projet : Gestion de sprites CPC+ sur CPC+

WoW ! c'est top ! sacré boulot

Si j'ai compris, tu as écrit le code en Pascal ? ça me rappelle de bons souvenirs (codage en Borland Pascal sur XT-AT)

Mais je suppose que certaines routines sont écrites en Assembleur ? Ou le tout est-il codé en pascal ?

En tout cas bravo, et merci pour ton partage 🙂

 

Hello. Oui c'est du Turbo Pascal v3. Il y a un peu d'assembleur mais ca se résume a des appels du Firmware avec des commades de type Inline. C'est du natif Pascal à 99%

Pour te donner un idée, voilà à quoi ressemble les procédures pour gérer l'ASIC  et gérer des "big sprites" (par exemple 32x48 pixels), aussi facilement que des sprites hardwares 16x16.

Les routines graphiques sont essentiellement des appels au firmware (voir l'unité UGraph dans les sources)

{ ========================================================================
TP-TOOLS v0.3 pour Turbo Pascal CPC+/CPM+. !!Uniquement pour CPC Plus!!
Unite UAsic. Gestion de l'ASIC du CPC+  By Nemo (2021)
-------------------------------------------------------------------------}
Type
{ Decription de la structure memoire de l'ASIC }
TSpr = Array[0..$f, 0..$f] Of Byte;
TScrPal= Array[0..$f] Of Integer; { SCReen PALette }
TSprPal= Array[1..$f] Of Integer; { SPRite PALette. 0-> Transparence }
TxySpr = Record x,y : Integer End;
TSprPos= Record xy : TxySpr; z: Byte; Bazar: Array[1..3] Of Byte End;
TBigSpr= Record Lrg, Htr, LxH, z: Byte End;

Const
Zy1=1; Zy2=2; Zy4=3;Zx1=4; Zx2=8; Zx4=12; { Zooms x et y }

Var
TbSpr : Array[0..15] Of TSpr Absolute $4000; { Les 16 sprites hard }
TbSprPos : Array[0..15] Of TSprPos Absolute $6000; { Position des 16 sprites }
TbScrPal : TScrPal Absolute $6400; { Palette 16 couleurs ecran }
ColBdr : Integer Absolute $6420; { Couleur du bord }
TbSprPal : TSprPal Absolute $6422; { Palette 15 coulleurs sprites }
RstIntLin: Byte Absolute $6800; { Raster Interrupt Line}
SplScrLin: Byte Absolute $6801; { Split Screen Line }
SplScrAdr: Integer Absolute $6802; { Split Screen sec. Addr.}

TbBigSpr: Array[0..15] Of TBigSpr; { Big sprites }
iSpr,jSpr : Byte;

Procedure DlkAsic; { Delock ASIC }
Type TCode = Array[1..17] Of Byte;
Const Code:TCode=($ff,$00,$ff,$77,$b3,$51,$a8,$d4,$62,$39,$9c,$46,$2b,$15,$8a,$cd,$ee);
Begin For iSpr:=1 To 17 Do Port[$bc00]:=Code[iSpr]; End;

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

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

Procedure SetAsicPalMod1(a,b,c,d:Integer);
Begin
OpnAsic;
TbScrPal[0]:=a;TbScrPal[1]:=b;TbScrPal[2]:=c;TbScrPal[3]:=d;
CloAsic;
End;

Procedure HidAllSpr;
Begin OpnAsic; For iSpr:=0 To 15 Do TbSprPos[iSpr].z:=0; CloAsic; End;

Procedure SetBigSpr(nr,a,b,zoom: Byte);
Begin
OpnAsic;
With TbBigSpr[nr] Do Begin Lrg:=a; Htr:=b; LxH:=a*b; z:=Zoom End;
For iSpr:=nr To a*b+nr-1 Do TbSprPos[iSpr].z:=zoom;
CloAsic;
End;

Procedure SetZoomBigSpr(Spr,Zoom:Byte);
Var n:Byte;
Begin
OpnAsic;
For n:=Spr To TbBigSpr[Spr].LxH Do TbSprPos[n].z:=Zoom;
CloAsic;
End;

Procedure MovAbsBigSpr(n:Byte; xBig, yBig: Integer);
Var Largeur,ZoomX,ZoomY:Byte;
Begin
OpnAsic;
Largeur:=TbBigSpr[n].Lrg;
Case TbBigSpr[n].z Of
5 : Begin ZoomY:=16; ZoomX:=16; End;
9 : Begin ZoomY:=16; ZoomX:=32; End;
13: Begin ZoomY:=16; ZoomX:=64; End;
6 : Begin ZoomY:=32; ZoomX:=16; End;
10: Begin ZoomY:=32; ZoomX:=32; End;
14: Begin ZoomY:=32; ZoomX:=64; End;
7 : Begin ZoomY:=64; ZoomX:=16; End;
11: Begin ZoomY:=64; ZoomX:=32; End;
15: Begin ZoomY:=64; ZoomX:=64; End;
End;

For iSpr:=0 To (TbBigSpr[n].LxH)-1 Do Begin
With TbSprPos[n+iSpr] Do Begin
xy.x:=xBig+(iSpr Mod Largeur)*ZoomX;
xy.y:=yBig+(iSpr Div Largeur)*ZoomY;
End;
End;
CloAsic;
End;

Procedure MovRelBigSpr(n:Byte; DeltaX, DeltaY: Integer);
Begin
OpnAsic;
For iSpr:=0 To TbBigSpr[n].LxH-1 Do Begin
With TbSprPos[n+iSpr] Do Begin
xy.x:=xy.x+DeltaX;
xy.y:=xy.y+DeltaY;
End;
End;
CloAsic;
End;

Procedure SetPal4096;
Begin OpnAsic; Inline($21/$b7f9/$cd/$fc5a/$bcdd); CloAsic; End;

Function GetScrNumPal(n:Byte):Integer;
Begin OpnAsic; GetScrNumPal:=TbScrPal[n]; CloAsic; End;

Procedure SetPalBdr(n:Integer);
Begin OpnAsic; ColBdr:=n; CloAsic; End;

Procedure CpySprToAsic(Src:TSpr; Dst:Byte);
Begin OpnAsic; TbSpr[Dst]:=Src; CloAsic; End;

Procedure SetZoomSpr(Spr,Zoom:Byte);
Begin OpnAsic; TbSprPos[Spr].z:=Zoom; CloAsic; End;

Procedure MovSpr(Spr:Byte; xs,ys: Integer);
Begin
OpnAsic;
TbSprPos[Spr].xy.x:=xs; TbSprPos[Spr].xy.y:=ys;
CloAsic;
End;

Procedure SetScrInkPal(n:Byte; c:Integer);
Begin OpnAsic; TbScrPal[n]:=c; CloAsic; End;

Procedure GetScrPal( Var Pal:TScrPal);
Var Temp:TScrPal;
Begin
OpnAsic; Temp:=TbScrPal; CloAsic;
Pal:=Temp;
End;

Procedure GetSprPal( Var Pal:TSprPal);
Var Temp:TSprPal;
Begin
OpnAsic; Temp:=TbSprPal; CloAsic;
Pal:=Temp;
End;

Procedure SetSprPal(Pal:TSprPal);
Begin OpnAsic; TbSprPal:=Pal; CloAsic; End;

Procedure CpyScrPalToSpr;
Begin
OpnAsic;
Move(TbScrPal[1], TbSprPal[1],30);
CloAsic;
End;

Procedure CpySprPalToScr;
Begin
OpnAsic;
Move(TbSprPal[1], TbScrPal[1],30);
CloAsic;
End;

Procedure SetSprPxl(n,x,y,e:Byte);
Begin OpnAsic; TbSpr[n][x,y]:=e; CloAsic; End;

Procedure SetBigSprPxl(n,x,y,e:Byte);
Var ns,xs,ys : Integer;
Begin
OpnAsic;
ns:= 1 + x Div 16 * TbBigSpr[1].Lrg + (y Div 16) ;
xs:=x Mod 16;
ys:=y Mod 16;
TbSpr[ns,xs,ys]:=e;
CloAsic;
End;

Function GetSprPxl(n,x,y:Byte):Byte;
Var e:Byte;
Begin OpnAsic; e:=TbSpr[n][x,y]; CloAsic; GetSprPxl:=e; End;

Procedure GetSprPos(n:Byte; Var x,y:Integer);
Begin
OpnAsic;
x:=TbSprPos[n].xy.x;
y:=TbSprPos[n].xy.y;
CloAsic;
End;

Function GetBigSprPxl(n,x,y:Byte):Byte;
Var ns,xs,ys : Integer;
Begin
OpnAsic;
ns:= 1 + x Div 16 * TbBigSpr[1].Lrg + (y Div 16) ;
xs:=x Mod 16;
ys:=y Mod 16;
GetBigSprPxl:=TbSpr[ns,xs,ys];
CloAsic;
End;

J'ai poussé la version 1.01 qui écrase la v1.0 dans le lien google drive. Ca ajoute les sauvegardes/chargements, les Undo  et le copier-coller entre différents sprites (ou animation) qui ne fonctionnaient pas bien en v1.

PS : je ne vois pas d'option pour pousser des textes formatés dans le forum... J'ai loupé un truc?

Tu attaques l'ASIC directement en définissant bien la structure mémoire de l'ASIC... pour gérer les sprite grâce à des tableaux ARRAY.OF...

trop fort 🙂

C'est un sacré boulot. J'ai hâte de tester lorsque mon 6128+ sera nettoyé.

Petite question : Pascal pour CPC n'utilise pas de pointeur (POINTER) ? (genre ^Tspr) pour pointer directement à la bonne adresse ?

Oui. Tu peux utiliser des pointeurs. J'en ai même des tonnes dans le programmes ;D Pour gérer les UNDO par exemple.

En fait le turbo PASCAL v3 pour CPC est exactement le même que le Turbo Pascal v3 MSDOS à quelques détails près.

Pour l'utilisation des pointeurs j'en parle dans cette vidéo : https://youtu.be/4CbTHgYUyeY

On peut faire des trucs très rapide sans assembleur. 

 

Ah oui, en effet, j'avais pourtant regardé ta vidéo mais je n'avais pas capté que tu utilises les pointeurs (notamment par le mot DISPOSE, qui aurait dû me faire comprendre 😉 )

Et je suis d'accord avec toi, le Pascal permet une exécution hyper rapide (pas autant que l'assembleur certes... mais pas loin 😉

A l'époque j'avais toujours été subjugué par la rapidité d'exécution d'un EXE compilé depuis Turbo Pascal. Ceci dit, c'est compilé, et non interprété, donc forcément c'est rapide à l'exécution 😉 D'ailleurs j'ai installé une DosBOX spécialement pour coder en Borland Pascal 16 bit, juste pour le fun 😉

J'apprécie spécialement le langage Pascal, il est structuré, puissant, et permet de programmer tout ce qu'on veut. Sur le PC, l'avantage de Borland Pascal, c'est qu'on peut directement coder en assembleur dans le code Pascal (procédure truc; assembler; asm... instructions assembleur ...end;) il faut juste faire attention à bien sauvegarder les registres, mais à part ça c'est du tout cuit.

Mais je suis un peu hors sujet là... désolé... revenons à nos Amstrad 😉

Je n'ai jamais codé en Pascal sur CPC, va falloir que je franchisse le pas.

Encore bravo pour ce que tu as fait, et merci de le partager

Hello

en fait la commande INLINE est l'ancêtre de ASM. Mais avec INLINE tu dois taper les codes hexa alors que ASM est un assembleur intégré. J'ai fait un petit programme qui génére automatique le code INLINE dans un source Pascal à partir de l'assembleur de WINAPE. La limitation (masi c'est pareil avec ASM je suppose est que le code doit être relogeable.

Finalement je n'ai pas trop programmé cette semaine de congés et j'ai plus profité du soleil (froid mais quand même)...J'ai fini quand même  la version 1.02 de TPSRPRITE. Là je me lance dans un petit jeu d'actions pour utiliser tout çà ;D En fait ce que j'aimerai est pouvoir appeler une procédure pascal (sans paramêtres) depuis du code assembleur mais je n'yarrive pas. Ca mettrait l'équivalent des AFTER, EVERY, ON SQ du Basic

doublon à supprimer

Super, ton utilitaire pour encoder en INLINE ton code assembleur winape 🙂 ouahhh 🙂 ça doit être pratique

Tu as essayé de créer un pointeur sur ta procédure pascal ?

Genre ça, qui marche en Borland Pascal :

Program test_ptr_proc;

Var Ptr_proc:pointer;

Procedure ma_proc; Far;
begin
end;

Begin
Ptr_proc:=@ma_proc;
end.

Pour compléter l'idée, l'idée est d'enregistrer ce PRT (Ptr_proc) dans une mémoire fixe, genre #EFFF, pour pouvoir ensuite appeler la procédure Pascal depuis l'assembleur en récupérant cette adresse et en JUMPant dessus.

La question est de savoir s'il faut d'abord sauvegarder les registres comme en appel de procédure ASM pascal (PUSHer les registres, puis les POPer après le RET.)

Franchement je sais même pas si ça peut marcher.........,c'est juste une idée 😉

Je ne sais même pas si ça existe de pouvoir pointer vers une procédure avec @ dans la version pascal que tu utilises sur le Z80.

En pascal Borland (16 bit) ça marche 😉

 

J'ai chargé Turbo Pascal sur 6128.

Un truc très simple : déclarer une variable de type pointeur :

Program Truc;

Var Vptr : Pointer;

Begin End.

Erreur de compilation... le type Pointer n'existe pas en Turbo Pascal version 3 ???