./1
- Posté le 12/11/2009 à 14:04 Membre depuis le 18/06/2001, 30136 messages
yop,

J'aimerais savoir comment faire une lib dynamique en C. Dans la doc, il ya ça :
You can produce an external library file by defining the global symbol _library, i.e. by putting int _library in your program.

Ca veut dire que je mets "int _library;" quelque part et c'est bon ? C'est tout ?!?
avatar <<< Kernel Extremist©®™ >>>
Saint Qt, priez pour nous.
./2
- Posté le 12/11/2009 à 14:07 Membre depuis le 10/06/2001, 34958 messages
Oui. (Enfin, il faut aussi définir USE_KERNEL évidemment, cf. options du projet si tu utilises l'EDI.)
avatar Mes news pour calculatrices TI: Ti-Gen (fr/en), MobiFiles (de)
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité
./3
- Posté le 12/11/2009 à 14:42 Membre depuis le 18/06/2001, 30136 messages
Ok, merci. happy
avatar <<< Kernel Extremist©®™ >>>
Saint Qt, priez pour nous.
./4
- Posté le 12/11/2009 à 14:59 Membre depuis le 28/08/2003, 8213 messages
Genre tu fais du C.
avatar « Quand le dernier arbre sera abattu, la dernière rivière empoisonnée, le dernier poisson capturé, alors vous découvrirez que l'argent ne se mange pas. »
./5
- Posté le 12/11/2009 à 14:59 Membre depuis le 18/06/2001, 30136 messages
Ouais grin
avatar <<< Kernel Extremist©®™ >>>
Saint Qt, priez pour nous.
./6
- Posté le 12/11/2009 à 15:00 Membre depuis le 18/06/2001, 30136 messages
On s'endort presque à utiliser genlib en C, tout est déjà fait. grin
truc
void gl_main()
{
while( 1 )
{
// Manage non-graphical part
switch( Task )
{
}

// Wait for real screen swapping
glaux_ready();

// Manage graphical part
switch( Task )
{
}

// Wait for synchro
glaux_synchro( 1 );
glaux_swap();
}

}
avatar <<< Kernel Extremist©®™ >>>
Saint Qt, priez pour nous.
./7
- Posté le 12/11/2009 à 15:05 Membre depuis le 18/06/2001, 30136 messages
Tiens ben pendant que j'y suis, une question.

Si j'ai deux fonctions, A et B, sans "return", mais dans lesquelles elles s'appellent mutuellement, est-ce que le programme va empiler des adresses de retour sur la pile ?
ie en assembleur, j'aurais fait des bra entre les fonctions, pas des bsr.
Ca se gère comment en C ? tout seul j'espère ?
avatar <<< Kernel Extremist©®™ >>>
Saint Qt, priez pour nous.
./8
- Posté le 12/11/2009 à 15:09 - Edité par Kevin Kofler le 12/11/2009 à 15:10 Membre depuis le 10/06/2001, 34958 messages
Ça va générer le bordel sur la pile effectivement, sauf dans les cas où une optimisation tailcall est possible.

Il vaut mieux travailler avec des boucles ou des goto dans ce cas.
avatar Mes news pour calculatrices TI: Ti-Gen (fr/en), MobiFiles (de)
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité
./9
- Posté le 12/11/2009 à 15:10 Membre depuis le 28/10/2001, 7568 messages
Si l'optimiseur de flot de contrôle de GCC 1) sait faire cette optimisation sur les fonctions qui s'appellement mutuellement (attention à la terminaison de la récursivité grin) et 2) arrive dans ton cas à déterminer qu'il peut faire cette optimisation, alors il la fera.
avatar Membre de la TI-Chess Team.
Co-mainteneur de GCC4TI (documentation en ligne de GCC4TI), TIEmu et TILP.
Co-admin de TI-Planet.
- Posté le 12/11/2009 à 15:13 - Edité par squalyl le 12/11/2009 à 15:25 Membre depuis le 16/06/2001, 59933 messages
(cross, réponse à martial)

non. ça va s'appeler récursivement et remplir la pile.

