/* ** Copyright (C) 1996, 1997 Microsoft Corporation. All Rights Reserved. ** ** File: utility.cpp ** ** Author: ** ** Description: ** Implementation of the non-templated utl classes. See utl.h. ** ** History: */ #include "pch.h" const Rotation c_rotationZero(0.0f, 0.0f, 1.0f, 0.0f); char UTL::s_artworkPath[MAX_PATH] = ""; char UTL::s_szUrlRoot[MAX_PATH] = ""; #ifndef DREAMCAST void UTL::SetUrlRoot(const char * szUrlRoot) { assert (szUrlRoot); strcpy(s_szUrlRoot, szUrlRoot); } void UTL::SetArtPath(const char* szArtwork) { int cbsz = lstrlen(szArtwork); assert(cbsz > 0 && cbsz < MAX_PATH); bool fTrailingBS = szArtwork[cbsz - 1] == '\\'; lstrcpy(s_artworkPath, szArtwork); if (!fTrailingBS) { s_artworkPath[cbsz] = '\\'; s_artworkPath[cbsz + 1] = 0; } } HRESULT UTL::getFile( const char* name, const char* extension, OUT char* artwork, bool downloadF, bool createF) { HRESULT rc = E_FAIL; assert (name && extension && artwork && *s_artworkPath); strcpy(artwork, s_artworkPath); { char* pArtwork = artwork + strlen(artwork); const char* pName = name; while ((*pName != '\0') && (*pName != ' ')) *(pArtwork++) = *(pName++); strcpy(pArtwork, extension); } OFSTRUCT filedata; filedata.cBytes = sizeof(filedata); if (OpenFile(artwork, &filedata, OF_EXIST) != HFILE_ERROR) rc = S_OK; else debugf("Unable to open %s%s\n", name, extension); return rc; } ///////////////////////////////////////////////////////// // SaveFile() // // Writes a blob to disk. // // szErrorMsg should be NULL if no error msg is wanted // // returns true iff no errors // bool UTL::SaveFile(const char * szFilename, const void *pData, unsigned cLen, OUT char * szErrorMsg, bool bCreateAsTemp) { HANDLE hFile = CreateFile(szFilename, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, bCreateAsTemp ? FILE_ATTRIBUTE_TEMPORARY : FILE_ATTRIBUTE_NORMAL, // use bCreateAsTemp for don't write to disk write away (for better performance). NULL); if (hFile == INVALID_HANDLE_VALUE) { if (szErrorMsg) sprintf(szErrorMsg, "Failed create file (%s); Error Code: %d ", szFilename, GetLastError()); return false; } unsigned long cBytesWritten; if (!WriteFile(hFile, pData, cLen, &cBytesWritten, NULL)) { if (szErrorMsg) sprintf(szErrorMsg, "Failed write file (%s); Error Code: %d ", szFilename, GetLastError()); return false; } if (!::CloseHandle(hFile)) { if (szErrorMsg) sprintf(szErrorMsg, "Couldn't close file (%s); Error Code: %d ", szFilename, GetLastError()); return false; } return true; } ///////////////////////////////////////////////////////// // AppendFile() // // Appends data to the end of a file // // returns true iff no errors // bool UTL::AppendFile(const char * szFileName, const void * data, unsigned bytes) { FILE* f; f = fopen( szFileName, "ab" ); // a == open for appending if (f == 0) return 0; if (fwrite( data, bytes, 1, f ) != 1) { fclose(f); return 0; } if (fclose(f)) return 0; return 1; } ///////////////////////////////////////////////////////// // SearchAndReplace() // // Searches a string, replacing a particular word with another. The case of the old word // doesn't matter. // // returns number of replacements made // int UTL::SearchAndReplace(char * szDest, const char * szSource, const char * szNewWord, const char * szOldWord) { int cbSource = strlen(szSource) + 1; int cbDest = strlen(szSource) + 1; int nLengthOldWord = strlen(szOldWord); int nLengthNewWord = strlen(szNewWord); char * szUpperSource = (char*)_alloca(cbSource); char * szUpperOldWord = (char*)_alloca(nLengthOldWord+1); strcpy(szUpperSource, szSource); strcpy(szUpperOldWord, szOldWord); _strupr(szUpperSource); _strupr(szUpperOldWord); memset(szDest, 0, cbDest); char * pszCurrent = szUpperSource; char * pszPrev = szUpperSource; int nSourceOffset = 0; int nDestOffset = 0; int cReplacements = 0; while(1) { pszCurrent = strstr(pszCurrent, szUpperOldWord); if (!pszCurrent) // szOldWord not found { // finish up and quit strcpy(szDest + nDestOffset, szSource + nSourceOffset); return cReplacements; } cReplacements++; int nMovement = pszCurrent-pszPrev; strncpy(szDest + nDestOffset, szSource + nSourceOffset, nMovement); strcat(szDest, szNewWord); nSourceOffset += nMovement + nLengthOldWord; nDestOffset += nMovement + nLengthNewWord; pszCurrent += nLengthOldWord; pszPrev = pszCurrent; } } #endif //dreamcast /*------------------------------------------------------------------------- * GetPathFromReg *------------------------------------------------------------------------- Purpose: Get a path out of the registry Parameters: Obvious. Notice that szPath must be of size MAX_PATH Returns: Return value from RegOpenKeyEx or RegQueryValueEx */ LONG UTL::GetPathFromReg(IN HKEY hkey, IN const char * szSubKey, OUT char * szPath) { HKEY hKey; DWORD cb = MAX_PATH; DWORD dw = REG_SZ; assert(hkey && szSubKey); szPath[0] = 0; LONG ret = RegOpenKeyEx(hkey, szSubKey, 0, KEY_READ, &hKey); if (ERROR_SUCCESS == ret) { ret = RegQueryValueEx(hKey, "ArtPath", NULL, &dw, (unsigned char*)szPath, &cb); RegCloseKey(hKey); } return ret; } // converts char * of hex to int. Assumes uppercase for 'A' to 'F'. int UTL::hextoi(const char * pHex) { int n = 0; while(1) { if (*pHex >= '0' && *pHex <= '9') { n *= 16; n += *pHex - '0'; } else if (*pHex >= 'A' && *pHex <= 'F') { n *= 16; n += 10 + *pHex - 'A'; } else break; pHex++; } return n; } /*------------------------------------------------------------------------- * CompareFileVersion *------------------------------------------------------------------------- * Purpose: * Compare a file's version (not file's product version) with a given version * * Parameters: * hInstance of file, version elements * * Returns: * If file's version is less than supplied version: -1 * If file's version is equal to supplied version: 0 * If file's version is greater than supplied version: 1 */ /* int CompareFileVersion(HINSTANCE hInstance, WORD v1, WORD v2, WORD v3, WORD v4) { GetModuleFileName(hInstDPlay, szFullPath, sizeof(szFullPath)); if (0 == (dwVerInfoSize = GetFileVersionInfoSize(szFullPath, &dwVerHnd))) goto Cleanup; if (NULL == (hMem = GlobalAlloc(GMEM_MOVEABLE, dwVerInfoSize)) || NULL == (lpvMem = GlobalLock(hMem))) goto Cleanup; GetFileVersionInfo(szFullPath, dwVerHnd, dwVerInfoSize, lpvMem); if (!VerQueryValue(lpvMem, "\\", &lpBuffer, &dwBytes)) goto Cleanup; lpvsFixedFileInfo = (VS_FIXEDFILEINFO*)lpBuffer; } */ char* UTL::strdup(const char* s) { if (s) { char* r = new char [strlen(s) + 1]; assert (r); strcpy(r, s); return r; } else return NULL; } void UTL::putName(char* name, const char* newVal) { assert (name); if (newVal) { strncpy(name, newVal, c_cbName - 1); name[c_cbName - 1] = '\0'; } else name[0] = '\0'; } void UTL::putFileName(char* fileName, const char* newVal) { assert (fileName); if (newVal) { strncpy(fileName, newVal, c_cbName - 1); fileName[c_cbName - 1] = '\0'; } else fileName[0] = '\0'; } /* ** Definitions for the List_utl class: */ List_utl::List_utl(void) : m_first(NULL), m_last(NULL), m_n(0) { } void List_utl::first(Link_utl* l) { assert (l); l->unlink(); l->m_txen = NULL; l->m_next = m_first; l->m_list = this; if (m_first) m_first->m_txen = l; else m_last = l; m_first = l; m_n++; } void List_utl::last(Link_utl* l) { assert (l); l->unlink(); l->m_txen = m_last; l->m_next = NULL; l->m_list = this; if (m_last) m_last->m_next = l; else m_first = l; m_last = l; m_n++; } Link_utl* List_utl::operator [] (int index) const { //Get the offset handling the case where index is < 0. int n = (index >= 0) ? index : (m_n + index); Link_utl* link = NULL; if ((n >= 0) && (n < m_n)) { if ((n << 1) < m_n) { /* ** Desired element is in the 1st half of the list, search from the front. */ link = m_first; while (n--) link = link->next(); } else { /* ** Desired element is in the last half of the list, search from the back. */ link = m_last; while (++n < m_n) link = link->txen(); } } return link; } /* ** Definitions for the Link_utl class: */ Link_utl::Link_utl(void) : m_list(NULL), m_txen(NULL), m_next(NULL) { } bool Link_utl::unlink(void) { if (!m_list) return false; if (m_next) { m_next->m_txen = m_txen; } else { m_list->m_last = m_txen; } if (m_txen) { m_txen->m_next = m_next; } else { m_list->m_first = m_next; } m_list->m_n--; m_list = NULL; m_next = NULL; m_txen = NULL; return true; } bool Link_utl::next(Link_utl* l) { if ((!m_list) || (l == NULL) || (l == this)) return false; l->unlink(); l->m_list = m_list; l->m_txen = this; l->m_next = m_next; if (m_next) m_next->m_txen = l; else m_list->m_last = l; m_next = l; m_list->m_n++; return true; } bool Link_utl::txen(Link_utl* l) { if ((!m_list) || (l == NULL) || (l == this)) return false; l->unlink(); l->m_list = m_list; l->m_txen = m_txen; l->m_next = this; if (m_txen) m_txen->m_next = l; else m_list->m_first = l; m_txen = l; m_list->m_n++; return true; } #ifndef DREAMCAST Lock_utl::Lock_utl(void) : m_lockedS(CreateSemaphore(NULL, 1, 1, NULL)), m_locking_threadID(0), m_locks(0) { } Lock_utl::~Lock_utl(void) { CloseHandle(m_lockedS); } void Lock_utl::lock(void) const { Lock_utl* t = (Lock_utl*)this; //cast away constness DWORD threadID = GetCurrentThreadId(); if (t->m_locking_threadID == threadID) { /* ** Just use the standard increment since this clause ** could only be executed if the list has been locked ** by this thread and this thread can only do one ** thing at a time. */ t->m_locks++; } else { WaitForSingleObject(t->m_lockedS, INFINITE); t->m_locking_threadID = threadID; t->m_locks = 1; } } void Lock_utl::unlock(void) const { Lock_utl* t = (Lock_utl*)this; //cast away constness /* ** We only need the standard decrement here because unlock should ** only be called from the controlling thread & therefore we don't ** have to worry about other threads making simultaneous calls. */ assert (GetCurrentThreadId() == t->m_locking_threadID); //NYI if (--(t->m_locks) == 0) { t->m_locking_threadID = 0; ReleaseSemaphore(t->m_lockedS, 1, NULL); } } #endif //dreamcast Rotation::Rotation(void) : m_angle(0.0f) { m_axis.x = m_axis.y = 0.0f; m_axis.z = -1.0; } Rotation::Rotation(const Rotation& r) : m_angle(r.m_angle) { m_axis = r.m_axis; } void Rotation::reset(void) { m_angle = m_axis.x = m_axis.y = 0.0f; m_axis.z = -1.0; } void Rotation::set(const Vector& axis, D3DVALUE angle) { m_axis = axis; m_angle = angle; } Rotation& Rotation::operator = (const Rotation& r) { m_axis = r.m_axis; m_angle = r.m_angle; return *this; } void Rotation::axis(const Vector& a) { m_axis = a; } void Rotation::angle(D3DVALUE a) { m_angle = a; } void Rotation::x(D3DVALUE t) { m_axis.x = t; } void Rotation::y(D3DVALUE t) { m_axis.y = t; } void Rotation::z(D3DVALUE t) { m_axis.z = t; }