1 points par GN⁺ 20 시간 전 | 1 commentaires | Partager sur WhatsApp
  • L’architecture de la PlayStation a adopté une conception simple et pragmatique pour réduire la complexité du développement matériel 3D, mais a laissé aux développeurs une charge supplémentaire et des limites visuelles en matière de tri graphique, de correction de texture et de précision
  • Le Sony CXD8530BQ est un SoC intégrant un cœur compatible MIPS R3000A basé sur CoreWare de LSI Logic, ainsi que le CP0, le GTE et le MDEC ; il fonctionne à 33,87 MHz et organise les transferts de données autour de 2 Mo de RAM, d’un Scratchpad de 1 Ko et du DMA
  • Côté graphismes, le GTE gère la projection 3D, l’éclairage et le clipping, tandis que le GPU rend lignes, rectangles et triangles via un système de commandes ; en l’absence de Z-buffer, il utilise une ordering table, ce qui oblige le CPU à déterminer l’ordre des polygones
  • Le GPU produit du tremblement, des chevauchements et du texture warping à cause de l’affine texture mapping, du nearest neighbour, des coordonnées entières et de l’absence de résolution subpixel ; des contournements comme la tessellation, le remplacement par des aplats de couleur ou les arrière-plans pré-rendus ont donc été utilisés
  • La conception fondée sur le CD-ROM, avec 620 Mo de stockage, le streaming audio ADPCM 44,1 kHz, un environnement d’exécution basé sur le BIOS, ainsi que la protection contre la copie Wobble Groove combinée au verrouillage régional, a transformé les méthodes de développement et de distribution des jeux

Conception de base et CPU

  • La PlayStation visait une architecture simple et pragmatique, partant du constat que le matériel 3D pouvait devenir complexe à développer, au prix de certaines limites assumées
  • La puce principale, Sony CXD8530BQ, correspondrait aujourd’hui à un SoC et utilise un cœur CPU CoreWare de LSI Logic, compatible binaire avec la famille MIPS R3000A
  • Le cœur CPU fonctionne à 33,87 MHz, avec l’ISA MIPS I, des mots de 32 bits, 32 registres généraux, un bus de données 32 bits, un bus d’adresses 32 bits, un pipeline à 5 étages et 4 Ko de cache d’instructions
  • Il n’y a pas de cache de données ; la mémoire de 1 Ko qui aurait dû en tenir lieu est fournie sous la forme d’un Scratchpad mappé à une adresse fixe, utilisable comme une SRAM rapide
  • Le système fournit 2 Mo de RAM EDO pour les usages généraux ; la RAM EDO est décrite comme légèrement plus efficace et à plus faible latence que la DRAM classique

Bus et coprocesseurs

  • Le bus de données est divisé entre un Main Bus 32 bits et un Sub Bus 16/8 bits ; le Main Bus relie le MDEC et le GPU, tandis que le Sub Bus relie les autres composants et les E/S
  • Le contrôleur CD-ROM, le MDEC, le GPU, le SPU et le port parallèle peuvent accéder au DMA controller ; le DMA prend le contrôle du bus principal pour transférer les données à haut débit sans passer par le CPU
  • Pendant que le DMA est actif, le CPU ne peut pas accéder au bus principal et se retrouve en attente s’il n’a rien à traiter dans le Scratchpad
  • Le CP0, ou System Control Coprocessor, gère l’implémentation du cache, l’accès direct au Scratchpad, l’isolation du cache d’instructions, les interruptions, les exceptions et les breakpoints
  • Le CP2, ou Geometry Transformation Engine, accélère les calculs vectoriels et matriciels en virgule fixe et prend en charge les premières étapes du pipeline graphique, comme la projection 3D, l’éclairage et le clipping
  • Le MDEC décompresse des macroblocs encodés de manière proche du JPEG dans un format compréhensible par le GPU ; il peut traiter 9 000 macroblocs 8×8 pixels en 24 bpp par seconde, permettant le streaming de FMV en 320×240 px à 30 fps
  • Aucun FPU correspondant au CP1 n’est fourni ; les calculs en virgule peuvent être traités en logiciel ou en virgule fixe, avec des limitations de vitesse ou de précision

