RSS

La programmation des jeux dans les années 80

Au tout début de l’informatique grand public, les machines étaient si peu puissantes que la façon même de les programmer était différente d’aujourd’hui.
Il fallait se donner du mal pour n’obtenir qu’un résultat juste correct, l’environnement de programmation était assez rudimentaire.

Toutefois, ces difficultés allaient de pair avec l’enthousiasme d’apprendre un domaine tout nouveau et largement mystérieux pour le grand public.
Une des conséquences d’avoir appris à programmer à cette époque, outre l’entraînement à la persévérance 😉 , c’est d’avoir finalement touché à toute la chaîne de l’informatique. Car pour obtenir un logiciel qui fonctionne normalement sur ces machines, il fallait tirer le maximum de leurs rares Mhz (oui, mega hertz, pas giga hertz !) et de leur mémoire d’oiseau amnésique. Il fallait donc les connaître dans leurs moindres détails.

Plutôt que de parler en général, je vais vous montrer en pratique à quoi cela ressemblait, en partie au travers de mon expérience personnelle et de quelques humbles œuvrettes de jeunesse.

Le ZX

Pour ma part, tout a démarré avec un précurseur de l’informatique accessible à tous, j’ai nommé le Sainclair ZX-81:

En résumé:

  • Pas cher (1000 FF à sa sortie, je crois, donc très accessible).
  • Enregistre sur des cassettes audio (il faut y brancher un magnétophone).
  • Mémoire ultra-faible même pour l’époque: 1 Ko !
  • Clavier de type industriel: une membrane avec des contacts dessous, comme certaines machines en plein-air.
  • Processeur 8 bits à 3,25 Mhz, que j’évaluerais à environ 0,15 Mips, le Z80.
  • Pas de mode graphique, tout est en texte.
  • Langage Basic intégré, assez simpliste.
  • Pas de son.

Détails sur Wikipedia.

Cette machine était construite pour que tout le monde puisse découvrir ce qu’est un ordinateur sans se ruiner.
Malheureusement, sa conception très bas-de-gamme le rendait presque inutilisable, sa faible puissance permettait à peine aux logiciels de tenir dans la mémoire et le manque de fiabilité de ses sauvegardes sur cassette audio nous faisait souvent perdre les programmes péniblement entrés à la main.

Il a toutefois servi à beaucoup de gens à se mettre à la programmation, car c’est bien ce qui était le plus passionnant à cette époque: créer quelque chose à partir de ces machines.

Comme toutes les machines 8 bits, il disposait d’un interpréteur Basic en ROM. D’ailleurs le système d’exploitation entier était en ROM, dans 8 petits Ko.

C’est une première chose étonnante vu d’aujourd’hui: comment un interpréteur Basic, en plus d’une gestion de fichiers sur cassette et de quelques autres ressources, pouvait tenir dans 8 minuscules Ko ?

La réponse est claire pour cette époque: tout le code de la ROM était écrit en Assembleur.
Pour les jeunes programmeurs, il n’est pas évident de savoir à quoi ressemble un code assembleur, puisqu’ aujourd’hui seuls quelques domaines particuliers nécessitent ce type de programmation.

Mais n’oublions pas que, par-dessus tout, la nécessité rend ingénieux. La capacité était faible, les gens ont trouvé des solutions pour en tirer partie malgré la difficulté.

Le code assembleur, dit code machine, en fait le jeu d’instructions du microprocesseur

Voici un extrait d’un code source, une partie de la routine de test de la RAM:

;; RAM-CHECK
L03CB: LD H,B ;
LD L,C ;
LD A,$3F ;

;; RAM-FILL
L03CF: LD (HL),$02 ;
DEC HL ;
CP H ;
JR NZ,L03CF ; to RAM-FILL

Vous trouverez le désassemblage complet de la ROM ici.
Malheureusement, ce genre de code est difficile à lire, c’est à dire à comprendre pour un humain.
Et encore, il faut imaginer un listing de 10000 lignes ainsi, on a vite fait de s’y perdre. Tout dépend alors de la qualité de la documentation.
Ce dernier code est à peu près équivalent à ce code C#:

void EffaceÉcran(byte* PFinÉcran)
{
// Remplissage:
byte* pécran = PFinÉcran;
while((pécran & 0xFF00) != 0)
*pécran-- = 2;
}

Vous pouvez voir que c’est déjà nettement plus lisible, surtout si vous savez programmer dans un langage proche syntaxiquement du C++. Et encore, on n’écrirait pas les choses ainsi en C#, on utiliserait un foreach.

Les pointeurs

À remarquer que mon transcodage en C# utilise un pointeur, déconseillé dans les langages modernes à cause des risques de dépassement. Ce pointeur reflète directement le registre HL du Z80 dans le code en assembleur.

On voit ici la raison d’être des pointeurs dans les langages comme le C++ : se calquer sur les instructions en code microprocesseur (ce qu’on appelle l’Assembleur, par un abus de langage, ou encore le code machine). On comprend bien, là, que le langage C est entièrement conçu pour coller au plus près des possibilités des microprocesseurs, ce qui le rend tout aussi rapide à l’exécution que dangereux.

L’inefficacité de la compilation C

Si je compile mon code C# (en fait une version en C K&R), j’obtiens ce long code machine (pour microprocesseur Z80):

 org &4000
nolist

jp main

main:
push bc
L1:
pop bc
ret
EffaceEcran:
push bc
ld hl,65536
add hl,sp
push hl
ld hl,6
add hl,sp
call Lgint
pop de
call Lpint
L3:
ld hl,65536
add hl,sp
call Lgint
push hl
ld hl,65280
pop de
call Land
push hl
ld hl,0
pop de
call Lne
ld a,h
or l
jp z,L4
ld hl,65536
add hl,sp
push hl
call Lgint
dec hl
pop de
call Lpint
inc hl
push hl
ld hl,2
pop de
call Lpchar
jp L3
L4:
L2:
pop bc
ret

; DATA

; CRT
Lpint:
ld a,l
ld (de),a
inc de
ld a,h
ld (de),a
ret

Lgint:
ld a,(hl)
inc hl
ld h,(hl)
ld l,a
ret

Lne:
R_crt1:
call Lcmp
ret nz
dec hl
ret

Lpchar:
ld a,l
ld (de),a
ret

Land:
ld a,l
and e
ld l,a
ld a,h
and d
ld h,a
ret

Lcmp:
ld a,e
sub l
ld e,a
ld a,d
sbc a,h
ld hl,1
jp m,Lcmp1
or e
ret
Lcmp1:
or e
scf
ret

Pourtant, si le compilateur C était efficace, je devrais obtenir le même code assembleur en 7 lignes que celui de la ROM du ZX-81.

L’exemple est un peu extrême, car ce compilateur (PhrozenC) est visiblement très inefficace. Ceci dit, même un bon compilateur (de cette époque ou de maintenant) produit un code 2 à 3 fois plus gros et plus lent que l’équivalent écrit à la main en code machine.
D’où la conclusion de tout programmeur qui veut écrire un logiciel raisonnablement rapide pour ce type d’ordinateur: il faut écrire entièrement en code machine.

L’incompatibilité des machines

Mais ici se pose un nouveau problème: un code machine dépend, par définition, d’un type de microprocesseur, et donc est incompatible avec d’autres microprocesseurs.
D’où le dilemme: soit on écrit en code machine et on obtient un logiciel petit et rapide, mais qui ne fonctionnera que sur des ordinateurs disposant du même microprocesseur, soit on écrit dans un langage plus évolué, comme le C, et on obtient un logiciel gros et lent mais plus portable.

Le système aussi est incompatible

À tous ces problèmes vient s’ajouter celui de l’incompatibilité des systèmes d’exploitation, la vraie plaie des années 80.
Même si deux machines ont le même microprocesseur, chacune a son propre système, en général écrit par le fabriquant de la machine.

Au début des années 80, lorsqu’on écrivait un logiciel destiné à plusieurs types de machines, il fallait écrire son architecture en conséquence. Le travail d’adaptation était tel qu’on appelait ça  » réécrire le logiciel pour telle machine« . Autant dire qu’écrire un logiciel pour 3 machines différentes demandait sans doute 4 ou 5 fois plus de travail que pour une seule. Certains logiciels tournaient sur une ou deux dizaines de plateformes, on imagine le travail nécessaire, et la maintenance cauchemardesque.

