MSX Village forum

La Place des Développeurs Projet GOS Et oui, encore trop d'ambitions ^^

aoineko Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : Shoutbox

Inscrit le : 02/01/2011 à 21h17

Messages: 2702

Le 08/02/2021 à 22h58

Reprise du message précédent

Bon, les amis, je suis face à un mur pour ce projet. :moue
Je pensais être limité par les capacités d'affichage du V9938 mais mes tests étaient assez concluant.
C'était pas super rapide, mais j'étais très agréablement surpris d'arriver à tout faire tenir en VRAM, à avoir un scrolling potable et à faire bouger 14 personnages bitmap en même temps (à 12,5 Hz).
Mes fonctions d'affichage sont bien optimisés donc le surcout à utiliser le C est assez faible.

Ce que j'avais sous-estimé, c'est le cout des opérations mathématiques (même simples) pour le CPU.
Là, même en optimisant bien, le C tue complètement les performances et je me retrouve avec 6 frames d'affichage pour 1 cycle gameplay... cycle durant lequel, je fais pas la moitié des opérations dont j'aurais besoin pour le jeu complet.
Je pense qu'en assembleur il y aurait moyen de faire tenir toute la logique de l'IA dans le temps de 4~6 frames d'affichage, mais si je continue en C, je vais me retrouver avec un jeu vraiment trop lent.

Je vais laisser reposer en paix le projet GOS et je vais réfléchir à quelque chose de plus réaliste.
La bonne nouvelle, c'est que j'ai maintenant un lib assez complète. :)
Et je compte bien en faire quelque chose !
Peut-être le jeu de tennis que j'avais en tête au départ.


On est toujours ignorant avant de savoir.
Github    
ericb59 Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : compte ++ Groupe : Shoutbox

Inscrit le : 17/04/2012 à 10h25

Messages: 5485

Le 09/02/2021 à 07h06
Il faut des compromis quelque part...
- utiliser des sprites hardware pour les joueurs ?
- diminuer le nombre de joueurs gérés par l'IA ?
- diminuer le nombre de joueurs tout court ?
- Une IA plus simple ?
- Ne pas faire de calculs ! Gérer avec des tables précalculees ?

Moi j'aimerai bien voir ce que ça donne en 3 VS 3
par exemple ...


banniere-ericb59e
Site web    
Metalion Membre non connecté

Conseiller Municipal

Rang

Avatar

Inscrit le : 23/12/2009 à 15h32

Messages: 1487

Le 09/02/2021 à 07h42
Je suis assez d'accord avec Eric ...
Il y a des solutions.

J'avoue que j'étais assez étonné de voir que tu utilisais des sprites hardware, qui sont lents par nature, alors que le V9938 te permet 32 sprites multicolores à l'écran, avec un nombre beaucoup moins important d'opérations pour les afficher et les gérer.

Et quels sont les calculs qui te bloquent ? Comme le dit Eric, les tables précalculées sont souvent la réponses à des calculs complexes. Je les utilise beaucoup dans ma démo d'Outrun, Je n'ai besoin que de 40.000 cycles pour calculer toute la projection de la route en 3D, tu n'as quand même pas de besoins plus importants pour ton jeu ?
Edité par Metalion Le 09/02/2021 à 07h42


MSX1: Daewoo DPC-200 / Yamaha CX5M
MSX2: Sony HB-F9P
MSXVR
Vidéo: V9990 (GFX-9)
Audio: MSX-Music (FM-PAC) / MSX-Audio (Audiowave) / OPL4 (Monster Sound FM Blaster) / OPNB (Neotron)
   
Jipe Membre non connecté

Maire-adjoint

Rang

Avatar

Association

Inscrit le : 02/10/2009 à 19h41

Messages: 10352

Le 09/02/2021 à 13h19
Faut pas baisser les bras

Connais tu les 2 jeux suivants :

https://www.generation-msx.nl/software/sega/champion-soccer/release/550/

https://www.generation-msx.nl/software/matsushita-electric-industrial/msx-soccer/release/595/

2 jeux de foot en rom 16k pour MSX1

il y a des videos ;)

si ça peut te donner des idées pour les gestions des joueurs


:noel
Site web    
aoineko Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : Shoutbox

Inscrit le : 02/01/2011 à 21h17

Messages: 2702

Le 09/02/2021 à 13h32
L'affichage n'est vraiment pas un soucis.
Je ne comptais pas avoir un jeu très rapide donc 12,5 Hz (4 frames) me suffises largement.
Il y a des optimisations possibles, mais rien de bloquant.

