Comme les jeux pour Sega Saturn ont été écrits en 1995

C'est un document que j'ai écrit en 1995 lorsque je travaillais sur le premier jeu du studio Neversoft: Skeleton Warriors. Ce fut le premier jeu dans lequel je n'utilisais pas le langage d'assemblage 68K.

Photo prise autour du temps. Le kit de développement («Small Box» et ICE) est à ma droite.


État du jeu


Le document ci-dessous décrit brièvement l'état du code Skeleton Warriors pour Sega Saturn, et mentionne également certains des nombreux aspects qui devaient encore être faits.

Le document était nécessaire pour accélérer la familiarisation de Dan, Ken et James avec le code prêt à l'emploi, pour leur expliquer le but de chaque module et l'interaction entre eux. Il m'a également permis d'apprécier le triste état de ce code et, je l'espère, m'a fait prendre la décision.

Je parle également un peu de l'intégration de données (fichiers .GOV et .GOB) dans le programme, et de ce que nous ferons à l'avenir.

Équipement de développement


Notre plate-forme cible est Sega Saturn, qui a deux microprocesseurs SH2 Risc et un 68000. Tant que nous n'utilisons que le processeur principal Master SH2, l'esclave auxiliaire SH2 sera utilisé lorsque nous déterminerons comment procéder. 68000 est utilisé pour contrôler la puce audio, nous n'avons pas eu à écrire de code pour cela, car il utilisera la bibliothèque de sons fournie par Sega.

Le programme est presque entièrement écrit en C. pur. Nous utilisons le compilateur GNU SH2 pour obtenir l'assembleur de sortie SH2. Il existe plusieurs modules SH2 dans le code, qui contiennent principalement exclusivement des données. Jusqu'à présent, je n'ai rien écrit de significatif sur SH2.

En tant que système de développement, nous utilisons PsyQ. Ce n'est pas un système de développement Sega standard, mais tous ceux qui y ont travaillé le considèrent comme le meilleur. Une alternative à cela est SNASM, créé par Cross Products appartenant à Sega. La plupart des exemples de code fournis par Sega devraient fonctionner dans le système de développement SNASM, mais ils peuvent être facilement convertis en PsyQ.

Le système PsyQ se compose d'une carte d'interface SCSI, qui est installée dans le PC, d'une cartouche qui se branche sur Saturne et connecte le câble. Les sources sont compilées sur un PC et téléchargées sur Saturne, où le programme démarre. Le code peut être débogué à partir du PC.


Système de développement PsyQ

La communication est contrôlée par un programme résident (PSYBIOS), qui traite les communications entre les machines. Cela permet à la console Saturn de télécharger des fichiers à partir d'un PC de la même manière qu'elle les téléchargerait à partir d'un CD. Nous utilisons cette fonction pour télécharger des fichiers de chaque niveau.

J'ai quelques grands tiroirs bruyants dans ma chambre et deux autres PC. La plus petite des deux boîtes est l'E7000PC, qui est un émulateur SH2 intégré. Il aide à déterminer où le programme se bloque si le débogueur PsyQ ne l'arrête pas. Il est également utile pour suivre les écritures en mémoire, mais jusqu'à présent, j'ai à peine utilisé cette fonctionnalité.

Le deuxième des tiroirs bruyants s'appelle la «petite boîte» (la première «grande boîte» avait à peu près la taille d'un petit réfrigérateur). En substance, il s'agit de Saturne avec des interfaces supplémentaires pour l'E7000 et l'émulateur de CD. Sur le panneau avant, il dispose de commutateurs d'identification de pays et d'un commutateur entre PAL et NTSC.

À l'intérieur du deuxième ordinateur se trouve un émulateur de CD - une grande carte, grâce à laquelle le disque dur de l'ordinateur prétend être un lecteur de CD. Vous pouvez y collecter une image de CD et l'émuler en temps réel pour voir à quoi ressemblera le jeu lorsqu'il arrivera sur un vrai CD. L'émulateur fonctionne plus ou moins, bien qu'il ait quelques problèmes sur lesquels nous travaillons avec Sega.

image

Le kit de développement de Sega lui-même

Compilation et liaison


L'assemblage général du programme terminé est contrôlé par un makefile: MAKEFILE.MAK. Il contient des dépendances et des cibles pour l'ensemble du projet, y compris la compilation de fichiers .GOB et .GOV.

Les modules de code source C individuels (fichiers .C) sont compilés par CCSH en modules d'objet SH2 (.OBJ). Il appelle d'abord le préprocesseur GNU C appelé CPPSH (situé dans C: \ GNUSH2 \ BIN), puis appelle CC1SH pour sa sortie pour créer le code assembleur SH2, et enfin appelle ASSH (dans C: \ PSYQ) pour le construire dans le format d'objet fini.

Nous n'utilisons pas C ++ car on m'a dit qu'il crée d'énormes fichiers objets. Cependant, je n'ai pas travaillé avec lui, vous pouvez expérimenter.

