diff --git a/source/lib/mmgr.cpp b/source/lib/mmgr.cpp index 502249d1c8..e625b9c965 100644 --- a/source/lib/mmgr.cpp +++ b/source/lib/mmgr.cpp @@ -99,12 +99,10 @@ static void unlock() throw() // enable all checks (slow!) #ifdef PARANOIA static uint options = MMGR_ALL; -static bool random_fill = true; static const size_t padding_size = 256 * sizeof(ulong); // normal settings #else static uint options = 0; -static bool random_fill = true; static const size_t padding_size = 1 * sizeof(ulong); #endif @@ -384,32 +382,6 @@ static const ulong pattern_freed = 0xdeadbeef; static void pattern_set(const Alloc* a, ulong pattern) { - // For a serious test run, we use wipes of random a random value. - // However, if this causes a crash, we don't want it to crash in a - // different place each time, so we specifically DO NOT call srand. - // If, by chance your program calls srand(), you may wish to disable - // that when running with a random wipe test. This will make any - // crashes more consistent so they can be tracked down. - - if(random_fill) - { - // note: rand typically returns 16 bits, - // so one call isn't enough. - pattern = 0; - for(size_t shift = 0; shift < sizeof(ulong)*8; shift += 8) - pattern |= (rand() & 0xff) << shift; - } - - // We should wipe with zero if we're not in debug mode, so we can - // help hide bugs if possible when we release the product. - // - // Note that options & MMGR_FILL should be turned on for this to have - // any effect, otherwise it won't do much good. But we'll leave it - // this way (as an option) because this does slow things down. -#ifndef NDEBUG - pattern = 0; -#endif - // fill user's data (optional) // note: don't use memset, because we want multi-byte patterns if(options & MMGR_FILL && a->user_size() > 0) diff --git a/source/lib/res/snd.cpp b/source/lib/res/snd.cpp index 4a0f39e1df..85b8b55fad 100755 --- a/source/lib/res/snd.cpp +++ b/source/lib/res/snd.cpp @@ -200,6 +200,7 @@ static int alc_init() // we hold a reference to prevent the actual unload, // thus speeding up startup by 100..400 ms. everything works ATM; // hopefully, OpenAL doesn't rely on them actually being unloaded. + #ifdef _WIN32 HMODULE dlls[3]; dlls[0] = LoadLibrary("wrap_oal.dll"); @@ -208,9 +209,10 @@ static int alc_init() #endif // for reasons unknown, the NV native OpenAL implementation - // causes an invalid exception internally when loaded (it's not - // caused by the DLL load hack above). we need to catch it to - // prevent the unhandled exception filter from reporting it. + // causes an "invalid handle" exception internally when loaded + // (it's not caused by the DLL load hack above). everything works and + // we can continue normally; we just need to catch it to prevent the + // unhandled exception filter from reporting it. #ifdef _WIN32 __try { @@ -1725,6 +1727,14 @@ static int vm_update() // (allow any and all of them to be 0 in case world isn't initialized yet). int snd_update(const float* pos, const float* dir, const float* up) { + // there's no sense in updating anything if we weren't initialized + // yet (most notably, if sound is disabled). we check for this to + // avoid confusing the code below. the caller should complain if + // this fails, so report success here (everything will work once + // sound is re-enabled). + if(!al_initialized) + return 0; + if(pos || dir || up) al_listener_set_pos(pos, dir, up); diff --git a/source/lib/sysdep/ia32.cpp b/source/lib/sysdep/ia32.cpp index a56f3fff45..783ad3e947 100755 --- a/source/lib/sysdep/ia32.cpp +++ b/source/lib/sysdep/ia32.cpp @@ -166,7 +166,7 @@ __asm // (optimized for size) -static void __declspec(naked) cpuid() +static void cpuid() { __asm { @@ -253,7 +253,6 @@ no_ext_funcs: no_cpuid: popad - ret } // __asm } // cpuid() @@ -266,7 +265,7 @@ bool ia32_cap(CpuCap cap) debug_warn("cap invalid"); return false; } - u32 bit = 1ul << (cap & 0x1f); + u32 bit = BIT(cap & 0x1f); return (caps[idx] & bit) != 0; } @@ -596,18 +595,17 @@ $no_lock: } -__declspec(naked) void __cdecl atomic_add(intptr_t* location, intptr_t increment) +void atomic_add(intptr_t* location, intptr_t increment) { __asm { cmp byte ptr [cpus], 1 - mov edx, [esp+4] // location - mov eax, [esp+8] // increment + mov edx, [location] + mov eax, [increment] je $no_lock _emit 0xf0 // LOCK prefix $no_lock: add [edx], eax - ret } } diff --git a/source/lib/sysdep/win/wdbg_sym.cpp b/source/lib/sysdep/win/wdbg_sym.cpp index fd4e3d84de..83e593a059 100755 --- a/source/lib/sysdep/win/wdbg_sym.cpp +++ b/source/lib/sysdep/win/wdbg_sym.cpp @@ -282,13 +282,24 @@ int debug_resolve_symbol(void* ptr_of_interest, char* sym_name, char* file, int* #ifdef _M_IX86 // optimized for size. -static __declspec(naked) void __cdecl get_current_context(void* pcontext) +static void get_current_context(void* pcontext) { + // for safety and future-proofing, we do not use __declspec(naked) and + // access the parameter ourselves. therefore, we need to grab it into + // a register before PUSHAD, which means we'd lose the register's + // previous contents. save it here to prevent that. + static u32 saved_eax; __asm { + ;// don't write into edi directly so that the compiler (if clever) + ;// doesn't need to generate register-save code. + mov [saved_eax], eax + mov eax, [pcontext] + pushad pushfd - mov edi, [esp+4+32+4] ;// pcontext + + xchg eax, edi ;// edi = (CONTEXT*)pcontext ;// ContextFlags mov eax, 0x10007 ;// segs, int, control @@ -323,14 +334,16 @@ rep stosd stosd mov eax, [esp+4+32-8] ;// ecx stosd - mov eax, [esp+4+32-4] ;// eax + mov eax, [saved_eax] stosd ;// CONTEXT_CONTROL - xchg eax, ebp + mov eax, ebp ;// despite being smaller, don't use XCHG - + ;// avoids silly "modifying ebp" warning + ;// (we restore via POPAD, but VC is stupid) stosd - mov eax, [esp+4+32] ;// eip - sub eax, 5 ;// back up to call site from ret addr + mov eax, [esp+4+32] ;// return address + sub eax, 5 ;// skip CALL instruction -> call site. stosd xor eax, eax mov ax, cs @@ -1420,38 +1433,57 @@ static int udt_get_child_type(const wchar_t* child_name, } -static int udt_dump_stl(const wchar_t* wtype_name, const u8* p, size_t size, DumpState state, +static int udt_dump_std(const wchar_t* wtype_name, const u8* p, size_t size, DumpState state, ULONG num_children, const DWORD* children) { int err; + // not a C++ standard library object; can't handle it. + if(wcsncmp(wtype_name, L"std::", 5) != 0) + return 1; + + // check for C++ objects that should be displayed via udt_dump_normal. + // STL containers are special-cased and the rest (apart from those here) + // are ignored, because for the most part they are spew. + if(!wcsncmp(wtype_name, L"std::pair", 9)) + return 1; + + // convert to char since debug_stl doesn't support wchar_t. + char ctype_name[DBG_SYMBOL_LEN]; + snprintf(ctype_name, ARRAY_SIZE(ctype_name), "%ws", wtype_name); + + // display contents of STL containers + // .. get element type DWORD el_type_id; size_t el_size; err = udt_get_child_type(L"value_type", num_children, children, &el_type_id, &el_size); if(err != 0) - return err; - - // debug_stl doesn't support wchar_t. - char ctype_name[DBG_SYMBOL_LEN]; - snprintf(ctype_name, ARRAY_SIZE(ctype_name), "%ws", wtype_name); - + goto not_valid_container; + // .. get iterator and # elements size_t el_count; DebugIterator el_iterator; u8 it_mem[DEBUG_STL_MAX_ITERATOR_SIZE]; err = stl_get_container_info(ctype_name, p, size, el_size, &el_count, &el_iterator, it_mem); + if(err != 0) + goto not_valid_container; + return dump_sequence(el_iterator, it_mem, el_count, el_type_id, el_size, state); +not_valid_container: - // type_name is unknown; can't handle it. - if(err == STL_CNT_UNKNOWN) - return 1; - // contents are invalid (uninitialized or corrupted) - else if(err == STL_CNT_INVALID) - { - out(L"(uninitialized/invalid %hs)", stl_simplify_name(ctype_name)); - return 0; - } - // supported and valid: output each element. + // build and display detailed "error" message. + char buf[100]; + const char* text = buf; + // .. C++ stdlib object that we didn't want to display + // (just output its simplified type) + if(err == STL_CNT_UNKNOWN || err == 1) + text = ""; + // .. container of a known type but contents are invalid + if(err == STL_CNT_INVALID) + text = "uninitialized/invalid "; + // .. some other error encountered else - return dump_sequence(el_iterator, it_mem, el_count, el_type_id, el_size, state); + snprintf(buf, ARRAY_SIZE(buf), "error %d while analyzing ", err); + out(L"(%hs%hs)", text, stl_simplify_name(ctype_name)); + return 0; } @@ -1507,15 +1539,6 @@ not_handle: static int udt_dump_suppressed(const wchar_t* type_name, const u8* p, size_t size, DumpState state, ULONG num_children, const DWORD* children) { - // avoid C++ library objects, since they result in serious spew. - if(!wcsncmp(type_name, L"std::pair", 9)) // allow - return 1; - if(!wcsncmp(type_name, L"std::", 5)) - { - out(L"(%s)", type_name); - return 0; - } - if(!udt_should_suppress(type_name)) return 1; @@ -1660,7 +1683,7 @@ static int dump_sym_udt(DWORD type_id, const u8* p, DumpState state) // note: order is important (e.g. STL special-case must come before // suppressing UDTs, which tosses out most other C++ stdlib classes) - ret = udt_dump_stl (type_name, p, size, state, num_children, children); + ret = udt_dump_std (type_name, p, size, state, num_children, children); if(ret <= 0) goto done; diff --git a/source/lib/sysdep/win/wdll.cpp b/source/lib/sysdep/win/wdll.cpp index c7cad3b8f9..da90a0de32 100755 --- a/source/lib/sysdep/win/wdll.cpp +++ b/source/lib/sysdep/win/wdll.cpp @@ -1,7 +1,6 @@ // modified from VC7 DelayHlp.cpp and DelayImp.h #include "precompiled.h" -#undef new // because it conflicts with some other uses of new #include "win_internal.h" diff --git a/source/lib/sysdep/win/wsdl.cpp b/source/lib/sysdep/win/wsdl.cpp index 01cda8964a..b541167024 100755 --- a/source/lib/sysdep/win/wsdl.cpp +++ b/source/lib/sysdep/win/wsdl.cpp @@ -882,6 +882,9 @@ SDL_VideoInfo* SDL_GetVideoInfo() // For very [very] basic memory-usage information. // Should be replaced by a decent memory profiler. +// +// copied from SDL_GetVideoInfo but cannot be implemented in terms of it: +// SDL_VideoInfo doesn't provide for returning "remaining video memory". int GetVRAMInfo(int& remaining, int& total) { int ok = 0;