Pour les problèmes de perf CPU, j'ai par exemple une fonction qui calcul la distance entre un joueur et le ballon. Seul le joueur de chaque équipe le plus proche du ballon a une vrai IA ; tous les autres ne font que suivre un slot précalculé en fonction du Y du ballon (pour simuler le placement défensif/offensif). Le calcul de distance carré (pour éviter la racine) pour les 14 joueurs prends actuellement 1,5 frame GPU ! Alors oui, je pourrais répartir ce calcul sur plusieurs frames mais quand je vois le code assembleur généré, c'est assez désespérant.
Je pense que les deux seules solutions seraient :
- De coder tous les gameplay en assembleur (je me sens pas encore prêt pour ça),
- De diminuer le nombre de joueur.

Le soucis, c'est que je voulais essayer de faire un "vrai" jeu de foot. En 5v5, c'est plus vraiment du foot. :-/
A la limite, faire du Street Soccer en 3v3 sur un écran fix, ça me semblerait jouable.
Par contre, c'est un genre de jeu qui demande un peu plus d'anims.
J'ai encore de la place en VRAM, mais faudrait que je produise de nouvelles images (ce que j'ai RIP ne suffirait pas).

Bref, je vais réfléchir à tout ça. :)


On est toujours ignorant avant de savoir.
Github    
Metalion Membre non connecté

Conseiller Municipal

Rang

Avatar

Inscrit le : 23/12/2009 à 15h32

Messages: 1487

Le 09/02/2021 à 15h13
aoineko :
Le calcul de distance carré (pour éviter la racine) pour les 14 joueurs prends actuellement 1,5 frame GPU ! Alors oui, je pourrais répartir ce calcul sur plusieurs frames mais quand je vois le code assembleur généré, c'est assez désespérant.

Oui, ça c'est énorme ... Si on parle bien du calcul de la distance : (Xb-Xa)^2+(Yb-Ya)^2 que tu dois faire pour les 14 joueurs par rapport à la balle (je suppose).

Et en imaginant que X € [0,255] et Y € [0,511], on a donc une multiplication 8bits x 8bits, une mutiplication 9bits x 9bits et une addition. En ordre de grandeur, en assembleur, la multiplication 8x8 prends 400 cycles, et celle en 9x9 prends 450 cycles. Cela fait donc 850 cycles plus l'addition, allez j'arrondi à 900 cycles si tu dois stocker le résultat quelque part.

Pour 14 joueurs, cela fait donc 12600 cycles, soit 0.2 frame CPU.




Edité par Metalion Le 09/02/2021 à 15h16


MSX1: Daewoo DPC-200 / Yamaha CX5M
MSX2: Sony HB-F9P
MSXVR
Vidéo: V9990 (GFX-9)
Audio: MSX-Music (FM-PAC) / MSX-Audio (Audiowave) / OPL4 (Monster Sound FM Blaster) / OPNB (Neotron)
   
ericb59 Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : compte ++ Groupe : Shoutbox

Inscrit le : 17/04/2012 à 10h25

Messages: 5485

Le 09/02/2021 à 15h35
Aoineko et Metalion

vous êtes de bien meilleurs programmeur que je ne le suis, mais il y a quelques temps de cela j'avais testé différentes solutions pour calculer rapidement la distance entre 2 points et/ou tracer une droite entre ces 2 points.
Les calculs en C sur un ordinateur 8bits c'est vraiment pas génial :p

Alors j'ai cette routine qui est plus rapide que les calculs que j'ai pu tester. On ne sait jamais, peut être que ça te sera utile.
Et sans doute qu'on peut encore l'optimiser ...

Code C :
 
int myLine(char x1, char y1, char x2, char y2, char col) {
    int        x, y,i;
    int        dx, dy;
    int        incx, incy;
    int        balance;
 
    if (x2 >= x1)
    {
        dx = x2 - x1;
        incx = 1;
    }
    else
    {
        dx = x1 - x2;
        incx = -1;
    }
 
    if (y2 >= y1)
    {
        dy = y2 - y1;
        incy = 1;
    }
    else
    {
        dy = y1 - y2;
        incy = -1;
    }
 
    x = x1;
    y = y1;
 
    if (dx >= dy)
    {
        dy <<= 1;
        balance = dy - dx;
        dx <<= 1;
        i=0;
        while (x != x2)
        {
            Pset(x, y,col,0);
            i++;
            if (balance >= 0)
            {
                y += incy;
                balance -= dx;
            }
            balance += dy;
            x += incx;
        } 
        Pset(x, y, col,0);
    }
    else
    {
        dx <<= 1;
        balance = dx - dy;
        dy <<= 1;
        i=0;
        while (y != y2)
        {
            Pset(x, y, col,0);
            i++;
            if (balance >= 0)
            {
                x += incx;
                balance -= dy;
            }
            balance += dx;
            y += incy;
        } 
        Pset(x, y, col,0);
    }
 
    return (i);
}
 
 


