Site logo

Triceraprog
La programmation depuis le Crétacé

  • Notes sur le Motorola 6809 ()

    Je place ici quelques notes sur le Motorola 6809, pour me remettre rapidement dans le bain lorsque je change de processeur.

    Registres

    • 2 accumulateurs 8 bits A et B, qui peuvent se joindre en un seul accumulateur 16 bits D
    • 1 registre d'index X 16 bits
    • 1 registre SP (Stack Pointer)
    • 1 registre PC (Program Counter)
    • 1 registre d'état : 11HINZVC
      • 5, H : half carry
      • 4, I : interrupt
      • 3, N : negative
      • 2, Z : zero
      • 1, V : overflow
      • 0, C : carry

    Interruptions

    • NMI (Non Maskable Interrupt)
    • IRQ1 (Interrupt Request) : pour les périphériques externes
    • IRQ2 (Interrupt Request) : pour le timer et l'interface série

    IRQ1 a la priorité sur IRQ2.

    Vecteurs d’interruptions :

    MSB LSB Interruption
    FFFE FFFF Reset
    FFFC FFFD NMI
    FFFA FFFB Software interrupt (SWI)
    FFF8 FFF9 IRQ1
    FFF6 FFF7 ICF (Input Capture)
    FFF4 FFF5 OCF (Output Compare)
    FFF2 FFF3 TOF (Timer Overflow)
    FFF0 FFF1 SCI (RDRF + ORFE + TDRE)

    Ensemble des Instructions

    Mode d'adressage

    • Implied/Inherent : aucune donnée n'est nécessaire
    • Immediate : la donnée est dans l'instruction (1 ou 2 octets)
    • Direct : la donnée est dans l'octet suivant (1 octet, le poids fort est fixé à $00)
    • Extended : la donnée est dans les deux octets suivants (adresse 16 bits)
    • Indexed : la donnée est dans la mémoire, à l'adresse donnée par le registre d'index (opérande de 8 bits ajoutée à X)
    • Relative : la donnée est dans l'octet suivant, signée (pour les branchements)

    Instructions

    Opérations à pointeur Mnemonic Imm Dir Ind Ext Inh Operation HINZVC
    Compare Index Reg CPX X X X X X - M : M + 1 ..!!!!
    Decrement Index Reg DEX X X - 1-> X ...!..
    Decrement SP DES X SP - 1-> SP ......
    Increment Index Reg INX X X + 1-> X ...!..
    Increment SP INS X SP + 1-> SP ......
    Load Index Reg LDX X X X X M -> Xh, M+1 -> Xl ..!!0.
    Load SP LDS X X X X M -> SPh, M+1 -> SPl ..!!0.
    Store Index Reg STX X X X Xh -> M, Xl -> M+1 ..!!0.
    Store SP STS X X X SPh -> M, SPl -> M+1 ..!!0.
    Index to Stack TXS X X - 1 -> SP ......
    Stack to Index TSX X SP + 1 -> X ......
    Add B with X ABX X B + X -> B ......
    Push X PSHX X Xl->(SP),SP-1>SP,Xh... ......
    Pull X PULX X (SP)+1->SP,Xh->Xh,... ......
    Operations Acc. & Mémoire Mnemonic Imm Dir Ind Ext Inh Operation HINZVC
    Add Accumulators ABA X A + B -> A !.!!!!
    Add B to X ABX X 00:B + X -> X ......
    Add A with Carry ADCA X X X X A + M + C -> A !.!!!!
    Add B with Carry ADCB X X X X B + M + C -> B !.!!!!
    Add with A ADDA X X X X A + M -> A !.!!!!
    Add with B ADDB X X X X B + M -> B !.!!!!
    Add Double ADDD X X X X D + M:M+1 -> D ..!!!!
    And with A ANDA X X X X A & M -> A ..!!0.
    And with B ANDB X X X X B & M -> B ..!!0.
    Shift Left Arithmetic M ASL X X B7 dans C, C dans B0 ..!!!!
    Shift Left Arithmetic A ASLA X B7 dans C, C dans B0 ..!!!!
    Shift Left Arithmetic B ASLB X B7 dans C, C dans B0 ..!!!!
    Shift Left Arithmetic D ASLD X B15 dans C, C dans B0 ? ..!!!!
    Shift Right Arithmetic M ASR X X B0 dans C, B7 dans B7 ..!!!!
    Shift Right Arithmetic A ASRA X B0 dans C, B7 dans B7 ..!!!!
    Shift Right Arithmetic B ASRB X B0 dans C, B7 dans B7 ..!!!!
    Bit Test A BITA X X X X A & M, A non modifié ..!!0.
    Bit Test B BITB X X X X B & M, B non modifié ..!!0.
    Compare A/B with M CBA X A & B, A/B non modifié ..!!!!
    Clear Memory CLR X X 00 -> M ..0100
    Clear A CLRA X 0 -> A ..0100
    Clear B CLRB X 0 -> B ..0100
    Compare with A CMPA X X X X A - M ..!!!!
    Compare with B CMPB X X X X B - M ..!!!!
    1's Complement M COM X X ~M -> M ..!!01
    1's Complement A COMA X ~A -> A ..!!01
    1's Complement B COMB X ~B -> B ..!!01
    Decimal Adj. A DAA X Ajustement BCD ..!!!!
    Decrement M DEC X X M - 1 -> M ..!!!.
    Decrement A DECA X A - 1 -> A ..!!!.
    Decrement B DECB X B - 1 -> B ..!!!.
    Exclusive OR with A EORA X X X X A ^ M -> A ..!!0.
    Exclusive OR with B EORB X X X X B ^ M -> B ..!!0.
    Increment M INC X X M + 1 -> M ..!!!.
    Increment A INCA X A + 1 -> A ..!!!.
    Increment B INCB X B + 1 -> B ..!!!.
    Load to A LDAA X X X X M -> A ..!!0.
    Load to B LDAB X X X X M -> B ..!!0.
    Load to D LDD X X X X M:M+1 -> D ..!!0.
    Logical Shift Left M LSL X X B7 dans C, 0 dans B0 ..!!!!
    Logical Shift Left A LSLA X B7 dans C, 0 dans B0 ..!!!!
    Logical Shift Left B LSLB X B7 dans C, 0 dans B0 ..!!!!
    Logical Shift Left D LSLD X B15 dans C, 0 dans B0 ? ..!!!!
    Shift Right Logical M LSR X X B0 dans C, 0 dans B7 ..0!!!
    Shift Right Logical A LSRA X B0 dans C, 0 dans B7 ..0!!!
    Shift Right Logical B LSRB X B0 dans C, 0 dans B7 ..0!!!
    Shift Right Logical D LSRD X B0 dans C, 0 dans B15 ? ..0!!!
    Multiply MUL X A * B -> D .....!
    2's Complement M NEG X X -M -> M ..!!!!
    2's Complement A NEGA X -A -> A ..!!!!
    2's Complement B NEGB X -B -> B ..!!!!
    No Operation NOP X ......
    Logical OR with A ORAA X X X X A M -> A
    Logical OR with B ORAB X X X X B M -> B
    Push A PSHA X A -> (SP), SP - 1 -> SP ......
    Push B PSHB X B -> (SP), SP - 1 -> SP ......
    Pull A PULA X SP + 1 -> SP, (SP) -> A ......
    Pull B PULB X SP + 1 -> SP, (SP) -> B ......
    Rotate Left M ROL X X C dans B0, B7 dans C ..!!!!
    Rotate Left A ROLA X C dans B0, B7 dans C ..!!!!
    Rotate Left B ROLB X C dans B0, B7 dans C ..!!!!
    Rotate Right M ROR X X C dans B7, B0 dans C ..!!!!
    Rotate Right A RORA X C dans B7, B0 dans C ..!!!!
    Rotate Right B RORB X C dans B7, B0 dans C ..!!!!
    Subtract A with B SBA X A - B -> A ..!!!!
    Subtract with Carry with A SBCA X X X X A - M - C -> A ..!!!!
    Subtract with Carry with B SBCB X X X X B - M - C -> B ..!!!!
    Store A STAA X X X A -> M ..!!0.
    Store B STAB X X X B -> M ..!!0.
    Store D STD X X X D -> M:M+1 ..!!0.
    Subtract from A SUBA X X X X A - M -> A ..!!!!
    Subtract from B SUBB X X X X B - M -> B ..!!!!
    Subtract Double SUBD X X X X D - M:M+1 -> D ..!!!!
    Transfer A to B TAB X A -> B ..!!0.
    Transfer B to A TBA X B -> A ..!!0.
    Test Zero or Minus M TST X X M, M non modifié ..!!00
    Test Zero or Minus A TSTA X A, A non modifié ..!!00
    Test Zero or Minus B TSTB X B, B non modifié ..!!00
    Sauts et Branches Mnemonic Dir Rel Ind Ext Inh Test HINZVC
    Branch Always BRA X ......
    Branch Never BRN X ......
    Branch on Carry Clear BCC X C = 0 ......
    Branch on Carry Set BCS X C = 1 ......
    Branch on Equal BEQ X Z = 1 ......
    Branch on Greater or Equal BGE X N ^ V = 0 ......
    Branch on Greater BGT X (N ^ V) Z = 0
    Branch on Higher BHI X C + Z = 0 ......
    Branch on Higher or Same BHS X C = 0 ......
    Branch on Less or Equal BLE X (N ^ V) Z = 1
    Branch on Less than 0 BLT X N ^ V = 1 ......
    Branch on Minus BMI X N = 1 ......
    Branch on Not Equal BNE X Z = 0 ......
    Branch on Overflow Clear BVC X V = 0 ......
    Branch on Overflow Set BVS X V = 1 ......
    Branch on Plus BPL X N = 0 ......
    Branch to Subroutine BSR X ......
    Jump JMP X X ......
    Jump to Subroutine JSR X X X ......
    Return from Interrupt RTI X !!!!!!
    Return from Subroutine RTS X ......
    Software Interrupt SWI X !1!!!!
    Wait for Interrupt WAI X ......
    Manipulation des drapeaux Mnemonic Inh Operation HINZVC
    Clear Carry CLC X 0 -> C .....0
    Clear Interrupt CLI X 0 -> I .0....
    Clear Overflow CLV X 0 -> V ....0.
    Set Carry SEC X 1 -> C .....1
    Set Interrupt SEI X 1 -> I .1....
    Set Overflow SEV X 1 -> V ....1.
    Accumulator to CCR TAP X A -> CCR !!!!!!
    CCR to Accumulator TPA X CCR -> A ......

    Ports

    Port 1

    P10-P17 : entrées/sorties, 8 bits. Toutes les lignes sont configurables en entrée ou en sortie indépendamment.

    Port 2

    P20-P24 : entrées/sorties, 5 bits.

    • P20 et P21 déterminent le mode de fonctionnement du processeur (lors du reset)
    • Si P21 est configuré en sortie, il est lié à la fonction de comparison du timer
    • Peut être utilisé comme port série
    • Les lignes sont configurables en entrée ou en sortie indépendamment.

    Port 3

    P30-P37 : entrées/sorties, 8 bits. Adresses et données multiplexées. A0 à A7 et D0 à D7.

    Port 4

    P40-P47 : adressage de la mémoire externe, A8 à A15.

    Mémoire interne

    • 128 octets de RAM interne

    Timer programmable

    • Compteur ($09:$0A) : lecture seule. Une écriture dans $09 reset le compteur à $FFF8, à éviter.
    • Comparateur ($0B:$0C) : 16 bits, lecture/écriture. Lorsqu'il est égal au compteur, OCF est mis à 1.
    • Capture d'entrée ($0D:$0E) : lecture seule. Enregistre la valeur du compteur lorsqu'une transition est détectée, tel que définie par IEG.
    • Contrôle du Timer ($08) : lecture, écriture sur bits 0-4. Les bits de poids fort représentent l'état.

  • Sous le capot de l'Alice 32/90, un EF9345 ()

    La machine de la nouvelle session du « Retro Programmers United for Obscure Systems » est connue. C'est le Matra Alice. Et plus exactement les version 32 et 90, afin de s'échapper de la trop grande proximité entre le Alice premier du nom et le Tandy MC-10 (une telle proximité que ce sont les mêmes machines).

    Les versions 32 et 90 étant très similaires niveau hardware, je les nommerais conjointement Alice 32/90.

    Pour cet article, ce qui va m'intéresser est que l'Alice 32/90 utilise un EF9345, comme le VG5000. Et l'EF9345 étant aussi utilisé dans le VG5000µ, c'est une puce que je connais bien. Cependant, l'Alice 32/90 l'utilise différemment. Je dirais même qu'il l'utilise mieux.

    L'autre axe de cet article est que je veux utiliser l'EF9345 depuis le BASIC. La machine tournant avec un 6803, les I/O sont mappées en mémoire. Et il est donc possible d'accéder aux registres de l'EF9345 depuis le BASIC avec des PEEKs et POKEs. Pas besoin de passer par l'assembleur. Par contre, pas de mystère, c'est lent !

    Le mode graphique en BASIC sur l'Alice

    Première chose amusante, l'Alice 32/90 démarre dans un mode 32 colonnes qui n'existe pas pour l'EF9345. Je pense que ce mode par défaut, qui utilise en fait le mode 40 colonnes de l'EF9345, est là pour être compatible avec le Alice 4k au niveau BASIC. Pour assurer cette compatibilité, des caractères utilisateurs sont chargés dans la RAM vidéo au démarrage pour représenter les différentes combinaison d'un bloc de 2x2 « gros pixels » pour chaque caractère.

    L'Alice 32/90 peut cependant utiliser l'EF9345 en vrai mode 40 colonnes, et même en mode 80 colonnes. Pour cela passer d'un mode à l'autre, il faut utiliser les commandes CLS32, CLS40 et CLS80. Je vais me concentrer sur le mode 40 colonnes.

    Celui-ci est initialisé dans le mode « 40 CHAR LONG ». C'est un mode qui prend trois pages de 1Ko en mémoire vidéo. La première page contient les caractères, la deuxième les attributs et la troisième les couleurs. Ça fait beaucoup sur les 8ko de RAM vidéo de la machine, et le VG5000µ avait fait le choix d'utilise le mode « 40 CHAR SHORT » qui ne prend que 2ko. Cependant, on y gagner en simplicité et flexibilité au niveau des attributs.

    Autre choix de l'Alice : le système ne conserve pas de miroir en RAM de l'affichage. Là encore, bon choix pour l'utilisation de la RAM principale. En contrepartie cela signifie que les opérations non prévues par le BASIC devront se faire en s'adressant directement à l'EF9345.

    Plus techniquement, le mode est initialisé avec les registres suivants :

    - TGS = 0x10 (binaire: 00010000) -> 312 lignes non entrelacées, synchro composite, pas de synchro entrante, service row = 0, 40 Char Long
    - MAT = 0x28 (binaire: 00101000) -> couleur de marge noire, curseur complet clignotant, curseur désactivé (!), simple hauteur
    - PAT = 0x67 (binaire: 01100111) -> service row visible, bulk haut et bas visible, conceal désactivé, flash activé
    - DOR = 0x13 (binaire: 00010011) -> page G'0 située en Z = 3, page G'10 située en Z = 2, page Q située en Z = 0
    - ROR = 0x08 (binaire: 00001000) -> première ligne bulk = 8, page d'origine Z = 0
    

    Les registres de l'EF9345

    Depuis le processeur, l'EF9345 est accessible via 8 registres. Ces registres sont accessibles en lecture et écriture, et sont tous des registres de 8 bits. Ils sont accessibles via les adresses suivantes :

    - R0 = $BF20 ; 48928 (commande)
    - R1 = $BF21 ; 48929 (paramètre principal)
    - R2 = $BF22 ; 48930 (paramètre)
    - R3 = $BF23 ; 48931 (paramètre)
    - R4 = $BF24 ; 48932 (pointeur auxiliaire haut)
    - R5 = $BF25 ; 48933 (pointeur auxiliaire bas)
    - R6 = $BF26 ; 48934 (pointeur principal haut)
    - R7 = $BF27 ; 48935 (pointeur principal bas)
    

    Une adresse supplémentaire est située en $BF28 (48936). Il s'agit en fait de R0 mais avec le flag d'exécution (bit 7 du numéro de registre) mis à 1. Cela permet de demander à l'EF9345 d'exécuter la commande indiquée dans R0.

    Techniquement, n'importe quel registre peut être utilisé pour exécuter une commande en mettant le bit 7 à 1. Cela permet d'ailleurs quelques optimisations. Je n'ai pas vérifié si les adresses au delà de $BF28 étaient mappées. Si ce n'est pas le cas, on n'utilisera pas, voire jamais, R0 directement en écriture directement, mais toujours via le « faux registre » R8.

    Note additionnel : le livre "les astuces d'Alice 32 et 90" indique qu'il est en effet possible d'utiliser tous les registres en mode « exécution ».

    Un premier affichage

    Voici un programme qui place tous les registres directs correctement pour afficher un « A » à l'écran sur la ligne 0 (ligne de service), colonne 10. Notez que cela fonctionnera parfaitement en mode CLS32. Vous pouvez vous amuser à écrire où vous voulez dans l'espace de 40 colonnes par 25 lignes pour constater que le mode 32 colonnes est en fait le mode 40.

    Attention, dans cette configuration de l'EF9345, la deuxième ligne affichée est la ligne... numéro 8.

    100 REM AFFICHE UN CARACTERE
    110 POKE 48928, 0   : REM R0 (COMMANDE) KRF / INUTILE
    120 POKE 48929, 65  : REM R1 (C)
    130 POKE 48930, 0   : REM R2 (B)
    140 POKE 48931, 20  : REM R3 (A)
    150 POKE 48932, 0   : REM R4 (NA pour KRF)
    160 POKE 48933, 0   : REM R5 (NA pour KRF)
    170 POKE 48934, 0   : REM R6 (MP / LIGNE)
    180 POKE 48935, 10  : REM R7 (MP / COL)
    190 POKE 48936, 1   : REM R0 + EXEC (KRF)
    

    Une démonstration plus complète

    Voici un programme de démonstration plus complet, mais pas entièrement, puisqu'il y a plein de choses à faire avec l'EF9345 qui ne sont pas démontrées ici.

    Attention : je n'ai pas du tout testé sur vrai matériel. L'EF9345 étant sensible aux synchronisations (on ne peut pas lui parler n'importe quand), je ne sais pas à quel point le BASIC est capable de gérer cela. Il est possible que ce programme ne fonctionne pas bien sur vrai matériel. Je suis preneur de retours (et j'essaierai moi même un de ces jours).

    Voici quelques commentaires :

    • En ligne 100, on initialise les registres nécessaires pour afficher une chaîne de caractère utilisant les mêmes attributs.
    • En ligne 200, on initialise les registres restants pour afficher un caractère et passer à la colonne suivante (attention, il n'y a pas de détection de fin de ligne).
    • En ligne 300, on initialise tous les registres pour afficher un caractère avec des attributs différents. Dans les commentaires KRF est le nom de la commande d'affichage d'un caractère en mode « 40 CHAR LONG ».
    • En ligne 400, une routine se charge de monter en mémoire vidéo les données pour un caractère utilisateur.
    • En ligne 10000, c'est le début du test et j'affichage "BONJOUR". C'est un PRINT en bien plus compliqué et bien plus lent...
    • En ligne 10100, j'affiche les 128 caractères alphanumériques en ROM de l'EF9345.
    • En ligne 10200, j'affiche une autre plage de 32 caractères, graphiques, en ROM de l'EF9345.
    • En ligne 10300, j'affiche les 128 caractères semi-graphiques en ROM de l'EF9345. Dans ces trois affichages, c'est la variable B qui indique le type de caractères à utiliser.
    • En ligne 10400, j'affiche un caractère graphique plein pour montrer les 16 teintes disponibles pour les caractères.
    • En ligne 11000, je tente de lire les registres indirects de l'EF9345. Cela ne fonctionne pas tout à fait bien. Possible que ce soit un problème de synchro (d'où la petite boucle, même si 1/ ce n'est pas comme cela qu'on synchronise l'EF9345 2/ la lenteur du BASIC me fait penser que quoique l'on fasse, il y a toujours un risque de tomber au mauvais moment).
    • En ligne 12300, je modifie le registre indirect ROR afin de faire un scrolling vertical. Comme la mémoire « sous » l'écran n'est pas préparée, cela affiche un peu n'importe quoi. C'est surtout une démonstration de l'utilisation de registre indirect en écriture.
    • En ligne 13000, je charge un caractère utilisateur (le bonhomme du manuel du VG5000µ) puis j'affichage un des « sets » de caractères redéfinis. Particularité : c'est un ensemble de 100 caractères allant de 0 à 3, puis de 32 à 127... L'adresse de destination A=192 est aussi assez compliquée à calculer (en tout cas, ça ne s'invente pas, et le datasheet demande une grande attention, je ferai peut-être un article séparé là-dessus). Dans les caractères affichés, vous verrez les blocs redéfinis pour la compatibilité avec l'Alice 4k.

    Pour la manière dont fonctionne la mémoire de l'EF9345, en attendant un article, vous pouvez tentez de comprendre avec le code du fichier ef9345_memory.py dans mon dépôt GitHub dédié aux outils d'étude pour le VG5000µ.

    10 CLS:GOTO 10000
    
    100 REM PREPARATION AFFICHAGE CARACTERE
    110 POKE 48930,B
    120 POKE 48931,A
    130 POKE 48934,Y
    140 POKE 48935,X
    150 RETURN
    
    200 REM AFFICHE UN CARACTERE AVEC INCREMENTATION
    210 POKE 48929,C
    220 POKE 48936,1:REM KRF + INCR
    230 RETURN
    
    300 REM AFFICHE UN SEUL CARACTERE COMPLET
    310 POKE 48929,C
    320 POKE 48930,B
    330 POKE 48931,A
    340 POKE 48934,Y
    350 POKE 48935,X
    360 POKE 48936,0:REM KRF
    370 RETURN
    
    400 REM CHARGEMENT D'UN CARACTERE REDÉFINI
    410 FOR I=1 TO 10
    420 READ C
    430 POKE 48932,INT(A/256)
    440 POKE 48933,A AND 255
    450 POKE 48929,C
    460 POKE 48936,48+4:REM OCT + AUX_PTR (EXEC)
    470 A=A+4
    480 NEXT I
    490 RETURN
    
    10000 REM PROGRAMME DE TEST
    10010 X=5:Y=0 : REM COORDONNEE
    10020 B=0:A=20 : REM ATTRIBUTS
    10030 A$="BONJOUR"
    10040 GOSUB 100
    10050 FOR I=1 TO LEN(A$)
    10060 C=ASC(MID$(A$,I,1))
    10070 GOSUB 200
    10080 NEXT I
    
    10100 REM AFFICHAGE DE CARACTERES
    10110 Y=8:X=0:B=0:A=112
    10120 FOR C=0 TO 127
    10130 IF X>39 THEN X=0:Y=Y+1
    10140 X=X+1
    10150 GOSUB 300
    10160 NEXT C
    
    10200 Y=12:X=0:B=48:A=112
    10210 FOR C=0 TO 31
    10220 GOSUB 300
    10230 X=X+1
    10240 NEXT C
    
    10300 Y=13:X=0:B=32:A=112
    10310 FOR C=0 TO 127
    10320 IF X>39 THEN X=0:Y=Y+1
    10330 GOSUB 300
    10340 X=X+1
    10350 NEXT C
    
    10400 REM COULEURS
    10410 Y=17:X=0:B=32:C=127
    10420 FOR A=16 TO 112 STEP 16
    10430 GOSUB 300
    10440 X=X+1
    10450 NEXT A
    10460 Y=18:X=0:B=33
    10470 FOR A=16 TO 112 STEP 16
    10480 GOSUB 300
    10490 X=X+1
    10500 NEXT A
    
    11000 REM LECTURE DES REGISTRES INDIRECTS
    11010 POKE 48936,128+8+1:REM IND + LECTURE + TGS (EXEC)
    11020 T=PEEK(48929):REM LECTURE R1
    11030 PRINT"TGS=";T:FOR I=0 TO 20:NEXT I
    11040 POKE 48936,128+8+2:REM IND + LECTURE + MAT (EXEC)
    11050 M=PEEK(48929):REM LECTURE R1
    11060 PRINT"MAT=";M:FOR I=0 TO 20:NEXT I
    11070 POKE 48936,128+8+3:REM IND + LECTURE + PAT (EXEC)
    11080 P=PEEK(48929):REM LECTURE R1
    11090 PRINT"PAT=";P:FOR I=0 TO 20:NEXT I
    11110 POKE 48936,128+8+5:REM IND + LECTURE + DOR (EXEC)
    11120 D=PEEK(48929):REM LECTURE R1
    11130 PRINT"DOR=";D:FOR I=0 TO 20:NEXT I
    11140 POKE 48936,128+8+7:REM IND + LECTURE + ROR (EXEC)
    11150 R=PEEK(48929):REM LECTURE R1
    11160 PRINT"ROR=";R
    
    12300 REM CHANGE ROR POUR SCROLLING
    12310 FOR I=8 TO 31
    12320 POKE 48929,I:REM ECRITURE R1
    12330 POKE 48936,128+0+7:REM IND + ECRITURE + ROR (EXEC)
    12340 FOR J=0 TO 20:NEXT J
    12350 NEXT I
    12360 POKE 48929,8:REM ECRITURE R1
    12370 POKE 48936,128+0+7:REM IND + ECRITURE + ROR (EXEC)
    
    13000 REM CARACTERES REDÉFINIS
    13010 DATA 28,58,28,8,127,93,93,28,54,99
    13020 A=192
    13030 GOSUB 400
    
    13100 Y=20:X=0:B=128+32+16:A=112:REM GP11
    13110 FOR C=0 TO 127
    13120 IF X>39 THEN X=0:Y=Y+1
    13125 IF C=4 THEN C=32
    13130 GOSUB 300
    13140 X=X+1
    13150 NEXT C
    
    14000 GOTO 14000
    

  • Dans la prison hantée sur AgonLight ()

    Comme présenté dans un article précédent, j'ai participé à la game jam Retro Programmers United for Obscure Systems, organisée par Olipix. Le principe est de développer un jeu pour une machine qui n'a pas eu une grande ludothèque (moins de 100 titres).

    Après avoir terminé ma contribution sur le Lynx, je me suis dit qu'un portage pour l'AgonLight serait intéressant et plutôt facile. Les capacités graphiques sont bien supérieures, et le processeur est un Z80, supporté par la même toolchain que j’avais utilisée pour le Lynx (z88dk).

    Un petit mois plus tard, c'est chose faite. Le jeu est disponible sur itch.io.

    J'en ai profité pour ajouter une version en anglais et une version en esperanto. Puisque tout est développé depuis les mêmes sources, ces versions sont aussi disponibles sur le Lynx.

    Au passage, la taille de l'exécutable a été un tout petit peu réduite. Pas assez pour entrer sur la version Lynx 48k malheureusement. Et en projetant le gain potentiel en travaillant la compression des données, j'ai assez peu d'espoir d'y arriver. Cela pourrait probablement être possible en reprogrammant le jeu en assembleur, mais j'ai déjà passé assez de temps sur ce projet et j'ai envie de passer à autre chose. De plus, je perdrai la possibilité d'un portage facile sur une machine avec un autre processeur.

    J'ai aussi publié les sources du jeu sur GitHub.

    À bientôt pour de nouvelles aventures !

    Dans la prison hantée sur AgonLight2


  • VG5000µ, Schémas de principe mis à jour en v1.5 ()

    Et voici une nouvelle mise à jour du schéma de principe.

    Il y a une seule modification par rapport à la version 1.4, qui est l'ajout du mode international lorsque la diode 6602 relie le signal NMI/ au Y3/ de 7807. Avec cette diode présente, le VG5000µ passe en anglais.

    Merci à Etno pour cette information.

    Ce qui donne, mis à jour.

    La platine principale

    Image cliquable pour une version en haute définition. (mise à jour 21 novembre 2023)

    Platine principale

    La platine K7/Son

    Image cliquable pour une version en haute définition. (mise à jour 9 sept. 2018)

    Platine K7/Son

    Rappel des versions précédentes


  • Un an de Retro Programmers United for Obscure Systems ()

    Un peu plus d'un an en fait, puisque Olipix lance ce groupe en juin 2022. L'idée, je le rappelle, est d'offrir à des machines qui en leur temps n'ont pas eu une grande ludothèque quelques titres supplémentaires, dans un format game jam de trois mois (souvent étendus à quatre).

    Dans cet article, je vais revenir rapidement sur les 4 jeux que j'ai développés à cette occasion, avec quelques commentaires.

    VG5000µ : La Maison dans la colline

    La première machine choisie a été le VG5000µ, une machine que, vous le savez si vous suivez ce blog, j'étudie depuis un moment. Pour un premier développement réel (autre que des tests), je voulais un affichage rapide, mais sans aller dans un jeu rapide. L'idée du jeu d'aventure graphique avec support de texte est arrivée rapidement.

    J'ai commencé ici une série d'articles sur le développement du jeu.

    Le jeu est développé avec z88dk, en C avec un peu d'assembleur pour l'affichage. J'ai aussi réalisé tous les graphismes (et ça se voit ?) avec Pixelorama. Pour les outils de données, c'est du Python avec un fichier de description du jeu, qui sort les données binaires injectées dans l'exécutable.

    Le jeu est disponible sur itch.io.

    Olipix fait une revue du jeu dans cette vidéo.

    La maison dans la colline

    EXL100 : Plouf... in space

    La deuxième machine choisie a été l'EXL100, une machine que je ne connaissais pas du tout. Et une machine plutôt exotique. Un processeur que je ne connais pas, l'essentiel de la mémoire utilisable non adressable par le processeur... et un synthétiseur vocal plutôt difficile à utiliser.

    J'avais quelques idées pour utiliser la machine, mais j'ai rapidement compris que le temps de me familiariser avec et de faire des tests, je n'aurais pas le temps de faire un jeu. J'ai donc changé d'avis et suis partie sur un jeu programmé en BASIC, qui permet facilement d'utiliser toute la mémoire. Et pour le type de jeu, un touché-coulé, mais avec un twist : les bateaux sont en mouvement. Je n'étais pas très certain que le gameplay donne quelque chose, mais au final et après quelques ajustements, ça fonctionne plutôt bien.

    Sur la fin, les calculs en BASIC commençaient à être un peu lents, et j'ai donc ajouté un peu d'assembleur dans le peu de mémoire adressable par le processeur. J'ai utilisé l'assembleur ASL qui est un des rares supportant le TMS7020. J'y associe un petit script en Python pour générer les DATA pour le BASIC. C'était assez manuel, je n'aime pas trop ça, mais comme souvent : manque de temps pour des choix assez tardifs.

    Puis les bateaux sont devenus des vaisseaux parce que... parce que.

    Je voulais aussi redéfinir quelques caractères pour un affichage plus sympa, mais je n'ai pas eu le temps. Peut-être un jour si je ressors l'idée ?

    Le jeu est disponible sur itch.io.

    Olipix fait une revue du jeu dans cette vidéo, dans laquelle nous avons aussi discuté du développement du jeu.

    Plouf... in space

    Aquarius : Le jardin des œufs

    La troisième machine a été l'Aquarius. Retour à du Z80 qui m'est familier. Et une machine simple. Dépouillée même. L'avantage pour le graphisme, c'est qu'il faut faire avec les caractères de la machine. Heureusement, un éditeur dédié à la machine est disponible en ligne, ce qui a bien simplifié les choses.

    Comme la fin de la game jam était autour de Pâques, j'ai voulu faire thématique avec une chasse au œufs. Dans la lignée des anciens jeux avec des plateformes qui n'ont pas vraiment de sens, j'ai designé un jardin étrange, avec quelques éléments de game design classiques.

    Dans tous ces jeux, je pars d'un principe : les joueurs de retro n'ont souvent pas vraiment de temps à passer sur ces machines, particulièrement celles qui ne sortent jamais. Je vise donc des jeux courts, quelque chose qui puisse se découvrir et se terminer en une vingtaine de minutes. Quitte à se qu'il se termine en moins de 5 minutes lorsque l'on connaît la solution.

    Puisque le jeu se termine rapidement, j'ai ajouté un compteur de mouvements, avec d'y associer une sorte de time attack... mais sans temps.

    Le jeu est entièrement en assembleur, utilisant sjasmplus, un assembleur que j'avais essayé auparavant et que je voulais creuser un peu plus. C'était l'occasion. Un jeu tout en assembleur, ça prend un peu plus de temps à développer, par contre, question mémoire, ça permettait de faire petit. Et encore, il y a de la marge d'optimisation.

    Le jeu est disponible sur itch.io.

    Olipix fait une revue du jeu dans cette vidéo.

    Le jardin des œufs

    Camputers Lynx : Dans la prison hantée

    Une nouvelle session, et une nouvelle machine sortie de nulle part. J'avais connaissance de la machine, mais je ne m'étais jamais penché dessus et... quel étonnement. Cette machine a été conçue avec des choix originaux. C'est du Z80, bon point pour moi. La partie vidéo est aussi très intéressante avec des pixels indépendants en couleur les uns des autres. Une rareté pour l'époque. Bien entendu, je me dis qu'il faudra absolument utiliser cette particularité.

    J'ai passé un bon moment sur la machine sur des tests variés. Les limitations d'accès à la RAM, avec un mapping vraiment pas simple, et des émulateurs pas très aboutis m'ont fait désespérer une paire de fois. J'ai souvent mis le projet sur le côté.

    Pour le jeu, je voulais aller du côté de Temple of Apshaï, un jeu qui m'avait marqué étant petit. Comme d'habitude, dans une formule courte. Vu tout le temps passés à faire des tests et à procrastiner, j'ai aussi fait le choix d'utiliser un set de sprites désigné par Kenney. Sur base d'un set noir et blanc, j'ai ajouté un peu de couleurs, puisque je voulais utiliser les capacités de la machine en la matière.

    Initialement, j'étais parti sur la réutilisation du format et des scripts de la Maison dans la Colline. Cependant, j'avais un peu luté avec le côté semi-manuel de la méthode. J'ai donc décidé d'utiliser Tiled pour la conception des niveaux, et un script Python pour générer les données. Tiled est vraiment sympa à utiliser et je pense que je le réutiliserai dans le futur pour des projets similaires.

    Pour le code, j'ai utilisé z88dk avec un peu d'assembleur pour l'affichage, mais beaucoup moins que pour le VG5000µ. Je voulais réutiliser le principe d'affichage rapide, mais les émulateurs Lynx ne supportent pas (encore ?) la redirection du vecteur d'interruption pour la VSYNC. J'ai rapidement fait une croix dessus. N'ayant pas accès à cette machine, je devais absolument faire avec les émulateurs.

    Aussi, rapidement, j'ai compris que le jeu n'entrerais pas en mémoire de la version 48k, mais uniquement sur la version 96k (cela semble beaucoup, mais de cette mémoire, 32ko sont réservés pour la vidéo).

    Le jeu est disponible sur itch.io.

    Retro VynZ a fait une partie filmée sur sa chaîne YouTube.

    Olipix présente le jeu, suivi d'un petit échange sur sa chaîne YouTube.

    Dans la prison hantée

    Et la suite ?

    J'ai passé de bons moments sur ces projets. Découvrir ces machines est un plaisir (même si elles sont parfois un peu énervantes), cela profite un peu (un tout petit peu) à leur visibilité, à leur redécouverte. Et si ça n'amuse que nous, c'est déjà ça.

    Je ne connais pas encore la prochaine machine, je ne sais donc pas vers où je vais aller, mais j'ai en tête deux défis : utiliser un peu plus de couleurs et, pour la première fois, ajouter du son !

    À bientôt pour de nouvelles aventures !


Page 1 / 20 (suivant) »