Il existait un semi-standard à peine émergeant: CP/M, mais il était sans doute trop « lourd » pour être largement installé sur les machines, et plutôt cher il me semble. Je ne l’ai personnellement jamais utilisé.

L’ensemble de ces difficultés explique pourquoi toute l’industrie de l’informatique s’est jeté sur les IBM PC: elle avait besoin d’un standard, pour n’écrire les logiciels et ne créer du matériel que pour une seule plateforme.

L’Amstrad CPC

Durant la première moitié des années 80, on voit une explosion des fabriquant d’ordinateurs, notamment entre 1982 et 1986.
À la fin de l’année 1984, un petit fabriquant d’électronique anglais, Amstrad, se lance sur le marché avec une machine simple et assez bien conçue. Son but n’est pas d’être révolutionnaire, mais d’être accessible aux familles, autant par son bas prix que par sa facilité d’installation et d’utilisation.

À cette époque, on avait le choix entre des machines hors de prix comme les Apple 2, et des ordinateurs plus familiaux comme les Commodore 64. Problème de ces derniers, et de leurs concurrents directs: la machine est vendue seule, il faut lui ajouter un magnétophone pour les sauvegardes et l’accès aux logiciels, un écran (en général une télévision), sans parler d’une éventuelle imprimante, le lecteur de disquette étant vraiment cher. Additionner tout cela pouvait monter facilement à environ 10000 FF, soit disons le tiers du prix d’une voiture.

D’où le choc à Noël 1984 lorsqu’ Amstrad annonce un ordinateur incluant le magnétophone et surtout l’écran, pour 4500 FF (en couleurs, sinon 3000 FF en N&B, il me semble). C’est la moitié du prix du matériel équivalent chez la concurrence.
De plus, bien que classique dans sa conception électronique, ses capacités sont bonnes, souvent meilleures que ses concurrents.

  • Processeur: classique 8 bits Z80 à 4 Mhz.
  • Mémoire 64 Ko. C’est vraiment beaucoup à cette époque, 2 à 4 fois plus que la concurrence.
  • Un vrai clavier, avec un pavé numérique. Le seul à son époque parmi les ordinateurs familiaux.
  • L’écran est de la qualité d’une télévision, mais sans tuner.
  • Le magnétophone est fiable (rare à l’époque), et il est même commandé par l’ordinateur (recherche automatique de fichiers, par exemple).
  • Un Basic intégré étendu très complet et rapide.

À l’époque, je pense que cette machine était une des plus astucieusement conçues, à mon sens globalement bien plus satisfaisante que la concurrence, et en plus bien moins chère.

Le choix classique du Z80 permettait à ceux qui avaient appris sa programmation en langage machine de pouvoir démarrer rapidement leurs essais sur cette toute nouvelle machine.

Au contraire du ZX-81, on peut dire qu’on avait enfin une machine qui permettait de vraiment programmer. Maintenant on pouvait enfin caser en mémoire à la fois un outil de programmation complet et le logiciel qu’on développait. Sur les machines moins puissantes, il fallait morceler les logiciels, ce qui est était lent et pénible à l’emploi.

J’aimerais vous montrer mes recherches de l’époque sur cette machine, mais malheureusement elles n’ont apparemment pas survécu au passage des cassettes aux disquettes.

La Bible du programmeur de l’Amstrad CPC : un sympathique pavé

En ce qui me concerne, c’est avec cette machine que j’ai vraiment commencé à explorer la programmation dans son ensemble. J’avais acheté un gros pavé, un livre appelé « La bible de l’Amstrad CPC » (maintenant téléchargeable en PDF), un classique pour comprendre et maîtriser la machine.

Ce type d’ouvrage est divisé en trois parties:

    * L’électronique de la machine.
    * Le système d’exploitation.
    * Le langage Basic.

Le système y était entièrement décompilé, c’est à dire que dans un premier temps un logiciel (un décompilateur) transforme le contenu de la ROM du système en un code source représentant les instructions machine du Z80 et les données, et dans un deuxième temps plusieurs personnes se sont donné le mal de comprendre et de commenter les 32 ko de la ROM. J’imagine combien de semaines il leur a fallu pour décrypter tout ce code, en expérimentant, en testant les routines système, etc.

Le plus passionnant, c’était de comprendre comment cette machine fonctionnait, d’en disséquer les composants tout autant que la programmation.
Et puis faire le lien entre les routines du système et l’explication sur le fonctionnement des circuits électroniques de la machine. Le but étant de pouvoir écrire un logiciel en langage machine qui puisse programmer directement les circuits, pour avoir un contrôle complet et une vitesse d’exécution maximale.

Autant dire que de telles notions apportent une excellente compréhension des concepts fondateurs des ordinateurs actuels:

  • programmation des circuits (parfait pour écrire des pilotes de périphérique aujourd’hui),
  • optimisation en langage machine (parfait pour programmer les micro-contrôleurs et les systèmes embarqués aujourd’hui, tels que les robots ou les ordinateurs d’avion ou de drone),
  • gestion des ressources, du partage du temps, des interruptions (parfait pour programmer des systèmes d’exploitation),
  • bibliothèque de routines de base (équivalent de la bibliothèque de base de C, ce qui fait qu’on comprend comment ce genre de chose s’écrit et fonctionne en pratique).

Durant mon travail actuel de programmeur, de temps en temps le souvenir d’une technique apprise sur cette ancestrale machine m’aide à résoudre un problème ou simplement à me faire une idée du fonctionnement d’un concept. J’ai par exemple appris dans ce livre comment générer des nombres pseudo-aléatoires, c’est une notion qui continue de m’être utile aujourd’hui. Pareil lorsque j’ai lu comment dessiner une ligne en mode graphique avec des méthodes optimisées, ce type d’optimisation m’a souvent servi dans des domaines pourtant très différents.

Voila une expérience que je suis content d’avoir vécu, car ce fut une époque de découverte, de défrichage, qui ne peut exister qu’une fois dans l’histoire d’une technique: à son départ.
Bien évidemment, on peut fixer le vrai départ de l’informatique dans les années 50, et surtout 60, mais il existe un vrai parallèle dans le monde de l’informatique « accessible », lorsqu’elle a vraiment atteint en masse l’industrie et les familles.

Ceci dit, la machine qui a été pour moi celle du commencement d’une programmation plus évoluée et riche, ça a été l’Atari ST.

L’Atari ST

Avec cette machine, une ère nouvelle s’ouvrait enfin au large public: l’interface graphique.

L’interface graphique est un concept essentiellement né dans les fameux laboratoires du Xerox PARC, durant les années 70.
Mais Xerox n’a pas vraiment produit de machine qui ait pu atteindre le public, que ce soit en entreprise ou en famille. Seuls quelques universitaires avaient accès aux prototypes de Xerox. D’où le mystère qui entourait ce nouveau concept d’interface utilisateur.

En 1985, il existait bien sûr une première matérialisation du concept grâce à Apple et son Lisa, suivi du Macintosh.
Malheureusement, le prix nettement prohibitif de ces machines les éloignait du grand public. Certes certaines entreprises les utilisaient, mais seules quelques personnes y avaient accès puisqu’il s’agit d’un ordinateur personnel.

J’étais jeune et j’ignorais presque tout de l’interface graphique, j’étais imprégné des interfaces textuelles classiques. J’avais certes lu des articles présentant le concept de l’interface graphique et aussi le Lisa, mais franchement il est nécessaire de manier une telle interface pour la comprendre, les mots et même les images sont insuffisants. Il faut la toucher, par la souris, la bouger, avec ses fenêtres, pour en ressentir le mouvement et la logique.

Ça a donc été un choc lorsque j’ai vu pour la 1ère fois un Atari ST, d’abord dans des articles puis dans des magasins.
Cette machine se présentait comme un concurrent du Macintosh, il avait clairement été conçu dans ce sens, mais il était à la fois plus puissant et beaucoup moins cher (à mon souvenir, environ 3 fois moins cher, c’est dire que les marges bénéficiaires d’Apple était déjà très confortables à l’époque).

