
                                GLCB
                                ----

             Librairie graphique pour les debutants en 'C'
             ---------------------------------------------


Le repertoire glcbase appartient au domaine public.
Vous pouvez diffuser librement tous les fichiers qui s'y trouvent.
Vous pouvez les utiliser a des fins commerciales ou non sans avoir
a reverser la moindre compensation a leur auteur.
Le but est de voir apparaitre rapidement une collection de programmes
du domaine public completement portables, mais neanmoins puissants
par leur graphisme, son, animation, gestion rapide de souris et clavier.
(Et aussi facile a recompiler!!! Y'en a marre des makefiles monstrueux!)
La seule restriction est que vous ne devez pas modifier les noms des
fonctions ainsi que leur parametres pour ne pas casser la portabilite.
Par contre vous pouvez modifier,ameliorer ou traduire la doc par exemple.
Vous serez aussi amene a optimiser votre module de base prefere...

Si vous faites un soft commercial, SVP faites plusieurs versions.
(les machines non compatibles PC ont du mal a survivre, aidez-les)

Si vous utilisez les modules et qu'ils vous rendent de grand services,
SVP faites l'effort d'ecrire au moins un petit programme domaine public
et faites l'effort ensuite de le placer sur un site accessible.


Introduction:
-------------

Qui n'a jamais reve de pouvoir ecrire rapidement un petit programme en C
avec un peu de graphisme et qui soit quand meme portable ?

Les modules de base ont ete concu dans cette optique. Ils proposent un jeu
d'instructions unique tres general pour faire du graphisme, des sprites,
du son et une bonne gestion de la souris, du clavier et des fichiers.
Il y a egalement des fonctions aleatoires, la gestion de l'horloge systeme,
et un systeme a 2 ecrans: un visible et un invisible qui sert d'ecran de
travail. En echangeant les 2 ecrans au bon moment on garantie une grande
proprete dans les animations graphiques.

Evidement en voulant etre portable on sacrifie les atouts des meilleures
machines... Ici on se contentera de 2 ecrans 320x200 en 16 couleurs et
d'une seule voie pour les sons digitalises. Neanmoins les sons digitalises
sont joues en interruption (vous ne perdez pas la main), les sprites sont
assez rapides, les evenements souris et claviers sont memorises et evitent
les boucles de scrutation, et les modules possedent leur propre fonte.

voici la liste des modules de base:
x11.c		Xwindows pour station vms,unix,etc...
x11local.c	Idem mais strategie d'affichage differente.Voir entete.
mac.c		macintosh
atarilas.c	st,ste,falcon,tt (laser C)
ataripur.c	st,ste,falcon,tt (Pure C)
+ataripu2.s
falcon.c	falcon (Pure C)
+falcon2.s
falcontc.c	falcon (Pure C)
+falcont2.s
amiga500.c	amiga 500/2000 (aztec C)
amiga.c		amiga (tous modeles) (lattice C)
amiga.lha	amiga (tous modeles) (Version amelioree "portable")
pc.c		pc (Windows 3.1 et MultiMedia) (BC++ ou TC++)
pcvga.c		pc (MsDos et carte VGA 256ko) (TC ou TC++)
+pcvga2.asm

Certains modules peuvent apporter un plus par rapport au cahier des
charges commun des modules. C'est le cas du module pcvga.c qui offre
256 couleurs. Neanmoins, vous ne devez reserver l'usage de cette
extension qu'a des cas particuliers: visionneur d'images, soft commercial.
Pour des programmes du domaine public, limitez vous a 16 couleurs! Ne
tombez pas dans le piege qui consiste a croire qu'un soft est bon a cause
du nombre de couleurs! C'est l'interet global qui compte! Et une grande
portabilite apporte un interet tres important. Normalement de nombreux
modules auront bientot cette extension (falcon,amiga20,maclc,x11 etc...).
Dans header.h definissez EXTENSION pour declarer ces fonctions.
Si vous diffusez un programme sous forme de sources, n'utilisez pas
d'extensions, ou alors, utilisez une definition de constante pour permettre
au module classique 16 couleurs de fonctionner avec le programme.

Ces modules peuvent bien sur etre ameliores. L'essentiel est de garder le
meme jeu de fonctions avec les memes noms et les memes parametres. Si votre
machine ne figure pas dans la liste ou si vous ameliorez un des modules,
je serais heureux de le voir rejoindre les autres! (il est difficile d'etre
a la hauteur sur toutes les machines... En particulier, on peut re-ecrire
un module pour un langage C plus recent - norme ANSI - ou corriger un bug)

Les modules de base ne contiennent que les fonctions vraiment vitales qui
dependent de la machine que vous utilisez. Pour avoir des fonctions elaborees,
par exemple, des fonctions de saisie de chaine ou de nombre, il suffit de
faire un module supplementaire (mais qui lui ne depends plus de votre machine
puisqu'il appele les fonctions d'un module de base).

Remarque: Si un pointeur dans votre programme se "deplace" sur un zone plus
large que 64Ko, declarez ce pointeur comme suit (pour nos amis les PC!):
char huge *ptr; (par exemple)
Pour assurer la compatibilite avec les autres machines, dans header.h ecrivez:
#define huge /**/


Description des fonctions des modules de base:
----------------------------------------------

variables globales utiles:
--------------------------

coordonnees instantannees de la souris: mousex et mousey
etat instantanne de ses boutons: mousek
  bit 0: bouton de gauche   bit 1: bouton du milieu
dernieres coordonnees mises a jour par getmouse(): msex et msey
dernier changement d'etat des boutons mis a jour par getmouse(): msek
  bit 0: bouton de gauche   bit 1: bouton du milieu   bit 2: bouton relache
extern int mousex,mousey,mousek;    (mise a jour perpetuelle)
extern int msex,msey,msek;          (mise a jour par getmouse())

etats instantannes des touches: mettre le code ascii en indice
extern char keymap[256]; (mise a jour perpetuelle)

Attention: les mises a jour perpetuelles ne sont garanties sur MAC,X11 et PC
  que si vous faites appel regulierement a getmouse() ou buthit()
  pour la souris, et a kbhit() pour le clavier. (ou keyhit() pour les 2)

tables trigonometriques 14 bits (en 256emes de tour):
-----------------------------------------------------

extern int *sn; (definie entre 0 et 255)
extern int *cs; (definie entre 0 et 255)
extern int *tg; (definie entre -32 et +32)

initialisation du systeme:
--------------------------

A appeler au debut et a la fin de votre fonction main()
extern int initsystem(void);  retourne une valeur non nulle si tout est ok
extern void killsystem(void);


gestion des 16 couleurs (emulation par tramage sur N&B):
--------------------------------------------------------

Definition des couleurs speciales utiles a la construction des sprites:
#define FOND 0x100
#define MASK 0x1ff

par defaut la palette est la suivante (EGA) (mais vous pouvez la redefinir):

(mettez les lignes suivantes dans votre programme pour vous aider)
#define noir         0
#define bleu         1
#define vert         2
#define cyan         3
#define rouge        4
#define violet       5
#define kaki         6
#define gris_clair   7
#define gris         8
#define bleu_violet  9
#define vert_clair   10
#define cyan_clair   11
#define marron       12
#define violet_clair 13
#define jaune        14
#define blanc        15

choix de la couleur courante,verification et modification de la palette:
les 16 couleurs sont des entiers 16 bits avec la structure 0xGRVB,
ou R,V et B sont les composantes rouge,vert,bleu (entre 0 et 15)
et G est le motif noir et blanc correspondant (entre 0 et 8).
(0 est le motif tout noir, 8 est le motif tout blanc)

extern void setcolor(int c);
extern void getpalette(unsigned int *pal);
extern void setpalette(unsigned int *pal);


gestion de palette etendue 256 couleurs (extension pour pcvga,x11,falcon):
--------------------------------------------------------------------------

extern void setbigcolor(int n,unsigned int r,unsigned int v,unsigned int b);
extern void getbigcolor(int n,unsigned int *r,unsigned int *v,unsigned int *b);
extern void setbigpalette(int no,int nb,unsigned int *ptr);
extern void getbigpalette(int no,int nb,unsigned int *ptr);

Ces fonctions permettent de verifier/modifier les couleurs une par une
ou en un seul bloc. Les composantes RVB sont comprises entre 0 et 65535.
Une portion de palette est un tableau d'entier ou les couleurs sont
donc codees sur 3 entiers chacune.
Normalement pour une carte VGA les composantes vont de 0 a 63, mais ces
fonctions assurent la compatibilite future avec les modes 256 couleurs
des systemes Xwindows,falcon,mac LC,mint et amiga 1200.
NE PAS UTILISER CES FONCTIONS POUR UN SOFT DOMAINE PUBLIC (merci)



instructions de gestion des ecrans graphiques:
----------------------------------------------

extern void simplescreen(void); choix d'un seul ecran: fortement deconseille!
extern void doublescreen(void); un ecran visible et un ecran invisible.
  C'est le mode par defaut. Il garantie la proprete des animations
  graphiques: on dessine sur l'ecran de travail invisible, puis on 
  permute les 2 ecrans avec la fonction swap().

extern void cls(void);         efface l'ecran de travail (couleur 0).
extern void copyscreen(void);  copie l'ecran visible dans l'ecran de travail.
extern void refresh(void);     met a jour l'ecran visible (simplescreen).
extern void swap(void);	       permute les 2 ecrans (doublescreen).


instructions graphiques de base:
--------------------------------

Dans la suite, c designe la couleur desiree (de 0 a 15,FOND ou MASK).
Si c = -1 alors la couleur est celle choisie precedement par setcolor
ou bien par une autre instruction graphique.

lx et ly designent la largeur et la hauteur.

extern void pellipse(int x,int y,int lx,int ly,int c); ellipse remplie
extern void pbox(int x,int y,int lx,int ly,int c);     rectangle rempli
extern void plot(int x,int y,int c);                   dessine un pixel
extern void vline(int x,int y,int y2,int c);           ligne verticale
extern void hline(int x,int y,int x2,int c);           ligne horizontale
extern void dline(int x1,int y1,int x2,int y2,int c);  ligne quelconque
extern void rline(int x1,int y1,int x2,int y2,int c);  ligne quelconque fine
extern void dbox(int x,int y,int lx,int ly,int c);     rectangle
extern void polyline(int n,int *tp,int c);             polygone fin
extern void polyfill(int n,int *tp,int c);             polygone rempli
  tp contient les coordonnees des sommets.
 (il faut repeter le 1er sommet a la fin si vous voulez une forme fermee)
  n est le nombre d'entiers contenu dans tp(2 fois le nombre de points (+2)).


instructions d'allocation memoire:
----------------------------------

extern long ramfree(void);        renvoie la taille de la RAM libre en octet.
extern void *memalloc(long size); renvoie un pointeur sur la zone desiree.
  Si l'allocation est impossible la fonction retourne un pointeur nul.
extern void memfree(void **ptr);  libere la zone precedement allouee
  et annule le pointeur.

transferts de blocs memoire:
----------------------------

extern void bmove(void *src,void *dst,long len); copie intelligente d'octets.


instructions de gestion d'horloge:
----------------------------------

extern unsigned long systime(void);    retourne l'horloge en millisecondes.
extern void waitdelay(unsigned int n); attends n milliseconde (max:1mn).

fonctions aleatoires:
---------------------

extern int randint(void);  retourne un entier entre 0 et 32767.
extern int randval(int n); retourne un entier entre 0 et n-1.


gestion des fichiers:
---------------------

La convention adoptee pour les chemin d'acces est la convention unix:
  rep1/rep2/file (separateur "/")
Conseils:
Ne mettez pas de point dans les noms de repertoires.
Limitez les noms de fichiers a 8+3 characteres alphabetiques.
Les chemin d'acces donne le chemin a suivre en partant du niveau ou
  le programme a ete lance. Abstenez vous de partir de la racine.

extern long bsize(char *nom); retourne la taille du fichier en octets.
extern int bexist(char *nom); non nul si le fichier existe.
extern int bsave(char *nom,void *adr,long offset,long len);
  sauve dans un fichier deja cree une partie des donnees (offset,longueur).
extern int bload(char *nom,void *adr,long offset,long len);
  charge une partie du fichier nom (offset,longueur en octets).
extern int bmake(char *nom,void *adr,long len);
  cree ou remplace le fichier nom et sauve les donnees (longueur en octets).

extern int bopen(char *nom);   ouverture en lecture. retourne un handle f.
extern int bread(int f,void *adr,long len);  lit un morceau.
extern int bclose(int f);                    fermeture.
extern int bcreate(char *nom); ouverture en creation. retourne un handle f.
extern int bwrite(int f,void *adr,long len); ecrit un morceau.

La trilogie bopen,bread,bclose permet de lire petit a petit des donnees.
La trilogie bcreate,bwrite,bclose permet d'ecrire petit a petit des donnees.

f est un handle:il permet de specifier le fichier sans redonner son nom.
S'il n'y a pas d'erreur a l'ouverture, f > 0.

Les fonctions bsave,bload,bmake,bread,bwrite,bclose retournent 0 s'il
  n'y a pas d'erreurs.

gestion de la souris et du clavier:
-----------------------------------

extern void hide(void); cache la souris (sauf sur MAC et X11)
extern void show(void); montre la souris (sauf sur MAC et X11)
extern int getmouse(void); retourne l'etat des boutons du dernier evenement
  souris ou 0 s'il ne s'est rien passe. S'il y a eu un evenement les
  variables globales msek,msex,msey,mclk sont mises a jour et donnent les
  indications relatives a cet evenement. (au moins 32 evenements memorises)
  msek: bit 0 bouton de gauche  bit 1: bouton de droite  bit 2: relachement
  sur MAC le bouton de droite est simule par la touche TABULATION.
  sur X11 le bouton de droite est le bouton du milieu.

extern int buthit(void); non nul si on a clicke dernierement avec la souris.
extern char getch(void); attends la pression d'une touche et renvoie son code.
extern int kbhit(void);  non nul si on a presse une touche dernierement.
extern int keyhit(void); non nul si on a clicke ou si on a presse une touche.
extern void confirm(void); attends un click de la souris.
extern void empty(void); oublie tous les evenements souris et clavier passes.

De preference utilisez confirm() et getch() car ces fonctions rendent la main
au serveur (sur X11): attente inactive, vous ne gaspillez pas de temps CPU.

Les touches flechees donnent comme code ascii: '^','<','>' et 'v'.
Sont detectes egalement: Escape (27), Return (13) et Backspace (8).
Sur X11 la touche escape est la touche en haut a gauche du clavier ('~').

gestion de blocs graphiques:
----------------------------

Il y a 2 sortes de blocs graphiques: les blocs rectangulaires et les sprites,
qui sont des blocs a qui on a donne une silhouette quelconque.
Pour utiliser un bloc il suffit de declarer une variable de type (void *)
qui doit etre initialise avec initbloc() et libere avec freebloc().
(Il peut etre utile de declarer un type Bloc avec 'typedef void *Bloc')

extern void initbloc(void **blocptr);            initialise le bloc.

extern void getbloc(void **blocptr,int x,int y,int lx,int ly);
  Une fois le bloc dessine sur l'ecran de travail, il faur le saisir avec
  getbloc(). lx et ly sont la largeur et la hauteur. Pour dessiner le bloc
  utilisez les couleurs de 0 a 15. Si ce bloc est destine a devenir un sprite,
  utilisez la couleur FOND pour les zones transparentes.
  ATTENTION: x et lx doivent toujours etre des multiples de 16!!!

extern void getmask(void **blocptr,int x,int y);
  Une fois le bloc saisie on peut le transformer en sprite en saisissant le
  masque qui lui donnera sa silhouette. Il doit avoir la meme taille que le
  bloc et doit etre dessine avec les couleurs FOND et MASK. La couleur MASK
  permet de dessiner le corps du sprite . Ces 2 couleurs speciales n'ont pas
  a etre utilisees pour dessiner autre chose que des sprites dans l'ecran
  de travail invisible. x doit etre un multiple de 16!!!

extern void copybloc(void **blocptrs,int xs,int ys,int lxs,int lys,
	void **blocptrd,int xd,int yd);   (s:source d:destination)
  copybloc permet de copier une partie d'un bloc dans un autre bloc.
  (les 2 blocs doivent etre de meme type:2 blocs normaux ou 2 sprites)
  ATTENTION:xs,lxs et xd doivent toujours etre des multiples de 16!!!

extern void putbloc(void **blocptr,int x,int y); affiche un bloc (ou sprite).
(au pixel pres, si le sprite depasse en haut ou en bas il sera tronque,
 s'il depasse a droite ou a gauche il ne sera pas affiche du tout)

extern void putpbloc(void **blocptr,int x,int y,int xs,int ys,int lxs,int lys);
  Affiche une partie d'un bloc (ou sprite)
  xs et lxs doivent etre des multiples de 16!!!

extern void freebloc(void **blocptr); liberer le bloc apres usage.


instructions de gestion de fonte:
---------------------------------

La fonte interne est juste la pour vous depanner.

Seuls les codes ascii entre 32 et 95 sont fidelement affiches.
Au dela de 95 (minuscules) on redescends a 64 (majuscules).
Les caracteres 10 et 13 sont pris en compte par printchar() et print().

Ces instructions dessinent des characteres avec la couleur courante.
Sur MAC seul les couleurs qui ont le motif N&B No 8 assurent une vitesse
  d'affichage elevee. Pour faire des animations rapides avec le texte,
  utilisez plutot des blocs graphiques.

extern void affchar(int x,int y,char c); affiche un charactere.
extern void afftext(int x,int y,char *s); affiche une chaine.
extern void printchar(char c); affiche un charactere a la suite des autres.
extern void print(char *s); affiche une chaine a la suite des autres et
  effectue un saut a la ligne.

Avec printchar() et print(), un affichage tout en bas de l'ecran genere
  un scrolling vertical.


gestion des samples (echantillons sonores):
-------------------------------------------

Les samples sont constitues d'une suite d'octets qui decrivent la forme
de l'onde sonore. Nous adopterons la convention suivante:
  255  -> niveau maximum
  128  -> niveau de repos (silence)
   0   -> niveau minimum

extern void fixsample(void *adr,long len);
  Cette convention n'etant pas applicable sur toutes les machines, avant
  de jouer un sample avec playsample(), vous devez appeler fixsample() en
  lui donnant l'adresse et la longueur du sample. Cela aura pour effet
  de preparez le sample a la convention attendue par votre machine.

extern void playsample(void *adr,long len,long freq);
  Joue le sample en interruption (vous gardez la main).
  Si un sample etait deja en cours, il est remplace par ce nouveau sample.

extern void stopsample(void); arrete un eventuel sample en cours d'execution.

Conclusion:
-----------

Cette doc est volontairement courte. C'est plutot un index pour vous
depanner rapidement. N'hesitez pas a re-ecrire, ou traduire tout ou partie
de cette doc. Le plus important est de bien comprendre exemple.c.

Le developpement des ces modules a pris enormement de temps.
Mais je pense que ca valait le coup, vu le service qu'ils rendent a 
un debutant qui n'a pas envie de se prendre la tete avec un systeme
d'exploitation moderne, certe complet, mais inutilement complique pour
l'usage qu'il doit en faire.

Il n'y aura pas de nouvelles versions de GLCbase. Ceci assure une grande
stabilite pour la librairie proposee. Et en fait, nos etudes terminees,
nous n'auront plus le temps libre necessaire pour ameliorer le concept.
Il est temps de faire des programmes!


L'equipe GLCB:
--------------

ROY Gilles		Supelec (94)	(kakanoid)
BOERI franck		Supelec (95)	(blockout)
JOUIN Christophe	Supelec (94)	(x11,amiga)
ROY Regis		Supelec (95)	(atari)
LAMONOCA Guillaume	Supelec (94)

Pour tout renseignement:

Guillaume LAMONOCA
7 allee lucien Mazan
13500 Martigues
FRANCE

(bal GL sur plusieurs messageries minitel)

