Generating a unique 8-character hex name from input binary? - string

in Source multiplayer games, with settings that allow saving sprays, you can automatically save images that other users post in-game just by seeing them. They save with names like this:
18ce2add.vtf
ce77eb5b.vtf
7dbd03ec.vtf
a24cb0d3.vtf
When looking through the SDK code, I found this part which I think is part of the function that creates the names for each image.
https://github.com/ValveSoftware/source-sdk-2013/blob/master/mp/src/game/client/c_te_playerdecal.cpp#L168
IMaterial *CreateTempMaterialForPlayerLogo( int iPlayerIndex, player_info_t *info, char *texname, int nchars )
{
// Doesn't have a logo?
if ( !info->customFiles[0] )
return NULL;
IMaterial *logo = materials->FindMaterial( VarArgs("decals/playerlogo%2.2d", iPlayerIndex), TEXTURE_GROUP_DECAL );
if ( IsErrorMaterial( logo ) )
return NULL;
char logohex[ 16 ];
Q_binarytohex( (byte *)&info->customFiles[0], sizeof( info->customFiles[0] ), logohex, sizeof( logohex ) );
// See if logo has been downloaded.
Q_snprintf( texname, nchars, "temp/%s", logohex );
char fulltexname[ 512 ];
Q_snprintf( fulltexname, sizeof( fulltexname ), "materials/temp/%s.vtf", logohex );
if ( !filesystem->FileExists( fulltexname ) )
{
char custname[ 512 ];
Q_snprintf( custname, sizeof( custname ), "download/user_custom/%c%c/%s.dat", logohex[0], logohex[1], logohex );
// it may have been downloaded but not copied under materials folder
if ( !filesystem->FileExists( custname ) )
return NULL; // not downloaded yet
// copy from download folder to materials/temp folder
// this is done since material system can access only materials/*.vtf files
if ( !engine->CopyLocalFile( custname, fulltexname) )
return NULL;
}
return logo;
}
What I can't figure out is the format the binary is recieved in (array?) exactly why the name is limited to just 8 characters, and how it decides to use the hex to create the filename. If there is any code that does something like this, I'd be happy to see it. I started learning C++ to try and solve this exact problem.

Related

After reboot, on resumption of uncompression, inflate() is reporting Z_DATA_ERROR

Thanks Mark, on resumption, now I get Z_DATA_ERROR
case STORED:
strm->msg = (char *)"invalid stored block lengths"; // got here - Anton
state->mode = BAD;
Just to see I understood your suggestions yesterday:
after inflateInit2()
// go to byte offset
ZSEEK64( , , streamCurrentPos, ZLIB_FILEFUNC_SEEK_SET)
if ( streamBits > 0 )
{
// get that byte
unz64local_getByte( , , &aByte)
// and shift down by the number of bits. This API doing it?
inflatePrime ( , streamBits, 8 - streamBits)
} else { no bits to insert }
inflateSetDictionary ()
And state of uncompression is saved like this:
typedef struct state_of_uncompression
{
ZPOS64_T streamCurrentPos; // from : unzGetCurrentFileZStreamPos64()
int streamBits; // from : stream.data_type & (~0x1C0), after clearing bits 8,7, and 6
Byte dictionary_buf[32768]; // from : inflateGetDictionary()
uInt dictLength; // from : inflateGetDictionary();
uint64_t output_wrt_offset // got this already.
} uncompression_state_info;
What? No.
inflatePrime ( , streamBits, 8 - streamBits) makes no sense. And you did nothing with the aByte you got.
It should be inflatePrime(strm, streamBits, aByte >> (8 - streamBits)).

Gdal:Increase dimensions (Resolution) of image obtained after using createcopy()

I am using visual c++ gdal to read .gis file from my desktop and then output the image of that file (png/jpeg). The code accepts the "input.gis" file and then creates "output.png".
Here is my working code :
GDALDriver *poDriver;
GDALDataset *poDataset;
char **papszMetadata;
double adfGeoTransform[6];
int nBlockXSize, nBlockYSize;
int bGotMin, bGotMax;
double adfMinMax[2];
GDALAllRegister();
poDataset = (GDALDataset *) GDALOpen("C:\\input.gis", GA_ReadOnly );
if( poDataset == NULL )
{
MessageBox::Show("cannot open");
}
else
{
poDataset->GetGeoTransform( adfGeoTransform );
GDALRasterBand *poBand;
poBand = poDataset->GetRasterBand( 1 );
float *pafScanline;
int nXSize = poBand->GetXSize();
poBand->GetBlockSize( &nBlockXSize, &nBlockYSize );
adfMinMax[0] = poBand->GetMinimum( &bGotMin );
adfMinMax[1] = poBand->GetMaximum( &bGotMax );
if( ! (bGotMin && bGotMax) )
GDALComputeRasterMinMax((GDALRasterBandH)poBand, TRUE, adfMinMax);
poDriver = GetGDALDriverManager()->GetDriverByName("PNG");
if( poDriver == NULL )
printf("Cannot create image");
else
{
papszMetadata = poDriver->GetMetadata();
if( CSLFetchBoolean( papszMetadata, GDAL_DCAP_CREATECOPY, FALSE ) )
{
printf( "Driver %s supports CreateCopy() method.\n", "png" );
}
}
GDALDataset *poDstDS;
poDstDS = poDriver->CreateCopy( "C:\\output.png", poDataset, FALSE, NULL, NULL, NULL );
if( poDstDS != NULL )
GDALClose( (GDALDatasetH) poDstDS );
GDALClose( (GDALDatasetH) poDataset );
}
My problem is when I use createcopy() function from gdal the size of image output is always 99 X 99 (which i guess is the default size). How can I increase the size of image to be outputted for example (512 x 512 )?
The dimensions of your output dataset output.png are 99 x 99 because those are also the dimensions of your input dataset input.gis. To create a new dataset with different dimensions you need to use the Create method as described in the GDAL tutorial.
The PNG driver unfortunately does not support this method which leaves you with two options:
Choose a different output format which supports the Create method.
Use the Create method to create a dataset in your memory and then use CreateCopy on it - as suggestested in this GIS.SE post