Pipeline et delay slots

  • Le pipeline MIPS I est vulnérable aux control hazards et data hazards, et fonctionne avec des branch delay slots où l’instruction suivant un branchement ou un saut est toujours exécutée
  • Les instructions load ne stoppent pas le pipeline jusqu’à ce que les données soient prêtes ; si l’instruction suivante dépend immédiatement du résultat du chargement précédent, il faut un remplissage pour obtenir le bon opérande
  • Certains delay slots peuvent être remplis par des instructions utiles, ils ne constituent donc pas toujours des cycles perdus
  • Fidèle à la philosophie RISC selon laquelle de bons compilateurs et assembleurs se chargent du réordonnancement des instructions ou de l’insertion de remplissages, MIPS a choisi d’exposer le pipeline CPU aux développeurs et à la toolchain
  • Ce choix a aussi l’inconvénient de compliquer la compatibilité ascendante à mesure que de nouvelles microarchitectures apparaissent dans les générations suivantes de CPU

Pipeline graphique

  • Une grande partie du pipeline graphique est traitée par le GTE, puis les données résultantes sont transmises au GPU propriétaire de Sony pour le rendu
  • Le système stocke le frame buffer, les textures et d’autres ressources de rendu dans 1 Mo de VRAM, que le CPU peut remplir via DMA
  • Sur les premiers modèles, la VRAM est de type dual-ported avec deux bus 16 bits, ce qui permet au CPU, au DMA, au GPU et à l’encodeur vidéo d’y accéder simultanément
  • Les modèles suivants sont passés à de la SGRAM utilisant un unique bus de données 32 bits ; à cause de différences de timing, des jeux plus tardifs comme Jet Moto 3 peuvent afficher des artefacts graphiques sur les systèmes à VRAM
  • Le CPU peut envoyer des données géométriques en remplissant jusqu’à 3 commandes dans le FIFO buffer de 64 octets du GPU ; ces commandes demandent un rendu, un changement de configuration ou des opérations sur la VRAM
  • Le GPU peut dessiner des lignes, des rectangles et des triangles individuellement ; les triangles servent d’élément de base pour construire des modèles 3D riches
  • Le système de coordonnées du GPU repose sur des coordonnées entières, chaque coordonnée correspondant au point d’échantillonnage au centre d’un pixel, sans coordonnées fractionnaires

Visibilité, rastérisation et textures

  • Le GPU de la PlayStation ne fournit pas de résolution matérielle de la visibilité et utilise une ordering table pour gérer les adresses des commandes GPU selon leur profondeur
  • Le CPU doit d’abord trier les polygones, placer leurs références dans l’entrée appropriée de la table, puis l’envoyer au GPU via DMA afin d’obtenir un rendu dans le bon ordre
  • Le GPU n’a besoin que d’un seul frame buffer, et le rasteriser convertit les sommets en lignes, triangles, rectangles et pixels
  • Les triangles sont les primitives les plus complexes et les plus polyvalentes, avec prise en charge des textures et du shading ; les lignes sont rapides mais mal adaptées aux surfaces texturées, et les rectangles sont limités à des sprites de 256×256 pixels au maximum, sans shading ni effets de transformation affine
  • Les effets d’éclairage se divisent entre flat shading et Gouraud shading ; le flat shading permet de remplir environ 2,5 fois plus de polygones par seconde que le Gouraud shading
  • Les textures sont appliquées au moyen d’un inverse texture mapping, qui recherche le texel de la texture map pour chaque pixel rastérisé
  • L’Affine Texture Mapping du GPU de la PlayStation n’utilise que les coordonnées 2D X/Y et ignore la profondeur, sans correction de perspective
  • Le texture filtering n’est pas implémenté ; pour la mise à l’échelle, le système utilise le nearest neighbour, rapide et peu coûteux, mais qui donne aux modèles texturés un aspect bloc
  • Le GPU prend en charge la semi-transparence et le dithering sur les triangles, et la PlayStation est décrite comme particulièrement performante sur ces effets