Voyons à quoi cela ressemble:

  • Un microprocesseur 16/32 bits, le Motorola 68000, à 8 Mhz, excellent.
  • 512 Ko de RAM. Vraiment impressionnant, le Macintosh n’ayant que 128 Ko.
  • Une souris à deux boutons.
  • Un lecteur de disquettes 3,5 pouces, un futur standard (naissant à cette époque) de 720 ko.
  • Un clavier complet, avec des touches de fonction, un pavé numérique.

Bien qu’annoncé en 1985, L’Atari ST est arrivé en France véritablement en 1986, soit deux années après le Macintosh.

Autant l’Amstrad CPC était une machine bonne et bien conçue, mais très classique quant à son électronique, autant l’Atari ST nous faisait passer dans une nouvelle période. Tout était différent: un microprocesseur à code 32 bits, une RAM gigantesque permettant enfin de faire de grandes choses, l’interface graphique qui bousculait les habitudes, et à un moindre degré le lecteur de disquettes enfin devenu une norme (finies les cassettes audio lentes et moins que fiables), et puis aussi un clavier complet presque digne d’un ordinateur professionnel (sauf que le toucher était trop « rebondissant » pour moi).

Sa seule vraie concurrence était le Commodore Amiga, sorti lui aussi avec beaucoup de retard, mais bien plus cher que l’Atari et selon moi moins fourni en logiciels. J’en ai acquis un également, mais plus tard, à cause de son prix, ce qui fait que je ne l’ai jamais autant « pratiqué » que l’Atari; l’Amiga était une excellente machine, qui aurait mérité une meilleure finition de son système d’exploitation (mince, je vais relancer la gué-guerre ST contre Amiga).

Le Motorola 68000

Un programmeur plus jeune pourrait se demander en quoi un microprocesseur 68000 était vraiment différent d’un Z80. On pourrait en effet croire que la différence principale était la vitesse (environ 1 Mips contre 0,2) ou le passage des accès mémoire de 8 à 16 bits. Mais en fait il s’avère qu’une architecture différente peut représenter en soi une avancée et une ouverture vers d’autres possibilités.

Le Z80 est un bon processeur 8 bits, mais fondamentalement son jeu d’instruction est limité à 8 bits pour les données et 16 bits pour les adresses, il n’est pas évolutif. D’ailleurs dans la pratique ce processeur n’a pas eu de suite (commercialement viable en tout cas).
Au contraire, le jeu d’instructions du 68000 avait été minutieusement conçu pour l’avenir. Il était conçu dès le départ pour manipuler des adresses sur 32 bits (une taille restée valable jusqu’en 2011 environ), et des données également sur 32 bits pour l’essentiel. En d’autres termes, un logiciel conçu en 1979 pour un 68000 devait pouvoir tourner sur un descendant du 68000 en 2011, soit pérenne durant 33 ans. Pas mal, pour un milieu aussi mouvant que l’informatique.

À cette époque, le grand concurrent du 68000 était l’Intel 8086. Tout ceux qui ont programmé sur les deux savent à quel point utiliser le 8086 était une torture, en comparaison. Autant le code du 68000 était élégant, facile à lire et à écrire, autant celui du 8086 était tortueux, inutilement complexe et lent.

Pour ce qui est du reste de l’électronique du ST, elle était assez classique, sobre et bien conçue, mais pas révolutionnaire. C’était un ordinateur conçu pour le travail en entreprise, mais il n’a finalement pas rencontré ce marché. Toutefois il a trouvé son public dans les familles.
Son système d’exploitation marque le début d’une nouvelle époque: dorénavant cette partie de la machine demande beaucoup de travail à son fabriquant, sans doute trop pour les petits fabriquant qui avaient fleuri au début des années 80, et qui du coup ont tous brutalement disparu, voir Sainclair, Oric, Amstrad, Acorn, tous les MSX.

En 1986, le ST est donc une machine très intéressante, et ses capacités atteignent enfin un niveau qui permet de programmer à l’aise et de produire des logiciels puissants. Par contre, l’apprentissage de la programmation des interfaces graphiques représente un véritable cap à franchir pour tous les programmeurs qui ont passé beaucoup de temps sur des questions d’optimisation et d’utilisation directe des circuits.
Avec le ST, l’optimisation reste de mise car ces machines ne sont pas encore assez puissantes pour pouvoir se reposer sur un compilateur, mais d’un autre côté, la programmation d’un logiciel à interface graphique n’est pas du tout adaptée au langage machine et oblige donc dans ce cas à utiliser un compilateur (C ou Basic, principalement, sur cette machine).
On peut dire que le programmeur a donc le choix entre deux façons de travailler: l’une plus tournée vers l’efficacité et donc vers les jeux et le multimédia, et l’autre plus vers l’interface et donc vers les logiciels professionnels.

Le premier choix est le plus technique, celui qui réclame le plus de finesse, d’imagination, de maîtrise de la machine, il est aussi sans doute le plus attirant lorsqu’on est jeune, créatif, et qu’on se lance des défis.
Je n’y ai pas échappé, et j’ai donc expérimenté ce type de programmation. Voyons un peu comment ça se passe en pratique.

Claustrophobia

Une vidéo est disponible sur Dailymotion. Malheureusement, on dirait que le lecteur flash la limite à 25 fps au lieu de 50. Moi qui était si fier de mes 50 fps !  😉







C’est un jeu en 2D dans lequel une tête se balade dans un château en volant, et doit récupérer ses membres perdus. On se demande comment cette tête peut se déplacer sans jambe et même sans corps, mais peu importe, elle vole !

D’un point de vue technique, déplacer cette tête a été un vrai casse-tête, justement.
Je ne voulais pas faire des « salles » séparées par des portes comme au temps des ordinateurs 8 bits, donc c’est le décor qui devait défiler.
Problème: l’électronique du ST ne permettait pas de faire défiler un écran, il fallait réécrire tout l’écran à chaque déplacement, du moins avec les premières versions du ST.
Comme le microprocesseur était un peu trop lent pour parvenir à redessiner l’écran 50 fois par seconde (oui, j’aime les défilements parfaits), j’ai dû à la fois réduire la taille de la zone de jeu (d’où les bordures vertes) et réduire le nombre de couleurs du décor. En fait le décor est réduit à quatre petites couleurs, alors que l’ordinateur pouvait en afficher 16. En nombre de bits, j’avais donc réduit la quantité de données de moitié par les couleurs, plus une petite réduction par les bordures, donc ouf!, l’animation était finalement parfaite.

Pour compenser le manque de couleurs du décor, j’ai intercepté les interruptions de « balayage horizontal » pour faire varier les couleurs verticalement.
Le balayage, c’est l’interruption qui se produit à chaque début de traçage d’une ligne horizontale de l’écran, soit environ 15000 fois par seconde. En termes de langages de programmation modernes, on appellerait peut-être ça un « évènement », mais ici il s’agit d’interruptions matérielles générées par le circuit graphique et directement reçues par le microprocesseur.

Étant donnée que le processeur ne fonctionne qu’à environ 1 Mips, 15000 interruptions à traiter chaque seconde consomment une bonne partie de son activité, d’où la nécessité de réutiliser ces interruptions pour générer en même temps les sons numériques.
Je rappelle qu’à cette époque, c’était le tout début des sons numériques sur ordinateurs. Auparavant, seuls des sons synthétiques étaient joués, d’où des bruitages simplistes mais mémorables dans les jeux d’arcade.

L’ennui avec le ST, c’est qu’il n’a pas été conçu comme une console de jeux (contrairement à son concurrent l’Amiga, oui j’attise la gué-guerre), et ne disposait pas d’un DMA pour gérer le son. Il devait ‘à la main’ modifier le son, quelques dizaines de milliers de fois par seconde.

Cet exemple de double utilisation d’une interruption, montre que l’optimisation d’un logiciel devait être globale, ici il a fallu programmer entièrement en langage machine, car presque chaque cycle d’instruction comptait.

