;*************************************************************************************** ;* L’interface MDCR * ;* ================ * ;* * ;* Le port B est programmé en OUTPUT ($FE01) * ;* ================================== * ;* * ;* - Les bits 0, 4, 5, 6, 7 sont utilisés pour le décodage d’adresse. * ;* - Les bits 2 et 3 déterminent le N° du MDCR qui peut aller de 1 à 4 * ;* - Le bit 1 permet d’activer le MDCR * ;* - 0 ==> MDCR désactivé * ;* - 1 ==> MDCR activé * ;* * ;* Le port A est programmé en INPUT ($FE00) * ;* ======================================== * ;* ___ ___ ___ ___ * ;* | RDC | WEN | CIP | xxx | xxx | xxx | BET| RDA | * ;* ************************************************* * ;* * ;* Le port CL est programmé en OUTPUT ($FE02) * ;* Le port CH est programmé en INPUT ($FE02) mais non utilisé * ;* ================================== * ;* ___ ___ ___ ___ * ;* | xxx | xxx | xxx | xxx | WCD | WDA | FWD | REV | * ;* ************************************************* * ;* * ;* Signification des signaux : * ;* ========================= * ;* * ;* RDC : Read Clock = signal d’horloge généré séparément comme strobe pour /RDA * ;* ___ * ;* WEN :(Write Enable = 0) ==> autorisation d’écrire (plug présent) * ;* ___ * ;* CIP :(Cassette In Place = 0) ==> cassette présente * ;* ___ * ;* BET :(Begin or End of Tape = 0) ==> début ou fin de bande détecté * ;* ___ * ;* RDA : Read Data ==> lecture des données sur bande (bit par bit) * ;* ___ * ;* WDA : Write Data ==> écriture des données sur bande (bit par bit) * ;* ___ * ;* WCD : Write Command ==> permet l’écriture via /WDA (provoque l’enregistrement) * ;* ___ * ;* FWD : Forward ==> défilement de la bande en avant * ;* ___ * ;* REV : Reverse ==> défilement de la bande en arrière * ;* * ;* Le mot de contrôle ($FE03) est programmé avec la valeur $98 * ;* =========================================================== * ;* * ;* | 1 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | * ;* ************************************************* * ;* C'est par lui qu'on programe les ports A, B, CL, CH dans les configurations voulues * ;* * ;* ________ * ;* | | * ;* | | 8 * ;* | A |<-----/------ PA7-PA0 * ;* | | * ;* | 82C55A | 4 * ;* | --|<-----/------ PC7-PC4 * ;* | | | * ;* D7-D0 <----->| C-| | * ;* | | | 4 * ;* | --|------/-----> PC3-PC0 * ;* | | * ;* | | 8 * ;* | B |------/-----> PB7-PB0 * ;* | | * ;* |________| * ;*************************************************************************************** ;* * ;* LES NOUVELLES ADRESSES EN RAM * ;* ============================= * ;* Les adresses ci-dessous sont des adresses de SPARE au niveau du DAI, c'est à dire * ;* qu'elles peuvent être utilisées pour de nouvelles extensions, c'est le cas ici avec * ;* le MDCR. * ;* * ;* $120 : ERRCO * ;* = 0 ==> On autorise l'affichage des erreurs * ;* <> 0 ==> Le code erreur est stocké dans (ERRCO) (après chaque commande * ;* VER, LOAD, ETC) * ;* Attentio dans la phras ci-dessus "(ERRCO)" = adr. indirect * ;* * ;* $11F : DCRSL * ;* 0 si MDCR N°0 * ;* 1 si MDCR N°1 * ;* 2 si MDCR N°2 * ;* 3 si MDCR N°3 * ;* * ;* $1B0 : FILES !!!! Attention,ce n'est pas une adresse de SPARE, elle empiète sur la * ;* fin de EBUF (CF memory map du DAI dans le firmware manual) !!! * ;* Cette adresse set à indiquer le nombre de fichiers utilisés dans les * ;* commandes telles que SKIP etc * ;* En pratique, on ne peut entrer au clavier une commande comme REW 15 * ; car le DTOS ne permet que les valeurs entre 0 et 9 ! On peut s'en * ; sortir via POKE #1B0, 20 par exemple qui permet un REW 20 * ;* * ;* $297 : TABLE * ;* En $297 et $298 sera stockée l'adresse de la table TABCMD c'est à dire * ;* $F786. Autrement dit après initialisation, $297 contiendra $86 et * ;* $298 contiendra $F7. * ;* Ceci permet à un programme quelconque de récupérer les différentes * ;* adresses des routines implémentant les différentes commandes du MDCR * ;* sans avoir à les coder en dur dans le code... C'est du luxe, on * ;* on devrait pouvoir se passer de cette table * ;* * ;* $299 : RSP * ;* Le pointeur de pile est stocké ici pendant l'exécution de la commande * ;* * ;* $2E3 : DINC * ;*************************************************************************************** ;* ;*********************************************************** ;* Adoption des mnémoniques utilisés dans la documentation * ;* MANUAL FOR THE MEMOCOM MDCR-D * ;* A partir du BASIC les deux exemple de commandes sont * ;* équivalents : * ;* 10 CALLM #F000:REM LAST * ;* 10 CALLM #F01B * ;* quelques exemples de commandes pour comprendre * ;* Sauter 20 fichiers * ;* ================== * ;* 10 POKE #1B0, 20 * ;* 15 CALLM #F015 * ;* Supprimer la sortie de erreurs * ;* ============================== * ;* 10 CALLM #F003,ERR% * ;* ==> utilisation de la deuxième forme du CALLM, * ;* CALLM I,V provoque l'exécution du pgr se trouvant en * ;* mémoire à l'adresse spécifiée par I et HL est chargé * ;* l'adresse mémoire de la variable V !!! * ;*********************************************************** ;* F000 C321F0 JMP $F021 ; REMS = exécute les commandes derrière un REM F003 C3B6F6 JMP $F6B6 ; ONERR = initialise ON ERROR F006 C3BFF6 JMP $F6BF ; NONERR = désactive ON ERROR F009 C348F3 JMP $F348 ; OPEN = Ouvre le DCR spécifié F00C C366F5 JMP $F566 ; DCR = Selection du DCR F00F C37BF5 JMP $F57B ; CAS = Selection de la cassette F012 C3D6F5 JMP $F5D6 ; CRWND = commande REWIND 'F' fichiers F015 C33DF6 JMP $F63D ; CSKIP = Commande SKIP 'F' fichiers F018 C3E2F6 JMP $F6E2 ; CVER = Commande verify F01B C3B8F5 JMP $F5B8 ; CLAST = Commande LAST F01E C35DF7 JMP $F75D ; CLOOK = commande look ;* F = tout nombre entre 0 et 255 ;* ;****************************************** ;* Exécute les commandes derrière un REM * ;****************************************** ;* ;******** ;* REMS * ;******** ;* F021 F5 PUSH PSW F022 C5 PUSH B F023 D5 PUSH D F024 E5 PUSH H F025 210A00 LXI H $A F028 39 DAD SP ; On ajoute 10 à SP et on met le tout en $299 F029 229902 SHLD $299 ; pendant l'execution de la commande on sauve le pointeur ; de pile dans la variable RSP F02C A LDAX B F02D FEA9 CPI $A9 ; Code BASIC semi-compilé de la commande REM F02F C24DC1 JNZ $C14D ; Effectue le POP H, POP D, POP B et RET ==> Pas de REM ==> on sort F032 3 INX B ; Pointeur sur le nb de caractères F033 A LDAX B F034 3C INR A ; A = nombre de caractères + 1 F035 323401 STA $134 ; On stocke le nb de car en $134 F038 60 MOV H.B F039 69 MOV L.C ; HL <-- BC F03A 223201 SHLD $132 ; EFEPT. Pointeur sur la ligne de BASIC venant juste d'être encodée F03D 3E01 MVI A $1 F03F 323501 STA $135 ; EFSW. 1 = Entrée à partir d'une chaîne F042 4F MOV C.A F043 CDA7F0 CALL $F0A7 ; Recherche de la commande CALL RCMD F046 AF XRA A ; A <-- 0 F047 323501 STA $135 ; 0 = Entrée à partir du clavier F04A 329A02 STA $29A ; ($29A) <-- 0 F04D D DCR C F04E CA0BDA JZ $DA0B ; Si C=0 ==> GOTO ERRSN = Exécute 'SYNTAX ERROR' F051 C34DC1 JMP $C14D ; GOTO EXIT <==> {POP H puis POP D puis POP B puis POP PSW et enfin RET} ;* ;***************************** ;* Entrée depuis le clavier * ;***************************** ;* ;********** ;* DINKBD * ;********** ;* F054 E5 PUSH H F055 211701 LXI H $117 ; RDIPF Flag set while running imput (set: #FF). (CF firmware manual). F058 7E MOV A.M ; On met dans A la valeur de DIPF F059 23 INX H ; H contient maintenant l'adresse de RUNF ($118) Flag set while running program. F05A B6 ORA M ; Ou logique entre RDIPF et RUNF F05B 6F MOV L.A ; On sauve A dans L F05C 3A3101 LDA $131 ; On charge A avec le contenu de OTSW (CF firmware manual). F05F E6FE ANI $FE ; Mise à 0 du bit 0 F061 B5 ORA L ; Ou logique entre RDIPF, RUNF, "From edit buffer to program area" F062 E1 POP H ; restaure H F063 C280F0 JNZ $F080 ; ? F066 CD80F0 CALL $F080 ; ? F069 F5 PUSH PSW F06A FE0D CPI $D F06C CA8BF0 JZ $F08B ; Si CR ==> Fin de la commande F06F FE09 CPI $9 F071 C27EF0 JNZ $F07E ; Si pas de touche TAB F074 3E0C MVI A $C ; Sinon on efface l'écran F076 CD95D6 CALL $D695 ; en cas de touche TAB appuyée <==> PRINT CHR$(12) F079 3E2A MVI A $2A ; Code ASCII de "*" F07B CD95D6 CALL $D695 ; Afficher "*" F07E F1 POP PSW F07F C9 RET ;* ;********************* ;* Commande suivante * ;********************* ;* F080 3A9602 LDA $296 ; A <-- INSW (0 = input via clavier <>0 input from DINC) F083 E601 ANI $1 F085 CAE2D1 JZ $D1E2 ; Lecture clavier teste si une touche est appuyée F088 C3E302 JMP $2E3 ; saut en $DDB4 cf routine d'init en $F4D4 ;* ;************************************* ;* RETOUR BASIC (Fin de la commande) * ;************************************* ;* F08B 35 DCR M ; Le contenu de la mémoire dont l'adresse est contenue dans HL ; est décrémenté de 1 F08C F1 POP PSW F08D 218FC8 LXI H $C88F ; GOTO ENDCOM F090 E3 XTHL F091 210000 LXI H $0 F094 39 DAD SP F095 229902 SHLD $299 ; pendant l'executionde la commande on sauve le pointeur ; de pile dans la variable RSP F098 E01 MVI C $1 F09A D5 PUSH D F09B CDA7F0 CALL $F0A7 ; Recherche de la commande CALL RCMD F09E D1 POP D F09F E1 POP H F0A0 AF XRA A F0A1 329A02 STA $29A F0A4 C345DD JMP $DD45 ; GOTO EXIT1 <==> {POH puis POP PSW puis CMC pui RET} ; CY est complémenté avant le RET suivant EXIT1 ;* ;***************************** ; Recherche de la commande * ;***************************** ;* ;* ;******** ;* RCMD * ;******** ;* F0A7 2A9702 LHLD $297 ; On met dans HL l'adresse de CMDTAB c'est à dire $F786 au bout du compte ! F0AA 1E01 MVI E $1 ; CF documentation firmware Manual en $CA34 (LOOKC) F0AC 7C MOV A.H F0AD B5 ORA L F0AE C8 RZ ; Si l'adresse de TBCMD n'est pas en $297, on sort... F0AF C5 PUSH B F0B0 CD34CA CALL $CA34 ; Réutilisation de la routine du BIOS LOOKC ; "FIND STRING BASIC INSTRUCTION IN TABLE" ici on va rechercher ; l'entrée de la table qui correspond à la chaîne de la ligne courante ; CF description firmware Manual en $CA34 (LOOKC) F0B3 DABEF0 JC $F0BE ; F0B6 C1 POP B F0B7 7E MOV A.M F0B8 23 INX H F0B9 66 MOV H.M F0BA 6F MOV L.A F0BB C3AAF0 JMP $F0AA F0BE 5E MOV E.M F0BF 23 INX H F0C0 56 MOV D.M F0C1 CDCDF0 CALL $F0CD F0C4 79 MOV A.C F0C5 C1 POP B F0C6 4F MOV C.A F0C7 21A7F0 LXI H $F0A7 F0CA E5 PUSH H F0CB EB XCHG F0CC E9 PCHL F0CD CDD2DD CALL $DDD2 ; Get character from line = CALL IGNB cf firmware manual F0D0 CD0DDE CALL $DE0D ; Compare la valeur de A à la valeur immédiate $30 F0D3 DAD9F0 JC $F0D9 ; Si A < $30 GOTO $F0D9 F0D6 3E2F MVI A $2F ; Sinon on met 47 (décimal) dans A F0D8 D DCR C ; ****** CONTINUER A DECODER ICI ****** F0D9 C INR C ; ****** MAIS VISIBLEMENT CECI VA ABOUTIR **** F0DA D630 SUI $30 ; ****** A STOCKER LE NB de FICHIERS à TRAITER DANS *** F0DC 32B001 STA $1B0 ; FILES F0DF CDD2DD CALL $DDD2 ; CALL IGNB. Get Char from line F0E2 C INR C F0E3 FE3A CPI $3A ; Test le ":" F0E5 C8 RZ ; Retour si ":" F0E6 FE0D CPI $D ; Test carriage return F0E8 C8 RZ ; Retour si carriage return F0E9 3AB001 LDA $1B0 ; On met le nb de fichiers dans A F0EC B7 ORA A F0ED F2DFF0 JP $F0DF ; F0F0 E01 MVI C $1 F0F2 1179F5 LXI D $F579 ; F0F5 C9 RET ;* ;********************************************* ;* Ecriture du nom de fichier * ;********************************************* ;* Entrée A = type de fichier (30 | 31 | 32) * ;* HL = @début nom fichier * ;* DE = lg nom * ;* C = FF ==> nom spécifié * ;* C = 0 ==> pas de nom spécifié * ;* 56 sert à constuire le checksum * ;* AA = header * ;* * ;********************************************* ;* ;********* ;* WOPEN * ;********* ;* F0F6 C5 PUSH B ;WOPEN F0F7 F5 PUSH PSW F0F8 E5 PUSH H F0F9 2A2001 LHLD $120 ; L = contenu de ERRCO L=($120) H=($121) F0FC 3600 MVI M $0 ; ERRCO <-- 0 ==> On autorise l'affichage des erreurs F0FE 2A0001 LHLD $100 ; début de la ligne courante L = ($100) H = ($101) F101 7C MOV A.H F102 B5 ORA L ; F103 C20EF1 JNZ $F10E ; si différent de zéro c'est qu'on est en train de faire ; un save pendant l'exécution d'un programme F106 CDFFDA CALL $DAFF ; Affiche le message pointé par les 2 prochains octets .WORD $CBF1 ; F1CB pointe sur le message à afficher. Le contrôle est ; rendu après affichage du message à l'adresse F10B ; ==> DONC ICI AFFICHAGE DE "INSERT WRITE-ENABLED" F10B CDCBD7 CALL $D7CB F10E 37 STC F10F CD48F3 CALL $F348 ; CALL OPEN (ouvre le DCR spécifié) F112 C2FEF0 JNZ $F0FE ; Jump si erreur F115 E1 POP H F116 CDF5F2 CALL $F2F5 F119 CD41DE CALL $DE41 ; Delai de 665 ms F11C 3EAA MVI A $AA F11E CD84F1 CALL $F184 ; Ecriture du header F121 5E MOV E.M F122 AF XRA A F123 57 MOV D.A F124 23 INX H F125 0 NOP F126 F1 POP PSW F127 D5 PUSH D F128 CD84F1 CALL $F184 ; Ecriture du type de fichier 30, 31 ou 32 F12B C33AF1 JMP $F13A ;* ;***************************** ;* HL = @ début du fichier * ;* DE = nb octets du fichier * ;***************************** ;* F12E C5 PUSH B F12F D5 PUSH D F130 CDF5F2 CALL $F2F5 F133 3EAA MVI A $AA F135 CD84F1 CALL $F184 F138 7F MOV A.A F139 7F MOV A.A F13A 3E00 MVI A $0 F13C CD6FF1 CALL $F16F ; Ecriture de la longueur du bloc et de son checksum F13F 10056 LXI B $5600 ; Réinitialisation du checksum à 56 ;* ;********* ;* BLOCK * ;********* ;* F142 7A MOV A.D F143 B3 ORA E F144 CA50F1 JZ $F150 ; Saut si tous les octets ont été écrits F147 1B DCX D F148 7E MOV A.M ; Récupère un octet du bloc F149 23 INX H ; pointe sur l'octet suivant F14A CD84F1 CALL $F184 ; Ecrit l'octet et met à jour le checksum F14D C342F1 JMP $F142 ; Boucle sur le traitement du bloc F150 0 NOP F151 0 NOP F152 0 NOP F153 78 MOV A.B ; Récupère le checksum calculé F154 CD84F1 CALL $F184 ; Et l'écrit évidemment... F157 D1 POP D F158 C1 POP B F159 CDACF1 CALL $F1AC ; CALL LECETAT : lecture de l'état du DCR F15C 3E0A MVI A $A ; F15E 3202FE STA $FE02 ; positionnement des bit WDC et FWD port C F161 C9 RET ;* ;********** ;* WCLOSE * ;********** ;* F162 F5 PUSH PSW ; Horloge d'écriture F163 3E08 MVI A $8 ; F165 3202FE STA $FE02 ; positionnement à 1 du bit WCD port C F168 CD01F3 CALL $F301 ; Délai F16B FB EI F16C C320F3 JMP $F320 F16F 656 MVI B $56 ; initialisation checksum F171 7A MOV A.D F172 CD84F1 CALL $F184 ; écriture + update CKS F175 E3 XTHL F176 E3 XTHL F177 7B MOV A.E ; Récupère octet d'adresse basse de la longueur F178 7B MOV A.E F179 CD84F1 CALL $F184 ; écriture + update CKS F17C E3 XTHL F17D E3 XTHL F17E 78 MOV A.B ; F17F 78 MOV A.B ; F180 0 NOP F181 0 NOP F182 0 NOP F183 78 MOV A.B ; Récupère CKS ;* ;********************************* ;* Ecriture BYTE * ;* entrée A = Octet à écrire * ;********************************* ;* ;********** ;* WBYTE * ;********** ;* F184 D5 PUSH D F185 1608 MVI D $8 ; on a 8 bits à écrire par octet... F187 0 NOP ;* ;********************************************************************************************* ;* Ecriture d'1 BIT * ;* Cette portion de code utilise une fonction subtile du 8255 qui permet de programmer * ;* n'importe quel bit du port C avec une seule instruction. * ;* Pour ce faire, on n'utilise pas l'adresse $FE02 du port C mais l'on passe directement * ;* par le mot de commande à l'adresse $FE03. Cf lecture du datasheet du 8255 qui décrit * ;* la fonction "Bit Set Reset" * ;********************************************************************************************* ; ;* ;******** ;* WBIT * ;******** ;* F188 7 RLC ; On sauve dans CY le bit b7 du registre A F189 5F MOV E.A ; On sauve A dans E qui contient donc les bits restants à écrire F18A 3E02 MVI A $2 ; Pour programmer correctement e mot de contrôle, cf la suite... F18C 17 RAL ; rotation gauche de A et CY donc b7 (bit à écrire) se retrouve dans le bit 0 de A F18D 3203FE STA $FE03 ; on écrit donc soit 0---0100 soit 0---0101 dans le mot de contrôle du 8255 ; ici le mode "Bit Set/Reset Format" est actif (cf datasheet) ; par conséquent les bits b4, b5 et b6 n'on aucune importance, c'est pourquoi ; je mets 3 tirets. En réalité ce code envoit 000 à la place des 3 tirets, ; mais il pourrait envoyer 111 à la place des 3 tirets, ça ne changerait rien ; au fonctionnement. ; Le résultat est la mise à 1 ou à 0 du bit b2 du port C selon que le bit en ; cours de traitement (donc le bit b7 de A en début de boucle) est à 1 ou à 0. ; En résumé on programme le bit /WDA du port C. ; F190 1F RAR ; on met le bit 0 de A (donc b7 de A en début de boucle) dans CY F191 3F CMC ; on inverse le flag CY F192 17 RAL ; le bit 0 de A contient maintenant l'inverse du bit 7 de A en début de boucle ; F193 15 DCR D ; On décrémente la boucle F194 CDACF1 CALL $F1AC ; CALL LECETAT : lecture de l'état du DCR (A est préservé) F197 3203FE STA $FE03 ; on écrit 0---0101 ou 0---0100 dans le mot de contrôle ; ; Arrivé à cet endroit du code l'écriture du premier morceau représentant le ; bit en cours a duré 166 states, c'est à dire 83 µs ; ; Le deuxième morceau commence maintenant après l'exécution de l'instruction ; en $F197 ; ; ici le mode "Bit Set/Reset Format" est actif (cf datasheet) ; par conséquent les bits b4, b5 et b6 n'on aucune importance, c'est pourquoi ; je mets 3 tirets. En réalité ce code envoit 000 à la place des 3 tirets, ; mais il pourrait envoyer 111 à la place des 3 tirets, ça ne changerait rien ; au fonctionnement. ; Le résultat est la mise à 0 ou à 1 du bit b2 du port C selon que le bit en ; cours de traitement (donc le bit b7 de A en début de boucle) est à 0 ou à 1. ; En résumé on programme le bit /WDA du port C. ; ;******************************************************************************* ;* on vient donc d'écrire un signal carré sur la bande en cours de défilement * ;******************************************************************************* ; F19A 7B MOV A.E ; bits restants F19B C2A3F1 JNZ $F1A3 ; délai 54 µs ; après le délai de 54µs, on revient en $F188 et il se passera encore exactement ; 83 µs entre le début d'écriture du deuxième morceau et le premier morceau du bit ; suivant. ;******************************************************************************* ;* on vient donc d'écrire un signal carré sur la bande en cours de défilement * ;* Ce signal a un niveau bas de 83 µs et un niveau haut de 83 µs, au total ;* chaque bit écrit dure exactement 166 µs. ;* Il se peut que le dernier bit écrit pour un octet dure plus longtemps, ça n'a ;* pas beaucoup d'intérêt de le calculer ;******************************************************************************* F19E D1 POP D F19F A8 XRA B F1A0 7 RLC ; élaboration du CKS F1A1 47 MOV B.A F1A2 C9 RET ;* ;****************** ;* Délai de 54 µs * ;****************** ;* F1A3 E3 XTHL F1A4 E3 XTHL F1A5 E3 XTHL F1A6 E3 XTHL F1A7 E3 XTHL F1A8 E3 XTHL F1A9 C388F1 JMP $F188 ; GOTO WBIT (écriture d'1 bit) = on boucle ;* ;******************** ;* Lecture état DCR * ;******************** ;* ;*********** ;* LECETAT * ;*********** ;* F1AC E5 PUSH H F1AD F5 PUSH PSW ; Préserver A F1AE 2100FE LXI H $FE00 ; Chargement de l'adresse du port A dans HL F1B1 7E MOV A.M ; A = lecture du port A F1B2 E602 ANI $2 ; Begin ou End of Tape (BET) F1B4 CA2BF3 JZ $F32B ; Goto ERR2B si BET détecté donc on y va avec 0 dans A F1B7 7E MOV A.M ; On relit le port A car on vient de modifier A... F1B8 E660 ANI $60 ; WEN + CIP (port A) = bit plug + bit K7 en place F1BA C229F3 JNZ $F329 ; Goto ERR34 si plug absent ou K7 pas en place F1BD 7F MOV A.A ; Pour remettre tous les flags à zéro ??? F1BE BF CMP A ; Pour mettre le ZFLAG à 1 avant de sortir ? F1BF F1 POP PSW ; Récupérer A F1C0 E1 POP H F1C1 C9 RET ;* ;******************************** ;* Message "SAVING ERROR 2" * ;******************************** ;* F1C2 FF .BYTE $FF ; * ??? F1C3 0D .BYTE $0D .BYTE "SAV" F1C7 DD0C .WORD $DD0C ; "ING ERROR "\0 à l'adresse DD0C F1C9 32 .BYTE $32 F1CA 00 .BYTE $00 F1CB 0D .BYTE $0D ;* ;****************************************************** ;* Message "INSERT WRITE-ENABLED CASSETTE,TYPE SPACE" * ;****************************************************** ;* F1CC .BYTE "INSERT WRITE-ENABLED " .BYTE $B7, $9C ; $B7 (inférieur à $C0) identifie un offset d'une sous chaîne ; à afficher (cette sous-chaine commençant ; par un octet de longueur spécifiant le nb ; de caractères à afficher). La routine ; en ROM ajoute $40 à cet offset, par conséquent ; la suite du message est en $F79C .BYTE $2C ; La virgule .BYTE $DB, $F7 ; $DB (supérieur à $C0) identifie une adresse de sous-chaine ; à afficher (cette sous-chaîne devant se terminer par ; un zéro). La routine en ROM n'ajoute rien dans ; ce cas. De ce fait, elle appelle une chaîne située en ; $DBF7 qui correspond à la chaîne "TYPE " .BYTE $8E, $56 ; $56 (inférieur à $C0) identifie un offset d'une sous chaîne ; à afficher (cette sous-chaine commençant ; par un octet de longueur spécifiant le nb ; de caractères à afficher. La routine ; en ROM ajoute $40 à cet offset, par conséquent ; la suite du message est en $CE56, ce qui correspond à la ; chaîne "SPACE" .BYTE $00 ; Fin du message. Finalement, ce message bien compliqué ; ==> donne "INSERT WRITE-ENABLED CASSETTE,TYPE SPACE" ;* ;******************************************** ;* Lecture du nom * ;* Entrée B = Type de fichier * ;* C = FF ==> impression du nom * ;* C = 0 = pas de nom * ;* HL = @nom à loader * ;******************************************** ;* ;******** ; ROPEN * ;******** F1E9 F5 PUSH PSW F1EA 5E MOV E.M F1EB 23 INX H F1EC AF XRA A F1ED 57 MOV D.A F1EE CD48F3 CALL $F348 ; CALL OPEN (Ouvre le DCR spécifié) F1F1 C2ECF1 JNZ $F1EC ; Attend que la cassette soit insérée F1F4 F1 POP PSW F1F5 CD58F4 CALL $F458 F1F8 F5 PUSH PSW F1F9 CDC9F2 CALL $F2C9 ; affiche le type de fichier F1FC 90 SUB B F1FD CD94F2 CALL $F294 F200 F5 PUSH PSW F201 F1 POP PSW F202 B7 ORA A F203 CA79F5 JZ $F579 ; 0 ==> tout est OK F206 5 DCR B F207 4 INR B F208 CA79F5 JZ $F579 ; Si le type de fichier est 0 F20B D DCR C F20C C INR C F20D C45EDD CNZ $DD5E ; CALL CRLF (Cf firmware manual) = affiche un CR (retour à la ligne) F210 C3ECF1 JMP $F1EC ;* ;******************************************** ;* Lecture d'un bloc * ;******************************************** ;* Entrée HL = @de chargement du fichier * ;* Sortie CY = 0 ==> erreur * ;* CY <>0 ==> HL = fin du fichier * ;******************************************** ;* ;********* ; RBLOCK * ;********* F213 C5 PUSH B F214 D5 PUSH D F215 E5 PUSH H F216 CD90D7 CALL $D790 ; Calcule mémoire dispo F219 EB XCHG F21A CD3DF4 CALL $F43D F21D D266F2 JNC $F266 ; erreur F220 CDA3F4 CALL $F4A3 F223 CD1DF4 CALL $F41D ; lecture longueur F226 DA66F2 JC $F266 F229 B7 ORA A F22A 3E00 MVI A $0 ; loading error 0 F22C C268F2 JNZ $F268 ; Si erreur de checksum F22F E5 PUSH H ; Sauvegarde long de bloc F230 19 DAD D F231 D1 POP D F232 3C INR A ; Loading error 2 F233 E1 POP H F234 E5 PUSH H ; récup adresse de début F235 DA68F2 JC $F268 F238 656 MVI B $56 ; initialisation checksum F23A 7A MOV A.D F23B B3 ORA E F23C CA4EF2 JZ $F24E ; Si tout le bloc a été lu F23F 1B DCX D F240 CD37F4 CALL $F437 ; Lecture d'un octet et update checksum F243 DA66F2 JC $F266 ; Si error loading 3 F246 77 MOV M.A ; tocke l'octet dans le buffer F247 23 INX H F248 E3 XTHL F249 E3 XTHL F24A 0 NOP F24B C33AF2 JMP $F23A F24E CDE0F3 CALL $F3E0 ; Lecture d'un octet et update checksum F251 CD1FF3 CALL $F31F ; CALL RCLOSE F254 DA66F2 JC $F266 F257 B8 CMP B ; compare CKS F258 3E02 MVI A $2 F25A C268F2 JNZ $F268 ; Loading Error 2 F25D F5 PUSH PSW F25E AF XRA A F25F CD80F2 CALL $F280 ; Pas d'erreur F262 F1 POP PSW F263 C3B4C6 JMP $C6B4 ;********************************************* ; Traitement des erreurs * ; sortie A = 0 ; CY = 0 ==> pas d'errreur * ; CY = 1 ==> erreur * ; HL = @nom à loader * ;********************************************* F266 3E03 MVI A $3 F268 B7 ORA A F269 CD1FF3 CALL $F31F ; CALL RCLOSE F26C F5 PUSH PSW F26D CD0FF3 CALL $F30F ; ignore l'erreur F270 CA7BF2 JZ $F27B F273 F1 POP PSW F274 CD7FF2 CALL $F27F ; Stockage du code erreur dans ERRCO F277 AF XRA A F278 C3B5C6 JMP $C6B5 F27B F1 POP PSW F27C C3B6C6 JMP $C6B6 ;* ;****************************************** ;* Chargement du code d'erreur dans ERRCO * ;****************************************** ;* F27F 3C INR A F280 E5 PUSH H F281 2A2001 LHLD $120 ; L = contenu de ERRCO L=($120) H=($121) F284 77 MOV M.A ; On met le code erreur dans ERRCO F285 E1 POP H F286 C9 RET ;* ;********* ; MBLOCK * ;********* ;* F287 C5 PUSH B F288 F5 PUSH PSW F289 CD3DF4 CALL $F43D F28C F1 POP PSW F28D C1 POP B F28E CDD3F2 CALL $F2D3 ; délai de 36 µs F291 0 NOP F292 0 NOP F293 0 NOP F294 C5 PUSH B ; Type de fichier requis sauvé en pile F295 E5 PUSH H ; On sauve le pointeur sur le début du nom de fichier attendu F296 47 MOV B.A ; ?? à investiguer F297 D5 PUSH D ; On sauve la longuer du nom du fichier lu F298 E5 PUSH H F299 CD1DF4 CALL $F41D F29C DAD8F2 JC $F2D8 F29F B7 ORA A F2A0 C2D8F2 JNZ $F2D8 F2A3 E5 PUSH H F2A4 CD1ADE CALL $DE1A ; CALL SUBDED = Calcule si différence lg nom lu sur K7 et lg nom prévu F2A7 7C MOV A.H ; .... A continuer ça se complique F2A8 B5 ORA L F2A9 67 MOV H.A F2AA 68 MOV L.B F2AB D1 POP D F2AC 656 MVI B $56 ; initialisation checksum F2AE E3 XTHL F2AF 7A MOV A.D F2B0 B3 ORA E F2B1 CA11F4 JZ $F411 F2B4 1B DCX D F2B5 CDD5F3 CALL $F3D5 ; CALL Fast Entry F2B8 CD87D3 CALL $D387 ; Update checksum (CF firmware manual) F2BB DAD8F2 JC $F2D8 F2BE CDC9F2 CALL $F2C9 F2C1 AE XRA M F2C2 23 INX H F2C3 E3 XTHL F2C4 B4 ORA H F2C5 67 MOV H.A F2C6 C3AEF2 JMP $F2AE F2C9 D DCR C F2CA C INR C ; Load pendant un pgr ? F2CB E5 PUSH H ; sauve la longueur du nom F2CC C2EDD7 JNZ $D7ED ; affiche le nom du pgr F2CF E1 POP H F2D0 C9 RET F2D1 0 NOP F2D2 0 NOP ;* ;****************** ;* Délai de 36 µs * ;****************** ;* F2D3 E3 XTHL ; Un call à cette adresse = délai de 36µS F2D4 E3 XTHL ;* ;****************** ;* Délai de 18 µs * ;****************** ;* F2D5 E3 XTHL ; Un call à cette adresse = délai de 18µS F2D6 E3 XTHL F2D7 C9 RET ;* ;********** ;* ERRTYP * ;********** ;* F2D8 E1 POP H F2D9 D1 POP D F2DA CD1FF3 CALL $F31F ; CALL RCLOSE F2DD CD0FF3 CALL $F30F F2E0 3E01 MVI A $1 F2E2 CAEDF2 JZ $F2ED F2E5 B5 ORA L F2E6 E603 ANI $3 F2E8 CD7FF2 CALL $F27F ; Stockage du code erreur dans ERRCO F2EB AF XRA A F2EC 6F MOV L.A F2ED B5 ORA L F2EE E1 POP H F2EF C1 POP B F2F0 C9 RET F2F1 FF RST 7 F2F2 C3D4F4 JMP $F4D4 F2F5 F3 DI F2F6 CD5CF1 CALL $F15C F2F9 E5 PUSH H F2FA D5 PUSH D F2FB 21E7FF LXI H $FFE7 F2FE C306F3 JMP $F306 F301 E5 PUSH H ; Delai de 130 ms F302 D5 PUSH D F303 21FBFF LXI H $FFFB ; 2*16/5=13000 F306 54 MOV D.H F307 5D MOV E.L F308 19 DAD D ; enlève 5 F309 DA08F3 JC $F308 F30C D1 POP D F30D E1 POP H F30E C9 RET ;* ;********************************************* ;* Vérification de la destination des erreurs* ;********************************************* ;* En sortie de cette routine ZFLAG = 1 si l'affichage des erreurs est autorisé ;* ;*********** ;* ERRDEST * ;*********** ;* F30F E5 PUSH H F310 2A2001 LHLD $120 ; HL = contenu de ERRCO L=($120) H=($121) F313 7C MOV A.H ; On met dans A la valeur de ($121) F314 B5 ORA L ; On error actif ? F315 CA1DF3 JZ $F31D ; Oui ==> Dans ce cas on sort avec ZFLAG = 1 F318 2A0001 LHLD $100 ; L = ($100) H = ($101), HL pointe sur la ligne courante F31B 7C MOV A.H F31C B5 ORA L ; Programme en cours ? ; Autrement dit si H=L=0 on sort avec ZFLAG = 1, ce qui ; autorise l'affichage des erreurs, dans le cas contraire ; nous sommes en cours d'exécution de programme et l'affichage ; des erreurs est invalidé F31D E1 POP H F31E C9 RET ;* ;********** ;* RCLOSE * ;********** ;* F31F F5 PUSH PSW F320 AF XRA A F321 3202FE STA $FE02 ; désactive les signaux port C F324 3201FE STA $FE01 ; désactive les signaux port B F327 F1 POP PSW F328 C9 RET ;* ;********************************************* ;* Erreur $34 Plug absent ou K7 pas en place * ;******************************************** ;* ;* ERR34 F329 3E09 MVI A $9 ; $9B + $2B = $34 on signale une erreur 4 visiblement... ;* ;*********************************** ; Erreur $2B Début ou fin de bande * ;*********************************** ;* ; ERR2B F32B C62B ADI $2B ; F32D F5 PUSH PSW F32E 23 INX H F32F 23 INX H F330 3600 MVI M $0 ; arrêt moteur F332 CD0FF3 CALL $F30F ; CALL ERRDEST soit avec l'erreur $34 soi avec l'erreur 2B. F335 CA43F3 JZ $F343 ; Si ERRDEST nous en a donné l'autorisation, alors on affiche l'erreur $2B ou $34 F338 F1 POP PSW F339 E607 ANI $7 ; Fin de bande = 1 F33B 1F RAR ; F33C 2A2001 LHLD $120 ; L = contenu de ERRCO L=($120) H=($121) F33F 77 MOV M.A F340 F1 POP PSW F341 E1 POP H F342 C9 RET ;* ;********************************** ;* Impression du message d'erreur * ;********************************** ;* F343 F1 POP PSW ; On récupère le N° de message d'erreur dans A F344 FB EI F345 C3F5D9 JMP $D9F5 ; On se débranche en ERROR (cf ERROR Handling firmware manual) ; Et on sort du DTOS visiblement... ;* ;*************************************************** ; OPEN = Ouvre le DCR spécifié * ;*************************************************** ; teste si K7 en place * ; OPEN initialise le DCE BUS pour le MDCR * ; si CY=1 à l'entrée, le plug (WEN) est recherché * ; Si pas de K7 ou EOT détecté ==> arrêt moteur * ; en sortie CY=0 si pas d'errreur * ;*************************************************** ;* ;******** ;* OPEN * ;******** ;* F348 F5 PUSH PSW F349 E5 PUSH H F34A 21ECFF LXI H $FFEC F34D 39 DAD SP F34E 7E MOV A.M F34F 77 MOV M.A F350 E1 POP H F351 3E98 MVI A $98 F353 3203FE STA $FE03 ; positionnement du mode pour le 8255 F356 3A1F01 LDA $11F ; DCRSL est chargé dans A (N° du DCR) F359 7 RLC F35A 7 RLC F35B C603 ADI $3 F35D 3201FE STA $FE01 ; Port B : Mode "Control/Status adress" sélectionné bit SEL = 1 (MDCR activé) F360 CDBBF3 CALL $F3BB F363 F1 POP PSW ; récup CY F364 3A00FE LDA $FE00 ; Lecture octet port A F367 D271F3 JNC $F371 F36A E662 ANI $62 ; WEN+CIP+BET F36C EE02 XRI $2 ; BET F36E C375F3 JMP $F375 ; test du WEN F371 E622 ANI $22 ; CIP + BET F373 EE02 XRI $2 ; BET F375 C41FF3 CNZ $F31F ; CALL RCLOSE : une erreur s'est produite F378 C9 RET ; En cas d'erreur CY <> 0 ;* ;************************** ;* Reset début de lecture * ;************************** ;* F379 AF XRA A F37A 3202FE STA $FE02 ; reset port C F37D 3E02 MVI A $2 F37F 3202FE STA $FE02 ; positionne FWD F382 C9 RET F383 AF XRA A F384 3202FE STA $FE02 ; reset port C F387 3E01 MVI A $1 F389 3202FE STA $FE02 ; positionne REV port C F38C C9 RET F38D 3E02 MVI A $2 F38F 3202FE STA $FE02 ; positionne FWD port C F392 CD01F3 CALL $F301 F395 C379F3 JMP $F379 F398 3E01 MVI A $1 F39A 3202FE STA $FE02 ; positionne REV port C F39D CD01F3 CALL $F301 F3A0 C383F3 JMP $F383 F3A3 F5 PUSH PSW F3A4 3EFF MVI A $FF ; On va mettre le nombre maximum de fichiers à rembobiner dans F3A6 32B001 STA $1B0 ; FILES ==> Visiblement on veut rembobiner tout F3A9 FB EI F3AA CDD6F5 CALL $F5D6 ; CALL CRWND = commande REWIND 'F' fichiers donc ici F = 255 F3AD CD01F3 CALL $F301 F3B0 CD48F3 CALL $F348 ; CALL OPEN = Ouvre le DCR spécifié F3B3 F1 POP PSW F3B4 F3 DI ; Démarre la lecture F3B5 F5 PUSH PSW F3B6 CD8DF3 CALL $F38D F3B9 F1 POP PSW F3BA C9 RET ;* ;**************************** ;* On teste la touche break * ;**************************** ;* F3BB CDA5D6 CALL $D6A5 F3BE D264F3 JNC $F364 ; si pas de BREAK F3C1 CD1FF3 CALL $F31F ; CALL RCLOSE F3C4 2A9902 LHLD $299 ; On s'apprête à restaurer le pointeur de pile à partir de RSP F3C7 7C MOV A.H F3C8 B7 ORA A F3C9 CA0CC8 JZ $C80C ; Si le pointeur de pile est à zéro ==> retour au moniteur BASIC start from scratch F3CC AF XRA A F3CD 323501 STA $135 F3D0 F9 SPHL ; sinon on restaure le pointeur de pile F3D1 3E02 MVI A $2 F3D3 37 STC F3D4 C9 RET ;* ;************** ;* Fast entry * ;************** ;* F3D5 3A00FE LDA $FE00 ; Lecture octet port A F3D8 C5 PUSH B F3D9 E01 MVI C $1 F3DB 609 MVI B $9 F3DD C3ECF3 JMP $F3EC ;* ;*************************************** ;Lecture d'un octet et update checksum * ;*************************************** ;* F3E0 C5 PUSH B ; 8 bits F3E1 E01 MVI C $1 F3E3 609 MVI B $9 ;* F3E5 5 DCR B F3E6 CA0BF4 JZ $F40B ; Trop long F3E9 3A00FE LDA $FE00 ; Lecture octet port A ;* F3EC B7 ORA A ; positionne flags F3ED F2E5F3 JP $F3E5 F3F0 1F RAR ; Bit dans CY F3F1 79 MOV A.C ; Bit précédent F3F2 17 RAL ; Bit nouveau prêt F3F3 DA0EF4 JC $F40E ; F3F6 4F MOV C.A ; sauve le bit F3F7 60F MVI B $F F3F9 5 DCR B F3FA CA0BF4 JZ $F40B F3FD 3A00FE LDA $FE00 ; Lecture octet port A F400 B7 ORA A F401 FAF9F3 JM $F3F9 F404 E622 ANI $22 ; CIP + BET F406 EE02 XRI $2 ; BET F408 CAE3F3 JZ $F3E3 F40B CD1FF3 CALL $F31F ; CALL RCLOSE F40E 3F CMC F40F C1 POP B F410 C9 RET F411 CDD5F3 CALL $F3D5 ; CALL Fast Entry F414 CD1FF3 CALL $F31F ; CALL RCLOSE F417 DAD8F2 JC $F2D8 ; F41A C3DED3 JMP $D3DE F41D CDD5F3 CALL $F3D5 ; CALL Fast Entry F420 C5 PUSH B F421 656 MVI B $56 ; Checksum de départ F423 CD87D3 CALL $D387 ; Update checksum (CF firmware manual) F426 67 MOV H.A F427 D4D5F2 CNC $F2D5 ; délai de 18 µs F42A D437F4 CNC $F437 ; Lecture d'un octet et update checksum F42D 6F MOV L.A F42E D4D3F2 CNC $F2D3 ; délai de 36 µs F431 D4E0F3 CNC $F3E0 ; Lecture d'un octet et update checksum F434 C39BD3 JMP $D39B F437 CDE0F3 CALL $F3E0 ; Lecture d'un octet et update checksum F43A C387D3 JMP $D387 ; Update checksum (CF firmware manual) ;* ;******************* ; Cherche un block * ;******************* ;* F43D AF XRA A F43E CD48F3 CALL $F348 ; CALL OPEN = Ouvre le DCR spécifié F441 C0 RNZ ; Si CY <> 0 alors on quitte en erreur F442 CD79F3 CALL $F379 ; pas d'erreur, on continue F445 1B400 LXI B $B4 F448 CD94F4 CALL $F494 ; CALL FLOW F44B C23DF4 JNZ $F43D F44E 60F MVI B $F F450 CD94F4 CALL $F494 F453 CDD5F3 CALL $F3D5 ; CALL Fast Entry F456 3F CMC F457 C9 RET ;* ;************************ ;* Recherche de fichier * ;************************ ;* F458 C5 PUSH B F459 CD8FD9 CALL $D98F ; Disable sound interrupt F45C CD70F4 CALL $F470 ; Cherche header F45F CDD5F3 CALL $F3D5 ; CALL Fast Entry F462 DA5CF4 JC $F45C F465 CDA3F4 CALL $F4A3 ; attend clock File Type F468 CDE0F3 CALL $F3E0 ; Lecture d'un octet et update checksum F46B DA5CF4 JC $F45C ; encore une fois si erreur de lecture F46E C1 POP B F46F C9 RET ;* ;******************** ;* Recherche header * ;******************** ;* F470 CDB4F3 CALL $F3B4 F473 FB EI F474 CDBBF3 CALL $F3BB F477 F3 DI F478 C28EF4 JNZ $F48E F47B CD79F3 CALL $F379 F47E 60F MVI B $F F480 CD94F4 CALL $F494 F483 C273F4 JNZ $F473 F486 696 MVI B $96 F488 CD94F4 CALL $F494 F48B E680 ANI $80 ; signal horloge en erreur (RDC bit) F48D C0 RNZ ; Bit found F48E CDA3F3 CALL $F3A3 ; Last file F491 C373F4 JMP $F473 ;* ;* FLOW (Find Low) ;* F494 B DCX B F495 78 MOV A.B F496 B1 ORA C F497 C8 RZ F498 3A00FE LDA $FE00 ; Lecture octet port A F49B E6A2 ANI $A2 ; RDC + /CIP + /BET F49D EE02 XRI $2 ; BET F49F CA94F4 JZ $F494 ; on boucle ; si /BET = 1 (c-à-d pas en début de bande ni en fin de bande) ; ET { ; si K7 présente (/CIP = 0) ; si RDC = 0 ; } F4A2 C9 RET ;* ;********************* ;* FCLK (Find Clock) * ;********************* ;* F4A3 C5 PUSH B F4A4 F5 PUSH PSW F4A5 60F MVI B $F F4A7 5 DCR B ; BOUCLE_FCLK F4A8 CAB3F4 JZ $F4B3 ; Au bout de 15 fois on sort, cf specs Service Manual Memocom pour comprendre F4AB 3A00FE LDA $FE00 ; Lecture octet port A F4AE E680 ANI $80 ; RDC F4B0 C2A7F4 JNZ $F4A7 ; Tant que RDC = niveau 1 on boucle F4B3 F1 POP PSW F4B4 C1 POP B F4B5 C9 RET ;* F4B6 C3F6F0 JMP $F0F6 ;WOPEN F4B9 C32EF1 JMP $F12E ;BLOCK F4BC C362F1 JMP $F162 ;WCLOSE F4BF C3E9F1 JMP $F1E9 ;ROPEN F4C2 C313F2 JMP $F213 ;RBLOCK F4C5 C31FF3 JMP $F31F ;RCLOSE F4C8 C387F2 JMP $F287 ;MBLOCK F4CB C9 RET F4CC 0 NOP F4CD 0 NOP F4CE C9 RET F4CF 0 NOP F4D0 0 NOP F4D1 C354F0 JMP $F054 ;DINKBD ;* ;************************************ ;* INITIALISATION DU DAI ET DU MDCR * ;************************************ ; F4D4 F5 PUSH PSW F4D5 C5 PUSH B F4D6 D5 PUSH D F4D7 E5 PUSH H F4D8 2186F7 LXI H $F786 ; HL contient l'adresse de la table des commandes TABCMD F4DB 229702 SHLD $297 F4DE 219602 LXI H $296 ; validation des cdes F4E1 3E02 MVI A $2 F4E3 B6 ORA M ; ($296) <> 0 => entrée via clavier F4E4 77 MOV M.A F4E5 AF XRA A F4E6 321F01 STA $11F ; On met 0 dans DCTSL ==> DCR 0 sélectionné F4E9 32C402 STA $2C4 F4EC CDBFF6 CALL $F6BF ; CALL NONERR = désactive "ON ERROR" F4EF 21B4DD LXI H $DDB4 ; On va mettre DDB4 dans HL F4F2 22E402 SHLD $2E4 ; On va donc stocker $B4 à l'adresse $2E4 et ; $DD à l'adresse $2E5 F4F5 3EC3 MVI A $C3 ; Code assembleur du JUMP !!! F4F7 32E302 STA $2E3 ; Au total ce bout de code vient de mettre ; JMP DDB4 dans la table de vecteurs IOVEC cf memory map ; C'est le vecteur permettant d'obtenir l'input depuis ; l'interface RS232 ! F4FA CD66F5 CALL $F566 ; CALL DCR = Select DCR F4FD 1604 MVI D $4 F4FF 15 DCR D F500 CA41F5 JZ $F541 F503 1E0C MVI E $C F505 CD48F3 CALL $F348 ; CALL OPEN = Ouvre le DCR spécifié F508 C260F5 JNZ $F560 F50B 37 STC F50C CD64F3 CALL $F364 F50F CA60F5 JZ $F560 F512 CD01F3 CALL $F301 F515 CD01F3 CALL $F301 F518 2A8000 LHLD $80 ; HL pointe sur le 1er byte de la mémoire écran (#BFFF) F51B 1FBFF LXI B $FFFB F51E 9 DAD B F51F 7E MOV A.M F520 EE0A XRI $A F522 77 MOV M.A F523 1D DCR E F524 C205F5 JNZ $F505 F527 AF XRA A F528 4F MOV C.A F529 47 MOV B.A F52A 3D DCR A F52B 32B001 STA $1B0 ; décrémente le nb de fichiers dans FILES F52E CDD6F5 CALL $F5D6 ; CALL CRWND = commande REWIND 'F' fichiers F531 21C8F6 LXI H $F6C8 F534 CDE9F1 CALL $F1E9 ; CALL ROPEN : lecture du nom de fichier F537 21FBFF LXI H $FFFB ; SP - 7 pour pointer le F53A 39 DAD SP ; type de fichier F53B 7E MOV A.M ; si type = 31 F53C FE31 CPI $31 ; alors on vérifie si F53E CA47F5 JZ $F547 ; le nom est "USER" F541 CDD6F5 CALL $F5D6 ; CALL CRWND = commande REWIND 'F' fichiers F544 C34DC1 JMP $C14D ; Effectue le POP H, POP D, POP B et RET ; * ; * Si le nom est "USER" alors RUN automatique ; * F547 CD74EF CALL $EF74 ; lit le nom F54A D2FFF4 JNC $F4FF ; fait 4 tentatives F54D E5 PUSH H F54E D5 PUSH D F54F 1100F9 LXI D $F900 F552 CD8AEF CALL $EF8A F555 D1 POP D F556 E1 POP H F557 D2FFF4 JNC $F4FF F55A E5 PUSH H F55B 214DC1 LXI H $C14D ; Effectue le POP H, POP D, POP B et RET F55E E3 XTHL ; démarre le programme F55F E9 PCHL F560 CD1FF3 CALL $F31F ; CALL RCLOSE F563 C34DC1 JMP $C14D ; Effectue le POP H, POP D, POP B et RET ;* ;********************* ;* Sélection du MDCR * ;********************* ;* ;******* ;* DCR * ;******* ;* F566 F5 PUSH PSW F567 D5 PUSH D F568 E5 PUSH H F569 C5 PUSH B F56A 11B6F4 LXI D $F4B6 ; DE = @ de WOPEN F56D 21D4F4 LXI H $F4D4 F570 1C502 LXI B $2C5 F573 CD4FDE CALL $DE4F F576 C1 POP B F577 E1 POP H F578 D1 POP D F579 F1 POP PSW F57A C9 RET ;* ;******************************* ;* Selection de la cassette * ;******************************* ;* ;******* ;* CAS * ;******* ;* F57B F5 PUSH PSW F57C D5 PUSH D F57D E5 PUSH H F57E 2AE402 LHLD $2E4 ; on préserve l'adresse présente dans le vecteur 2E3 F581 E5 PUSH H F582 CD95D7 CALL $D795 ; CALL MPT01 transfer data/cassette switching vectors from ; ROM to RAM vector area F585 E1 POP H F586 22E402 SHLD $2E4 ; On remet l'adresse du vecteur 2E3 F589 3EC3 MVI A $C3 F58B 32E302 STA $2E3 ; On vient d'écrire JMP "adresse préservée" en 2E3 F58E 2154F0 LXI H $F054 F591 22E102 SHLD $2E1 F594 C377F5 JMP $F577 ;* ;***************** ;* Cde Delete * ;***************** ;* ;***************** ;* DEL ou DELETE * ;***************** ;* F597 F5 PUSH PSW F598 CDA6F5 CALL $F5A6 F59B C2A4F5 JNZ $F5A4 F59E CDBBF3 CALL $F3BB F5A1 CA9EF5 JZ $F59E F5A4 F1 POP PSW F5A5 C9 RET F5A6 3AB001 LDA $1B0 ; On met le nb de fichiers issu de FILES dans A F5A9 B7 ORA A F5AA F20BDA JP $DA0B F5AD 37 STC F5AE CD48F3 CALL $F348 ; CALL OPEN = Ouvre le DCR spécifié F5B1 C0 RNZ F5B2 3E0A MVI A $A F5B4 3202FE STA $FE02 ; Positionnement WCD et FWD port C F5B7 C9 RET ;* ;************************ ; CLAST = Commande LAST * ;************************ ;* ;******** ;* LAST * ;******** ;* F5B8 F5 PUSH PSW F5B9 CDC0F5 CALL $F5C0 F5BC C5 PUSH B F5BD C37CF6 JMP $F67C ; rewind 1 fichier F5C0 CDA6F5 CALL $F5A6 F5C3 C0 RNZ F5C4 CDBBF3 CALL $F3BB F5C7 C0 RNZ F5C8 CD87F6 CALL $F687 ; 255 fois F5CB C8 RZ F5CC 3D DCR A F5CD CDD3F2 CALL $F2D3 ; délai de 36 µs F5D0 C2CCF5 JNZ $F5CC ; moyenne 188 fois F5D3 C3C4F5 JMP $F5C4 ;* ;***************************** ;* commande REWIND 'F' Files * ;***************************** ;* ;***************** ;* REWIND ou REW * ;***************** ;* F5D6 F5 PUSH PSW F5D7 AF XRA A F5D8 CD48F3 CALL $F348 ; CALL OPEN = Ouvre le DCR spécifié F5DB C2D8F5 JNZ $F5D8 F5DE CD01F3 CALL $F301 F5E1 3AB001 LDA $1B0 ; On récupère le nb de fichiers à rembobiner dans FILES F5E4 B7 ORA A F5E5 CD87F3 CALL $F387 F5E8 FA9EF5 JM $F59E F5EB C5 PUSH B F5EC CA36F6 JZ $F636 F5EF F3 DI F5F0 CD98F3 CALL $F398 F5F3 601 MVI B $1 F5F5 CD94F4 CALL $F494 F5F8 FB EI F5F9 CDBBF3 CALL $F3BB F5FC F3 DI F5FD C236F6 JNZ $F636 F600 CD83F3 CALL $F383 F603 61E MVI B $1E F605 CD94F4 CALL $F494 F608 C2F8F5 JNZ $F5F8 F60B 6FF MVI B $FF F60D CD94F4 CALL $F494 F610 CA0BF6 JZ $F60B F613 E680 ANI $80 F615 CA36F6 JZ $F636 F618 CD87F6 CALL $F687 F61B C2F8F5 JNZ $F5F8 ; Test BREAK et continue F61E CDF9F2 CALL $F2F9 F621 AF XRA A F622 CD8FF3 CALL $F38F F625 CD8DF3 CALL $F38D F628 608 MVI B $8 F62A CD94F4 CALL $F494 F62D CA36F6 JZ $F636 F630 CD64F3 CALL $F364 F633 CA28F6 JZ $F628 F636 CD1FF3 CALL $F31F ; CALL RCLOSE F639 C1 POP B F63A F1 POP PSW F63B FB EI F63C C9 RET ;* ;*************************** ;* Commande SKIP 'F' Files * ;*************************** ;* ;******** ;* SKIP * ;******** ;* F63D F5 PUSH PSW F63E AF XRA A F63F CD48F3 CALL $F348 ; CALL OPEN = Ouvre le DCR spécifié F642 C23FF6 JNZ $F63F F645 CD01F3 CALL $F301 F648 3AB001 LDA $1B0 ; arrête quand nb de fichiers = 0 F64B B7 ORA A ; dans FILES F64C C5 PUSH B F64D CA36F6 JZ $F636 F650 CD8FD9 CALL $D98F ; Disable sound interrupt F653 CDB4F3 CALL $F3B4 F656 696 MVI B $96 F658 CD94F4 CALL $F494 F65B FB EI F65C CDBBF3 CALL $F3BB F65F F3 DI F660 C236F6 JNZ $F636 F663 CD79F3 CALL $F379 F666 60A MVI B $A F668 CD94F4 CALL $F494 F66B C25BF6 JNZ $F65B F66E CD87F6 CALL $F687 F671 CA36F6 JZ $F636 F674 696 MVI B $96 F676 CD94F4 CALL $F494 F679 C25BF6 JNZ $F65B F67C CD98F3 CALL $F398 F67F 3E01 MVI A $1 F681 32B001 STA $1B0 ; On stocke 1 dans FILES F684 C3F8F5 JMP $F5F8 F687 3AB001 LDA $1B0 ; On s'apprête à décrémenter le nb de fichiers à traiter F68A 3D DCR A ; dans la variable F68B 32B001 STA $1B0 ; FILES F68E C9 RET ;* ;******************** ;* Selection du DCR * ;******************** ;* ;******* ;* DCR * ;******* ;* F68F F5 PUSH PSW F690 3AB001 LDA $1B0 ; On récupère le nb de fichiers à traiter dans FILES F693 B7 ORA A ; Curieux... FILES semble utilisé aussi pour récupérer ; le N° de MDCR dans la commande... Donc ici $1B0 ; ne contiendrait pas un nombre de fichiers mais un ; N° de DCR qui sera ensuite mis dans DCRSL ??? ; Curieuse façon de faire... F694 F298F6 JP $F698 F697 3C INR A F698 E603 ANI $3 F69A 321F01 STA $11F ; On stocke le N° du DCR dans DCRSL F69D C367F5 JMP $F567 ;* ;************************************ ;* Selection du lecteur de cassette * ;************************************ ;* ;******************* ;* CASSETTE ou CAS * ;******************* ;* F6A0 F5 PUSH PSW F6A1 3AB001 LDA $1B0 ; On récupère le nb de fichiers... Remarque identique ; que celle pour la routine DCR !!! FILES ; sauf que là on va aller alimenter la variable CASSL ; cf memory map du DAI F6A4 B7 ORA A F6A5 F2AAF6 JP $F6AA F6A8 3E01 MVI A $1 F6AA E603 ANI $3 F6AC 7 RLC F6AD 7 RLC F6AE 7 RLC F6AF 7 RLC F6B0 323D01 STA $13D ; On positionne CASSL avec #10 (CASSETTE1) ou #20 (CASSETTE2) F6B3 C37CF5 JMP $F57C ;********************** ; initialise ON ERROR * ; ********************* ;* ;********* ;* ONERR * ;********* ;* F6B6 E5 PUSH H ; On préserve HL F6B7 23 INX H ; On augmente HL F6B8 23 INX H ; de 3 F6B9 23 INX H ; unités F6BA 222001 SHLD $120 ; On stocke le résultat dans ERRCO qui contient donc l'adresse ; de la variable passée en paramètre du CALLM #F003,PARAM% donc ; l'adresse de PARAM% augmentée de 3 unités. F6BD E1 POP H F6BE C9 RET ;* ;******************************************* ;* désactive ON ERROR retour à la gestion * ;******************************************* ;* ;***************************** ;* NONERR = désactive ON ERR * ;***************************** ;* F6BF E5 PUSH H F6C0 210000 LXI H $0 F6C3 222001 SHLD $120 ; On stocke 0 à l'adresse 120 (adresse de spare non utilisée par le DAI) ; S'il y avait une adresse de variable, maintenant il n'y en a plus. F6C6 E1 POP H F6C7 C9 RET .BYTE 4 .BYTE "USERDAI TOS V1.2" .BYTE 0 .BYTE D .BYTE "SAV" .BYTE DD .BYTE C .BYTE 31 .BYTE 0 ;* ;****************** ; Commande verify * ;****************** ;* ;* ;***************** ;* VERIFY ou VER * ;***************** ;* F6E2 F5 PUSH PSW F6E3 C5 PUSH B F6E4 D5 PUSH D F6E5 E5 PUSH H F6E6 3AB001 LDA $1B0 ; On récupère le nb de fichiers à traiter dans FILES F6E9 B7 ORA A F6EA F20BDA JP $DA0B F6ED 3E01 MVI A $1 F6EF 32B001 STA $1B0 ; Si était à zéro on fait mine qu'on l'a pas vu et on met 1 F6F2 CDD6F5 CALL $F5D6 ; CALL CRWND = commande REWIND 'F' fichiers F6F5 2A0001 LHLD $100 F6F8 7C MOV A.H F6F9 B5 ORA L F6FA 210000 LXI H $0 F6FD C22DF7 JNZ $F72D F700 CD5EDD CALL $DD5E ; CALL CRLF (Cf firmware manual) = affiche un CR (retour à la ligne) F703 1FF00 LXI B $FF F706 CDE9F1 CALL $F1E9 ; CALL ROPEN F709 FE33 CPI $33 F70B D227F7 JNC $F727 F70E C INR C F70F 3E00 MVI A $0 F711 CD87F2 CALL $F287 F714 CC87F2 CZ $F287 F717 C222F7 JNZ $F722 F71A CDFFDA CALL $DAFF ; Affiche le message pointé par les 2 prochains octets .WORD $C0DB ; DBC0 pointe sur le message à afficher. Le contrôle est ; rendu après affichage du message à l'adresse F71F ; ==> En DBC0 on trouve " OK" + 0D F71F C356F7 JMP F756 F722 CDFFDA CALL $DAFF ; Affiche le message pointé par les 2 prochains octets .WORD $DBDB ; DBDB pointe sur le message à afficher. Le contrôle est ; rendu après affichage du message à l'adresse F727 ; ==> En DBDB on trouve " BAD" F727 CD5EDD CALL $DD5E ; CALL CRLF (Cf firmware manual) = affiche un CR (retour à la ligne) F72A C356F7 JMP $F756 F72D 10000 LXI B $0 F730 2A2001 LHLD $120 ; L = contenu de ERRCO L=($120) H=($121) F733 E5 PUSH H F734 210000 LXI H $0 F737 222001 SHLD $120 ; Réinitialise ERRCO F73A CDE9F1 CALL $F1E9 ; CALL ROPEN F73D FE33 CPI $33 F73F D24DF7 JNC $F74D F742 3E00 MVI A $0 F744 CD87F2 CALL $F287 F747 CC87F2 CZ $F287 F74A CA4FF7 JZ $F74F F74D 3E01 MVI A $1 F74F E1 POP H F750 222001 SHLD $120 F753 CD80F2 CALL $F280 F756 CD1FF3 CALL $F31F ; CALL RCLOSE F759 FB EI F75A C34DC1 JMP $C14D ; Effectue le POP H, POP D, POP B et RET ;**************** ; commande look * ;**************** ; LOOK F75D F5 PUSH PSW F75E C5 PUSH B F75F D5 PUSH D F760 E5 PUSH H F761 3AB001 LDA $1B0 ; On récupère le nb de fichier dont il faut regarder le nom... F764 B7 ORA A F765 F20BDA JP $DA0B ; On affiche SYNTAXE ERROR si un nombre est donné CALL ERRSN F768 210000 LXI H $0 F76B 1FF00 LXI B $FF F76E CD5EDD CALL $DD5E ; CALL CRLF (Cf firmware manual) = affiche un CR (retour à la ligne) F771 CDE9F1 CALL $F1E9 ; Lecture du nom F774 CD1FF3 CALL $F31F ; CALL RCLOSE F777 CD5EDD CALL $DD5E ; CALL CRLF (Cf firmware manual) = affiche un CR (retour à la ligne) F77A 3E01 MVI A $1 F77C 32B001 STA $1B0 ; On 1 dans FILES pour rembobiner 1 fois F77F CDD6F5 CALL $F5D6 ; CALL CRWND = commande REWIND 'F' fichiers, ici F = 1 F782 FB EI F783 C34DC1 JMP $C14D ; Effectue le POP H, POP D, POP B et RET ;************************************************* ; Table des commandes avec adresses des routines * ;************************************************* ; TABCMD F786 .BYTE 6 .BYTE "REWIND" .WORD $F5D6 ; adresse de la routine REWIND 'F' fichiers F78F .BYTE 3 .BYTE "REW" .WORD $F5D6 ; adresse de la routine REWIND 'F' fichiers F795 .BYTE 4 .BYTE "SKIP" .WORD $F63D ; adresse de la routine SKIP 'F' fichiers F79C .BYTE 8 ; Utilisé comme offset par le message en F1CB .BYTE "CASSETTE" .WORD $F6A0 ; adresse de la routine CASSETTE F7A7 .BYTE 3 .BYTE "CAS" .WORD $F6A0 ; adresse de la routine CAS F7AD .BYTE 3 .BYTE "DCR" .WORD $F68F ; adresse de la routine DCR F7B3 .BYTE 6 .BYTE "DELETE" .WORD $F597 ; adresse de la routine DEL F7BC .BYTE 3 .BYTE "DEL" .WORD $F597 ; adresse de la routine DEL F7C2 .BYTE 4 .BYTE "LAST" .WORD $F5B8 ; adresse de la routine LAST F7C9 .BYTE 6 .BYTE "VERIFY" .WORD $F6E2 ; adresse de la routine VERIFY F7D3 .BYTE 3 .BYTE "VER" .WORD $F6E2 ; adresse de la routine VERIFY F7D9 .BYTE 4 .BYTE "LOOK" .WORD $F75D ; adresse de la routine LOOK F7DF 0 .BYTE 0 F7E0 0 .BYTE 0 F7E1 0 .BYTE 0 .BYTE "COPYRIGHT 1981 BY MEMOCOM B.V."