Gestion de la VRAM et limites visuelles

  • L’idée d’utiliser une grande partie du 1 Mo de VRAM pour le frame buffer impose des réajustements aux formats standard des téléviseurs, réduit l’espace pour les textures et les tables de couleurs, et le GPU lui-même ne peut rendre qu’un frame buffer 16 bits de 640×480 pixels au maximum
  • Un buffer 640×480 en 16 bits laisse 424 Ko de VRAM pour les ressources, mais l’avantage d’une haute résolution restait peu marqué sur les téléviseurs domestiques de l’époque
  • Le frame-buffer ajustable consiste à ne pas gaspiller de VRAM sur une résolution peu perceptible, en réduisant la taille du frame buffer pour augmenter l’espace disponible pour les textures et les colour lookup tables
  • La démo Gears Episode 2 de Halkun montre une configuration où le frame buffer 640×480 est divisé en deux buffers de 320×480, avec page flipping pour rendre une scène pendant que l’autre est affichée
  • Cette disposition ne consomme que 600 Ko de VRAM, laissant les 424 Ko restants pour les colour lookup tables et les textures, ce qui forme un agencement efficace avec le cache de textures de 2 Ko
  • La VRAM peut mapper simultanément plusieurs profondeurs de couleur, ce qui permet par exemple de placer un bitmap 24 bpp, souvent utilisé pour les images FMV, à côté d’un frame buffer 16 bpp
  • Le rasteriser ne travaille qu’au niveau du pixel et ne suit pas la part fractionnaire d’un pixel couverte par un triangle, ce qui peut provoquer des sauts sur les contours des modèles, ainsi que du scintillement et des chevauchements aux intersections de triangles
  • L’ordering table laisse aux développeurs ou au programme la charge de décider quelle géométrie se trouve devant ; si l’on recourt à des calculs approximatifs pour des raisons de performance, cela peut entraîner du scintillement ou des problèmes de surfaces occultées
  • Les transformations affines n’intègrent pas de notion de profondeur et peuvent provoquer du texture warping lorsque la caméra est proche du modèle et perpendiculaire à son regard ; certains jeux réduisaient cette distorsion par tessellation ou en remplaçant certaines textures par des aplats de couleur
  • Les arrière-plans pré-rendus étaient utilisés lorsqu’une scène plus réaliste que le rendu GPU temps réel était nécessaire, en diffusant via le MDEC une vidéo appliquée sur deux triangles

Audio et jeux sur CD

  • Le SPU prend en charge 24 canaux d’échantillons ADPCM 16 bits à 44,1 kHz, soit une qualité Audio CD
  • Le SPU fournit la modulation de hauteur, la modulation de fréquence, des enveloppes ADSR, le bouclage et la réverbération numérique
  • La Sound RAM, qui sert de tampon audio, est une DRAM de 512 Ko ; le jeu ne peut utiliser que 508 Ko pour stocker ses échantillons, et l’activation de la réverbération réduit encore cette capacité disponible
  • Le contrôleur CD peut envoyer directement des échantillons vers le mixeur audio sans tampon audio ni intervention du CPU ; les échantillons compressés en XA peuvent être décodés en temps réel par le SPU
  • Le support CD-ROM offre aux jeux PS1 620 Mo d’espace de stockage, une qualité audio riche et une vitesse de lecture relativement rapide grâce au lecteur 2x
  • Les révisions de la PS1 commercialisées jusqu’en 1997 sont connues pour un laser de lecteur CD défectueux, causant de fréquents sauts en FMV et sur les Audio CD ; les modèles ultérieurs ont amélioré le bloc laser et son châssis pour atténuer le problème

