As the games for Sega Saturn were written in 1995

Original author: Mick West
  • Transfer
This is a document I wrote in 1995 when I was working on the first game of the Neversoft studio: Skeleton Warriors. This was the first game in which I did not use the 68K assembly language.

Photo taken at about the time. The dev kit (“Small Box” and ICE) is on my right.


Game state


The document below briefly describes the status of the Skeleton Warriors code for Sega Saturn, and also mentions some of the many aspects that still needed to be done.

The document was needed in order to speed up Dan, Ken and James familiarity with the ready-made code, to explain to them the purpose of each module and the interaction between them. He also allowed me to assess the sad state of this code, and, hopefully, made me take up the mind.

I also talk a bit about embedding data (.GOV and .GOB files) in the program, and about what we will do in the future.

Development Equipment


Our target platform is Sega Saturn, which has two SH2 Risc microprocessors and one 68000. As long as we use only the Master SH2 main processor, the auxiliary SH2 slave will be used when we figure out how to do this. 68000 is used to control the sound chip, we did not have to write code for it, because it will use the sound library provided by Sega.

The program is almost entirely written in pure C. We use the GNU SH2 compiler to get the SH2 output assembler. There are several SH2 modules in the code, which mainly contain data exclusively. So far I have not written anything meaningful on SH2.

As a development system, we use PsyQ. This is not a standard Sega development system, but everyone who worked with it considers it the best. An alternative to it is SNASM, created by Cross Products owned by Sega. Most of the code samples supplied by Sega should work in the SNASM development system, but can be easily converted to PsyQ.

The PsyQ system consists of a SCSI interface board, which is installed in the PC, a cartridge that is inserted into Saturn and connects the cable. Sources are compiled on a PC and downloaded to Saturn, where the program starts. Code can be debugged from PC.


The PsyQ

communications development system is controlled by a resident program (PSYBIOS) that processes communications between machines. This allows the Saturn console to download files from a PC in much the same way that it would download them from a CD. We use this function to download files of each level.

I have a couple of large and loud drawers in my room, and two more PCs. The smaller of the two boxes is the E7000PC, which is a built-in SH2 emulator. It helps to figure out where the program crashes if the PsyQ debugger does not stop it. It is also useful for tracking memory writes, but so far I have hardly used this feature.

The second of the loud drawers is something called the Small Box (the first Large Box was about the size of a small refrigerator). In essence, it is Saturn with additional interfaces for the E7000 and the CD emulator. On the front panel, it has country ID switches and a switch between PAL and NTSC.

Inside the second computer is a CD emulator - a large board, thanks to which the computer’s hard drive pretends to be a CD drive. You can collect a CD image in it and emulate it in real time to see how the game will look when it gets to a real CD. The emulator more or less works, although it has some problems that we are currently working on with Sega.

image

Sega's Dev kit itself

Compiling and Linking


The general assembly of the finished program is controlled by one makefile: MAKEFILE.MAK. It contains dependencies and targets for the entire project, including compiling .GOB and .GOV files.

Individual C source code modules (.C files) are compiled by CCSH into SH2 object modules (.OBJ). It first calls the GNU C preprocessor called CPPSH (located in C: \ GNUSH2 \ BIN), then calls CC1SH for its output to create the SH2 assembler code, and finally calls ASSH (in C: \ PSYQ) to build it into the finished object format.

We do not use C ++ because I was told that it creates huge object files. However, I did not work with him, you can experiment.

Several SH2 assembler files (with the .S extension) are simply collected using ASMSH directly into .OBJ files (this is not the same as ASSH, but a more complex macro assembler). Currently, they are used only for embedding data, and do not contain machine-dependent code.

Saturn RAM, into which the code can be loaded, is divided into two 1MB blocks. One starts at $ 06,000,000, and the other at $ 002,000,000. The block at the address $ 00200000 is used exclusively for storing graphics of the main character. The program code is written at the address $ 06010000 (the first $ 10,000 bytes are used for the system space, stack, and the like.)

The code is position-dependent and compiled to run at this specific address ($ 06010000) and nothing else.

The .OBJ files are linked together using the PSYLINK program to create the MAIN.CPE file, an executable program with a small header that can be downloaded to Saturn with the RUN command. PSYLINK uses the TEST.LNK file to indicate which .OBJ files to include and where to put them.

Data


