sdl: remove complicated mouse button check/workaround; that's now done in Interact.cpp (which makes the assumptions being tested)
ia32.asm: move get_current_context code here wdbg_sym: revised get_context code; moved it into walk_stack (fixes bug on non-ia32) wsdl: bring in line with real SDL SDL_BUTTON_* (sorry nicolai!) interact now checks for expected values of SDL_BUTTON. This was SVN commit r2991.
This commit is contained in:
parent
359f55700a
commit
b80be29eab
@ -1,16 +1,10 @@
|
||||
#ifndef _lib_sdl_H
|
||||
#define _lib_sdl_H
|
||||
#ifndef LIB_SDL_H__
|
||||
#define LIB_SDL_H__
|
||||
|
||||
#define SDL_BUTTON_INDEX_COUNT 5
|
||||
|
||||
#if OS_WIN && !defined(NO_WSDL)
|
||||
#if OS_WIN && !defined(CONFIG_NO_WSDL)
|
||||
# include "sysdep/win/wsdl.h"
|
||||
|
||||
// The SDL_BUTTON_* enum is zero-based and in the range [0..4] in wsdl.h
|
||||
#define SDL_BUTTON_TO_INDEX(_but) _but
|
||||
#define SDL_INDEX_TO_BUTTON(_idx) _idx
|
||||
|
||||
#else
|
||||
|
||||
# include <SDL/SDL.h>
|
||||
# include <SDL/SDL_thread.h>
|
||||
# include <SDL/SDL_endian.h>
|
||||
@ -19,22 +13,6 @@
|
||||
// will strip them if unused, and this is more convenient than
|
||||
// another header that toggles between wsdl and SDL_endian.h.
|
||||
|
||||
#if SDL_BUTTON_LEFT == 1 && SDL_BUTTON_MIDDLE == 2 && SDL_BUTTON_RIGHT == 3 \
|
||||
&& SDL_BUTTON_WHEELUP == 4 && SDL_BUTTON_WHEELDOWN == 5
|
||||
|
||||
#define SDL_BUTTON_TO_INDEX(_but) ((_but) - 1)
|
||||
#define SDL_INDEX_TO_BUTTON(_idx) ((_idx) - 1)
|
||||
|
||||
#else
|
||||
|
||||
/* Add a test like the one above for your set of button constants, and implement
|
||||
the BUTTON_TO_INDEX macros so that the resulting indices are within the range
|
||||
[0, SDL_BUTTON_INDEX_COUNT-1]
|
||||
*/
|
||||
#error "Platform with unrecognized SDL constants. Update sdl.h"
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif // _lib_sdl_H
|
||||
#endif // LIB_SDL_H__
|
||||
|
@ -358,6 +358,81 @@ sym(ia32_control87):
|
||||
xor eax, eax ; return value
|
||||
ret
|
||||
|
||||
|
||||
; write the current execution state (e.g. all register values) into
|
||||
; (Win32::CONTEXT*)pcontext (defined as void* to avoid dependency).
|
||||
; optimized for size; this must be straight asm because __declspec(naked)
|
||||
; is compiler-specific and compiler-generated prolog code inserted before
|
||||
; inline asm trashes EBP and ESP (unacceptable).
|
||||
; extern "C" void ia32_get_current_context(void* pcontext)
|
||||
global sym(ia32_get_current_context)
|
||||
sym(ia32_get_current_context):
|
||||
pushad
|
||||
pushfd
|
||||
mov edi, [esp+4+32+4] ; pcontext
|
||||
|
||||
; ContextFlags
|
||||
mov eax, 0x10007 ; segs, int, control
|
||||
stosd
|
||||
|
||||
; DRx and FloatSave
|
||||
; rationale: we can't access the debug registers from Ring3, and
|
||||
; the FPU save area is irrelevant, so zero them.
|
||||
xor eax, eax
|
||||
push byte 6+8+20
|
||||
pop ecx
|
||||
rep stosd
|
||||
|
||||
; CONTEXT_SEGMENTS
|
||||
mov ax, gs
|
||||
stosd
|
||||
mov ax, fs
|
||||
stosd
|
||||
mov ax, es
|
||||
stosd
|
||||
mov ax, ds
|
||||
stosd
|
||||
|
||||
; CONTEXT_INTEGER
|
||||
mov eax, [esp+4+32-32] ; edi
|
||||
stosd
|
||||
xchg eax, esi
|
||||
stosd
|
||||
xchg eax, ebx
|
||||
stosd
|
||||
xchg eax, edx
|
||||
stosd
|
||||
mov eax, [esp+4+32-8] ; ecx
|
||||
stosd
|
||||
mov eax, [esp+4+32-4] ; eax
|
||||
stosd
|
||||
|
||||
; CONTEXT_CONTROL
|
||||
xchg eax, ebp ; ebp restored by POPAD
|
||||
stosd
|
||||
mov eax, [esp+4+32] ; return address
|
||||
sub eax, 5 ; skip CALL instruction -> call site.
|
||||
stosd
|
||||
xor eax, eax
|
||||
mov ax, cs
|
||||
stosd
|
||||
pop eax ; eflags
|
||||
stosd
|
||||
lea eax, [esp+32+4+4] ; esp
|
||||
stosd
|
||||
xor eax, eax
|
||||
mov ax, ss
|
||||
stosd
|
||||
|
||||
; ExtendedRegisters
|
||||
xor ecx, ecx
|
||||
mov cl, 512/4
|
||||
rep stosd
|
||||
|
||||
popad
|
||||
ret
|
||||
|
||||
|
||||
;-------------------------------------------------------------------------------
|
||||
; init
|
||||
;-------------------------------------------------------------------------------
|
||||
|
@ -76,6 +76,9 @@ extern void ia32_debug_break(void);
|
||||
|
||||
extern void ia32_memcpy(void* dst, const void* src, size_t nbytes);
|
||||
|
||||
// write the current execution state (e.g. all register values) into
|
||||
// (Win32::CONTEXT*)pcontext (defined as void* to avoid dependency).
|
||||
extern void ia32_get_current_context(void* pcontext);
|
||||
|
||||
// CPU caps (128 bits)
|
||||
// do not change the order!
|
||||
|
@ -21,7 +21,6 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "lib.h"
|
||||
|
||||
#include "win_internal.h"
|
||||
#define _NO_CVCONST_H // request SymTagEnum be defined
|
||||
#include "dbghelp.h"
|
||||
@ -30,15 +29,13 @@
|
||||
#include "sysdep/cpu.h"
|
||||
#include "wdbg.h"
|
||||
#include "debug_stl.h"
|
||||
#if CPU_IA32
|
||||
# include "lib/sysdep/ia32.h"
|
||||
#endif
|
||||
|
||||
#define SELF_TEST_ENABLED 0 // raises an an annoying exception
|
||||
#include "self_test.h"
|
||||
|
||||
// optional: enables translation of the "unhandled exception" dialog.
|
||||
#ifdef I18N
|
||||
#include "ps/i18n.h"
|
||||
#endif
|
||||
|
||||
|
||||
#if MSC_VERSION
|
||||
#pragma comment(lib, "dbghelp.lib")
|
||||
@ -265,122 +262,6 @@ int debug_resolve_symbol(void* ptr_of_interest, char* sym_name, char* file, int*
|
||||
// stack walk via dbghelp
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
// rationale: to function properly, StackWalk64 requires a CONTEXT on
|
||||
// non-x86 systems (documented) or when in release mode (observed).
|
||||
// exception handlers can call walk_stack with their context record;
|
||||
// otherwise (e.g. dump_stack from debug_assert), we need to query it.
|
||||
// there are 2 platform-independent ways to do so:
|
||||
// - intentionally raise an SEH exception, then proceed as above;
|
||||
// - GetThreadContext while suspended (*).
|
||||
// the latter is more complicated and slower, so we go with the former
|
||||
// despite it outputting "first chance exception" on each call.
|
||||
//
|
||||
// on IA-32, we use ia32_get_win_context instead of the above because
|
||||
// it is 100% accurate (noticeable in StackWalk64 results) and simplest.
|
||||
//
|
||||
// * it used to be common practice not to query the current thread's context,
|
||||
// but WinXP SP2 and above require it be suspended.
|
||||
|
||||
// copy from CONTEXT to STACKFRAME64
|
||||
|
||||
#if CPU_IA32
|
||||
|
||||
// optimized for size.
|
||||
// this is the (so far) only case where __declspec(naked) is absolutely
|
||||
// critical. compiler-generated prolog code trashes EBP and ESP,
|
||||
// which is especially bad here because the stack trace code relies
|
||||
// on us returning their correct values.
|
||||
static __declspec(naked) void get_current_context(void* pcontext)
|
||||
{
|
||||
// squelch W4 unused parameter warning (it's accessed from asm)
|
||||
UNUSED2(pcontext);
|
||||
__asm
|
||||
{
|
||||
pushad
|
||||
pushfd
|
||||
mov edi, [esp+4+32+4] ;// pcontext
|
||||
|
||||
;// ContextFlags
|
||||
mov eax, 0x10007 ;// segs, int, control
|
||||
stosd
|
||||
|
||||
;// DRx and FloatSave
|
||||
;// rationale: we can't access the debug registers from Ring3, and
|
||||
;// the FPU save area is irrelevant, so zero them.
|
||||
xor eax, eax
|
||||
push 6+8+20
|
||||
pop ecx
|
||||
rep stosd
|
||||
|
||||
;// CONTEXT_SEGMENTS
|
||||
mov ax, gs
|
||||
stosd
|
||||
mov ax, fs
|
||||
stosd
|
||||
mov ax, es
|
||||
stosd
|
||||
mov ax, ds
|
||||
stosd
|
||||
|
||||
;// CONTEXT_INTEGER
|
||||
mov eax, [esp+4+32-32] ;// edi
|
||||
stosd
|
||||
xchg eax, esi
|
||||
stosd
|
||||
xchg eax, ebx
|
||||
stosd
|
||||
xchg eax, edx
|
||||
stosd
|
||||
mov eax, [esp+4+32-8] ;// ecx
|
||||
stosd
|
||||
mov eax, [esp+4+32-4] ;// eax
|
||||
stosd
|
||||
|
||||
;// CONTEXT_CONTROL
|
||||
xchg eax, ebp ;// ebp restored by POPAD
|
||||
stosd
|
||||
mov eax, [esp+4+32] ;// return address
|
||||
sub eax, 5 ;// skip CALL instruction -> call site.
|
||||
stosd
|
||||
xor eax, eax
|
||||
mov ax, cs
|
||||
stosd
|
||||
pop eax ;// eflags
|
||||
stosd
|
||||
lea eax, [esp+32+4+4] ;// esp
|
||||
stosd
|
||||
xor eax, eax
|
||||
mov ax, ss
|
||||
stosd
|
||||
|
||||
;// ExtendedRegisters
|
||||
push 512/4
|
||||
pop ecx
|
||||
rep stosd
|
||||
|
||||
popad
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
#else // #if CPU_IA32
|
||||
|
||||
static void get_current_context(CONTEXT* pcontext)
|
||||
{
|
||||
__try
|
||||
{
|
||||
RaiseException(0xF001, 0, 0, 0);
|
||||
}
|
||||
__except(*pcontext = (GetExceptionInformation())->ContextRecord, EXCEPTION_CONTINUE_EXECUTION)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
// called for each stack frame found by walk_stack, passing information
|
||||
// about the frame and <user_arg>.
|
||||
// return <= 0 to stop immediately and have walk_stack return that;
|
||||
@ -400,7 +281,10 @@ static int walk_stack(StackFrameCallback cb, void* user_arg = 0, uint skip = 0,
|
||||
|
||||
const HANDLE hThread = GetCurrentThread();
|
||||
|
||||
// get CONTEXT (see above)
|
||||
// to function properly, StackWalk64 requires a CONTEXT on
|
||||
// non-x86 systems (documented) or when in release mode (observed).
|
||||
// exception handlers can call walk_stack with their context record;
|
||||
// otherwise (e.g. dump_stack from debug_assert), we need to query it.
|
||||
CONTEXT context;
|
||||
// .. caller knows the context (most likely from an exception);
|
||||
// since StackWalk64 may modify it, copy to a local variable.
|
||||
@ -409,8 +293,43 @@ static int walk_stack(StackFrameCallback cb, void* user_arg = 0, uint skip = 0,
|
||||
// .. need to determine context ourselves.
|
||||
else
|
||||
{
|
||||
get_current_context(&context);
|
||||
skip++; // skip this frame
|
||||
|
||||
// there are 4 ways to do so, in order of preference:
|
||||
// - asm (easy to use but currently only implemented on IA32)
|
||||
// - RtlCaptureContext (only available on WinXP or above)
|
||||
// - intentionally raise an SEH exception and capture its context
|
||||
// (spams us with "first chance exception")
|
||||
// - GetThreadContext while suspended* (a bit tricky + slow).
|
||||
//
|
||||
// * it used to be common practice to query the current thread's context,
|
||||
// but WinXP SP2 and above require it be suspended.
|
||||
//
|
||||
// this MUST be done inline and not in an external function because
|
||||
// compiler-generated prolog code trashes some registers.
|
||||
|
||||
#if CPU_IA32
|
||||
ia32_get_current_context(&context);
|
||||
#else
|
||||
// try to import RtlCaptureContext (available on WinXP and later)
|
||||
HMODULE hKernel32Dll = LoadLibrary("kernel32.dll");
|
||||
VOID(*pRtlCaptureContext)(PCONTEXT*);
|
||||
*(void**)&pRtlCaptureContext = GetProcAddress(hKernel32Dll, "RtlCaptureContext");
|
||||
FreeLibrary(hKernel32Dll); // doesn't actually free the lib
|
||||
if(pRtlCaptureContext)
|
||||
pRtlCaptureContext(&context);
|
||||
// not available: raise+handle an exception; grab the reported context.
|
||||
else
|
||||
{
|
||||
__try
|
||||
{
|
||||
RaiseException(0xF001, 0, 0, 0);
|
||||
}
|
||||
__except(context = (GetExceptionInformation())->ContextRecord, EXCEPTION_CONTINUE_EXECUTION)
|
||||
{
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
pcontext = &context;
|
||||
|
||||
@ -427,7 +346,7 @@ static int walk_stack(StackFrameCallback cb, void* user_arg = 0, uint skip = 0,
|
||||
int ret = WDBG_NO_STACK_FRAMES_FOUND;
|
||||
for(;;)
|
||||
{
|
||||
BOOL ok = StackWalk64(machine, hProcess, hThread, &sf, (void*)pcontext,
|
||||
BOOL ok = StackWalk64(machine, hProcess, hThread, &sf, (PVOID)pcontext,
|
||||
0, SymFunctionTableAccess64, SymGetModuleBase64, 0);
|
||||
|
||||
// no more frames found - abort.
|
||||
@ -984,7 +903,7 @@ in_register:
|
||||
|
||||
*pp = (const u8*)addr;
|
||||
|
||||
debug_printf("DET_SYM_ADDR %ws at %p flags=%X dk=%d sym->addr=%I64X addrofs=%X addr2=%I64X ofs2=%X\n", sym->Name, *pp, sym->Flags, data_kind, sym->Address, addrofs, addr2, ofs2);
|
||||
debug_printf("SYM: %ws at %p flags=%X dk=%d sym->addr=%I64X addrofs=%X addr2=%I64X ofs2=%X\n", sym->Name, *pp, sym->Flags, data_kind, sym->Address, addrofs, addr2, ofs2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1724,7 +1643,7 @@ static int dump_sym_unknown(DWORD type_id, const u8* UNUSED(p), DumpState UNUSED
|
||||
if(!SymGetTypeInfo(hProcess, mod_base, type_id, TI_GET_SYMTAG, &type_tag))
|
||||
return WDBG_TYPE_INFO_UNAVAILABLE;
|
||||
|
||||
debug_printf("Unknown tag: %d\n", type_tag);
|
||||
debug_printf("SYM: unknown tag: %d\n", type_tag);
|
||||
out(L"(unknown symbol type)");
|
||||
return 0;
|
||||
}
|
||||
@ -1737,9 +1656,7 @@ static int dump_sym_unknown(DWORD type_id, const u8* UNUSED(p), DumpState UNUSED
|
||||
// delegates to dump_sym_* depending on the symbol's tag.
|
||||
static int dump_sym(DWORD type_id, const u8* p, DumpState state)
|
||||
{
|
||||
int ret = out_check_limit();
|
||||
if(ret != 0)
|
||||
return ret;
|
||||
RETURN_ERR(out_check_limit());
|
||||
|
||||
DWORD type_tag;
|
||||
if(!SymGetTypeInfo(hProcess, mod_base, type_id, TI_GET_SYMTAG, &type_tag))
|
||||
|
@ -204,15 +204,12 @@ SDL_QuitEvent;
|
||||
|
||||
enum SDL_MouseButtonEvent_button
|
||||
{
|
||||
// do not change order or values
|
||||
// ... but if you do, update lib/sdl.h so that SDL_BUTTON_TO_INDEX still
|
||||
// yields contiguous values
|
||||
SDL_BUTTON_LEFT=0,
|
||||
SDL_BUTTON_RIGHT=1,
|
||||
SDL_BUTTON_MIDDLE=2,
|
||||
|
||||
SDL_BUTTON_WHEELUP=3,
|
||||
SDL_BUTTON_WHEELDOWN=4
|
||||
// to remain compatible with regular SDL, these values must not change!
|
||||
SDL_BUTTON_LEFT = 1,
|
||||
SDL_BUTTON_MIDDLE = 2,
|
||||
SDL_BUTTON_RIGHT = 3,
|
||||
SDL_BUTTON_WHEELUP = 4,
|
||||
SDL_BUTTON_WHEELDOWN = 5
|
||||
};
|
||||
|
||||
enum SDL_MouseButtonEvent_state
|
||||
|
@ -835,6 +835,11 @@ InReaction interactInputHandler( const SDL_Event* ev )
|
||||
//CTerrain *pTerrain=g_Game->GetWorld()->GetTerrain();
|
||||
|
||||
// One entry for each mouse button
|
||||
// note: to store these in an array, we make assumptions as to the
|
||||
// SDL_BUTTON_* values; these are verified at compile time.
|
||||
cassert(SDL_BUTTON_LEFT == 1 && SDL_BUTTON_MIDDLE == 2 && SDL_BUTTON_RIGHT == 3 && \
|
||||
SDL_BUTTON_WHEELUP == 4 && SDL_BUTTON_WHEELDOWN == 5);
|
||||
const uint SDL_BUTTON_INDEX_COUNT = 6;
|
||||
static double lastclicktime[SDL_BUTTON_INDEX_COUNT];
|
||||
static HEntity lastclickobject[SDL_BUTTON_INDEX_COUNT];
|
||||
static u8 clicks[SDL_BUTTON_INDEX_COUNT];
|
||||
@ -917,7 +922,7 @@ InReaction interactInputHandler( const SDL_Event* ev )
|
||||
return( IN_HANDLED );
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
{
|
||||
int button = SDL_BUTTON_TO_INDEX(ev->button.button);
|
||||
int button = ev->button.button;
|
||||
// Only process buttons within the range for which we have button state
|
||||
// arrays above.
|
||||
if (button >= 0 && button < SDL_BUTTON_INDEX_COUNT)
|
||||
|
Loading…
Reference in New Issue
Block a user