Plus haut, une image montre l »écran d’accueil de la démo, qui présentait des couleurs.
Cet écran illustre bien la possibilité du changement de palettes. Chaque ligne horizontal affiche ici 24 couleurs différentes. Sachant que le ST était normalement limité à 16 couleurs pour la totalité de l’écran, on voit bien qu’il a fallu modifier cette palette à chaque ligne, et même plusieurs fois par ligne.

Voyons un peu à quoi ressemble le code machine 68000.

En résumé, le 68000 dispose de 8 registres de données en 32 bits et 8 registres d’adresse en 32 bits (servant de pointeur). Il n’existe pas de registre particulier (type Accumulateur en Z80 ou certains autres en 8086, que j’ai oublié – c’est dire si ce dernier processeur m’a peu passionné). Tous les registres de données sont généraux.

Par chance, il me reste une partie de mes codes sources de l’époque. J’ai quand même dû écrire un logiciel pour pouvoir relire les disquettes sous Windows, à cause de limitations de Windows NT.

e2i38:
move.l #e2coul1,$ffff825a.w
move.b #1,$fffffa21.w
move.l #e2i39,$120.w
bclr #0,$fffffa0f.w
rte

e2i39:; Avant-dernière inteeruption HBL.
move.l #e2coul1,$ffff825a.w
move.b #1,$fffffa21.w; laisser toujours 1.
move.l #e2i40,$120.w
bclr #0,$fffffa0f.w
rte

e2i40:; Dernière interruption HBL.
move.l #e2coul2,$ffff825a.w
;bset #3,$fffffa17.w
bclr #0,$fffffa0f.w
bclr #0,$fffffa13.w
rte

