thug/Code/Sys/File/XBox/p_pre.cpp

1158 lines
27 KiB
C++
Raw Normal View History

2016-02-13 21:39:12 +00:00
/*****************************************************************************
** **
** Neversoft Entertainment. **
** **
** Copyright (C) 2000 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: skate3 **
** **
** Module: Xbox specific PRE module **
** **
** File name: p_pre.cpp **
** **
** Created by: dc **
** **
** Description: **
** **
*****************************************************************************/
/*****************************************************************************
** Includes **
*****************************************************************************/
#include <core/defines.h>
#include <core/HashTable.h>
#include <core/StringHashTable.h>
#include <sys/File/PRE.h>
#include <sys/file/filesys.h>
#include <sys/config/config.h>
#include <gel/music/music.h>
// script stuff
#include <gel/scripting/struct.h>
#include <gel/scripting/symboltable.h>
/*****************************************************************************
** DBG Information **
*****************************************************************************/
#define DEBUG_PRE 0
namespace File
{
/*****************************************************************************
** Externals **
*****************************************************************************/
/*****************************************************************************
** Defines **
*****************************************************************************/
#define CURRENT_PRE_VERSION 0xabcd0002 // as of 3/14/2001
//#define CURRENT_PRE_VERSION 0xabcd0001 // until 3/14/2001
#define RINGBUFFERSIZE 4096 /* N size of ring buffer */
#define MATCHLIMIT 18 /* F upper limit for match_length */
#define THRESHOLD 2 /* encode string into position and length */
#define WriteOut(x) {*pOut++ = x;}
/*****************************************************************************
** Private Types **
*****************************************************************************/
/*****************************************************************************
** Private Data **
*****************************************************************************/
PreMgr *PreMgr::sp_mgr = NULL;
bool PreMgr::s_lastExecuteSuccess = false;
/*****************************************************************************
** Public Data **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Private Functions **
*****************************************************************************/
#define USE_BUFFER 1 // we don't need no stinking buffer!!!!
#if USE_BUFFER
unsigned char text_buf[RINGBUFFERSIZE + MATCHLIMIT - 1];
#endif
#define ReadInto(x) if (!Len) break; Len--; x = *pIn++
#define ReadInto2(x) Len--; x = *pIn++ // version that knows Len is Ok
// Decode an LZSS encoded stream
// Runs at approx 12MB/s on PS2 without scratchpad (which slows it down in C)
// a 32x CD would run at 4.8MB/sec, although we seem to get a lot less than this
// with our current file system, more like 600K per seconds.....
// Need to write a fast streaming file system....
void DecodeLZSS( unsigned char *pIn, unsigned char *pOut, int Len ) /* Just the reverse of Encode(). */
{
int i, j, k, r, c;
// uint64 LongWord;
// int bytes = 0;
// unsigned char *pScratch;
unsigned int flags;
// int basetime = (int) Tmr::ElapsedTime(0);
// int len = Len;
// int OutBytes = 4;
// int OutWord = 0;
# if USE_BUFFER
for (i = 0; i < RINGBUFFERSIZE - MATCHLIMIT; i++)
text_buf[i] = ' ';
r = RINGBUFFERSIZE - MATCHLIMIT;
# else
r = RINGBUFFERSIZE - MATCHLIMIT;
# endif
flags = 0;
for ( ; ; )
{
if (((flags >>= 1) & 256) == 0)
{
ReadInto(c);
flags = c | 0xff00; /* uses higher byte cleverly */
} /* to count eight */
if (flags & 1)
{
ReadInto(c);
// putc(c, outfile);
WriteOut(c);
#if USE_BUFFER
text_buf[r++] = c;
r &= (RINGBUFFERSIZE - 1);
#else
r++;
// r &= (RINGBUFFERSIZE - 1); // don't need to wrap r until it is used
#endif
}
else
{
ReadInto(i);
ReadInto2(j); // note, don't need to check len on this one....
i |= ((j & 0xf0) << 4); // i is 12 bit offset
#if !USE_BUFFER
j = (j & 0x0f) + THRESHOLD+1; // j is 4 bit length (above the threshold)
unsigned char *pStream;
r &= (RINGBUFFERSIZE - 1); // wrap r around before it is used
pStream = pOut - r; // get base of block
if (i>=r) // if offset > r, then
pStream -= RINGBUFFERSIZE; // it's the previous block
pStream += i; // add in the offset to the base
r+=j; // add size to r
while (j--) // copy j bytes
WriteOut(*pStream++);
#else
j = (j & 0x0f) + THRESHOLD; // j is 4 bit length (above the threshold)
for (k = 0; k <= j; k++) // just copy the bytes
{
c = text_buf[(i+k) & (RINGBUFFERSIZE - 1)];
WriteOut(c);
text_buf[r++] = c;
r &= (RINGBUFFERSIZE - 1);
}
#endif
}
}
// int Time = (int) Tmr::ElapsedTime(basetime);
// if (Time > 5)
// {
// printf("decomp time is %d ms, for %d bytes, %d bytes/second\n", Time,len, len * 1000 /Time );
// }
}
void PreFile::s_delete_file(_File *pFile, void *pData)
{
Dbg_Assert(pFile);
delete pFile;
}
PreFile::PreFile(uint8 *p_file_buffer)
{
mp_table = new Lst::StringHashTable<_File>(4);
Dbg_AssertPtr(p_file_buffer);
mp_buffer = p_file_buffer;
uint version = *((int *) (mp_buffer + 4));
Dbg_MsgAssert(version == CURRENT_PRE_VERSION,( "PRE file version not current"));
m_numEntries = *((int *)(mp_buffer + 8));
uint8 *pEntry = mp_buffer + 12;
for (int i = 0; i < m_numEntries; i++)
{
int data_size = *((int *) pEntry);
int compressed_data_size = *((int *) (pEntry + 4));
int text_size = *((int *) (pEntry + 8));
int actual_data_size = (compressed_data_size != 0) ? compressed_data_size : data_size;
char *pName = (char *) pEntry + 12;
uint8 *pCompressedData = pEntry + 12 + text_size;
_File *pFile = new (Mem::Manager::sHandle().TopDownHeap()) _File;
if (!mp_table->GetItem(pName))
{
// file is not in table, safe to add
mp_table->PutItem(pName, pFile);
pFile->compressedDataSize = compressed_data_size;
pFile->pCompressedData = pCompressedData;
pFile->pData = NULL;
pFile->sky.POS = 0;
pFile->sky.SOF = data_size;
}
else
// Somehow, file is already in table, just kill it
// Later, I'll want to add an assert
delete pFile;
# if DEBUG_PRE
printf(" %s, size %d\n", pName, data_size);
# endif
pEntry += 12 + text_size + ((actual_data_size + 3) & (~3));
}
# if DEBUG_PRE
printf("Done loading PRE\n");
# endif
mp_activeFile = NULL;
}
PreFile::~PreFile()
{
delete mp_buffer;
mp_table->HandleCallback(s_delete_file, NULL);
mp_table->FlushAllItems();
delete mp_table;
}
bool PreFile::FileExists(const char *pName)
{
_File *pFile = mp_table->GetItem(pName, false);
return (pFile != NULL);
}
// returns handle pointer
void *PreFile::GetContainedFile(const char *pName)
{
_File *pFile = mp_table->GetItem(pName, false);
if (!pFile)
return NULL;
dumbSkyFile *pHandle = &pFile->sky;
// kinda roundabout, but sets mp_activeFile
GetContainedFileByHandle(pHandle);
// do we need to fetch file data?
if (!mp_activeFile->pData)
{
if (mp_activeFile->compressedDataSize)
{
mp_activeFile->pData = new (Mem::Manager::sHandle().TopDownHeap()) uint8[mp_activeFile->sky.SOF];
// need to uncompress data
DecodeLZSS(mp_activeFile->pCompressedData, mp_activeFile->pData, mp_activeFile->compressedDataSize);
}
}
return pHandle;
}
uint8 *PreFile::GetContainedFileByHandle(void *pHandle)
{
mp_table->IterateStart();
_File *pFile = mp_table->IterateNext();
while(pFile)
{
uint8 *pCompressedData = pFile->pCompressedData;
if (pCompressedData && &pFile->sky == pHandle)
{
mp_activeFile = pFile;
if (mp_activeFile->compressedDataSize)
return mp_activeFile->pData;
else
return mp_activeFile->pCompressedData;
}
pFile = mp_table->IterateNext();
}
return NULL;
}
// allocate memory and load file directly from a pre file, if it is there
// This avoids the problem of having to have the decompressed file in memory twice
// when we are loading directly, like with Pip::Load()
// using this enables us to actually load network game, where there is 1MB less heap during loading
//
// returns a pointer to the file in memory
// or NULL if the file is not in this pre file.
void *PreFile::LoadContainedFile( const char *pName, int *p_size, void *p_dest )
{
// The dest parameter is used only on Ps2.
Dbg_Assert( p_dest == NULL );
_File *pFile = mp_table->GetItem( pName, false );
if( !pFile )
{
return NULL;
}
*p_size = pFile->sky.SOF;
p_dest = Mem::Malloc( pFile->sky.SOF );
// Do we need to decompress file data?
if( !pFile->pData )
{
if( pFile->compressedDataSize )
{
// Need to uncompress data.
DecodeLZSS( pFile->pCompressedData, (uint8*)p_dest, pFile->compressedDataSize );
}
else
{
memcpy( p_dest, (void*)pFile->pCompressedData, pFile->sky.SOF );
}
}
else
{
memcpy( p_dest, (void*)pFile->pData, pFile->sky.SOF );
}
return p_dest;
}
void PreFile::Reset()
{
Dbg_AssertPtr(mp_activeFile);
mp_activeFile->sky.POS = 0;
}
uint32 PreFile::Read( void *addr, uint32 count )
{
Dbg_AssertPtr( mp_activeFile );
int seek_offs = mp_activeFile->sky.POS;
unsigned int limit = mp_activeFile->sky.SOF - seek_offs;
int copy_number = (count <= limit) ? count : limit;
if (mp_activeFile->compressedDataSize)
{
Dbg_MsgAssert(mp_activeFile->pData,( "file not uncompressed"));
memcpy( addr, mp_activeFile->pData + mp_activeFile->sky.POS, copy_number );
}
else
{
memcpy(addr, mp_activeFile->pCompressedData + mp_activeFile->sky.POS, copy_number);
}
mp_activeFile->sky.POS += copy_number;
# if DEBUG_PRE
printf("PRE: read %d bytes from file, handle 0x%x\n", copy_number, (int) mp_activeFile->pData);
# endif
return copy_number;
}
int PreFile::Eof()
{
Dbg_AssertPtr(mp_activeFile);
if (mp_activeFile->sky.POS >= mp_activeFile->sky.SOF)
{
#if DEBUG_PRE
printf("PRE: at end of file\n");
#endif
return 1;
}
#if DEBUG_PRE
printf("PRE: not at end of file\n");
#endif
return 0;
}
void PreFile::Close()
{
//Dbg_MsgAssert(mp_activeFile->pData,( "file not uncompressed"));
if (mp_activeFile->pData)
delete mp_activeFile->pData;
mp_activeFile->pData = NULL;
}
int PreFile::Seek(long offset, int origin)
{
int32 old_pos = mp_activeFile->sky.POS;
// SEEK_CUR, SEEK_END, SEEK_SET
switch(origin)
{
case SEEK_CUR:
mp_activeFile->sky.POS += offset;
break;
case SEEK_END:
mp_activeFile->sky.POS = mp_activeFile->sky.SOF - offset;
break;
case SEEK_SET:
mp_activeFile->sky.POS = offset;
break;
default:
return -1;
}
if (mp_activeFile->sky.POS < 0 || mp_activeFile->sky.POS > mp_activeFile->sky.SOF)
{
mp_activeFile->sky.POS = old_pos;
return -1;
}
return 0;
}
PreMgr::PreMgr()
{
mp_table = new Lst::StringHashTable<PreFile>(4);
sp_mgr = this;
mp_activeHandle = NULL;
mp_activeData = NULL;
mp_activeNonPreHandle = NULL;
}
PreMgr::~PreMgr()
{
delete mp_table;
}
// Returns handle
// Not frequently called
void *PreMgr::getContainedFile(const char *pName)
{
Dbg_AssertPtr(pName);
// replace all '/' with '\'
char cleaned_name[128];
const char *pCharIn = pName;
char *pCharOut = cleaned_name;
while (1)
{
*pCharOut = *pCharIn;
if (*pCharIn == '\0') break;
if (*pCharOut == '/') *pCharOut = '\\';
pCharIn++;
pCharOut++;
}
void *pHandle = NULL;
mp_table->IterateStart();
PreFile *pPre = mp_table->IterateNext();
while(pPre)
{
pHandle = pPre->GetContainedFile(cleaned_name);
if (pHandle)
{
mp_activePre = pPre;
mp_activeHandle = pHandle;
mp_activeData = pPre->GetContainedFileByHandle(pHandle);
# ifdef __PLAT_NGPS__
// scePrintf("+++ %s is in PRE\n", cleaned_name);
# endif
return pHandle;
}
pPre = mp_table->IterateNext();
}
# ifdef __PLAT_NGPS__
// scePrintf("--- %s not found in PRE\n", cleaned_name);
# endif
return NULL;
}
// returns true if the file exists in any of the pre files
bool PreMgr::fileExists(const char *pName)
{
Dbg_AssertPtr(pName);
// replace all '/' with '\'
char cleaned_name[128];
const char *pCharIn = pName;
char *pCharOut = cleaned_name;
while (1)
{
*pCharOut = *pCharIn;
if (*pCharIn == '\0') break;
if (*pCharOut == '/') *pCharOut = '\\';
pCharIn++;
pCharOut++;
}
mp_table->IterateStart();
PreFile *pPre = mp_table->IterateNext();
while(pPre)
{
if (pPre->FileExists(cleaned_name))
{
return true;
}
pPre = mp_table->IterateNext();
}
return false;
}
// returns pointer to data
uint8 *PreMgr::getContainedFileByHandle(void *pHandle)
{
Dbg_AssertPtr(pHandle);
// if we know that the file in question is not in the PRE system,
// then it's a regular file, don't waste time looking for it
if (mp_activeNonPreHandle == pHandle)
return NULL;
if (mp_activeHandle == pHandle)
// mp_activePre will be unchanged
return mp_activeData;
uint8 *pData = NULL;
mp_table->IterateStart();
PreFile *pPre = mp_table->IterateNext();
while(pPre)
{
pData = pPre->GetContainedFileByHandle(pHandle);
if (pData)
{
mp_activePre = pPre;
mp_activeHandle = pHandle;
mp_activeData = pData;
return pData;
}
pPre = mp_table->IterateNext();
}
// obviously this file is not in the PRE system, mark as such
mp_activeNonPreHandle = pHandle;
return NULL;
}
// there's a wrapper around this now, so that we can do
// some memory-context switching
void PreMgr::loadPre(const char *pFilename, bool dont_assert)
{
m_blockPreLoading = (bool) Script::GetInt("block_pre_loading", false);
if (m_blockPreLoading)
return;
if( Pcm::UsingCD() )
{
Dbg_MsgAssert( 0,( "File access forbidden while PCM audio is in progress." ));
return;
}
// Moved this to below the Pcm::UsingCD() call as that is used (bad!!) to turn off
// music and streams.
# ifdef __PLAT_NGC__
OSReport ( "Warning: Attempting to load pre file: %s (ignored)\n", pFilename );
return;
# endif // __PLAT_NGC__
# ifdef __PLAT_NGPS__
// scePrintf("Loading PRE file %s...\n", pFilename);
# endif
char fullname[256];
sprintf(fullname, "pre\\%s", pFilename);
// Replace the .pre extension with .prx for Xbox PRE file.
fullname[strlen( fullname ) - 1] = 'x';
// Create a lower-case version.
char lower[128];
for( unsigned int lp = 0; lp < strlen( fullname ) + 1; lp++ ) lower[lp] = tolower( fullname[lp] );
Tmr::Time basetime = Tmr::ElapsedTime(0);
int file_size;
uint8 *pFile = NULL;
file_size = CanFileBeLoadedQuickly( fullname );
if ( file_size )
{
pFile = new (Mem::Manager::sHandle().TopDownHeap()) uint8[file_size];
bool fileLoaded= LoadFileQuicklyPlease( fullname, pFile );
if ( !fileLoaded )
{
printf( "pre file %s failed to load quickly.\n", fullname );
Dbg_MsgAssert( 0,( "Fire Matt - pre file didn't load quickly." ));
}
}
else
{
#ifdef __PLAT_NGC__
NsFile file;
if ( file.exist( fullname ) )
{
file.open( fullname );
#else
void *fp = File::Open(fullname, "rb");
if (!fp)
{
#endif // __PLAT_NGC__
// always run the code below if CD build
if (dont_assert || Config::CD())
{
printf("couldn't open %s\n", fullname);
return;
}
Dbg_MsgAssert(0,( "couldn't open %s\n", fullname));
}
#ifdef __PLAT_NGC__
file.read( &file_size, 4 );
file_size = nLtEn32(file_size);
#else
File::Read(&file_size, 4, 1, fp);
Dbg_MsgAssert(file_size > 0,( "%s has incorrect file size\n", fullname));
#endif // __PLAT_NGC__
if (Config::CD())
{
if (file_size <= 0) printf("%s has incorrect file size\n", fullname);
}
// Now allocates the .PRE file from the top of the heap, to avoid fragmentation.
pFile = new (Mem::Manager::sHandle().TopDownHeap()) uint8[file_size];
//uint8 *pFile = new uint8[file_size];
#ifdef __PLAT_NGC__
file.read( pFile + 4, file_size );
file.close();
#else
File::Read(pFile + 4, 1, file_size, fp);
File::Close(fp);
#endif // __PLAT_NGC__
}
printf("load time for file size %d is %d ms\n", file_size, (int) Tmr::ElapsedTime(basetime));
// the PRE file object winds up at the top of the heap, too. This is fine because
// it will be unloaded at the same time as the big file buffer
if (!mp_table->PutItem(pFilename, new (Mem::Manager::sHandle().TopDownHeap()) PreFile(pFile)))
Dbg_MsgAssert(0,( "PRE %s loaded twice", pFilename));
}
/*****************************************************************************
** Public Functions **
*****************************************************************************/
DefineSingletonClass(PreMgr, "PRE Manager");
bool PreMgr::InPre(const char *pFilename)
{
return mp_table->GetItem( pFilename );
}
void PreMgr::LoadPre( const char *pFilename, bool dont_assert )
{
// GJ: This function is a wrapper around loadPRE(), to
// make sure that all allocations go on the top-down heap
Mem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());
loadPre(pFilename, dont_assert);
Mem::Manager::sHandle().PopContext();
}
void PreMgr::LoadPrePermanently(const char *pFilename, bool dont_assert)
{
// GJ: This function is a wrapper around LoadPRE(),
// used for loading PRE files which will reside in memory
// permanently. Essentially, we need to make sure that the
// data is above Renderware's resource arena. If you didn't
// use this function, you'd get fragmentation when the resource
// arena resized itself.
// Mick: Removed reference to renderware, the old "arena" concept is gone
// Load the pre file...
// This will go on the top-down heap by default
LoadPre(pFilename, dont_assert);
}
void PreMgr::UnloadPre(const char *pFilename, bool dont_assert)
{
// scePrintf("Unloading PRE file %s\n", pFilename);
if (m_blockPreLoading)
return;
PreFile *pThePre = mp_table->GetItem(pFilename);
if (!pThePre)
{
if (dont_assert) return;
Dbg_MsgAssert(0,( "PRE file %s not in PRE manager", pFilename));
}
mp_table->FlushItem(pFilename);
delete pThePre;
}
bool PreMgr::sPreEnabled()
{
return sp_mgr != NULL;
}
bool PreMgr::sPreExecuteSuccess()
{
return s_lastExecuteSuccess;
}
# ifndef __PLAT_NGC__
bool PreMgr::pre_fexist(const char *name)
{
Dbg_MsgAssert(name,( "requesting file NULL"));
if( sp_mgr->fileExists( name ))
{
# if DEBUG_PRE
printf("PRE: file %s exists\n", name);
# endif
s_lastExecuteSuccess = true;
return true;
}
if ( Pcm::UsingCD( ) )
{
Dbg_MsgAssert( 0,( "File access forbidden while PCM audio is in progress." ));
return false;
}
return s_lastExecuteSuccess = false;
}
void *PreMgr::pre_fopen(const char *name, const char *access)
{
Dbg_MsgAssert(name,( "trying to open file NULL" ));
char nameConversionBuffer[256];
// Just as we do in the Xbox version of prefopen(), if this is a .tex file, switch to a .txx file.
int length = strlen( name );
strncpy( nameConversionBuffer, name, length + 1 );
if((( nameConversionBuffer[length - 1] ) == 'x' ) &&
(( nameConversionBuffer[length - 2] ) == 'e' ) &&
(( nameConversionBuffer[length - 3] ) == 't' ))
{
nameConversionBuffer[length - 2] = 'x';
}
void *pHandle = sp_mgr->getContainedFile( nameConversionBuffer );
if( pHandle )
{
// if we are going to write the file, we want to use the regular file system
const char *pChar = access;
bool am_writing = false;
while(*pChar)
{
if (*pChar != 'r' && *pChar != 'b')
am_writing = true;
pChar++;
}
if (am_writing)
{
# ifdef __PLAT_NGPS__
// scePrintf(" writing file %s\n", name);
# endif
// am writing, so we don't need file open in PRE system
sp_mgr->mp_activePre->Close();
}
else
{
// we're reading the file from the PRE system
# if DEBUG_PRE
printf("PRE: opened file %s, handle is 0x%x\n", name, (int) pHandle);
# endif
sp_mgr->mp_activePre->Reset();
s_lastExecuteSuccess = true;
return pHandle;
}
}
// if we get here, we are using the regular file system
if( Pcm::UsingCD())
{
Dbg_MsgAssert( 0, ( "File access forbidden while PCM audio is in progress." ));
return NULL;
}
s_lastExecuteSuccess = false;
return NULL;
//return pHandle;
}
int PreMgr::pre_fclose(void *fptr)
{
Dbg_MsgAssert(fptr,( "calling fclose with invalid file ptr"));
uint8 *pData = sp_mgr->getContainedFileByHandle(fptr);
if (pData)
{
#if DEBUG_PRE
printf("PRE: closed file, handle 0x%x\n", (int) fptr);
#endif
sp_mgr->mp_activePre->Close();
s_lastExecuteSuccess = true;
return 0;
}
s_lastExecuteSuccess = false;
return 0;
}
size_t PreMgr::pre_fread(void *addr, size_t size, size_t count, void *fptr)
{
Dbg_MsgAssert(fptr,( "calling fread with invalid file ptr"));
uint8 *pData = sp_mgr->getContainedFileByHandle( fptr );
if (pData)
{
// read from a simulated file stream in PRE file
Dbg_AssertPtr(sp_mgr->mp_activePre);
// There is a subtle bug in the PS2 version, in that the pre version of fread()
// returns the number of bytes read, rather than the number of items. This
// version does return the correct value.
size_t bytes_read = sp_mgr->mp_activePre->Read( addr, size * count );
// return bytes_read / size;
return bytes_read;
}
if ( Pcm::UsingCD( ) )
{
Dbg_MsgAssert( 0,( "File access forbidden while PCM audio is in progress." ));
return 0;
}
s_lastExecuteSuccess = false;
return 0;
}
size_t PreMgr::pre_fwrite(const void *addr, size_t size, size_t count, void *fptr)
{
uint8 *pData = sp_mgr->getContainedFileByHandle(fptr);
Dbg_MsgAssert(!pData,( "can't write to a PRE file"));
if ( Pcm::UsingCD( ) )
{
Dbg_MsgAssert( 0,( "File access forbidden while PCM audio is in progress." ));
return 0;
}
s_lastExecuteSuccess = false;
return 0;
}
char *PreMgr::pre_fgets(char *buffer, int maxLen, void *fptr)
{
uint8 *pData = sp_mgr->getContainedFileByHandle(fptr);
Dbg_MsgAssert(!pData,( "can't do string ops on a PRE file"));
s_lastExecuteSuccess = false;
return NULL;
}
int PreMgr::pre_fputs(const char *buffer, void *fptr)
{
uint8 *pData = sp_mgr->getContainedFileByHandle(fptr);
Dbg_MsgAssert(!pData,( "can't do string ops on a PRE file"));
s_lastExecuteSuccess = false;
return 0;
}
int PreMgr::pre_feof(void *fptr)
{
Dbg_MsgAssert(fptr,( "calling feof with invalid file ptr"));
uint8 *pData = sp_mgr->getContainedFileByHandle(fptr);
if (pData)
{
Dbg_AssertPtr(sp_mgr->mp_activePre);
s_lastExecuteSuccess = true;
return sp_mgr->mp_activePre->Eof();
}
s_lastExecuteSuccess = false;
return 0;
}
int PreMgr::pre_fseek(void *fptr, long offset, int origin)
{
uint8 *pData = sp_mgr->getContainedFileByHandle(fptr);
if( pData )
{
s_lastExecuteSuccess = true;
return sp_mgr->mp_activePre->Seek( offset, origin );
}
Dbg_MsgAssert( !pData, ( "seek not supported for PRE file" ));
s_lastExecuteSuccess = false;
return 0;
}
int PreMgr::pre_fflush(void *fptr)
{
uint8 *pData = sp_mgr->getContainedFileByHandle(fptr);
Dbg_MsgAssert(!pData,( "flush not supported for PRE file"));
s_lastExecuteSuccess = false;
return 0;
}
int PreMgr::pre_ftell(void *fptr)
{
uint8 *pData = sp_mgr->getContainedFileByHandle(fptr);
if( pData )
{
return sp_mgr->mp_activePre->TellActive();
}
Dbg_MsgAssert( !pData, ( "tell supported for PRE file" ));
s_lastExecuteSuccess = false;
return 0;
}
# endif // __PLAT_NGC__
// @script | InPreFile |
// @uparm "string" | filename
bool ScriptInPreFile(Script::CStruct *pParams, Script::CScript *pScript)
{
const char *pFilename;
pParams->GetText(NONAME, &pFilename, true);
Spt::SingletonPtr<PreMgr> pre_mgr;
return pre_mgr->InPre(pFilename);
}
// @script | LoadPreFile |
// @uparm "string" | filename
// @flag dont_assert |
bool ScriptLoadPreFile(Script::CStruct *pParams, Script::CScript *pScript)
{
const char *pFilename;
pParams->GetText(NONAME, &pFilename, true);
Spt::SingletonPtr<PreMgr> pre_mgr;
pre_mgr->LoadPre(pFilename, pParams->ContainsFlag("dont_assert"));
return true;
}
// @script | UnloadPreFile |
// @flag BoardsPre |
// @flag dont_assert |
// @uparm "string" | filename
bool ScriptUnloadPreFile(Script::CStruct *pParams, Script::CScript *pScript)
{
Spt::SingletonPtr<PreMgr> pre_mgr;
if (pParams->ContainsFlag("BoardsPre"))
{
// Spt::SingletonPtr< Mdl::Skate > pSkate;
// pSkate->UnloadBoardPreIfPresent(pParams->ContainsFlag("dont_assert"));
printf ("STUBBED: Unload BoardsPre, in ScriptUnloadPreFile\n");
return true;
}
const char *pFilename;
pParams->GetText(NONAME, &pFilename, true);
pre_mgr->UnloadPre(pFilename, pParams->ContainsFlag("dont_assert"));
return true;
}
void *PreMgr::LoadFile( const char *pName, int *p_size, void *p_dest )
{
// The dest parameter is used only on Ps2.
Dbg_Assert( p_dest == NULL );
// NOTE: THIS IS JUST CUT AND PASTE FROM Pre::fileExists
Dbg_AssertPtr( pName );
// Replace all '/' with '\'
char cleaned_name[128];
const char *pCharIn = pName;
char *pCharOut = cleaned_name;
while (1)
{
*pCharOut = *pCharIn;
if (*pCharIn == '\0') break;
if (*pCharOut == '/') *pCharOut = '\\';
pCharIn++;
pCharOut++;
}
mp_table->IterateStart();
PreFile *pPre = mp_table->IterateNext();
while(pPre)
{
void *p_data = pPre->LoadContainedFile(cleaned_name,p_size);
if (p_data)
{
return p_data;
}
pPre = mp_table->IterateNext();
}
return NULL;
}
} // namespace File