mirror of
https://github.com/thug1src/thug.git
synced 2025-01-22 05:43:47 +00:00
798 lines
20 KiB
C
798 lines
20 KiB
C
#include <stdio.h>
|
|
#include <sys/file.h>
|
|
#include <kernel.h>
|
|
#include <string.h>
|
|
#include <libsd.h>
|
|
#include <libcdvd.h>
|
|
#include "bgm_i.h"
|
|
|
|
#define DEBUGGING_PLEASE 0
|
|
#if DEBUGGING_PLEASE
|
|
#define Dbg_Printf(A...) printf(##A)
|
|
#else
|
|
#define Dbg_Printf(A...)
|
|
#endif
|
|
|
|
// wav format ------------------------
|
|
#define RIFF_HEADER_SIZE 44
|
|
typedef struct {
|
|
unsigned char chunkID[4];
|
|
unsigned int chunkSize;
|
|
unsigned short* data;
|
|
} DATAHeader;
|
|
|
|
typedef struct {
|
|
unsigned char chunkID[4];
|
|
unsigned int chunkSize;
|
|
unsigned short waveFmtType;
|
|
unsigned short channel;
|
|
unsigned int samplesPerSec;
|
|
unsigned int bytesPerSec;
|
|
unsigned short blockSize;
|
|
unsigned short bitsPerSample;
|
|
} FMTHeader;
|
|
|
|
typedef struct {
|
|
unsigned char chunkID[4];
|
|
unsigned int chunkSize;
|
|
unsigned char formType[4];
|
|
FMTHeader fmtHdr;
|
|
DATAHeader dataHdr;
|
|
} RIFFHeader;
|
|
//------------------------------------
|
|
|
|
typedef struct {
|
|
unsigned int size;
|
|
// unsigned int offset;
|
|
unsigned int pos;
|
|
} BGM_WAVE;
|
|
|
|
|
|
BGM_WAVE gWave[2];
|
|
|
|
int gMemInitializedForCD = 0;
|
|
short gBgmPause[2] = { 0, 0 };
|
|
short gBgmPreload[ 2 ] = { 0, 0 };
|
|
char gFileFromCD[ 2 ] = { 0, 0 };
|
|
char gBgmVolumeSet[2] = { 0, 0 };
|
|
volatile char gFileOpened[2] = { 0, 0 };
|
|
volatile char gBgmIntr[2] = { 0, 0 };
|
|
int gThid = 0;
|
|
int gSem = 0;
|
|
int gFd[2];
|
|
int gBuffRaw[2];
|
|
int gBuffSpu[2] = {0, 0};
|
|
int gRPacketSize[2];
|
|
int gSPacketSize[2];
|
|
int gAllockedSize[2];
|
|
int gBgmVolume[2];
|
|
int gBgmMode[2] = { BGM_MODE_REPEAT_OFF, BGM_MODE_REPEAT_OFF };
|
|
int gBgmStereoMode[ 2 ] = { 0, 0 };
|
|
|
|
#define MAX_FILENAME_LENGTH 50
|
|
char gFilename[ 2 ][ MAX_FILENAME_LENGTH ];
|
|
|
|
// Larger buffers will prevent skipping when loading in the background...
|
|
// The more streams, the larger the buffers have to be.
|
|
// Reading from the CDVD will be faster than debug stations from the host over the network,
|
|
// so don't freak if you notice corruption on a dev system w/o CD.
|
|
#define SECTOR_SIZE 2048
|
|
#define NUM_SECTORS_PER_READ 2
|
|
#define BUFFER_SIZE_FOR_HOST_FILE ( 2048 * 132 ) // multiple of 6
|
|
#define BUFFER_SIZE_FOR_CD_FILE ( SECTOR_SIZE * NUM_SECTORS_PER_READ * 6 )
|
|
|
|
#define RING_BUFFER_NUM_SECTORS 48
|
|
#define RING_BUFFER_ALLIGNMENT 64
|
|
#define RING_BUFFER_NUM_PARTITIONS 3
|
|
unsigned char gRingBuffer[ 2 ][ RING_BUFFER_NUM_SECTORS * 2048 ] __attribute__((aligned ( RING_BUFFER_ALLIGNMENT )));
|
|
unsigned char gCDBuffSpu[ 2 ][ BUFFER_SIZE_FOR_CD_FILE ]__attribute__((aligned ( 64 )));
|
|
|
|
int _BgmPlay( int status );
|
|
void _BgmRaw2Spu(u_long *src, u_long *dst, u_long block_count );
|
|
void _BgmRaw2SpuMono(u_long *src, u_long *dst, u_long block_count );
|
|
int BgmPreLoad( int ch, int status );
|
|
void SetStereoOn( int ch, int stereo );
|
|
|
|
static int IntFunc0( void* common )
|
|
{
|
|
gBgmIntr[0] = 1;
|
|
iSignalSema( gSem );
|
|
return 1; //-- Required for re-enabling interrupts
|
|
}
|
|
|
|
static int IntFunc1( void* common )
|
|
{
|
|
gBgmIntr[1] = 1;
|
|
iSignalSema( gSem );
|
|
return 1; //-- Required for re-enabling interrupts
|
|
}
|
|
|
|
|
|
static int makeMyThread( void )
|
|
{
|
|
struct ThreadParam param;
|
|
int thid;
|
|
|
|
param.attr = TH_C;
|
|
param.entry = _BgmPlay;
|
|
param.initPriority = BASE_priority-3;
|
|
param.stackSize = 0x800;
|
|
param.option = 0;
|
|
|
|
/* Create thread */
|
|
thid = CreateThread(¶m);
|
|
|
|
return thid;
|
|
}
|
|
|
|
static int makeMySem( void )
|
|
{
|
|
struct SemaParam sem;
|
|
|
|
sem.initCount = 0;
|
|
sem.maxCount = 1;
|
|
sem.attr = AT_THFIFO;
|
|
|
|
/* Create semaphore. */
|
|
return CreateSema(&sem);
|
|
}
|
|
|
|
|
|
int BgmRaw2Spu( int ch, int which )
|
|
{
|
|
if ( gBgmStereoMode[ ch ] )
|
|
{
|
|
_BgmRaw2Spu( (u_long *)(gBuffRaw[ch]+ (gRPacketSize[ch])*which)
|
|
, (u_long *)(gBuffSpu[ch] + (gSPacketSize[ch])*which)
|
|
, gSPacketSize[ch]/1024 );
|
|
}
|
|
else
|
|
{
|
|
_BgmRaw2SpuMono ((u_long *)(gBuffRaw [ch] + (gRPacketSize [ch]) * which),
|
|
(u_long *)(gBuffSpu [ch] + (gSPacketSize [ch]) * which),
|
|
gSPacketSize [ch] / 1024);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// returns zero if no longer playing...
|
|
int BgmSetVolumeDirect( int ch, unsigned int vol )
|
|
{
|
|
sceSdSetParam( (ch)|SD_P_BVOLR, vol>>16 );
|
|
sceSdSetParam( (ch)|SD_P_BVOLL, vol&0xFFFF);
|
|
return ( gBgmMode[ch] & ~BGM_MASK_STATUS );
|
|
}
|
|
|
|
|
|
|
|
void BgmSdInit(int ch, int status )
|
|
{
|
|
// This is already called from the soundFX module.
|
|
//sceSdInit(0);
|
|
return;
|
|
}
|
|
|
|
|
|
int BgmInit( int ch, int useCD )
|
|
{
|
|
|
|
if( gSem == 0 ){
|
|
gSem = makeMySem();
|
|
}
|
|
if( gThid == 0 ){
|
|
gThid = makeMyThread();
|
|
Dbg_Printf("PCM Audio Streamer: create thread ID= %d, ", gThid );
|
|
/* Activate thread */
|
|
StartThread( gThid, (u_long)NULL );
|
|
}
|
|
|
|
if ( !gBuffSpu[ ch ] )
|
|
{
|
|
gAllockedSize[ch] = useCD ? BUFFER_SIZE_FOR_CD_FILE : BUFFER_SIZE_FOR_HOST_FILE;
|
|
if ( useCD )
|
|
{
|
|
gBuffSpu[ ch ] = ( int )gCDBuffSpu[ ch ]; //(int)AllocSysMemory( 0, gAllockedSize[ ch ], NULL );
|
|
}
|
|
else
|
|
{
|
|
gBuffSpu[ ch ] = ( int )AllocSysMemory( 0, gAllockedSize[ ch ], NULL );
|
|
}
|
|
Dbg_Printf(" PCM spu buffer mem: 0x%x - 0x%x\n", gBuffSpu[ch], gBuffSpu[ch]+gAllockedSize[ ch ] );
|
|
}
|
|
// the memory should work for mono or stereo 44k files ( raw buffer always the same... )
|
|
gRPacketSize[ ch ] = gAllockedSize[ ch ] / 6;
|
|
gBuffRaw[ ch ] = ( int )( gBuffSpu[ ch ] + ( gRPacketSize[ ch ] * 4 ) );
|
|
gMemInitializedForCD = useCD;
|
|
|
|
return gThid;
|
|
}
|
|
|
|
void BgmQuit(int ch, int status )
|
|
{
|
|
if ( ( gBuffSpu[ ch ] ) && ( gBuffSpu[ ch ] != ( int ) gCDBuffSpu ) )
|
|
FreeSysMemory( (void*)gBuffSpu[ch] );
|
|
gBuffSpu[ch] = 0;
|
|
//-- Frees resources unless another channel is used.
|
|
if( gBuffSpu[1-ch] == 0 ){
|
|
if (gThid != 0) TerminateThread( gThid );
|
|
if (gSem != 0) DeleteSema( gSem );
|
|
if (gThid != 0) DeleteThread( gThid );
|
|
gThid = 0;
|
|
gSem = 0;
|
|
}
|
|
return;
|
|
}
|
|
|
|
/*
|
|
void WaitForCDReady( char *description )
|
|
{
|
|
printf( "wait %s", description );
|
|
while( SCECdComplete != sceCdDiskReady( 1 ) )
|
|
{
|
|
printf( "." );
|
|
}
|
|
printf( "\n" );
|
|
}*/
|
|
|
|
#define NUM_BYTES_TO_CLEAR 512 // must be divisible by 4!!!
|
|
|
|
int BgmOpen( int data, char* filename )
|
|
{
|
|
// unsigned int channel;
|
|
RIFFHeader wavHdr;
|
|
int offset;
|
|
int *addr;
|
|
int i;
|
|
int ch = data & 1;
|
|
int stereo = data & WAV_STEREO_BIT;
|
|
|
|
SetStereoOn( ch, stereo );
|
|
|
|
for ( i = 0; i < 2; i++ )
|
|
{
|
|
if ( gFileOpened[ i ] )
|
|
{
|
|
printf( "%s: Failed: Audio stream already running: %s\n", filename, gFilename[ i ] );
|
|
// Dbg_Printf( "File already opened on that channel...\n" );
|
|
return -1;
|
|
}
|
|
}
|
|
printf("pcm filename %s\n", filename );
|
|
|
|
if ( !strncmp( filename, "host", 4 ) )
|
|
{
|
|
if ( gMemInitializedForCD )
|
|
{
|
|
printf( "Loading file from host when mem configured for CD... SOUND QUALITY WILL SUCK.\n" );
|
|
printf( "If calling ezBGM_INIT with useCD (2nd param), send CDROM0 in filename...\n" );
|
|
}
|
|
|
|
// load the file from the dev system...
|
|
if (( gFd[ch] = open ( filename, O_RDONLY)) < 0)
|
|
{
|
|
ERROR(("file open failed. %s \n", filename));
|
|
return -1;
|
|
}
|
|
|
|
if ( read (gFd[ch], (unsigned char*)(&wavHdr)
|
|
,RIFF_HEADER_SIZE ) != RIFF_HEADER_SIZE ) {
|
|
ERROR(("file read failed. %s \n", filename));
|
|
return -1;
|
|
}
|
|
if ( wavHdr.fmtHdr.channel == 2 )
|
|
{
|
|
if ( !stereo )
|
|
printf( "WARNING: Playing stereo sound %s in mono mode.\n", filename );
|
|
}
|
|
else if ( stereo )
|
|
{
|
|
printf( "WARNING: Playing mono sound %s in stereo mode.\n", filename );
|
|
}
|
|
|
|
gWave[ch].size = wavHdr.dataHdr.chunkSize;
|
|
gWave[ch].pos = 0;
|
|
|
|
//--- Seek to start of data
|
|
offset = (unsigned int)&(wavHdr.dataHdr.data) -(unsigned int)&wavHdr;
|
|
|
|
lseek( gFd[ ch ], offset , SEEK_SET );
|
|
|
|
gFileFromCD[ ch ] = 0;
|
|
gFileOpened[ ch ] = 1;
|
|
gBgmPreload[ ch ] = 3;
|
|
}
|
|
else
|
|
{
|
|
sceCdlFILE fp;
|
|
sceCdRMode mode;
|
|
int retVal;
|
|
unsigned int stringLength;
|
|
unsigned int lsn;
|
|
int foundCDData = 0;
|
|
int byteIndex;
|
|
// open a stream and load from CD...
|
|
// 1st arg: size in num sectors ( actual size / 2048 ).
|
|
// WaitForCDReady( "st init" );
|
|
// sceCdDiskReady( 0 );
|
|
sceCdStInit( RING_BUFFER_NUM_SECTORS, RING_BUFFER_NUM_PARTITIONS, ( u_int )( gRingBuffer[ ch ] ) ); //+ ( RING_BUFFER_ALLIGNMENT - 1 ) ) );
|
|
// printf( "wait for ready." );
|
|
// sceCdDiskReady( 0 );
|
|
// WaitForCDReady( "init" );
|
|
// printf( "cdSearchFile\n" );
|
|
stringLength = strlen( filename );
|
|
if ( filename[ stringLength + 1 ] == '@' )
|
|
{
|
|
foundCDData = 1;
|
|
lsn = 0;
|
|
for ( byteIndex = 0; byteIndex < 4; byteIndex++ )
|
|
{
|
|
lsn |= ( ( ( unsigned int )( filename[ stringLength + 2 + byteIndex ] ) ) & 255 ) << ( 8 * byteIndex );
|
|
}
|
|
}
|
|
if ( !foundCDData )
|
|
{
|
|
if ( !( retVal = sceCdSearchFile( &fp, filename ) ) )
|
|
{
|
|
ERROR(("cd filesearch failed %d. file %s \n", retVal, filename));
|
|
return -1;
|
|
}
|
|
lsn = fp.lsn;
|
|
}
|
|
|
|
// WaitForCDReady( "find" );
|
|
// sceCdDiskReady( 0 );
|
|
mode.trycount = 0;
|
|
mode.spindlctrl = SCECdSpinNom;
|
|
mode.datapattern = SCECdSecS2048;
|
|
sceCdStStart( lsn, &mode );
|
|
gFileFromCD[ ch ] = 1;
|
|
gBgmPreload[ ch ] = 3;
|
|
gFileOpened[ ch ] = 1;
|
|
gWave[ ch ].pos = 0;
|
|
gWave[ ch ].size = gRPacketSize[ ch ] * 4;
|
|
}
|
|
|
|
// printf("wave size %d offset %d\n", gWave[ch].size, gWave[ch].offset );
|
|
|
|
BgmSetVolumeDirect( ch, 0 );
|
|
|
|
strncpy( gFilename[ ch ], filename, MAX_FILENAME_LENGTH );
|
|
|
|
// clear out the end of the second half of the last buffer...
|
|
addr = ( int * )( gBuffRaw[ ch ] + ( gRPacketSize[ ch ] ) + ( gRPacketSize[ ch ] >> 1 ) );
|
|
for ( i = 0; i < ( ( gRPacketSize[ ch ] >> 1 ) >> 2 ); i++ )
|
|
{
|
|
*( addr++ ) = 0;
|
|
}
|
|
|
|
if( ch == 0 )
|
|
{
|
|
sceSdSetTransCallback( ch, IntFunc0 );
|
|
}
|
|
else
|
|
{
|
|
sceSdSetTransCallback( ch, IntFunc1 );
|
|
}
|
|
|
|
return ( gWave[ ch ].size );
|
|
}
|
|
|
|
void _BgmClose(int ch, int status)
|
|
{
|
|
if ( !gFileOpened[ ch ] )
|
|
{
|
|
PRINTF(("Calling BgmClose when no file opened on that channel...\n"));
|
|
return;
|
|
}
|
|
Dbg_Printf( "_BgmClose\n" );
|
|
if ( gFileFromCD[ ch ] )
|
|
{
|
|
sceCdStStop( );
|
|
}
|
|
else
|
|
{
|
|
close( gFd[ch] );
|
|
//FreeSysMemory( ( void* )gBuffSpu[ ch ] );
|
|
//gBuffSpu[ ch ] = 0;
|
|
}
|
|
gFileOpened[ ch ] = 0;
|
|
return;
|
|
}
|
|
|
|
void BgmStart(int ch, int status )
|
|
{
|
|
int retVal;
|
|
if ( !gFileOpened[ ch ] )
|
|
{
|
|
printf( "trying to start track not loaded.\n" );
|
|
return;
|
|
}
|
|
Dbg_Printf( "starting block trans from bgm start/unpause\n" );
|
|
if ( gBgmPause[ ch ] )
|
|
{
|
|
Dbg_Printf( "Starting music on channel where pause is requested...\n" );
|
|
gBgmPause[ ch ] = 0;
|
|
}
|
|
while( -1 == sceSdBlockTrans( ch, SD_TRANS_MODE_WRITE|SD_BLOCK_LOOP, (u_char*)gBuffSpu[ch], (gSPacketSize[ch]*2) ) )
|
|
{
|
|
for ( retVal = 0; retVal < 10000; retVal++ )
|
|
;
|
|
Dbg_Printf( "failed to start loop.\n" );
|
|
}
|
|
if ( !( gBgmPreload[ ch ] ) )
|
|
{
|
|
BgmSetVolumeDirect(ch, gBgmVolume[ch]);
|
|
}
|
|
gBgmMode[ch] &= BGM_MASK_STATUS;
|
|
gBgmMode[ch] |= BGM_MODE_RUNNING;
|
|
|
|
return;
|
|
}
|
|
|
|
void BgmCloseNoWait( int ch, int status )
|
|
{
|
|
if ( !gFileOpened[ ch ] )
|
|
{
|
|
PRINTF(("Calling BgmClose when no file opened on that channel...\n"));
|
|
return;
|
|
}
|
|
if ( gBgmPause[ ch ] )
|
|
{
|
|
printf( "stopping music when pause is requested..." );
|
|
return;
|
|
}
|
|
// if the pause has already stopped the callback, it's safe to unload now:
|
|
if ( gBgmMode[ ch ] & BGM_MODE_PAUSE )
|
|
{
|
|
// callback isn't happening right now... can terminate with no worries here:
|
|
Dbg_Printf( "unpausing from BgmClose\n" );
|
|
gBgmMode[ch] &= BGM_MASK_STATUS; // Switch to IDLE mode
|
|
_BgmClose( ch, status );
|
|
Dbg_Printf( "calling _BgmClose from BgmClose\n" );
|
|
return;
|
|
}
|
|
gBgmMode[ch] &= BGM_MASK_STATUS;
|
|
gBgmMode[ch] |= BGM_MODE_TERMINATE;
|
|
}
|
|
|
|
void BgmClose( int ch, int status )
|
|
{
|
|
int i;
|
|
BgmCloseNoWait( ch, status );
|
|
printf( "PCM close" );
|
|
while ( ( gBgmMode[ ch ] & BGM_MODE_TERMINATE ) )
|
|
{
|
|
for ( i = 0; i < 20000; i++ )
|
|
;
|
|
printf( "." );
|
|
}
|
|
printf( "\n" );
|
|
}
|
|
|
|
int BgmPreLoad( int ch, int status )
|
|
{
|
|
if ( ( status == 666 ) || ( ( gWave[ ch ].size - gWave[ ch ].pos ) < gRPacketSize[ ch ] * 4 ) )
|
|
{
|
|
int i;
|
|
int *addr;
|
|
Dbg_Printf( "preloading at end of song. zero buffers.\n" );
|
|
// we're at the end of the song... fill up read buffers with zero,
|
|
// and convert...
|
|
addr = ( int * )( gBuffRaw[ ch ] );
|
|
for ( i = 0; i < ( ( gRPacketSize[ ch ] * 2 ) >> 2 ); i++ )
|
|
{
|
|
*( addr++ ) = 0;
|
|
}
|
|
// fill up the spu with both buffers...
|
|
BgmRaw2Spu( ch, 0 );
|
|
BgmRaw2Spu( ch, 1 );
|
|
return ( 0 );
|
|
}
|
|
|
|
// it's still in preload mode... no need to preload ourselves...
|
|
if ( gBgmPreload[ ch ] == 3 )
|
|
return ( 0 );
|
|
|
|
if ( gFileFromCD[ ch ] )
|
|
{
|
|
unsigned int err;
|
|
sceCdStRead( NUM_SECTORS_PER_READ * 2, ( u_int * )gBuffRaw[ ch ], STMBLK, &err );
|
|
if ( err )
|
|
{
|
|
printf( "PCM A Disk error code 0x%08x\n", err );
|
|
}
|
|
|
|
// fill up the spu with both buffers...
|
|
BgmRaw2Spu( ch, 0 );
|
|
BgmRaw2Spu( ch, 1 );
|
|
|
|
// fill up the buffers again...
|
|
sceCdStRead( NUM_SECTORS_PER_READ * 2, ( u_int * )gBuffRaw[ ch ], STMBLK, &err );
|
|
if ( err )
|
|
{
|
|
printf( "PCM B Disk error code 0x%08x\n", err );
|
|
}
|
|
|
|
gWave[ ch ].pos += gRPacketSize[ ch ] * 2;
|
|
return 0;
|
|
}
|
|
// reading from a file...
|
|
if ( read (gFd[ch], (unsigned char*)(gBuffRaw[ch])
|
|
, gRPacketSize[ch]*2 ) != gRPacketSize[ch]*2 ) {
|
|
ERROR (("BgmPreLoad: read failed \n")); return -1;
|
|
}
|
|
|
|
BgmRaw2Spu( ch, 0 );
|
|
BgmRaw2Spu( ch, 1 );
|
|
|
|
if ( read (gFd[ch], (unsigned char*)(gBuffRaw[ch])
|
|
, (gRPacketSize[ch]*2) ) != gRPacketSize[ch]*2) {
|
|
ERROR (("BgmPreLoad: read failed \n")); return -1;
|
|
}
|
|
|
|
gWave[ch].pos += gRPacketSize[ch]*4;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void _BgmPause(int ch, int status)
|
|
{
|
|
Dbg_Printf( "stopping spu block trans in _BgmPause\n" );
|
|
sceSdBlockTrans( ch, SD_TRANS_MODE_STOP, NULL, 0 );
|
|
gBgmMode[ch] &= BGM_MASK_STATUS; // Switch to PAUSE mode
|
|
gBgmMode[ch] |= BGM_MODE_PAUSE;
|
|
return;
|
|
}
|
|
|
|
void _BgmStopAndUnload(int ch, int status)
|
|
{
|
|
Dbg_Printf( "stopping block trans from _BgmStopAndUnload\n" );
|
|
sceSdBlockTrans( ch, SD_TRANS_MODE_STOP, NULL, 0 );
|
|
gBgmMode[ch] &= BGM_MASK_STATUS; // Switch to IDLE mode
|
|
Dbg_Printf( "bgm close from _BgmStopAndUnload\n" );
|
|
_BgmClose( ch, status );
|
|
return;
|
|
}
|
|
|
|
// should be fucking called "BgmPause"
|
|
void BgmStop( int ch, unsigned int vol )
|
|
{
|
|
int i;
|
|
|
|
if ( gBgmMode[ ch ] & BGM_MODE_TERMINATE )
|
|
{
|
|
Dbg_Printf( "trying to pause PCM when stopped.\n" );
|
|
return;
|
|
}
|
|
if ( !gBgmMode[ ch ] & BGM_MODE_RUNNING )
|
|
{
|
|
Dbg_Printf( "trying to pause PCM when not running.\n" );
|
|
return;
|
|
}
|
|
gBgmPause[ch] = 1;
|
|
printf( "waiting for pause" );
|
|
while ( !( gBgmMode[ ch ] & BGM_MODE_PAUSE ) )
|
|
{
|
|
for ( i = 0; i < 10000; i++ )
|
|
;
|
|
printf( "." );
|
|
}
|
|
printf( "\n" );
|
|
// don't set the flag until the callback has paused it:
|
|
// gBgmMode[ch] &= BGM_MASK_STATUS;
|
|
// gBgmMode[ch] |= BGM_MODE_PAUSE;
|
|
return;
|
|
}
|
|
|
|
|
|
int BgmSetVolume( int ch, unsigned int vol )
|
|
{
|
|
gBgmVolumeSet[ch] = 1;
|
|
gBgmVolume[ch] = vol;
|
|
return ( gBgmMode[ch] & ~BGM_MASK_STATUS );
|
|
}
|
|
|
|
|
|
unsigned int BgmGetMode( int ch, int status )
|
|
{
|
|
return gBgmMode[ch];
|
|
}
|
|
|
|
void BgmSeek( int ch, unsigned int value )
|
|
{
|
|
// lseek(gFd[ch], gWave[ch].offset+value, SEEK_SET );
|
|
// gWave[ch].pos = value;
|
|
printf( "seek not supported\n" );
|
|
return;
|
|
}
|
|
|
|
void SetStereoOn( int ch, int stereo )
|
|
{
|
|
if ( stereo )
|
|
{
|
|
gSPacketSize[ ch ] = gAllockedSize[ ch ] / 6;
|
|
gBgmStereoMode[ ch ] = 1;
|
|
}
|
|
else
|
|
{
|
|
gSPacketSize[ ch ] = gAllockedSize [ ch ] / 3;
|
|
gBgmStereoMode[ ch ] = 0;
|
|
}
|
|
}
|
|
|
|
void PreloadFile( int which, int ch )
|
|
{
|
|
switch ( gBgmPreload[ ch ] )
|
|
{
|
|
case ( 3 ):
|
|
if ( gFileFromCD[ ch ] )
|
|
{
|
|
RIFFHeader *pWavHdr;
|
|
int i;
|
|
int offset;
|
|
unsigned char *pData;
|
|
pWavHdr = ( RIFFHeader * )( gBuffRaw[ ch ]+gRPacketSize[ch]*which );
|
|
if ( pWavHdr->dataHdr.chunkSize < gWave[ ch ].size )
|
|
{
|
|
printf( "BIG WARNING: Cd audio file currently playing is TOO SMALL!\n" );
|
|
}
|
|
if ( pWavHdr->fmtHdr.channel == 2 )
|
|
{
|
|
if ( !gBgmStereoMode[ ch ] )
|
|
printf( "WARNING: Playing stereo sound %s in mono mode.\n", gFilename[ ch ] );
|
|
}
|
|
else if ( gBgmStereoMode[ ch ] )
|
|
{
|
|
printf( "WARNING: Playing mono sound %s in stereo mode.\n", gFilename[ ch ] );
|
|
}
|
|
|
|
SetStereoOn( ch, pWavHdr->fmtHdr.channel == 2 );
|
|
gWave[ch].size = pWavHdr->dataHdr.chunkSize;
|
|
//gWave[ch].offset = (unsigned int)&( pWavHdr->dataHdr.data ) - ( unsigned int )pWavHdr;
|
|
offset = (unsigned int)&( pWavHdr->dataHdr.data ) - ( unsigned int )pWavHdr;
|
|
// clear out the area where the header is... don't want some loud obnoxious sounds...
|
|
pData = ( unsigned char * )( gBuffRaw[ ch ]+gRPacketSize[ch]*which );
|
|
if ( offset > gRPacketSize[ ch ] )
|
|
offset = gRPacketSize[ ch ]; // don't fuck up memory if some strange read happened...
|
|
for ( i = 0; i < offset; i++ )
|
|
{
|
|
pData[ i ] = 0;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case ( 2 ):
|
|
break;
|
|
|
|
case ( 1 ):
|
|
// turn the volume back up, the spooler is at the beginning of
|
|
// the good SPU buffer...
|
|
BgmSetVolume( ch, gBgmVolume[ch] );
|
|
break;
|
|
|
|
default:
|
|
printf( "unknown preload state... fire Matt.\n" );
|
|
break;
|
|
}
|
|
--gBgmPreload[ ch ];
|
|
}
|
|
|
|
int _BgmPlay( int status )
|
|
{
|
|
int i, ch, read_size, which;
|
|
int *addr, remain;
|
|
Dbg_Printf( "entering _BgmPlay\n" );
|
|
while ( 1 )
|
|
{
|
|
//-- Wait for playing of buffer to finish
|
|
WaitSema(gSem);
|
|
|
|
//-- Which channel is the interrupt from?
|
|
if( (gBgmIntr[0] == 1) && ( ch != 0 ) ) ch = 0;
|
|
else if( (gBgmIntr[1] == 1) && ( ch != 1 ) ) ch = 1;
|
|
else if( gBgmIntr[0] == 1 ) ch = 0;
|
|
else if( gBgmIntr[1] == 1 ) ch = 1;
|
|
else continue;
|
|
|
|
gBgmIntr[ch] = 0;
|
|
|
|
which = 1 - (sceSdBlockTransStatus( ch, 0 )>>24);
|
|
|
|
//--- Stopped due to end of data (no looping)
|
|
if( ( gBgmMode[ ch ] & BGM_MODE_TERMINATE ) != 0 )
|
|
{
|
|
WaitSema( gSem ); // Wait until another interrupt is received
|
|
_BgmStopAndUnload( ch, 0 );
|
|
BgmSetVolumeDirect( ch, 0x0 );
|
|
continue;
|
|
}
|
|
|
|
//--- Volume change event
|
|
if ( ( gBgmVolumeSet[ ch ] == 1 ) && ( !gBgmPreload[ ch ] ) )
|
|
{
|
|
BgmSetVolumeDirect( ch, gBgmVolume[ch] );
|
|
gBgmVolumeSet[ch] = 0;
|
|
}
|
|
|
|
//--- Convert buffer
|
|
|
|
BgmRaw2Spu( ch, which );
|
|
|
|
//--- File READ for buffer
|
|
|
|
remain = gWave[ ch ].size - gWave[ ch ].pos;
|
|
if ( remain > gRPacketSize[ch] )
|
|
{
|
|
if ( gFileFromCD[ ch ] )
|
|
{
|
|
//--- Not end of data
|
|
unsigned int err;
|
|
sceCdStRead( NUM_SECTORS_PER_READ, ( u_int * )( gBuffRaw[ ch ]+gRPacketSize[ch]*which ), STMBLK, &err );
|
|
if ( err )
|
|
{
|
|
printf( "PCM C Disk error code 0x%08x\n", err );
|
|
}
|
|
read_size = gRPacketSize[ ch ];
|
|
}
|
|
else
|
|
{
|
|
read_size = read (gFd[ch], (unsigned char*)(gBuffRaw[ch]+gRPacketSize[ch]*which), gRPacketSize[ch] );
|
|
}
|
|
if ( read_size < gRPacketSize[ch] )
|
|
continue; //retry
|
|
if ( gBgmPreload[ ch ] )
|
|
{
|
|
PreloadFile( which, ch );
|
|
}
|
|
gWave[ch].pos += read_size;
|
|
}
|
|
else //--- End of data
|
|
{
|
|
if ( gFileFromCD[ ch ] )
|
|
{
|
|
//--- Not end of data
|
|
unsigned int err;
|
|
sceCdStRead( NUM_SECTORS_PER_READ, ( u_int * )( gBuffRaw[ ch ]+gRPacketSize[ch]*which ), STMBLK, &err );
|
|
if ( err )
|
|
{
|
|
printf( "PCM C Disk error code 0x%08x\n", err );
|
|
}
|
|
read_size = gRPacketSize[ ch ];
|
|
}
|
|
else
|
|
{
|
|
read_size = read (gFd[ch], (unsigned char*)(gBuffRaw[ch]+gRPacketSize[ch]*which), remain );
|
|
}
|
|
|
|
if( read_size < remain ) continue; //retry
|
|
|
|
PRINTF(("end of PCM track - ch %d\n", ch));
|
|
|
|
addr = ( int * )( gBuffRaw[ ch ] + ( gRPacketSize[ ch ] * which ) + remain );
|
|
for( i = 0; i < ((gRPacketSize[ch]-remain)>>2); i++ )
|
|
{
|
|
*(addr++) = 0;
|
|
}
|
|
gBgmMode[ch] &= BGM_MASK_STATUS;
|
|
gBgmMode[ch] |= BGM_MODE_TERMINATE;
|
|
}
|
|
|
|
//-- Stop event
|
|
if( (gBgmPause[ch] == 1) )
|
|
{
|
|
//printf( "_BgmPlay :: pause\n" );
|
|
_BgmPause( ch, 0 );
|
|
BgmSetVolumeDirect(ch, 0x0);
|
|
gBgmPause[ch] = 0;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------
|
|
* End on File
|
|
* ---------------------------------------------------------------- */
|
|
/* This file ends here, DON'T ADD STUFF AFTER THIS */
|
|
|
|
// Ha ha I added some stuff... FUCK YOU SONY!
|