Please consider supporting The Cutting Room Floor on Patreon. Thanks for all your support!

Arcade Party Pak

From The Cutting Room Floor
Jump to: navigation, search

Title Screen

Arcade Party Pak

Developer: Digital Eclipse
Publisher: Midway Games
Platform: PlayStation
Released in US: September 30, 1999
Released in EU: February 23, 2001


CopyrightIcon.png This game has hidden developer credits.
GraphicsIcon.png This game has unused graphics.


Hidden Developer Credit

Present at 0x6DDDD in SMASH.EXE is a hidden credit for the port of Smash T.V..

PORTED TO PLAYSTATION BY PULSAR INTERACTIVE, 1999, JOHN HARRIS, CHRIS IDEN, DAVID MACE
(Source: Ferrox)

Unused Graphics

OpenIcePS1-placeholder1.pngOpenIcePS1-placeholder2.png

Present in all four of the CDPAD.DAT files are a couple of placeholder graphics.


(Source: Ferrox)

Source Code

The files MEDA.PCK & MEDR.PCK contain game source code.

#include <sys/types.h>
#include <libetc.h>
#include <libgte.h>
#include <libgpu.h>
#include <libsn.h>

#include <sys/types.h>
#include <libetc.h>
#include <libgte.h>
#include <libgpu.h>
#include <libcd.h>
#include <libspu.h>
#include <r3000.h>
#include <asm.h>
#include <kernel.h>
#include <libsn.h>

#include "xaapi.h"

#define VERBOSE

// the prototype
extern int CDFile_CdSearchFile(CdlFILE *file_info, char *filename);

void xaStop( void );



#define Min2Milli( a,b,c ) (((a)*60000) + ((b)*1000 ) + ((c)*10 ))
#define CDSpeed (1)
#define Milli2Sectors(a) (((a) * 75 <<(CDSpeed-1) ) / 1000 )
 
typedef struct XaPackFile{
	int	startSector;
	char * fileName;
}XaPackFile;

 
typedef struct XaTrack{
	int	startSector;
	int numSectors;
	int	channel;
	int	packIndex;
}XaTrack;


