Au travail, nous avons fait un concours de scores à Super Mario Bros,
version arcade (Unisystem VS). Étant insatisfait de mon score,
j'ai voulu me pratiquer à la maison avec la version NES.
Après quelques minutes de jeu, je me suis rendu compte qu'il y
avait plusieurs différences entre la version Arcade et la version
originale pour NES.
Dans la version arcade, il y a moins de champignons (),
moins de fleurs (), et
moins de vies (). À leurs place,
ils mettent des pièces de monnaie
ou rien du tout. Certains ennemies sont différents, il y a plus
trous dans le sol et certains niveaux sont complètement
différents.
Pour me pratiquer, au lieu d'utiliser simplement l'émulateur Mame pour jouer
à la version arcade, j'ai décidé de modifier
une console NES pour l'utiliser avec des ROMS d'arcade. J'aurais aussi
pu construire une cartouche, mais modifier la console était plus
amusant et j'ai appris plusieurs choses. D'ailleurs, je me demande si
je m'amuse plus en modifiant la console ou en jouant au jeu...)
Le résultat: Une console dédié au jeu Super Mario Bros VS.
sans cartouche (pas de problème de contacts) avec des interrupteurs
permettant de configurer certains paramètres du jeu (version 'user-friendly'
des interrupteurs dips de la carte d'arcade).
Dans les pages qui suivent, vous trouverez des photos et des explications à propos
du travail que j'ai du faire pour parvenir à ce résultat. Et il ne s'agit
pas uniquement d'électronique...
L'unisystem VS est comme deux consoles NES sur la même carte, sans
cartouche (les ROMS s'installent directement sur la carte).
Quelques points communs:
Même CPU, soit le 2A03 (6502 modifié)
PPU compatibles au niveau des registres.
Mémoire CPU divisée de la même façon
La lecture de l'état des boutons sur les manettes se fait
de la même manière et les donnés sont compatibles.
Quelques différences:
La palette des PPU diffère. Le NES utilise un ppu 2c02. L'Unisystem
utilise d'autres versions comme 2c03, 2c04, 2c05. Ils ont tous des palette
différentes (mais je crois que les palettes du 2c02 et 2c03 sont très
semblables).
Les PPU d'arcade ont une sortie RGB plutot que composite. (Beaucoup mieux!)
L'Unisystem VS possede des dip switch pour configurer le jeu (Nombres de vies,
prix, etc)
L'Unisystem a une entrée pour détecter la monnaie.
Les deux systèmes sur la carte de l'Unisystem peuvent communiquer
ensemble.
L'Unisystem n'a pas de puce de protection comme le NES
L'architecture du NES est très flexible. Il est possible d'ajouter des
composantes (mappers) dans la cartouche pour utiliser de plus gros ROMS, ou même
ajouter de la mémoire, selon les besoins du jeu.
L'unisystem VS ne permet pas ce genre de choses car les roms s'installent directement
dans la carte. Les jeux doivent donc faire avec. Voici l'architecture résultante:
ROM de $8000 à $FFFF. (Normal, comme sur un NES)
Mémoire additionelle de $6000 à $7FFF. (Certains cartouches NES le font)
2 ROMs de 16Ko pour le PPU, sélectionnables depuis le CPU à l'aide
d'une sortie d'expansion. (Possible sur un NES, mais je ne connais pas de jeu qui le font)
Il y a 4Ko de mémoire pour le PPU au lieu de 2Ko. (Certaines cartouches
NES fournissent de la mémoire additionelle aussi)
Étape 1: Désactiver la puce de protection du NES
La puce de protection à l'intérieur du NES est censée communiquer
avec une autre puce de protection à l'intérieur de la cartouche. Comme
il n'y aura pas de cartouche, il faut la désactiver. Cela se fait en débranchant
la patte #4 du circuit imprimé (en la coupant) et en la connectant au ground. Pour
plus de détails, voir ma page
Trucs et modifications
pour le NES
Étape 2: Mémoire additionnelle pour le PPU
Comme je l'ai précisé plus haut, le PPU doit avoir accès
à 4K de mémoire au lieu de 2K. Il faut donc replacer la puce de
mémoire déja présente (U4) par une autre, de taille supérieure.
Le pinout des puces de mémoire sont généralement assez
similaires pour qu'il soit possible de souder une puce de taille supérieur à la place
de l'ancienne, avec un nombre minimal de pattes soulevés et quelques fils. La ligne d'addresse
supplémentaire A11 doit être relié à la patte 27 du PPU. Si vous utilisez
une puce de plus que 4K, branchez les autres lignes d'addresse (A12 et plus) a +5Volt ou au ground.
J'ai récupéré une puce de mémoire statique de 32K,
numéro As7c256
sur une carte maitresse de 486. Pour l'installer correctement à la place de la
puce de mémoire du NES (une LH5216), j'ai fait un schéma pour bien voir
les différences entre les deux puces.
Étape 3, Mémoire additionelle du CPU
L'Unisystem VS fournit 2Ko de mémoire supplémentaire au CPU. Pour ce faire,
j'ai récupéré la puce de 2 Ko (une LH5216) qui servait de mémoire
vive pour le PPU. Pour l'installer facilement, j'ai plié les pattes vers le haut et je
l'ai soudé en dessous de la carte maitresse, vis à vis de l'autre puce de
mémoire du CPU (U1).
La patte /CE (Chip enable) est soulevé car celle-ci doit être accessible
de $6000 à $7fff. La patte #7 de la puce 74ls139 sur la carte maitresse du NES est
justement à 0 dans cette plage d'addresses. La patte /CE est donc reliée
à la patte #7 de cette puce.
Étape 4: ROM pour le cpu (PRG-ROM)
L'Unisystem VS utilise 4 roms de 8Kb pour le CPU (prg-rom). Pour ne pas avoir
à utiliser 4 eproms, 4 connecteurs et plein de fils, j'utilse un seul eprom de 32K.
Pour faciliter encore plus l'installation, je l'ai soudé par dessus la puce de mémoire
du CPU (U1). Le signal /CE provient de la patte #9 du 74ls139 (U3). Le ROM est donc visible de $8000
à $FFFF.
J'ai fait un petit schéma pour bien voir quelles pattes ont la même
fonction sur la mémoire et sur le eprom. Attention, le dessin est pour un 27128 (16K) au
lieu d'un 27256 (32K). Sur un 27256 la patte #1 est A14 et sur un 27128 la patte #1 est VPP.
Étape 5: ROM pour le PPU (CHR-ROM)
L'Unisystem VS met deux ROMs de 8K à la disposition du PPU. La patte #37 du
CPU controle lequel des deux est présentement utilisable. Toujours dans un souci
d'éviter d'avoir beaucoup de filage à faire, au lieu d'utiliser deux
eproms de 8K, j'utilise un seul eprom de 16K. Puisque j'ai un seul ROM, j'ai relié la patte
#37 du CPU à l'entrée A13 de mon ROM. Le signal /CE du ROM est relié directement
au signal A13 du PPU.
J'ai installé le ROM par dessus la mémoire du PPU. Encore une fois, un
schéma de correspondance entre la puce de mémoire et le ROM s'est avéré
utile.
Étape 6: Cablage additionel du à l'absence d'une cartouche
1: Le signal /CE de la mémoire du PPU est normalement controlé par le
signal A13 inversé (inverseur U9, pattes 5,6) en passant par la cartouche.
Ceci permet aux jeux de désactiver la puce de mémoire interne pour utiliser
la leur (habituellement plus grosse). Puisque nous n'avons pas de cartouche, il faut
relier le contact #58 (CHR /A13) au contact #57 (ciram /CE).
2: La ligne d'addresse A10 de la mémoire du PPU ne provient pas directement de
celui-ci, mais de la cartouche. Ceci permet aux jeux de choisir le type de "mirroring"
qu'il leurs faut en branchant le signal A10 de la mémoire à A10 ou A11
du PPU. Nous avons 4K de mémoire alors le "mirroring" ne s'applique pas. Il faut
simplement relier le contact #62 (CHR A10) au contact #22 (CIRAM A10).
Étape 7: Bouton pour pièces de monnaie
L'Unisystem VS possède une entrée pour recevoir le signal de l'accepteur
de pièces. Électriquement, c'est le même principe qu'un bouton.
Le jeu surveille continuellement cette entrée via le bit 5 de l'addresse $4016 (comme
pour première manette). Lorsqu'une lecture est effectuée à cette addresse, la patte 36
du cpu descends à zero. C'est à ce moment que le 74hc368 (U7) prends le controle de
certains signaux de donnés du BUS.
Pour controler D5, il est possible de se servir d'une porte logique non utilisée d'U7.
Coupez la trace reliant la patte #6 d'U7 au ground, et installez une resistance de "pull up"
d'environ 10k. Ensuite, reliez à cette patte à un des contacts du bouton d'insertion
de monnaie. L'autre contact du bouton doit être relié au ground. Finalement, branchez
la patte #7 d'U7 au signal D5 du cpu.
Sur la carte de l'Unisystem, les interrupteurs dip permettent de configurer
certains paramètres du jeu.
Le jeu y accède en lisant aux addresses $4016 et $4017, comme pour lire
le signal de l'accepteur de monnaie, mais cette fois ci, il y a plusieurs
bits importants, un par interrupteur.
Voici un tableau résumant à quelle bit et à quelle addresse correspond
chaque interrupteur, l'endroit ou ils peuvent être connectés
et quel paramètre ils influencent:
Dip
Addresse
Bit
Point de connection
Fonction
Dip 1
$4016
Bit 3
P4, patte #7
Ajustement du ratio
Argent/Credits:
3/1, 2/1, 1/1, 1/2, 1/3, 1/4, 1/5 ou
gratuit.
Dip 2
$4016
Bit 4
P4, patte #6
Dip 3
$4017
Bit 2
U8, patte #10
Dip 4
$4017
Bit 3
P5, patte #6
Vies au départ. 2 ou 3.
Dip 5
$4017
Bit 4
P5, patte #7
Nombre de pièces
pour avoir une vie supplémentaire.
100, 150, 200 ou 250
Dip 6
$4017
Bit 5
Utilisez un buffer avec un état flottant quand la patte
#35 du cpu n'est pas basse et reliez les sorties au bits
5, 6, et 7 du bus du CPU. J'ai utilisé un 74ls125. Un
74ls244, 74ls240 ou même un 74hc368 d'un autre NES
ferait aussi l'affaire.
Dip 7
$4017
Bit 6
Vitesse du chronomètre.
Rapide ou lente.
Dip 8
$4017
Bit 7
Vies après un 'continue'. 3 ou
4.
Pour les options utilisant plusieurs interrupteurs DIP, j'ai
utilisé des interrupteurs rotatifs. Un petit circuit
composé de diodes me permet de convertir la position
des interrupteur en binaire. J'ai un peu modifié
le boitier pour avoir assez d'espace:
Patch pour la palette
Le PPU utilisé par la version arcade de Super Mario Bros (2c05) n'est pas le
même. Ils sont compatibles mais la palette de couleurs est différente.
Voici à quoi ressemble le jeu d'arcade avec un PPU de NES normal (2c02):
Les registres du PPU de $3f00 à $3f1f (se répètent
en fait de $3f00 à $3fff) contiennent les 16 couleurs choisies
pour l'arrière plan suivi des 16 couleurs choisies pour les sprites.
Chaque octet représente un numéro de couleur. C'est ici qu'il y a
une différence. Par exemple, la couleur $1a sur le PPU 2c05 est un bleu
mais sur le PPU 2c02 c'est un vert!
Pour corriger ce problème, j'ai modifié le rom pour qu'il envoi
les bonnes couleurs au PPU. Voici comment j'ai procédé:
J'ai converti les fichiers des ROMS d'Unisystem en .NES pour pouvoir
l'utiliser dans un émulateur et/ou déboggeur NES.
(Note: Il faut utiliser le mapper 99)
À l'aide de No$NES
(un déboggeur pour NES), j'ai
trouvé le code utilisé pour transférer la palette
au PPU. Cette routine commence à l'addresse $914a. Elle utilise
un pointeur (à l'addresse $0000) vers une structure de copie. Cette
structure de copie contient l'addresse de destination (du PPU), la longueur
et ensuite les donnés.
La routine fonctionne comme suit:
L'addresse de destination est transmise au PPU.
Toutes les donnés sont transmises au PPU.
Retour
J'ai repéré un endroit que je présume comme libre
dans le ROM (que des $FF, à partir de $959C pendant 148 octets)
assez gros pour mettre mon code de conversion
des couleurs et la table de conversion des couleurs. Je me suis servi
d'une table de conversion trouvée dans le code source de
l'émulateur AdvanceMame.
J'ai mis un saut (JMP) juste avant la boucle dans la routine de copie dont j'ai
parlé au #1 de sorte que mon code est exécuté. Puisque
la routine de copie ne sert pas seulement à copier la palette, mon
code vérifie que l'addresse de destination dans la structure de copie
est bien $3fxx. Si l'addresse n'est pas dans cette plage, je saute (JMP) à
la boucle de copie originale. Si l'addresse est bonne, ma boucle de copie
s'exécute, convertissant les valeurs au fur et à mesure
à l'aide de la table de conversion.
Voici des images avant et après avoir appliqué le patch:
Comment appliquer le patch:
Premièrement, voici un fichier binaire qu'il faut placer à
l'addresse $159C du fichier mds-sm4.1d:
fix_palette.bin
Ensuite, à l'addresse $116B du fichier mds-sm4.1d, remplacez les
3 octets $4A $4A $AA (lsr A, lsr A, txa) par $4C $9C $95 (jmp $959c).
Voici le code source de mon patch. J'utilise
wla dx pour pouvoir compiler
sous Linux: fix_palette.asm
NOTE: Ce n'est pas la peine de me demander ou vous pouvez télécharger
ces ROMS, ni me demander de vous les faire parvenir. Je ne réponderai pas.
Adaptation des rom
Les roms des jeux d'Unisystem VS sont en plusieurs fichiers puisque
sur la carte ils sont dans plusieurs EPROMs. J'utilise un EPROM qui
est capable de contenir le jeu au complet car c'est plus facile. Il
suffit de combiner les fichiers dans le bon ordre.
Si vous regardez le schéma de l'Unisystem VS
attentivement, vous verrez (peut etre que non...) que les roms sont répartis
dans la mémoire de cette façon:
1D: $8000 à $9FFF
1C: $A000 à $BFFF
1B: $C000 à $DFFF
1A: $E000 à $FFFF
Il faut donc les combiner dans l'ordre D, C, B, A. Voici un
exemple montrant comment le faire sous Linux:
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.