Como los juegos para Sega Saturn fueron escritos en 1995

Este es un documento que escribí en 1995 cuando estaba trabajando en el primer juego del estudio Neversoft: Skeleton Warriors. Este fue el primer juego en el que no utilicé el lenguaje ensamblador 68K.

Foto tomada alrededor del tiempo. El kit de desarrollo ("Small Box" e ICE) está a mi derecha.


Estado del juego


El siguiente documento describe brevemente el estado del código de Skeleton Warriors para Sega Saturn, y también menciona algunos de los muchos aspectos que aún deben hacerse.

El documento era necesario para acelerar la familiaridad de Dan, Ken y James con el código prefabricado, para explicarles el propósito de cada módulo y la interacción entre ellos. También me permitió apreciar el triste estado de este código y, con suerte, me hizo tomar la decisión.

También hablo un poco sobre la incorporación de datos (archivos .GOV y .GOB) en el programa, y ​​sobre lo que haremos en el futuro.

Equipo de desarrollo


Nuestra plataforma de destino es Sega Saturn, que tiene dos microprocesadores Risc SH2 y un 68000. Siempre que usemos solo el procesador principal Master SH2, el esclavo SH2 auxiliar se usará cuando descubramos cómo hacer esto. 68000 se usa para controlar el chip de sonido, no tuvimos que escribir código para él, porque usará la biblioteca de sonido proporcionada por Sega.

El programa está escrito casi por completo en puro C. Utilizamos el compilador GNU SH2 para obtener el ensamblador de salida SH2. Hay varios módulos SH2 en el código, que contienen principalmente datos exclusivamente. Hasta ahora no he escrito nada significativo en SH2.

Como sistema de desarrollo, utilizamos PsyQ. Este no es un sistema de desarrollo estándar de Sega, pero todos los que trabajaron con él lo consideran el mejor. Una alternativa a esto es SNASM, creado por Cross Products, propiedad de Sega. La mayoría de los ejemplos de código suministrados por Sega deberían funcionar en el sistema de desarrollo SNASM, pero se pueden convertir fácilmente a PsyQ.

El sistema PsyQ consta de una tarjeta de interfaz SCSI, que se instala en la PC, un cartucho que se conecta a Saturno y conecta el cable. Las fuentes se compilan en una PC y se descargan a Saturno, donde se inicia el programa. El código se puede depurar desde la PC.


Sistema de desarrollo PsyQ

La comunicación es controlada por un programa residente (PSYBIOS), que procesa las comunicaciones entre máquinas. Esto permite que la consola Saturn descargue archivos de una PC de la misma manera que los descargaría de un CD. Utilizamos esta función para descargar archivos de cada nivel.

Tengo un par de cajones grandes y ruidosos en mi habitación, y dos PC más. El más pequeño de los dos cuadros es el E7000PC, que es un emulador SH2 incorporado. Ayuda a determinar dónde se bloquea el programa si el depurador PsyQ no lo detiene. También es útil para el seguimiento de las escrituras en la memoria, pero hasta ahora apenas he usado esta función.

El segundo de los cajones ruidosos es algo llamado "Caja pequeña" (la primera "Caja grande" era del tamaño de un refrigerador pequeño). En esencia, es Saturno con interfaces adicionales para el E7000 y el emulador de CD. En el panel frontal, tiene interruptores de ID de país y un interruptor entre PAL y NTSC.

Dentro de la segunda computadora hay un emulador de CD, una placa grande, gracias a la cual el disco duro de la computadora pretende ser una unidad de CD. Puede recopilar una imagen de CD y emularlo en tiempo real para ver cómo se verá el juego cuando llegue a un CD real. El emulador funciona más o menos, aunque tiene algunos problemas en los que estamos trabajando junto con Sega.

imagen

Sega's Dev kit en sí

Compilar y vincular


