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

Reprise du message précédent
Bon, les amis, je suis face à un mur pour ce projet.
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.

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 ...
- 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 ...
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
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)
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
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

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.
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.
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)

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
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 ...
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 .
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

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 .
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
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)

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.
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.

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
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.

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.
Génère :
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.
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.

C'est étrange je n'obtient pas le même code que toi (SDCC 4.0.7 #11994)
pour les boucles FOR
En ASM
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 :
Edité par
ericb59
Le 11/02/2021 à 11h43
_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: }

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é.
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.
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.
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)

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.
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.
Répondre
Vous n'êtes pas autorisé à écrire dans cette catégorie