Blog

  • CEO-MAG 350

    Sommaire :

    • 2 LA VISU DE L’ÉTÉ
    • 4 REVUE DES BELLES LETTRES
    • 6 COLLECTION HIRES
    • 7 PUBLICITÉ
    • 8 FONCTIONNEMENT DE LA PILE MATÉRIELLE DU 6502 (4)
    • 13 QUELQUES BLAGUES
    • 14 MECCANO – MAN

    Edito

    C’est l’été, les vacances approchent ou ont commencé pour certains. Les différents articles du mois devraient permettre à chacun de passer de bonnes vacances ( Nous sommes à la moitié de la saga proposée par Yann ; et nul doute que les programmeurs en herbe pourront déjà utiliser toutes les techniques détaillées autour de la pile du 6502. Pour la sieste, les 12 disquettes d’écran hires compiliées par André permettront de somnoler devant les plus beaux écrins Oric. Enfin (et je ne l’avais pas dans mes tap en stock), vous pourrez pour le dessert analyser les 3 pages de listings de Meccano scannées par Steve. A noter que le jeu (en tout cas le tap) n’est pas 100% compatible avec l’Atmos ; du fait de la fonction PLOT. A privilégier sur une config Oric1. Bonnes vacances. Didier

    [wpdm_package id=’2628′]

    [wpdm_package id=’2629′]

    [wpdm_package id=’2660′]

  • Fonctionnement de la pile matérielle du 6502 (4/8)

    PARAMÈTRES ET SOUS-ROUTINES

    L’entrée et la sortie de données nécessaires au fonctionnement d’une sous-routine, peut se dérouler de quatre façons :

    1. En passant par les registres (A, X et / ou Y). C’est la meilleure méthode et la plus performante lorsqu’il s’agit de données constituées d’un ou deux octets
    2. En passant par des variables en RAM. Cette méthode est parfaite pour des données qui doivent rester en RAM et qui doivent servir à d’autres routines. Elle est souvent utilisée de manière conjointe à la première méthode.
    3. Les besoins en entrées de la sous-routine peuvent être intégrés au programme lui-même, juste après l’instruction JSR (comme par exemple une chaîne alphanumérique à afficher). Dans ce cas, la sous-routine utilise l’adresse de retour stockée sur la pile en guise d’adresse de début des données. Elle peut aussi utiliser un octet qui détermine le nombre de données ou un délimiteur afin de savoir de combien d’octets avancer l’adresse de retour avant d’exécuter l’instruction RTS (et d’éviter que le processeur ne traite les données comme une instruction).
    4. En passant par la pile matériel.
      • Pile en page 1 : le programme appelant empile la (ou les) données grâce à PHA, puis récupère le (ou les) résultats grâce à PLA, au retour de la sous-routine.
      • Pile virtuelle en page 0 : Idem précédemment, avec une pile de données différentes de la pile matérielle, ce qui peut faciliter certaines opérations sur la pile et l’adressage indirect. Par exemple, la pile de données peut être utilisée dans un processus en plusieurs étapes pour calculer une adresse, adresse qui à son tour peut être utilisée pour un accès indirect à un octet dans un tableau pour faire un calcul ou une opération logique.
      • Pile en RAM : Idem pile virtuelle en page 0, mais pouvant typiquement servir pour des nombres en virgule flottante autres que des adresses nécessitant les modes d’adressage disponibles en page 0.

    Examinons un exemple dans lequel il s’agit d’utiliser la pile matériel pour une donnée d’entrée. Dans cet exemple, notre sous-routine transforme un demi-octet hexadécimal en octet ASCII, avec un octet en entrée et un octet en sortie, le tout stocké sur la pile matériel.

    <do_stuff>      ; Get the nybble into A.  Allowable value is 0-F.
    PHA             ; Other code can be put between the PHA and the PLA, as long
    JSR  NYB2ASCII ; as it doesn't care if NYB2ASCII overwrites A and X. The
    PLA             ; subroutine's input and output are protected on the stack though.
    <do_stuff>      ; Do something with the ASCII output, like add it to a string, display it, etc..

    La sous-routine NYB2ASCII pourrait ressembler à ceci.

    NYB2ASCII:

    TSX

    LDA  $103,X     ; 103 reaches past the return address, to the input parameter.

    CMP  #$0A       ; Anything below $0A will end up in the $30’s.

    CLC             ; CLC before the BMI so we only have to do it once.

    BMI  n2a1       ; For 9 or less, skip the next instruction.

    ADC  #7         ; $0A becomes $11, $0B becomes $12, etc..  C is still clear.

     n2a1:  ADC  #$30       ; Whether the 7 got added above or not, this gives the ASCII.

    STA  $103,X     ; Put it on the stack, overwriting the input value.  Note

    RTS             ; that we read and overwrote the byte just behind the

    ; return address, leaving the return address undisturbed.

    Voici un autre exemple dans lequel deux nombres de 16 bits non signés en entrée sur la pile, sont multipliés pour donner un nombre de 32 bits non signé, en sortie sur la pile.

    On empile tout d’abord les deux nombres à transformer, chacun avec le poids fort en premier, de sorte que le poids fort prenne l’adresse la plus haute comme dans le fonctionnement habituel du 6502.

    <do_stuff>     ; Get high byte of first input,

    PHA            ; and push it.

    <do_stuff>     ; Get low  byte of first input,

    PHA            ; and push it.

    <do_stuff>     ; Get high byte of second input,

    PHA            ; and push it.

    <do_stuff>     ; Get low byte of second input,

    PHA            ; and push it.

    JSR  UM_STAR   ; Now you can call the subroutine below that does the multiplying.

                   ; If you pull the product off the stack now, the byte order will be:

    PLA            ; 2nd-highest byte

    <do_stuff>

    PLA            ; high byte

    <do_stuff>

    PLA            ; low byte

    <do_stuff>

    PLA            ; 2nd lowest byte

    <do_stuff>

    Selon les opérations que vous souhaitez réaliser ensuite, vous pouvez très bien laisser le premier résultat sur la pile.

    Si l’opération après la multiplication des deux nombres est de calculer la racine carrée pour en obtenir la raison géométrique, alors il convient de ne pas toucher à la pile tant que cette seconde opération n’est pas effectuée (la raison géométrique équivaut à une moyenne logarithmique. La raison géométrique de 1 et 100 est de 10, et non de 50,5).

    Pour accéder aux données stockées sur la pile sans les dépiler et dans l’ordre de votre préférence, vous pouvez continuer d’utiliser X comme index de pile (ainsi que décrit dans l’exemple UM_STAR ci-dessous). En cas de TSX, vous devrez ajuster l’index en tenant compte du fait que l’adresse de retour n’est plus sur la pile, et comme décrit ci-après, qu’un PLA a déplacé les résultats sur la pile de $101,X à $104,X. Par contre, sans TSX l’index est toujours valide et pointe bien sur les bonnes données.

    UM_STAR: LDA #0                 ; Unsigned, mixed-precision (16-bit by 16-bit input, 32-bit output)

             PHA                    ; multiply.  Add a variable byte to the stack, initializing it as 0.

             TSX                    ; Now 101,X holds that new variable, $102,X and $103,X hold the return address

             LSR $107,X             ;and $104,X to $107,X holds the inputs and later the outputs.

             ROR $106,X

             FOR_Y  16, DOWN_TO, 0  ; Loop 16x.  The DEY, BNE in NEXT_Y below will drop through on 0.

                 IF_CARRY_SET

                     CLC

                     PHA            ; Note that the PHA (and PLA below) doesn’t affect the indexing.

                        LDA $101,X

                        ADC $104,X

                        STA $101,X

                     PLA

                     ADC $105,X

                 END_IF

                 ROR

                 ROR $101,X

                 ROR $107,X

                 ROR $106,X

             NEXT_Y

             STA $105,X

             PLA                    ; Retrieve the variable byte we added at the top, cleaning up the stack.

             STA $104,X             ; Again note that the PLA changed S but not X, so the $104 is still $104.

             RTS

    Note : Dans de nombreux cas, il serait plus judicieux de nommer les données présentes sur la pile, en utilisant la macro EQU, plutôt que de se contenter de $101,X ou équivalent.

    Supposons maintenant que vous ayez besoin d’une sous-routine avec quatre octets en entrée et six octets en sortie.

    Afin de servir de la pile matérielle pour deux données supplémentaires en sortie, il faut donc résoudre le problème de l’adresse de retour qui ne sera pas en haut de la pile lors du RTS.

    La meilleure méthode consiste à faire de la place sur la pile avant d’appeler la sous-routine :

    PHA              ; Push two dummy bytes onto the stack to hold the

    PHA              ; positions open for outputs of the subroutine called below.

    <do_stuff>       ; Prepare the subroutine input bytes to be passed.

    JSR  subroutine  ; Without changing the stack pointer, the subroutine

    ; can now give you two more bytes of output than input.

    Autre cas pratique, celui où vous auriez besoin de plus de données en entrées qu’en sortie.

    Dans ce cas, il suffit de dépiler les données inutiles après être sorti de la sous-routine.

    Ainsi, pour restaurer la hauteur de pile, faites :

    <do_stuff>        ; Set up inputs, reserve output byte places in stack, etc..

    TSX               ; Mark the current stack position.

    <do_more_stuff>

    JSR  <subroutine>

    <do_stuff>        ; Handle outputs, etc..

    TXS               ; Restore stack to the marker set earlier, possibly also

    ; to put certain outputs at the top.

    Évidemment le registre X ne devra pas être modifié par la sous-routine, ou alors il faudra le sauvegarder à son tour sur la pile.

    Comme décrit précédemment, la pile matériel n’est pas la seule solution en tant que pile de stockage. Une pile en page zéro (ZP) présente par exemple l’avantage de disposer de modes d’adressages supplémentaires.

    Utiliser une autre pile que la pile matériel permet aussi de résoudre le problème suivant : admettons que la pile matériel en page 1 serve pour passer des paramètres à une sous-routine qui elle-même doit fournir des paramètres à autre sous-routine. Lors de l’entrée dans la seconde sous-routine, l’adresse de retour se retrouve donc désormais au sommet de la pile, tandis que les données d’entrée sont décalées vers le bas, ce qui donnera à coup sûr des résultats erronés.

    Mettons en œuvre cet exemple avec la sous-routine GEOMEAN.

    GEOMEAN: JSR  UM_STAR  ; Multiply two 16-bit unsigned inputs on the stack.  Get 32-bit product.

             JSR  SQRT     ; Take a 32-bit input on the stack and get a 16-bit output, leaving two

             RTS           ; dummy bytes on stack (problem: GEOMEAN’s return addr is still on top!)

    Supposons que vous commenciez par empiler $1234 sur la pile matériel (poids fort en premier, sur le dessus de la pile), puis que vous empiliez $5678 avant d’appeler la sous-routine GEOMEAN.

    Lorsque le pointeur de programme attend la première instruction après PHA et TSX dans le programme UM_STAR, UM_STAR part à la recherche du premier nombre à multiplier ($1234 dans notre exemple), censé se trouver aux adresses $106,X et $107,X, puis du second nombre ($5678 dans l’exemple) qui se trouve aux adresses $104,X et $105,X. L’adresse de retour se trouve quant à elle indexée par $102,X et $103,X.

    Il y a cependant maintenant deux adresses de retour au sommet de la pile : celle qui a fait appel à UM_STAR et celle qui a fait appel à GEOMEAN. UM_STAR va donc ignorer $1234 et multiplier $5678 avec l’adresse de retour de GEOMEAN, entraînant ainsi un résultat erroné et l’écrasement de l’adresse de retour de GEOMEAN. C’est le plantage assuré !

    Vous vous apercevez également que le fait d’utiliser JMP au lieu de la paire d’instruction JSR / RTS peut entraîner des problèmes d’incompatibilité liés à une mauvaise gestion des données empilées sur la pile matériel.

    La pile en page zéro permet de contourner ce genre de problème, tout simplement parce que l’adresse de retour n’est pas empilée sur cette dernière.

    En plus de l’adressage de la page zéro qui est plus performant que celui de la pile matériel, signalons aussi les bénéfices suivants :

    • Inutile de replacer les paramètres d’entrée sur la pile sans arrêt, avec pour résultat immédiat une exécution plus rapide des étages de la pile ;
    • Réduction des effets liés à la récursivité (ce sujet sera abordé dans un prochain article) ;
    • Possibilité de placer plusieurs type (et quantité) de valeurs ;
    • Code plus compact qui permet un meilleur fonctionnement car plus besoin de devoir empiler/dépiler des paramètres lors de l’appel de sous-routines.

    Revenons maintenant à notre sous-routine qui transforme un demi-octet hexadécimal en octet ASCII et voyons comment réaliser cette transformation en utilisant une pile ZP.

    X servira de pointeur de pile, initialisé en début de programme pour indexer de la manière suivante $00,X.

    Pour empiler en page zéro, il faut donc faire un DEX puis stocker en $0,X.

    Voici ce que donne la routine modifiée pour la pile ZP :

    <do_stuff>      ; Get the nybble into A.  Allowable value is 0-F.

    DEX

    STA  0,X        ; Other code can be put between the STA and the LDA, and

    JSR  NYB2ASCII  ; NYB2ASCII’s input and output are protected on the stack.

    LDA  0,X        ; X must be preserved as the data stack pointer of course.

    INX

    <do_stuff>      ; Do something with the ASCII output, like add it to a string, display it, etc..

    Note : Si vous avez besoin du registre X dans le reste de votre programme, il vous faudra le sauver sur la pile matériel.

    La sous-routine NYB2ASCII devient :

    NYB2ASCII:              ; (The initial TSX is no longer necessary.)

            LDA  0,X        ; Get the input parameter from the data stack.

            CMP  #$0A       ; Anything below $0A will end up in the $30’s.

            CLC             ; CLC before the BMI so we only have to do it once.

            BMI  n2a1       ; For 9 or less, skip the next instruction.

            ADC  #7         ; $0A becomes $11, $0B becomes $12, etc..  C is still clear.

     n2a1:  ADC  #$30       ; Whether the 7 got added above or not, this gives the ASCII.

            STA  0,X        ; Put it on the data stack, overwriting the input value.  Note

            RTS             ; that the return address is not on this stack to worry about.

    Procédons selon la même logique pour la sous-routine UM_STAR.

    UM_STAR: DEX                    ; Add a stack byte to use as a temporary variable.

             LDA  #0

             STA  0,X               ; 0,X addresses the temporary variable.  These are in ZP.

             LSR  4,X

             ROR  3,X

             FOR_Y  16, DOWN_TO, 0

                 IF_CARRY_SET       ; The 1st time thru the loop, A needs 0; so don’t use STZ above.

                     CLC

                     PHA

                        LDA  0,X

                        ADC  1,X

                        STA  0,X

                     PLA

                     ADC  2,X

                 END_IF

                 ROR

                 ROR  0,X

                 ROR  4,X

                 ROR  3,X

             NEXT_Y

             STA  2,X

             LDA  0,X

             STA  1,X

             INX                    ; Take back the stack byte we used as a temporary variable.

             RTS

     ;——————

    Ici, un octet est empilé sur la pile ZP grâce à l’instruction DEX (puis dépilé grâce à INX), de la même manière que pour PHA (puis PLA). La pile ZP permet donc d’éviter d’avoir à sauver/restaurer l’index X.

    Il est en outre possible de se passer des instructions DEX/INX en adressant le nouvel octet grâce à $FF,X qui permet de rester en page zéro et qui économise au passage 2 octets et 4 cycles d’horloge.

    Assurez-vous cependant de n’avoir aucune sous-routine ou interruption susceptible d’écraser cet octet, car X semble indiquer que cet emplacement est libre.

    La sous-routine GEOMEAN quant à elle, peut désormais s’écrire :

    GEOMEAN: JSR  UM_STAR  ; Multiply two 16-bit unsigned inputs on the stack and get a 32-bit product.

             JMP  SQRT     ; (JSR, RTS)  Take a 32-bit input on the stack and get a 16-bit output.

     ;——————

    Voici dans le détail les avantages à travailler avec des piles séparées :

    • Le nombre d’octets entrés est indépendant du nombre d’octets sortis. En d’autres termes, nul besoin de nettoyer les octets de sortie factices ni de placer des octets factices sur la pile ;
    • En disposant de données séparées, les adresses de retour ne sont pas traitées comme des données. Le paramétrage devient implicite ;
    • Une sous-routine peut faire appel à une autre sous-routine sans avoir à faire le ménage sur la pile matériel (qui devient désormais la pile de retour) ;
    • La pile matériel est maintenant disponible pour d’autres usages tels que la gestion des limites et des index de boucles (y compris des boucles imbriquées) ;
    • L’ajout d’une nouvelle pile permet d’augmenter l’espace de stockage et d’éviter un crash sur la pile matériel ;
    • Grâce aux modes d’adressages du 6502 en page zéro (ZP,X), nous pouvons adresser la pile ZP très facilement.

    Voyons justement comment mettre à profit les modes d’adressage ZP,X dans l’exemple de routine de déplacement suivante.

    Nous appellerons cette routine CMOVE, pour “character move”.

    Avant de faire tourner cette routine, nous plaçons six octets sur la pile ZP, sous la forme de 3 nombres de 16 bits (poids fort sur l’adresse la plus haute dans chaque cas) :

    • Adresse de départ
    • Adresse de destination
    • Taille de mémoire à déplacer (pouvant aller jusqu’à quelques dizaines de milliers d’octets)

    CMOVE:  LDA  0,X      ; “See-move” Character (memory) move  ( from to len — )

            ORA  1,X

            BEQ  POP3     ; If remaining length is 0, branch to POP3 which is just 6 INX’s, then RTS.

            LDA  (4,X)    ; Get a byte and

            STA  (2,X)    ; transfer it.

            INC  4,X

            BNE  cm1$

            INC  5,X      ; Increment the source addr

     cm1$:  INC  2,X

            BNE  cm2$

            INC  3,X      ; and the destination addr,

     cm2$:  DEC  0,X      ; decrement the count left,

            LDA  0,X

            CMP  #$FF

            BNE  CMOVE

            DEC  1,X

                          ; and go back up for another loop.  If we’re done,

            BRA  CMOVE    ; that fact will be caught in the first three lines (BRA is for 65c02 only and stands for Branch Always).

    Quand faut-il éviter l’emploi d’une pile pour l’usage de paramètres d’entrées / sorties dans des sous-routines ?

    Déplacer des données dans une pile requiert du temps processeur.

    Aussi, si vous devez manipuler une grande quantité de données, comme une chaîne alphanumérique, un tableau ou même une matrice, placez là ailleurs en mémoire et indiquez son adresse de stockage sur la pile.

    RÉCURSIVITÉ

    Une sous-routine peut présenter la particularité d’être récursive, à savoir qu’elle peut s’appeler elle-même à de nombreuses reprises.

    Afin d’éviter que ce genre de sous-routine ne reboucle indéfiniment, entraînant une surcharge de la pile matériel, il faut prévoir une condition qui permette de quitter la sous-routine au bout de x boucles récursives.

    Lorsque cette (ou ces) condition(s) est respectée, on quitte alors la sous-routine par une série de RTS.

    Chaque sous-routine nidifiée (imbriquée) peut disposer de ses propres variables ayant  pourtant des noms semblables.

    Prenons l’exemple de la fonction de Fibonacci qui est utilisée en calculs financiers, lors de la génération de nombres pseudo aléatoires, dans des algorithmes de tri et de recherche ou encore pour la compression de fichiers audio.

    fiboIO:    SETL $103    ; For clarity, give names to the locals.

    fiboTemp:  SETL $102    ; (Record of X will be at $101,X.)

    FIBO:  CMP  #2          ; Test the input.

           BCC  end         ; If it’s 0 or 1, so is the output, so just end.

                            ; This prevents endless nesting, too.  Otherwise,

           PHA              ; create local variable fiboIO, and store A there.

           PHA              ; Create another local variable byte, fiboTemp.

                            ; (Its initial value doesn’t matter.)

           PHX              ; Push X too, to protect the calling routines.

           TSX              ; Prepare X to use for stack-relative addressing.

           DEA              ; Get the n-1 term

           JSR  FIBO        ; and calculate the number for it (recursing here)

           STA  fiboTemp,X  ; and store its result in local variable fiboTemp.

           LDA  fiboIO,X

           DEA

           DEA              ; Now get the n-2 term

           JSR  FIBO        ; and calculate the number for it (recursing here).

           CLC

           ADC  fiboTemp,X  ; Add those two together, and

           STA  fiboIO,X    ; store the answer.  Don’t forget the “,X”!

                            ; Note that there is no looping.

           PLX              ; Restore X for the calling routines.

           PLA              ; Pull fiboTemp off the stack and discard it.

           PLA              ; Pull the answer (fiboIO) off the stack into A.

    end:   RTS

    Cette sous-routine tient sur 34 octets et n’utilise pas la RAM pour le stockage, hormis bien sûr la pile matériel.

    La donnée d’entrée doit rester inférieure à 14 car la donnée de sortie est sur 8 bits et le nombre de Fibonacci pour 13 est 233.

    Avec une réponse sur deux octets ou plus, nous pourrions avoir une donnée d’entrée plus grande sans manquer de place sur la pile, même si ce genre de sous-routine en consomme beaucoup.

    La place disponible sur la pile est largement suffisante pour des sous-routines simples, mais rappelons que les routines récursives ne sont pas des routines normales.

    À suivre.

  • CEO-MAG 349

    Sommaire

    • 2 VISU D’ETE
    • 4 CHARGEMENT CASSETTE : NOVALIGHT V1.2A
    • 7 PUBLICITÉ
    • 8 LES CLONES DE PAC-MAN SUR ORIC (FIN)
    • 12 TESTEUR DE DRAM 4164 POUR ORIC
    • 14 FONCTIONNEMENT DE LA PILE MATÉRIELLE DU 6502 (3)
    • 17 BLAGUES, HOMMAGE À PIERRE DAC (5)
    • 18 FROGGER, LE TAPE-INS DU MOIS
    • 22 LA VISU HIVERNALE EN IMAGES
    • 25 QUELQUES BLAGUES

    Edito

    André est décidément incontournable. il maintient en éveil de nombreux Oriciens avec ses articles toujours précis et propices à nous faire découvrir de nouvelles facettes de notre ordinateur préféré ; mais en plus c’est un de nos gamers les plus avertis. Il nous a de nouveau gratifié de 2 high scores ce mois-ci. Bravo André. L’été approche, vous allez pouvoir prendre vos Orics pour aller à la plage et programmer, jouer, souder. Mais il vous faudra aussi prendre votre PC (ou votre MAC) pour écrire les articles de la rentrée et participer à ce mag qui prend de plus en plus de place dans ma bibliothèque.

    [wpdm_package id=’2630′]

    [wpdm_package id=’2632′]

    [wpdm_package id=’2658′]

  • Chargement cassette rapide: Novalight par Simon

     Depuis l’avènement des fichiers WAV, l’Oric a connu plusieurs nouveaux modes de chargement cassette accélérés: TAP2CD, F16, … En voici un petit nouveau, dont la gestation m’aura bien occupé !

    Je vous présente Novalight, qui se veut le mode de chargement cassette Oric le plus rapide à ce jour de février 2019. Son nom a été choisi en hommage à deux regrettés disparus. Twilighte tout d’abord, qui a programmé tant d’outils, jeux et démos pour Oric, en essayant souvent de garder ses jeux Oric compatibles avec le format cassette. Paul Woakes ensuite, un non-Oricien disparu en 2017. Il a été le co-fondateur de la société de jeux vidéo Novagen, auteur de l’excellente série Mercenary, et créateur de NovaLoad sur Commodore 64… NovaLoad étant précisément un mode de chargement cassette rapide, très répandu à l’époque !

    Tout est parti au début sur une idée de compresser le signal cassette au niveau des bits (plutôt qu’au niveau des octets). Après des simulations sur 5 ou 6 façons de faire, il est apparu que la plus régulièrement efficace est celle… Qu’utilisait déjà TAP2CD de Fabrice ! Novalight doit donc son épine dorsale à TAP2CD: il lui emprunte cette “compression”, ainsi qu’un principe de fonctionnement par interruptions, indispensable pour analyser suffisamment finement la durée des sinusoïdes du signal audio. J’aurais presque pu l’appeler “TAP2CD2” ! Côté outil PC, Novalight est un dérivé direct (mais bien modifié) des outils existants comme TAP2WAV.

    Fabrice a apporté, comme toujours, un soutien régulier; il est fort probable que sans son aide le projet n’aurait pas vu le jour. Il me faut remercier également les Oriciens sur les forums Oric.org et Defence-Force.com, qui ont pris de leur temps pour tester diverses beta-versions et donner des conseils.

    Quelles différences entre TAP2CD, F16 et Novalight ?

    Commençons à situer entre eux les chargements “turbo” existants. On pourrait les hiérarchiser ainsi:

    – F16: le plus lent des trois, il a l’avantage d’accélérer les chargements pour tous les Oric (Oric-1 et Atmos), et ne nécessite aucun loader ! C’est en fait une optimisation du signal audio pour les routines existantes en ROM.

    – TAP2CD: très, très rapide, TAP2CD nécessite une ROM 1.1. Il utilise un loader et sera très fiable à partir du moment où votre liaison audio est de bonne qualité

    – Novalight: reprend les principes de TAP2CD, mais en les poussant aux limites quasi-maximum et en ajoutant une compatibilité ROM 1.0. Il sera donc plus rapide que TAP2CD, mais au détriment de la fiabilité: il faut une connexion audio et un player de WAV d’excellente qualité (Audacity ?), et certains Oric au hardware un peu fatigué, malgré tout, ne seront pas compatibles. A noter que Novalight gagne un peu de temps sur le chargement de son loader… En utilisant le format F16 puis en se chargeant en partie lui-même au format Novalight 😉

    Novalight va se loger en page 1, sous la pile, et laisse assez peu de place à cette dernière: 54 octets. Attention à l’utilisation dans un programme donc, éviter de faire trop d’appels à des sous-programmes !


    Comparatif des vitesses Loader + Programme

    slow Fast standard F16 TAP2CD Novalight
    Zorgon  (37K) ? 4min 26s 2min 38s 31s 15s
    Xenon-1 (37K)            28min 4min 15s 2min 31s 32s 12s
    Acheron’s Rage (43K) 32min 5min 12s 3min 12s 40s 12s
    Oricium (46K)            ? 5min 31s 3min 27s 48s 18s
    Voilier (Hires – 8K) 6min 56s 34s 8s 3s
    Cercle (Hires – 8K) ? 1min 03s 42s 11s 2s
    Ecran TEXT (1K) ? 10s 6.5s 5s 1.5s

    En détail, les modifications et ajouts par rapport à TAP2CD

    – les périodes de base servant à encoder 2 bits dans le signal (fichier WAV), sont passées de 4, 6, 8, 10 samples, à 3, 4, 5 et 6 samples. Cela a sans doute été le travail le plus difficile: bien souvent ces durées raccourcies n’étaient pas correctement reconnues par les Oric, dont certains prenaient l’une pour l’autre. Il a fallu tester toutes formes de sinusoïdes pour voir laquelle permettait au mieux à un maximum d’Oric de distinguer correctement ces quatre durées. Au final quelques Oric avec un VIA fatigué n’arriveront jamais à décoder correctement ce signal. C’est LA limite de Novalight, TAP2CD sera plus fiable à ce niveau.

    – des statistiques ont été effectuées et ont montré que dans les programmes Oric, on utilise environ 60% de bits à 0, et 40% de bits à 1. La période la plus courte a donc été utilisée en priorité pour encoder “00”, alors que dans TAP2CD elle servait pour “11”. Le gain ne sera pas systématique, il s’agit vraiment d’une statistique…

    – une compression RLE a été ajoutée: si un octet est répété plusieurs fois à la suite, il n’est encodé qu’une seule fois, et sera suivi par le nombre de répétitions. Dans le signal, un octet répété N fois se traduit donc par cet octet, suivi de (N-1) sinusoïdes de 3 samples, puis une dernière sinusoïde de 4 samples qui marque la dernière répétition (et leur fin donc).

    – création de dictionnaires: avant de créer le signal, le fichier TAP est analysé et on repère les octets non répétés (échappant à la compression RLE donc), qui occupent la plus grande place dans le signal. Les 14 octets avec le plus grand nombre d’occurrences sont placés dans deux tableaux de 7 octets chacun, chargés en page 2 avec l’en-tête du programme. Les octets de chaque dictionnaire bénéficieront d’un encodage particulier, plus rapide qu’un octet normal: une seule sinusoïde de 3 à 9 samples.

    – les bits de stop ont été supprimés, l’Oric travaille pendant le bit de start. Et ce bit de start devient porteur d’information: s’il dure 5 samples, ce qui suit est un octet normal. 6 ou 7 samples, c’est un octet à chercher dans un des deux dictionnaires. Enfin 8 samples: ce qui suit est une répétition d’octet (RLE). Pourquoi pas moins de 5 samples ? Parce que c’est pendant cette durée que l’Oric assemble les bits et met en mémoire l’octet précédent. Il faut quand même lui laisser ces 115 microsecondes pour cela; on pourrait donc dire que les bits de stop ne sont pas vraiment supprimés, mais regroupés avec le bit de start 😉

    ROM 1.0: l’horrible bug d’affichage du Loading en HIRES n’affectera plus les écrans que vous chargerez !

    Si on arrivait à faire en sorte que l’Oric travaille plus vite, on pourrait raccourcir ce bit de stop. Mais le code a été tordu dans tous les sens pour minimiser les sauts et autres “pertes de temps”. Au final quand défilent les bits, l’Oric doit, dans toutes les situations, travailler en moins de 69µs (3 samples, période la plus courte pour encoder “00”) pour être certain de ne pas rater une information; et en fin d’octet, pour assembler en plus l’octet et le placer en mémoire, travailler donc en moins de 115µs.

    – pour son loader, Novalight utilise le format F16 plutôt que le format standard, ce qui fait gagner environ 1 seconde. Ensuite il inverse la valeur des bits, pour encoder des 1 (plus courts) à la place des 0 (plus nombreux); gain environ 10% de temps. Enfin le loader Novalight est découpé en morceaux: un “noyau” chargé en vitesse F16, qui peut charger le reste de son code à la vitesse Novalight sans compression, sous forme de banques. Chaque banque contient le code nécessaire au moment voulu (compression, fin de programme, etc.).

    – Ce système de banques permet de gagner de l’espace mémoire, suffisamment pour permettre de rendre Novalight compatible Oric-1 et Atmos

    – En bonus, le chargement des écrans Hires n’est plus abîmé sur Oric-1 par l’affichage de “Loading” au beau milieu du dessin. Le CLOAD de la ROM va commencer par afficher ce bug, mais il sera effacé par l’écran chargé, lequel ne sera ensuite plus altéré à la fin du chargement.

    Mise au point

    La mise au point de Novalight s’est étalée sur plusieurs années, non sans difficultés. Le principe est le suivant: quand une sinusoïde se présente, le VIA (6522) détecte un signal (front montant), et envoie une interruption à l’Oric. Lors du front montant suivant, l’Oric calcule le temps écoulé entre ces deux sinusoïdes. Cette durée est comparée à des seuils (des bornes, donc) qui lui permettent de déterminer si la sinusoïde valait 3, 4, 5 samples (etc.). Problème : la valeur de cette durée, mesurée par l’Oric, diffère légèrement d’une machine à l’autre. Et donc les seuils à utiliser pour l’encadrer diffèrent aussi un peu selon chaque Oric.

    Ainsi le programme, s’il veut tourner sur tous les Oric, devrait soit gérer ces variations (autocalibration: test sur la machine et adaptation des seuils), soit utiliser des valeurs qui seront communes à tous les Oric et Atmos. La calibration nécessitant trop de temps d’exécution et de place dans le programme, il a fallu étudier le cas d’un maximum de machines pour tenter de déterminer des seuils moyens, communs à tous. J’ai pu tester régulièrement Novalight sur 3 à 10 machines, plus l’aide ponctuelle de testeurs sur les forums Oric ou par email, sur 4 ou 5 autres machines. Sur les 10 régulières, seule une machine est récalcitrante, il faut dire qu’elle ne doit pas être en forme: même avec des seuils personnalisés, elle n’est pas capable de distinguer à chaque coup entre 3 et 4 samples. Deux autres machines nécessitent un volume sonore minimal pour fonctionner, les autres un volume maximal. Comme d’habitude donc, le volume semble être un paramètre essentiel et aléatoire d’une machine à l’autre !

    La difficile recherche des seuils communs à plusieurs Oric et aux émulateurs, en fonction des formes d’ondes.

    Compatibilité ROM 1.0

    Initialement, Novalight ne fonctionne que sur ROM 1.1, avec un loader de 218 octets. Impossible de faire l’équivalent sur ROM 1.0, programmée de façon moins modulaire que la ROM 1.1. Il aurait fallu reproduire de longs morceaux de la ROM, ce qui aurait pris trop d’octets.

    L’idée est donc venue petit à petit: créer un “noyau” Novalight, permettant, sur toute ROM, de charger à vitesse accélérée mais sans toutes les options (compression et dictionnaires absents); puis des “banques” (de 40 à 60 octets) chargeant des morceaux de code à exécuter ensuite. Au final Novalight utilise un noyau chargé en 2 parties, et 4 banques. La place ainsi gagnée a permis d’écrire du code compatible Oric-1 et Atmos !

    L’avantage “bonus” est que le loader initial est plus court, donc plus rapide à charger. Les banques se chargeant à vitesse “Novalight réduite” sont beaucoup plus rapides à charger. Au final, le loader se charge en moins de 0,7 seconde. Le revers de la médaille est pour les programmes en plusieurs parties: il faut recharger le loader à chaque fois, car les banques écrasent le code initial.

    Le fichier WAV sera donc construit avec une succession de programmes à charger:

    Loader (vitesse standard ou F16): initialisations du VIA, des interruptions, et chargement de la suite du loader

    Suite du loader contenant les instructions de chargement des banques  (vitesse Novalight “lente”)

    En-tête du programme (vitesse Novalight “lente”)

    Banque 2 (vitesse Novalight “lente”): affichage Loading etc., et chargement de la suite

    Banque 3 (vitesse Novalight “lente”): chargement de la compression RLE et des dictionnaires Novalight

    Programme (vitesse Novalight maximale)

    Banque 4 (vitesse Novalight “lente”): réinitialisation du VIA, des interruptions, lancement du programme chargé

    Afin de garder un peu de  flexibilité, une option existe dans Novalight pour utiliser l’ancien loader: ROM 1.1 uniquement, mais il n’est pas utile de le recharger à chaque fois. Cela peut être utile, par exemple, pour faire des slide-shows ou des animations.

    La surprise Oric

    Les tests ont été l’occasion d’avoir une petite surprise.

    C’était presque ça ! Try again…

     

    Pour être très rapide, une des idées de Novalight est que l’Oric doit rester synchronisé avec le signal audio du début à la fin. Le signal audio numérique se déroulant à vitesse parfaitement constante, il “suffit” que l’Oric travaille assez vite pour lire les informations et les traiter avant de lire l’information suivante… Il se trouve que sur un Atmos particulier, j’avais des erreurs, d’abord prises pour des erreurs de calibration des seuils. Mais rien n’y faisait… La conclusion a fini par s’imposer: le traitement du dictionnaire était un peu long, et passait sur certains Atmos, mais pas sur celui-ci quand il était appelé plus de 3 fois de suite ! Il était donc exécuté plus lentement, trop lentement ! Et déphasait doucement le signal audio et l’Atmos, qui finissait par perdre une information. Autrement dit, et ça a été ma surprise: tous les Oric ne travaillent pas exactement à la même vitesse !

    En réduisant un peu la durée de traitement du dictionnaire, tout est rentré dans l’ordre… Comprendre le problème aura pris plusieurs jours !

    La surprise PC

    Autre surprise sur laquelle je me suis arraché les cheveux… Le PC (sous Windows XP), au bout d’un certain temps de fonctionnement, ne semble plus générer un signal audio aussi propre qu’après le boot ! Un de mes Oric en prend ombrage et ne charge plus les programmes, alors que tout va bien sur les autres…

    En cas de doute, appliquez la règle universelle: rebootez l’ordi qui lit le WAV !

    Utilisation

    En ligne de commande : Novalight [ -option1 ] [ -option2 ] <.TAP ficher en entrée> <.WAV fichier en sortie>

    Il existe bien entendu des options:

    -s  ‘standard speed’: utiliser la vitesse standard au lieu de la vitesse F16 pour le loader (plus lent, mais certains Oric supporteraient mal la vitesse F16 ?)

    -o  ‘old loader’: utiliser l’ancien loader ROM 1.1-seulement au lieu du nouveau compatible 1.0/1.1. L’ancien a un avantage: il peut être chargé une seule fois, puis appelé plusieurs fois par un CALL#100, tant qu’il reste intact bien sûr. Vous pourrez ainsi charger plusieurs programmes ou écrans sauvés au format Novalight sans loader. Mais adieu la ROM 1.0 donc.

    -n  ‘no loader’: génère les WAV Novalight sans y ajouter de loader. Il vous faudra charger un ‘old loader’ d’abord puis utiliser CALL#100 pour charger chaque WAV ainsi constitué. ROM 1.1 seulement.

    -p  ‘long pause’: génère un silence de plusieurs secondes après chaque programme sur le WAV. Raison ? Les programmes ERE Informatique, par exemple, nécessitent du temps pour dessiner l’écran de chargement; c’est dommage si le WAV démarre avant que l’Oric ait fini son dessin…

    Novalight affichera, pour chaque programme converti, le dictionnaire utilisé pour la compression, ainsi que des statistiques de compression. Vous verrez que certains programmes y sont peu propices, alors qu’un écran HIRES presque vide sera quasi-totalement compressé, et donc très, très rapide à charger.

     

    Où trouver Novalight

    Vous devriez trouver Novalight sur la disquette du magazine à télécharger. Y sont inclus des sources; C pour le programme MS-DOS, et assembleur pour le loader Oric. Attention toutefois, ce n’est pas normalisé et je n’ai rien nettoyé, ne soyez pas surpris… Mon assembleur est autodidacte et donc plein d’astuces rédactionnelles perso, et je vois surtout ces fichiers comme des brouillons desquels il aurait été dommage d’effacer certaines idées. Le C néanmoins, devrait compiler comme il faut !

    Un petit fichier mp3 est aussi là pour l’anecdote: quand une idée arrivait subitement, je m’enregistrais pour ne pas l’oublier, tout en espérant l’exposer clairement pour qu’à la réécoute, elle reste compréhensible ! J’ignore si ça peut être rigolo à écouter, ou si ce sera totalement pénible, à vous de me dire si vous en avez le courage 😉

    Il est aussi possible de récupérer Novalight avec les autres outils cassette de Fabrice:

    https://sourceforge.net/projects/euphorictools/files/Tape%20tools/

    Zorgons Revenge à la moulinette Novalight: un seul programme, moyennement compressé.

    N’oubliez pas les impératifs:

    – liaison audio au top, et aucune perturbation audio pendant la lecture (téléphone sans fil, sons sur l’ordi qui joue le WAV, Wifi ?, …)

    – ne surtout pas modifier le WAV ou le convertir dans un autre format: chaque sample compte

    – lecteur de WAV à 44kHz, au top (la moindre approximation, et c’est l’échec)

    – il reste la possibilité que votre Oric ne soit pas compatible

    Snif, la fin !

    J’espère que vous pourrez profiter de Novalight sur vos Oric-1 et vos Atmos. C’est pour moi la fin d’un long projet passionnant, de plusieurs années, à créer des outils pour faire des mesures, des statistiques, à réfléchir à la compression, à réduire la taille du code, à l’accélérer, à échanger avec les Oriciens, … Et j’espère qu’un jour quelqu’un fera mieux – plus rapide ou plus fiable, voire les deux !

    Tests de signal sur l’Atmos de Chema, début 2018.

    Merci pour leur aide, tests et conseil, à…

    Fabrice, FredV60, Musepat, Kenneth, Dom50, Voyageur, Oric1-Atmos, Froggy, Godzil, DrPsy, ISS, Chema, Dbug, NekoNoNiaow.

    Annexe 1: séquence de chargement du loader Novalight dans la pile, puis du programme.

    Annexe 2: Format du WAV, et séquence de chargement du loader Novalight, puis du programme.

    Codage WAV Contenu loader normal
    3000 samples Silence d’intro, au cas où un player “mange” le début du signal. 0,07s.
    F16 30 octets de synchro (surtout pour la même raison que le silence qui précède)
    F16 header et nom de programme = au nom du programme dans le .TAP
    100*3 samples Gap: bits de stop pour laisser le temps à l’Oric de travailler
    F16 $13E-14A – 13 octets: code pour inverser les bits des octets qui suivent
    F16, bits inversés $14B-$1BD – Common Area 1 et décodage de base Novalight (sans dictionnaire ni compression RLE)

    115 octets, inverser les bits permet de gagner 10% de temps (les 0 étant encodés plus lentement que les 1 en F16)

    Détail:

    $14E-$14F: saut pour exécuter la “Common Area 1”

    $150-$15C: interruption de lecture du signal

    $15D-$18F: décodage d’un octet Novalight “normal” (non compressé RLE, et hors dictionnaire)

    $190-$1C0: “Common Area 1”: initialisation du VIA, mise en place de l’interruption Novalight, chargement de la “Common Area 0”

    500 samples Silence pour séparer les programmes (purement visuel). 0,0115 secondes. Réduire cette durée affecte la compatibilité Euphoric.
    100*3 samples Synchro Novalight
    Novaligth “basique” (sans compression RLE ni dictionnaire), octets inversés $100-$14C – Common Area 0

    77 octets, du dernier au premier (permet au code de chargement d’être plus compact). A noter: écrase la partie précédente $141-$14F, devenue inutile.

    Détail:

    $100-$117: chargement du header (et du dictionnaire) du programme à charger

    $118-$120: chargement et exécution de la “Common Area 2” (affichage du Loading, gestion du Hires et du bug de la ROM 1.0)

    $121-$128: chargement de la “Common Area 3” (gestion de la compression RLE et du dictionnaire Novalight)

    $129-13A: chargement du program principal, 100% Novalight

    $13B-$145: chargement et exécution de la “Common Area 4” (restauration des interruptions et du VIA, lancement du programme chargé)

    $146-$14F: sous-programme de chargement des “Common Area”

    30*3 samples Petit gap
    Novaligth “basique” 30 octets de synchro ($16)
    Novaligth “basique”, octets inversés $292-$2BF – En-tête du programme + dictionnaire

    46 octets, du dernier au premier (permet au code de chargement d’être plus compact).

    Contient les infos du programme à charger (header classique) + les dictionnaires de 14 octets les plus répétés dans le programme (pour la compression)

    Novaligth “basique”, octets inversés $18D-$1BA – Common Area 2

    46 octets, du dernier au premier (permet au code de chargement d’être plus compact).

    Détail:

    Affichage du Loading, gestion du Hires et du bug de la ROM 1.0: si l’écran est en Hires, on n’affiche pas le Loading, et on évite ainsi une ligne avec des points blancs.

    100*3 samples Synchro Novalight
    Novaligth “basique”, octets inversés $18D-$1C9 – Common Area 3

    61 octets, du dernier au premier (permet au code de chargement d’être plus compact).

    Détail:

    $190-$1BB: décodage d’un octet du dictionnaire

    $1BC-$1CD: décodage d’octets compressés RLE

    Novalight Programme à charger (fichier TAP), à vitesse maxi ! (avec compression RLE et dictionnaire).
    2*9 samples Marqueur de fin de programme
    100*3 samples Synchro Novalight
    Novaligth “basique”, octets inversés $18D-$1C4 – Common Area 4

    56 octets, du dernier au premier (permet au code de chargement d’être plus compact).

    Détail:

    Restauration des interruptions et du VIA, lancement du programme chargé.

    2*3 samples Pour terminer la synchro Novalight
    15000 samples Silence de fin, au cas où un player “mange” la fin du signal.
  • CEO-MAG 348

    Sommaire

    • 4 CHARGEMENT CASSETTE RAPIDE : NOVALIGHT
    • 11 PUBLICITÉ
    • 12 LA TOUCHE FUNCT (2)
    • 15 BLAGUES, HOMMAGE À PIERRE DAC (4)
    • 16 FONCTIONNEMENT DE LA PILE MATÉRIELLE DU 6502 (2)
    • 18 3D MAZE, LE TAPE-INS DU MOIS

    Edito

    A l’approche de la visu d’été (à priori le 15/6) ; Steve, Simon, André et Yann nous offrent de nouvelles découvertes à faire avec notre oric. Nous ne remercierons jamais assez ces mousquetaires de la préservation, qui nous permettent mois après mois d’aller plus loin avec notre ordinateur préféré, de découvrir quelques lignes perdues dans un magazine … Bientot, Voyageur nous proposera de nouvelles modifications à réaliser sur nos Oric (je dis «nos» car je me vois mal faire des modifications sur mon unique Oric). Préparez vos fers à souder.

    [wpdm_package id=’2634′]

    [wpdm_package id=’2636′]

    [wpdm_package id=’2656′]

  • Fonctionnement de la pile matérielle du 6502 (1/8)

    EN GUISE D’INTRODUCTION

    Fasciné par certaines utilisations détournées de la pile de matériel du 6502, telles que les programmes de protections, j’ai voulu en apprendre davantage sur son fonctionnement.
    Je vous propose donc ici la traduction partielle d’un sujet dont la version originale se trouve à l’adresse suivante : http://wilsonminesco.com/stacks/

    QUELQUES DEFINITIONS

    Le type de pile dont il est question ici est une partie de la mémoire vive utilisée pour le stockage temporaire de données, qu’il s’agisse de variables ou d’adresses, avec comme mode d’accès, dernier entré, premier sorti (Last In First Out).
    On compare généralement ce type de pile à une pile d’assiettes dans un meuble à ressorts que l’on peut trouver à côté d’un buffet restaurant.

    La quantité de compression ou d’étirement des ressorts est proportionnelle au poids des assiettes que le meuble contient, de sorte que tant que le meuble n’est pas rempli complètement, un employé peut ajouter n’importe quel nombre d’assiettes récemment lavées et les assiettes seront toujours dans la même position au sommet, prêtes pour le prochain client.

    D’habitude, ni l’employé ni le client n’ont besoin de savoir combien d’assiettes chaudes sont stockées en dessous.

    On peut aussi prendre l’exemple d’une tige métallique avec un tas de papiers embrochés.  Vous pouvez voir les documents qui sont sous le sommet, et vous pourriez même lire ou écrire sur eux dans une certaine mesure sans retirer ceux qui sont au-dessus, mais le retrait ou l’ajout réel de documents a toujours lieu par le sommet.

    Le contraire d’une pile (ou mémoire LIFO) serait une mémoire de type premier entré, premier sorti (FIFO) ou file d’attente, qui peut dans ce cas être comparée au convoyeur d’une machine à rayons X dans un aéroport. Sur cette machine, les affaires passent d’un côté à un autre des rayons X, dans le même ordre qu’elles sont entrées.

    Contrairement à la pile d’assiettes, une pile de nombres dans la mémoire de l’ordinateur ne se déplace pas de haut en bas quand quelque chose est ajouté ou enlevé de la pile. Il serait en effet contre-productif de déplacer toutes ces données vers le haut ou vers le bas comme pour les assiettes, alors qu’il est plus simple d’utiliser un pointeur réglable pour savoir où se trouve le haut ou, en fait, dans le cas de la pile matériel du 6502, quelle est l’adresse RAM qui est la prochaine disponible pour mettre quelque chose sur la pile.

    Ce pointeur est le registre S (Stack pointer) du 6502.

    Dès lors, si l’analogie du distributeur d’assiettes ne tient plus, pourquoi l’évoquer ?

    En fait, ce qu’il convient surtout de retenir ici, c’est qu’habituellement, on ne s’occupe que de ce qui se trouve au-dessus de la pile, sans se soucier de la profondeur de celle-ci, comme un navire en pleine mer qui flotte de la même manière que la profondeur de l’eau soit de 100 mètres ou de 1000 mètres. Tant qu’une action ou une routine dispose des éléments de la pile dont elle a besoin, peu importe combien d’autres éléments sont plus bas dans la pile, en attendant d’être utilisés par d’autres routines ou parties d’une routine.

    La pile du processeur 6502 permet de stocker des adresses pour des sous-routines et des interruptions (moins fréquentes que pour des sous-routines) ainsi que des variables.

    C’est dans la première page du 6502 ($0100-$01FF) que réside la pile de matériel. Les tests montrent d’ailleurs que contrairement à une légende urbaine, cette zone mémoire est beaucoup plus grande que ce dont le programmeur a réellement besoin.

    Le pointeur de la pile de matériel est le registre S qui n’a que 8 bits de largeur; le 6502 ajustant automatiquement le numéro de page à $01 pour tous les accès à la pile. La pile de matériel en page 1 se développe vers le bas, et non vers le haut. Toute routine de réinitialisation doit donc initialiser le pointeur de pile au sommet de l’espace disponible. Il s’agit habituellement de l’adresse $01FF. Cette routine s’écrira simplement :

    LDX  #$FF ; Initialise X au sommet de la pile
    TXS ; Transfère dans le pointeur de pile

    Puisque la pile se développe vers le bas, le pointeur de pile se décrémente après chaque octet poussé sur la pile, et s’incrémente avant que chaque octet ne soit tiré hors de la pile.

    ADRESSES DE SOUS-ROUTINE ET NIDIFICATION

    Une sous-routine est une partie de votre programme dont vous avez besoin à de multiples reprises et à différents endroits. Au lieu d’avoir une copie de cette routine à chaque endroit où vous en avez besoin, vous l’écrivez une fois pour toutes et vous l’appelez depuis la portion de programme requise. Le compteur de programme se rend à cette sous-routine puis doit pointer de nouveau sur la routine d’appel pour reprendre l’exécution. Pour savoir où revenir, le compteur de programme (donc l’adresse de retour) a au préalable été sauvée sur la pile.

    C’est ce que réalise l’instruction JSR : « Jump, Saving Return address » (JSR est habituellement traduit par « Jump to SubRoutine », ce qui fonctionne tout aussi bien mais n’est pas tout à fait exact.) Supposons maintenant que cette routine doive en appeler d’autres. Comme chaque JSR met l’adresse de retour sur la pile, les adresses de retour nécessaires en premier lieu seront les dernières stockées sur la pile.

    La nidification est ce qui convient de mieux pour ce genre de situation. On appelle nidification (ou imbrication), le fait qu’une sous-routine en appelle une autre, qui à son tour en appelle une autre, et ainsi de suite. Si vous n’aviez pas besoin de la nidification, vous pourriez inscrire l’adresse de retour dans une variable ou un registre; mais vous vous apercevez que dès la première nidification, la variable serait écrasée et la première adresse de retour serait perdue.

    C’est là que la pile entre en jeu.

    Considérons à présent la nidification des sous-routines ci-dessous.

    Dans ce scénario, la pile contiendra les nombres hexadécimaux suivants aux points  (a), (b) et (c) ; (sans compter ce qui aurait déjà pu être sur la pile avant (a).

      (a)(b)(c)
    Sommet pile (*) $1915 $2632 $2F43
        $1915 $2632
          $1915

    (*) Top Of Stack (TOS)

    Ce tableau semble comporter des erreurs. En effet, au point (a)  l’adresse de la prochaine instruction est censée être $1916, et non $1915.

    En fait, l’instruction RTS (Return From subroutine) incrémentera l’adresse de retour et l’exécution du programme reprendra bien à $1916 (ce qui n’est pas le cas pour RTI, ReTurn-from-Interrupt, et fera l’objet d’un autre article).

    Puisque le bus de données et la mémoire du 6502 sont adressés sur 8 bits, chaque adresse de retour évoquée ci-dessus nécessite deux emplacements dans la pile. Lorsque JSR pousse l’adresse de retour (moins 1) sur la pile, il pousse d’abord l’octet haut, puis l’octet bas. N’oubliez pas que la pile grandit, et que le pointeur de la pile se décrémente lorsque les octets sont poussés sur la pile, de sorte que l’ordre d’octet résultant est l’octet de poids faible dans l’adresse mémoire la plus basse, comme le sont les autres adresses dans le 6502.

    Supposons par exemple que la valeur du pointeur de pile (registre S) était $EF avant que le code n’entre dans le diagramme de pile ci-dessus. Cela donnerait une occupation de l’espace mémoire de la pile selon le tableau suivant (ne sachant pas ce qui figurait de $EF à $FF, ces octets ne sont pas cartographiés).

    Lorsque vous quittez les sous routines et que vous revenez à la routine principale, voici à quoi ressemble la mémoire de la pile.

    Les nombres entre parenthèses sont toujours là, mais cette partie de la mémoire de la pile est libérée. Retirer quelque chose de la pile signifie simplement que le processeur en lit le contenu et incrémente ensuite le pointeur de la pile. Pouvez-vous utiliser ces chiffres, puisqu’ils sont toujours là ? Si vous avez des interruptions, la réponse est non, car une interruption pourrait survenir à tout moment et les écraser. Cela violerait le protocole LIFO et le processus des interruptions nécessite que ce protocole soit respecté.

    À suivre.

  • CEO-MAG 347

    Sommaire :

    • 4 CR DE L’AG DU 2 FÉVRIER 2019
    • 6 LA TOUCHE FUNCT (1)
    • 7 BLAGUES, HOMMAGE À PIERRE DAC (3)
    • 8 RÉGLAGE DU SON DE L’ORIC
    • 12 FONCTIONNEMENT DE LA PILE MATÉRIELLE DU 6502 (1)
    • 15 PUBLICITÉ
    • 16 C’EST LA MÈRE MICHEL : ERRATUM
    • 17 QUELQUES BLAGUES

    Edito

    Après une sympathique visu où nous avons testé un atelier de coworking tous à l’étroit pour découvrir les nouveautés apportées par les uns et les autres, J’ai pris une longue pause, suis parti en voyage mais rien n’est perdu. De retour avec un peu de temps, je profite de ce premier week-end un peu plus calme pour libérer enfin le mag de mars. Vous y découvrirez une nouvelle série proposée par Yann qui vous permettra de maitriser la pile de l’Oric, ou encore comment réduire les nuisances sonores du zap et du ping Bonne lecture A bientot, Didier

    [wpdm_package id=’2638′]

    [wpdm_package id=’2640′]

    [wpdm_package id=’2654′]

  • Bienvenue sur la page du Club Europe Oric (CEO)

    Club Europe Oric : Kézako ?

    Oric est une marque de micro-ordinateurs 8 bits ayant connu un certain succès dans le milieu des années 80, notamment en France et en Grande-Bretagne.

    Le CEO est un club d’utilisateurs Oric, constitué en association à but non lucratif (loi 1901) et regroupant une centaine de membres.

    Le CEO diffuse à ses membres un magazine, le Ceo-Mag, (principalement en français), contenant des infos, des dossiers, des trucs et astuces, des listings, des cours de programmation, etc. Ce magazine est diffusé sous forme électronique (emag) ou ‘physique’ (mag papier).

    Le club propose en outre des fichiers associés au magazine regorgeant de logiciels liés à l’Oric. Les fichiers comprennent généralement des programmes Oric au format K7 (.tap) ou au format disquette (Sedoric) utilisables avec un émulateur tel Euphoric ou Oricutron. Des utilitaires ou un pc ancien permettant de transformer à domicile ces fichiers numériques en cassettes / disquettes bien réelles pour l’Oric.

    Pour les nouveaux adhérents, l’adhésion au club pour l’année en cours coûte 20 euros tout compris. Il s’agit d’un tarif unique donnant droit à tous les services du club, notamment un abonnement d’office au ceomag et au ceodisk (sous réserve de fournir une adresse email bien sûr). Les coordonnées (postales et email) du trésorier et du président figurent sur le formulaire d’adhésion. Notez bien que ce formulaire est à retourner au trésorier.
    Pour les renouvellements d’adhésion, le montant est de 10 euros pour l’année.

    A quoi sert ma cotisation ?

    Paiement de l’hébergement
    Location d’une salle deux fois par an
    Frais postaux

    A quoi ai je droit en étant adhérent ?

    Non adhérent Adhérent CEO
    Accès aux deux meeting Annuels Oric
    Accès à tous les ceomag depuis 1990
    Disposer d’une adresse mail oric.org
    Pouvoir acheter du matériel mis en vente par le club (controleur microdisc)
    Accès aux articles sur oric.bqtt.net/
    Hébergement de son site perso sur oric.org

    Consulter notre présentation du dernier numéro du Ceo-Mag: LE MAG DU MOIS (SOMMAIRE)

    Exceptionnel:


    Plusieurs numéros du magazine sont en téléchargement libre.
    Cliquez sur l’une des couvertures pour découvrir notre magazine ..

    Participez à nos visus

    Le CEO organise également des réunions (“VISUS”) entre Oriciens qui se tiennent à Paris (en général deux fois par an, en janvier et en juin).

    Pour tout savoir sur la prochaine visu … : venir

    Quelques photos prises lors de nos visus :

    FAQ


    Que m’apporte l’adhésion au club

    • l’accès au magazine, téléchargeable en ligne
    • l’accès à du contenu supplémentaire sur le site du ceo
    • l’accès à des photos, vidéos et des articles en lignes
    • la possibilité d’avoir un mail (boite ou redirection) en @oric.org

    Est ce que la visu est payante ?

    La visu est ouverte gratuitement à tous.

    Comment renouveler mon abonnement ?

    L’abonnement est réalisé pour l’année en cours. Il n’y a pas d’inscription au prorata de l’année en cours, le montant est indivisible quelque soit la date d’inscription.

    Il n’y a pas de bulletin de réinscription au Club Europe Oric. Tous les membres sont contactés par le trésorier de l’association pour le renouvellement de l’adhésion.

    Comment télécharger le mag ?

    Le téléchargement du mag ainsi que d’autres documents est réservé aux membres du Club Europe Oric.

    Pour télécharger le magazine, pointer sur le magazine choisi dans la rubrique magazine et cliquer sur download. (image)

    Vous pouvez choisir de télécharger quelques pages ou le magazine dans son intégralité. Ce n’est que lors de la demande de téléchargement du pdf que vous sont demandés le login et le mot de pass fournis lors de votre inscription.

    Le téléchargement des programmes du mois au format k7 ou disquette, des fichiers options pour votre ordinateur sont accessibles en remontant le chemin à l’année en cours puis en sélectionnant le dossier software. (image)

    Je n’ai pas mes logins (ou je les ai perdu), comment faire ?

    Prendre contact avec le trésorier de l’association via le formulaire de contact : RECUPERER SON LOGIN

  • CEO-MAG 346

    Sommaire :

    • 2 VISU HIVERNALE J-6
    • 4 DE MUSIC À SOUND
    • 7 BLAGUES, HOMMAGE À PIERRE DAC (2)
    • 8 UNE MÈRE MICHEL DE MÉLOMANE
    • 11 PUBLICITÉ
    • 12 FDC 1793 ET READ TRACK
    • 14 THE WHITE BARROWS
    • 16 ALIEN DROPOUT

    Edito

    Bonjour et Meilleurs Voeux à tous, J-6 pour la visu, l’occasion de nous revoir et de découvrir le gagnant du concours NY 2019 CEO. Les tests impitoyables du jury se poursuivent … Profitons de ces quelques jours pour faire un peu de type-ins. En effet, Steve nous a scanné des tonnes de documents dont ce sympathique Alien Dropout (que l’auteur avait visiblement pensé appeller Alien Invasion. Le jeu m’a fait replonger des années en arrière, et m’a rappellé un de mes premiers jeux acquis avec mon Oric : Envahisseurs (oui, je sais, j’aurais peut etre pu mieux choisir à l’époque). Alors à vos claviers, relevez le défi (et pour les fainéants, le jeu est en exclusivité sur le zip du mois et sera uploadé dans quelques jours sur oric.org A bientot à la visu et que les comptables en herbe se préparent, nous fèterons le départ en retraite de René notre trésorier, après des années de bons et loyaux services. Une place en or est à prendre !

    [wpdm_package id=’2642′]

    [wpdm_package id=’2644′]

    [wpdm_package id=’2652′]

  • CEO-MAG 345

    Sommaire

    • 2 Visu Hivernale
    • 4 Concours NY2019, les 9 prétendants
    • 6 Réalisez de beaux écrans haute résolution
    • 9 Publicité
    • 10 Transcrivez votre partition musicale en programme Oric
    • 14 Histoire d’O

    Edito

    Bonjour et Meilleurs Voeux à tous, C’est la période des voeux. Je me plierais donc à la tradition. Avec ce numéro, je fais le voeu de recoller à la sortie mensuelle du mag. Vous en trouverez donc un exemplaire des plus classiques avec les incontournables articles d’André et de Yann qui en ce début d’année nous propose des trucs, astuces et recettes pour maitriser les domaines artistiques de l’Oric. Je me laisse un peu aller …. à un deuxième voeu…. imaginez la richesse du mag si chaque adhérent / lecteur assidu écrivait un article par an. Un test d’un jeu oublié, une solution, ou l’explication d’une routine / d’un hardware qu’il développe. Ce faisant, l’année 2019 démarre sur les chapeaux de roue, avec la prochaine visu et la remise des prix du concours CEO 2019.

    [wpdm_package id=’2646′]

    [wpdm_package id=’2649′]

    [wpdm_package id=’2651′]