Plusieurs fichiers dans le langage assembleur SH2 (avec l'extension .S) sont simplement collectés à l'aide d'ASMSH directement dans des fichiers .OBJ (ce n'est pas la même chose qu'ASSH, mais un assembleur de macros plus complexe). Actuellement, ils ne sont utilisés que pour incorporer des données et ne contiennent pas de code dépendant de la machine.

La RAM Saturn, dans laquelle le code peut être chargé, est divisée en deux blocs de 1 Mo. L'un commence à 06 000 000 $ et l'autre à 002 000 000 $. Le bloc à 00 200 000 $ est utilisé exclusivement pour stocker des graphiques du personnage principal. Le code du programme est écrit à 06010000 $ (les premiers 10 000 octets sont utilisés pour l'espace système, la pile, etc.)

Le code est dépendant de la position et compilé pour s'exécuter à cette adresse spécifique (06010000 $) et rien d'autre.

Les fichiers .OBJ sont liés entre eux à l'aide du programme PSYLINK pour créer le fichier MAIN.CPE, un programme exécutable avec un petit en-tête qui peut être téléchargé sur Saturne avec la commande RUN. PSYLINK utilise le fichier TEST.LNK pour indiquer les fichiers .OBJ à inclure et où les placer.

Les données


Le jeu est divisé en plusieurs niveaux, de nombreux niveaux utilisent les mêmes données, mais fondamentalement, ils sont différents pour chaque niveau. Toutes les données de chaque niveau sont collectées dans deux énormes fichiers .GOV et .GOB. (dans le cas d'une mine, il s'agit de MINE.GOV et MINE.GOB). Le fichier GOV contient un en-tête court, puis vient toutes les données qui devraient être dans la mémoire vidéo. Le fichier .GOB contient toutes les données qui doivent être en RAM.

Le niveau se compose d'une partie des fichiers de données illustrés ci-dessous.

.SSQ - fichier séquenceur sprite
.SBM - fichier bitmap utilisé pour les arrière-plans de bits
.MAP - les deux cartes pour les arrière-plans remplis de symboles.
.TIL - tuiles et palettes pour les arrière-plans remplis de symboles.
.PTH - données des points de route et des déclencheurs.
.TEX - textures pour la route.

Les fichiers .SSQ et .SBM ont été créés par mon séquenceur SEQ de plus en plus inconfortable. Les fichiers .MAP, .TIL, .PTH et .TEX ont été créés par Dan, un éditeur de cartes TULE de plus en plus étonnant.

Ces fichiers sont assemblés à l'aide de l'assembleur ASMSH dans les fichiers .GOV et .GOB correspondants. Pour voir comment cela se fait, consultez les fichiers LEVEL.S et LEVEL1.S. Un fichier .GOV comprend également certaines des données à un niveau particulier.

Modules


TEST.S - rien de spécial, définit quelques étiquettes.

MAIN.C est le niveau supérieur du programme. Il contient l'initialisation de l'équipement, les paramètres de niveau, un code pour passer les niveaux et divers autres petits éléments qui devraient être placés dans des modules plus appropriés. Il y a beaucoup de déchets, car il est plus facile d'ajouter quelque chose de nouveau à ce module pour des tests rapides. Contient le code de démarrage à partir d'un CD ou d'un serveur de fichiers sur un PC. Contient un indicateur pour activer ou désactiver les barres de couleur TIMING.

GFXLIB.C - diverses procédures pour accéder à l'équipement et exécuter diverses fonctions graphiques. Presque tous sont écrits à partir de zéro par Dan et sont souvent très inefficaces. Si vous utilisez souvent la procédure à partir d'ici, ce serait bien de jeter un œil à ce qu'elle fait et d'écrire une version plus rapide dans votre code.

Cependant, toutes les fonctions fonctionnent et fournissent un excellent cadre pour une implémentation et des tests approximatifs. Merci Dan, cela n'aurait pas été possible sans lui.

SMP_PAD.C - diverses procédures de lecture à partir du joystick Saturn, très dépendant de l'équipement.

GLOBALS.C - toutes les variables globales et plusieurs fonctions communes. L'utilisation de variables globales est une pratique de programmation acceptable. Cependant, pour diverses raisons, l'implémentation des variables globales dans SH2 est assez lente, donc au fil du temps je convertirai probablement la pièce en structures globales si nécessaire. Contient des variables décrivant l'état de MAN et PATH .

MAN.C - gère le mouvement et l'affichage d'une personne (Prince Lightstar, Talyn, Guardian ou Grimskull - le personnage contrôlé par le joueur). Jusqu'à présent, c'est principalement la logique du mouvement et des collisions avec la route. De plus, il fournit l'animation appropriée pour chaque action. Il y a encore beaucoup de travail à faire.

OB.C - gère le mouvement et l'affichage des objets dans le jeu, en particulier les objets des ennemis, par exemple, les guerriers squelettes et les petits extraterrestres. La partie principale du gameplay est programmée ici: l'IA ennemie, les mouvements de base et le déclenchement des déclencheurs. La structure des données n'est pas encore prête, en particulier, les problèmes de collisions et d'animations ne sont pas complètement résolus. Il y a encore beaucoup de travail à faire.

DATA.S - divers tableaux, actuellement principalement des animations des personnages principaux du joueur.

LAYER.C - défilement des arrière-plans avec parallaxe. Met à jour les arrière-plans des symboles et les bitmaps de défilement. Défilement également des lignes (effet d'onde) dans la couche de brouillard. Jusqu'à présent, les tables des couches de carte de symboles sont stockées sans compression. Ils doivent être compressés au format RLE que j'ai utilisé pour la version Genesis. Cette tâche peut être confiée à Ken si nous obtenons un système de développement pour Saturne plus tôt que pour Sony.

PAL.C - palette. Vous pouvez choisir parmi 2048 couleurs. Tout pixel à l'écran peut être l'une de ces couleurs. J'ai logiquement divisé la palette en huit palettes de 256 couleurs. PAL.C contient du code pour leur initialisation, préparation et code pour leur changement cyclique. Ils auront également besoin de gradation et d'un décalage cyclique plus complexe, ainsi que de flashs de luminosité, etc.

BUL.C est un système primitif pour traiter des obus (lancer une épée, poinçonner une main, des roquettes tirées des mains, etc.) comme des objets séparés. Beaucoup de travail est encore nécessaire pour une utilisation plus complexe des coques. Vous avez également besoin du bon code de collision et d'animation.

PAD.C est un module simple pour stocker l'état du joystick dans un format plus pratique. Mémorise si le bouton a été pressé récemment et s'il est maintenant pressé.

START.C - une ligne qui indique quel niveau sera le premier, pour faciliter le changement dans le fichier de commandes.

PANEL.C - procédures simples pour retirer une séquence de force.

PATH.C - procédures monstrueuses pour tracer la route, ainsi que pour gérer les collisions avec la route.

MATH.C - sinus simple, cosinus et rotation d'un point par un angle.

[Mise à jour] Voici un exemple de code de MAN.C. Tout est écrit de manière rigide dans le code et fait référence à la structure de données globale Man. Un tas de chiffres écrits dans le code.

/**************************************************************/ /* Trigger jumping if needed, also variable height jump logic */ Man_JumpTrigger() { if ( Man.JumpFudge ) { Man.JumpFudge--; } if ( Man.Mode != M_Crouch || Man_StandingRoom() ) // ok if not crouched, or there is headroom { if (Pad_Jump->Pressed) /* jump button pressed */ { if ((Man.Contact || (Man.Mode == M_Hang) || Man.JumpFudge) && Pad_Jump->Triggered && !Man.Blocking) /* and not already jumping */ { if (Man.Mode == M_Hang && Pad1.Down.Pressed) { Man.Contact=0; Man.Mode=M_Jump; Man.AnimBase = LS_Jumping; /* Change base anim to jumping */ Man_TriggerSeq(LS_Jump); /* start the jumping start anim */ Man.YV.f = 0x10000; /* and have no YV */ Man.Yi += 4; /* and have no YV */ } else { Pad_Jump->Triggered = 0; if ( !JetPacCheat ) Man.YV.f = -0x00080000; /* Initial jump speed */ else Man.YV.f = -0x00008000; // Initial speed in Jetpac mode Man.Contact = 0; /* not on the ground any more */ Man.JumpTime = 0; /* just started jumping */ Man.AnimBase = LS_Jumping; /* Change base anim to jumping */ Man_TriggerSeq(LS_Jump); /* start the jumping start anim */ Man.XV.f+=Man.FlyVel; if (Man.HangEnd && Man.Mode == M_Hang) // if hanging { // and on the end of a path Man.HangEnd = 0; Man.Xi += 12*Man.Facing; // the move past end of path Man.JumpTime = -3; // bit more fixed v jump time } Man.Mode = M_Jump; /* change mode to jumping */ } } else /* Already jumping */ { if (Man.JumpTime++ < MaxJumpTime) /* Still in initial jump period */ Man.YV.f -= 0x0005000; /* So can maintain jump YV */ } } else /* jump button not pressed */ { Man.JumpTime = MaxJumpTime+1; /* so can't alter YV again until landed */ } } } 

OB.C est devenu un fichier monstrueux de 9 000 lignes, qui comprend tous les modèles de comportement des objets individuels dans le jeu. Il y a aussi un grand nombre de nombres écrits dans le code, par exemple, tels que:

 Drop_Arac(S_Ob *pOb) { int t; if (pOb->Jump==1) { pOb->yv.f+=0x7fff; pOb->y.f+=pOb->yv.f; t=Path_GetYZ(pOb->xi,pOb->yi,pOb)-15; if ((t>pOb->yi)&&(t<pOb->y.i+20)) { pOb->Jump=0; pOb->y.i+=15; Turn_Around(pOb); pOb->SeqFile=Sprites[SpriteMap[34]]; Object_TriggerSeq(Arac_JumpLand,pOb); } } else { if (pOb->Frame==16) pOb->Jump=1; if (pOb->AnimStat==AnimDone) { pOb->t1=0; pOb->Mode=&Pattern_Arac; } } Command_Arac(pOb); } 

Une vue désagréable. Ce style de code est venu d'une époque où les jeux étaient très petits et je l'ai développé en travaillant avec 68K.

image

Source: https://habr.com/ru/post/fr459622/


All Articles