forked from 0ad/0ad
# vista compat (fixes wsnd issue) and improvements
lib: move IsSimilarMagnitude and downcasters here from single modules where they're used acpi: simplify by only using v1.0 or 2.0 tables snd: add note on why OpenAL can't be used mahaf: change prefix wcpu: cache results, reinstate wcpu_ClockFrequency win: add winreg.h for registry functions wsnd: only do the DSound thing on non-vista (and delay-load to avoid overhead) wutil: add code to correctly detect windows version This was SVN commit r5090.
This commit is contained in:
parent
ceee6e00bd
commit
452d67f0b7
@ -32,10 +32,6 @@ u16 subusw(u16 x, u16 y)
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// rand
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// type conversion
|
||||
|
||||
|
@ -170,7 +170,7 @@ STMT(\
|
||||
**/
|
||||
#define SAFE_FREE(p)\
|
||||
STMT(\
|
||||
free(p); /* if p == 0, free is a no-op */ \
|
||||
free((void*)p); /* if p == 0, free is a no-op */ \
|
||||
(p) = 0;\
|
||||
)
|
||||
|
||||
@ -206,6 +206,14 @@ inline bool feqf(float f1, float f2, float epsilon = 0.001f)
|
||||
return fabsf(f1 - f2) < epsilon;
|
||||
}
|
||||
|
||||
inline bool IsSimilarMagnitude(double d1, double d2, const double relativeErrorTolerance = 0.05)
|
||||
{
|
||||
const double relativeError = fabs(d1/d2 - 1.0);
|
||||
if(relativeError > relativeErrorTolerance)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// type conversion
|
||||
@ -222,6 +230,32 @@ extern u16 u32_lo(u32 x); /// return lower 16-bits
|
||||
extern u64 u64_from_u32(u32 hi, u32 lo); /// assemble u64 from u32
|
||||
extern u32 u32_from_u16(u16 hi, u16 lo); /// assemble u32 from u16
|
||||
|
||||
// safe downcasters: cast from any integral type to u32 or u16;
|
||||
// issues warning if larger than would fit in the target type.
|
||||
//
|
||||
// these are generally useful but included here (instead of e.g. lib.h) for
|
||||
// several reasons:
|
||||
// - including implementation in lib.h doesn't work because the definition
|
||||
// of debug_assert in turn requires lib.h's STMT.
|
||||
// - separate compilation of templates via export isn't supported by
|
||||
// most compilers.
|
||||
|
||||
template<typename T> u32 u32_from_larger(T x)
|
||||
{
|
||||
const u32 max = std::numeric_limits<u32>::max();
|
||||
if((u64)x > (u64)max)
|
||||
throw std::out_of_range("u32_from_larger");
|
||||
return (u32)(x & max);
|
||||
}
|
||||
|
||||
template<typename T> u16 u16_from_larger(T x)
|
||||
{
|
||||
const u16 max = std::numeric_limits<u16>::max();
|
||||
if((u64)x > (u64)max)
|
||||
throw std::out_of_range("u16_from_larger");
|
||||
return (u16)(x & max);
|
||||
}
|
||||
|
||||
/// convert double to u8; verifies number is in range.
|
||||
extern u8 u8_from_double(double in);
|
||||
/// convert double to u16; verifies number is in range.
|
||||
|
@ -22,31 +22,6 @@
|
||||
#include "file_internal.h"
|
||||
|
||||
|
||||
// safe downcasters: cast from any integral type to u32 or u16;
|
||||
// issues warning if larger than would fit in the target type.
|
||||
//
|
||||
// these are generally useful but included here (instead of e.g. lib.h) for
|
||||
// several reasons:
|
||||
// - including implementation in lib.h doesn't work because the definition
|
||||
// of debug_assert in turn requires lib.h's STMT.
|
||||
// - separate compilation of templates via export isn't supported by
|
||||
// most compilers.
|
||||
|
||||
template<typename T> u32 u32_from_larger(T x)
|
||||
{
|
||||
const u32 max = std::numeric_limits<u32>::max();
|
||||
debug_assert((u64)x <= (u64)max);
|
||||
return (u32)(x & max);
|
||||
}
|
||||
|
||||
template<typename T> u16 u16_from_larger(T x)
|
||||
{
|
||||
const u16 max = std::numeric_limits<u16>::max();
|
||||
debug_assert((u64)x <= (u64)max);
|
||||
return (u16)(x & max);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// timestamp conversion: DOS FAT <-> Unix time_t
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -29,7 +29,7 @@ static const AcpiTable* AllocateCopyOfTable(u64 physicalAddress)
|
||||
{
|
||||
// 4 KiB ought to be enough; if not, the table will be re-mapped.
|
||||
const size_t initialSize = 4*KiB;
|
||||
const AcpiTable* mappedTable = (const AcpiTable*)MapPhysicalMemory(physicalAddress, initialSize);
|
||||
const AcpiTable* mappedTable = (const AcpiTable*)mahaf_MapPhysicalMemory(physicalAddress, initialSize);
|
||||
if(!mappedTable)
|
||||
return 0;
|
||||
const size_t size = mappedTable->size;
|
||||
@ -37,8 +37,8 @@ static const AcpiTable* AllocateCopyOfTable(u64 physicalAddress)
|
||||
if(size > initialSize)
|
||||
{
|
||||
// re-map with correct size
|
||||
UnmapPhysicalMemory((void*)mappedTable);
|
||||
mappedTable = (const AcpiTable*)MapPhysicalMemory(physicalAddress, size);
|
||||
mahaf_UnmapPhysicalMemory((void*)mappedTable);
|
||||
mappedTable = (const AcpiTable*)mahaf_MapPhysicalMemory(physicalAddress, size);
|
||||
if(!mappedTable)
|
||||
return 0;
|
||||
}
|
||||
@ -47,7 +47,7 @@ static const AcpiTable* AllocateCopyOfTable(u64 physicalAddress)
|
||||
if(table)
|
||||
cpu_memcpy(table, mappedTable, size);
|
||||
|
||||
UnmapPhysicalMemory((void*)mappedTable);
|
||||
mahaf_UnmapPhysicalMemory((void*)mappedTable);
|
||||
return table;
|
||||
}
|
||||
|
||||
@ -86,14 +86,10 @@ static bool VerifyTable(const AcpiTable* table, const char* signature = 0)
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// get pointer to (eXtended) Root System Descriptor Table
|
||||
// Root System Descriptor Pointer
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Root System Descriptor Pointer
|
||||
|
||||
static const size_t RSDP_ALIGNMENT = 16;
|
||||
|
||||
struct RSDPv1
|
||||
struct RSDP
|
||||
{
|
||||
char signature[8]; // "RSD PTR "
|
||||
u8 checksum; // sum of this struct = 0
|
||||
@ -102,20 +98,7 @@ struct RSDPv1
|
||||
u32 rsdtPhysicalAddress;
|
||||
};
|
||||
|
||||
struct RSDPv2Additions
|
||||
{
|
||||
u32 size; // of entire table (including V1)
|
||||
u64 xsdtPhysicalAddress64;
|
||||
u8 extendedChecksum; // sum of entire table (including V1) = 0
|
||||
char reserved[3]; // must be 0
|
||||
};
|
||||
|
||||
struct RSDP
|
||||
{
|
||||
RSDPv1 v1;
|
||||
RSDPv2Additions v2;
|
||||
};
|
||||
|
||||
static const size_t RSDP_ALIGNMENT = 16;
|
||||
|
||||
static const RSDP* LocateRsdp(const u8* buf, size_t numBytes)
|
||||
{
|
||||
@ -124,10 +107,10 @@ static const RSDP* LocateRsdp(const u8* buf, size_t numBytes)
|
||||
{
|
||||
const RSDP* rsdp = (const RSDP*)p;
|
||||
|
||||
if(memcmp(rsdp->v1.signature, "RSD PTR ", 8) != 0)
|
||||
if(memcmp(rsdp->signature, "RSD PTR ", 8) != 0)
|
||||
continue;
|
||||
|
||||
if(ComputeChecksum(p, 20) != 0)
|
||||
if(ComputeChecksum(p, sizeof(RSDP)) != 0)
|
||||
continue;
|
||||
|
||||
return rsdp;
|
||||
@ -139,13 +122,13 @@ static const RSDP* LocateRsdp(const u8* buf, size_t numBytes)
|
||||
|
||||
static bool LocateAndRetrieveRsdp(uintptr_t physicalAddress, size_t numBytes, RSDP& rsdp)
|
||||
{
|
||||
void* virtualAddress = MapPhysicalMemory(physicalAddress, numBytes);
|
||||
void* virtualAddress = mahaf_MapPhysicalMemory(physicalAddress, numBytes);
|
||||
|
||||
const RSDP* prsdp = LocateRsdp((const u8*)virtualAddress, numBytes);
|
||||
if(prsdp)
|
||||
rsdp = *prsdp; // stash in output parameter before unmapping
|
||||
|
||||
UnmapPhysicalMemory(virtualAddress);
|
||||
mahaf_UnmapPhysicalMemory(virtualAddress);
|
||||
return (prsdp != 0);
|
||||
}
|
||||
|
||||
@ -159,7 +142,7 @@ static uintptr_t LocateEbdaPhysicalAddress()
|
||||
u16 ebdaSegment;
|
||||
// ...
|
||||
};
|
||||
const BiosDataArea* bda = (const BiosDataArea*)MapPhysicalMemory(0x400, 0x100);
|
||||
const BiosDataArea* bda = (const BiosDataArea*)mahaf_MapPhysicalMemory(0x400, 0x100);
|
||||
if(!bda)
|
||||
return 0;
|
||||
const uintptr_t ebdaPhysicalAddress = ((uintptr_t)bda->ebdaSegment) * 16;
|
||||
@ -183,22 +166,7 @@ static bool RetrieveRsdp(RSDP& rsdp)
|
||||
}
|
||||
|
||||
|
||||
static bool VerifyRsdp(const RSDP& rsdp)
|
||||
{
|
||||
if(ComputeChecksum(&rsdp.v1, sizeof(rsdp.v1)) != 0)
|
||||
return false;
|
||||
|
||||
if(rsdp.v1.revision >= 2)
|
||||
{
|
||||
if(ComputeChecksum(&rsdp, rsdp.v2.size) != 0)
|
||||
return false;
|
||||
|
||||
if(rsdp.v2.size < sizeof(RSDP))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Root System Descriptor Table
|
||||
struct RSDT
|
||||
@ -207,107 +175,63 @@ struct RSDT
|
||||
u32 tables[1];
|
||||
};
|
||||
|
||||
// eXtended root System Descriptor Table (same thing, just 64-bit pointers)
|
||||
struct XSDT
|
||||
{
|
||||
AcpiTable header;
|
||||
u64 tables[1];
|
||||
};
|
||||
|
||||
|
||||
// caller is responsible for verifying the table is valid and must
|
||||
// free() the returned pointer.
|
||||
static const XSDT* AllocateCopyOfXsdt()
|
||||
{
|
||||
RSDP rsdp;
|
||||
if(!RetrieveRsdp(rsdp))
|
||||
return 0;
|
||||
|
||||
if(!VerifyRsdp(rsdp))
|
||||
return 0;
|
||||
|
||||
// callers should only have to deal with XSDTs, not the obsolete RSDTs.
|
||||
|
||||
// ACPI 2.0+, already have XSDT (note: caller must verify+free it)
|
||||
if(rsdp.v1.revision >= 2)
|
||||
return (const XSDT*)AllocateCopyOfTable(rsdp.v2.xsdtPhysicalAddress64);
|
||||
|
||||
// ACPI 1.0 - convert RSDT to XSDT (32->64 bit pointers)
|
||||
const RSDT* rsdt = (const RSDT*)AllocateCopyOfTable(rsdp.v1.rsdtPhysicalAddress);
|
||||
if(!rsdt)
|
||||
return 0;
|
||||
if(!VerifyTable((const AcpiTable*)rsdt, "RSDT"))
|
||||
{
|
||||
free((void*)rsdt);
|
||||
return 0;
|
||||
}
|
||||
const size_t numTables = (rsdt->header.size - sizeof(AcpiTable)) / sizeof(u32);
|
||||
const size_t xsdtSize = sizeof(AcpiTable) + numTables * sizeof(u64);
|
||||
XSDT* xsdt = (XSDT*)malloc(xsdtSize);
|
||||
if(xsdt)
|
||||
{
|
||||
xsdt->header = rsdt->header;
|
||||
cpu_memcpy(xsdt->header.signature, "XSDT", 4);
|
||||
xsdt->header.size = (u32)xsdtSize;
|
||||
for(size_t i = 0; i < numTables; i++)
|
||||
xsdt->tables[i] = (u64)rsdt->tables[i];
|
||||
xsdt->header.checksum = -ComputeChecksum(xsdt, xsdtSize);
|
||||
}
|
||||
|
||||
free((void*)rsdt);
|
||||
return xsdt;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
typedef std::map<u32, const AcpiTable*> Tables;
|
||||
static Tables tables;
|
||||
// avoid std::map et al. because we are called before _cinit
|
||||
static const AcpiTable** tables;
|
||||
static size_t numTables;
|
||||
|
||||
static bool LatchAllTables()
|
||||
{
|
||||
const XSDT* xsdt = AllocateCopyOfXsdt();
|
||||
if(!xsdt)
|
||||
RSDP rsdp;
|
||||
if(!RetrieveRsdp(rsdp))
|
||||
return false;
|
||||
if(!VerifyTable((const AcpiTable*)xsdt, "XSDT"))
|
||||
const RSDT* rsdt = (const RSDT*)AllocateCopyOfTable(rsdp.rsdtPhysicalAddress);
|
||||
if(!rsdt)
|
||||
return false;
|
||||
if(!VerifyTable((const AcpiTable*)rsdt, "RSDT"))
|
||||
{
|
||||
free((void*)xsdt);
|
||||
free((void*)rsdt);
|
||||
return false;
|
||||
}
|
||||
|
||||
const size_t numTables = (xsdt->header.size - sizeof(AcpiTable)) / sizeof(u64);
|
||||
numTables = (rsdt->header.size - sizeof(AcpiTable)) / sizeof(rsdt->tables[0]);
|
||||
tables = new const AcpiTable*[numTables];
|
||||
|
||||
for(size_t i = 0; i < numTables; i++)
|
||||
{
|
||||
const AcpiTable* table = AllocateCopyOfTable(xsdt->tables[i]);
|
||||
const AcpiTable* table = AllocateCopyOfTable(rsdt->tables[i]);
|
||||
if(!table)
|
||||
continue;
|
||||
if(!VerifyTable(table))
|
||||
debug_warn("invalid ACPI table");
|
||||
const u32 signature32 = *(u32*)table->signature;
|
||||
tables[signature32] = table;
|
||||
// table is now owned by tables and released via FreeAllTables.
|
||||
tables[i] = table; // transfers ownership
|
||||
}
|
||||
|
||||
free((void*)xsdt);
|
||||
free((void*)rsdt);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static void FreeAllTables()
|
||||
{
|
||||
for(Tables::iterator it(tables.begin()); it != tables.end(); ++it)
|
||||
for(size_t i = 0; i < numTables; i++)
|
||||
{
|
||||
std::pair<u32, const AcpiTable*> item = *it;
|
||||
free((void*)item.second);
|
||||
SAFE_FREE(tables[i]);
|
||||
}
|
||||
delete[] tables;
|
||||
}
|
||||
|
||||
|
||||
const AcpiTable* acpiGetTable(const char* signature)
|
||||
const AcpiTable* acpi_GetTable(const char* signature)
|
||||
{
|
||||
const u32 signature32 = *(u32*)signature;
|
||||
const AcpiTable* table = tables[signature32];
|
||||
return table;
|
||||
// (typically only a few tables, linear search is OK)
|
||||
for(size_t i = 0; i < numTables; i++)
|
||||
{
|
||||
const AcpiTable* table = tables[i];
|
||||
if(strncmp(table->signature, signature, 4) == 0)
|
||||
return table;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -315,24 +239,24 @@ const AcpiTable* acpiGetTable(const char* signature)
|
||||
|
||||
static ModuleInitState initState;
|
||||
|
||||
bool acpiInit()
|
||||
bool acpi_Init()
|
||||
{
|
||||
if(!ModuleShouldInitialize(&initState))
|
||||
return true;
|
||||
|
||||
if(!MahafInit())
|
||||
if(!mahaf_Init())
|
||||
return false;
|
||||
|
||||
LatchAllTables();
|
||||
return true;
|
||||
}
|
||||
|
||||
void acpiShutdown()
|
||||
void acpi_Shutdown()
|
||||
{
|
||||
if(!ModuleShouldShutdown(&initState))
|
||||
return;
|
||||
|
||||
FreeAllTables();
|
||||
|
||||
MahafShutdown();
|
||||
mahaf_Shutdown();
|
||||
}
|
||||
|
@ -48,9 +48,9 @@ struct AcpiGenericAddress
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
extern bool acpiInit();
|
||||
extern void acpiShutdown();
|
||||
extern bool acpi_Init();
|
||||
extern void acpi_Shutdown();
|
||||
|
||||
extern const AcpiTable* acpiGetTable(const char* signature);
|
||||
extern const AcpiTable* acpi_GetTable(const char* signature);
|
||||
|
||||
#endif // #ifndef INCLUDED_ACPI
|
||||
|
@ -17,12 +17,14 @@ char snd_drv_ver[SND_DRV_VER_LEN];
|
||||
|
||||
void snd_detect()
|
||||
{
|
||||
// note: OpenAL alGetString is worthless: it only returns
|
||||
// OpenAL API version and renderer (e.g. "Software").
|
||||
|
||||
#if OS_WIN
|
||||
extern LibError win_get_snd_info();
|
||||
win_get_snd_info();
|
||||
#else
|
||||
// At least reset the values for unhandled platforms. Should perhaps do
|
||||
// something like storing the OpenAL version or similar.
|
||||
// At least reset the values for unhandled platforms.
|
||||
debug_assert(SND_CARD_LEN >= 8 && SND_DRV_VER_LEN >= 8); // protect strcpy
|
||||
SAFE_STRCPY(snd_card, "Unknown");
|
||||
SAFE_STRCPY(snd_drv_ver, "Unknown");
|
||||
|
@ -45,21 +45,21 @@ static u32 ReadPort(u16 port, u8 numBytes)
|
||||
return value;
|
||||
}
|
||||
|
||||
u8 ReadPort8(u16 port)
|
||||
u8 mahaf_ReadPort8(u16 port)
|
||||
{
|
||||
const u32 value = ReadPort(port, 1);
|
||||
debug_assert(value <= 0xFF);
|
||||
return (u8)(value & 0xFF);
|
||||
}
|
||||
|
||||
u16 ReadPort16(u16 port)
|
||||
u16 mahaf_ReadPort16(u16 port)
|
||||
{
|
||||
const u32 value = ReadPort(port, 2);
|
||||
debug_assert(value <= 0xFFFF);
|
||||
return (u16)(value & 0xFFFF);
|
||||
}
|
||||
|
||||
u32 ReadPort32(u16 port)
|
||||
u32 mahaf_ReadPort32(u16 port)
|
||||
{
|
||||
const u32 value = ReadPort(port, 4);
|
||||
return value;
|
||||
@ -80,23 +80,23 @@ static void WritePort(u16 port, u32 value, u8 numBytes)
|
||||
WARN_WIN32_ERR;
|
||||
}
|
||||
|
||||
void WritePort8(u16 port, u8 value)
|
||||
void mahaf_WritePort8(u16 port, u8 value)
|
||||
{
|
||||
WritePort(port, (u32)value, 1);
|
||||
}
|
||||
|
||||
void WritePort16(u16 port, u16 value)
|
||||
void mahaf_WritePort16(u16 port, u16 value)
|
||||
{
|
||||
WritePort(port, (u32)value, 2);
|
||||
}
|
||||
|
||||
void WritePort32(u16 port, u32 value)
|
||||
void mahaf_WritePort32(u16 port, u32 value)
|
||||
{
|
||||
WritePort(port, value, 4);
|
||||
}
|
||||
|
||||
|
||||
void* MapPhysicalMemory(uintptr_t physicalAddress, size_t numBytes)
|
||||
void* mahaf_MapPhysicalMemory(uintptr_t physicalAddress, size_t numBytes)
|
||||
{
|
||||
AkenMapIn in;
|
||||
in.physicalAddress = (DWORD64)physicalAddress;
|
||||
@ -118,7 +118,7 @@ void* MapPhysicalMemory(uintptr_t physicalAddress, size_t numBytes)
|
||||
}
|
||||
|
||||
|
||||
void UnmapPhysicalMemory(void* virtualAddress)
|
||||
void mahaf_UnmapPhysicalMemory(void* virtualAddress)
|
||||
{
|
||||
AkenUnmapIn in;
|
||||
in.virtualAddress = (DWORD64)virtualAddress;
|
||||
@ -237,7 +237,7 @@ create:
|
||||
|
||||
static ModuleInitState initState;
|
||||
|
||||
bool MahafInit()
|
||||
bool mahaf_Init()
|
||||
{
|
||||
if(!ModuleShouldInitialize(&initState))
|
||||
return true;
|
||||
@ -257,7 +257,7 @@ bool MahafInit()
|
||||
}
|
||||
|
||||
|
||||
void MahafShutdown()
|
||||
void mahaf_Shutdown()
|
||||
{
|
||||
if(!ModuleShouldShutdown(&initState))
|
||||
return;
|
||||
|
@ -14,17 +14,17 @@
|
||||
#ifndef INCLUDED_MAHAF
|
||||
#define INCLUDED_MAHAF
|
||||
|
||||
extern bool MahafInit();
|
||||
extern void MahafShutdown();
|
||||
extern bool mahaf_Init();
|
||||
extern void mahaf_Shutdown();
|
||||
|
||||
extern u8 ReadPort8 (u16 port);
|
||||
extern u16 ReadPort16(u16 port);
|
||||
extern u32 ReadPort32(u16 port);
|
||||
extern void WritePort8 (u16 port, u8 value);
|
||||
extern void WritePort16(u16 port, u16 value);
|
||||
extern void WritePort32(u16 port, u32 value);
|
||||
extern u8 mahaf_ReadPort8 (u16 port);
|
||||
extern u16 mahaf_ReadPort16(u16 port);
|
||||
extern u32 mahaf_ReadPort32(u16 port);
|
||||
extern void mahaf_WritePort8 (u16 port, u8 value);
|
||||
extern void mahaf_WritePort16(u16 port, u16 value);
|
||||
extern void mahaf_WritePort32(u16 port, u32 value);
|
||||
|
||||
extern void* MapPhysicalMemory(uintptr_t physicalAddress, size_t numBytes);
|
||||
extern void UnmapPhysicalMemory(void* virtualAddress);
|
||||
extern void* mahaf_MapPhysicalMemory(uintptr_t physicalAddress, size_t numBytes);
|
||||
extern void mahaf_UnmapPhysicalMemory(void* virtualAddress);
|
||||
|
||||
#endif // INCLUDED_MAHAF
|
||||
|
@ -20,21 +20,60 @@
|
||||
// WinAPI only supports max. 32 CPUs anyway (due to DWORD bitfields).
|
||||
static const uint MAX_CPUS = 32;
|
||||
|
||||
// note: the below routines should cache their results to simplify things
|
||||
// for callers. however, we don't want to set the variables during init
|
||||
// because that would create init order dependencies (if other modules
|
||||
// use this from e.g. their PreLibcInit). hence, each routine must check
|
||||
// if they've been called for the first time.
|
||||
|
||||
/// get number of CPUs (can't fail)
|
||||
uint wcpu_NumProcessors()
|
||||
{
|
||||
static uint numProcessors = 0;
|
||||
if(numProcessors)
|
||||
return numProcessors;
|
||||
|
||||
SYSTEM_INFO si;
|
||||
GetSystemInfo(&si);
|
||||
const uint num_processors = (uint)si.dwNumberOfProcessors;
|
||||
return num_processors;
|
||||
numProcessors = (uint)si.dwNumberOfProcessors;
|
||||
|
||||
return numProcessors;
|
||||
}
|
||||
|
||||
|
||||
double wcpu_ClockFrequency()
|
||||
{
|
||||
static double clockFrequency = -1.0;
|
||||
if(clockFrequency > 0.0)
|
||||
return clockFrequency;
|
||||
|
||||
// read CPU frequency from registry
|
||||
HKEY hKey;
|
||||
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
|
||||
{
|
||||
DWORD freqMhz;
|
||||
DWORD size = sizeof(freqMhz);
|
||||
if(RegQueryValueEx(hKey, "~MHz", 0, 0, (LPBYTE)&freqMhz, &size) == STATUS_SUCCESS)
|
||||
clockFrequency = freqMhz * 1e6;
|
||||
else
|
||||
debug_assert(0);
|
||||
|
||||
RegCloseKey(hKey);
|
||||
}
|
||||
else
|
||||
debug_assert(0);
|
||||
|
||||
return clockFrequency;
|
||||
}
|
||||
|
||||
|
||||
int wcpu_IsThrottlingPossible()
|
||||
{
|
||||
static int isThrottlingPossible = -1;
|
||||
if(isThrottlingPossible != -1)
|
||||
return isThrottlingPossible;
|
||||
|
||||
WIN_SAVE_LAST_ERROR;
|
||||
int is_throttling_possible = -1;
|
||||
|
||||
// CallNtPowerInformation
|
||||
// (manual import because it's not supported on Win95)
|
||||
@ -50,7 +89,7 @@ int wcpu_IsThrottlingPossible()
|
||||
if(pCNPI(SystemPowerCapabilities, 0,0, &spc,sizeof(spc)) == STATUS_SUCCESS)
|
||||
{
|
||||
if(!spc.ProcessorThrottle || !spc.ThermalControl)
|
||||
is_throttling_possible = 0;
|
||||
isThrottlingPossible = 0;
|
||||
}
|
||||
|
||||
// probably speedstep if cooling mode active.
|
||||
@ -59,7 +98,7 @@ int wcpu_IsThrottlingPossible()
|
||||
if(pCNPI(SystemPowerInformation, 0,0, &spi,sizeof(spi)) == STATUS_SUCCESS)
|
||||
{
|
||||
if(spi.CoolingMode != PO_TZ_INVALID_MODE)
|
||||
is_throttling_possible = 1;
|
||||
isThrottlingPossible = 1;
|
||||
}
|
||||
|
||||
// definitely speedstep if any throttle is less than 100%.
|
||||
@ -71,7 +110,7 @@ int wcpu_IsThrottlingPossible()
|
||||
{
|
||||
if(p->MhzLimit != p->MaxMhz || p->CurrentMhz != p->MaxMhz)
|
||||
{
|
||||
is_throttling_possible = 1;
|
||||
isThrottlingPossible = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -81,7 +120,7 @@ int wcpu_IsThrottlingPossible()
|
||||
|
||||
// CallNtPowerInformation not available, or none of the above apply:
|
||||
// don't know yet (for certain, at least).
|
||||
if(is_throttling_possible == -1)
|
||||
if(isThrottlingPossible == -1)
|
||||
{
|
||||
// check if running on a laptop
|
||||
HW_PROFILE_INFO hi;
|
||||
@ -93,13 +132,13 @@ int wcpu_IsThrottlingPossible()
|
||||
|
||||
// we'll guess SpeedStep is active if on a laptop.
|
||||
// ia32 code will get a second crack at it.
|
||||
is_throttling_possible = (is_laptop)? 1 : 0;
|
||||
isThrottlingPossible = (is_laptop)? 1 : 0;
|
||||
}
|
||||
|
||||
WIN_RESTORE_LAST_ERROR;
|
||||
|
||||
debug_assert(is_throttling_possible == 0 || is_throttling_possible == 1);
|
||||
return is_throttling_possible;
|
||||
debug_assert(isThrottlingPossible == 0 || isThrottlingPossible == 1);
|
||||
return isThrottlingPossible;
|
||||
}
|
||||
|
||||
|
||||
@ -155,6 +194,7 @@ LibError wcpu_CallByEachCPU(CpuCallback cb, void* param)
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if 0
|
||||
|
||||
// we need a means of measuring performance, since it is hard to predict and
|
||||
// depends on many factors. to cover a wider range of configurations, this
|
||||
@ -371,3 +411,4 @@ probably hard; a start would be just the function in which the address is, then
|
||||
|
||||
|
||||
*/
|
||||
#endif
|
||||
|
@ -14,8 +14,8 @@
|
||||
#include "lib/sysdep/cpu.h"
|
||||
|
||||
extern uint wcpu_NumProcessors();
|
||||
extern int wcpu_IsThrottlingPossible();
|
||||
extern double wcpu_ClockFrequency();
|
||||
extern int wcpu_IsThrottlingPossible();
|
||||
extern LibError wcpu_CallByEachCPU(CpuCallback cb, void* param);
|
||||
|
||||
#endif // #ifndef INCLUDED_WCPU
|
||||
|
@ -70,9 +70,10 @@
|
||||
#define NOPROFILER // Profiler interface.
|
||||
#define NODEFERWINDOWPOS // DeferWindowPos routines
|
||||
#define NOMCX // Modem Configuration Extensions
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <winreg.h>
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// fixes for VC6 platform SDK
|
||||
|
@ -23,41 +23,6 @@
|
||||
#include "wutil.h"
|
||||
|
||||
|
||||
// DirectSound header
|
||||
// HACK: workaround for "subwtype.h not found" errors on VC6/7 hybrid.
|
||||
// (subwtype.h <- d3dtypes.h <- dsound.h)
|
||||
// since we're only using one DS function (DirectSoundEnumerate),
|
||||
// we forward-declare it rather than fix/mess with the system headers.
|
||||
#if 0
|
||||
// mmsystem.h is necessary for dsound.h; we cut out unnecessary junk
|
||||
# define MMNODRV // Installable driver support
|
||||
# define MMNOSOUND // Sound support
|
||||
//# define MMNOWAVE // Waveform support
|
||||
# define MMNOMIDI // MIDI support
|
||||
# define MMNOAUX // Auxiliary audio support
|
||||
# define MMNOMIXER // Mixer support
|
||||
# define MMNOTIMER // Timer support
|
||||
# define MMNOJOY // Joystick support
|
||||
# define MMNOMCI // MCI support
|
||||
# define MMNOMMIO // Multimedia file I/O support
|
||||
# define MMNOMMSYSTEM // General MMSYSTEM functions
|
||||
# include <MMSystem.h>
|
||||
# define DIRECTSOUND_VERSION 0x0500
|
||||
# include <dsound.h>
|
||||
#else
|
||||
# define DS_OK 0
|
||||
typedef BOOL (CALLBACK* LPDSENUMCALLBACKA)(void*, const char*, const char*, void*);
|
||||
EXTERN_C __declspec(dllimport) HRESULT WINAPI DirectSoundEnumerateA(LPDSENUMCALLBACKA, void*);
|
||||
#endif
|
||||
|
||||
#if MSC_VERSION
|
||||
#pragma comment(lib, "dsound.lib")
|
||||
#endif
|
||||
|
||||
|
||||
// note: OpenAL alGetString is worthless: it only returns OpenAL API version
|
||||
// and renderer (e.g. "Software").
|
||||
|
||||
// indicate if this directory entry is an OpenAL DLL.
|
||||
// (matches "*oal.dll" and "*OpenAL*", as with OpenAL router's search)
|
||||
static LibError IsOpenAlDll(const DirEnt* ent)
|
||||
@ -120,50 +85,64 @@ static LibError add_oal_dlls_in_dir(const char* dir, StringSet* dlls)
|
||||
}
|
||||
|
||||
|
||||
// DS3D driver path; filled by ds_enum, used by win_get_snd_info.
|
||||
// side effect: remains zeroed if there's no sound card installed.
|
||||
static char ds_drv_path[MAX_PATH+1];
|
||||
//-----------------------------------------------------------------------------
|
||||
// DirectSound driver version
|
||||
|
||||
// we've seen audio problems caused by buggy DirectSound drivers (because
|
||||
// OpenAL can use them in its implementation), so their version should be
|
||||
// retrieved as well. the only way I know of is to enumerate all DS devices.
|
||||
//
|
||||
// unfortunately this fails with Vista's DS emulation - it returns some
|
||||
// GUID crap as the module name. to avoid crashing when attempting to get
|
||||
// the version info for that bogus driver path, we'll skip this code there.
|
||||
// (delay-loading dsound.dll eliminates any overhead)
|
||||
|
||||
static char directSoundDriverPath[MAX_PATH+1];
|
||||
|
||||
// store sound card name and path to DirectSound driver.
|
||||
// called for each DirectSound driver, but aborts after first valid driver.
|
||||
static BOOL CALLBACK ds_enum(void* guid, const char* description,
|
||||
static BOOL CALLBACK DirectSoundCallback(void* guid, const char* UNUSED(description),
|
||||
const char* module, void* UNUSED(ctx))
|
||||
{
|
||||
// skip first dummy entry (description == "Primary Sound Driver")
|
||||
if(guid == NULL)
|
||||
return TRUE; // continue calling
|
||||
|
||||
strcpy_s(snd_card, SND_CARD_LEN, description);
|
||||
|
||||
// note: $system\\drivers is not in LoadLibrary's search list,
|
||||
// so we have to give the full pathname.
|
||||
snprintf(ds_drv_path, ARRAY_SIZE(ds_drv_path), "%s\\drivers\\%s", win_sys_dir, module);
|
||||
snprintf(directSoundDriverPath, ARRAY_SIZE(directSoundDriverPath), "%s\\drivers\\%s", win_sys_dir, module);
|
||||
|
||||
// we assume the first "driver name" (sound card) is the one we want;
|
||||
// stick with that and stop calling.
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static const char* GetDirectSoundDriverPath()
|
||||
{
|
||||
#define DS_OK 0
|
||||
typedef BOOL (CALLBACK* LPDSENUMCALLBACKA)(void*, const char*, const char*, void*);
|
||||
HRESULT (WINAPI *pDirectSoundEnumerateA)(LPDSENUMCALLBACKA, void*);
|
||||
HMODULE hDsoundDll = LoadLibrary("dsound.dll");
|
||||
*(void**)&pDirectSoundEnumerateA = GetProcAddress(hDsoundDll, "DirectSoundEnumerateA");
|
||||
if(pDirectSoundEnumerateA)
|
||||
{
|
||||
if(DirectSoundEnumerateA(DirectSoundCallback, (void*)0) != DS_OK)
|
||||
debug_warn("DirectSoundEnumerate failed");
|
||||
}
|
||||
FreeLibrary(hDsoundDll);
|
||||
|
||||
return directSoundDriverPath;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
LibError win_get_snd_info()
|
||||
{
|
||||
// get sound card name and DS driver path.
|
||||
if(DirectSoundEnumerateA((LPDSENUMCALLBACKA)ds_enum, (void*)0) != DS_OK)
|
||||
debug_warn("DirectSoundEnumerate failed");
|
||||
|
||||
// there are apparently no sound card/drivers installed; so indicate.
|
||||
// (the code below would fail and not produce reasonable output)
|
||||
if(ds_drv_path[0] == '\0')
|
||||
{
|
||||
strcpy_s(snd_card, SND_CARD_LEN, "(none)");
|
||||
strcpy_s(snd_drv_ver, SND_DRV_VER_LEN, "(none)");
|
||||
return INFO::OK;
|
||||
}
|
||||
|
||||
// find all DLLs related to OpenAL, retrieve their versions,
|
||||
// and store in snd_drv_ver string.
|
||||
dll_list_init(snd_drv_ver, SND_DRV_VER_LEN);
|
||||
(void)dll_list_add(ds_drv_path);
|
||||
if(!wutil_IsVista())
|
||||
(void)dll_list_add(GetDirectSoundDriverPath());
|
||||
StringSet dlls; // ensures uniqueness
|
||||
(void)add_oal_dlls_in_dir(win_exe_dir, &dlls);
|
||||
(void)add_oal_dlls_in_dir(win_sys_dir, &dlls);
|
||||
|
@ -226,6 +226,39 @@ static void EnableLowFragmentationHeap()
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// version
|
||||
|
||||
static char versionString[20];
|
||||
|
||||
static void DetectWindowsVersion()
|
||||
{
|
||||
// note: don't use GetVersion[Ex] because it gives the version of the
|
||||
// emulated OS when running an app with compatibility shims enabled.
|
||||
HKEY hKey;
|
||||
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
|
||||
{
|
||||
DWORD size = ARRAY_SIZE(versionString);
|
||||
(void)RegQueryValueEx(hKey, "CurrentVersion", 0, 0, (LPBYTE)versionString, &size);
|
||||
|
||||
RegCloseKey(hKey);
|
||||
}
|
||||
else
|
||||
debug_assert(0);
|
||||
}
|
||||
|
||||
const char* wutil_WindowsVersionString()
|
||||
{
|
||||
debug_assert(versionString[0] != '\0');
|
||||
return versionString;
|
||||
}
|
||||
|
||||
bool wutil_IsVista()
|
||||
{
|
||||
debug_assert(versionString[0] != '\0');
|
||||
return (versionString[0] >= '6');
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Wow64
|
||||
|
||||
@ -304,6 +337,8 @@ static LibError wutil_PreLibcInit()
|
||||
|
||||
GetDirectories();
|
||||
|
||||
DetectWindowsVersion();
|
||||
|
||||
ImportWow64Functions();
|
||||
DetectWow64();
|
||||
|
||||
|
@ -94,6 +94,14 @@ extern char win_sys_dir[MAX_PATH+1];
|
||||
extern char win_exe_dir[MAX_PATH+1];
|
||||
|
||||
|
||||
//
|
||||
// version
|
||||
//
|
||||
|
||||
extern const char* wutil_WindowsVersionString();
|
||||
extern bool wutil_IsVista();
|
||||
|
||||
|
||||
//
|
||||
// Wow64
|
||||
//
|
||||
|
Loading…
Reference in New Issue
Block a user