La routine est ici configurée pour tracer une droite entre (X1,Y1) et (X2,Y2) en mode Screen8.
Elle retourne la distance entre les 2 points.
Enlèves les quatre PSET de la routine, juste pour avoir le calcul de distance, en retour .



banniere-ericb59e
Site web    
Metalion Membre non connecté

Conseiller Municipal

Rang

Avatar

Inscrit le : 23/12/2009 à 15h32

Messages: 1487

Le 10/02/2021 à 09h47
Tu peux aussi utiliser une table précalculée pour la distance.
Si par exemple tu ne calcule que tous les 8 pixels, cela fait une table de 32x64x2=4096 octets, tout à fait gérable. Edité par Metalion Le 10/02/2021 à 10h26


MSX1: Daewoo DPC-200 / Yamaha CX5M
MSX2: Sony HB-F9P
MSXVR
Vidéo: V9990 (GFX-9)
Audio: MSX-Music (FM-PAC) / MSX-Audio (Audiowave) / OPL4 (Monster Sound FM Blaster) / OPNB (Neotron)
   
aoineko Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : Shoutbox

Inscrit le : 02/01/2011 à 21h17

Messages: 2702

Le 10/02/2021 à 15h25
Le problème de distance, c'est juste un exemple parmi tant d'autres de fonctions couteuses de base, beaucoup plus couteuses en C et encore plus couteuses quand tu as 15 acteurs à gérer (le ballon et 14 joueurs).
Si je prends 4 Ko pour régler chaque soucis, ça va vite déborder. ^^
Si j'en crois mes outils de profling (et les 6 cycles VDP que prends le code actuellement), ça me semble pas tenable en C.
Ceci dit, j'ai des chiffres étrangement haut (même pour du C).
Je vais creuser un peu pour voir si y a pas des pertes évitables.
Je me rappel avoir vu un bug de SDCC qui générait du code atrocement lent sur une boucle, mais je me souviens plus des détails. :(


On est toujours ignorant avant de savoir.
Github    
ericb59 Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : compte ++ Groupe : Shoutbox

Inscrit le : 17/04/2012 à 10h25

Messages: 5485

Le 10/02/2021 à 19h29
Citation :


Je me rappel avoir vu un bug de SDCC qui générait du code atrocement lent sur une boucle, mais je me souviens plus des détails


Il me semble que les boucles while sont plus rapides que les boucles For.
J’ai lu ça, mais ce n’est peut être plus vrai aujourd’hui.


banniere-ericb59e
Site web    
aoineko Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : Shoutbox

Inscrit le : 02/01/2011 à 21h17

Messages: 2702

Le 10/02/2021 à 20h23
Normalement, la différence, c'est surtout entre le ++i ou le i++ dans les boucles for (le 1er étant censé être plus rapide).

MAIS... je viens de vérifier, et SDCC se comporte mal dans les 2 cas. :(

Code C :
 
    for(u8 i = 0; i < 100; i++)
        g_Frame = i;
 
    for(u8 j = 0; j < 100; ++j)
        g_Frame = j;
 
    u8 k = 0;
    do {
        g_Frame = k++;        
    } while(k < 100);


Génère :

Code ASM :
;D:\Dev\Private\MSX\proj\tennis\tennis.c:81: for(u8 i = 0; i < 100; i++)
    xor    a, a
00110$:
    cp    a, #0x64
    jr    NC,00101$
    ld    (_g_Frame+0), a
    inc    a
    jr    00110$
00101$:
;D:\Dev\Private\MSX\proj\tennis\tennis.c:86: for(u8 j = 0; j < 100; ++j)
    xor    a, a
00113$:
    cp    a, #0x64
    jr    NC,00102$
    ld    (_g_Frame+0), a
    inc    a
    jr    00113$
00102$:
;D:\Dev\Private\MSX\proj\tennis\tennis.c:92: u8 k=0; do { ... k++; } while(k < 100);
    xor    a, a
00103$:
    ld    (_g_Frame+0), a
    inc    a
    cp    a, #0x64
    jr    C,00103$
 


Du coup, oui, avec SDCC le do/while est plus performant que la boucle for... mais ça ne devrait pas être le cas avec un bon compilateur.

Le bug dont je parlais était beaucoup grave. Je ne me souviens plus du détail, mais ça avait complètement tué mes perfs d'un coup.

EDIT : Pour info, u8 l=0; while(l < 100) { ... l++; }; a le même problème que les boucle for.


On est toujours ignorant avant de savoir.
Github    
ericb59 Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : compte ++ Groupe : Shoutbox

Inscrit le : 17/04/2012 à 10h25

Messages: 5485

Le 11/02/2021 à 11h43
C'est étrange je n'obtient pas le même code que toi (SDCC 4.0.7 #11994)
pour les boucles FOR

Code C :
 
char Frame;
void main (void)
{
    char i,j,k;
 for( i = 0; i < 100; i++)
 {
      Frame = i;
  }
 
  for( j = 0; j < 100; ++j)
  {
      Frame = j;
  }
 
    k = 0;
    do {
        Frame = k++;        
    } while(k < 100);
}
 



En ASM

Code ASM :
 
_main::
;testx.c:16: for( i = 0; i < 100; i++)
    ld    c, #0x64
00108$:
;testx.c:18: Frame = i;
    ld    a, c
    dec    a
    ld    (_Frame+0), a
    ld    c, a
;testx.c:16: for( i = 0; i < 100; i++)
    or    a, a
    jr    NZ, 00108$
;testx.c:21: for( j = 0; j < 100; ++j)
    ld    c, #0x64
00111$:
;testx.c:23: Frame = j;
    ld    a, c
    dec    a
    ld    (_Frame+0), a
    ld    c, a
;testx.c:21: for( j = 0; j < 100; ++j)
    or    a, a
    jr    NZ, 00111$
;testx.c:27: do {
    xor    a, a
00103$:
;testx.c:28: Frame = k++;        
    ld    (_Frame+0), a
    inc    a
;testx.c:29: } while(k < 100);
    cp    a, #0x64
    jr    C, 00103$
;testx.c:32: }
 
Edité par ericb59 Le 11/02/2021 à 11h43


banniere-ericb59e
Site web    
aoineko Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : Shoutbox

Inscrit le : 02/01/2011 à 21h17

Messages: 2702

Le 11/02/2021 à 12h42
J'utilise l'option de compilation --opt-code-speed ; toi aussi ?

En tout cas, pour nous deux, la version do/while reste la plus propre.
Ce qui est étonnant, c'est que la boucle for avec post-incrémentation devrait être tout aussi optimisé.


On est toujours ignorant avant de savoir.
Github    
Metalion Membre non connecté

Conseiller Municipal

Rang

Avatar

Inscrit le : 23/12/2009 à 15h32

Messages: 1487

Le 11/02/2021 à 13h11
Globalement, le code généré n'a pas l'air si mauvais que ça ...
Bien sûr il pourrait être optimisé, mais ce n'est pas le but d'une compilation C.


MSX1: Daewoo DPC-200 / Yamaha CX5M
MSX2: Sony HB-F9P
MSXVR
Vidéo: V9990 (GFX-9)
Audio: MSX-Music (FM-PAC) / MSX-Audio (Audiowave) / OPL4 (Monster Sound FM Blaster) / OPNB (Neotron)
   
aoineko Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : Shoutbox

Inscrit le : 02/01/2011 à 21h17

Messages: 2702

Le 11/02/2021 à 14h08
Grauw dit aussi tout le temps « si c'est en C, c'est que vous voulez pas un truc optimisé »... et bah, j'suis pas tout à fait d'accord.
Je sais bien qu'on pourra jamais avoir un truc aussi optimisé que l'assembleur (et encore, un compilateur ultime devrait pouvoir battre un humain en théorie), mais c'est pas une raison pour ne pas tenter de s'en approcher.
Surtout pour une fonctionnalité aussi basique et intensivement utilisée qu'une boucle.

Après, encore une fois, à l'origine je parlais d'un vrai gros bug.
Pour les boucles, c'est assez gênant, mais c'est pas critique.


On est toujours ignorant avant de savoir.
Github    
ericb59 Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : compte ++ Groupe : Shoutbox

Inscrit le : 17/04/2012 à 10h25

Messages: 5485

Le 11/02/2021 à 15h58
Non j'étais en --opt-code-size

mais je viens de tester en --opt-code-speed

et j'ai exactement le même résultat.


banniere-ericb59e
Site web    
Répondre
Vous n'êtes pas autorisé à écrire dans cette catégorie