Obligement - L'Amiga au maximum

Vendredi 02 mai 2025 - 00:48  

Translate

En De Nl Nl
Es Pt It Nl


Rubriques

Actualité (récente)
Actualité (archive)
Comparatifs
Dossiers
Entrevues
Matériel (tests)
Matériel (bidouilles)
Points de vue
En pratique
Programmation
Reportages
Quizz
Tests de jeux
Tests de logiciels
Tests de compilations
Trucs et astuces
Articles divers

Articles in English


Réseaux sociaux

Suivez-nous sur X




Liste des jeux Amiga

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z,
ALL


Trucs et astuces

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Glossaire

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Galeries

Menu des galeries

BD d'Amiga Spécial
Caricatures Dudai
Caricatures Jet d'ail
Diagrammes de Jay Miner
Images insolites
Fin de jeux (de A à E)
Fin de Jeux (de F à O)
Fin de jeux (de P à Z)
Galerie de Mike Dafunk
Logos d'Obligement
Pubs pour matériels
Systèmes d'exploitation
Trombinoscope Alchimie 7
Vidéos


Téléchargement

Documents
Jeux
Logiciels
Magazines
Divers


Liens

Associations
Jeux
Logiciels
Matériel
Magazines et médias
Pages personnelles
Réparateurs
Revendeurs
Scène démo
Sites de téléchargement
Divers


Partenaires

Annuaire Amiga

Amedia Computer

Relec


A Propos

A propos d'Obligement

A Propos


Contact

David Brunet

Courriel

 


Programmation : C - Mémoire tampon en tant que mémoire principale et ChipMemFirst
(Article écrit par Philippe Vautrin et extrait d'Amiga News Tech - novembre 1991)


Pour illustrer nos nouvelles connaissances sur la gestion de la mémoire par Exec, je vous propose deux petits programmes C pour le prix d'un seul.

Mémoire Tampon

Le premier programme commence par réserver un tampon mémoire de 16 ko et lui attribue un MemHeader particulier. Ainsi, on peut user de ce tampon mémoire exactement comme s'il s'agissait de la mémoire principale de l'ordinateur, à ceci près que seules les fonctions Allocate() et Deallocate() sont utilisables. Ce programme est interactif, c'est-à-dire que c'est vous qui décidez des opérations à suivre (allocation ou libération d'un bloc quelconque). Le programme affiche à chaque fois l'état du MemHeader, les différents MemChunks qui peuvent résulter de la fragmentation du tampon mémoire, ainsi que l'adresse et la taille des différents blocs alloués.

L'utilisation en est très simple, bien qu'entièrement au clavier. Vous entrez une lettre de commande suivi d'un nombre x. La lettre peut être A, ce qui demande d'allouer x octets dans le tampon mémoire, ou bien L, ce qui demander de libérer le bloc numéro x, ou enfin Q, ce qui met fin au programme. Faites attention à ne bien entrer que des nombres décimaux, aucune vérification particulière n'étant faite à ce niveau.

Makefile

EXE=Memory
SRC=Memory.c
OBJ=Memory.o
ARG=-b1 -cfist -v -y
LIB=LIB:lc.lib LIB:amiga.lib
LNK=SC SD NOICONS ADDSYM

Memory:   $(OBJ)
          BLink LIB:c.o $(OBJ) TO $(EXE) LIB $(LIB) $(LNK)

Memory.o: $(SRC)
          Lc $(ARG) $(SRC)

Listing

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <exec/types.h>
#include <exec/memory.h>

#ifdef LATTICE
#include <proto/exec.h>
#endif

#define IsDigit(c) ((c) >= '0' && (c) <= '9')

#define BLOCSIZE 0x4000

UBYTE help[]="\fAn=Allouer n octets, "
             "Lx=Libérer bloc n°x, "
             "Q=Quitter\n";

void main(void);
void mem_demo(struct MemHeader *mh);

void main(void)
{
struct MemHeader *mh;
struct MemChunk *mc;

  if (mh = (struct MemHeader *)AllocMem(sizeof(*mh), MEMF_CLEAR))
  { if (mc = (struct MemChunk *)AllocMem(BLOCSIZE, 0))
    { mh->mh_Node.ln_Type = NT_MEMORY;
      mh->mh_Node.ln_Name = "MemDemo.chunck";
      mh->mh_First        = mc;
      mh->mh_Lower        = (APTR)mc;
      mh->mh_Upper        = (APTR)((ULONG)mc + BLOCSIZE);
      mh->mh_Free         = BLOCSIZE;

      mc->mc_Next         = NULL;
      mc->mc_Bytes        = BLOCSIZE;

      mem_demo(mh);

      FreeMem((APTR)mc, BLOCSIZE);
    }
    FreeMem((APTR)mh, sizeof(*mh));
  }
  exit(0);
}