E/S, BIOS et environnement de développement

  • Les premières PlayStation disposaient de ports d’E/S Serial et Parallel pour des extensions, mais ceux-ci ont été retirés des révisions suivantes en raison de leur faible adoption et des craintes de contournement de la protection contre la copie
  • Le sous-système CD se compose d’un DSP contrôlant le moteur, le laser et le signal RF, d’un Sub-CPU avec microcontrôleur Motorola 68HC05, 512 octets de RAM et 16 Ko de ROM, d’un CD Controller faisant l’interface entre le CPU principal et le sous-système CD, ainsi que d’un tampon SRAM de 32 Ko
  • Le programme ROM du Sub-CPU met en œuvre la procédure de protection contre la copie et l’impose indépendamment de la volonté du CPU principal
  • En façade, on trouve 4 connecteurs pour 2 manettes et 2 Memory Card ; les quatre slots sont électriquement identiques et leurs adresses sont codées en dur
  • Le système stocke le BIOS dans une ROM de 512 Ko ; le BIOS fournit le démarrage, le shell utilisateur et les routines d’E/S
  • L’accès à la ROM du BIOS est très lent à cause du bus de données 8 bits ; l’API est donc fournie sous la forme d’un Kernel copié en RAM principale au démarrage, avec 64 Ko de RAM principale réservés au système d’exploitation de la PlayStation
  • Le processus de démarrage suit l’ordre suivant : exécution de la ROM du BIOS, chargement du système d’exploitation PlayStation, affichage du splash screen, vérification de l’authenticité du CD, vérification et exécution de SYSTEM.CNF, ou affichage du shell
  • Le shell est une interface graphique simple permettant de copier ou supprimer des sauvegardes sur Memory Card et de lire des Audio CD
  • Le SDK de Sony incluait un compilateur C et des bibliothèques ; ces dernières se connectaient aux routines du BIOS pour l’accès au matériel
  • Le DTL-H2000 destiné aux studios est une carte ISA double slot contenant l’intérieur d’une PS1, ses E/S et des circuits de débogage, qui nécessite un logiciel fonctionnant sur un PC équipé de Windows 3.1 ou 95
  • Le Net Yaroze destiné aux amateurs fournissait un toolkit, un manuel et une console PS1 noire, mais sans accès au lecteur CD, ce qui imposait que le logiciel homebrew tienne entièrement dans la RAM principale

Protection contre la copie et verrouillage régional

  • La protection contre la copie de Sony repose sur une vérification, par le Sub-CPU, de la présence dans la table des matières du CD d’un Wobble Groove gravé à une fréquence spécifique
  • Le Wobble Groove est introduit lors du mastering et ne peut pas être copié avec un graveur CD ordinaire ; la TOC se trouve dans la zone Lead-In du CD et est répétée plusieurs fois pour la tolérance aux pannes
  • La TOC des jeux contient l’une des chaînes SCEA, SCEE ou SCEI, et ce mécanisme est également utilisé pour le verrouillage régional
  • La vérification n’étant effectuée qu’une seule fois au démarrage, il est possible de la contourner par la méthode du swap trick, consistant à changer manuellement de disque juste après l’authentification, au risque d’endommager le lecteur
  • Certains jeux tentaient de bloquer cette méthode en réinitialisant le lecteur pendant la partie afin de relancer la vérification
  • Un modchip est une petite carte programmée pour imiter le signal du Wobble Groove ; il était soudé à la console, et bien que juridiquement controversé, il est devenu très populaire
  • Par la suite, certains jeux ont ajouté leurs propres protections fondées sur des checksums pour répondre à la diffusion des modchips, des graveurs CD et des émulateurs
  • Le Libcrypt de Sony combine une approche matérielle, qui stocke des checksums de secteurs spécifiques dans le sous-canal du disque, et des routines logicielles qui récupèrent ces checksums à divers endroits du jeu pour les mélanger à d’autres valeurs et les vérifier