XaPackFile XaPacks[] = {
	{0,"BIG.PCK;1"},
	{0,"MEDBIG.PCK;1"},
	{0,"MED.PCK;1"},
	{0,"MEDS.PCK;1"},
	{0,"SMALL.PCK;1"},
	{0,0}
};
XaTrack XaTracks[]={
	//small
	{0,Milli2Sectors(Min2Milli(  0,11, 6 )),1,5}, 	//32WIN5
	{0,Milli2Sectors(Min2Milli(  0,12, 6 )),0,5}, 	//09VICMSC
	//medium small
	{0,Milli2Sectors(Min2Milli(  0,16, 9 )),7,4}, 	//28WHEEL
	{0,Milli2Sectors(Min2Milli(  0,24,54 )),6,4}, 	//720track10
	{0,Milli2Sectors(Min2Milli(  0,29,65 )),5,4}, 	//720track12
	{0,Milli2Sectors(Min2Milli(  0,30,17 )),4,4}, 	//2CWIN2
	{0,Milli2Sectors(Min2Milli(  0,30,17 )),3,4}, 	//12WIN7
	{0,Milli2Sectors(Min2Milli(  0,30,17 )),2,4}, 	//14WIN8
	{0,Milli2Sectors(Min2Milli(  0,30,17 )),1,4}, 	//2AWIN1
	{0,Milli2Sectors(Min2Milli(  0,30,17 )),0,4}, 	//16ADDA
	// medium
	{0,Milli2Sectors(Min2Milli(  0,30,17 )),7,3}, 	//2EWIN3
	{0,Milli2Sectors(Min2Milli(  0,30,17 )),6,3}, 	//30WIN4
	{0,Milli2Sectors(Min2Milli(  0,30,68 )),5,3}, 	//720track13
	{0,Milli2Sectors(Min2Milli(  0,30,68 )),4,3}, 	//720track8
	{0,Milli2Sectors(Min2Milli(  0,30,17 )),3,3}, 	//34WIN6
	{0,Milli2Sectors(Min2Milli(  0,34,77 )),2,3}, 	//720track7
	{0,Milli2Sectors(Min2Milli(  0,36,81 )),1,3}, 	//720track3
	{0,Milli2Sectors(Min2Milli(  0,41,92 )),0,3}, 	//720track1
	//medium big
	{0,Milli2Sectors(Min2Milli(  0,42,95 )),7,2}, 	//720track5
	{0,Milli2Sectors(Min2Milli(  0,45, 2 )),6,2}, 	//720track2
	{0,Milli2Sectors(Min2Milli(  0,48, 8 )),5,2}, 	//720track9
	{0,Milli2Sectors(Min2Milli(  0,48, 8 )),4,2}, 	//720track11
	{0,Milli2Sectors(Min2Milli(  0,59,33 )),3,2}, 	//720track6
	{0,Milli2Sectors(Min2Milli(  1, 8,54 )),2,2}, 	//720track14
	{0,Milli2Sectors(Min2Milli(  1,12,40 )),1,2}, 	//05TUNE3
	{0,Milli2Sectors(Min2Milli(  1,28,49 )),0,2}, 	//0FHIMUSC
	//big
	{0,Milli2Sectors(Min2Milli(  1,30, 4 )),7,1}, 	//720track4
	{0,Milli2Sectors(Min2Milli(  1,41,57 )),6,1}, 	//01TUNE2
	{0,Milli2Sectors(Min2Milli(  1,57,66 )),5,1}, 	//0ETUNE4
	{0,Milli2Sectors(Min2Milli(  1,58,66 )),4,1}, 	//B2BONS1
	{0,Milli2Sectors(Min2Milli(  2, 0,68 )),3,1}, 	//02ENDT
	{0,Milli2Sectors(Min2Milli(  2, 1,68)), 2,1}, 	//03TUNE1
	{0,Milli2Sectors(Min2Milli(  2, 3,69 )),1,1}, 	//0ABTUNE3
	{0,Milli2Sectors(Min2Milli(  2, 5,70 )),0,1}, 	//04BTUNE1
	{0,0,0,0},
};


  
CdlFILTER	filter;
static 	CdlLOC pos;
static 	CdlLOC posinfo;
static 	CdlLOC pause_pos;
static 	char	  pad[16];
static 	CdlATV cdMute;
static 	unsigned int cur_pos;

static 	unsigned char result[8];
static 	unsigned char param[8];
static 	unsigned int error = 0;
static 	unsigned int good = 0;

static 	CdlATV cdVol;
static 	unsigned int Volume;

static unsigned int StartSector = 0;
static unsigned int EndSector = 0;
static unsigned int LastCommand = 0;
static unsigned int Command = 0;

#define IDLE		(0)
#define PLAY    	(1)
#define STARTING    (2)
#define NEWCOMMAND  (3)
#define ERRORCHECK  (4)

static 	unsigned int IsPaused= 0;
static 	unsigned int State= IDLE;
static 	unsigned int PausedState= IDLE;
static	unsigned int PreviousState= IDLE;

#ifdef VERBOSE
static int profile;
static int min=1000;
static int max=0;
#endif

XA_SYSTEM *xaSystem;

XA_SYSTEM xaSystemShell; 	// the lovely struct for them to see us 


// set cd mix on in spu common attr
void SetMix( void ) 
{
    SpuCommonAttr c_attr;

    /* Initialise sound */

    c_attr.mask = SPU_COMMON_CDMIX | SPU_COMMON_CDVOLL| SPU_COMMON_CDVOLR ;

    c_attr.cd.mix  = SPU_ON; 	/* cd mixing  */
    c_attr.cd.volume.left = c_attr.cd.volume.right  = 0x1fff; 	/* cd mixing volume */

    SpuSetCommonAttr(&c_attr);

}

// set cdVol struct from global volume value
void MixVol( void )
{
	*(u_long *)&cdVol = 0x00000000;
	Volume = Volume & 0xff;
	cdVol.val0 = cdVol.val3 = Volume;
	cdVol.val1 = cdVol.val2 = Volume;
}


// start song 
static void xastart( unsigned long command)
{
	#ifdef VERBOSE
	printf (" start %d", command );
	#endif
	LastCommand = command;

	filter.file = 1;
	filter.chan = XaTracks[command].channel;

	StartSector = XaTracks[command].startSector;
	EndSector = StartSector + ( XaTracks[command].numSectors) ;

   	CdControlB(CdlSetfilter, (u_char *)&filter, 0) ;

	State = STARTING;
} 

