Modification d'un NES pour les jeux d'arcade VS

L'idée

zoomed mario 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 (mushroom), moins de fleurs (flower), et moins de vies (life mushroom). À 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...


Différences entre le NES et l'Unisystem VS

Si vous souhaitez étudier les différences vous même, voici les schémas:
miniature schema unisystem schéma de l'Unisystem VS
miniature schema cpu nes miniature schema entree nes schéma du NES. CPU, PPU, Memoire et connecteur cartouche.
schéma du NES. Circuits d'entrée pour les manettes.

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

image de la puce de protection 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.

image sram sur carte maitresse miniature schema de corresponsance 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

photo puce additionelle 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)

photo eprom cpu 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.
photo eprom cpu angle miniature du schema de correspondance


Étape 5: ROM pour le PPU (CHR-ROM)

photo eprom ppu 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.
photo eprom ppu angle miniature du schema de correspondance


É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.

Voici une image résumant cette modification:
miniature photo modification
Référez-vous a schéma de l'Unisystem VS et au circuit d'entrée pour les manettes pour bien comprendre.


Étape 8: Ajout d'interrupteurs DIP (dip switches)

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:
DipAddresseBitPoint de connectionFonction
Dip 1$4016Bit 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$4016Bit 4 P4, patte #6
Dip 3$4017Bit 2 U8, patte #10
Dip 4$4017Bit 3 P5, patte #6 Vies au départ. 2 ou 3.
Dip 5$4017Bit 4 P5, patte #7 Nombre de pièces pour avoir une vie supplémentaire. 100, 150, 200 ou 250
Dip 6$4017Bit 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$4017Bit 6 Vitesse du chronomètre. Rapide ou lente.
Dip 8$4017Bit 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:
coupage du boitier cablage des boutons cablage cablage 74ls125


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):
ecran titre sans patch fin de niveau sans patch

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é:
  1. 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)
  2. screenshot No$NES À 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
  3. 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.
  4. 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:
scores sans le patch scores avec 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:
# cat mds-sm4.1d > mds-sm4.bin
# cat mds-sm4.1c >> mds-sm4.bin
# cat mds-sm4.1b >> mds-sm4.bin
# cat mds-sm4.1a >> mds-sm4.bin

Et il faut utiliser le même principe pour les ROM du PPU. B ensuit A.

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.




Avertissement

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.