Pour ma première participation au RetroChallenge, je prévois tenter
le projet suivant:
Conçevoir un adaptateur permettant le raccord d'un NES Zapper sur un PC modèle Tandy 1000 EX.
Coder un clone de Duck Hunt ou un mini-jeu original si je trouve l'inspiration.
Utiliser le mode graphique 16 couleurs Tandy. (Il serait regrettable de ne pas le faire!)
J'aimerais aussi tenter, si le temps le permet:
Suporter le mode 320x200 CGA standard, et faire fonctionner le jeu sur un clone XT avec carte CGA.
Explorer la possibilité de faire fonctionner un Zapper sans modifications avec un écran VGA.
Permettre au jeu de fonctionner avec une souris (possiblement à un rythme accéléré pour maintenir la difficulté)
Introduction
À l'éopque où les ordinateurs personnels étaient un concept relativement nouveau, les écrans dédiés
n'étaient pas donnés. Les PCs à cet époque étaient donc souvent pourvus de sorties vidéo composite,
permettant aux utilisateur d'utiliser simplement une télévision déjà en leur possession. Tout comme
les consoles de jeu quoi!
Certains ordinateurs tels que le PC d'IBM étaient offerts avec une carte CGA comportant une sortie video composite,
mais les capacités graphiques (4 couleurs) étaient limités et il fallait installer une carte additionelle
pour pouvoir y raccorder des joysticks. D'autres systèmes, tels que ceux de la série
Tandy 1000 (depuis 1984) offrait un mode graphique
16 couleur, des ports joystick intégrés et un circuit de son amélioré. Beaucoup mieux adapté aux jeux vidéos!
La console NES a été lancée en 1985, et nous savons tous qu'elle se raccorde directement à un écran de télévision. Un
pistolet nommé Zapper était fourni avec la console, permettant de viser des objets sur l'écran et fonctionnait
par détection de lumière. Afin d'éviter que les sources lumineuses autres que l'écran interfère, le Zapper
comporte des filtres ajustés pour un fonctionnement optimal sur écran avec rafraîchissement 60Hz vertical et environ
15 kHz horizontal.
Je pense qu'il est possible de faire fonctionner le Zapper même si la NES est remplacée par un Tandy 1000 ou un
système avec carte CGA. Les fréquences de rafraîchissement sont les mêmes, ou assez près pour ne pas s'en soucier. Je
crois qu'il est intéressant d'essayer, et comme l'ordinateur que je vais utiliser et les Zapper sont de la
même époque, il me semble qu'il aurait été parfaitement possible à l'époque d'acheter un Zapper pour son Tandy 1000,
si un adaptateur et des jeux compatibles avait existé. (Est-ce le cas et je l'ignore!?)
Pour RC2018/04, je prévois réaliser un adaptateur pour le Zapper et créer un jeu le supportant. Pour le jeu, j'utiliserai
ma librairie graphique et les outils que j'ai développés pour RATillery.
Mais le jeu en soi, les graphiques (et la musique s'il y en a) verront le jour entre le 1er et 30 Avril, conformément
aux règles du RC2018/04.
De plus, si j'ai le temps (et à défaut de l'avoir, je le ferai ensuite) j'aimerais tester une théorie. Il parait que
le Zapper ne fonctionne pas avec les écrans VGA en raison de la fréquence de rafraîchissement horizontale qui est
trop élevée. J'aimerais d'abord vérifier cette affirmation. Ensuite, j'aimerais tenter de trouver une manière de faire
fonctionner un Zapper non-modifié avec un écran VGA.
Mise à jour 3 Avril
J'ai commencé par jouer un peu à Duck Hunt afin de vérifier le bon fonctionnement du
Zapper lui-même, et m'assurer qu'il fonctionnait avec les écrans monochromes comme celui
que j'allais utiliser pour commencer. (Je compte utiliser l'énorme télé couleur plus tard). Duck
Hunt a fonctionné à merveille, alors j'ai branché le Tandy 1000 EX et préparé une disquette
pour le projet.
Test de Duck Hunt
Préparation du Tandy 1000
Prochain but: Fabriquer un adaptateur. Se servir du port de joystick était la solution évidente
en raison de la présence d'une sortie 5 volt (pour alimenter le Zapper) et de deux entrées boutons (
une pour la gâchette, l'autre pour la détection de lumière).
J'ai déniché une rallonge NES et le boût d'un vieux câble DIN-6 dans ma boîte de pièces. Après
avoir déduit le code de couleur utilisé par les deux câbles, je les ai utilisé pour fabriquer un
adaptateur, selon le tableau suivant:
Port joystick
Zapper
Commentaire(s)
5v
5v
GND
GND
Button 1
Gâchette
Tiré vers le GND lorsque le joueur fait feu
Button 2
Detect
Continuellement tiré vers le GND, sauf lorsque de la lumière est détectée (plus d'info là dessus sous peu)/td>
J'ai été très attentif et pris le temps de vérifier plusieurs fois, et j'ai également
sondé le connecteur de joystick du Tandy 1000 EX afin d'être certain que l'alimentation
était bien là où je m'y attendais.
DIN6 du bac de pièces
Déduction du brochage
Vérification du voltage
Adaptateur câblé
L'état des deux boutons du joystick peut être surveillé en lisant le port 0x201. Les
deux bits les plus significatifs en représentent l'état. J'ai écrit un petit programme
BASIC affichant continuellement la valeur du port. Je me suis aussi arrangé pour
qu'il y ait un rectangle blanc clignotant à l'écran afin de le viser avec le Zapper
en observant l'effet.
J'ai également installé l'oscilloscope sur la sortie de détection de lumière du Zapper afin
de pouvoir bien voir le comportement et le timing.
Programme de test
Gâchette au repos, pas de lumière
Gâchette active, pas de lumière
Gâchette active, lumière détectée
Cela fonctionnait! Mais la détection de lumière n'était pas stable. Sur l'image ci-dessus à droite (celle
avec le rectangle blanc) affiche 176, mais ce nombre ne faisait qu'apparaitre momentanément.
À l'écran de l'oscilloscope, j'ai observé qu'il y avait des impulsions d'environ 2ms. Et en y réfléchissant,
c'est tout à fait logique. Nos yeux ne peuvent le voir, mais la surface du rectangle n'est jamais
"allumée" au complet. Le Zapper arrive à "voir" le faisceau dessiner chaque ligne, alors que la précédente
est déjà éteinte. Dès que le balayage est rendu sous le rectangle, le Zapper cesse d'indiquer
présence de lumière, et ce jusqu'au prochain rafraichissement vertical, ce qui a lieu à chaque 16ms (à 60 Hz)
Alors que j'écris ces lignes, je soupçonne que pointer le Zapper vers un écran complètement blanc résulterait
peut-être en une impulsion beaucoup plus longe. (À essayer!)
Test avec Oscilloscope
L'impulsion
Le code que j'avais utilisé jusqu'à ce point lisait le port et affichait la valeur à l'écran
en boucle. Le BASIC interprété étant déjà lent, l'écriture de nombres sur l'écran en
décimal entre chaque lecture du registre était évidemment bien trop lent pour détecter
l'impulsion.
J'ai alors créé un nouveau programme qui surveillait le port sans afficher la valeur, attendait
que la gâchette soit tirée (a très bien fonctionné) puis attendait l'impulsion indiquant de la lumière,
avec une boucle dont l'échéance en indiquait l'absence, c'est à dire une cible manquée. Mais
cela n'a pas suffit à obtenir une détection fiable.
Détecter une impulsion ne durant que 2ms en lisant un port en boucle en BASIC est probablement
impossible sur cette machine lente. Mais c'est sans importance, je n'utilisais le langage
BASIC qu'en tant qu'outil temporaire et pratique pour expérimenter rapidement. Le jeu
sera évidemment écrit en assembleur. La prochaine étape sera donc de refaire l'expérience
en assembleur, pour voir s'il sera possible d'obtenir un système fonctionnant bien.
Mise à jour 9 Avril
Tel que prévu, j'ai refait le test en assembleur et tout semble fonctionner très bien, bien qu'il s'agisse
pour le moment d'une implémentation incomplète. En effet, en ce moment, il suffit de viser n'importe quelle
zone lumineuse de l'écran pour "atteindre" sa cible. Ou pire encore, viser un écran voisin fonctionne aussi...
Mais quoi qu'il en soit, la faisabilité du projet est confirmée!
Cible manquée
Cible atteinte
La procédure employée est décrite ci-dessous:
Attends que la gâchette soit tirée
Une fois tirée:
Attends le rafraichissement vertical
Surveille le signal de détection de lumière pendant une trame complète
Si de la lumière a été détectée, considère la cible atteinte
Sinon, cible manquée
Attends que la gâchette soit relâchée
Retourne au début
Afin de corriger les défauts dont le paragraphe précédent fait mention, je crois qu'il suffit de faire
la détection en deux phases:
Première phase: Les cibles sont repeintes en noir, et on voudra que le Zapper ne détecte PAS de lumière.
Deuxième phase: Les cibles seront repeintes en blanc, et on voudra détecter de la lumière.
Seuls les tirs répondant aux deux conditions, c'est à dire l'absence de lumière lors de la première trame suivie de présence
de lumière dans la seconde, seront considérés comme réussis.
S'il faut gérer plusieurs cibles, il suffira de les repeindre en blanc à tour de rôle. Le moment exact du retour de la
lumière à l'endroit visé permettra d'identifier laquelle a été touchée.
Tout ceci corresponds à peu près à ce que fait le jeu Duck Hunt. En fait, la seule différence est que dans Duck Hunt,
c'est l'écran au complet qui devient noir plutôt que seulement les cibles. Est-ce pour des raisons cosmétiques ou plutôt pour
une raison technique? Mes prochaines expériences me le diront. À suivre...
Mise à jour 15 Avril
Toujours pas de jeu à présenter cette semaine, mais les bases sont bien en place et je crois avoir une
bonne compréhension de ce dont le Zapper est capable. Alors je devrais avoir un démo jouable sous peu!
Rejet des objets passifs
Les défauts facilitant la triche que j'ai expliqués la semaine passée sont corrigés tel que prévu. D'abord
couvrir la cible de noir lors d'une première trame puis la couvrir de blanc pour la deuxième, le tout en
vérifiant que le signal provenant du Zapper varie en conséquence. Le fonctionnement est
démontré dans les images suivantes: Le carré au centre de l'écran n'est pas une cible (c'est un
objet passif) alors que celui près du coin supérieur gauche est une cible en bonne et due forme.
Les tirs visant l'objet passif n'ont
aucun effet alors que ceux visant la cible près du coin sont correctement détectés. C'est ce qu'il
faut pour les jeux car on ne veut pas de réaction si un tir touche le décor ou le score, par exemple.
Cible visée et touchée!
Objet passif, cible manquée.
Code de rejet des objets passifs
Bien entendu, le désavantage de cette technique est que l'objet scintille un peu lorsqu'on
tire la gâchette.
Déduction du Y par chrono
Le code de détection de lumière dont j'ai parlé la semaine passée attends le rafraîchissement
vertical puis surveille ensuite le signal provenant du Zapper pendant une trame complète.
Pourquoi? Car le moment exact auquel le Zapper indiquera présence de lumière n'est
pas connu d'avance. Ce moment dépends de la hauteur de l'objet visé.
En y repensant cette semaine, j'ai compris que cela signifiait qu'il serait possible de déterminer
la hauteur Y du tir en chronométrant le temps écoulé entre la fin de la période de rafraîchissement
vertical et l'apparition de la lumière perçue par le Zapper. J'ai donc écrit un nouveau programme
de test affichant une colonne sur toute la hauteur de l'écran, puis ajouté du code pour compter
le nombre d'itérations avant la présence de lumière et le nombre d'itérations total pendant une trame.
(Je parle d'itérations puisqu'il s'agit de compteurs dans la boucle de polling surveillant
le signal du Zapper et un registre d'état la carte vidéo. Les valeurs exactes dépendent de la vitesse
de l'ordinateur).
Le mode vidéo utilisé comportant 200 lignes, Y est environ équivalent
à [cycles_première_lumière] * 200 / [cycles_total_trame]. Le logiciel de test calcule Y et affiche
à côté de la colonne un carré rouge/rose dont la hauteur correspond. En pratique, il semble y
avoir une erreur d'échelle, et je crois que ceci pourrait être causé par les 40 lignes de noir
supplémentaires que la carte vidéo ajoute probablement pour générer un signal NTSC 240p. Je regarderai
cela de plus près si je me sers de cette technique dans un jeu...
Au fait, je me demande s'il y a des jeux NES utilisant cette technique, n'ayant examiné de près
que Duck Hunt... Quoi qu'il en soit, pour un jeu avec beaucoup de cibles non alignés verticalement,
la procédure de rejet des objets passifs peut être faite d'un seul coup pour toutes les cibles, plutôt
qu'une par une.
Y=162
Y=125
Y=78
Y=42
J'ai aussi profité de l'occasion pour faire un test de couleur, afin de voir comment le
Zapper réagirait. Toutes les cibles colorés sont bien détectés, même à une bonne distance. Sur un
fond noir, il serait probablement possible de détecter une cible sans la couvrir de blanc...
Du côté droit de l'écran, la série de traits de diverses épaisseurs était pour savoir s'il y avait
un minimum pour la détection, mais il se trouve que toutes les lignes, même la plus mince, sont
détectées.
Mise à jour 24 Avril
Un premier prototype de jeu
Ces derniers jours, j'ai passé du temps sur un premier concept de jeu. Il s'agit d'un mini jeu
où il faut vaporiser des gouttes d'eau à l'aide du Zapper avant qu'elles ne tombent sur votre
clavier. Reste encore quelques trucs à faire: Le rythme d'apparition des gouttes ainsi que la vitesse à laquelle
elles tombent doit aller en augmentant. Lorsque plus que la moitié des touches sont brisées le jeu
doit s'arrêter. Il faudrait aussi mémoriser et afficher le meilleur score.
J'ignore jusqu'où je me rendrai d'ici la fin de RC2018-04, mais j'aimerais au moins faire
un deuxième jeu.
Voici quelques screenshots réalisés avec DOSBox:
Clavier intact, tout va bien
Deux touches brisées
Quatre touches brisées, ça va mal!
Et bien entendu, le jeu fonctionne sur mon Tandy 1000 EX:
C'est tout pour l'instant, je vous quitte avec l'animation d'une touche qui se désintègre
suite au court-circuit causé par la goutte d'eau...
Mise à jour 25 Avril
Zapper vs. Écran VGA
Il est bien connu que le Zapper, du moins le modèle conçu pour les télévisions NTSC, fonctionne
avec une fréquence de rafraîchissement vertical de 60Hz, et horizontale de 15.75 kHz. Sur un écran
VGA, il exite bien un mode à 60Hz, mais la fréquence horizontale est environ le double, soit 31.46875 kHz.
Cela n'est donc pas, en théorie du moins, adéquat pour le Zapper.
À l'aide d'une petite expérience, j'ai tenté de vérifier à quelle plage de fréquence le Zapper répond. J'ai
installé un LED blanc sur la sortie d'un générateur de fréquence générant une onde carrée, puis j'ai
aligné un Zapper sur le LED. Un oscilloscope surveillait la sortie du générateur de fréquence et la
sortie de détection de lumière du Zapper. Voici une photo de l'expérience:
J'ai pu constater que le Zapper en ma possession, lorsqu'on lui présente une onde carrée continue et
un contraste très élevé (c'est bien le cas puisque ce LED est plutôt aveuglant), accepte des fréquences d'environ 1 kHz jusqu'à 74 kHz! Et à une distance plus élevée (on passe de 1m à 3m) le plafond était situé à 38 kHz.
Je regrette de ne pas avoir essayé de diminuer l'intensité du LED pour être juste au dessus du seuil détection, pour ensuite varier la fréquence. Puisque aucun écran n'est aussi brillant que le LED que j'utilisais, impossible de savoir
environ quelles sont les limites en pratique à une intensité d'écran cathodique normal...
Mais comme 31.5kHz semblait être à l'intérieur de la plage de réponse du Zapper, je l'ai pointé à un écran
VGA puis j'ai jeté un coup d'oeil à l'oscilloscope. Malheureusement, rien. Même en dessinant un rectangle
blanc en mode 12h (VGA 640x480@60Hz).
Au cours des jours qui suivirent, j'ai eu les réflexions suivantes:
Bien que le Zapper ait réagit à un signal fort de plus que 3 fois la fréquence nominale de 15 kHz attendue,
cela ne veut certainement pas dire qu'il soit aussi sensible aux fréquences dans les extrême qu'il
l'est à 15 kHz. Il est en fait raisonnable de s'attendre à une courbe de réponse plus ou moins en forme de cloche.
L'écran VGA que j'ai utilisé n'émet pas beaucoup de lumière, même avec les ajustements au maximum. L'intensité
lumineuse émise étant largement inférieure à celle de l'expérience avec un LED, il se pouvait simplement
que cela ne suffisait pas.
Pour obtenir plus de lumière, j'ai refait une tentative avec un écran plus lumineux. Mais cela n'a pas suffit. Bon.
Mais j'avais une idée depuis le début du projet, née des réflexions suivantes:
Lorsque le Zapper est pointé sur un zone blanche d'un écran dont le rafraîchissement horizontal
est à 31 kHz, il reçoit des impulsions espacés d'environ 32 microsecondes. Il s'agit du faisceau
lumineux dans le champ de vision du zapper répété pour chaque ligne tracée.
Lorsqu'il s'agit d'une écran télé ou CGA, le temps qui sépare ces impulsions est le double, soit environ 63
microsecondes. Et dans ces conditions, le Zapper fonctionne bien.
« Et si, en mode VGA 640x480@60Hz, je dessinais une ligne sur deux en noir? Les Zapper ne verrait deux
fois moins d'impulsions, et le temps séparant chaque impulsion doublerait: Environ 63 microsecondes!»
L'idée semblait prometteuse. À l'aide de QBasic, sélectionné le mode 12 puis dessiné 3 zones de test:
Une première parfaitement blanche (contrôle), une deuxième dont une ligne sur deux est en blanc, puis
une dernière où une ligne sur trois est en blanc.
QBasic! Que de souvenirs...
Les 3 zones de test
J'ai pointé le Zapper sur chaque zone et consulté l'oscilloscope pour voir si le Zapper
détectait quelque chose. Aucune réaction sur le carré blanc ni sur la zone à une ligne sur trois,
mais sur celle d'une ligne sur deux, un signal est détecté! Hourra!
Zone blanche 100%. Pas d'impulsion.
Zone une ligne sur trois. Pas d'impulsion.
Zone une ligne sur deux. Ça fonctionne!
Conclusion: Il semble que le Zapper peut fonctionner avec un écran VGA lorsqu'une ligne sur deux est en noir.
Je vais fabriquer un adaptateur Zapper à joystick DB15 et faire un test complet! Mais tout d'abord, il me
faut ajouter le support du mode VGA 12h à 16 couleurs à ma librairie graphique maison...
Mise à jour 27 Avril
Suite au test concluant avec un écran VGA il y a deux jours, j'ai fabriqué un adaptateur Zapper
à port joystick DB15 afin de tester la boucle complète (Zapper + PC + Écran VGA cathodique).
Schéma
Les pièces
Assemblage...
Terminé!
Après avoir mis du temps sur ma librairie graphique pour gérer le mode VGA 16 couleurs en
640x480, j'ai modifié un des tests précédents (voir section du 15 Avril). J'ai installé
l'adaptateur et j'ai lancé le test.
Rappel: Le carré au centre de l'écran n'est pas une cible (c'est un objet passif) alors que celui près du coin supérieur gauche est une cible en bonne et due forme. Lorsque le test détecte que la cible a été touchée, le mot "detected" s'affiche dans le coin. Sinon, c'est le mot "miss".
Installation de l'adaptateur
Écran de test
Cela fonctionne parfaitement à bout portant et jusqu'à une distance d'environ 1.5m. Plus loin, il devient difficile
de toucher la cible. Soit qu'elle est trop petite, soit que l'écran n'est pas assez lumineux, et sans doute
une combinaison des deux.
À bout portant sur la cible
À bout portant sur l'objet passif
D'un peu plus loin: Sur la cible
D'un peu plus loin: Sur l'objet passif
Note: Ce petit programme de test fera parti du release final avec code source que je
rendrai disponible à la fin du projet.
Bon, assez dévié du but pour le moment, j'ai un jeu à terminer!
Mise à jour 29 Avril
Je continue d'apporter des touches finales au mini-jeu de vaporisation de gouttes d'eau.
Tout d'abord l'élément le plus visible, l'écran titre.
Un ami a tracé l'esquisse suivante, qui représente de manière un peu humoristique la situation
du jeu:
J'ai réduit la taille de l'image et soigneusement retracé les countours. Afin que l'image
soit la plus belle possible sur un écran de télévision, j'ai évité les traits minces d'un
seul pixel qui génèrent des artefacts de couleur.
J'ai coloré l'intérieur des différentes zones. J'ai bien apprécié avoir 16 couleurs, ce qui
est bien moins contraignant que les 4 couleurs que procure CGA. Toutefois j'aurais bien aimé
avoir une couleur « peau »... Tant pis, j'ai fait comme dans Commande Keen et utilisé du blanc. Voici
le résultat:
Pas mal! Mais lorsque j'ai essayé sur la télé:
Oh? Qu'est-ce qui arrive à mon jaune? Et le vert des pantalons est bien pâle? J'ignore s'il
s'agit d'un problème avec mon Tandy 1000 EX ou si la sortie vidéo NTSC donne toujours
ce genre de résultats. Évidemment l'idéal serait d'utiliser un écran CGA, mais je n'en ai pas.
Afin d'obtenir la couleur jaune recherchée, j'ai utilisé du brun (ce qui corresponds
généralement à du jaune foncé sur certains écrans). Pour le petit problème de vert,
j'ai simplement utilisé du vert foncé.
Sur un écran CGA (et dans DOSBox) cela
donne ceci, qui n'est pas trop mal (pour le clavier, pas certain, mais bon...):
La même image sur la télé, le résultat est bon:
Outre l'écran titre, j'ai corrigé de petits détails tels que le score qui n'était pas visible
sur un écran de télé puisqu'il était trop prés du bord, l'augmentation graduelle de la vitesse
et de la difficulté, l'affichage du meilleur score à date (gardé en mémoire RAM seulement) et
l'ajout d'une banière affichée lors du retour au DOS. J'ai aussi ajouté un écran « Game over ».
Game over
Bannière à la sortie
Nouveau record
J'ai une version VGA en cours de mise au point qui permet au choix de jouer avec une souris ou
avec un Zapper. Les dimensions de la zone de jeu s'adaptent automatiquement à la plus haute résolution!
Reste à voir si ce sera utilisable avec le Zapper ou si les cibles seront trop petites. Si c'est
le cas, soit j'augmenterai la taille des grapiques, soit je dessinerai un rectangle plus gros que la
cible lors de la détection.
Les versions VGA et CGA (pas encore commencé) seront disponibles quelques jours ou semaines après
la fin de RC2018/04 puisqu'il ne reste que quelques heurs pour finir la version Tandy du jeu (objectif
principal).
Mise à jour 30 Avril (finale)
Encore quelques heures, car si j'ai bien compris RC2018/04 prends fin à minuit! Heureusement, car
j'avais encore quelques trucs à faire avant la fin:
Afficher des instructions en bas de l'écran d'accueil, telles que « Tirer la gâchette pour commencer » et « Appuyez sur ESC pour quitter ». Du plus, si un pilote de souris est présent: « Cliquez pour comencer ».
Active le mode souris ou le mode Zapper en fonction de l'action à l'écran d'accueil.
Permettre de sortir de l'écran « Game Over » en tirant la gâchette. Évite au joueur d'aller au clavier pour rejouer.
Faire un release.
J'ai eu un souci sur le Tandy 1000 EX. Lorsque je faisais appel à l'interruption 33h (pilote souris) l'écran se
remplissait progressivement de caractères et le système plantait! J'ai examiné le vecteur d'interuption
avec la commande DEBUG.COM de DOS et j'ai constaté que le vecteur 33h est initialisé à 0000:0000... Comme
je n'ai pas de pilote souris (ni de souris) sur cette machine, c'est sans doute le BIOS (ou DOS 2.11) qui
l'initialize ainsi. J'ai ajouté du code pour détecter cette situation et éviter un plantage.
Ah les surprises de dernière minute!
Le problème
Examen de la mémoire
Une fois ce petit problème corrigé, les deux écrans, avec et sans souris, fonctionnent:
Avec souris
Sans souris
À propos du release
Les fichiers faisant partie du premier release sont les suivants:
rain.com (28K) : Le jeu « Rain Zapper » présenté ci-dessus.
zapdemo1.com (14K) : Le test du 9 Avril qui affiche deux carrés. Pratique pour tester votre adaptateur si vous en fabriquez un.
zapdemo2.com (14K) : Le test de chrono. pour calculer le Y. Pratique aussi pour tester la performance du Zapper avec différentes couleurs et épaisseurs de traits.
IMPORTANT: Ces logiciels ne fonctionnent que sur les ordinateur avec carte video Tandy,
tel qu'intégrée dans le Tandy 1000 EX. Sous DOSBox, il faut utiliser 'machine=tandy'. Note: Avec la
vieille version de DOSBox incluses dans Linux Debian, la fonction souris de DOSBox dans ce mode vidéo
ne fonctionne pas correctement. Le pointeur efface le contenu de l'écran et les valeurs X rapportées
sont incorrecte (semblent être divisées par deux).
Oui mais, et CGA, EGA et VGA alors!?
C'est à venir d'ici quelques jours! Au début CGA n'était qu'un objectif secondaire, et pour VGA je ne savais
même pas encore que c'était possible. C'est prêt! Voir ci-dessous.
Prêt à essayer le jeu?
Le jeu Rain Zapper est disponible ci-dessous. Si le code source vous intéresse, visitez le projet GitHub (ci-dessous également).
Version 3 27 mai 2024 (Lundi)
Version 3, maintenant avec son et mémorisation du high score. Quelques bug fix concernant la gestion de la souris.
Ce projet est aussi disponible sur GitHub! Pour suggérer de nouvelles fonctionnalités, signaler un problème ou contribuer au projet,
vous pouvez m'écrire ou utiliser le dépôt GitHub: https://github.com/raphnet/rc201804
Conclusion
Commentaires et réflection sur le projet
C'était ma première participation au RetroChallenge, et pour résumer: J'ai adoré. Ce concours était
la parfaite excuse pour jouer avec du vieux matériel: Utiliser un écran CRT couleur ambre, manipuler
des disquettes 5.25", coder en assembleur 8088, utiliser un peu GW-Basic et QBasic... Mais aussi pour
apprendre de nouveaux trucs: Comprendre à fond le fonctionnement du Zapper, utiliser nasm un peu
mieux qu'avant en me servant de STRUC, concevoir des macros nasm pour gérer facilement des listes
d'objets (les gouttes d'eau dans le jeu), découvrir et entrevoir la puissance de la programmation VGA,
utiliser le pilote de souris via int 33h...
Vais-je reparticiper au Retro Challenge? Si je peux, c'est certain!
Est-ce que j'ai atteint mes buts?
En résumé: Oui!
Mes objectifs principaux étaient:
Conçevoir un adaptateur permettant le raccord d'un NES Zapper sur un PC modèle Tandy 1000 EX. Oui! C'était l'élément essentiel, je m'en suis chargé dès la première semaine.
Coder un clone de Duck Hunt ou un mini-jeu original si je trouve l'inspiration. Oui! Finalement j'ai réalisé un mini-jeu original: Vaporiser les gouttes d'eau avant qu'elles n'atteigne
et n'endommage un clavier au bas de l'écran.
Utiliser le mode graphique 16 couleurs Tandy. Oui! Ce n'était pas trop difficile puisque ce n'était pas la première
fois que j'utilsais ce mode video. J'ai en fait réutilisé du code de RATillery.
Objectifs secondaires, à réaliser si le temps le permet:
Suporter le mode 320x200 CGA standard, et faire fonctionner le jeu sur un clone XT avec carte CGA. Non. Je n'ai pas eu le temps de réaliser une version CGA. Mais ce sera fait d'ici quelques jours.
Toutefois pour le test sur XT, ce sera difficile puisque je n'ai pas de port de jeu. Mais je pourrais peut-être utiliser le port
parallèle...
Explorer la possibilité de faire fonctionner un Zapper sans modifications avec un écran VGA. Oui!. J'ai fait quelques expériences qui m'ont permit de vérifier que c'était
faisable. On parle bien ici d'un écran VGA Cathodique bien sûr. L'objectif était « explorer la possibilité », mais j'ai
fait un peu plus: Une version VGA du jeu est en cours de réalisation!
Permettre au jeu de fonctionner avec une souris. Oui!. Le jeu comporte un mode souris, parfait pour jouer dans DOSBox ou sur un PC
qui n'est pas doté d'un adaptateur pour Zapper.
Epilogue - 27 Mai
RC2018/04 a pris fin le 30 Avril sans que j'aie eu le temps de réaliser les versions CGA et VGA pour permettre
d'utiliser un Zapper sur des systèmes non-Tandy. J'y ai travaillé pendant ces dernières semaines et ces
deux nouvelles versions du jeu sont maintenant disponibles!
Version CGA
J'ai modifié chaque dessin pour n'utiliser que 4 couleurs. L'écran titre m'a posé quelques difficultés, mais cela m'a
permit d'appendre des techniques intéressantes telles que l'utilisation de doubles contours à certains endroits, notamment
sur le clavier, sans quoi les bras noirs seraient invisibles sur ce fond noir.
Côté code, je n'ai ensuite eu qu'à utiliser ma librairie graphique CGA (celle que j'avais créée pour RATillery) et recompiler.
J'ai choisi d'utiliser la palette CGA Cyan/Magenta/Blanc/Noir car il me fallait absolument une couleur évoquant de l'eau (le cyan).
En ce moment, c'est la version faible intensité de cette palette qui est mise en oeuvre. Sur un écran sombre, il se peut donc
que le Zapper ne recoive pas assez de lumière mais je n'ai pas eu ce problème. Une solution serait d'activer la version
haute intensité pour le temps de détection seulement, ce qui ferait aussi un effect de flash..
Version VGA
Cette version m'a pris plus de temps car la programmation VGA était pour moi une nouveauté.
J'utilise le mode 12h (640x480, 16 couleurs), un mode planaire, ce qui est complètement différent
des modes CGA et Tandy. Heureusement le livre Graphics Programming Black Book était là
pour tout expliquer.
Côté graphiques, VGA offre par défaut les mêmes 16 couleurs que Tandy. J'ai choisi de les conserver,
ce qui devait me permettre de réutiliser les graphiques de la version Tandy.
J'avais publié un screenshot du prototype de la version VGA le 29 Avril (voir plus haut) où je montrais
un jeu avec le double des touches à protéger au bas de l'écran (Le double, car on passe de 320 pixels à 640 pixels).
Mais je formulais également mes craintes à propos de la taille des cibles, craintes qui se sont avérés fondées: Les
cibles était trop difficiles à atteindre autrement qu'à boût portant.
Pour palier à ce problème, j'ai simplement doublé la taille de tous les éléments graphiques. Les touches qui faisaient
32x32 font 64x64, les gouttes qui faisaient 16x16 font désormais 32x32, et ainsi de suite. Comme je tenais à profiter
de la résolution plus haute, j'ai passé beaucoup de temps à retoucher les images en ajoutant manuellement des
points pour adoucir les courbes, arrondir certaines zones ou augmenter les détails. Pour l'écran titre, j'y ai
passé quelques heures!
Cette version fonctionne parfaitement bien sur mon 386SX (l'ordinateur le plus lent doté d'une carte VGA que je
possède) avec l'adaptateur Zapper à DB15. Toutefois en mode souris, le pointeur disparait lorsqu'il est près du
haut de l'écran. C'est que le jeu cache le pointeur pendant qu'il dessine les objets qui se sont déplacés.
Lorsque le pointeur est affiché à nouveau, le balayage de l'écran a déjà commencé et si le faisceau est rendu
plus bas que l'endroit où le pointeur doit apparaître, ce dernier est invisible.
Il faudrait que j'accélère mon code de dessin, ce qui est encore possible! Car en ce moment les gouttes sont
dessinées en copiant des données de la mémoire vive vers la mémoire vidéo. Il faudrait que les gouttes d'eau
soient stockées en mémoire vidéo, ce qui permettrait d'utiliser des techniques de copie plus rapide (VGA permet
de copier 4 octets d'un coup via la lecture puis l'écritude d'un seul octet). Autre piste d'optimisation: Le jeu
pourrait gérer l'affichage du curseur lui-même, plutôt que de faire des appels répétés à int 33h. Cela permettrait
de stocker le pointeur en mémoire vidéo également. Le pilote de souris pourrait le faire, mais ce n'est vraiment
pas certain.
Je compte publier les schémas pour l'adaptateur, ainsi que le code source des jeux l'utilisant. L'avertissement ci-dessous s'appliquera.
Je ne saurais être tenu responsable pour les dommages
que l'utilisation des informations ou la mise en œuvre des instructions présentées
sur cette page pourrait causer à votre équipement,
à vous-même ou à autrui. Aussi, je ne donne aucune garantie quant
à l'exactitude des informations et à leur fonctionnement.