void Ready ( u_char intr, u_char *result )
{
	if (intr == CdlDiskError ) error++;
	if (intr == CdlDataReady )
	{
		CdGetSector(( int *) &posinfo,2);
		cur_pos = CdPosToInt(&posinfo);
		good++;
	}
}

int xaService( void )
{
	int RcntIn;
	#ifdef VERBOSE
	pollhost();
	#endif

	if( IsPaused ) return;
	if( State == IDLE ) return;
	SetMix();		//should not need this
	#ifdef VERBOSE
	RcntIn = profile = VSync(1);
	#endif

	switch( State){
		case NEWCOMMAND:
			CdReadyCallback ( 0 );
			xastart( Command );
			cur_pos = 0;
			break;
		case STARTING:
			SetMix();		//should not need this!
			CdIntToPos( StartSector , &pos);
		  	CdControlF(CdlReadS, (u_char *)&pos);
			CdReadyCallback ( Ready );
			MixVol();
			State = ERRORCHECK;
			break;
		case ERRORCHECK:
			CdSync( 1, result );
			if ( result[0] == CdlNoIntr ) 
			{
				break;
			}
			if ( result[0] == CdlComplete )
			{
				State = PLAY;
			}	
			if ( result[0] == CdlDiskError ) 
			{
				State = STARTING;
			}
			break;

		case PLAY:
		/* check for end of xa track */			
	  	if( cur_pos > EndSector )
		{
			#ifdef VERBOSE
			printf( " END ");
			#endif
			xaStop();
	  	}
		else
		{
			CdMix( &cdVol);
		}
		break;
	}

	#ifdef VERBOSE
	profile = VSync(1) - profile;
	if( profile > max ) max = profile;
	if( profile < min ) min = profile;
	#endif

	return 1; //success
	
}

void xaInit( void )
{
	CdInit();
	SetMix();
	Volume = 0xff;						//full on
	*(u_long *)&cdVol = 0xffffffff;		// full on
	*(u_long *)&cdMute = 0;				// init mute 
	CdMix( &cdMute);					//start out muted
	param[0] = 	 CdlModeRT | CdlModeSF | CdlModeSize1;	  //1x ,ADPCM, filter
	if ( CDSpeed == 2 ){
		param[0] |= 	 CdlModeSpeed;	  //2x	- never happen
	}
  	while (CdControlB(CdlSetmode, param, 0) == 0);		//set cd system in xa streaming mode..

	filter.file = 1;									  //file 1 channel 0
	filter.chan = 0;
  	while (CdControlB(CdlSetfilter, (u_char *)&filter, 0) == 0);// just in case

   	CdIntToPos( XaTracks[0].startSector , &pos);
  	while (CdControlB(CdlSeekL, (u_char *)&pos, 0) == 0);		// seek towards xa data - might help first seek

	CdSync(0,0);		//blocking sync - wait until seek is completed

  	CdControlB(CdlPause,  (u_char *)&pos, 0);		// pause at the xa data area
	
	State= IDLE;
	printf( ( "xa init" ));
	CdReadyCallback ( 0 );							// no callback becasue no xa playing

}
void xaPlay( unsigned long command )
{
	#ifdef VERBOSE
	printf("command %d ",command  );
	#endif
	Command = command;			//twisted shit
	State = NEWCOMMAND;
}


void xaStop( void )
{
	if( State == IDLE ) return;		// can't stop if not playing

	#ifdef VERBOSE
	printf("STOP !!! ");
	#endif
  	CdControlB(CdlPause, 0, 0);

	CdMix( &cdMute);
	State = IDLE;
}
void xaSetVolume( unsigned char volume )
{
	#ifdef VERBOSE
	printf ( "xaSetVolume %d ",volume );
	#endif
	Volume = volume;
	MixVol();

}


//never ever used!
unsigned char xaGetStatus( void )
{
	return State == PLAY;
}