1 commentaires

 
Avis sur Hacker News
  • Il existe des zones mémoire mappées sur la même mémoire physique — https://psx-spx.consoledev.net/memorymap/
    Lors du portage de Metal Gear Solid de la PSX vers le PC, les programmeurs de Konami ont utilisé une astuce assez brutale pour enregistrer si une charge C4 était placée sur un mur ou sur le sol.
    En gros, le pointeur visait la même adresse de mémoire physique, mais selon qu’elle était fixée à un mur ou au sol, ils faisaient apparemment un OR avec 80000000h ou utilisaient A0000000h. C’était il y a longtemps donc je ne me souviens plus exactement de ce qu’ils faisaient, mais le portage vers PC était amusant

    • Le bootloader de carte mémoire fonctionne aussi de cette manière.
      Le code du BIOS a un itérateur de tableau défectueux, ce qui permet de copier des données arbitraires vers des positions plus hautes que le pointeur de base dans la carte mémoire. Normalement, le pointeur de base se trouve très haut, donc on ne peut pas écraser le code exécutable, mais à cause de l’alias mémoire, si on choisit bien la valeur, l’écriture peut « revenir » et écraser le BIOS.
      En pratique, cela permet de démarrer un BIOS personnalisé simplement en entrant dans l’écran de la carte mémoire, puis d’exécuter un PSX.EXE sans passer par les vérifications du mechacon, ce qui contourne la protection contre la copie.
      J’aimerais aussi en savoir plus sur le portage de MGS. Je me demande s’il te reste des souvenirs. Il me semble que la majeure partie du scripting utilisait TCL, et que MGS 1 à 4 employaient une même lignée de langage de script.
      Le code source de MGS2 a récemment fuité, mais c’était probablement une réécriture presque complète, donc il ne devait quasiment rien partager avec la base de code PSX
    • De nos jours, ce genre d’astuce utilise généralement les bits de poids faible valides du pointeur, puis les enlève par masquage au moment du déréférencement. En contrepartie, cela impose un alignement plus strict : par exemple, utiliser 4 bits nécessite un alignement sur 16 octets.
      La PS1 non plus n’avait pas assez de RAM pour couvrir toute la fenêtre de décodage RAM, d’où l’alias de RAM. Je ne connais pas le mécanisme exact, mais j’ai déjà vu un exécutable PS1 définir le pointeur de pile à la fin des 8 MiB de RAM du kit de développement, et malgré cela fonctionner normalement sur une machine commerciale en retombant en pratique à la fin des 2 MiB de RAM. En théorie, on pourrait aussi y stocker des bits, sans même toucher à une zone mémoire au comportement de cache différent
    • Intéressant. Ce n’est pas facile de retrouver cette partie dans le code décompilé. Je me demande si cela n’a simplement pas encore été découvert et documenté.
      https://github.com/FoxdieTeam/mgs_reversing/blob/master/sour...
    • Les premiers Mac utilisaient l’octet de poids fort des pointeurs 32 bits pour y stocker d’autres données.
      https://en.wikipedia.org/wiki/Classic_Mac_OS_memory_manageme...
      Cela a conduit certains modèles à disposer d’un mode de compatibilité descendante pas si différent de la porte A20 sur PC, mais cette période a été courte
    • Aujourd’hui, ce type de fonctionnalité est standardisé via des extensions matérielles.
      Il y a Arm Top Byte Ignore (TBI), Intel Linear-Address Masking (LAM) et sa variante corrigée Linear Address Space Separation (LASS), ainsi qu’AMD Upper Address Ignore (UAI), et UAI n’est pas encore sûr face aux attaques SLAM. Par-dessus, il existe aussi des extensions de sécurité comme ARM Memory Tagging Extension (MTE)
  • Excellent article, mais il a en fait été publié à l’origine en 2019. Les discussions précédentes datent de 2020 sur https://news.ycombinator.com/item?id=22932134 et de 2021 sur https://news.ycombinator.com/item?id=27576902, avec 114 commentaires à chaque fois

    • Il a toutefois été mis à jour plusieurs fois depuis
    • Même comme ça, cela remonte à 5 à 7 ans. Je ne l’avais jamais vu, donc je suis content qu’il soit remonté
  • C’est un site web vraiment magnifiquement conçu. Tout est disposé avec soin, et cela donne un très bon exemple de jardin numérique bien curé. On sent fortement que c’est bien entretenu et fait par une personne

  • Je travaille en ce moment sur un projet lié à la PS1 et j’aimerais le rendre public bientôt, donc j’ai posté cet article.
    Je me demande s’il existe des recommandations pour des émulateurs PS1 web/JS/WASM. Sur desktop, PCSX-Redux [0] et DuckStation [1] m’ont bien plu.
    J’ai trouvé quelques tentatives basées sur JS/emscripten, mais je serais reconnaissant pour toute recommandation.
    [0] https://github.com/grumpycoders/pcsx-redux/
    [1] https://duckstation.org/

  • La PS1 est l’architecture qui m’a fait aimer le RISC, ou plus précisément l’architecture load-store, et qui m’a fait comprendre que je me trompais du côté de x86

  • L’architecture de la PS1 est fascinante. Elle montre aussi pourquoi les jeux PS1 ont acquis ce style si distinctif et immédiatement reconnaissable que l’on cherche encore à reproduire aujourd’hui

  • J’aime les articles de Copetti. Je ne maîtrise pas tout ce qu’il couvre, mais même survoler ses textes et ses schémas est un plaisir.
    J’aime particulièrement essayer de comprendre ce qui se passe à l’intérieur de machines comme les consoles de cinquième et de sixième génération

    • Si tu aimes Copetti, tout le travail de Fabien Sanglard vaut aussi le détour. Il y a les Black Books sur Wolfenstein et Doom, l’analyse du portage d’Another World, ainsi que des dizaines d’autres revues de code qu’il a publiées
      https://fabiensanglard.net/
    • La date de 1994 m’étonne toujours aussi. Ces machines donnent l’impression d’appartenir davantage à la fin des années 90
  • C’est encore mieux comme article parce qu’il est antérieur à Claude

  • Le fait d’exécuter l’instruction après un saut paraissait complètement absurde au début, mais au bout de quelques jours c’est devenu naturel. La N64 avait aussi un problème similaire, où il fallait trouver une instruction à placer entre deux multiplications
    Si la première multiplication se terminait en deux cycles, par exemple parce qu’elle multipliait par 0, le CPU se bloquait si l’instruction suivante était aussi une multiplication

    • Autre bizarrerie : les instructions COP2, c’est-à-dire GTE, commencent leur exécution une instruction plus tôt que leur position selon le compteur ordinal
      Donc, si une exception se produit, le gestionnaire d’interruptions du noyau doit vérifier si l’instruction suivante est une COP2 et ajouter 4 au compteur ordinal pour éviter de l’exécuter deux fois
      Les instructions COP2 ne pouvaient pas non plus être placées dans un branch delay slot, probablement pour une raison similaire. Pourtant, certains jeux, de mémoire Tekken 3, le faisaient réellement. Comme plusieurs émulateurs ont eu des problèmes à cet endroit ou ont eu besoin d’un traitement spécial, je me suis toujours demandé si ce n’était pas une protection anti-émulation discrètement glissée là
  • Les articles de cette série sont toujours excellents
    Les jeux PS1 ont moins bien vieilli selon les standards actuels, mais je trouve que les jeux PS2 sont presque parfaits une fois upscalés en 1440p~4K

    • Les jeux PS1 tiennent aussi plutôt bien si on y joue comme c’était prévu à l’origine, si possible sur un CRT, ou sinon avec un filtre CRT dans un émulateur. Les jouer sur un LCD très net à une très haute résolution me paraît être la pire façon de les découvrir
    • Dire que « les jeux PS1 sont difficiles à regarder aujourd’hui » reste très subjectif. La PS1 a marqué le début de l’ère 3D sur console de salon, et beaucoup apprécient aussi les modèles 3D low poly avec ce « tremblement » caractéristique de la PS1
      Il y a sans doute une grande part de nostalgie, mais il y a aussi un charme bien réel, et depuis que je comprends les contraintes matérielles si particulières de la PS1, je les apprécie de plus en plus avec le temps. Rien qu’en regardant les fils des réseaux sociaux, on voit que les « graphismes PS1 » connaissent une petite résurgence, et que beaucoup cherchent à recréer cette esthétique
    • Quand on voit les spécifications, ce que les développeurs ont réussi à en tirer est vraiment impressionnant
    • Côté graphismes, il suffit d’utiliser un CRT ou un filtre CRT, ou bien un émulateur prenant en charge la correction géométrique PGXP pour supprimer le tremblement des sommets à haute résolution de rendu
      Côté gameplay, cette console possède une énorme ludothèque, avec des milliers de jeux commercialisés et beaucoup de perles cachées. Je serais presque surpris qu’un joueur ne trouve pas un seul titre à son goût dans cette liste
    • Les jeux 2D, eux, tiennent encore très bien aujourd’hui. Des titres comme Symphony of the Night, par exemple