Strange noise and abnormalities when writing audio data from libspotify into a file

Currently we're implementing Libspotify in a win 7 64 bit system. Everything seems to work fine except the playback. We get data from the callback , but even using audicity on the saved audio, is filled with abnormalities. So to research further we took the win32 sample (spshell ) and modified it to save the music data to file. Same problem, definitely music with these ticks in it. I'm sure there's something simple I'm missing here, but I'm at a loss as to what could be the problem. Any help would be great since as it stands our project is at a stand still until we can resolve this.
The audio saved can be viewed here
http://uploader.crestron.com/download.php?file=8001d80992480280dba365752aeaca81
Below are the code changes I made to save the file ( for testing only )
static FILE *pFile;
int numBytesToWrite=0;
CRITICAL_SECTION m_cs;
int SP_CALLCONV music_delivery(sp_session *s, const sp_audioformat *fmt, const void *frames, int num_frames)
{
if ( num_frames == 0 )
return;
EnterCriticalSection(&m_cs);
numBytesToWrite = ( num_frames ) * fmt->channels * sizeof(short);
if (numBytesToWrite > 0 )
fwrite(frames, sizeof(short), numBytesToWrite, pFile);
LeaveCriticalSection(&m_cs);
return num_frames;
}
static void playtrack_test(void)
{
sp_error err;
InitializeCriticalSection(&m_cs);
pFile = fopen ("C:\\zzzspotify.pcm","wb");
test_start(&playtrack);
if((err = sp_session_player_load(g_session, stream_track)) != SP_ERROR_OK) {
test_report(&playtrack, "Unable to load track: %s", sp_error_message(err));
return;
}
info_report("Streaming '%s' by '%s' this will take a while", sp_track_name(stream_track),
sp_artist_name(sp_track_artist(stream_track, 0)));
sp_session_player_play(g_session, 1);
}
void SP_CALLCONV play_token_lost(sp_session *s)
{
fclose(pFile);
DeleteCriticalSection(&m_cs);
stream_track_end = 2;
notify_main_thread(g_session);
info_report("Playtoken lost");
}
static int check_streaming_done(void)
{
if(stream_track_end == 2)
test_report(&playtrack, "Playtoken lost");
else if(stream_track_end == 1)
test_ok(&playtrack);
else
return 0;
fclose(pFile);
stream_track_end = 0;
return 1;
}
It looks like this is the problem:
fwrite(frames, sizeof(short), numBytesToWrite, pFile);
The fwrite documentation states that the second argument is the "size in bytes of each element to be written", and the third is this "number of elements, each one with a size of size bytes".
The way you're calling frwritewill tell it to write numBytesToWrite * sizeof(short) bytes, which will run right off the end of the given buffer. I'm actually surprised it doesn't crash!
I'd suggest changing your fwrite call to something like:
fwrite(frames, sizeof(char), numBytesToWrite, pFile);
or:
int numSamplesToWrite = num_frames * fmt->channels;
fwrite(frames, sizeof(short), numSamplesToWrite, pFile);
Edit:
After looking at your audio in detail, I'm more convinced that this is the case. The song seems to be playing at half speed (i.e., 2x as much data is being written) and the artefacts seem to look like buffer overrun into random memory.

Read file metadata via Windows Search from MFC program