The game is divided into several levels, many levels use the same data, but basically they are different for each level. All data for each level is collected in two huge .GOV and .GOB files. (in the case of a mine, it is MINE.GOV and MINE.GOB). The GOV file contains a short header, and then comes all the data that should be in the video memory. The .GOB file contains all the data that must be in RAM.

The level consists of a portion of the data files shown below.

.SSQ - sprite sequencer file
.SBM - bitmap file used for bit backgrounds
.MAP - both cards for symbol-filled backgrounds.
.TIL - tilesets and palettes for symbol-filled backgrounds.
.PTH - data of road points and triggers.
.TEX - textures for the road.

The .SSQ and .SBM files were created by my increasingly uncomfortable SEQ sequencer. The .MAP, .TIL, .PTH, and .TEX files were created by Dan, an increasingly awesome TULE map editor.

These files are assembled using the ASMSH assembler into the corresponding .GOV and .GOB files. To see how this is done, see the LEVEL.S and LEVEL1.S files. A .GOV file also includes a piece of data at a particular level.

Modules


TEST.S - nothing special, sets a few labels.

MAIN.C is the top level of the program. It contains the initialization of equipment, level settings, a code for passing levels and various other small elements that actually should be placed in more suitable modules. There is a lot of garbage in it, because it is easiest to add something new to this module for quick testing. Contains the download code from a CD or file server on a PC. Contains a flag to enable or disable the TIMING color bars.

Gfxlib.c- various procedures for accessing equipment and performing various graphic functions. Almost all of them are written from scratch by Dan and are often very inefficient. If you often use the procedure from here, it would be nice to take a look at what it does and write a faster version in your code.

However, all functions work and provide an excellent framework for rough implementation and testing. Thank Dan, it would not have been possible without him.

SMP_PAD.C - various procedures for reading from the Saturn joystick, very dependent on the equipment.

GLOBALS.C- all global variables and several common functions. Using global variables is an acceptable programming practice. However, for various reasons, the implementation of global variables in SH2 is rather slow, so over time I will probably convert the part to global structures if necessary. Contains variables describing the state of MAN and PATH .

MAN.C - handles the movement and display of a person (Prince Lightstar, Talyn, Guardian or Grimskull - the character controlled by the player). So far, this is mainly the logic of movement and collisions with the road. In addition, it provides the appropriate animation for each action. There is still a lot of work to do.

OB.C- Handles the movement and display of objects in the game, especially objects of enemies, for example, skeleton warriors and small aliens. The main part of the gameplay is programmed here: enemy AI, basic movements and triggering of triggers. The data structure is not yet ready, in particular, problems with collisions and animations are not completely worked out. There is still a lot of work to do.

DATA.S - various tables, currently mainly animations of the player’s main characters.

LAYER.C- scrolling of backgrounds with parallax. Updates symbol backgrounds and scrolling bitmaps. Also scrolling lines (wave effect) in the fog layer. So far, tables for symbol map layers are stored without compression. They need to be compressed to the RLE format that I used for the Genesis version. This task can go to Ken if we get a development system for Saturn earlier than for Sony.

PAL.C - palette. You can choose from 2048 colors. Any pixel on the screen can be one of these colors. I logically divided the palette into eight palettes of 256 colors. PAL.C contains code for their initialization, preparation, and code for their cyclic change. They will also need dimming and a more complex cyclic shift, as well as flashes of brightness, etc.

BUL.C- A primitive system for processing shells (throwing a sword, punching a hand, rockets fired from the hands, etc.) as separate objects. Quite a lot of work is still required for the more complex use of shells. You also need the correct collision and animation code.

PAD.C is a simple module for storing the state of the joystick in a more convenient format. Memorizes whether a button has been pressed recently and whether it is pressed now.

START.C - one line that tells which level will be the first, for ease of changing it in the batch file.

PANEL.C - simple procedures for withdrawing a streak of strength.

PATH.C - monstrous procedures for drawing the road, as well as handling collisions with the road.

MATH.C- simple sine, cosine and rotation of a point on an angle.

[Update] Here is a sample code from MAN.C. Everything is rigidly written in the code and refers to the global data structure Man. A bunch of numbers written in the 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.Y.i += 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.X.i += 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 has grown into a monstrous file of 9,000 lines, which includes all the behavior patterns of individual objects in the game. There is also a huge number of numbers written in the code, for example, these:

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->x.i,pOb->y.i,pOb)-15;
    if ((t>pOb->y.i)&&(ty.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);
}

An unpleasant sight. This style of code came from a time when the games were very small and I developed it when working with 68K.

image

Also popular now: