Reply 80 of 91, by SiliconClassics
- Rank
- Member
Just wanted to provide a brief update regarding the status of this winter project. At this point I've finished sifting through the Indies, some of which contain some fun 3D models and other art assets. One has a working install of Alias|Wavefront 4, and another has Nichimen N-World 3.1, which unfortunately crashes on startup. Three of them were from Probe in the UK, and they've got some of the most interesting art inside.
Turns out there was one other system from Iguana (had a small asset tag on a corner of the lid) that does contain a copy of the Turok source code. I haven't decided what to do with it yet. Despite the massive amount of criticism I received a few weeks ago for selling the first one to a collector on eBay, I do genuinely want to ensure that the code is preserved for posterity. Many comments on YouTube and Reddit suggested offering it to the Internet Archive, so I might look into that before dispensing with it, and I've already mentioned it to Stephen Kick at Night Dive in case they might have a use for it.
A search of the other Indies didn't turn up any new source code for games, but a search of the CDR backup discs did uncover what appears to be the source for NBA Jam Extreme. The title isn't mentioned anywhere in the code, which instead refers to the game as "Squid," which appears to be an internal codename. A section of the game's main C file is below.
I'll be posting further updates to Twitter and YouTube over the coming weeks, and I'll continue to sell these Indies on eBay until they're all gone (have eight more left to sell as of today).
/*
* File -> squid.c
* Description -> SQUID top-level game module
* Created -> Jan 19, 1995
* Author -> Dwain Skinner & Dave Ross
* Modified -> Michael Callahan, Daren Smith
*/
/*
* SQUID.C: Highest level (MAIN) game module
*
* Version 1.00 Jan. 19, 1995
*/
#define SQUID_C
#include <sys/types.h>
#include <libetc.h>
#include <libgte.h>
#include <libgpu.h>
#include <libgs.h>
#include <libsn.h>
#include <asm.h>
#include <kernel.h>
#include <libarc95.h>
#include <libcd.h>
#include "mikecode.h"
#include "squid.h"
#include "config.h"
#include "ai.h"
#include "anim.h"
#include "task.h"
#include "taskv.c"
#include "squidv.c"
#include "pstats.c"
#include "aiv.c"
#include "coinv.c"
#include "gpv.c"
//msa #include "sqaudio.h"
#include "hardware.h"
#include "account.h"
#include "coin.h"
#include "loaders.h"
#include "fluff/fluff.h"
#include "turbo.h"
//msa #include "daughter.h"
#include "teams.h"
//msa #define TEST_HEADROID TRUE
#define TEST_HEADROID FALSE
void fullGameBonus(short i);
void game_skip_fluff_quasi_state();
void diagnostics();
void gameFluffMainTask1();
void nbalicense();
//void intro();
extern unsigned int mike_mode; // sets mode, ms
extern int diagnostics_done;
unsigned int ShootOutOn=0;
int OneQuarterTournamentMode;
int free_play_mode; // do not initialize here. Initialized through diagnostics.
u_char quarterGameCounter[4];
int gameDate;
int gameVolume;
int attractModeSound;
int ComputerDifficulty;
int OverTimeFree;
int GameTimeSpeed;
u_char whichRodman[4];
extern long Quarter;
extern unsigned short PlyrSnds[];
extern unsigned char PlyrDurs[];
extern unsigned short TeamSnds[];
extern unsigned char TeamDurs[];
extern short passwordScreenAlready;
extern short winningTeam[4];
extern short freeGameWindow;
extern short freeGameFlag;
extern short freeGameBonus;
u_short checkForButtonTimer;
///////////////////////////////////////////////////////////////////////////
// extern declarations for things that aren't in header files yet.
/* set true to enable main debugging print statements */
#define MDP FALSE
#define max(a,b) ((a>=b) ? a : b)
//--------------------------------------------------------------------------
// Function Prototypes
//msa void exitProgram() __attribute__ ((noreturn));
void game_boot_state();
void game_attract_state();
void game_quarter_wrapper_state();
void game_play_state();
void game_quarter_over_state();
void game_demo_state();
int period_available_p(int i);
//--------------------------------------------------------------------------
// Global Variables
int GameOverFlag;
int OverTimeFlag;
typedef void (*void_function)();
// WARNING: This order needs to match the one in the game_state_enum type
void_function game_state_functions[] =
{
game_boot_state,
game_attract_state,
game_quarter_wrapper_state,
game_play_state,
game_quarter_over_state,
game_demo_state,
};
int start_game_flag;
int player_mode;
////////////////////////////////////////////////////////////////////////////
// This is the main function, it just does some simple initialization
// stuff and then jumps into the tasking stuff leaving function MainGame
// to do all of the meatier stuff.
//
void
main()
{
int squidout;
// CheckSecurity();
store_gp(squid_gp); //save our global base for use by interrupt routines.
// SetPIORegs(); //set PIO bus timing for optimal performance
//msa SetPIOARRAYRegs();
ResetCallback();
/*
* Patch of gte
* You must link patchgte.obj when you use this function.
* You should call this function at the beginning of main().
*/
_patch_gte();
// Do a hardware check here
//msa StartupHardwareCheck();
//msa #if DEVELOPMENT
// Init the pc file system, this is only a developement option.
//msa PCinit();
/*
squidout = PCopen("squidout.txt", 1, 0);
if (squidout < 0)
{
exit(100);
}
PClseek(squidout,0,2);
// PClseek(cpefile,0,0);
// PCwrite(cpefile, (char *)location, length);
PCwrite(squidout, "ok\n", 3);
PCclose(squidout);
*/
// CD
CdInit();
CdSetDebug(0);
//msa #endif
// Load basic stuff into memory ??? - already there in this version
{
extern long RandomNumber;
RandomNumber = STACKSIZE;
}
SetRomLen(); //ms
init_cd_loc(); //ms
initPlayerTrps(); //ms
// Initialize the Tasking System!!!!
InitTaskingSystem();
// Init the MainTCB with 3 Tasks and stack size of 0x400
InitTCB(&MainTCB, &MainTCBData[0], MAXMAINTASKS, MAINSTACKSIZE);
// Must set the current TCB before calling scheduler
CurrentTCB = &MainTCB;
// Fire up the Main Task
ExecuteTask(&MainTCB, &MainGame, 0, 0);
// Call Scheduler and never come back!!!!!!
TaskScheduler();
}
unsigned int FontUp=FALSE;//debug
/* msa
void PrintAddrs()
{
int i;
extern unsigned long BallFlags;
//special signal to output debug data for Dwain//
if(!FontUp)
{
FntLoad(960, 256);
font_id[0] = FntOpen(-128,120-5*8-1, 176+128, 5*8, 1, 512);
font_id[1] = FntOpen(-128,120-5*8-1, 176+128, 5*8, 1, 512);
SetDumpFnt(font_id[0]);
SetDumpFnt(font_id[1]);
FontUp=TRUE;
}
for(i=0;i<16;i+=4)
FntPrint(font_id[activeBuff], "%x %x %x %x\n",
PlayerTCBData[i+0].TaskAddress,
PlayerTCBData[i+1].TaskAddress,
PlayerTCBData[i+2].TaskAddress,
PlayerTCBData[i+3].TaskAddress);
FntPrint(font_id[activeBuff], "%x\n",
BallFlags);
FntFlush(font_id[activeBuff]);
}
*/ //msa
//////////////////////////////////////////////////////////////////////////
// Main game play
//
//
// The master exec is a simple state machine.
//
// Here are the modes it currently can be in:
// GAME_STARTUP:
// The game starts in this state, it just inits the fluff.
// GAME_FLUFF:
// Jump around to generic fluff screens, start the game
// if certain conditions are met.
// GAME_PLAY
// Play the game, when it's over, it sets it's own state.
// GAME_OVER
// Init fluff and jump to GAME_FLUFF state.
//
u_long cache_reg, global2;
void mike_set_teams()
{
extern int PlayerChallengeFactor[4];
extern int ShootoutEnableCode[4];
#if 1
//msa TeamIndex[0]=SANANTONIO;
//msa TeamIndex[1]=HOUSTON;
// TeamIndex[0]=SMILEY;
// TeamIndex[1]=MISFIT1;
// TeamIndex[0]=ALLSTAREAST1;
// TeamIndex[1]=ALLSTARWEST1;
// TeamIndex[0]=SMILEY;
// TeamIndex[0]=INVISIBLE;
// TeamIndex[1]=INVISIBLE;
// TeamIndex[0]=CLEVELAND;
// TeamIndex[1]=CLEVELAND;
TeamIndex[0]=(GetRandom255() % NUMBER_OF_TEAMS);
TeamIndex[1]=(GetRandom255() % NUMBER_OF_TEAMS);
// TeamIndex[0]=(GetRandom255() % NUMBER_OF_TEAMS);
// TeamIndex[1]=(GetRandom255() % NUMBER_OF_TEAMS);
// TeamIndex[0]=(GetRandom255() % NUMBER_OF_TEAMS);
// TeamIndex[1]=(GetRandom255() % NUMBER_OF_TEAMS);
// TeamIndex[0]=SECRET;
// TeamIndex[1]=SECRET;
// TeamIndex[0]=SMILEY;
// TeamIndex[1]=SMILEY;
PlayerIndex[0]=(GetRandom255() % 6);
PlayerIndex[1]=(GetRandom255() % 6);
PlayerIndex[2]=(GetRandom255() % 6);
PlayerIndex[3]=(GetRandom255() % 6);
// TeamIndex[0]=UTAH;
// TeamIndex[1]=UTAH;
// PlayerIndex[0]=1; // webb index, for minnesota
// PlayerIndex[1]=1;
// PlayerIndex[2]=1;
// PlayerIndex[3]=1;
// PlayerIndex[0]=2;
// PlayerIndex[1]=2;
// PlayerIndex[2]=2;
// PlayerIndex[3]=2;
// PlayerIndex[0]=0;
// PlayerIndex[1]=1;
// PlayerIndex[2]=0;
// PlayerIndex[3]=1;
#else
TeamIndex[0]=CHICAGO;
TeamIndex[1]=CHICAGO;
PlayerIndex[0]=0;
whichRodman[0]=0;
PlayerIndex[1]=0;
whichRodman[1]=1;
PlayerIndex[2]=0;
whichRodman[2]=2;
PlayerIndex[3]=0;
whichRodman[3]=3;
#endif
//msa ChallengeFactor=30;
ChallengeFactor=30;
//msa SetTeamPlyrSnds();
PlayerChallengeFactor[0]=1;
PlayerChallengeFactor[1]=1;
PlayerChallengeFactor[2]=1;
PlayerChallengeFactor[3]=1;
//msa ShootOutOn=0;
ShootOutOn=0; //ms
// mike_mode = 1; //ms
// mike_mode = 3; //ms
// mike_mode = 10; //ms
// mike_mode = 11; //ms
// mike_mode = 9; //ms
// mike_mode = 0; //ms
// mike_mode = 14; //ms
// mike_mode = 15; //ms
ClearLockRead();
}
void MainGame()
{
int SlowMo = 0; /*how many frames to wait each loop*/
int i, j;
// int periods_left = 4;
/* Initialize the accounting software. */
/* (do this before accepting coins) */
//msa InitAccounting();
/* start accepting coins */
InitCoinHandler();
/* init fluff tasking*/
//msa init_buffers_1();
init_fluff_1();
init_nvram_1(); // do checksum on nvram. Init if checksum not valid
//msaq init_records_1();
/* Init the game playing state - do after NVRAM init so we set to correct volume */
//msa init_audio( gameVolume );
#if SKIP_FLUFF
//msa #include "teams.h"
{
mike_set_teams();
}
#endif
/* init the ai tasking */
init_ai_1();
/* Init the animation stuff that should only be initialized one time */
init_anim_1();
for (i=0; i<4; i++)
{
Controller[i] = LEController[i] = TOGController[i] = 0;
}
RealGameState = GAME_BOOT;
GameOverFlag = 0;
OverTimeFlag = 0;
start_game_flag = 0;
player_mode = 0;
checkForButtonTimer = 0;
// Loop forever in here, doing toplevel game play stuff
while(TRUE)
{
/*our super slow-mo problem is due to the interupt maks register getting
set to zero (all-ints masked) and never getting reset. It gets set to zero
ALL THE TIME in SONY's code (for entering critical sections) so how can
we detect when it's getting set to zero without chance of getting reset?
With a pretty fancy piece of hardware...in the meantime kludgily set it
to it's usuaul value of 0x109. (GPU int's enabled, VBLANK int's enabled,
and one other kind that I don't know - it's SONY's secret). -DJR 2/25/96 */
while ( ((volatile)*((u_short *)0x1f801074) & 0x9) != 0x9 )
(volatile)*((u_short *)0x1f801074) = 0x9;//kludgily fix the symptoms of the problem
// cache_reg = (volatile)*((u_long *)0xfffe0130);
// Attempt to fix the slowdown bug by zeroing the interupt register
// each time through. - MWC 3/15/96
if ( *((u_short *)0x1f8010f4) )
*((u_short *)0x1f8010f4) = 0;
UpdateRandom();
FrameCnt++;
if (test_switch_flag)
{
//msa run_diagnostics();
//msa init_audio( gameVolume ); //until the diagnostics causes a volume change
TaskWait(1);
test_switch_flag = 0;
}
// FrameCnt &= 0xffffff;
/* Read controller button status */
GetInput();
// FntPrint(font_id[activeBuff], "%d %d %d %d\n",
// coins[0], coins[1], coins[2], coins[3]);
// FntPrint(font_id[activeBuff], "%d %d %d %d\n",
// credits[0], credits[1], credits[2], credits[3]);
start_game_flag = 0;
if (free_play_mode)
{
// Check to see if someone has started the game at any time
// If someone has 1 credit and they push the
// simulated start button, then assign them a period purchased
// and start up the game.
// TODO: Make it so overtime can be paid for.
for (i=0;i<4;i++)
{
if ((LEController[i] & CONTROLLER_START)
&& period_available_p(i))
{
if (!periods[0] && !periods[1] &&
!periods[2] && !periods[3] &&
!player_mode)
startTotalGameTimer();
if (!periods[i])
{
// player being added in so stop
stopPlayerGameTimer(); // current player timer and restart
// setNovRam(); // new one with new number of players
periods[i]++; //get new period setting for the next function
startPlayerGameTimer();
periods[i]--; // return to old periods so it can be incremented below
}
incrementTotalPlays();
periods[i]++;
fullGameBonus(i);
if (freeGameWindow && !winningTeam[i])
freeGameFlag = 1;
if (freeGameFlag && winningTeam[i])
if (!OneQuarterTournamentMode)
{
for(j = periods[i]; j < 4; j++)
incrementTotalPlays();
periods[i] = freeGameBonus;
}
else
{
for(j = periods[i]; j < 1; j++)
incrementTotalPlays();
periods[i] = 1;
}
checkForValidCpuOpponent();
start_game_flag = 1;
}
}
}
else // NOT FREE PLAY MODE
{
/* msa
start_game_flag = 0;
if (coin_dropped_flag)
{
//msa make_coin_accept_sound();
start_game_flag = 1;
coin_dropped_flag = 0;
}
for (i=0; i<4; i++)
{
if ((LEController[i] & CONTROLLER_START)
&& period_available_p(i)
&& ((credits[GlobalCoinCounters?0:i]
>= ((((player_mode>>i)&1) || periods[i])
?CreditsToContinue:CreditsToStart)) ||
(!freeGameWindow && freeGameFlag && winningTeam[i]) ||
((((player_mode>>i)&1) || periods[i]) && OverTimeFlag && OverTimeFree) ))
{
if (!((LEController[i] & CONTROLLER_START)
&& (freeGameFlag && !freeGameWindow && winningTeam[i])) &&
!((((player_mode>>i)&1) || periods[i]) && OverTimeFlag && OverTimeFree) )
{
credits[GlobalCoinCounters?0:i] -=
((((player_mode>>i)&1) || periods[i])
?CreditsToContinue:CreditsToStart);
CreditsCounter[i] += ((((player_mode>>i)&1) || periods[i])
?CreditsToContinue:CreditsToStart);
}
if (!periods[0] && !periods[1] &&
!periods[2] && !periods[3] &&
!player_mode)
startTotalGameTimer();
if (!periods[i])
{
// player being added in so stop
stopPlayerGameTimer(); // current player timer and restart
// setNovRam(); // new one with new number of players
periods[i]++; //get new period setting for the next function
startPlayerGameTimer();
periods[i]--; // return to old periods so it can be incremented below
}
incrementTotalPlays();
periods[i]++;
fullGameBonus(i);
if (freeGameWindow && !winningTeam[i])
freeGameFlag = 1;
if (freeGameFlag && winningTeam[i])
if (!OneQuarterTournamentMode)
{
for(j = periods[i]; j < 4; j++)
incrementTotalPlays();
periods[i] = freeGameBonus;
}
else
{
for(j = periods[i]; j < 1; j++)
incrementTotalPlays();
periods[i] = 1;
}
checkForValidCpuOpponent();
start_game_flag = 1;
}
}
*/ //msa
}
// Dispatch to the function representing the current mode that
// we are running in:
game_state_functions[RealGameState]();