I would like to read metadata of a DWG/AutoCAD file via Windows Search indexing service. I'm talking about properties that can be accessed with the right click in explorer without opening AutoCAD.
I have an MFC dialog based application written in Visual C++ 2005 and from inside this app I would like to access metadata (such as author, creation date etc.) of the given file. This was done by iFilter but it is deprecated since Windows XP and will be gone in Windows 8 (and LoadIFilter is not present in VS2005). Now from what I understand, it can be done with windows search - correct me if I'm wrong. Every example I found (msdn included) shows how to give data about your own files to windows search for indexing though. What I need is to know how to ask Windows Search about metadata for a given file.
Thanks
t.g.wilk
EDIT:
Here's what I've come up with so far:
BOOL WSQ_DoQuery( const wchar_t *constr, const wchar_t *querystr, VARIANT &result ) {
HRESULT hr = 0;
BOOL ret;
// Get the ADO connection
_Connection *con = NULL;
hr = CoCreateInstance( CLSID_Connection, NULL, CLSCTX_ALL, IID__Connection, (LPVOID *)&con );
if ( SUCCEEDED(hr) ) {
_Recordset *rs = NULL;
// Convert wide strings to BSTR as required by ADO APIs
BSTR bconstr = SysAllocString( constr );
BSTR bquerystr = SysAllocString( querystr );
if ( bconstr && bquerystr ) {
// Open the connection
hr = con->Open( bconstr, NULL, NULL, 0 );
if ( SUCCEEDED(hr) ) {
// Execute the query
hr = con->Execute( bquerystr, NULL, 0, &rs );
if ( SUCCEEDED(hr) ) {
// Display the results
ret = WSQ_GetCDate( rs ,result);
rs->Release();
} else {
TRACE( "Failed to execute query, %08x\r\n", hr );
} // if
} else {
TRACE( "Failed to open ADO connection, %08x\r\n", hr );
} // if
} else {
TRACE("Failed to convert wide to BSTR\r\n" );
} // if
con->Release();
if ( bconstr ) {
SysFreeString( bconstr );
}
if ( bquerystr ) {
SysFreeString( bquerystr );
}
} else {
TRACE("Failed to get connection, %08x\r\n", hr );
} // if
return ret;
} // DoQuery
The connection string (constr) is
provider=Search.CollatorDSO.1;EXTENDED PROPERTIES="Application=Windows"
as returned by ISearchQueryHelper.
And the query (querystr) is
SELECT System.Document.DateCreated FROM SystemIndex WHERE System.FileName LIKE 'filename%' AND DIRECTORY='file:C:\path\to\file'
The problem now is that I get an exception:
First-chance exception at 0x77c5fc56 in fraudTest.exe: Microsoft C++ exception: CNLBaseException at memory location 0x0012d6d0..
on this line
hr = con->Open( bconstr, NULL, NULL, 0 );
followed by the empty result from the query (this code is from WSQ_GetCDate):
rs->get_EOF( &eor );
while ( eor != VARIANT_TRUE ) { //this never executes }
Suprisingly SUCCEEDED(hr) returns true after the exception.
Where have I made en error and how to try and find it?
Thanks
t.g.wilk
I didn't solve this particular problem, but I learned that I don't need Windows Search to get the file metadata. The keyword to look for is "properties" instead of meta-data. I got my piece of code from Windows SDK v7.0 sample application named PropertyEdit.

Test in Perl if data is available on Device::SerialPort

I have written a Perl script that reads data from the serial port.
use Device::SerialPort;
$PortObj = new Device::SerialPort ($PortName, $quiet, $lockfile);
$PortObj->read_const_time( 500 ); # timeout waiting for data after 500ms
...
The main loop tries to read data from the serial port:
while ( 1 ) {
( $count, $data ) = $PortObj->read( $frameLength );
process_my_data( $data );
do_something_entirely_different_that_needs_being_done;
}
But rather than having a $PortObj->read time out (which consumes a lot of time), I want to be able to test if data is available in the buffer, so I can speed up the loop:
while ( 1 ) {
if ( test_serial_data_available ) { ( $count, $data ) = $PortObj->read( $frameLength ); }
do_something_entirely_different_that_needs_being_done;
}
Can I test the serial buffer for data availability?
EDIT1: I've been spending this morning rewriting the problem to use serial device as a file handle and reading data works, but it is still blocking the loop. This might open up new options to check for data available in the buffer.
In pseudo-Perl:
use Symbol qw( gensym );
my $handle = gensym();
my $PortObj = tie( *$handle, "Device::SerialPort", $PortName );
while ( 1 ) {
my $frameData;
if ( test_serial_data_available ) { my $readLength = read( $handle , $frameData , $frameLength ); }
do_something_entirely_different_that_needs_being_done;
}
So my question is: What should test_serial_data_available look like?
Since you have a filehandle, you can use select.
select will take an arbitrary number of file descriptors and wait until one of them becomes "ready", where ready is defined by which of the 3 sets select gets contains the filehandle. See perldoc -f select for details.
select accepts a timeout, so if you give it a timeout of 0, it becomes a polling function. So this function will do what you need:
sub poll {
my ($fh) = #_;
my $in = '';
vec($in,fileno($fh),1) = 1;
return select($in,undef,undef,0);
}
# ...
if ( poll($handle) ) { my $readLength = read( $handle , $frameData , $frameLength ); }

Resources