Cet exemple montre des routines qui traitent l’interruption des lignes d’écran (« HBL = horizontal blank line »).
On peut remarquer qu’elles se chaînent (par le move.l #e2i39,$120.w). En effet, au lieu de lire le contenu d’un tableau par indirection et d’incrémenter un index à chaque appel, j’ai préféré que chaque routine ne lise qu’une simple variable, puis elle modifie le vecteur (l’adresse de la routine) de l’interruption.
Ainsi, le code est plus rapide. Par contre il a nécessité l’écriture de 40 routines différentes. J’avais bien sûr utilisé un générateur de macros pour les créer.
Le gain peut paraître faible, mais il a lieu plus de 15000 fois par seconde. Sur ce type de machine, il faut savoir économiser le moindre cycle d’instruction.

À noter que des instructions d’indirection complexe sont apparus avec les versions suivantes du 68000. De plus le cache RAM change le calcul du temps d’exécution sur ces processeurs.
L’optimisation n’est pas toujours une activité pérenne, elle n’est efficace que temporairement, dans un contexte précis. Toutefois, ses principes restent valables et utiles.

La gué-guerre 68000 contre 8086

Cet exemple montre également que le 68000 gère effectivement les données et les adresses en 32 bits.
À titre de comparaison, son concurrent, le 8086, ne gère que des données en 16 bits et doit donc s’y prendre à plusieurs fois pour une seule donnée. De plus, sauf erreur, le 8086 ne peut pas écrire une valeur dans une variable (une case mémoire) en une seule instruction: il doit passer par l’intermédiaire d’un registre. D’où le véritable jonglage permanent de registres, d’autant que ses registres sont, en plus, spécialisés: on ne peut tout faire avec n’importe quel registre. Et hop, vive la jongle !
Et je ne parle pas de cette ignominie du 8086 que sont les Segments.
On voit ici par contre que le 68000 peut en une seule instruction écrire une valeur 32 bits dans une variable.

Si je voulais être mauvaise langue, je dirais qu’Intel et Microsoft ont ceci de commun qu’ils n’ont jamais eu besoin de sortir de bons produits, car il leur suffisait de représenter un standard.
Bon, c’est un peu faux car Intel a quand même eu un peu de concurrence avec AMD, durant quelques courtes années.  😉

Enfin bon, les compilateurs cachent toutes les plaies (c’est à dire le code machine).

Les outils improbables

Pour mon travail, j’avais aussi créé des tas d’outils en tous genres, qui peuvent paraître bizarroïdes maintenant, mais qui à l’époque me rendaient de bons services.

  • L’assembleur en Reset
    Mon outil préféré était un assembleur-désassembleur-débogueur-éditeur appelé K-Seka. Il était très pratique car il avait tout en un seul programme. Un peu un IDE rudimentaire, quoi.
    Mon problème était qu’à cette époque il n’existait pas de protection de mémoire dans le système d’exploitation, donc un logiciel pouvait joyeusement faire planter le système entier !
    Inutile de dire qu’écrire un jeu, lequel manipule les circuits intégrés directement, ça fait planter souvent.
    J’avais donc modifié cet assembleur pour intercepter la remise à zéro du ST, lorsqu’on presse la touche Reset à l’arrière de la machine, et remettre le système en état de fonctionner, notamment remettre tous les circuits dans un état valide, puis donner la main au débogueur de K-Seka.
    Imaginez: vous lancez votre jeu, il plante, vous pressez le bouton Reset, et hop!, vous vous retrouvez dans votre IDE. Magique !
    Quel gain temps, comparé avec devoir redémarrer la machine et recharger l’IDE.
  • Un filtreur graphique en simili-4096 couleurs
    Je m’en servais pour récupérer les images du numériseur, via un magnétoscope, et pour les traiter: réduction à 512 ou à 16 couleurs avec des contraintes de palette, détramage, débruitage, moyennage sur plusieurs images (vue la faible qualité des magnétoscopes), ajustage de la luminosité, séparation du fond, etc.
    J’avais besoin d’afficher les images dans un maximum de couleurs, or comme le ST était limité à 16 couleurs simultanées, j’utilisais à la fois la technique du changement de palette 3 fois par ligne, plus un clignotement (tramé pour ne pas trop me bousiller le cerveau), et enfin un tramage en affichage.
  • Des éditeurs de niveaux
    Forcément, ils sont nécessaires pour créer le décor des jeux, placer les obstacles ou les personnages, etc.
    Je pouvais lancer une version limitée du jeu à tout moment pour tester le niveau, puis revenir à l’éditeur.
    Ce type d’outil était programmé en Basic (avec GFA-Basic), car on programme beaucoup plus vite ainsi qu’en langage machine, avec moins d’erreurs, et que la vitesse d’exécution ne pose pas de problème.
    Le GFA-Basic permettait aussi d’écrire une interface graphique simple sans trop d’effort.
  • Un constructeur de macro-instructions
    Pour des besoins particuliers, j’avais besoin de créer des morceaux de code machine assez longs et répétitifs mais nécessaires pour ne pas perdre de précieux cycles d’exécution.
    Le 68000 disposait par exemple d’une instruction Movem qui pouvait à elle seule empiler plusieurs ou même tous les registres du processeur. Il était courant de la détourner de son but pour copier ou écrire des blocs complets de mémoire avec un minimum d’instructions.
    « movem.l d1-d7/a0-a5,-(a6) » peut ainsi écrire 52 octets en une seule instruction. Toutefois, cela occupe les registres. J’avais donc écrit différentes macros pour gérer les instructions et les registres en fonction de l’effet désiré, avec des paramètres.
    C’est typiquement le genre d’outil qui aujourd’hui ne s’utiliserait que dans un contexte très particulier, comme dans une routine essentielle dans un jeu, ou dans une analyse ou un tracé en boucle pour un robot par exemple.
  • Un formateur de disquettes avec sur-capacité et « protection »
    Une fois que j’ai su programmer le circuit contrôlant le lecteur de disquettes, j’ai commencé à jouer avec la capacité des disquettes. Sur le ST on pouvait ainsi facilement passer de 720 ko à 800 ko en toute sécurité, voire 880 ko avec des ralentissements et une fiabilité incertaine.
    On pouvait aussi formater d’une façon particulière pour éviter les copies pirates. À cette époque il y avait une vraie escalade entre les « déplombeurs » et les éditeurs de logiciels. Chaque nouveau type de protection entrainait une réplique sous forme d’un logiciel de copie.
    Cela rendait ce domaine assez stratégique et également intéressant d’un point de vue intellectuel.
    Ce genre de connaissance m’a permis d’écrire récemment un logiciel de récupération des vieilles disquettes ST, sous Windows. Il m’a fallu réviser le mode MFM , pour me rappeler des codes de correction de données et autres joyeusetés, ça m’a un peu rappelé le bon vieux temps. 🙂
    À l’époque j’avais écrit un mode de protection de disquette dont je m’étais servi pour envoyer une démo de jeu à des éditeurs. Je me rappelle encore l’un d’eux se plaignant de n’être pas parvenu à copier la disquette pour ses collaborateurs. Ah ah ! Il avait essayé tous les logiciels de copie du marché, en vain, ça m’avait bien fait rire (ce qu’on peut être bête, à c’t’âge ! Je parle de moi..).
  • Un module lecteur de fichiers en multi-tâches
    Il permettait de charger des fichiers en RAM durant un jeu tout en continuant l’activité en cours. Par exemple, on pouvait jouer à un niveau pendant que le ST chargeait le prochain niveau.
    Ce genre de chose nécessitait une bonne connaissance du contrôleur de disquette, pour tout gérer par interruptions. En comparaison, le système du ST bloquait tout l’ordinateur lorsqu’il accédait à un fichier, et il ne savait pas accèder en parallèle à plusieurs fichiers.

Etc. J’ai presque tout oublié, tellement ces outils étaient nombreux et souvent particuliers à un besoin temporaire.
C’était vraiment l’époque de la débrouille et de la créativité. Il fallait à tout moment être assez inventif et ingénieux pour trouver une méthode qui permettrait d’obtenir un meilleur résultat, ou bien qui faciliterait ou raccourcirait le travail.
D’où ma façon personnelle de programmer: faire plus au départ pour faire beaucoup moins sur l’ensemble d’un projet. Ce que certains appellent perdre du temps pour mieux en gagner.

Car crash

Une vidéo est disponible sur Dailymotion. Malheureusement, on dirait que le lecteur flash la limite à 25 fps au lieu de 50.

C’est un jeu de voitures, comme on peut le voir.





Tramage et clignotement:
La première image introduit le jeu, le temps de le charger (en environ 40 secondes).
Pour améliorer l’image, j’ai utilisé un système de clignotement des pixels, histoire de simuler un dégradé de 16 niveaux d’orange au lieu de 8.
Mais là où j’ai passé du temps, c’est sur une chose qui ne se remarque pas: la structure du « tramage ». J’appelle tramage l’effet de points qui comble en quelque sorte le manque de niveaux dans le dégradé. Il existe des formules de tramage toutes faites, mais elles donnent un résultat soit trop grossier soit trop régulier. D’où du temps passé à chercher une meilleure méthode, adaptée à une basse résolution et de gros pixels. C’est par exemple un domaine de recherche pour les ingénieurs travaillant pour les fabriquant d’imprimantes.

Palette variable verticalement:
Sur les images du jeu proprement dit, on voit que pour améliorer les couleurs (problème récurrent sur ces machines, jusqu’en 1993 environ), j’ai utilisé tout autant le tramage (notamment dans le ciel) que le changement de palette vertical par interruption (comme décrit ci-dessus pour Claustrauphobia).

Calculs en 3D:
Contrairement à presque tous les jeux de voiture de l’époque, les calculs de la route étaient en vraies 3D. Il faut savoir que ce type de microprocesseur ne dispose pas d’unité de calculs en virgule flottante, et qu’une simple multiplication entière 16 bits * 32 bits prend environ 60 à 200 cycles d’instruction (à mon souvenir). Lorsqu’on doit effectuer beaucoup de calculs, et qu’on tente d’obtenir 50 images par seconde, ça devient vite un casse-tête qui nécessite des tas de caches de pré-calculs et d’optimisations diverses et variées.

Zoom pré-calculé et étirement vertical:
Les « sprites » (les images qui se déplacent sur l’écran) avaient, pour leur zoom, une taille variable pré-calculée (encore une petite optimisation), mais comme cela occupait finalement beaucoup de place en RAM (imaginez: toutes les tailles affichables d’un sprite !), j’avais fait une autre optimisation spéciale aux tailles les plus grandes: les lignes horizontales y étaient dupliquées lors du dessin.
Sur une image, on voit que le palmier le plus grand est en quelques sortes « étiré » en hauteur, ses pixels sont rectangulaires, plus hauts que larges. C’est donc essentiellement pour une économie de RAM.
Petite astuce, grosse économie de RAM.

Le jeu était sensé comporter un aspect aventures, j’avais donc présenté des images fixes de décors accompagnant l’histoire.

La difficulté était que le ST ne dispose que de 16 couleurs simultanées, choisies parmi 512. On est loin des 16 millions modernes.
Pour pallier ce manque de couleurs, j’ai utilisé une technique assez classique sur cet ordinateur: afficher 16 couleurs différentes sur chaque ligne horizontale, ce qui permet de démultiplier les possibilités.
En fait c’est même plus que ça car on change trois fois la palette de 16 couleurs sur chaque ligne horizontale.
Si on regarde attentivement cette image, on voit qu’il y a parfois des petits traits pleins horizontaux: c’est lorsque l’algorithme que j’avais créé pour la circonstance n’a pas pu trouver assez de couleurs à un endroit donné, malgré toutes les variations de palette.
C’est beaucoup de complications pour un peu plus de couleurs. Le principal problème, c’est que cela occupe complètement le microprocesseur, et ce durant environ 64 % du temps. À noter que l’Amiga n’a pas ce problème puisqu’il dispose d’un circuit programmable capable de gérer à lui seul ce type de changement de palette, sans compter son mode HAM.

Conclusion

Comme on peut le voir, ce type de programmation consiste à passer des jours à optimiser chaque petit détail à peine visible à l’écran, mais dont la somme fera au final la différence entre un logiciel rapide et un autre saccadé (et souvent moche en prime).

Voila pourquoi selon moi c’est un genre de programmation très pointu, très formateur car on y apprend toutes sortes de techniques. Il nous rend très minutieux à cause des nécessaires optimisations, et très prévoyant car une erreur de structure dans un programme en langage machine oblige souvent à le restructurer en grande partie.

J’ai aussi écrit ce petit article car bien souvent lorsqu’un programmeur dit qu’il écrit des jeux, les professionnels du secteur informatique l’imaginent en train de jouer devant sa console toute la journée, alors que c’est bien souvent l’inverse: ce type de travail demande plus de technicité, de sérieux et de compétence que bien d’autres travaux de programmation.
En ce qui me concerne, créer une application bureautique me demande moins d’efforts, ce sont presque des vacances, en comparaison, du boulot bien pépère !  😉

De l’époque des premiers ordinateurs familiaux, j’ai gardé le goût du travail bien exécuté, bien pensé au départ, minutieux et pérenne, et aussi la passion d’une certaine forme de programmation, où la créativité a autant sa place que le sérieux, car les deux se complètent.

Espérons que dans le futur la programmation reste un plaisir pour tous les programmeurs !  🙂

Publicités
 
1 commentaire

Publié par le 2012-09-03 dans Programmation

 

Différence en C# entre new et override lors du remplacement d’une fonction à hériter

Au départ, un débutant en C# se demande quelle peut bien être la différence entre new et override, et lequel choisir lorsqu’il souhaite remplacer une méthode dans une classe héritante.

Vocabulaire utilisé ici

  • Classe à hériter = classe de base.
  • Classe héritante = classe dérivée (elle hérite de la classe de base).

En une phrase

Avec override (et donc virtual), le code de la classe à hériter (la classe de base) appellera soit sa propre méthode virtual, soit la méthode d’une classe héritante (dérivée de cette classe de base) si celle-ci la remplace avec override.

Exemple montrant la différence

Le code:

public class ClasseÀHériter
{
    public string FonctionNormale()
    {
        return "FonctionNormale dans la classe de base";
    }
    public virtual string FonctionExplicitementRemplaçable()
    {
        return "FonctionExplicitementRemplaçable dans la classe de base ";
    }
    public string Résultat()
    {
        return
            this.FonctionNormale()  // Appelle toujours la fonction définie dans cette classe.
            + "\n"
            + this.FonctionExplicitementRemplaçable(); // La fonction appelée a pu être remplacée dans une classe héritante.
    }
}

public class ClasseHéritante : ClasseÀHériter
{
    public new string FonctionNormale()
    {
        return "FonctionNormale dans la classe dérivée";
    }
    public override string FonctionExplicitementRemplaçable()
    {
        return "FonctionExplicitementRemplaçable dans la classe dérivée";
    }
    public string AutreRésultat()
    {
        return
            this.FonctionNormale()
            + "\n"
            + this.FonctionExplicitementRemplaçable();
    }
}

public MainWindow()
{
    InitializeComponent();

    // ------------------

    ClasseÀHériter càh = new ClasseÀHériter();
    string scàh = càh.Résultat();

    ClasseHéritante ch = new ClasseHéritante();

    string schr = ch.Résultat();
    string scàhar = ch.AutreRésultat();
}

Résultats:

Classe utilisée Méthode appelée Texte renvoyé par FonctionNormale() Texte renvoyé par FonctionExplicitementRemplaçable()
ClasseÀHériter Résultat() de ClasseÀHériter FonctionNormale dans la classe de base FonctionExplicitementRemplaçable dans la classe de base
ClasseHéritante Résultat() de ClasseÀHériter FonctionNormale dans la classe de base FonctionExplicitementRemplaçable dans la classe dérivée
ClasseHéritante AutreRésultat() de ClasseHéritante FonctionNormale dans la classe dérivée FonctionExplicitementRemplaçable dans la classe dérivée

Interprétation:

  • Lorsqu’on instancie ClasseÀHériter, elle utilise ses propres fonctions.
  • Lorsqu’on hérite de ClasseÀHériter dans ClasseHéritante, la méthode FonctionNormale() appartenant à ClasseÀHériter utilise la méthode FonctionExplicitementRemplaçable() remplacée par ClasseHéritante avec override.
  • Lorsqu’on hérite de ClasseÀHériter (dans ClasseHéritante), la méthode AutreRésultat() de ClasseHéritante utilise les deux méthodes remplacées (avec new et avec override).

Aspect technique

Alors que new se contente de définir une méthode dont le nom remplace celui de la classe à hériter, override redirige les appels à la méthode remplacée même pour le code de la classe de base à hériter.
Cela implique de placer dans la partie statique de la classe à hériter, et dans toutes ses dérivées, un pointeur (un délégué, si vous voulez) qui permet au code de la classe à hériter de trouver un éventuel remplacement (par override) dans les classes héritantes.

Simulation de la virtualisation

Pour comprendre le mécanisme, voici une sorte d’écriture manuelle d’une méthode virtualisée dans une classe:

public class SimulationDeVirtualisation
{
    public delegate string ModèleDeLaMéthodeÀVirtualiser();

    public ModèleDeLaMéthodeÀVirtualiser RedirecteurVersLaMéthodeÀUtiliser; // En fait devrait être statique.

    public SimulationDeVirtualisation() // Constructeur:
    {
        RedirecteurVersLaMéthodeÀUtiliser = MéthodeDebaseRemplaçable;
    }

    private string MéthodeDebaseRemplaçable()
    {
        return "Méthode dans la classe de base";
    }

    public string DitSiMéthodeRemplacée()
    {
        return RedirecteurVersLaMéthodeÀUtiliser();
    }
}

public class ClasseHéritanteAvecMéthodeVirtualisée : SimulationDeVirtualisation
{
    public ClasseHéritanteAvecMéthodeVirtualisée() // Constructeur:
    {
        RedirecteurVersLaMéthodeÀUtiliser = MéthodeDebaseRemplaçante;
    }

    static private string MéthodeDebaseRemplaçante()
    {
        return "Méthode dans la classe dérivée";
    }
}
   
public MainWindow()
{
    InitializeComponent();

    // ------------------

    SimulationDeVirtualisation sv = new SimulationDeVirtualisation();
    string tsv = sv.DitSiMéthodeRemplacée();    // Renvoie "Méthode dans la classe de base".

    ClasseHéritanteAvecMéthodeVirtualisée chamv = new ClasseHéritanteAvecMéthodeVirtualisée();
    string tchamv = chamv.DitSiMéthodeRemplacée(); // Renvoie "Méthode dans la classe dérivée".
}

Je n’ai pas pu implémenter aussi parfaitement que je l’aurai voulu, à cause de limitations de C#, mais on voit bien que la classe de base utilise soit sa propre fonction virtuelle, soit la fonction remplaçante implémentée dans la classe dérivée.

À noter que RedirecteurVersLaMéthodeÀUtiliser devrait être statique, aussi bien dans la classe de base que dans chaque dérivation de cette classe, et que dans ce cas il est inutile de l’initialiser dans le constructeur de chaque classe.

Bien entendu, le compilateur C# s’occupe de ces détails à notre place lorsqu’on utilise les mots-clés virtual et override.
Mais il est bon de savoir ce qu’implique cette utilisation, en terme de ressources et de performances.

Conclusion(s)

  • Virtual vous est utile lorsque vous écrivez une classe à hériter (une classe de base), et que vous voulez y utiliser des informations qui n’existeront que dans les classes qui en hériteront.
  • L’utilisation de Virtual entraîne l’ajout d’un pointeur caché (au sens du C) dans la partie statique des classes à hériter et des classes héritantes, et une redirection dans le code de la classe à hériter. Soit un peu plus de complication.
    Mieux vaut donc éviter de créer des classes virtuelles et leur préférer des remplacements par new lorsque c’est possible. Surtout pour des petites classes souvent instanciées.
  •  
Poster un commentaire

Publié par le 2012-06-24 dans Programmation

 

Étiquettes : , , , , , , , , , ,

Installer les Additions de Virtualbox dans Windows 8 Consumer Preview, et éviter l’écran noir

Installer Windows 8 Consumer Preview sous VirtualBox 4.1.10 ne m’a posé aucun problème. Par contre, installer les Additions de VirtualBox s’est révélé problématique.
Pourtant, J’en avais besoin pour utiliser le partage de fichiers. Le problème se situe dans le pilote de la carte graphique: à la fin de l’installation des Additions, et aussi au redémarrage du système, un horrible écran noir s’affiche.

La solution

Ma solution permet d’avoir les avantages des Additions, hormis le pilote graphique, que l’on doit désactiver. Ces avantages incluent notamment le partage des fichiers.

Première étape: activer le menu de démarrage proposant le mode sans échec

Comme beaucoup l’ont remarqué, Windows 8 ne propose pas par défaut ce menu.
Heureusement, Korben nous propose une méthode pour l’activer.
Il va nous être nécessaire, donc avant de continuer ma procédure, suivez les instructions disponibles sur son site (en français): https://korben.info/windows-8-mode-sans-echec-2.html

Deuxième étape: Installer les Additions

(j’écris tout ça de mémoire, il se peut que les textes soient légèrement différents de ce que j’ai noté ici)

  1. Assurez-vous que la configuration de votre machine virtuelle utilise bien l’accélération 3D, et que la mémoire vidéo est réglée sur 128 Mo.
    Je ne suis pas sûr que ces deux réglages soient nécessaires, mais je sais que la méthode fonctionne, ainsi.
  2. Lancez votre machine virtuelle et Windows 8 en mode normal, puis ouvrez une session administrateur.
  3. Lancez l’installation des Additions de VirtualBox. Remarquez que celle-ci nous impose le pilote expérimental Direct3D.
  4. Lorsque la première confirmation d’installation d’un pilote Oracle s’ouvre, pensez à cocher la case « Toujours faire confiance aux pilotes d’Oracle » (ou un texte proche de ça).
  5. L’installation se poursuit jusqu’à ce que l’écran devienne tout noir.
    À partir de là, attendez quelques minutes, pour laisser le temps à l’installeur de finir son travail, car il n’est pas bloqué, bien qu’on ne le voie pas.

Troisième étape: Désactiver le pilote graphique de VirtualBox

  1. Ensuite forcez le redémarrage de la machine virtuelle.
  2. Démarrez Windows 8 en mode sans échec.
    La première fois, Windows redémarre encore un coup, c’est normal.
  3. En mode sans échec, ouvrez une session administrateur.
  4. Ouvrez le panneau de configuration du matériel:
    Windows+R et le nom:
    DEVMGMT.MSC
  5. Dans la partie Carte graphique, faites un clic droit sur le pilote graphique « VirtualBox Graphics Adapter (Microsoft Corporation – WDDM)« , et choisissez le menu Mettre à jour le pilote.
  6. Dans le panneau suivant, choisissez Recherchez un pilote sur mon ordinateur..
  7. Dans le panneau suivant, choisissez Rechercher parmi une liste de pilotes de périphériques sur mon ordinateur.
    Ça nous parle de pilotes compatibles avec ce matériel.
  8. Une liste de deux pilotes apparaît, le pilote normal « Carte vidéo de base Microsoft« , et le pilote « VirtualBox Graphics Adapter (Microsoft Corporation – WDDM)« .
    Choisissez le premier, le pilote de base, et validez.
  9. Redémarrez Windows 8 en mode normal. Il devrait démarrer normalement, tel qu’il était avant l’installation des Additions.

Seulement maintenant vous bénéficiez des avantages des Additions (hormis dans le domaine graphique), notamment le partage des fichiers.

J’espère que ça marchera aussi bien pour vous que ça a marché pour moi.   🙂

 
Poster un commentaire

Publié par le 2012-03-29 dans Astuces

 

Étiquettes : , , ,

Arrêter Windows 8 avec une simple combinaison de touches

Avec Windows, pour arrêter l’ordinateur ou fermer une session utilisateur, il faut passer par plusieurs étapes, ce qui est plutôt pénible à la longue.
C’est même encore plus complexe et pénible avec Windows 8.

Pourtant il existe un moyen de se faciliter la vie.


A. Une combinaison de touches et un raccourci pour fermer la session utilisateur:

Voici les étapes détaillées:

  1. Ouvrez l’explorateur de fichiers (Windows+E).
  2. Choisissez un répertoire pour y créer des fichiers, par exemple Documents.
  3. Ouvrez le bloc-note de Windows (Windows+R, puis tapez notepad, puis validez).
  4. Tapez ce texte:
    shutdown /L
  5. Ouvrez le menu Fichier / Enregistrer sous…
  6. Changez le Type de fichier pour Tous les fichiers.
  7. Entrez ce nom de fichier:
    Ferme la session utilisateur.cmd
  8. Cliquez sur Enregistrer.
  9. Fermez le bloc-note.
  10. Dans l’explorateur de fichiers, vous trouverez alors le fichier que vous venez de créer.
    Il devrait être de type Script de commande Windows.
    Copiez-le.
  11. Affichez le bureau (Windows+D).
  12. Faites un clic-droit sur le bureau et choisissez Coller le raccourci.
  13. Affichez les propriétés de ce nouveau raccourci (clic-droit dessus, puis Propriétés).
  14. Cliquez dans la zone Touches de raccourci, là où il y a écrit pour l’instant Aucun.
  15. Tapez au clavier la combinaison de touches de votre choix pour fermer une session,
    par exemple AltGr+S.
  16. Validez en cliquant sur OK.
  17. Essayez votre combinaison de touches (par exemple AltGr+S), ce qui va fermer votre session.
    ATTENTION, pensez à sauvegarder vos documents, si vous en avez ouvert (conseil général avant de fermer Windows ou une session).

Normalement, la session va se fermer.
Dorénavant vous pourrez fermer la session soit par la combinaison de touches, soit en cliquant sur le raccourci sur le bureau.


B. Une combinaison de touches et un raccourci pour arrêter l’ordinateur:

La procédure est la même, sauf que le texte à taper dans le bloc-note est:
shutdown /S      pour arrêter l’ordinateur avec une annonce et un délai d’une minute.
shutdown /P      pour arrêter l’ordinateur immédiatement, sans délai ni annonce.


C. D’autres possibilités:

La même commande (shutdown) offre diverses autres possibilités qui peuvent vous être utiles:

  • shutdown /R      pour redémarrer l’ordinateur.
  • shutdown /H      pour mettre l’ordinateur en veille prolongée (s’il est configuré pour cela).
  • shutdown /S /HYBRID      pour mettre l’ordinateur en veille « hybride » (s’il est configuré pour cela).

Il existe en fait beaucoup d’options à cette commande.
Pour les connaître, il vous suffit de les demander:

  1. Ouvrez une console de commande en mode texte
    (Windows+R puis entrez CMD puis validez).
  2. Tapez ce texte:
    shutdown /?
  3. Validez avec la touche Entrée.
  4. Vous pouvez agrandir la fenêtre pour mieux voir le texte.


Une icône pour mieux repérer le raccourci

Tout raccourci peut afficher l’icône de votre choix.
Il vous suffit d’afficher les propriétés du raccourci, et d’appuyer sur le bouton Changer d’icône.

Voila, j’espère que ça vous sera utile.

 
Poster un commentaire

Publié par le 2012-03-28 dans Astuces

 

Étiquettes : , ,

ST Recover 1.0

Bonjour !

Pour inaugurer ce nouveau blog, je vais vous présenter mon nouveau petit logiciel: ST Recover.

Vous le trouverez ici:
https://strecover.codeplex.com/

Description du projet

ST Recover permet de transférer des disquettes d’Atari ST vers un PC sous Windows, y compris les formats spéciaux tels que 800 ou 900 Ko et les disquettes endommagées ou désynchronisées, et produit des fichiers images standards de disquettes en .ST. Ensuite les fichiers images peuvent être lues par des émulateurs de ST, comme WinSTon ou Steem.


disquette ST -> lecteur de disquettes PC -> fichier image de disquette .ST

Captures d’écran

Configuration requise

  • Un PC avec un lecteur de disquettes.Interne si possible, mais un externe peut être utilisé (avec des limitations).
  • Windows.Devrait être compatible avec Windows 8,7,Vista,XP,2000,ME,98,95 et suivants.Testé avec Vista.

Installation

Il y a 4 étapes:

  1. Si vous avec un lecteur de disquettes interne (pas un lecteur externe USB),téléchargez et installez le pilote de lecteur de disquettes, à partir d’un site web tiers.C’est une option (mais nécessaire pour les formats spéciaux) et vous aurez besoin de droits d’aministrateur.
  2. Téléchargez le fichier Zip de ST Recover.
  3. Extrayez-le.
  4. Lancez ST_Recover.exe .Il n’y a pas d’installateur, donc il est portable.

Utilisation

  1. Lancez ST Recover.
  2. Insérez une disquette ST dans le lecteur du PC.
  3. Si nécessaire, sélectionnez le bon lecteur (A ou B).
  4. Cliquez sur « Read disk and save image file« .
  5. Choisissez un emplacement et le nom du fichier image à créer.
  6. Attendez.

Les particularités

1.
Normalement, Windows ne peut pas lire les formats spéciaux (tels que 800 ou 900 Ko) à cause de limitations de son pilote de lecteur de disquettes.
Malheureusement, ces formats sont très utilisés dans le monde du ST.
ST Recover profite d’un pilote gratuit qui peut lire ces formats spéciaux.

2.
Un effort a été fait pour la récupération de disquettes désynchronisées ou endommagées.

3.
Vous pouvez afficher la géographie des secteurs sur votre disquette:

Ceci représente la surface d’une face d’une vraie disquette de 800 Ko. La ligne noire à droite est une marque virtuelle de synchronisation.

Sur votre PC réel, un lecteur non-USB est nécessaire pour les formats spéciaux

Lecteur de disquettes externe (USB).Limité à:

  • 360 Ko
  • 720 Ko
Lecteur de disquettes interne.Permet tous les formats:

  • 360 Ko
  • 720 Ko
  • 400 Ko
  • 800 Ko
  • 450 Ko
  • 900 Ko

Etc..

Avec un lecteur de disquette USB, ST Recover ne peut pas lire les formats spéciaux, à cause des limitations de cette interface.

Toutefois un lecteur USB peut lire les formats normaux tels que 360 ou 720 Ko.

Analyse de la surface

Si votre disquette parait endommagée, ou juste par curiosité, cliquez sur « Analyze surface » pour voir une analyse géographique des secteurs sur la disquette.

Chaque « cercle découpé » représente une Piste (la couleur est alternée d’une piste à l’autre), et chaque morceau de ce cercle représente un Secteur, qui est un paquet de 512 octets (en général).

La ligne sur la droite représente l’emplacement de la marque virtuelle de synchronisation sur la disquette. Les secteurs sont lus dans le sens inverse des aiguilles d’une montre à partir de cette marque.

Cette représentation est calculée à partir d’une analyse temporale effectuée durant la lecture des secteurs. Donc elle représente la disposition réelle des secteurs sur la disquette (à l’exception du diamètre des cercles internes, qui est relativement plus grande en réalité).

Il est intéressant de noter que les secteurs externes occupent plus d’espace physique que les secteurs internes (en réalité ils sont environ deux fois plus grands). Ceci explique pourquoi les premiers secteurs (la piste 0 est la piste la plus externe) sont considérés comme plus sûrs que les derniers secteurs (la piste interne est la dernière) : plus de surface magnétique pour la même quantité de données.

Sur les disques-durs modernes, la surface des secteurs est (pratiquement) constante, ce qui permet de gagner 50% de secteurs en plus mais nécessite un traitement un (peu) plus complexe. Sur les cdroms, la surface/secteur est constante mais la vitesse de rotation est variable. De toutes façons bien des techniques ont changé depuis le vieux temps des disquettes, MFM a heureusement disparu, on a une surface/secteur constante, il y a plus de deux niveaux par information, etc..

Questions fréquentes

  • Le logiciel dit « No disk in drive » mais il y a bien une disquette !
    • Peut-être que le tout premier secteur, le secteur de démarrage, n’est pas lu correctement.Essayez de nouveau de lire la disquette, ça devrait marcher après quelques essais.
  • Que signifient les couleurs dans les Tables des secteurs ?
    • Blanc: pas analysé pour le moment.
    • Vert: lu (sans problème).
    • Bleu foncé: lu (avec plus d’analyse).
    • Rouge: n’a pas pu être lu du tout (peut-être endommagé physiquement), même après plusieurs essais.
  • Que se passe-t-il si un secteur ne peut pas être lu ?
    • ST Recover replacera ses données par une phrase répétitive, de façon à vous faciliter sa détection.Ça devrait être « ======== SORRY, THIS SECTOR CANNOT BE READ FROM FLOPPY DISK BY ST RECOVER. ======== », ou quelque chose de ressemblant.Dans les Tables de secteurs, ce secteur sera marqué en rouge.
  • Dans les graphes de Surface, les « cercles » ne sont pas fermés. Manque-t-il quelque chose ?
    • D’habitude, dans ce cas un secteur n’est pas facilement lu. C’est très courant avec les disquettes formatées avec certains programmes sur ST (comme Fastcopy Pro, par exemple), avec plus de 9 secteurs/piste. Le premier secteur de chaque piste n’est pas vu par le contrôleur de disquettes dans des conditions normales.Heureusement, dans la plupart des cas, ST Recover est capable de lire ces secteurs, au prix d’une lente analyse. Ces secteurs seront marqués en bleu foncé, dans les Tables de secteurs.
  • Pourquoi certains secteurs sont marqués en bleu foncé dans les Tables de secteurs, et l’analyse est très lente ?
    • Voir ci-dessus l’explication. Ces secteurs sont lus correctement, bien que lentement.

Compilation du code source

Le code a été édité et compilé avec Borland Turbo C++ 2006 Explorer, un RAD gratuit.

Il est supposé être compilable avec les versions suivantes de Borland (Embarcadero) C++ Builder. Je n’ai pas essayé car je n’ai aucun de ces RADs.

Turbo C++ 2006 Explorer était gratuit mais il semble ne plus être distribué. Il nécessitait un enregistrement et l’installation de plusieurs logiciels, tels que dot.net 1 et JSharp.

Au fait, mon code source est commenté en français.

Licence

La licence pour le code source et pour les binaires est la Ms-RL, laquelle vous permet globalement de reproduire le code, de le modifier, de le distribuer, mais vous devrez alors rendre le code source et les modifications disponibles.

Par ailleurs il est libre de brevets.
Disquettes lentes

Parfois, une disquette prend du temps à être lue.

Les raisons possibles peuvent être:

  • La disquette est désynchronisée.
  • La disquette est physiquement endommagée.Dans ce cas, des secteurs seront colorés en rouge.

Disquette désynchronisée

Ce genre de disquette prendra plus de temps à être lue, et les tables de secteurs montreront des rectangles bleus:

Les rectangles bleus indiquent des secteurs particuliers, mais bien lus. En fait, ici ces secteurs ont seulement besoin de plus de temps pour être lus, mais ils sont lus correctement (sinon la couleur serait le rouge).

Pour comprendre ce qu’est la désynchronisation, lancez une analyse de surface:

Comme vous pouvez le voir, un secteur par piste n’est pas détecté, et juste au milieu de là où il devrait être (le triangle rouge), la marque (la ligne verte) passe dedans.

Voici l’explication: la tête de lecture passe au-dessus de la piste à partir de la ligne, mais il est trop tard pour voir le début du secteur, donc le premier secteur n’est pas détecté par le test de surface.

Mais il reste possible d’essayer de lire le premier secteur au prochain tour, ça demande juste plus de temps.

Plus en détails: J’ai dû implémenter une analyse particulière de la piste, de façon à pouvoir extraire les informations du secteur (bleu). Heureusement, le pilote spécial peut extraire une piste entière. C’est une question de décodage MFM, avec (6250) octets par piste partiellement désynchronisés, etc..

Au passage, la méthode de décodage et de récupération est entièrement une question de de désynchronisation de bits MFM, ça n’a rien à voir avec la marque de synchronisation de la disquette:

La marque de synchronisation de la disquette est l’origine du problème, à cause d’un mauvais réglage du lecteur qui a formaté à l’origine la disquette, et le décodage et la resynchronisation des bits MFM est une méthode que j’utilise pour récupérer le secteur.

Si vous avez suivi l’explication, vous devriez avoir remarqué que le problème est avec le premier secteur de chaque piste. Alors pourquoi dans la table des secteurs les rectangles bleus ne sont pas tous dans la première ligne ? C’est parce que les secteurs n’ont pas été numérotés normalement durant le formatage, ils ont été décalés de manière à permettre au contrôleur du lecteur (le processeur qui s’occupe du lecteur) plus de temps pour déplacer la tête vers la piste suivante (ça prend du temps et la disquette continue à tourner) et pour lire aussi tôt que possible le prochain secteur.

Désolé si je ne suis pas assez clair, vous pourrez trouver plus d’informations sur internet à propos de comment accélérer les accès disque par le biais de l’entrelacement de secteurs.

Non testés

Il y a des formats que je n’ai pas testés:

  • Les tailles de secteur différentes de 512 (128, 256 or 1024) octets.Pour autant que je me rappelle, je n’ai pas écrit beaucoup de logique pour prendre en compte ces tailles (ce n’était pas mon but).
  • Les disquettes protégées dont le format physique est différent du format logique (indiqué dans le secteur de démarrage).Par exemple certains secteurs peuvent être numérotés non à partir de 1 mais de 40.
  • Les disquettes protégées dont les secteurs ne sont pas bien formés.Par exemple, ils peuvent être coupés au milieu juste pour tromper les programmes de copie de disquettes.
  • Les disquettes de 900 Ko. J’ai besoin de formater une nouvelle disquette de 900 Ko sur mon vieux ST puis d’essayer de la lire avec mon plutôt vieux PC de bureau.

Tout cela parce que j’ai créé cet outil pour récupérer mon ancien travail sur ST, et pas pour analyser des disquettes protégées ou anormales.

Légal

Le texte et les images de cette documentation ont des droits réservés par Christophe Bertrand sous la licence CC-BY-SA, sauf:

  • L’image de l’Atari ST est placée sous « CC-BY-2.5 — Attribution license » par Bill Bertram. Voir ici.
  • Les icônes de disquette, de disque-dur et de répertoire sont sous LGPL, et proviennent du Crystal Project.
  • L’image du PC de bureau est dans la domaine publique et a été trouvée ici.
 
1 commentaire

Publié par le 2012-03-27 dans Logiciels

 

Étiquettes : , , , , , , , ,