the cutting room mirror

Arcade Party Pak

It's a grab bag of arcade games made by Midway.

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#

Present in MEDA.PCK and MEDR.PCK.

#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
    }
}

References#


  1. MobyGames↩︎