ce que tu veux faire ça s'appelle des threads/couroutines/tâches, faut deux piles différentes et utiliser un truc de taskswitch préemptif style je-sais-plus-le-nm-du-truc-de-ximoon

alternativement ça peut se faire assez simplement (sisi #trioui#) avec setjmp

https://www.unsads.com/scm/svn/squalyl/asi/systeme/P3S/test/switcher-ti68k/
user guest
pass guest

(je sais plus si c'est complet, je sais plus si ça marche, mais le principe y est. Dommage j'avais un truc encore plus simple que ça, je le retrouve plus sad )

edit: ah le voila

#include <stdio.h>
#include <setjmp.h>

/*
| context switch presque portable avec setjmp, longjmp
| pour comprendre setjmp et longjmp voir la doc :
| http://www-ensimag.imag.fr/cours/Systeme/setjmp.longjmp
|
*/

#define K 1024
#define TAILLE_PILE 4*K

int mem [TAILLE_PILE]; /* memoire pour la pile du processus 1 */
int * deb_mem;
int proc_actif = 0;
jmp_buf buf_processus[2];

/*----------------------------------------------------------------------------*/
void ctxsw(actif, elu) {
if (setjmp(buf_processus[actif]) == 0) {
proc_actif = elu;
longjmp(buf_processus[elu], 1);
}
}
/*----------------------------------------------------------------------------*/
int choix_elu() {
if (proc_actif == 0) return 1; else return 0;
}
/*----------------------------------------------------------------------------*/
void resched() {
int proc_elu;
proc_elu = choix_elu();
ctxsw(proc_actif, proc_elu);
}
/*----------------------------------------------------------------------------*/
/*
| code execute par les 2 processus
|
*/
void code_processus(char * mess) {
int i;
while(1) {
printf ("%s", mess);
resched(); /* changement de processus */
}
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
int main() {
deb_mem = mem; /* on pourrait faire un malloc a la place */
/*
| ici c'est le processus 0 qui s'exécute avec la pile allouée au lancement du programme C
*/
if (setjmp(buf_processus[1]) == 0) {
#ifdef LINUX
/*
| Initialisation de la pile pour le processus 1 (petit bricolage specifique pour linux/i386)
*/
buf_processus[1][0].__jmpbuf[JB_SP] = deb_mem + TAILLE_PILE;
#else
#ifdef SOLARIS
/*
| Initialisation de la pile pour le processus 1
| (petit bricolage specifique pour Solaris/Sparc)
*/
buf_processus[1][1] = (int) deb_mem + TAILLE_PILE - 16;
#else
#error "use -DLINUX or -DSOLARIS"
#endif
#endif
printf ("Je suis le processus 0 et je pars dans la boucle\n");
code_processus("je pense\n");
} else {
printf ("Je suis le processus 1 et je pars dans la boucle\n");
code_processus(" donc tu es\n");
}
}
- Posté le 12/11/2009 à 15:21 Membre depuis le 10/06/2001, 34958 messages
Pour la TI, le code spécifique à la plateforme, c'est:
buf_processus[1]->A7 = (unsigned long) deb_mem + TAILLE_PILE;

Mais ce hack est vraiment #sick#! (Enfin, mon Task Switcher contient pire que ça, hein.)
avatar Mes news pour calculatrices TI: Ti-Gen (fr/en), MobiFiles (de)
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité
- Posté le 12/11/2009 à 15:23 Membre depuis le 16/06/2001, 59933 messages
oui ce hack est mégamoche mais franchement tu connais d'autres moyens? c'est toujours la même histoire non? allocation de l'espace mémoire du nouveau processus, et changement de SP/PC plus autres registres (bien entendu sur pc c'est carrément plus compliqué avec les mmu et etc). SetJmp n'est qu'un outil userspace pratique pour les besoins de la démo.

d'ailleurs pour avoir testé ça marche très bien sur 68k.
- Posté le 12/11/2009 à 15:28 - Edité par Folco le 12/11/2009 à 15:30 Membre depuis le 18/06/2001, 30136 messages
Kevin Kofler (./8) :
Ça va générer le bordel sur la pile effectivement, sauf dans les cas où une optimisation tailcall est possible.

Il vaut mieux travailler avec des boucles ou des goto dans ce cas.

Ok, je vais m'organiser autrement.
squalyl (./10) :
ce que tu veux faire ça s'appelle des threads/couroutines/tâches, faut deux piles différentes et utiliser un truc de taskswitch préemptif style je-sais-plus-le-nm-du-truc-de-ximoon

alternativement ça peut se faire assez simplement (sisi /v31/gfx/s3/trioui.gif ) avec setjmp

Hmm t'as vraiment pas plus simple #trilove#

Regarde à quel point j'en suis techniquement :
	char * Buffer[10] ;

sprintf( Buffer , "unmap%u" , Level );

J'aurais voulu savoir si c'est valide. Il va bien y avoir un 0 à la fin de "unmap%u" ? cheeky Ou dois-je écrire "unamp%u\0" ?

PS -> Ca fait bien deux octets un int sur TI ?

edit :
	sprintf( Buffer , "unmap%hu" , Level );
MapDesc = LibsBegin( Buffer , 0 );

Faut inclure quoi pour avoir les ramcalls ? J'ai inclus tigcclib.h, j'ai fait un #define USE_KERNEL, mais il veut pas de mon LibsBegin #ouin#
avatar <<< Kernel Extremist©®™ >>>
Saint Qt, priez pour nous.
- Posté le 12/11/2009 à 15:29 Membre depuis le 10/06/2001, 34958 messages
squalyl (./12) :
oui ce hack est mégamoche mais franchement tu connais d'autres moyens?

L'autre moyen, c'est de faire une seule fonction avec des goto, voire une simple boucle si le fonctionnement est suffisamment régulier.
avatar Mes news pour calculatrices TI: Ti-Gen (fr/en), MobiFiles (de)
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité
- Posté le 12/11/2009 à 15:32 Membre depuis le 10/06/2001, 34958 messages
Folco (./13) :
Regarde à quel point j'en suis techniquement :
	char * Buffer[10] ;

sprintf( Buffer , "unmap%u" , Level );

J'aurais voulu savoir si c'est valide.

Non. Un %u peut faire jusqu'à 5 caractères ("65535"), plus les 5 du "unmap" plus le \0, ça fait 11, donc ton buffer est trop petit.

Il va bien y avoir un 0 à la fin de "unmap%u" ? cheeky

Oui. Mais il faut le compter dans ta taille du buffer aussi!

Ou dois-je écrire "unamp%u\0" ?

Non.

PS -> Ca fait bien deux octets un int sur TI ?

Oui.
avatar Mes news pour calculatrices TI: Ti-Gen (fr/en), MobiFiles (de)
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité
- Posté le 12/11/2009 à 15:42 Membre depuis le 18/06/2001, 30136 messages
Merci pour tout. smile
En fait, mon argument "Level" ne peut dépasser 3 caractères, donc ça ira. C'est pour construire un nom de fichier.


Par contre, j'ai un problème qui me gave bien, ça fait patrie des trucs du C qui ressemblent pour moi à une machinerie assez obscure :
J'inclus "genlib.h". Dans la doc de genlib, c'est écrit ça :
And you don’t need to include tigcclib since genlib.h do it for you.

Et apparemment, tigcclib ne connait pas LibsBegin.

Je vais donc pour inclure kernel.h de PreOS, header kernel pour le C. Mais dans le header, je trouve ça :
#if defined(NOSTUB) || defined(KERNEL) || defined(DOORS)
# error "kernel.h" must not be included with tigcclib.h
#endif

Et c'est con, parce que dedans, il y a les définitions des romcalls. sad

Comment faire alors ? PpHd, c'est quoi les règles de l'art en la matière ?
avatar <<< Kernel Extremist©®™ >>>
Saint Qt, priez pour nous.
- Posté le 12/11/2009 à 15:47 Membre depuis le 28/08/2003, 8213 messages
./7 Euh je ne comprends pas pourquoi squalyl te parle de tout ça… #trifus#
Si effectivement tes fonctions s’appellent de façon croisée et non conditionnelle (à l’extérieur d’un if) ton programme ne terminera pas (enfin au moment du stack overflow seulement grin ).
Pour résoudre ça le mieux est de faire des boucles, et le moins mieux est d’utiliser goto.

[edit] : un dernier truc : teste ton code toutes les 10 lignes. Évite d’écrire des pages et des pages sans même voir si ça compile ou sans même tester si la fonctionnalité ajoutée fonctionne comme prévu.
avatar « Quand le dernier arbre sera abattu, la dernière rivière empoisonnée, le dernier poisson capturé, alors vous découvrirez que l'argent ne se mange pas. »
- Posté le 12/11/2009 à 15:50 Membre depuis le 18/06/2001, 30136 messages
Merci pour les tips. Pour ce qui est de la compilation, t'inquiète pas, je suis tellement skillé que je suis obligé de tester à chaque ligne. #trioui#
C'est vrai qu'en assembleur, je peux écrire beaucoup sans relire ou tester, mais là c'est pas la peine. grin
avatar <<< Kernel Extremist©®™ >>>
Saint Qt, priez pour nous.
- Posté le 12/11/2009 à 15:52 Membre depuis le 28/10/2001, 7568 messages
Un "int" fait 2 octets sur TI-68k (sauf si tu actives une option à la con du compilo, auquel cas les fonctions de la famille *printf ne vont plus fonctionner correctement, parce qu'elles supposent qu'un int fait 2 octets grin), mais 4 sur la plupart des plate-formes actuelles. Utiliser "int" n'a pas que des avantages.
Tu peux utiliser "short", "unsigned short", "int16_t" ou "uint16_t" (les deux derniers sont dans le header <stdint.h>, qui est inclus par <inttypes.h>) si tu veux une variable 16 bits (.w), et "long", "unsigned long", "int32_t" ou "uint32_t" si tu veux une variable 32 bits.
avatar Membre de la TI-Chess Team.
Co-mainteneur de GCC4TI (documentation en ligne de GCC4TI), TIEmu et TILP.
Co-admin de TI-Planet.
- Posté le 12/11/2009 à 16:21 Membre depuis le 18/06/2001, 30136 messages
Bon, j'ai résoudru le problème de la pile : main est un scheduler qui appelle la fonction qui va bien :
schedule
void gl_main()
{
while(1)
{
// Schedule tasks
switch( NextTask )
{
case TASK_EXIT:
return;
case TASK_INTRO:
LoadIntro();
break;
case TASK_GAME:
LoadGame();
break;
}
CurTask = NextTask ;
InfiniteLoop();
}
}

Et dans InfiniteLoop(), on fait un return si CurTask a été mis à 0 par la tâche en cours.

C'est bien. smile
Enfin presque, faut que je trouve un moyen de faire passer une valeur d'une fonction à une autre maintenant...
avatar <<< Kernel Extremist©®™ >>>
Saint Qt, priez pour nous.
- Posté le 12/11/2009 à 17:09 Membre depuis le 18/06/2001, 30136 messages
Tiens, j'avais pas vu ce warning, j'en reste #confus#, bien que je fasse sûrement une erreur :
Le proto de sprintf :
short sprintf (char *buffer, const char *format, ...);

Mon code :
	char * Buffer[ 10 ] ;
const char * Filename = "unmap%u" ;

sprintf( Buffer , Filename , Level );

Level est un int. J'ai ce ouarningue :
game.c:17: warning: passing argument 1 of '(<U9e70> = &_ROM_CALL_53)' from incompatible pointer type

Pourquoi ?
avatar <<< Kernel Extremist©®™ >>>
Saint Qt, priez pour nous.
- Posté le 12/11/2009 à 17:17 Membre depuis le 13/06/2002, 39523 messages
Parceque ton buffer, tel que déclaré, est un tableau de pointeurs vers des "char". Ce que sprintf attend c'est juste un tableau de char (donc au choix "char Buffer[10]" ou "char* Buffer" selon que tu veux du statique ou du dynamique).
avatar I invited your best friend the companion cube. Of course, he couldn't come because you murdered him.
------------------------------------------
Mirari² :: It offers what you want, not what you need
3l33t :: Relax, we understand j00 ^^
- Posté le 12/11/2009 à 17:22 Membre depuis le 18/06/2001, 30136 messages
Ah, parce que un tableau est un pointeur, donc "char Buffer[10 ] est un pointeur. Merci ! smile
avatar <<< Kernel Extremist©®™ >>>
Saint Qt, priez pour nous.
- Posté le 12/11/2009 à 17:26 Membre depuis le 28/08/2003, 8213 messages
Disons plutôt que, après la déclaration :
char buffer[10];

On a :
« buffer » est un « char * »
« buffer[n] » est un « char »
avatar « Quand le dernier arbre sera abattu, la dernière rivière empoisonnée, le dernier poisson capturé, alors vous découvrirez que l'argent ne se mange pas. »
- Posté le 12/11/2009 à 17:34 Membre depuis le 18/06/2001, 30136 messages
Ok, merci pour ça. happy
avatar <<< Kernel Extremist©®™ >>>
Saint Qt, priez pour nous.
- Posté le 12/11/2009 à 19:03 Membre depuis le 11/06/2001, 19240 messages
Folco (./16) :
Merci pour tout. smile
En fait, mon argument "Level" ne peut dépasser 3 caractères, donc ça ira. C'est pour construire un nom de fichier.


Par contre, j'ai un problème qui me gave bien, ça fait patrie des trucs du C qui ressemblent pour moi à une machinerie assez obscure :
J'inclus "genlib.h". Dans la doc de genlib, c'est écrit ça :
And you don’t need to include tigcclib since genlib.h do it for you.

Et apparemment, tigcclib ne connait pas LibsBegin.

Je vais donc pour inclure kernel.h de PreOS, header kernel pour le C. Mais dans le header, je trouve ça :
#if defined(NOSTUB) || defined(KERNEL) || defined(DOORS)
# error "kernel.h" must not be included with tigcclib.h
#endif

Et c'est con, parce que dedans, il y a les définitions des romcalls. sad

Comment faire alors ? PpHd, c'est quoi les règles de l'art en la matière ?


#include "kernel.h"
#include "genlib.h"

doit marcher.
- Posté le 12/11/2009 à 19:03 Membre depuis le 11/06/2001, 19240 messages
Folco (./6) :
On s'endort presque à utiliser genlib en C, tout est déjà fait. grin
truc
void gl_main()
{
while( 1 )
{
// Manage non-graphical part
switch( Task )
{
}

// Wait for real screen swapping
glaux_ready();

// Manage graphical part
switch( Task )
{
}

// Wait for synchro
glaux_synchro( 1 );
glaux_swap();
}

}


C'est fait pour!
- Posté le 12/11/2009 à 19:37 - Edité par Folco le 12/11/2009 à 20:23 Membre depuis le 18/06/2001, 30136 messages
Merci ! Mais j'ai fait un testcase minimal qui ressemble à ./27, et j'obtiens ça :
/opt/gcc4ti/lib/tigcc.a: Error: Unresolved reference to `__main'.

C'est vrai que les headers C, c'est compliqué avec cette manière de pouvoir dé-définir des symboles...

En plus, quand je compile avec "-Wa,-l", il me dit
1. Que j'ai encore de l'espace à gagner avec le switch -l de GAS !!
2. Que les ramcalls peuvent pas être relatifs (sans blague) et qu'il les passe en absolu.
avatar <<< Kernel Extremist©®™ >>>
Saint Qt, priez pour nous.
- Posté le 12/11/2009 à 20:15 Membre depuis le 11/06/2001, 19240 messages
Ajoute #define _main __main tout en haut avant le premier include.
- Posté le 12/11/2009 à 20:20 Membre depuis le 18/06/2001, 30136 messages
Miracle, ça marche, bien joué. smile

Pour faire propre, ce #define doit aller où ?

edit -> je veux dire, dans quel header grin
avatar <<< Kernel Extremist©®™ >>>
Saint Qt, priez pour nous.