El ensamblaje general del programa terminado está controlado por un archivo MAKEFILE.MAK. Contiene dependencias y objetivos para todo el proyecto, incluida la compilación de archivos .GOB y .GOV.

CCSH compila módulos de código fuente C individuales (archivos .C) en módulos de objetos SH2 (.OBJ). Primero llama al preprocesador GNU C llamado CPPSH (ubicado en C: \ GNUSH2 \ BIN), luego llama a CC1SH por su salida para crear el código ensamblador SH2, y finalmente llama a ASSH (en C: \ PSYQ) para construirlo en el formato del objeto terminado.

No usamos C ++ porque me dijeron que crea grandes archivos de objetos. Sin embargo, no trabajé con él, puedes experimentar.

Varios archivos en el lenguaje ensamblador SH2 (con la extensión .S) simplemente se recopilan utilizando ASMSH directamente en archivos .OBJ (esto no es lo mismo que ASSH, sino un ensamblador de macros más complejo). Actualmente, se usan solo para incrustar datos y no contienen código dependiente de la máquina.

La RAM de Saturno, en la que se puede cargar el código, se divide en dos bloques de 1 MB. Uno comienza en $ 06,000,000 y el otro en $ 002,000,000. El bloque de $ 00,200,000 se usa exclusivamente para almacenar gráficos del personaje principal. El código del programa está escrito en $ 06010000 (los primeros $ 10,000 bytes se usan para el espacio del sistema, la pila y similares).

El código depende de la posición y se compila para ejecutarse en esta dirección específica ($ 06010000) y nada más.

Los archivos .OBJ se vinculan mediante el programa PSYLINK para crear el archivo MAIN.CPE, un programa ejecutable con un pequeño encabezado que se puede descargar a Saturno con el comando EJECUTAR. PSYLINK usa el archivo TEST.LNK para indicar qué archivos .OBJ incluir y dónde colocarlos.

Datos


El juego está dividido en varios niveles, muchos niveles usan los mismos datos, pero básicamente son diferentes para cada nivel. Todos los datos para cada nivel se recopilan en dos enormes archivos .GOV y .GOB. (en el caso de una mina, es MINE.GOV y MINE.GOB). El archivo GOV contiene un encabezado corto y luego vienen todos los datos que deberían estar en la memoria de video. El archivo .GOB contiene todos los datos que deben estar en la RAM.

El nivel consta de una parte de los archivos de datos que se muestran a continuación.

.SSQ - archivo secuenciador de sprites
.SBM: archivo de mapa de bits utilizado para fondos de bits
.MAP: ambos mapas para fondos llenos de símbolos.
.TIL: conjuntos de mosaicos y paletas para fondos llenos de símbolos.
.PTH: datos de puntos de ruta y disparadores.
.TEX: texturas para el camino.

Los archivos .SSQ y .SBM fueron creados por mi secuenciador SEQ cada vez más incómodo. Los archivos .MAP, .TIL, .PTH y .TEX fueron creados por Dan, un editor de mapas TULE cada vez más impresionante.

Estos archivos se ensamblan utilizando el ensamblador ASMSH en los archivos .GOV y .GOB correspondientes. Para ver cómo se hace esto, vea los archivos LEVEL.S y LEVEL1.S. Un archivo .GOV también incluye algunos de los datos en un nivel particular.

Módulos


TEST.S : nada especial, establece algunas etiquetas.

MAIN.C es el nivel superior del programa. Contiene la inicialización de equipos, configuraciones de nivel, un código para pasar niveles y varios otros elementos pequeños que en realidad deberían colocarse en módulos más adecuados. Hay mucha basura en él, porque es más fácil agregar algo nuevo a este módulo para una prueba rápida. Contiene el código de arranque de un CD o servidor de archivos en una PC. Contiene una bandera para habilitar o deshabilitar las barras de colores TIMING.