void mem_demo(struct MemHeader *mh)
{
UBYTE cmd[128], c, *ptr, *adr;
ULONG blocs[32], tailles[32], taille;
SHORT bloc, nb_blocs = 0, i;
BOOL fini = FALSE;
struct MemChunk *mc;

  for (i = 0; i < 32; i++)
    blocs[i] = tailles[i] = -1L;

  while (!fini)
  { puts(help);

    printf("MemHeader :");
    printf(" Lower=$%08lx, Upper=$%08lx, Free=$%08lx\n\n",
             mh->mh_Lower,   mh->mh_Upper,   mh->mh_Free);

	for (i = 0, mc = mh->mh_First; mc; mc = mc->mc_Next)
      printf("MemChunk %2d, Next=$%08lx, Bytes=$%08lx\n",
                       i++, mc->mc_Next, mc->mc_Bytes);

	printf("\n");
    for (i = 0; i < nb_blocs; i++)
      printf("Bloc %2d, adresse: $%08lx, taille: $%08lx\n",
              i,        blocs[i],        tailles[i]);

    printf("\n[An|Lx|Q] > ");
    gets(ptr = cmd);

    while (c = *ptr++)
    { switch (c | 0x20)
      { case 'q':  /* Quitter */
          fini = TRUE;
        break;

        case 'a':  /* Allouer */
          c = *ptr++;
          while (!IsDigit(c)) c = *ptr++;
          taille = c - '0';

          c = *ptr++;
          while (IsDigit(c))
          { taille = (taille * 10) + (c - '0');
            c = *ptr++;
          }
          *ptr = '\0';

          if (nb_blocs < 32)
          { if (taille)
            { adr = Allocate(mh, taille);
              if (adr)
              { printf("Allocation de  %ld octets\n", taille);
                blocs[nb_blocs]   = (ULONG)adr;
                tailles[nb_blocs] = taille;
                nb_blocs++;
              }
              else puts("L'allocation a échoué !");
            }
            else puts("Taille incorrecte.");
          }
          else puts("Nombre maximum de bloc atteint.");
        break;

        case 'l':  /* Libérer */
        case 'f':
          c = *ptr++;
          while (!IsDigit(c)) c = *ptr++;
          bloc = c - '0';

          c = *ptr++;
          while (IsDigit(c))
          { bloc = (bloc * 10) + (c - '0');
            c = *ptr++;
          }
          *ptr = '\0';

          if (bloc < nb_blocs)
          { if (blocs[bloc] != -1L)
            { printf("Libération du bloc n°%ld\n\n", bloc);
              Deallocate(mh, (APTR)blocs[bloc], tailles[bloc]);
              for (i = bloc; i < 32; i++)
              { blocs[i]   = blocs[i+1];
                tailles[i] = tailles[i+1];
              }
              --nb_blocs;
            }
            else puts("Bloc non réservé.");
          }
          else puts("Numéro de bloc invalide.");
        break;
      }
    }
  }
}

ChipMemFirst

Ce tout petit programme est un petit truc pour vous permettre de modifier la priorité d'allocation de la mémoire Chip. Il se contente de changer la priorité de la liste Chip dans la structure ExecBase. Ainsi, et sous réserve qu'il y en ait suffisamment, ce sera en priorité de la mémoire Chip qu'AllocMem() et consoeurs alloueront. Cela peut être utile par exemple pour charger une ancienne démo qui refuse de tourner correctement avec une extension de mémoire.

Par défaut, la nouvelle priorité est de 10, ce qui devrait être amplement suffisant dans la plupart des cas (Exec l'initialise à -10, la mémoire Fast étant à 0). Mais il peut arriver que certaines extensions, notamment 32 bits sur les cartes 68030, aient des priorités supérieures. C'est pourquoi il est possible de préciser en paramètre sur la ligne de commande, la nouvelle priorité à appliquer à la mémoire Chip.

Makefile

EXE=ChipMemFirst
SRC=ChipMemFirst.c
OBJ=ChipMemFirst.o
ARG=-b1 -cfist -v -y
LIB=LIB:lc.lib LIB:amiga.lib
LNK=SC SD NOICONS NODEBUG

ChipMemFirst:   $(OBJ)
          BLink LIB:c.o $(OBJ) TO $(EXE) LIB $(LIB) $(LNK)

ChipMemFirst.o: $(SRC)
          Lc $(ARG) $(SRC)

Listing

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <exec/types.h>
#include <exec/memory.h>
#include <exec/execbase.h>

#ifdef LATTICE
#include <proto/exec.h>
#endif

extern struct ExecBase *SysBase;

void main(int argc, char **argv)
{
int newpri = 25;
struct MemHeader *mh;

	if (argc > 1)
		newpri = atoi(argv[1]);

	Disable();
	if (mh = FindName(&SysBase->MemList, "Chip Memory"))
	{	Remove((struct Node *)mh);
		mh->mh_Node.ln_Pri = newpri;
		Enqueue(&SysBase->MemList, (struct Node *)mh);
	}
	Enable();
}

Mise à jour de mai 2025 : une archive contenant le listing adapté à vbcc, et avec l'exécutable compilé par vbcc, a été réalisée par Yann-Gaël Guéhéneuc et est disponible sur obligement.free.fr/files/antbufferandchipmemory.lha.



[Retour en haut] / [Retour aux articles]