// just use this stuff because it wroks!
void xaPause( void )
{
	if( IsPaused ) return;
	if( State == IDLE ) return;
	CdSync(0,0);

	CdMix( &cdMute);
	IsPaused = 1;
	PausedState= State;

	CdReadyCallback ( 0 );

	do
	{
		CdControl(CdlNop, 0,result);
	}while( result[0] == CdlStatSeek );
  	CdControlB(CdlGetlocL, 0, (u_char *)&pause_pos);
	CdSync(0,0);

  	CdControlB(CdlSeekL,  (u_char *)&pause_pos, 0);
	CdSync(0,0);

  	CdControlB(CdlPause,  (u_char *)&pause_pos, 0);
	CdSync(0,0);
}

void xaResume( void )
{
	if( !IsPaused ) return;
	if( State == IDLE ) return;
	
	IsPaused= 0;

	CdSync(0,0);
  	CdControl(CdlReadS, (u_char *)&pause_pos, 0);
	CdMix( &cdVol);
	State = PausedState;
	CdReadyCallback ( Ready );
}

int XaHandler( void )
{	
	switch( xaSystem->xaSystemRequest )
	{
		case XA_INIT:
			xaInit();
			break;
		case XA_PLAY:
			xaPlay( xaSystem->xaCommandData );
			break;
		case XA_STOP:
			xaStop();
			break;
		case XA_SET_VOLUME:
			xaSetVolume( xaSystem->xaCommandData );
			break;
		case XA_PAUSE:
			xaPause();
			break;
		case XA_RESUME:
			xaResume();
			break;

		case XA_GETSTATUS:
			xaSystem->xaCommandData = xaGetStatus();
			break;

		default:
			// whats up with this - no error checking?
	}
	return 1;		//success!
}
void CacheXADirectory( void ){
 	CdlFILE thisFile;
 	CdlLOC		thisLocation;
	unsigned int thisSector;
	int i=0;

	// get the start sector for each pscked xa file
	while( XaPacks[i].fileName ){

		CDFile_CdSearchFile( &thisFile, XaPacks[i].fileName);
		thisLocation = thisFile.pos;
		thisSector = CdPosToInt( &thisLocation );
		XaPacks[i].startSector = thisSector;
		i++;
	}

	i = 0;
	// patch the start sector into each track 
	// note: packIndex is offset by one to ease null termination
	// note: add channel offset to packed files starsector to get xa data start sector 
	while( XaTracks[i].packIndex ){
		XaTracks[i].startSector = XaPacks[XaTracks[i].packIndex-1].startSector + XaTracks[i].channel ;
		i++;
	}
}


/*sample usage
	XA_CALL->xaSystemRequest = XA_INIT;
	XA_CALL->xaCommandHandler();
	XA_CALL->xaSystemRequest = XA_PLAY;
	XA_CALL->xaCommandData = XA_01TUNE2;
	XA_CALL->xaCommandHandler();

also need a regular call to:
	XA_CALL->xaVsyncService();



*/
void XaSystemPreInit( void )
{
	// cache all the file starts in each xa entry
	CacheXADirectory();

	// set the interface peep-hole to point to the shells xa system struct
	*((unsigned int * )XA_SYSTEM_POINTER) = (unsigned int)&xaSystemShell;
	xaSystem = (XA_SYSTEM*)*((unsigned int * )XA_SYSTEM_POINTER);

	// set the struct entries:
	// function dispathcher
 	xaSystem->xaCommandHandler = &XaHandler;
	// regular service
	xaSystem->xaVsyncService = &xaService;
	// function type
	xaSystem->xaSystemRequest = XA_NULL;
	// function data
 	xaSystem->xaCommandData = 0;
}


// temporary shit to test one xa track
void TestTheXaCrap( void ){

	int i,j;

	xaSystem->xaSystemRequest = XA_INIT;
	xaSystem->xaCommandHandler();


	i = 0;
	// patch the start sector into each track 
	// note: packIndex is offset by one to ease null termination
	// note: add channel offset to packed files starsector to get xa data start sector 
	while( XaTracks[i].packIndex ){

		xaSystem->xaSystemRequest = XA_PLAY;
		xaSystem->xaCommandData = (enumXAs)i;
		xaSystem->xaCommandHandler();


		do{
			VSync(0);
			xaSystem->xaVsyncService();

			xaSystem->xaSystemRequest = XA_GETSTATUS;
			xaSystem->xaCommandHandler();

		}while( xaSystem->xaCommandData );
		i++;
		for ( j = 0;j<180 ;j++) VSync(0);	// wait one second between songs
	}
}