DC @MINIFONTE 812CF % adresse de la minifonte

SAVE

%-----------------------------------------------------------------------------%
% Récupération de l'adresse de la chaîne et vérification des arguments        %
%-----------------------------------------------------------------------------%
% En sortie :                                                                 %
% R1a = adresse de la chaîne                                                  %
% D1 pointe sur le prologue de la chaîne                                      %
%-----------------------------------------------------------------------------%

C=DAT1.A ?C#0.A {
  % erreur "pas assez d'arguments"
  LOAD
  LC 00201
  GOVLNG 266C6
}
D1=C R1=C.A % R1a contient l'adresse de la chaîne
A=DAT1.A LC 02A2C
?C=A.A {
  % erreur "bad argument type"
  LOAD
  LC 00202
  GOVLNG 266C6
}


%-----------------------------------------------------------------------------%
% Calcul de la taille du GROB                                                 %
%-----------------------------------------------------------------------------%
% Utilisation des registres :                                                 %
% Aa = nombre de caractères lus sur la ligne courrante                        %
% Ba = nombre de caractères de la plus grande ligne trouvée                   %
% Cw = caractères lus                                                         %
% Dw est utilisé pour faciliter les tests de retour chariots                  %
% D0 = nombre de lignes (utiliser D0 comme compteur, c'est pas banal !)       %
% D1 pointe sur les caractères à lire                                         %
% R2a = longueur de la chaîne (nombre de caractères*2)                        %
%-----------------------------------------------------------------------------%

% Initialisation
LC 0A0A0A0A0A0A0A0A D=C.W % 0A = retour chariot
D1+5 C=DAT1.A C-5.A R2=C.A % lecture de la taille de la chaîne
D1+5
A=0.A B=0.A
D0=A D0+1 % au moins une ligne !

% 1ère étape : puisque le nombre de caractères n'est pas nécessairement un
% multiple de 8, il faut traiter quelques caractères différement... on utilise
% pour cela le champ WP
P=C.0
?P=0 { % pas besoin de faire la première étape si P=0 !
  P-1 C=DAT1.WP     % récupération des caractères à lire
  CD1EX C+P+1 CD1EX % on les saute...
  {
    ?C=0.P -> .QUARTET_0 % si le 1er quartet du caractère est 0.
    % pas un retour à la ligne
    A+1.A
    P-1 P-1 UPNC
    EXIT
  
    *.QUATET_0
    % le premier quartet du caractère est un 0
    P-1 % on regarde le second quartet
    ?C=D.P -> .NEWLINE % si le deuxième quartet est un A
    % pas un retour à la ligne
    A+1.A
    P-1 UPNC
    EXIT
  
    *.NEWLINE
    % le caractère est un retour à la ligne
    D0+1
    ?A<=B.A { B=A.A }
    A=0.A
    P-1 UPNC
  }
  P=0
}

% 2ème étape : ce coup-ci on utilise un champ W !
C=R2.A CSR.A
C-1.A SKIPC
{
  RSTK=C % sauvegarde du compteur de boucle dans la RSTK
  C=DAT1.16 D1+16 
  % cette boucle est semblable à la première, mais P est incrémenté au lieu
  % d'être décrementé, ca évite de le remettre à 0
  {
    ?C=D.P -> .QUARET_A
    A+1.A
    P+1 P+1 UPNC
    EXIT
  
    *.QUARET_A
    P+1
    ?C=0.P -> .NEWLINE2
    A+1.A
    P+1 UPNC
    EXIT
  
    *.NEWLINE2
    D0+1
    ?A<=B.A { B=A.A }
    A=0.A
    P+1 UPNC
  }
  C=RSTK
  C-1.A UPNC
}

% ne pas oublier que la dernière ligne peut être plus grande que les autres !
?A<=B.A { B=A.A }

% Pour la troisième étape : on écrit un retour chariot supplémentaire après
% la chaine, en sauvegardant dans RSTK la valeur écrasée
C=DAT1.B RSTK=C LC 0A DAT1=C.B


%-----------------------------------------------------------------------------%
% Reservation du GROB                                                         %
%-----------------------------------------------------------------------------%
% En sortie :                                                                 %
% D0 pointe sur le premier caractère de la chaîne                             %
% R0a = adresse du GROB                                                       %
% R1a = adresse de la chaîne                                                  %
% R2a = taille de la chaîne (nombre de caractères * 2)                        %
% R3a = hauteur du GROB en pixels                                             %
% R4a = largeur du GROB en quartets                                           %
%-----------------------------------------------------------------------------%

CD0EX C+C.A D=C.A C+C.A C+D.A R3=C.A % R3a = nombre de lignes * 6
D=C.A C=0.A
A=B.A R4=A.A % R4a = taille en caractères de la plus grande  ligne
?ABIT=0.0 { A+1.A } % la taille d'une ligne d'un GROB doit être multiple de 8
% simple multiplication de Aa par Da, resultat dans Ca
{
  D+D.A ASRB.A
  ?ABIT=0.0 { C+D.A }
  ?A#0.A UP
}
C+10.A % taille pour stoquer la largeur et la hauteur du GROB
RES.STR % reservation
D0-10 LC 02B1E DAT0=C.A % écriture du prologue d'un GROB
D0+10
C=R3.A DAT0=C.A % écriture de la hauteur du GROB
D0+5
C=R4.A
A=C.A ?ABIT=0.0 { A+1.B } R4=A.A % R4a = nombre de quartets par ligne
C+C.A C+C.A DAT0=C.A % écriture de la largeur du GROB
D0+5


%-----------------------------------------------------------------------------%
% Ecriture des caractères dans le GROB avec la minifonte                      %
%-----------------------------------------------------------------------------%
% utilisation des registres pour la boucle sur les lignes :                   %
% Da = adresse de la minifonte                                                %
% D1 pointe sur les caractères de la chaîne                                   %
% R3a (hauteur du GROB) est utilisé comme compteur                            %
% RSTK = D0 = adresse du premier quartet de la ligne en cours dans le GROB    %
%-----------------------------------------------------------------------------%

% Initilisation
CD0EX D0=C RSTK=C
C=R1.A D1=C D1+10
LC(5)@MINIFONTE D=C.A

% Boucle sur les lignes
{
  C=R3.A C-6.A
  SKIPNC { EXIT2 }
  R3=C.A
  % Boucle sur les caractères d'une ligne
  {
    % lecture de deux caractères
    A=DAT1.A D1+4
    LC 0A ?C#A.B {
      % Si le premier des deux caractères est un retour chariot
      D1-2
      GOTO .FIN_LIGNE
    }
    % Ca = adresse de la bitmap du premier caractère dans la fonte
    C=0.A C=A.B
    B=C.A C+C.A
    C+B.A C+C.A C+D.A
    % Sauvegarde de D0 dans la RSTK, et D0 pointe sur la bitmap du premier
    % caractère
    CD0EX RSTK=C
    % On passe au second caractère
    ASR.A ASR.X
    % Si le second caractère est un retour chariot
    LC 0A ?C#A.B { GOTO .ECRIRE_UN_CHAR }

    % Aa = adresse du second caractère dans la fonte
    C=0.A C=A.B
    C+C.A A=C.A
    C+C.A A+C.A
    C=D.A A+C.A
    % On échange le contenu de Da (adresse minifonte) et R4a (taille ligne)
    CR4EX.A D=C.A
    % Lecture de la bitmap du premier caractère
    C=DAT0.6
    % Lecture de la bitmap du second caractère, décalée d'un quartet
    A-1.A D0=A A=DAT0.7
    % Ecriture des deux carcatères à la fois, pour les six lignes
    A=C.P % on réunit les deux bitmaps de la première ligne
    P=6
    CSR.WP B=C.A % on fout la bitmap du premier caractère dans Ba
    C=RSTK D0=C % on récupère D0
    DAT0=A.B % et on écrit
    C+D.A D0=C % on passe à la ligne suivante
    ASR.WP % on décale la bitmap du second caractère
    P=0
    A=B.P DAT0=A.B % etc...
    C+D.A D0=C
    ASR.W BSR.A
    A=B.P DAT0=A.B
    C+D.A D0=C
    ASR.A BSR.A
    A=B.P DAT0=A.B
    C+D.A D0=C
    ASR.A BSR.A
    A=B.P DAT0=A.B
    C+D.A D0=C
    ASR A BSR.B
    A=B.P DAT0=A.B
    % On reéchange le contenu de Da et de R4a
    CDEX.A A=C.A
    CR4EX.A CDEX.A
    % On retourne sur la première ligne des caractères écrits dans le GROB
    C-A.A
    A+A.A A+A.A C-A.A
    D0=C
    D0+2 % on passe aux caractères suivants
    UP

    *.ECRIRE_UN_CHAR
    % La même chose qu'avant mais ici on n'écrit qu'un caractère au lieu de 2
    D0-1 A=DAT0.7 % lecture de la bitmap du caractère
    ASR.B
    C=D.A CR4EX.A D=C.A % echange de Da et R4a
    C=RSTK D0=C % recuperation de D0
    DAT0=A.B
    P=6 ASR.W ASR.W
    B=A.A % on fout la bitmap dans Ba
    P=1 A=0.P P=0 % on en profite pour mettre A1 à 0
    C+D.A D0=C
    DAT0=A.B % on fait quand même des écritures sur un champ B pour unifomiser
    BSR.A A=B.P % etc...
    C+D.A D0=C
    DAT0=A.B
    BSR.A A=B.P
    C+D.A D0=C
    DAT0=A.B
    BSR.A A=B.P
    C+D.A D0=C
    DAT0=A.B
    BSR.B A=B.P
    C+D.A D0=C
    DAT0=A.B
    CDEX.A A=C.A
    CR4EX.A CDEX.A
    C-A.A
    A+A.A A+A.A C-A.A
    D0=C D0+2
   
    *.FIN_LIGNE
    C=RSTK RSTK=C % on récupère l'adresse du début de la ligne dans le GROB
    AD0EX D0=A % et l'adressee du début du char dans le GROB
    ACEX.A RSTK=C % qu'on sauve dans la RSTK
    C-A.A % calcule le nombre de quartets déjà écrits dans la ligne
    A=R4.A C=A-C.A % nombre de quartets restant à écrire dans la ligne
    C-1.A SKIPC {
      P=15 LC 5 % compteur de lignes dans Cs
      P=C.0 % on va écrire par bloc de 16 quartets, plus le modulo 16
      A=0.W % va servir pour écrire du blanc
      CSR.A
      B=C.A % on sauvegarde dans Ba
      {
        % écriture par bloc de 16 quartets
        C-1.A SKIPC
        {
          DAT0=A.16 D0+16
          C-1.A UPNC
        }
        DAT0=A.WP % écriture des quartets restants
        % passe à la ligne suivante
        A=R4.A
        C=RSTK C+A.A RSTK=C
        D0=C
        % on a utilisé Aa, il faut le remettre à 0
        A=0.A
        C=B.A
        C-1.S UPNC
      }
      P=0
    }
    % il faut enlever ce qu'on avait mis dans la RSTK
    C=RSTK
  }
 
  % On passe à la ligne de texte suivante
  C=RSTK
  A=R4.A
  A+A.A C+A.A A+A.A C+A.A
  D0=C RSTK=C
  UP
}

% on enleve ce qu'on avait mis dans la RSTK
C=RSTK
% on restaure l'octet après la chaîne qu'on avait écrasé pour mettre un
% retour chariot
D1-2 C=RSTK DAT1=C.B

% et on quitte en posant le GROB sur la pile...
LOAD
A=R0.A
GOVLNG 03A86

@