GFXLIB.C : varios procedimientos para acceder al equipo y realizar diversas funciones gráficas. Casi todos están escritos desde cero por Dan y, a menudo, son muy ineficientes. Si a menudo usa el procedimiento desde aquí, sería bueno echar un vistazo a lo que hace y escribir una versión más rápida en su código.

Sin embargo, todas las funciones funcionan y proporcionan un marco excelente para una implementación y pruebas aproximadas. Gracias a Dan, no hubiera sido posible sin él.

SMP_PAD.C : varios procedimientos para leer desde el joystick de Saturno, muy dependientes del equipo.

GLOBALS.C : todas las variables globales y varias funciones comunes. El uso de variables globales es una práctica de programación aceptable. Sin embargo, por varias razones, la implementación de variables globales en SH2 es bastante lenta, por lo que con el tiempo probablemente convertiré la parte a estructuras globales si es necesario. Contiene variables que describen el estado de MAN y PATH .

MAN.C : maneja el movimiento y la exhibición de una persona (Prince Lightstar, Talyn, Guardian o Grimskull, el personaje controlado por el jugador). Hasta ahora, esta es principalmente la lógica del movimiento y las colisiones con la carretera. Además, proporciona la animación adecuada para cada acción. Todavía queda mucho trabajo por hacer.

OB.C : maneja el movimiento y la visualización de objetos en el juego, especialmente objetos de enemigos, por ejemplo, guerreros esqueleto y pequeños alienígenas. Aquí se programa la parte principal del juego: IA enemiga, movimientos básicos y activación de disparadores. La estructura de datos aún no está lista, en particular, los problemas con colisiones y animaciones no están completamente resueltos. Todavía queda mucho trabajo por hacer.

DATA.S : varias tablas, actualmente principalmente animaciones de los personajes principales del jugador.

LAYER.C : desplazamiento de fondos con paralaje. Actualiza fondos de símbolos y mapas de bits de desplazamiento. También líneas de desplazamiento (efecto de onda) en la capa de niebla. Hasta ahora, las tablas para las capas del mapa de símbolos se almacenan sin compresión. Deben comprimirse al formato RLE que utilicé para la versión Genesis. Esta tarea puede ir a Ken si obtenemos un sistema de desarrollo para Saturno antes que para Sony.

PAL.C - paleta. Puedes elegir entre 2048 colores. Cualquier píxel en la pantalla puede ser uno de estos colores. Lógicamente dividí la paleta en ocho paletas de 256 colores. PAL.C contiene código para su inicialización, preparación y código para su cambio cíclico. También necesitarán atenuación y un cambio cíclico más complejo, así como destellos de brillo, etc.

BUL.C es un sistema primitivo para procesar proyectiles (lanzar una espada, golpear una mano, lanzar cohetes desde las manos, etc.) como objetos separados. Todavía se requiere mucho trabajo para el uso más complejo de los depósitos. También necesita el código correcto de colisión y animación.

PAD.C es un módulo simple para almacenar el estado del joystick en un formato más conveniente. Memoriza si el botón se presionó recientemente y si ahora se presionó.

START.C : una línea que indica qué nivel será el primero, para facilitar su modificación en el archivo por lotes.

PANEL.C - procedimientos simples para retirar una racha de fuerza.

PATH.C : procedimientos monstruosos para dibujar el camino, así como para manejar colisiones con el camino.

MATH.C : seno simple, coseno y rotación de un punto por un ángulo.

[Actualización] Aquí hay un código de muestra de MAN.C. Todo está escrito rígidamente en el código y se refiere a la estructura de datos global Man. Un montón de números escritos en el código.

/**************************************************************/ /* 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 se ha convertido en un monstruoso archivo de 9,000 líneas, que incluye todos los patrones de comportamiento de objetos individuales en el juego. También hay una gran cantidad de números escritos en el código, por ejemplo:

 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); } 

Una vista desagradable. Este estilo de código vino de una época en que los juegos eran muy pequeños y lo desarrollé cuando trabajaba con 68K.

imagen

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


All Articles